Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions e2e/solid-start/virtual-routes/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
node_modules
package-lock.json
yarn.lock

.DS_Store
.cache
.env
.vercel
.output

/build/
/api/
/server/build
/public/build
# Sentry Config File
.env.sentry-build-plugin
/test-results/
/playwright-report/
/blob-report/
/playwright/.cache/
4 changes: 4 additions & 0 deletions e2e/solid-start/virtual-routes/.prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
**/build
**/public
pnpm-lock.yaml
routeTree.gen.ts
37 changes: 37 additions & 0 deletions e2e/solid-start/virtual-routes/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{
"name": "tanstack-solid-start-e2e-virtual-routes",
"private": true,
"sideEffects": false,
"type": "module",
"scripts": {
"dev": "vite dev --port 3000",
"dev:e2e": "vite dev",
"build": "vite build && tsc --noEmit",
"start": "pnpx srvx --prod -s ../client dist/server/server.js",
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

🧩 Analysis chain

Verify the relative path in the start script.

The start script references ../client which seems unusual. Ensure this path correctly points to the client output directory for the production server.


🏁 Script executed:

#!/bin/bash
# Verify the directory structure and whether ../client exists or is created during build
fd -t d "client" e2e/solid-start/virtual-routes

Length of output: 0


🏁 Script executed:

#!/bin/bash
# List full directory structure under e2e/solid-start/virtual-routes
echo "=== Full directory structure ==="
find e2e/solid-start/virtual-routes -type d | head -20

echo ""
echo "=== Files in e2e/solid-start/virtual-routes ==="
find e2e/solid-start/virtual-routes -maxdepth 2 -type f | head -20

echo ""
echo "=== Check parent directory e2e/solid-start ==="
find e2e/solid-start -maxdepth 2 -type d

echo ""
echo "=== Content of package.json ==="
cat e2e/solid-start/virtual-routes/package.json

Length of output: 4311


🏁 Script executed:

#!/bin/bash
# Check other e2e projects' start scripts for patterns
echo "=== Checking start scripts in other e2e projects ==="
rg -n '"start"' e2e/solid-start/*/package.json -A1 -B1

echo ""
echo "=== Check if there's a vite config or tsconfig ==="
find e2e/solid-start/virtual-routes -maxdepth 1 -name "vite.config.*" -o -name "tsconfig.*" -o -name "solid.config.*" | xargs ls -la 2>/dev/null

echo ""
echo "=== Look for any client build output references ==="
rg -i "client" e2e/solid-start/virtual-routes/ --type ts --type js -n

Length of output: 4234


🏁 Script executed:

#!/bin/bash
# Check the vite config to understand build output structure
echo "=== Content of vite.config.ts ==="
cat e2e/solid-start/virtual-routes/vite.config.ts

echo ""
echo "=== Check what files are generated after build ==="
grep -r "outDir\|build" e2e/solid-start/virtual-routes/vite.config.ts

Length of output: 553






🌐 Web query:

srvx npm package --prod -s flag documentation

💡 Result:

Do you want the meaning/behavior of the --prod and -s flags for the srvx CLI, or examples of how to run them? I can look up the official docs and quote the CLI help—tell me which and I’ll fetch the exact docs.


🌐 Web query:

Solid Start build output directory structure dist/client

💡 Result:

dist/client is the client-side output of a Solid Start (Vite-based) build — it contains the static assets the browser needs: bundled JS/CSS for hydration, chunk files, asset files (images/fonts), and the Vite-generated client manifest/ssr-manifest used by server rendering. The server-side build (dist/server) contains the SSR/server bundle (handler) that imports the client manifest to emit correct asset tags and preload hints. In short:

  • dist/client — browser assets (bundles, .vite folder, assets, css, js, manifest). [1][2]
  • dist/server — server bundle/entry that performs SSR and references dist/client assets at runtime. [1][2]

Sources: Solid Start repo/docs (build layout and tooling), Vite SSR docs on client/server builds and ssr-manifest. [1][2][3]

References
[1] solidjs/solid-start (GitHub). (github.com)
[2] Vite — Server-Side Rendering / client+server build details (ssr-manifest). (v2.vitejs.dev)
[3] Solid Start "use server" / docs (shows server/client model in Solid Start). (docs.solidjs.com)

Citations:


🌐 Web query:

srvx CLI help documentation static files directory

💡 Result:

Do you mean:

  • the filesystem path where the srvx CLI stores its built-in help/static docs, or
  • how to serve a static files directory with the srvx CLI, or
  • where the srvx project’s documentation/static site lives (repo or site)?

Which one do you want?


🏁 Script executed:

#!/bin/bash
# Search for any build scripts or monorepo configuration that might create ../client
echo "=== Check root package.json or monorepo config ==="
find . -maxdepth 2 -name "package.json" -type f | head -3 | xargs grep -l "workspaces\|build" 2>/dev/null | head -1 | xargs cat | head -50

echo ""
echo "=== Search for ../client references in build or config files ==="
rg -l "\.\./client" --type json --type ts --type js e2e/ | head -10

echo ""
echo "=== Check if there are any symlinks or shared directories ==="
find e2e/solid-start -maxdepth 1 -type l 2>/dev/null

Length of output: 3030


Correct the start script to reference the actual client build output directory.

The ../client path does not exist in the repository. Solid Start builds client assets to dist/client during the build process. The srvx command's -s flag should reference this directory to serve static files correctly.

Change:

"start": "pnpx srvx --prod -s ../client  dist/server/server.js",

To:

"start": "pnpx srvx --prod -s dist/client  dist/server/server.js",

This issue appears consistently across multiple Solid Start and React Start e2e projects, so the same fix should be applied to all affected projects.

🤖 Prompt for AI Agents
In e2e/solid-start/virtual-routes/package.json around line 10, the "start"
script uses "-s ../client" which points to a nonexistent path; update the static
serve path to the actual Solid Start client build output "dist/client" so the
srvx command becomes "pnpx srvx --prod -s dist/client dist/server/server.js";
apply the same change to other Solid Start and React Start e2e project
package.json files that use "../client".

"test:e2e": "rm -rf port*.txt; playwright test --project=chromium"
},
"dependencies": {
"@tanstack/solid-router": "workspace:^",
"@tanstack/solid-router-devtools": "workspace:^",
"@tanstack/solid-start": "workspace:^",
"@tanstack/virtual-file-routes": "workspace:^",
"solid-js": "^1.9.5",
"redaxios": "^0.5.1",
"tailwind-merge": "^2.6.0",
"vite": "^7.1.7",
"zod": "^3.24.2"
},
"devDependencies": {
"@playwright/test": "^1.50.1",
"@tanstack/router-e2e-utils": "workspace:^",
"@types/node": "^22.10.2",
"vite-plugin-solid": "^2.11.9",
"autoprefixer": "^10.4.20",
"combinate": "^1.1.11",
"postcss": "^8.5.1",
"srvx": "^0.8.6",
"tailwindcss": "^3.4.17",
"typescript": "^5.7.2",
"vite-tsconfig-paths": "^5.1.4"
}
}
42 changes: 42 additions & 0 deletions e2e/solid-start/virtual-routes/playwright.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { defineConfig, devices } from '@playwright/test'
import {
getDummyServerPort,
getTestServerPort,
} from '@tanstack/router-e2e-utils'
import packageJson from './package.json' with { type: 'json' }

const PORT = await getTestServerPort(packageJson.name)
const EXTERNAL_PORT = await getDummyServerPort(packageJson.name)
const baseURL = `http://localhost:${PORT}`

/**
* See https://playwright.dev/docs/test-configuration.
*/
export default defineConfig({
testDir: './tests',
workers: 1,

reporter: [['line']],

globalSetup: './tests/setup/global.setup.ts',
globalTeardown: './tests/setup/global.teardown.ts',

use: {
/* Base URL to use in actions like `await page.goto('/')`. */
baseURL,
},

webServer: {
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`,
url: baseURL,
reuseExistingServer: !process.env.CI,
stdout: 'pipe',
},

projects: [
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] },
},
],
})
6 changes: 6 additions & 0 deletions e2e/solid-start/virtual-routes/postcss.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export default {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Binary file added e2e/solid-start/virtual-routes/public/favicon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions e2e/solid-start/virtual-routes/public/script.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
console.log('SCRIPT_1 loaded')
window.SCRIPT_1 = true
2 changes: 2 additions & 0 deletions e2e/solid-start/virtual-routes/public/script2.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
console.log('SCRIPT_2 loaded')
window.SCRIPT_2 = true
19 changes: 19 additions & 0 deletions e2e/solid-start/virtual-routes/public/site.webmanifest
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"name": "",
"short_name": "",
"icons": [
{
"src": "/android-chrome-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "/android-chrome-512x512.png",
"sizes": "512x512",
"type": "image/png"
}
],
"theme_color": "#ffffff",
"background_color": "#ffffff",
"display": "standalone"
}
24 changes: 24 additions & 0 deletions e2e/solid-start/virtual-routes/routes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import {
index,
layout,
physical,
rootRoute,
route,
} from '@tanstack/virtual-file-routes'

export const routes = rootRoute('root.tsx', [
index('home.tsx'),
route('/posts', 'posts/posts.tsx', [
index('posts/posts-home.tsx'),
route('$postId', 'posts/posts-detail.tsx'),
]),
layout('first', 'layout/first-layout.tsx', [
layout('layout/second-layout.tsx', [
route('route-without-file', [
route('/layout-a', 'a.tsx'),
route('/layout-b', 'b.tsx'),
]),
]),
]),
physical('/classic', 'file-based-subtree'),
])
38 changes: 38 additions & 0 deletions e2e/solid-start/virtual-routes/src/posts.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { notFound } from '@tanstack/solid-router'
import axios from 'redaxios'

export type PostType = {
id: string
title: string
body: string
}

let queryURL = 'https://jsonplaceholder.typicode.com'

if (import.meta.env.VITE_NODE_ENV === 'test') {
queryURL = `http://localhost:${import.meta.env.VITE_EXTERNAL_PORT}`
}

export const fetchPost = async (postId: string) => {
console.info(`Fetching post with id ${postId}...`)
await new Promise((r) => setTimeout(r, 500))
const post = await axios
.get<PostType>(`${queryURL}/posts/${postId}`)
.then((r) => r.data)
.catch((err) => {
if (err.status === 404) {
throw notFound()
}
throw err
})
Comment on lines +22 to +27
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

🧩 Analysis chain

Verify the error property for redaxios.

The error handling checks err.status, but axios-like libraries typically expose the status code at err.response.status. Please verify that redaxios uses err.status directly and not the nested err.response.status property.


🌐 Web query:

redaxios error object structure and status code property

💡 Result:

Short answer: redaxios follows the Axios API for errors — the HTTP status code is on error.response.status (not error.status). The error object otherwise looks like a standard AxiosError (message, name, stack, config, code, request, response). Use optional chaining to be safe: const status = error.response?.status.

Sources: redaxios package README (axios-compatible wrapper). [1] Axios error handling / AxiosError shape (shows error.response.status). [2]

References
[1] redaxios package (axios-compatible, uses fetch).
[2] axios docs — error/response handling (error.response.status).


Fix the error property access for redaxios in the error handler.

The code checks err.status, but redaxios follows the Axios API where the HTTP status code is at err.response.status. Change line 23 to if (err.response?.status === 404) to properly access the nested status property.

🤖 Prompt for AI Agents
In e2e/solid-start/virtual-routes/src/posts.tsx around lines 22 to 27, the error
handler checks err.status but redaxios follows Axios semantics and places the
HTTP status on err.response.status; update the condition to check
err.response?.status === 404 (use optional chaining to avoid undefined) so the
404 case triggers correctly, and leave the rest of the catch logic unchanged.


return post
}

export const fetchPosts = async () => {
console.info('Fetching posts...')
await new Promise((r) => setTimeout(r, 500))
return axios
.get<Array<PostType>>(`${queryURL}/posts`)
.then((r) => r.data.slice(0, 10))
}
Loading
Loading