Skip to content

feat: Add plugin routes to tanstack start - #764

Open
aXenDeveloper wants to merge 2 commits into
feat/tanstack_start_4from
feat/tanstack_start_5
Open

feat: Add plugin routes to tanstack start#764
aXenDeveloper wants to merge 2 commits into
feat/tanstack_start_4from
feat/tanstack_start_5

Conversation

@aXenDeveloper

Copy link
Copy Markdown
Owner

Improving Documentation

Description

What?

Why?

@vercel

vercel Bot commented Aug 28, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
vitnode-docs Ready Ready Preview Aug 28, 2026 7:43am

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3b0b3ba863

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/web/src/lib/plugin-routes.ts Outdated
Comment on lines +193 to +194
const claimed = new Set(appPaths)
const collision = specs.find((spec) => claimed.has(spec.path))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Compare route match shapes instead of parameter names

When a plugin route and an app route use different names for the same dynamic segment, this exact string comparison misses the collision. For example, the existing /api/$ splat and a plugin declaration such as /api/:slug both match /api/foo, while /api/$ and /api/$slug are treated as distinct here; similarly, an app /posts/$id and plugin /posts/:slug conflict. Normalize TanStack parameters and splats into comparable match shapes before mounting the plugin subtree, otherwise routing precedence decides which handler or page serves the URL.

Useful? React with 👍 / 👎.

routeTree: TRouteTree,
specs: PluginRouteSpec[],
): TRouteTree => {
if (specs.length === 0) return routeTree

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Remove the previous subtree when the route list becomes empty

When the last plugin route is removed during development, this early return leaves the previously mounted _plugins child on the cached routeTree. The implementation explicitly supports repeated composition against that singleton, but transitioning from a non-empty list to [] therefore keeps the disabled plugin page reachable until the process is restarted. Rebuild the root children without the old plugin container even when specs is empty.

Useful? React with 👍 / 👎.

Comment thread apps/web/vitnode-plugin-routes.ts Outdated
Comment on lines +119 to +120
const loaded = await import(pathToFileURL(file).href)
const declarations = routeDeclarationsFromManifest(loaded, specifier)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Bust the module cache when reloading a changed manifest

When a watched compiled route manifest changes, regenerate() imports this identical file URL again, so Node returns the already-cached ESM namespace instead of evaluating the new contents. Consequently edits to an existing manifest do not update either generated file despite the watcher firing, and developers must restart the Vite process. Import through a cache-busted URL or another loader that invalidates the module between regenerations.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9fcee194a4

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

* the bundle by construction rather than by a filter somebody has to remember.
*/
const readConfiguredPluginIds = async (): Promise<string[]> => {
const jiti = createJiti(import.meta.url, { interopDefault: true })

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Disable Jiti caching for watched config reloads

When src/vitnode.config.ts changes during development, configureServer calls this loader again expecting the configured plugin list to refresh, but Jiti uses its module cache by default; creating another Jiti instance does not evict the config from the underlying module cache. Adding or removing a plugin can therefore regenerate from the previous configuration until Vite is restarted. Load watched configuration with moduleCache: false or explicitly invalidate it before importing.

Useful? React with 👍 / 👎.

Comment on lines +271 to +273
component: lazyRouteComponent(async () =>
assertPluginRouteModule(await spec.load(), spec.route.id),
),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Expose matched params to dynamic plugin pages

When a plugin declares a supported dynamic path such as /blog/:slug, this registration hands TanStack only the loaded zero-prop component. TanStack route components do not receive match parameters as props, and the repository adds no framework-neutral adapter or context, so the documented framework-neutral page cannot determine which slug matched without importing TanStack-specific hooks. Dynamic plugin pages therefore cannot render or SSR the requested resource; expose normalized parameters through the plugin route contract or reject dynamic declarations until that contract exists.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

💡 Feature A new feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant