Skip to content

Conversation

@edmundhung
Copy link
Contributor

@edmundhung edmundhung commented Nov 20, 2025

This updates prerendering to use Vite's preview server instead of directly importing the server bundle. This makes prerendering runtime-agnostic. It works the same way regardless of whether your server targets Node.js, Cloudflare Workers, or other runtimes. The preview server handles the runtime differences, so the prerendering logic doesn't need to know about them.

This particularly enables Cloudflare projects to prerender with full Workers runtime support and access to all bindings. I have updated the Cloudflare packages (wrangler and @cloudflare/vite-plugin) to fix a workerd cleanup issue, and added a prerendering test for the Cloudflare e2e project to verify everything works correctly.

All existing prerendering tests for Node.js continue to pass, so no additional test coverage was needed there.

The wrangler update (039c805) brings a large amount of generated type definition changes, so it's recommended to review this by commit.

Summary by CodeRabbit

  • New Features

    • Added a /static page that exposes a Cloudflare env value and new Solid/React route scaffolding and UI (not-found and error boundaries).
    • Added a preconfigured router and app shell for Solid.
  • Build / Runtime

    • Prerender now runs via a preview server; post-build flow adjusted to run as a separate post-build step.
  • Dependencies

    • Bumped Cloudflare Vite plugin and wrangler dev deps.
  • Tests

    • Added E2E tests validating prerender output and /static content.

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

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 20, 2025

Walkthrough

Adds a /static route and tests for Cloudflare e2e examples, enables prerendering for that route, and refactors post-build/prerender to run against a Vite preview server (removing reliance on a server bundle and adjusting plugin hooks and signatures).

Changes

Cohort / File(s) Summary
React Cloudflare static route & types
e2e/react-start/basic-cloudflare/src/routes/static.tsx, e2e/react-start/basic-cloudflare/src/routeTree.gen.ts
New /static file route with loader calling a server fn returning env.MY_VAR; route tree and TypeScript route maps/types augmented to include /static.
React Cloudflare tests & config
e2e/react-start/basic-cloudflare/tests/app.spec.ts, e2e/react-start/basic-cloudflare/vite.config.ts, e2e/react-start/basic-cloudflare/package.json
Added test asserting prerendered static HTML and page content; enabled TanStack Start prerender filter for /static; bumped @cloudflare/vite-plugin and wrangler dev deps.
Start plugin: post-build & API
packages/start-plugin-core/src/plugin.ts, packages/start-plugin-core/src/post-server-build.ts
Removed serverBundle usage from build handler; moved post-build call to a dedicated plugin hook and removed serverBundle parameter from postServerBuild signature.
Prerender -> Vite preview server
packages/start-plugin-core/src/prerender.ts
Replaced bundle-based prerendering with starting a Vite preview server at runtime; use resolved preview URL for fetches; added lifecycle handling (ensure server closed).
Solid Cloudflare example scaffolding
e2e/solid-start/basic-cloudflare/*, e2e/solid-start/basic-cloudflare/src/routes/*, e2e/solid-start/basic-cloudflare/src/components/*, e2e/solid-start/basic-cloudflare/tests/*, e2e/solid-start/basic-cloudflare/vite.config.ts, e2e/solid-start/basic-cloudflare/wrangler.jsonc
New Solid Start Cloudflare example: routeTree, routes (/ and /static), router/getRouter, DefaultCatchBoundary, NotFound, styles, SEO util, Playwright config, tests, postcss, manifest, wrangler config, tsconfig, and related test setup/teardown.

Sequence Diagram(s)

sequenceDiagram
    participant Build as Build Process
    participant Plugin as start-plugin-core (post-build)
    participant PostBuild as postServerBuild
    participant PreRender as prerender
    participant Preview as Vite Preview Server
    participant Fetcher as HTTP Fetcher

    Build->>Plugin: buildApp completes
    Plugin->>PostBuild: invoke postServerBuild(builder, startConfig)
    PostBuild->>PreRender: prerender({ builder, startConfig })

    rect rgba(200,220,240,0.6)
    Note over PreRender,Preview: NEW — start preview server & resolve base URL
    PreRender->>Preview: startPreviewServer(viteConfig)
    Preview-->>PreRender: previewServer instance
    PreRender->>PreRender: baseURL = getResolvedUrl(previewServer)
    end

    rect rgba(240,230,210,0.6)
    Note over PreRender,Fetcher: Prerender loop (pages)
    loop for each page
      PreRender->>Fetcher: fetch(baseURL + page.path)
      Fetcher-->>PreRender: HTML response
      PreRender->>PreRender: write HTML to disk
    end
    end

    rect rgba(220,240,220,0.6)
    Note over PreRender,Preview: cleanup
    PreRender->>Preview: previewServer.close() (finally)
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Areas to focus:
    • packages/start-plugin-core/src/prerender.ts — preview server lifecycle, URL resolution, and fetch/write logic.
    • packages/start-plugin-core/src/plugin.ts & post-server-build.ts — ensure plugin ordering and parameter changes are consistent.
    • e2e/* Cloudflare examples and tests — verify prerender filter, route wiring, and expected test artifacts (dist paths).

Possibly related PRs

Suggested labels

ssr, package: solid-start, package: react-start

Suggested reviewers

  • schiller-manuel
  • birkskyum

Poem

🐰 I hopped in with a tiny ping—
A preview server starts to sing.
Static pages bloom so bright,
Cloudflare whispers, "All is right."
Prerendered carrots, sweet and light. 🥕

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 PR title 'feat: prerender with vite preview server' directly and concisely describes the main change: transitioning prerendering to use Vite's preview server instead of the server bundle.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

@edmundhung edmundhung marked this pull request as ready for review November 20, 2025 11:24
@nx-cloud
Copy link

nx-cloud bot commented Nov 20, 2025

View your CI Pipeline Execution ↗ for commit b954752

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

☁️ Nx Cloud last updated this comment at 2025-11-20 18:43:40 UTC

@edmundhung
Copy link
Contributor Author

cc: @schiller-manuel

@pkg-pr-new
Copy link

pkg-pr-new bot commented Nov 20, 2025

More templates

@tanstack/arktype-adapter

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

@tanstack/directive-functions-plugin

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

@tanstack/eslint-plugin-router

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

@tanstack/history

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

@tanstack/nitro-v2-vite-plugin

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

@tanstack/react-router

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

@tanstack/react-router-devtools

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

@tanstack/react-router-ssr-query

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

@tanstack/react-start

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

@tanstack/react-start-client

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

@tanstack/react-start-server

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

@tanstack/router-cli

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

@tanstack/router-core

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

@tanstack/router-devtools

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

@tanstack/router-devtools-core

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

@tanstack/router-generator

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

@tanstack/router-plugin

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

@tanstack/router-ssr-query-core

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

@tanstack/router-utils

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

@tanstack/router-vite-plugin

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

@tanstack/server-functions-plugin

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

@tanstack/solid-router

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

@tanstack/solid-router-devtools

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

@tanstack/solid-router-ssr-query

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

@tanstack/solid-start

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

@tanstack/solid-start-client

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

@tanstack/solid-start-server

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

@tanstack/start-client-core

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

@tanstack/start-plugin-core

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

@tanstack/start-server-core

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

@tanstack/start-static-server-functions

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

@tanstack/start-storage-context

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

@tanstack/valibot-adapter

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

@tanstack/virtual-file-routes

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

@tanstack/zod-adapter

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

commit: b954752

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: 0

🧹 Nitpick comments (1)
packages/start-plugin-core/src/prerender.ts (1)

62-89: Preview-server-based prerender flow looks solid; a couple of small robustness tweaks to consider

The new approach of starting a Vite preview server, resolving its URL, and then using localFetch against that base is a nice way to make prerendering runtime‑agnostic and unlock Workers support. A few minor hardening points you might want to consider:

  • Always close the preview server, even if URL resolution fails
    Right now, startPreviewServer and getResolvedUrl(previewServer) run before the try/finally. If getResolvedUrl throws (e.g. resolvedUrls.local is unexpectedly empty), the function will exit before reaching the finally block and previewServer.close() won’t be called. It’s low‑probability, but you could avoid any leak by moving the getResolvedUrl call inside the try (or wrapping server startup + URL resolution in their own try/finally and guarding previewServer before closing).

  • Make redirect handling base‑URL aware instead of hard‑coding http://localhost
    In localFetch, redirects are only treated as “local” if the location header starts with 'http://localhost' or '/'. Now that the preview base URL is dynamic, it may be safer to compare against baseUrl.origin (e.g. location.startsWith(baseUrl.origin)) rather than assuming localhost, which would make this logic more resilient if Vite or the runtime ever emits redirects to a different loopback host.

These are defensive improvements; the core design and flow of the new prerender implementation look correct.

Also applies to: 91-103, 265-296

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f139f1e and 006ef54.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (8)
  • e2e/react-start/basic-cloudflare/package.json (2 hunks)
  • e2e/react-start/basic-cloudflare/src/routeTree.gen.ts (3 hunks)
  • e2e/react-start/basic-cloudflare/src/routes/static.tsx (1 hunks)
  • e2e/react-start/basic-cloudflare/tests/app.spec.ts (2 hunks)
  • e2e/react-start/basic-cloudflare/vite.config.ts (1 hunks)
  • packages/start-plugin-core/src/plugin.ts (1 hunks)
  • packages/start-plugin-core/src/post-server-build.ts (1 hunks)
  • packages/start-plugin-core/src/prerender.ts (5 hunks)
🧰 Additional context used
🧠 Learnings (3)
📚 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/react-start/basic-cloudflare/vite.config.ts
  • packages/start-plugin-core/src/prerender.ts
  • e2e/react-start/basic-cloudflare/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/react-start/basic-cloudflare/tests/app.spec.ts
  • e2e/react-start/basic-cloudflare/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/react-start/basic-cloudflare/src/routeTree.gen.ts
🧬 Code graph analysis (1)
packages/start-plugin-core/src/plugin.ts (1)
packages/start-plugin-core/src/post-server-build.ts (1)
  • postServerBuild (8-70)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Preview
  • GitHub Check: Test
🔇 Additional comments (6)
e2e/react-start/basic-cloudflare/package.json (1)

23-36: Cloudflare tooling version bumps look aligned with the new preview-based prerender flow

The updated @cloudflare/vite-plugin and wrangler versions make sense given the move to a preview-server-based prerender and the referenced workerd cleanup fix. Just make sure these versions remain in sync with whatever minimum versions the core plugin assumes when this lands on main (especially around preview behavior and bindings exposure).

e2e/react-start/basic-cloudflare/tests/app.spec.ts (1)

1-31: Prerender E2E test nicely covers both build artifact and runtime behavior

The prerender with Cloudflare Workers runtime test looks solid: it asserts that /static is actually prerendered to dist/client/static/index.html and then verifies, via Playwright, that the page renders with the expected heading and binding-derived content. This lines up well with the new /static route and prerender filter.

packages/start-plugin-core/src/plugin.ts (1)

328-360: Clean separation of build vs post-build responsibilities

Moving postServerBuild into a dedicated buildApp hook with order: 'post' keeps the core builder.buildApp focused purely on building client/server environments while still guaranteeing that prerendering + sitemap run after a successful build. The getConfig() usage here reuses the parsed startConfig and stays consistent with how config is resolved earlier.

e2e/react-start/basic-cloudflare/vite.config.ts (1)

13-18: Prerender config correctly scopes output to /static

Enabling prerendering with a filter that matches only page.path === '/static' is a good fit for this e2e app: it keeps the prerender surface minimal while lining up with the new /static route and the test that asserts dist/client/static/index.html exists.

e2e/react-start/basic-cloudflare/src/routes/static.tsx (1)

1-25: /static route cleanly exercises Cloudflare bindings via a server function

The route setup looks good: createServerFn reads env.MY_VAR from the Workers environment, the loader delegates to it, and StaticPage consumes the loader data with Route.useLoaderData() while exposing stable test IDs. This should give strong coverage of Worker bindings in both runtime and prerender flows.

packages/start-plugin-core/src/post-server-build.ts (1)

6-14: postServerBuild API adjustment matches preview-based prerender flow

Dropping the serverBundle parameter and calling prerender({ startConfig, builder }) keeps this helper aligned with the new preview-server-based prerender implementation while preserving the existing prerender/spa/sitemap behaviors. Call sites (in the core plugin) have been updated consistently.

Also applies to: 53-59

Comment on lines +354 to +360
buildApp: {
order: 'post',
async handler(builder) {
const { startConfig } = getConfig()
await postServerBuild({ builder, startConfig })
},
},
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I have moved the postServerBuild step to the buildApp hook to ensure all plugins finish their builds before we start the preview server.

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: 1

🧹 Nitpick comments (1)
e2e/solid-start/basic-cloudflare/src/components/DefaultCatchBoundary.tsx (1)

17-17: Consider adding a descriptive prefix to the error log for consistency.

Other similar error boundary components in the codebase use a descriptive prefix (e.g., 'DefaultCatchBoundary Error:') when logging errors, which aids in debugging and log filtering.

Apply this diff to add a descriptive prefix:

-  console.error(error)
+  console.error('DefaultCatchBoundary Error:', error)
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 006ef54 and b954752.

⛔ Files ignored due to path filters (8)
  • e2e/solid-start/basic-cloudflare/public/android-chrome-192x192.png is excluded by !**/*.png
  • e2e/solid-start/basic-cloudflare/public/android-chrome-512x512.png is excluded by !**/*.png
  • e2e/solid-start/basic-cloudflare/public/apple-touch-icon.png is excluded by !**/*.png
  • e2e/solid-start/basic-cloudflare/public/favicon-16x16.png is excluded by !**/*.png
  • e2e/solid-start/basic-cloudflare/public/favicon-32x32.png is excluded by !**/*.png
  • e2e/solid-start/basic-cloudflare/public/favicon.ico is excluded by !**/*.ico
  • e2e/solid-start/basic-cloudflare/public/favicon.png is excluded by !**/*.png
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (20)
  • e2e/solid-start/basic-cloudflare/.gitignore (1 hunks)
  • e2e/solid-start/basic-cloudflare/package.json (1 hunks)
  • e2e/solid-start/basic-cloudflare/playwright.config.ts (1 hunks)
  • e2e/solid-start/basic-cloudflare/postcss.config.mjs (1 hunks)
  • e2e/solid-start/basic-cloudflare/public/site.webmanifest (1 hunks)
  • e2e/solid-start/basic-cloudflare/src/components/DefaultCatchBoundary.tsx (1 hunks)
  • e2e/solid-start/basic-cloudflare/src/components/NotFound.tsx (1 hunks)
  • e2e/solid-start/basic-cloudflare/src/routeTree.gen.ts (1 hunks)
  • e2e/solid-start/basic-cloudflare/src/router.tsx (1 hunks)
  • e2e/solid-start/basic-cloudflare/src/routes/__root.tsx (1 hunks)
  • e2e/solid-start/basic-cloudflare/src/routes/index.tsx (1 hunks)
  • e2e/solid-start/basic-cloudflare/src/routes/static.tsx (1 hunks)
  • e2e/solid-start/basic-cloudflare/src/styles/app.css (1 hunks)
  • e2e/solid-start/basic-cloudflare/src/utils/seo.ts (1 hunks)
  • e2e/solid-start/basic-cloudflare/tests/app.spec.ts (1 hunks)
  • e2e/solid-start/basic-cloudflare/tests/setup/global.setup.ts (1 hunks)
  • e2e/solid-start/basic-cloudflare/tests/setup/global.teardown.ts (1 hunks)
  • e2e/solid-start/basic-cloudflare/tsconfig.json (1 hunks)
  • e2e/solid-start/basic-cloudflare/vite.config.ts (1 hunks)
  • e2e/solid-start/basic-cloudflare/wrangler.jsonc (1 hunks)
✅ Files skipped from review due to trivial changes (2)
  • e2e/solid-start/basic-cloudflare/package.json
  • e2e/solid-start/basic-cloudflare/.gitignore
🧰 Additional context used
🧠 Learnings (5)
📚 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/solid-start/basic-cloudflare/tsconfig.json
  • e2e/solid-start/basic-cloudflare/src/routeTree.gen.ts
  • e2e/solid-start/basic-cloudflare/tests/setup/global.setup.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/solid-start/basic-cloudflare/src/router.tsx
  • e2e/solid-start/basic-cloudflare/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/solid-start/basic-cloudflare/tests/app.spec.ts
  • e2e/solid-start/basic-cloudflare/public/site.webmanifest
  • e2e/solid-start/basic-cloudflare/playwright.config.ts
📚 Learning: 2025-09-28T21:41:45.233Z
Learnt from: nlynzaad
Repo: TanStack/router PR: 5284
File: e2e/react-start/basic/server.js:50-0
Timestamp: 2025-09-28T21:41:45.233Z
Learning: In Express v5, catch-all routes must use named wildcards. Use `/*splat` to match everything except root path, or `/{*splat}` (with braces) to match including root path. The old `*` syntax is not allowed and will cause "Missing parameter name" errors. This breaking change requires explicit naming of wildcard parameters.

Applied to files:

  • e2e/solid-start/basic-cloudflare/src/routes/__root.tsx
📚 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/solid-start/basic-cloudflare/src/routeTree.gen.ts
🧬 Code graph analysis (10)
e2e/solid-start/basic-cloudflare/src/components/NotFound.tsx (4)
examples/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)
examples/solid/start-basic-nitro/src/components/NotFound.tsx (1)
  • NotFound (3-25)
e2e/solid-start/basic-solid-query/src/router.tsx (1)
  • NotFound (16-16)
e2e/solid-start/basic-cloudflare/src/utils/seo.ts (2)
examples/solid/start-basic/src/utils/seo.ts (1)
  • title (1-33)
examples/solid/start-basic-cloudflare/src/utils/seo.ts (1)
  • title (1-33)
e2e/solid-start/basic-cloudflare/src/components/DefaultCatchBoundary.tsx (3)
e2e/solid-start/server-routes/src/components/DefaultCatchBoundary.tsx (1)
  • DefaultCatchBoundary (10-53)
examples/solid/start-basic-cloudflare/src/components/DefaultCatchBoundary.tsx (1)
  • DefaultCatchBoundary (10-53)
examples/solid/start-basic-nitro/src/components/DefaultCatchBoundary.tsx (1)
  • DefaultCatchBoundary (10-53)
e2e/solid-start/basic-cloudflare/src/router.tsx (2)
e2e/solid-start/basic-cloudflare/src/components/DefaultCatchBoundary.tsx (1)
  • DefaultCatchBoundary (10-53)
e2e/solid-start/basic-cloudflare/src/components/NotFound.tsx (1)
  • NotFound (3-25)
e2e/solid-start/basic-cloudflare/tests/setup/global.teardown.ts (1)
scripts/set-ts-version.js (1)
  • packageJson (33-33)
e2e/solid-start/basic-cloudflare/playwright.config.ts (1)
scripts/set-ts-version.js (1)
  • packageJson (33-33)
e2e/solid-start/basic-cloudflare/src/routes/__root.tsx (5)
e2e/solid-start/basic-cloudflare/src/routes/index.tsx (1)
  • Route (5-8)
e2e/solid-start/basic-cloudflare/src/routes/static.tsx (1)
  • Route (5-8)
e2e/solid-start/basic-cloudflare/src/utils/seo.ts (1)
  • seo (1-33)
e2e/solid-start/basic-cloudflare/src/components/DefaultCatchBoundary.tsx (1)
  • DefaultCatchBoundary (10-53)
e2e/solid-start/basic-cloudflare/src/components/NotFound.tsx (1)
  • NotFound (3-25)
e2e/solid-start/basic-cloudflare/src/routes/static.tsx (2)
e2e/solid-start/basic-cloudflare/src/routes/index.tsx (1)
  • Route (5-8)
e2e/solid-start/basic-cloudflare/worker-configuration.d.ts (1)
  • env (9632-9632)
e2e/solid-start/basic-cloudflare/src/routeTree.gen.ts (1)
e2e/solid-start/basic-cloudflare/src/router.tsx (1)
  • getRouter (6-16)
e2e/solid-start/basic-cloudflare/src/routes/index.tsx (2)
e2e/solid-start/basic-cloudflare/src/routes/static.tsx (1)
  • Route (5-8)
e2e/solid-start/basic-cloudflare/worker-configuration.d.ts (1)
  • env (9632-9632)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Test
  • GitHub Check: Preview
🔇 Additional comments (20)
e2e/solid-start/basic-cloudflare/src/utils/seo.ts (1)

1-33: LGTM!

The SEO utility implementation is consistent with other examples in the codebase and correctly generates meta tags for social media platforms.

e2e/solid-start/basic-cloudflare/postcss.config.mjs (1)

1-5: LGTM!

Standard PostCSS configuration for Tailwind CSS integration.

e2e/solid-start/basic-cloudflare/src/styles/app.css (1)

1-30: LGTM!

Standard Tailwind CSS base layer configuration with appropriate light/dark mode support.

e2e/solid-start/basic-cloudflare/src/components/DefaultCatchBoundary.tsx (1)

10-52: LGTM!

The error boundary component correctly handles errors with appropriate user actions for recovery and navigation.

e2e/solid-start/basic-cloudflare/src/components/NotFound.tsx (1)

1-25: LGTM!

The NotFound component is well-structured and consistent with similar implementations across the codebase. The inclusion of the test ID enables proper e2e testing.

e2e/solid-start/basic-cloudflare/tests/app.spec.ts (1)

1-31: LGTM!

The test suite effectively validates Cloudflare Workers runtime behavior, including the new prerendering functionality. The prerender test correctly verifies both the build artifact and runtime behavior.

e2e/solid-start/basic-cloudflare/tests/setup/global.teardown.ts (1)

1-6: LGTM!

The global teardown function properly cleans up the test server after test execution.

e2e/solid-start/basic-cloudflare/wrangler.jsonc (2)

4-4: Verify the compatibility date is appropriate.

The compatibility_date is set to 2025-09-24, which is about 2 months before the PR creation date (November 2025). Ensure this date aligns with the intended Cloudflare Workers runtime features and behaviors for this test project.


1-10: LGTM!

The Wrangler configuration correctly sets up the Cloudflare Workers environment with Node.js compatibility and the required environment variable for testing.

e2e/solid-start/basic-cloudflare/public/site.webmanifest (1)

1-19: LGTM! Empty values are acceptable in e2e test fixtures.

The empty name and short_name fields are acceptable for an e2e test fixture, as the test does not validate these specific fields.

Based on learnings

e2e/solid-start/basic-cloudflare/tests/setup/global.setup.ts (1)

1-6: LGTM!

The test setup is clean and follows the standard pattern for starting the e2e dummy server.

e2e/solid-start/basic-cloudflare/tsconfig.json (1)

1-24: LGTM!

The TypeScript configuration is appropriate for a SolidJS project with Cloudflare Workers support. The strict mode, modern module resolution, and path aliases are all configured correctly.

e2e/solid-start/basic-cloudflare/src/router.tsx (1)

6-16: LGTM!

The router configuration is clean and follows Solid Router best practices. The settings for preload, error handling, and scroll restoration are all appropriate.

e2e/solid-start/basic-cloudflare/src/routes/__root.tsx (1)

60-86: LGTM!

The RootDocument shell component is well-structured with proper hydration setup, head content, and scripts placement.

e2e/solid-start/basic-cloudflare/src/routes/index.tsx (1)

1-27: LGTM!

The route implementation correctly uses Cloudflare Workers environment variables and follows Solid Start patterns. The test identifiers will enable reliable e2e testing.

e2e/solid-start/basic-cloudflare/src/routes/static.tsx (1)

1-25: LGTM!

The static route implementation is clean and follows the same pattern as the index route. While there is some code duplication with the getData server function, this is acceptable for e2e test fixtures where each route may have different data requirements.

e2e/solid-start/basic-cloudflare/vite.config.ts (1)

7-21: LGTM!

The Vite configuration is well-structured for Cloudflare Workers with SSR support. The prerender filter correctly targets only the /static route, which aligns with the PR's objective to test prerendering with Cloudflare Workers runtime.

e2e/solid-start/basic-cloudflare/playwright.config.ts (2)

11-38: LGTM! Well-structured Playwright configuration.

The configuration correctly:

  • Uses a single worker to prevent port conflicts during Cloudflare preview server testing
  • Wires global setup/teardown for test lifecycle management
  • Configures the preview server workflow (build && preview) which aligns with the PR's objective of using Vite's preview server for prerendering
  • Sets appropriate server reuse and output handling

3-5: No issues found. Modern syntax features are properly supported.

The project's Node.js version (24.4.1, specified in the root .nvmrc) and ES module configuration ("type": "module" in package.json) fully support both import assertions and top-level await. The configuration is correct as-is.

e2e/solid-start/basic-cloudflare/src/routeTree.gen.ts (1)

7-9: Skipping review of autogenerated file.

This file is autogenerated by TanStack Router and should not be manually modified. Based on learnings, autogenerated routeTree.gen.ts files are not reviewed.

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 the color value typo.

The color value '#fffff' has 5 hexadecimal digits. Valid hex colors should be either 3 digits (#fff) or 6 digits (#ffffff).

Apply this diff to fix the typo:

-      { 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
In e2e/solid-start/basic-cloudflare/src/routes/__root.tsx around line 51, the
meta object has an invalid color value '#fffff' (5 hex digits); replace it with
a valid hex color such as '#ffffff' (or '#fff') so the color value is 6 (or 3)
hex digits.

@birkskyum birkskyum merged commit 9da5517 into TanStack:main Nov 20, 2025
6 checks passed
@edmundhung
Copy link
Contributor Author

Thank you @birkskyum!

@daveycodez
Copy link
Contributor

daveycodez commented Nov 21, 2025

@edmundhung

I'm having issues during prerendering on Cloudflare where it imports my API routes which in turn import my db.ts for Drizzle, which has my Neon Database.

It throws an error due to process.env.DATABASE_URL being undefined. This doesn't happen for local builds with pre-rendering, only on Cloudflare. It seems to be throwing away all non VITE_ environment variables, and this is causing errors during the pre-rendering phase specifically on Cloudflare, since it is importing the entire route tree including API routes which might throw when env variables are missing.

pgrealtime/pgrealtime#8

I was able to suppress it by wrapping my Neon with a try catch, but it doesn't feel right.

@daveycodez
Copy link
Contributor

daveycodez commented Nov 21, 2025

It looks like the specific issue is that process.env is not being populated. I see in your example you are using import { env } from 'cloudflare:workers' in the static page and you have environment variables working there.

https://developers.cloudflare.com/workers/configuration/environment-variables/#environment-variables-and-nodejs-compatibility

Here it seems that the compatibility option to load in process.env vars as well isn't happening during the prerender.

EDIT- even with using { env } binding, I'm still getting the error.

db.ts

import { env } from "cloudflare:workers"
import { neon } from "@neondatabase/serverless"
import { drizzle } from "drizzle-orm/neon-http"
import * as schema from "./schema"

const sql = neon(env.DATABASE_URL)
export const db = drizzle(sql, { schema })

Looks like the issue is that it is not binding my secrets, during the build, specifically:

Screenshot 2025-11-20 at 11 54 06 PM
23:51:23.795	Your Worker has access to the following bindings:
23:51:23.796	Binding              Resource                  
23:51:23.796	env.FOO ("BAR")      Environment Variable      

@edmundhung
Copy link
Contributor Author

Hi @daveycodez,

Thanks for giving it a try! We don't inject runtime variables and secret in the build environment for you at the moment. You will need to set them up in the build settings in the dashboard.

I will share this with the CI team to see how we can simplify this further. Just let me know if you run into any issue with prerendering. 👍🏼

@daveycodez
Copy link
Contributor

@edmundhung Oh I actually also added them as both Environment Variables & Build variables and they still weren't present during the pre-render phase

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants