Skip to content

Conversation

@birkskyum
Copy link
Member

@birkskyum birkskyum commented Dec 17, 2025

Summary by CodeRabbit

  • Tests

    • Added end-to-end test suite validating navigation, redirects, server functions, and routing with custom basepath support.
  • Chores

    • Added complete e2e test application infrastructure including Express server, route configurations, test setup utilities, and development environment configurations.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 17, 2025

Walkthrough

Adds a new complete Vue e2e example app at e2e/vue-start/custom-basepath with scaffolding including configuration files, route definitions, server and client entry points, utilities, components, and Playwright tests to demonstrate routing with a custom basepath configuration.

Changes

Cohort / File(s) Summary
Project Configuration
package.json, tsconfig.json, vite.config.ts, playwright.config.ts, postcss.config.mjs
Define project metadata, build scripts, dependencies, TypeScript settings, Vite build config with base path /custom/basepath, Playwright test config with environment-aware port resolution, and PostCSS/Tailwind setup.
Git & Formatter Configuration
.gitignore, .prettierignore
Ignore patterns for dependencies, build artifacts, test results, Playwright cache, and formatted output exclusions.
Server Entry Points
express-server.ts, src/server.ts
Express server with dev/prod modes (dev uses Vite middleware, prod serves static from dist), SSR handler delegation; server.ts proxies HTTP requests to TanStack Vue Start handler.
Router & Route Tree
src/router.tsx, src/routeTree.gen.ts
Router factory with TanStack Vue Router, error/not-found boundaries, scroll restoration, basepath configuration; auto-generated route tree defining route hierarchy and type-safe route definitions.
Route Files
src/routes/__root.tsx, src/routes/index.tsx, src/routes/posts.tsx, src/routes/posts.index.tsx, src/routes/posts.$postId.tsx, src/routes/posts_.$postId.deep.tsx, src/routes/users.tsx, src/routes/users.index.tsx, src/routes/users.$userId.tsx, src/routes/deferred.tsx, src/routes/logout.tsx, src/routes/redirect.index.tsx, src/routes/redirect.throw-it.tsx, src/routes/api/users.ts, src/routes/api/users.$userId.ts
File-based route definitions for home, posts list/detail, nested deep view, users list/detail, deferred data loading with Suspense, logout form, redirect tests, and API endpoints with middleware/loaders.
Components
src/components/CustomMessage.tsx, src/components/DefaultCatchBoundary.tsx, src/components/NotFound.tsx, src/components/PostErrorComponent.tsx, src/components/UserErrorComponent.tsx
Reusable components for custom messages, error boundaries, not-found views, and error handling.
Utilities
src/utils/basepath.ts, src/utils/posts.tsx, src/utils/users.tsx, src/utils/seo.ts
Basepath constant /custom/basepath, server functions for posts/users data fetching with environment-aware URLs and test port switching, SEO meta tag builder.
Styling & Type Declarations
src/styles/app.css, src/vite-env.d.ts
Tailwind CSS configuration with dark mode support and global styling; TypeScript declarations for Vite URL imports.
Public Assets
public/script.js, public/script2.js, public/site.webmanifest
Test scripts logging to console, web app manifest with icon definitions.
E2E Tests & Setup
tests/navigation.spec.ts, tests/setup/global.setup.ts, tests/setup/global.teardown.ts
Playwright test suite verifying navigation, redirects, title updates, and basepath-aware server function URLs; global setup/teardown for dummy server initialization.
Port Configuration
port-tanstack-router-e2e-react-basepath-file-based.txt, port-tanstack-router-e2e-react-basepath-file-based-external.txt
Port allocation files (52265, 52266) for test server coordination.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Areas requiring extra attention:
    • express-server.ts — Environment-dependent dev/prod logic with middleware setup and SSR handler wrapping
    • src/routes/deferred.tsx — Async data loading with Suspense/Await patterns and server function composition
    • src/routes/api/users.ts — Middleware stack composition and environment-aware query URL switching
    • tests/navigation.spec.ts — Basepath-aware test assertions and redirect verification logic

Possibly related PRs

Suggested labels

package: vue-router

Suggested reviewers

  • schiller-manuel
  • brenelz

Poem

🐰 Hops around the code with glee,
A Vue app with routes, now we see!
Basepath set to /custom, so fine,
SSR plus E2E tests align,
From posts to users, deferred dreams flow—
Watch the scaffolding steal the show! 🚀

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'test(vue-start): custom-basepath' accurately describes the main change - adding a comprehensive e2e test project for Vue Start with custom basepath support.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch vue-start-custom-basepath

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@nx-cloud
Copy link

nx-cloud bot commented Dec 17, 2025

View your CI Pipeline Execution ↗ for commit 7c1fbbb

Command Status Duration Result
nx affected --targets=test:eslint,test:unit,tes... ✅ Succeeded 49s View ↗
nx run-many --target=build --exclude=examples/*... ✅ Succeeded 5s View ↗

☁️ Nx Cloud last updated this comment at 2025-12-17 21:58:03 UTC

@pkg-pr-new
Copy link

pkg-pr-new bot commented Dec 17, 2025

More templates

@tanstack/arktype-adapter

npm i https://pkg.pr.new/TanStack/router/@tanstack/arktype-adapter@6130

@tanstack/directive-functions-plugin

npm i https://pkg.pr.new/TanStack/router/@tanstack/directive-functions-plugin@6130

@tanstack/eslint-plugin-router

npm i https://pkg.pr.new/TanStack/router/@tanstack/eslint-plugin-router@6130

@tanstack/history

npm i https://pkg.pr.new/TanStack/router/@tanstack/history@6130

@tanstack/nitro-v2-vite-plugin

npm i https://pkg.pr.new/TanStack/router/@tanstack/nitro-v2-vite-plugin@6130

@tanstack/react-router

npm i https://pkg.pr.new/TanStack/router/@tanstack/react-router@6130

@tanstack/react-router-devtools

npm i https://pkg.pr.new/TanStack/router/@tanstack/react-router-devtools@6130

@tanstack/react-router-ssr-query

npm i https://pkg.pr.new/TanStack/router/@tanstack/react-router-ssr-query@6130

@tanstack/react-start

npm i https://pkg.pr.new/TanStack/router/@tanstack/react-start@6130

@tanstack/react-start-client

npm i https://pkg.pr.new/TanStack/router/@tanstack/react-start-client@6130

@tanstack/react-start-server

npm i https://pkg.pr.new/TanStack/router/@tanstack/react-start-server@6130

@tanstack/router-cli

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-cli@6130

@tanstack/router-core

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-core@6130

@tanstack/router-devtools

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-devtools@6130

@tanstack/router-devtools-core

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-devtools-core@6130

@tanstack/router-generator

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-generator@6130

@tanstack/router-plugin

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-plugin@6130

@tanstack/router-ssr-query-core

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-ssr-query-core@6130

@tanstack/router-utils

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-utils@6130

@tanstack/router-vite-plugin

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-vite-plugin@6130

@tanstack/server-functions-plugin

npm i https://pkg.pr.new/TanStack/router/@tanstack/server-functions-plugin@6130

@tanstack/solid-router

npm i https://pkg.pr.new/TanStack/router/@tanstack/solid-router@6130

@tanstack/solid-router-devtools

npm i https://pkg.pr.new/TanStack/router/@tanstack/solid-router-devtools@6130

@tanstack/solid-router-ssr-query

npm i https://pkg.pr.new/TanStack/router/@tanstack/solid-router-ssr-query@6130

@tanstack/solid-start

npm i https://pkg.pr.new/TanStack/router/@tanstack/solid-start@6130

@tanstack/solid-start-client

npm i https://pkg.pr.new/TanStack/router/@tanstack/solid-start-client@6130

@tanstack/solid-start-server

npm i https://pkg.pr.new/TanStack/router/@tanstack/solid-start-server@6130

@tanstack/start-client-core

npm i https://pkg.pr.new/TanStack/router/@tanstack/start-client-core@6130

@tanstack/start-plugin-core

npm i https://pkg.pr.new/TanStack/router/@tanstack/start-plugin-core@6130

@tanstack/start-server-core

npm i https://pkg.pr.new/TanStack/router/@tanstack/start-server-core@6130

@tanstack/start-static-server-functions

npm i https://pkg.pr.new/TanStack/router/@tanstack/start-static-server-functions@6130

@tanstack/start-storage-context

npm i https://pkg.pr.new/TanStack/router/@tanstack/start-storage-context@6130

@tanstack/valibot-adapter

npm i https://pkg.pr.new/TanStack/router/@tanstack/valibot-adapter@6130

@tanstack/virtual-file-routes

npm i https://pkg.pr.new/TanStack/router/@tanstack/virtual-file-routes@6130

@tanstack/vue-router

npm i https://pkg.pr.new/TanStack/router/@tanstack/vue-router@6130

@tanstack/vue-router-devtools

npm i https://pkg.pr.new/TanStack/router/@tanstack/vue-router-devtools@6130

@tanstack/vue-router-ssr-query

npm i https://pkg.pr.new/TanStack/router/@tanstack/vue-router-ssr-query@6130

@tanstack/vue-start

npm i https://pkg.pr.new/TanStack/router/@tanstack/vue-start@6130

@tanstack/vue-start-client

npm i https://pkg.pr.new/TanStack/router/@tanstack/vue-start-client@6130

@tanstack/vue-start-server

npm i https://pkg.pr.new/TanStack/router/@tanstack/vue-start-server@6130

@tanstack/zod-adapter

npm i https://pkg.pr.new/TanStack/router/@tanstack/zod-adapter@6130

commit: 7c1fbbb

@birkskyum birkskyum merged commit abac5ce into main Dec 17, 2025
5 of 6 checks passed
@birkskyum birkskyum deleted the vue-start-custom-basepath branch December 17, 2025 21:59
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🧹 Nitpick comments (20)
e2e/vue-start/custom-basepath/src/components/PostErrorComponent.tsx (1)

3-5: Consider using ErrorComponent directly in route configuration.

This wrapper component only forwards the error prop without additional logic. You could use ErrorComponent directly in the route's errorComponent property to reduce indirection.

If you prefer to keep the wrapper for consistency or future extensibility, this is acceptable.

e2e/vue-start/custom-basepath/src/components/UserErrorComponent.tsx (1)

4-6: Consider using ErrorComponent directly in route configuration.

Like PostErrorComponent, this wrapper only forwards the error prop. Consider using ErrorComponent directly in the route's errorComponent property to simplify the code.

If maintaining a consistent pattern across routes is preferred, the current approach is acceptable.

e2e/vue-start/custom-basepath/src/routes/api/users.$userId.ts (1)

5-9: Consider extracting shared queryURL configuration.

This environment-aware URL logic is duplicated in users.ts. For an e2e test project this is acceptable, but extracting it to a shared utility (e.g., ~/utils/apiConfig.ts) would improve maintainability if more API routes are added.

e2e/vue-start/custom-basepath/src/routes/api/users.ts (3)

5-13: Unused request parameter in middleware.

The request parameter is destructured but not used. Consider removing it or prefixing with underscore to indicate intentional non-use.

 const userLoggerMiddleware = createMiddleware().server(
-  async ({ next, request }) => {
+  async ({ next }) => {
     console.info('In: /users')
     const result = await next()
     result.response.headers.set('x-users', 'true')
     console.info('Out: /users')
     return result
   },
 )

15-23: Same unused request parameter here.

 const testParentMiddleware = createMiddleware().server(
-  async ({ next, request }) => {
+  async ({ next }) => {
     console.info('In: testParentMiddleware')

25-39: Unused request parameter and commented-out code.

The request parameter is unused. The commented-out redirect code is fine for testing purposes but consider removing if not needed.

e2e/vue-start/custom-basepath/src/utils/posts.tsx (3)

11-15: Consider using const with a ternary for immutability.

Using let for a value that's set once at module initialization can be replaced with a const and ternary expression for better immutability and clarity.

Apply this diff:

-let queryURL = 'https://jsonplaceholder.typicode.com'
-
-if (import.meta.env.VITE_NODE_ENV === 'test') {
-  queryURL = `http://localhost:${import.meta.env.VITE_EXTERNAL_PORT}`
-}
+const queryURL = import.meta.env.VITE_NODE_ENV === 'test'
+  ? `http://localhost:${import.meta.env.VITE_EXTERNAL_PORT}`
+  : 'https://jsonplaceholder.typicode.com'

17-18: Add actual validation logic to the inputValidator.

The inputValidator currently just passes through the postId without any validation. Consider adding checks to ensure the input is a valid, non-empty string (or number if you adjust the type).

Apply this diff:

 export const fetchPost = createServerFn({ method: 'GET' })
-  .inputValidator((postId: string) => postId)
+  .inputValidator((postId: string) => {
+    if (!postId || typeof postId !== 'string') {
+      throw new Error('Invalid postId')
+    }
+    return postId
+  })
   .handler(async ({ data: postId }) => {

35-42: Consider adding error handling for consistency.

Unlike fetchPost, fetchPosts doesn't have explicit error handling. While errors will naturally propagate, adding a .catch() block for logging or transforming errors could improve debugging and consistency.

Apply this diff if you want consistent error handling:

 export const fetchPosts = createServerFn({ method: 'GET' }).handler(
   async () => {
     console.info('Fetching posts...')
     return axios
       .get<Array<PostType>>(`${queryURL}/posts`)
       .then((r) => r.data.slice(0, 10))
+      .catch((err) => {
+        console.error(err)
+        throw err
+      })
   },
 )
e2e/vue-start/custom-basepath/tests/setup/global.setup.ts (1)

1-6: LGTM with optional improvement.

The global setup logic is correct and uses the standard import attributes syntax for JSON imports. The async setup appropriately starts the dummy server using the package name.

Consider adding error handling for better debugging if the server fails to start:

 export default async function setup() {
-  await e2eStartDummyServer(packageJson.name)
+  try {
+    await e2eStartDummyServer(packageJson.name)
+  } catch (error) {
+    console.error('Failed to start dummy server:', error)
+    throw error
+  }
 }
e2e/vue-start/custom-basepath/tests/setup/global.teardown.ts (1)

1-6: LGTM with optional improvement.

The global teardown logic mirrors the setup and correctly stops the dummy server. The implementation is sound.

Consider adding error handling for better debugging, though teardown failures are typically less critical:

 export default async function teardown() {
-  await e2eStopDummyServer(packageJson.name)
+  try {
+    await e2eStopDummyServer(packageJson.name)
+  } catch (error) {
+    console.error('Failed to stop dummy server:', error)
+    // Don't rethrow in teardown to allow cleanup to continue
+  }
 }
e2e/vue-start/custom-basepath/src/styles/app.css (1)

1-30: Consider merging the two @layer base blocks.

The CSS is well-structured with good dark mode support. However, the two separate @layer base blocks (lines 3-11 and 13-30) could be merged into a single block for better organization.

Apply this diff to merge the blocks:

 @import 'tailwindcss';
 
 @layer base {
   *,
   ::after,
   ::before,
   ::backdrop,
   ::file-selector-button {
     border-color: var(--color-gray-200, currentcolor);
   }
-}
-
-@layer base {
+
   html {
     color-scheme: light dark;
   }
 
   * {
     @apply border-gray-200 dark:border-gray-800;
   }
 
   html,
   body {
     @apply text-gray-900 bg-gray-50 dark:bg-gray-950 dark:text-gray-200;
   }
 
   .using-mouse * {
     outline: none !important;
   }
 }
e2e/vue-start/custom-basepath/src/routes/logout.tsx (1)

14-14: Component name mismatch.

The component is named Home but it implements a logout page. This creates confusion about the component's purpose.

Apply this diff to use a more descriptive name:

-  component: Home,
+  component: LogoutComponent,
 })
 
-function Home() {
+function LogoutComponent() {
e2e/vue-start/custom-basepath/src/router.tsx (2)

14-14: Use ES6 object property shorthand.

The property assignment basepath: basepath can be simplified using ES6 shorthand syntax.

Apply this diff:

-    basepath: basepath,
+    basepath,

7-7: Add explicit return type annotation.

Per the coding guidelines requiring TypeScript strict mode, add an explicit return type to improve type safety.

As per coding guidelines, apply this diff:

-export function getRouter() {
+export function getRouter(): ReturnType<typeof createRouter> {
e2e/vue-start/custom-basepath/src/utils/seo.ts (1)

12-30: Filter out meta tags with undefined content.

Lines 14-15, 17, and 22 can produce meta tags with content: undefined, which results in invalid HTML attributes. While browsers may tolerate this, it's semantically incorrect and could cause issues with SEO crawlers or validators.

Apply this diff to filter out tags with undefined content:

   const tags = [
     { title },
     { name: 'description', content: description },
     { name: 'keywords', content: keywords },
     { name: 'twitter:title', content: title },
     { name: 'twitter:description', content: description },
     { name: 'twitter:creator', content: '@tannerlinsley' },
     { name: 'twitter:site', content: '@tannerlinsley' },
     { name: 'og:type', content: 'website' },
     { name: 'og:title', content: title },
     { name: 'og:description', content: description },
     ...(image
       ? [
           { name: 'twitter:image', content: image },
           { name: 'twitter:card', content: 'summary_large_image' },
           { name: 'og:image', content: image },
         ]
       : []),
-  ]
+  ].filter((tag) => !('content' in tag) || tag.content !== undefined)
 
   return tags
e2e/vue-start/custom-basepath/src/routes/posts.tsx (1)

38-38: <hr /> may not render as expected in flex layout.

The horizontal rule element between the posts list and the Outlet may not provide the intended visual separation within a flex container without specific styling.

Consider using a vertical divider or adjusting the layout:

-      <hr />
+      <div class="border-r border-gray-300" />
e2e/vue-start/custom-basepath/src/routes/users.$userId.tsx (2)

12-12: Use template literals for URL construction.

String concatenation with the + operator is less readable than template literals.

Apply this diff:

-      .get<User>(basepath + '/api/users/' + userId)
+      .get<User>(`${basepath}/api/users/${userId}`)

14-16: Original error context is lost.

The catch block discards the original error and throws a generic message. This loses valuable debugging information such as status codes, response data, or network error details.

Consider preserving the original error:

       .catch(() => {
-        throw new Error('Failed to fetch user')
+        throw new Error(`Failed to fetch user: ${err.message || 'Unknown error'}`)
       })

Or rethrow the original error:

-      .catch(() => {
-        throw new Error('Failed to fetch user')
+      .catch((err) => {
+        console.error('Failed to fetch user:', err)
+        throw err
       })
e2e/vue-start/custom-basepath/playwright.config.ts (1)

30-30: Consider extracting the webServer command to a script file.

The webServer command is lengthy and contains multiple environment variables. For better maintainability, consider extracting this into a dedicated script file (e.g., scripts/start-test-server.sh).

Example refactor:

Create scripts/start-test-server.sh:

#!/bin/bash
export VITE_NODE_ENV="test"
export VITE_EXTERNAL_PORT=$1
export VITE_SERVER_PORT=$2
export PORT=$2
pnpm build && pnpm start

Then update the config:

-    command: `VITE_NODE_ENV="test" VITE_EXTERNAL_PORT=${EXTERNAL_PORT} pnpm build && VITE_NODE_ENV="test" VITE_EXTERNAL_PORT=${EXTERNAL_PORT} VITE_SERVER_PORT=${PORT} PORT=${PORT} pnpm start`,
+    command: `./scripts/start-test-server.sh ${EXTERNAL_PORT} ${PORT}`,
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ede47af and 7c1fbbb.

⛔ Files ignored due to path filters (8)
  • e2e/vue-start/custom-basepath/public/android-chrome-192x192.png is excluded by !**/*.png
  • e2e/vue-start/custom-basepath/public/android-chrome-512x512.png is excluded by !**/*.png
  • e2e/vue-start/custom-basepath/public/apple-touch-icon.png is excluded by !**/*.png
  • e2e/vue-start/custom-basepath/public/favicon-16x16.png is excluded by !**/*.png
  • e2e/vue-start/custom-basepath/public/favicon-32x32.png is excluded by !**/*.png
  • e2e/vue-start/custom-basepath/public/favicon.ico is excluded by !**/*.ico
  • e2e/vue-start/custom-basepath/public/favicon.png is excluded by !**/*.png
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (45)
  • e2e/vue-start/custom-basepath/.gitignore (1 hunks)
  • e2e/vue-start/custom-basepath/.prettierignore (1 hunks)
  • e2e/vue-start/custom-basepath/express-server.ts (1 hunks)
  • e2e/vue-start/custom-basepath/package.json (1 hunks)
  • e2e/vue-start/custom-basepath/playwright.config.ts (1 hunks)
  • e2e/vue-start/custom-basepath/postcss.config.mjs (1 hunks)
  • e2e/vue-start/custom-basepath/public/script.js (1 hunks)
  • e2e/vue-start/custom-basepath/public/script2.js (1 hunks)
  • e2e/vue-start/custom-basepath/public/site.webmanifest (1 hunks)
  • e2e/vue-start/custom-basepath/src/components/CustomMessage.tsx (1 hunks)
  • e2e/vue-start/custom-basepath/src/components/DefaultCatchBoundary.tsx (1 hunks)
  • e2e/vue-start/custom-basepath/src/components/NotFound.tsx (1 hunks)
  • e2e/vue-start/custom-basepath/src/components/PostErrorComponent.tsx (1 hunks)
  • e2e/vue-start/custom-basepath/src/components/UserErrorComponent.tsx (1 hunks)
  • e2e/vue-start/custom-basepath/src/routeTree.gen.ts (1 hunks)
  • e2e/vue-start/custom-basepath/src/router.tsx (1 hunks)
  • e2e/vue-start/custom-basepath/src/routes/__root.tsx (1 hunks)
  • e2e/vue-start/custom-basepath/src/routes/api/users.$userId.ts (1 hunks)
  • e2e/vue-start/custom-basepath/src/routes/api/users.ts (1 hunks)
  • e2e/vue-start/custom-basepath/src/routes/deferred.tsx (1 hunks)
  • e2e/vue-start/custom-basepath/src/routes/index.tsx (1 hunks)
  • e2e/vue-start/custom-basepath/src/routes/logout.tsx (1 hunks)
  • e2e/vue-start/custom-basepath/src/routes/posts.$postId.tsx (1 hunks)
  • e2e/vue-start/custom-basepath/src/routes/posts.index.tsx (1 hunks)
  • e2e/vue-start/custom-basepath/src/routes/posts.tsx (1 hunks)
  • e2e/vue-start/custom-basepath/src/routes/posts_.$postId.deep.tsx (1 hunks)
  • e2e/vue-start/custom-basepath/src/routes/redirect.index.tsx (1 hunks)
  • e2e/vue-start/custom-basepath/src/routes/redirect.throw-it.tsx (1 hunks)
  • e2e/vue-start/custom-basepath/src/routes/users.$userId.tsx (1 hunks)
  • e2e/vue-start/custom-basepath/src/routes/users.index.tsx (1 hunks)
  • e2e/vue-start/custom-basepath/src/routes/users.tsx (1 hunks)
  • e2e/vue-start/custom-basepath/src/server.ts (1 hunks)
  • e2e/vue-start/custom-basepath/src/styles/app.css (1 hunks)
  • e2e/vue-start/custom-basepath/src/utils/basepath.ts (1 hunks)
  • e2e/vue-start/custom-basepath/src/utils/posts.tsx (1 hunks)
  • e2e/vue-start/custom-basepath/src/utils/seo.ts (1 hunks)
  • e2e/vue-start/custom-basepath/src/utils/users.tsx (1 hunks)
  • e2e/vue-start/custom-basepath/src/vite-env.d.ts (1 hunks)
  • e2e/vue-start/custom-basepath/tests/navigation.spec.ts (1 hunks)
  • e2e/vue-start/custom-basepath/tests/setup/global.setup.ts (1 hunks)
  • e2e/vue-start/custom-basepath/tests/setup/global.teardown.ts (1 hunks)
  • e2e/vue-start/custom-basepath/tsconfig.json (1 hunks)
  • e2e/vue-start/custom-basepath/vite.config.ts (1 hunks)
  • port-tanstack-router-e2e-react-basepath-file-based-external.txt (1 hunks)
  • port-tanstack-router-e2e-react-basepath-file-based.txt (1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use TypeScript strict mode with extensive type safety for all code

Files:

  • e2e/vue-start/custom-basepath/src/components/NotFound.tsx
  • e2e/vue-start/custom-basepath/src/utils/basepath.ts
  • e2e/vue-start/custom-basepath/src/routes/__root.tsx
  • e2e/vue-start/custom-basepath/src/routes/redirect.throw-it.tsx
  • e2e/vue-start/custom-basepath/src/vite-env.d.ts
  • e2e/vue-start/custom-basepath/src/routes/users.index.tsx
  • e2e/vue-start/custom-basepath/src/utils/users.tsx
  • e2e/vue-start/custom-basepath/src/routes/api/users.$userId.ts
  • e2e/vue-start/custom-basepath/src/utils/seo.ts
  • e2e/vue-start/custom-basepath/src/routes/posts.$postId.tsx
  • e2e/vue-start/custom-basepath/src/routes/posts_.$postId.deep.tsx
  • e2e/vue-start/custom-basepath/tests/navigation.spec.ts
  • e2e/vue-start/custom-basepath/src/routes/index.tsx
  • e2e/vue-start/custom-basepath/src/components/UserErrorComponent.tsx
  • e2e/vue-start/custom-basepath/express-server.ts
  • e2e/vue-start/custom-basepath/src/utils/posts.tsx
  • e2e/vue-start/custom-basepath/src/routes/deferred.tsx
  • e2e/vue-start/custom-basepath/src/routes/api/users.ts
  • e2e/vue-start/custom-basepath/tests/setup/global.setup.ts
  • e2e/vue-start/custom-basepath/src/routes/users.tsx
  • e2e/vue-start/custom-basepath/src/components/CustomMessage.tsx
  • e2e/vue-start/custom-basepath/src/routes/posts.tsx
  • e2e/vue-start/custom-basepath/src/routes/posts.index.tsx
  • e2e/vue-start/custom-basepath/vite.config.ts
  • e2e/vue-start/custom-basepath/src/components/PostErrorComponent.tsx
  • e2e/vue-start/custom-basepath/src/components/DefaultCatchBoundary.tsx
  • e2e/vue-start/custom-basepath/src/routes/logout.tsx
  • e2e/vue-start/custom-basepath/tests/setup/global.teardown.ts
  • e2e/vue-start/custom-basepath/src/server.ts
  • e2e/vue-start/custom-basepath/src/routes/redirect.index.tsx
  • e2e/vue-start/custom-basepath/src/router.tsx
  • e2e/vue-start/custom-basepath/src/routes/users.$userId.tsx
  • e2e/vue-start/custom-basepath/playwright.config.ts
  • e2e/vue-start/custom-basepath/src/routeTree.gen.ts
**/*.{js,ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Implement ESLint rules for router best practices using the ESLint plugin router

Files:

  • e2e/vue-start/custom-basepath/src/components/NotFound.tsx
  • e2e/vue-start/custom-basepath/src/utils/basepath.ts
  • e2e/vue-start/custom-basepath/src/routes/__root.tsx
  • e2e/vue-start/custom-basepath/src/routes/redirect.throw-it.tsx
  • e2e/vue-start/custom-basepath/src/vite-env.d.ts
  • e2e/vue-start/custom-basepath/src/routes/users.index.tsx
  • e2e/vue-start/custom-basepath/src/utils/users.tsx
  • e2e/vue-start/custom-basepath/src/routes/api/users.$userId.ts
  • e2e/vue-start/custom-basepath/src/utils/seo.ts
  • e2e/vue-start/custom-basepath/public/script2.js
  • e2e/vue-start/custom-basepath/src/routes/posts.$postId.tsx
  • e2e/vue-start/custom-basepath/src/routes/posts_.$postId.deep.tsx
  • e2e/vue-start/custom-basepath/tests/navigation.spec.ts
  • e2e/vue-start/custom-basepath/src/routes/index.tsx
  • e2e/vue-start/custom-basepath/src/components/UserErrorComponent.tsx
  • e2e/vue-start/custom-basepath/express-server.ts
  • e2e/vue-start/custom-basepath/src/utils/posts.tsx
  • e2e/vue-start/custom-basepath/src/routes/deferred.tsx
  • e2e/vue-start/custom-basepath/src/routes/api/users.ts
  • e2e/vue-start/custom-basepath/tests/setup/global.setup.ts
  • e2e/vue-start/custom-basepath/src/routes/users.tsx
  • e2e/vue-start/custom-basepath/src/components/CustomMessage.tsx
  • e2e/vue-start/custom-basepath/src/routes/posts.tsx
  • e2e/vue-start/custom-basepath/src/routes/posts.index.tsx
  • e2e/vue-start/custom-basepath/vite.config.ts
  • e2e/vue-start/custom-basepath/src/components/PostErrorComponent.tsx
  • e2e/vue-start/custom-basepath/src/components/DefaultCatchBoundary.tsx
  • e2e/vue-start/custom-basepath/src/routes/logout.tsx
  • e2e/vue-start/custom-basepath/tests/setup/global.teardown.ts
  • e2e/vue-start/custom-basepath/src/server.ts
  • e2e/vue-start/custom-basepath/src/routes/redirect.index.tsx
  • e2e/vue-start/custom-basepath/public/script.js
  • e2e/vue-start/custom-basepath/src/router.tsx
  • e2e/vue-start/custom-basepath/src/routes/users.$userId.tsx
  • e2e/vue-start/custom-basepath/playwright.config.ts
  • e2e/vue-start/custom-basepath/src/routeTree.gen.ts
**/package.json

📄 CodeRabbit inference engine (AGENTS.md)

Use workspace protocol workspace:* for internal dependencies in package.json files

Files:

  • e2e/vue-start/custom-basepath/package.json
🧠 Learnings (9)
📚 Learning: 2025-12-17T02:17:47.423Z
Learnt from: schiller-manuel
Repo: TanStack/router PR: 6120
File: packages/router-generator/src/generator.ts:654-657
Timestamp: 2025-12-17T02:17:47.423Z
Learning: In `packages/router-generator/src/generator.ts`, pathless_layout routes must receive a `path` property when they have a `cleanedPath`, even though they are non-path routes. This is necessary because child routes inherit the path from their parent, and without this property, child routes would not have the correct full path at runtime.

Applied to files:

  • e2e/vue-start/custom-basepath/src/routes/__root.tsx
  • e2e/vue-start/custom-basepath/src/routes/redirect.throw-it.tsx
  • e2e/vue-start/custom-basepath/src/routes/posts_.$postId.deep.tsx
  • e2e/vue-start/custom-basepath/src/routes/index.tsx
  • e2e/vue-start/custom-basepath/src/routes/posts.tsx
  • e2e/vue-start/custom-basepath/src/routes/redirect.index.tsx
  • e2e/vue-start/custom-basepath/src/router.tsx
  • e2e/vue-start/custom-basepath/src/routeTree.gen.ts
📚 Learning: 2025-10-01T18:31:35.420Z
Learnt from: schiller-manuel
Repo: TanStack/router PR: 5330
File: e2e/react-start/custom-basepath/src/routeTree.gen.ts:58-61
Timestamp: 2025-10-01T18:31:35.420Z
Learning: Do not review files named `routeTree.gen.ts` in TanStack Router repositories, as these are autogenerated files that should not be manually modified.

Applied to files:

  • e2e/vue-start/custom-basepath/src/routes/__root.tsx
  • port-tanstack-router-e2e-react-basepath-file-based.txt
  • port-tanstack-router-e2e-react-basepath-file-based-external.txt
  • e2e/vue-start/custom-basepath/.prettierignore
  • e2e/vue-start/custom-basepath/src/routeTree.gen.ts
📚 Learning: 2025-10-08T08:11:47.088Z
Learnt from: nlynzaad
Repo: TanStack/router PR: 5402
File: packages/router-generator/tests/generator/no-formatted-route-tree/routeTree.nonnested.snapshot.ts:19-21
Timestamp: 2025-10-08T08:11:47.088Z
Learning: Test snapshot files in the router-generator tests directory (e.g., files matching the pattern `packages/router-generator/tests/generator/**/routeTree*.snapshot.ts` or `routeTree*.snapshot.js`) should not be modified or have issues flagged, as they are fixtures used to verify the generator's output and are intentionally preserved as-is.

Applied to files:

  • e2e/vue-start/custom-basepath/src/routes/__root.tsx
  • e2e/vue-start/custom-basepath/src/routes/redirect.throw-it.tsx
  • e2e/vue-start/custom-basepath/tests/navigation.spec.ts
  • e2e/vue-start/custom-basepath/src/routes/api/users.ts
  • port-tanstack-router-e2e-react-basepath-file-based.txt
  • e2e/vue-start/custom-basepath/src/routes/posts.index.tsx
  • port-tanstack-router-e2e-react-basepath-file-based-external.txt
  • e2e/vue-start/custom-basepath/.prettierignore
  • e2e/vue-start/custom-basepath/tests/setup/global.teardown.ts
  • e2e/vue-start/custom-basepath/src/routes/redirect.index.tsx
  • e2e/vue-start/custom-basepath/src/routeTree.gen.ts
📚 Learning: 2025-12-06T15:03:07.223Z
Learnt from: CR
Repo: TanStack/router PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-06T15:03:07.223Z
Learning: Applies to **/*.{js,ts,tsx} : Implement ESLint rules for router best practices using the ESLint plugin router

Applied to files:

  • e2e/vue-start/custom-basepath/src/routes/__root.tsx
  • e2e/vue-start/custom-basepath/tsconfig.json
  • e2e/vue-start/custom-basepath/src/routes/redirect.throw-it.tsx
  • e2e/vue-start/custom-basepath/src/routes/index.tsx
  • e2e/vue-start/custom-basepath/src/routes/posts.tsx
  • e2e/vue-start/custom-basepath/src/routes/posts.index.tsx
  • e2e/vue-start/custom-basepath/.prettierignore
  • e2e/vue-start/custom-basepath/src/routes/redirect.index.tsx
  • e2e/vue-start/custom-basepath/src/routeTree.gen.ts
📚 Learning: 2025-12-06T15:03:07.223Z
Learnt from: CR
Repo: TanStack/router PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-06T15:03:07.223Z
Learning: Applies to **/*.{ts,tsx} : Use TypeScript strict mode with extensive type safety for all code

Applied to files:

  • e2e/vue-start/custom-basepath/tsconfig.json
📚 Learning: 2025-11-02T16:16:24.898Z
Learnt from: nlynzaad
Repo: TanStack/router PR: 5732
File: packages/start-client-core/src/client/hydrateStart.ts:6-9
Timestamp: 2025-11-02T16:16:24.898Z
Learning: In packages/start-client-core/src/client/hydrateStart.ts, the `import/no-duplicates` ESLint disable is necessary for imports from `#tanstack-router-entry` and `#tanstack-start-entry` because both aliases resolve to the same placeholder file (`fake-start-entry.js`) in package.json during static analysis, even though they resolve to different files at runtime.

Applied to files:

  • e2e/vue-start/custom-basepath/tsconfig.json
  • e2e/vue-start/custom-basepath/express-server.ts
  • e2e/vue-start/custom-basepath/tests/setup/global.setup.ts
  • e2e/vue-start/custom-basepath/package.json
  • e2e/vue-start/custom-basepath/.prettierignore
  • e2e/vue-start/custom-basepath/tests/setup/global.teardown.ts
  • e2e/vue-start/custom-basepath/src/server.ts
  • e2e/vue-start/custom-basepath/src/routes/redirect.index.tsx
  • e2e/vue-start/custom-basepath/src/routeTree.gen.ts
📚 Learning: 2025-10-01T18:30:26.591Z
Learnt from: schiller-manuel
Repo: TanStack/router PR: 5330
File: packages/router-core/src/router.ts:2231-2245
Timestamp: 2025-10-01T18:30:26.591Z
Learning: In `packages/router-core/src/router.ts`, the `resolveRedirect` method intentionally strips the router's origin from redirect URLs when they match (e.g., `https://foo.com/bar` → `/bar` for same-origin redirects) while preserving the full URL for cross-origin redirects. This logic should not be removed or simplified to use `location.publicHref` directly.

Applied to files:

  • e2e/vue-start/custom-basepath/src/routes/redirect.throw-it.tsx
  • e2e/vue-start/custom-basepath/src/routes/redirect.index.tsx
📚 Learning: 2025-12-06T15:03:07.223Z
Learnt from: CR
Repo: TanStack/router PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-06T15:03:07.223Z
Learning: Use file-based routing in `src/routes/` directories or code-based routing with route definitions

Applied to files:

  • e2e/vue-start/custom-basepath/src/routes/users.index.tsx
  • e2e/vue-start/custom-basepath/src/routes/posts_.$postId.deep.tsx
  • e2e/vue-start/custom-basepath/src/routes/users.tsx
  • e2e/vue-start/custom-basepath/src/routes/posts.tsx
  • e2e/vue-start/custom-basepath/src/routes/posts.index.tsx
  • e2e/vue-start/custom-basepath/src/routeTree.gen.ts
📚 Learning: 2025-10-09T12:59:14.842Z
Learnt from: hokkyss
Repo: TanStack/router PR: 5418
File: e2e/react-start/custom-identifier-prefix/public/site.webmanifest:2-3
Timestamp: 2025-10-09T12:59:14.842Z
Learning: In e2e test fixtures (files under e2e directories), empty or placeholder values in configuration files like site.webmanifest are acceptable and should not be flagged unless the test specifically validates those fields.

Applied to files:

  • e2e/vue-start/custom-basepath/public/site.webmanifest
  • e2e/vue-start/custom-basepath/playwright.config.ts
🧬 Code graph analysis (20)
e2e/vue-start/custom-basepath/src/components/NotFound.tsx (2)
e2e/solid-start/basic-cloudflare/src/components/NotFound.tsx (1)
  • NotFound (3-25)
e2e/solid-start/server-routes/src/components/NotFound.tsx (1)
  • NotFound (3-25)
e2e/vue-start/custom-basepath/src/routes/__root.tsx (3)
e2e/vue-start/custom-basepath/src/routes/index.tsx (1)
  • Route (4-6)
e2e/vue-start/custom-basepath/src/utils/seo.ts (1)
  • seo (1-33)
e2e/vue-start/custom-basepath/src/components/NotFound.tsx (1)
  • NotFound (3-25)
e2e/vue-start/custom-basepath/src/routes/users.index.tsx (3)
e2e/vue-start/custom-basepath/src/routes/users.$userId.tsx (1)
  • Route (9-23)
e2e/vue-start/custom-basepath/src/routes/users.tsx (1)
  • Route (6-16)
e2e/vue-start/custom-basepath/src/routes/index.tsx (1)
  • Route (4-6)
e2e/vue-start/custom-basepath/src/routes/api/users.$userId.ts (2)
e2e/vue-start/custom-basepath/src/routes/users.$userId.tsx (1)
  • Route (9-23)
e2e/vue-start/custom-basepath/src/routes/api/users.ts (1)
  • Route (47-65)
e2e/vue-start/custom-basepath/src/routes/posts.$postId.tsx (2)
e2e/vue-start/custom-basepath/src/components/PostErrorComponent.tsx (1)
  • PostErrorComponent (3-5)
e2e/vue-start/custom-basepath/src/components/NotFound.tsx (1)
  • NotFound (3-25)
e2e/vue-start/custom-basepath/src/routes/posts_.$postId.deep.tsx (3)
e2e/vue-start/custom-basepath/src/routes/posts.$postId.tsx (1)
  • Route (7-14)
e2e/vue-start/custom-basepath/src/utils/posts.tsx (1)
  • fetchPost (17-33)
e2e/vue-start/custom-basepath/src/components/PostErrorComponent.tsx (1)
  • PostErrorComponent (3-5)
e2e/vue-start/custom-basepath/src/routes/index.tsx (5)
e2e/vue-start/custom-basepath/src/routes/logout.tsx (1)
  • Route (13-15)
e2e/vue-start/custom-basepath/src/routes/posts.index.tsx (1)
  • Route (2-4)
e2e/vue-start/custom-basepath/src/routes/redirect.index.tsx (1)
  • Route (3-5)
e2e/vue-start/custom-basepath/src/routes/users.index.tsx (1)
  • Route (2-4)
e2e/vue-start/custom-basepath/src/components/CustomMessage.tsx (1)
  • CustomMessage (1-8)
e2e/vue-start/custom-basepath/express-server.ts (1)
examples/solid/basic-ssr-file-based/server.js (1)
  • vite (18-18)
e2e/vue-start/custom-basepath/src/routes/deferred.tsx (2)
e2e/vue-start/custom-basepath/src/routes/__root.tsx (1)
  • Route (16-55)
e2e/vue-start/custom-basepath/src/routes/index.tsx (1)
  • Route (4-6)
e2e/vue-start/custom-basepath/src/routes/api/users.ts (4)
e2e/vue-start/custom-basepath/src/routes/users.tsx (1)
  • Route (6-16)
e2e/vue-start/custom-basepath/src/routes/api/users.$userId.ts (1)
  • Route (11-34)
e2e/vue-start/custom-basepath/src/server.ts (1)
  • fetch (4-6)
e2e/vue-start/custom-basepath/src/utils/users.tsx (1)
  • User (1-5)
e2e/vue-start/custom-basepath/tests/setup/global.setup.ts (1)
scripts/set-ts-version.js (1)
  • packageJson (33-33)
e2e/vue-start/custom-basepath/src/routes/posts.tsx (2)
e2e/vue-start/custom-basepath/src/routes/posts.$postId.tsx (1)
  • Route (7-14)
e2e/vue-start/custom-basepath/src/utils/posts.tsx (1)
  • fetchPosts (35-42)
e2e/vue-start/custom-basepath/src/routes/posts.index.tsx (2)
e2e/vue-start/custom-basepath/src/routes/posts.tsx (1)
  • Route (5-15)
e2e/vue-start/custom-basepath/src/routes/index.tsx (1)
  • Route (4-6)
e2e/vue-start/custom-basepath/src/components/DefaultCatchBoundary.tsx (2)
packages/router-core/src/router.ts (1)
  • state (1088-1090)
e2e/vue-start/basic/src/components/DefaultCatchBoundary.tsx (1)
  • setup (18-61)
e2e/vue-start/custom-basepath/src/routes/logout.tsx (3)
e2e/vue-start/custom-basepath/src/routes/posts.tsx (1)
  • Route (5-15)
e2e/vue-start/custom-basepath/src/routes/index.tsx (1)
  • Route (4-6)
e2e/vue-start/custom-basepath/src/routes/redirect.throw-it.tsx (1)
  • Route (3-10)
e2e/vue-start/custom-basepath/tests/setup/global.teardown.ts (1)
scripts/set-ts-version.js (1)
  • packageJson (33-33)
e2e/vue-start/custom-basepath/src/routes/redirect.index.tsx (1)
e2e/vue-start/custom-basepath/src/routes/redirect.throw-it.tsx (1)
  • Route (3-10)
e2e/vue-start/custom-basepath/src/router.tsx (3)
e2e/vue-start/custom-basepath/src/components/DefaultCatchBoundary.tsx (1)
  • DefaultCatchBoundary (10-53)
e2e/vue-start/custom-basepath/src/components/NotFound.tsx (1)
  • NotFound (3-25)
e2e/vue-start/custom-basepath/src/utils/basepath.ts (1)
  • basepath (1-1)
e2e/vue-start/custom-basepath/playwright.config.ts (1)
scripts/set-ts-version.js (1)
  • packageJson (33-33)
e2e/vue-start/custom-basepath/src/routeTree.gen.ts (2)
packages/router-generator/tests/generator/types-disabled/routeTree.nonnested.snapshot.js (4)
  • PostsRoute (17-21)
  • UsersUserIdRoute (27-31)
  • PostsRouteWithChildren (42-42)
  • PostsRouteChildren (38-40)
e2e/vue-start/custom-basepath/src/router.tsx (1)
  • getRouter (7-18)
🪛 Biome (2.1.2)
e2e/vue-start/custom-basepath/src/routes/deferred.tsx

[error] 34-34: Avoid passing children using a prop

The canonical way to pass children in React is to use JSX elements

(lint/correctness/noChildrenProp)


[error] 49-49: Avoid passing children using a prop

The canonical way to pass children in React is to use JSX elements

(lint/correctness/noChildrenProp)

🔇 Additional comments (42)
port-tanstack-router-e2e-react-basepath-file-based-external.txt (1)

1-1: Fixture file; no review needed.

This is a test data file, not source code.

port-tanstack-router-e2e-react-basepath-file-based.txt (1)

1-1: Fixture file; no review needed.

This is a test data file, not source code.

e2e/vue-start/custom-basepath/.gitignore (1)

1-20: Well-structured gitignore for the e2e example project.

The ignore patterns are comprehensive and correctly cover all the necessary artifacts: package manager dependencies, system/IDE files, environment configurations, build outputs (server/client), test results/reports, and Playwright cache. The organization with inline comments makes the file easy to maintain.

e2e/vue-start/custom-basepath/src/vite-env.d.ts (1)

1-4: The vite-env.d.ts file is properly configured. The vite/client types are already configured in tsconfig.json via the "types": ["vite/client"] compiler option, so all Vite type declarations including the ?url module are available throughout the project. The custom *?url declaration does not require an additional triple-slash reference and is not redundant given this setup.

Likely an incorrect or invalid review comment.

e2e/vue-start/custom-basepath/postcss.config.mjs (1)

1-5: LGTM!

Standard PostCSS configuration for Tailwind CSS integration. The setup is correct and minimal.

e2e/vue-start/custom-basepath/public/site.webmanifest (1)

1-19: LGTM!

The manifest file is correctly structured. Empty name and short_name fields are acceptable for e2e test fixtures.

Based on learnings, placeholder values in e2e configuration files are acceptable unless the test specifically validates those fields.

e2e/vue-start/custom-basepath/src/routes/redirect.index.tsx (1)

1-15: LGTM!

The route definition follows TanStack Vue Router file-based routing patterns correctly. The Link to the throw-it route properly demonstrates the redirect functionality being tested.

e2e/vue-start/custom-basepath/tsconfig.json (1)

1-24: LGTM!

TypeScript configuration is properly set up with:

  • Strict mode enabled (line 4) as required by coding guidelines
  • Correct Vue JSX configuration with jsxImportSource: "vue"
  • Modern module resolution and ES2022 target
  • Appropriate path aliases and type definitions
e2e/vue-start/custom-basepath/src/server.ts (1)

1-7: LGTM!

Clean server entry implementation that properly delegates to the TanStack Vue Start server handler. The Request type annotation is correct, and the delegation pattern is appropriate for this use case.

e2e/vue-start/custom-basepath/express-server.ts (3)

1-8: LGTM! Server setup with environment-aware configuration.

The Express server setup correctly distinguishes between development and production modes. The use of Number.parseInt for PORT is adequate, though note that invalid values will result in NaN, which Express will handle by falling back to a default behavior.


9-28: Well-structured development mode with proper error handling.

The Vite middleware mode setup with SSR loading and stack trace fixing follows established patterns. The type guard for ssrFixStacktrace is correctly implemented.


29-40: Production mode correctly configured with basepath-aware static serving.

The static assets are correctly served under /custom/basepath, aligning with the router's basepath configuration. Error propagation to Express error handlers is properly implemented.

e2e/vue-start/custom-basepath/src/routes/api/users.$userId.ts (1)

11-34: Route handler implementation looks correct.

The GET handler properly fetches user data, handles errors with a 404 response, and returns a sanitized user object. The error logging is appropriate for debugging e2e tests.

e2e/vue-start/custom-basepath/src/components/DefaultCatchBoundary.tsx (1)

10-52: Verify Vue component definition pattern.

This component uses a plain function syntax rather than defineComponent with a setup function, which is the standard pattern used in the similar basic e2e example (see e2e/vue-start/basic/src/components/DefaultCatchBoundary.tsx). In Vue 3 with TSX, functional components typically need to be wrapped in defineComponent or use the composition API pattern to properly integrate with Vue's reactivity system.

The isRoot.value access on line 31 suggests this should work, but verify this renders correctly during e2e testing.

e2e/vue-start/custom-basepath/src/routes/api/users.ts (1)

47-65: Verify middleware ordering is intentional.

The middleware array [testMiddleware, userLoggerMiddleware, testParentMiddleware] includes testParentMiddleware both directly and via testMiddleware's chain (line 26). This will execute testParentMiddleware twice per request. If this is intentional for testing middleware composition, LGTM. Otherwise, consider removing the duplicate.

e2e/vue-start/custom-basepath/src/routes/deferred.tsx (3)

5-16: Server functions are well-structured.

The personServerFn and slowServerFn demonstrate both sync and async server function patterns with input validation. Using Math.random() is fine for demo/test purposes.


29-56: Static analysis hint is a false positive for Vue TSX.

The Biome warning about children prop usage is designed for React patterns. In Vue with TSX, the Await component's children prop is the correct way to pass render functions for slot content. This pattern is appropriate for Vue's composition with JSX/TSX.


68-79: Good demonstration of deferred loading patterns.

The loader correctly demonstrates three data-fetching patterns:

  1. deferredStuff: Raw promise for client-side resolution
  2. deferredPerson: Server function returning a promise
  3. person: Awaited server function for immediate data

This provides good test coverage for the deferred loading feature.

e2e/vue-start/custom-basepath/public/script.js (1)

1-2: LGTM!

This simple script is appropriate for e2e testing scenarios where you need to verify that public assets load and execute correctly.

e2e/vue-start/custom-basepath/public/script2.js (1)

1-2: LGTM!

This script follows the same pattern as script.js and is suitable for verifying that multiple public assets can be loaded in e2e tests.

e2e/vue-start/custom-basepath/.prettierignore (1)

1-4: LGTM!

The ignore patterns are appropriate for a TanStack Router Vue Start project:

  • Build and public directories contain generated/static assets.
  • routeTree.gen.ts is auto-generated and should not be formatted.
  • Lock files should remain untouched by formatters.

Based on learnings, routeTree.gen.ts is an auto-generated file in TanStack Router projects and should be excluded from formatting.

e2e/vue-start/custom-basepath/src/components/CustomMessage.tsx (1)

1-8: LGTM!

The component is correctly implemented for Vue 3 with JSX:

  • Proper TypeScript typing for props.
  • Uses class attribute (Vue style) instead of className.
  • Simple, clear, and functional.
e2e/vue-start/custom-basepath/src/utils/basepath.ts (1)

1-1: LGTM!

Centralizing the basepath as a constant is excellent practice. It ensures consistency across the router configuration, tests, and any other code that needs to reference the base path.

e2e/vue-start/custom-basepath/src/routes/redirect.throw-it.tsx (1)

1-10: LGTM! Redirect implementation follows TanStack Router best practices.

The use of beforeLoad to throw a redirect is the correct pattern for navigation guards in TanStack Router. The redirect configuration with path and params is properly structured.

e2e/vue-start/custom-basepath/src/routes/index.tsx (1)

1-15: LGTM! Root route implementation is clean and follows best practices.

The route structure correctly uses createFileRoute with a functional component. The use of the CustomMessage component and JSX syntax is appropriate.

e2e/vue-start/custom-basepath/src/routes/users.index.tsx (1)

1-8: LGTM! Users index route follows the expected pattern.

The route structure is consistent with other index routes in the project (e.g., posts.index.tsx) and correctly implements the TanStack Router file-based routing pattern.

e2e/vue-start/custom-basepath/src/routes/posts.index.tsx (1)

1-8: LGTM! Posts index route with good test support.

The route implementation is correct and includes a data-testid attribute, which is excellent for the e2e testing context of this project.

e2e/vue-start/custom-basepath/vite.config.ts (1)

1-20: LGTM! Vite configuration is properly structured for the custom basepath setup.

The configuration correctly sets the base path to '/custom/basepath' (matching the PR objective) and the plugin order is appropriate (tsConfigPaths first, then tanstackStart, followed by Vue plugins).

e2e/vue-start/custom-basepath/src/utils/users.tsx (1)

1-9: LGTM! Type definitions and constants are appropriate for e2e testing.

The User type is well-defined and the DEPLOY_URL construction with environment variable fallback is suitable for this e2e test context.

e2e/vue-start/custom-basepath/src/routes/logout.tsx (1)

17-32: LGTM!

The logout form correctly demonstrates that server function URLs include the app's basepath. The hardcoded CSRF token is acceptable for an e2e test scenario.

e2e/vue-start/custom-basepath/src/routes/posts.$postId.tsx (1)

7-35: LGTM!

The route structure is well-organized with proper error handling, loader configuration, and component implementation. The dynamic post view correctly uses loader data and provides navigation to the deep view.

e2e/vue-start/custom-basepath/src/routes/posts_.$postId.deep.tsx (1)

6-24: LGTM!

The deep view route is correctly structured with proper loader configuration, error handling, and component implementation. The navigation back to the posts list is intuitive.

e2e/vue-start/custom-basepath/src/routes/posts.tsx (1)

5-42: LGTM!

The posts route is well-structured with appropriate head metadata, loader configuration, and component implementation. The layout with the posts list and nested outlet works correctly for the e2e scenario.

e2e/vue-start/custom-basepath/src/routes/__root.tsx (1)

16-114: LGTM!

The root route configuration is comprehensive with proper head metadata, error handling, and layout structure. The navigation links correctly demonstrate basepath-aware routing, and the intentional non-existent route link is appropriately marked with @ts-expect-error for testing purposes.

e2e/vue-start/custom-basepath/src/routes/users.$userId.tsx (1)

9-34: LGTM!

The user detail route is properly structured with appropriate error handling components and loader configuration. The component correctly displays user information from the loader data.

e2e/vue-start/custom-basepath/src/routes/users.tsx (2)

18-46: LGTM!

The component correctly uses Vue Router's useLoaderData hook and renders the user list with proper Links. The synthetic "Non-existent User" entry (line 26) appears intentional for testing 404 routing behavior, which aligns with the e2e test purpose of this fixture.


7-14: The API endpoint /api/users is already properly defined in e2e/vue-start/custom-basepath/src/routes/api/users.ts as a server route with a GET handler. The basepath configuration is correct, and the loader implementation follows proper TypeScript and TanStack Router best practices.

Likely an incorrect or invalid review comment.

e2e/vue-start/custom-basepath/tests/navigation.spec.ts (3)

3-34: LGTM!

The navigation tests are well-structured and follow Playwright best practices. They appropriately test post navigation, user navigation, 404 handling, and client-side title updates within the custom basepath context.


36-45: LGTM!

The test correctly validates that server function URLs include the application basepath. This is critical for ensuring server functions work correctly when the app is hosted at a custom basepath.


47-78: LGTM! Well-designed redirect tests.

The redirect tests effectively validate both client-side and server-side redirect behavior with custom basepath:

  • Client-side redirect (lines 47-54): Verifies the redirect flow results in the correct URL with basepath.
  • Server-side redirect (lines 56-78): Uses maxRedirects: 0 to inspect intermediate Location headers, ensuring:
    1. Requests without basepath are redirected to add the basepath
    2. Requests with basepath correctly redirect to the final destination with basepath preserved

This comprehensive approach validates critical basepath routing behavior.

e2e/vue-start/custom-basepath/src/routeTree.gen.ts (1)

1-367: Skipping review of autogenerated file.

This file is automatically generated by TanStack Router (as indicated in lines 7-9) and should not be manually modified or reviewed. Based on learnings, routeTree.gen.ts files are excluded from code review as they are regenerated by the router generator tooling.

e2e/vue-start/custom-basepath/playwright.config.ts (1)

6-6: The import attribute syntax (with { type: 'json' }) is supported in Node.js since version 20.10 and requires no special transpilation configuration. The proposals reached stage 4 at the October 2024 meeting, and the Node.js implementation already matches exactly the semantics required by the proposals. This is standard, stable syntax—not experimental.

Likely an incorrect or invalid review comment.

Comment on lines +14 to +16
"@tanstack/vue-router": "workspace:^",
"@tanstack/vue-router-devtools": "workspace:^",
"@tanstack/vue-start": "workspace:^",
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Use workspace:* protocol for internal dependencies.

The coding guidelines require using workspace:* instead of workspace:^ for internal monorepo dependencies.

As per coding guidelines, apply this diff:

   "dependencies": {
-    "@tanstack/vue-router": "workspace:^",
-    "@tanstack/vue-router-devtools": "workspace:^",
-    "@tanstack/vue-start": "workspace:^",
+    "@tanstack/vue-router": "workspace:*",
+    "@tanstack/vue-router-devtools": "workspace:*",
+    "@tanstack/vue-start": "workspace:*",
     "express": "^4.21.2",
     "redaxios": "^0.5.1",
     "vue": "^3.5.25"
   },
   "devDependencies": {
     "@playwright/test": "^1.50.1",
     "@tailwindcss/postcss": "^4.1.15",
-    "@tanstack/router-e2e-utils": "workspace:^",
+    "@tanstack/router-e2e-utils": "workspace:*",
     "@types/express": "^5.0.3",

Also applies to: 24-24

🤖 Prompt for AI Agents
In e2e/vue-start/custom-basepath/package.json around lines 14-16 (and also line
24), internal monorepo dependencies use the workspace:^ protocol; update these
entries to use workspace:* instead (replace "workspace:^" with "workspace:*" for
"@tanstack/vue-router", "@tanstack/vue-router-devtools", "@tanstack/vue-start"
and the dependency on line 24) to conform to the coding guidelines.

@@ -0,0 +1,25 @@
import { Link } from '@tanstack/vue-router'

export function NotFound({ children }: { children?: any }) {
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

Replace any type with proper type annotation.

The children parameter uses any, which violates TypeScript strict mode best practices. Use a more specific type like JSX.Element | string | undefined or unknown if the type is truly unconstrained.

As per coding guidelines, TypeScript strict mode with extensive type safety should be used for all code.

Apply this diff:

-export function NotFound({ children }: { children?: any }) {
+export function NotFound({ children }: { children?: JSX.Element | string }) {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export function NotFound({ children }: { children?: any }) {
export function NotFound({ children }: { children?: JSX.Element | string }) {
🤖 Prompt for AI Agents
In e2e/vue-start/custom-basepath/src/components/NotFound.tsx around line 3, the
component uses the unsafe `any` type for `children`; replace it with a stricter
annotation such as `JSX.Element | string | undefined` (or another appropriate
union like `JSX.Element | string | null | undefined`) in the function signature
so the parameter is strongly typed; update the signature to use that union type
and run TypeScript to ensure no other typing adjustments are needed.

sizes: '16x16',
href: '/favicon-16x16.png',
},
{ rel: 'manifest', href: '/site.webmanifest', color: '#fffff' },
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Fix color value typo.

The hex color value '#fffff' has only 5 characters. It should be either '#ffffff' (6 characters) or '#fff' (3 characters).

Apply this diff:

-      { rel: 'manifest', href: '/site.webmanifest', color: '#fffff' },
+      { rel: 'manifest', href: '/site.webmanifest', color: '#ffffff' },
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
{ rel: 'manifest', href: '/site.webmanifest', color: '#fffff' },
{ rel: 'manifest', href: '/site.webmanifest', color: '#ffffff' },
🤖 Prompt for AI Agents
e2e/vue-start/custom-basepath/src/routes/__root.tsx around line 48: the manifest
link's color value is a typo ('#fffff' has 5 hex digits); replace it with a
valid hex color such as '#ffffff' (or the short form '#fff') by updating the
color property to the correct 6- or 3-character hex code.

Comment on lines +5 to +9
export type PostType = {
id: string
title: string
body: string
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
cd e2e/vue-start/custom-basepath || true
if [ -d "src" ]; then
  find . -name "posts.tsx" -o -name "posts.ts" | head -5
fi

Repository: TanStack/router

Length of output: 103


🏁 Script executed:

#!/bin/bash
cat -n e2e/vue-start/custom-basepath/src/utils/posts.tsx

Repository: TanStack/router

Length of output: 1448


🏁 Script executed:

#!/bin/bash
cat -n e2e/vue-start/custom-basepath/src/routes/posts.tsx

Repository: TanStack/router

Length of output: 1340


🏁 Script executed:

#!/bin/bash
# Check if there are any post detail views that use the postId
find e2e/vue-start/custom-basepath/src -name "*post*" -type f | grep -E '\.(tsx?|jsx?)$'

Repository: TanStack/router

Length of output: 340


🏁 Script executed:

#!/bin/bash
cat -n e2e/vue-start/custom-basepath/src/routes/posts.\$postId.tsx

Repository: TanStack/router

Length of output: 1337


🏁 Script executed:

#!/bin/bash
# Check if there are tests that might mock the API with string IDs
grep -r "id.*:" e2e/vue-start/custom-basepath/src --include="*.tsx" --include="*.ts" | grep -E "(mock|test|Mock|Test)" | head -10

Repository: TanStack/router

Length of output: 304


🏁 Script executed:

#!/bin/bash
# Check if there are any TypeScript errors in the build or type checking
# Look for any test files that might validate the API response
find e2e/vue-start/custom-basepath -name "*.test.*" -o -name "*.spec.*" | head -5

Repository: TanStack/router

Length of output: 113


🏁 Script executed:

#!/bin/bash
cat -n e2e/vue-start/custom-basepath/tests/navigation.spec.ts

Repository: TanStack/router

Length of output: 3349


🏁 Script executed:

#!/bin/bash
# Verify the actual JSONPlaceholder response by checking if there's any API documentation or mock data in the codebase
grep -r "jsonplaceholder" e2e/vue-start/custom-basepath --include="*.ts" --include="*.tsx" --include="*.json"

Repository: TanStack/router

Length of output: 386


Change id field in PostType from string to number to match JSONPlaceholder API response format.

JSONPlaceholder API returns post IDs as numeric values, so the type definition should reflect this. Update line 6:

 export type PostType = {
-  id: string
+  id: number
   title: string
   body: string
 }
🤖 Prompt for AI Agents
In e2e/vue-start/custom-basepath/src/utils/posts.tsx around lines 5 to 9, the
PostType currently declares id as a string but JSONPlaceholder returns numeric
IDs; change the id field's type from string to number on line 6 and update any
local usages or tests that assume string IDs so they compile (rerun TypeScript
checks to confirm no downstream type errors).

Comment on lines +24 to +30
.catch((err) => {
console.error(err)
if (err.status === 404) {
throw notFound()
}
throw err
})
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Update error status code access to use proper response structure.

Redaxios 0.5.1 includes a fix to match Axios error handling, rejecting errors as response objects. The HTTP status code is located at error.response.status, requiring a check that error.response is defined before accessing its properties. Update the error handler:

       .catch((err) => {
         console.error(err)
-        if (err.status === 404) {
+        if (err.response?.status === 404) {
           throw notFound()
         }
         throw err
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
.catch((err) => {
console.error(err)
if (err.status === 404) {
throw notFound()
}
throw err
})
.catch((err) => {
console.error(err)
if (err.response?.status === 404) {
throw notFound()
}
throw err
})
🤖 Prompt for AI Agents
In e2e/vue-start/custom-basepath/src/utils/posts.tsx around lines 24-30, the
error handler assumes err.status exists but Redaxios provides the HTTP status on
err.response.status; update the catch to first check that err.response is
defined (e.g., if (err && err.response && err.response.status === 404)) before
accessing status, preserve existing console.error(err) logging, throw notFound()
when the guarded status is 404, and rethrow the original error otherwise.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants