-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Add start-basic-cloudflare
example
#5254
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add start-basic-cloudflare
example
#5254
Conversation
WalkthroughAdds a new React Start example targeting Cloudflare Workers under examples/react/start-basic-cloudflare (configs, routes, server handlers, utilities, styles, generated route tree) and applies minor typing/import/formatting tweaks to the existing start-basic example. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor User
participant Browser as Browser (Client)
participant Router as getRouter()
participant Root as Root Route Shell
participant Server as Server Functions/API
User->>Browser: Navigate to /
Browser->>Router: initialize & resolve route
Router->>Root: render shell (Head, Nav, Outlet)
Router->>Server: invoke createServerFn loader
Server-->>Router: returns { message, env: MY_VAR }
Router-->>Browser: render Home with loader data
sequenceDiagram
autonumber
actor Client
participant Route as /api/users
participant MW1 as testMiddleware
participant MW2 as testParentMiddleware
participant MW3 as userLoggerMiddleware
participant Upstream as jsonplaceholder.typicode.com
Client->>Route: GET /api/users
Route->>MW1: invoke
MW1->>MW2: next()
MW2->>MW3: next()
MW3->>Upstream: fetch users
Upstream-->>MW3: JSON list
MW3-->>Route: Response JSON (first 10)
Route-->>Client: 200 application/json
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches
🧪 Generate unit tests
Comment |
View your CI Pipeline Execution ↗ for commit c9f437a
☁️ Nx Cloud last updated this comment at |
More templates
@tanstack/arktype-adapter
@tanstack/directive-functions-plugin
@tanstack/eslint-plugin-router
@tanstack/history
@tanstack/nitro-v2-vite-plugin
@tanstack/react-router
@tanstack/react-router-devtools
@tanstack/react-router-ssr-query
@tanstack/react-start
@tanstack/react-start-client
@tanstack/react-start-server
@tanstack/router-cli
@tanstack/router-core
@tanstack/router-devtools
@tanstack/router-devtools-core
@tanstack/router-generator
@tanstack/router-plugin
@tanstack/router-ssr-query-core
@tanstack/router-utils
@tanstack/router-vite-plugin
@tanstack/server-functions-plugin
@tanstack/solid-router
@tanstack/solid-router-devtools
@tanstack/solid-start
@tanstack/solid-start-client
@tanstack/solid-start-server
@tanstack/start-client-core
@tanstack/start-plugin-core
@tanstack/start-server-core
@tanstack/start-static-server-functions
@tanstack/start-storage-context
@tanstack/valibot-adapter
@tanstack/virtual-file-routes
@tanstack/zod-adapter
commit: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 20
🧹 Nitpick comments (20)
examples/react/start-basic-cloudflare/src/routes/customScript[.]js.ts (1)
7-11
: Consider declaring UTF-8 in the script’s Content-Type headerCloudflare (and some intermediaries) fall back to ISO-8859-1 when the charset is omitted. Declaring UTF-8 keeps you covered if the script ever includes non-ASCII characters.
- 'Content-Type': 'application/javascript', + 'Content-Type': 'application/javascript; charset=utf-8',examples/react/start-basic-cloudflare/src/utils/users.tsx (1)
1-5
: Use .ts instead of .tsx for non-JSX utility typesNo JSX here; prefer .ts for clarity and faster TS transforms.
examples/react/start-basic-cloudflare/README.md (1)
1-44
: Optional: add Wrangler auth prerequisiteConsider noting that first-time deployers may need
pnpm wrangler login
(or API token setup) beforepnpm run deploy
.examples/react/start-basic-cloudflare/package.json (1)
6-13
: Postinstall should not shell to npmUse the underlying command to avoid tool coupling; PNPM/Yarn users may hit friction.
Apply this diff:
- "cf-typegen": "wrangler types", - "postinstall": "npm run cf-typegen" + "cf-typegen": "wrangler types", + "postinstall": "wrangler types"examples/react/start-basic/src/routes/users.tsx (1)
12-15
: Inline and cast JSON to User[]
Replace the two lines in your loader with:- const data = await res.json() - return data as Array<User> + return (await res.json()) as Array<User>This keeps the loader return type strongly typed at parse site and avoids widening to any.
examples/react/start-basic/src/routes/redirect.tsx (1)
4-8
: LGTM; consider replacing history entry on redirectOptional: use replace to avoid adding an extra history entry.
Apply this diff:
- beforeLoad: () => { - throw redirect({ - to: '/posts', - }) - }, + beforeLoad: () => { + throw redirect({ + to: '/posts', + replace: true, + }) + },examples/react/start-basic-cloudflare/tailwind.config.mjs (1)
1-4
: LGTMConfig is minimal and correct for the example. Consider adding './index.html' if Tailwind classes are used there in the future.
examples/react/start-basic-cloudflare/src/utils/loggingMiddleware.tsx (1)
1-1
: Nit: use .ts instead of .tsxNo JSX here; consider renaming this utility to .ts.
examples/react/start-basic/src/routes/users.$userId.tsx (2)
4-4
: Use project alias for consistencyPrefer the established alias import to match other lines in this file.
Apply this diff:
-import type { User } from '../utils/users' +import type { User } from 'src/utils/users'
7-18
: Surface 404 as notFound, not a generic errorTo actually render notFoundComponent for missing users, throw a notFound() when the API returns 404.
Apply this diff:
-import { createFileRoute } from '@tanstack/react-router' +import { createFileRoute, notFound } from '@tanstack/react-router' @@ - if (!res.ok) { - throw new Error('Unexpected status code') - } + if (res.status === 404) { + throw notFound() + } + if (!res.ok) { + throw new Error('Unexpected status code') + }examples/react/start-basic-cloudflare/src/routes/redirect.tsx (1)
3-9
: Consider replace: true for redirectPrevents adding an extra history entry during redirects.
Apply this diff:
export const Route = createFileRoute('/redirect')({ beforeLoad: () => { throw redirect({ to: '/posts', + replace: true, }) }, })
examples/react/start-basic-cloudflare/public/site.webmanifest (1)
2-19
: Populate manifest metadata for PWA
Icons under public/ are present. Addname
/short_name
(and optionallystart_url
/scope
) for better PWA UX:examples/react/start-basic-cloudflare/public/site.webmanifest { - "name": "", - "short_name": "", + "name": "TanStack Start", + "short_name": "Start", + "start_url": "/", + "scope": "/", "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" }examples/react/start-basic-cloudflare/src/styles/app.css (1)
19-22
: Preserve visible focus for keyboard usersYou’re removing outlines within
.using-mouse
, which is good for mouse UX. Consider adding an explicit:focus-visible
style to ensure accessible focus indication for keyboard users.Apply this diff:
.using-mouse * { outline: none !important; } + :focus-visible { + /* Ensure a visible focus ring for keyboard navigation */ + @apply outline-none ring-2 ring-cyan-500 dark:ring-cyan-400; + }examples/react/start-basic-cloudflare/src/components/NotFound.tsx (1)
3-3
: Type children as ReactNode instead of anyImproves strictness and DX.
+import type { ReactNode } from 'react' -export function NotFound({ children }: { children?: any }) { +export function NotFound({ children }: { children?: ReactNode }) {As per coding guidelines
examples/react/start-basic-cloudflare/src/utils/seo.ts (1)
20-22
: Useproperty
for Open Graph meta tags (notname
)OG parsers expect
property="og:*"
. This change improves SEO correctness.- { name: 'og:type', content: 'website' }, - { name: 'og:title', content: title }, - { name: 'og:description', content: description }, + { property: 'og:type', content: 'website' }, + { property: 'og:title', content: title }, + { property: 'og:description', content: description }, @@ - { name: 'og:image', content: image }, + { property: 'og:image', content: image },Optionally filter out undefined
content
entries fordescription
/keywords
.Also applies to: 27-27
examples/react/start-basic-cloudflare/src/routes/api/users.ts (1)
6-13
: Avoid logging all request headersRequest headers can include sensitive data (e.g., cookies). Prefer logging only what’s needed or redact sensitive headers.
- console.info('Request Headers:', getRequestHeaders()) + const { cookie, authorization, ...safe } = getRequestHeaders() + console.info('Request Headers (redacted):', safe)examples/react/start-basic-cloudflare/src/routes/users.tsx (1)
2-2
: Use the same alias convention for User type importKeep imports consistent with the rest of the example.
-import type { User } from '../utils/users' +import type { User } from '~/utils/users'examples/react/start-basic-cloudflare/src/routes/__root.tsx (1)
16-31
: Add a proper theme-color meta if you need a brand colorIf the intent was to set a theme color, add a meta tag instead.
head: () => ({ meta: [ { charSet: 'utf-8', }, { name: 'viewport', content: 'width=device-width, initial-scale=1', }, + { + name: 'theme-color', + content: '#ffffff', + }, ...seo({ title: 'TanStack Start | Type-Safe, Client-First, Full-Stack React Framework', description: `TanStack Start is a type-safe, client-first, full-stack React framework. `, }), ],examples/react/start-basic-cloudflare/src/utils/posts.tsx (1)
10-15
: Optional: tighten input validationGuard against empty/whitespace ids to avoid unnecessary network calls.
export const fetchPost = createServerFn({ method: 'POST' }) - .inputValidator((d: string) => d) + .inputValidator((d: string) => { + if (typeof d !== 'string' || !d.trim()) { + throw new Error('Invalid post id') + } + return d.trim() + })examples/react/start-basic-cloudflare/src/routes/users.$userId.tsx (1)
2-4
: Use~/
path aliases consistently-import { NotFound } from 'src/components/NotFound' -import { UserErrorComponent } from 'src/components/UserError' -import type { User } from '../utils/users' +import { NotFound } from '~/components/NotFound' +import { UserErrorComponent } from '~/components/UserError' +import type { User } from '~/utils/users'
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (8)
examples/react/start-basic-cloudflare/public/android-chrome-192x192.png
is excluded by!**/*.png
examples/react/start-basic-cloudflare/public/android-chrome-512x512.png
is excluded by!**/*.png
examples/react/start-basic-cloudflare/public/apple-touch-icon.png
is excluded by!**/*.png
examples/react/start-basic-cloudflare/public/favicon-16x16.png
is excluded by!**/*.png
examples/react/start-basic-cloudflare/public/favicon-32x32.png
is excluded by!**/*.png
examples/react/start-basic-cloudflare/public/favicon.ico
is excluded by!**/*.ico
examples/react/start-basic-cloudflare/public/favicon.png
is excluded by!**/*.png
pnpm-lock.yaml
is excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (50)
examples/react/start-basic-cloudflare/.gitignore
(1 hunks)examples/react/start-basic-cloudflare/.prettierignore
(1 hunks)examples/react/start-basic-cloudflare/.vscode/settings.json
(1 hunks)examples/react/start-basic-cloudflare/README.md
(1 hunks)examples/react/start-basic-cloudflare/package.json
(1 hunks)examples/react/start-basic-cloudflare/postcss.config.mjs
(1 hunks)examples/react/start-basic-cloudflare/public/site.webmanifest
(1 hunks)examples/react/start-basic-cloudflare/src/components/DefaultCatchBoundary.tsx
(1 hunks)examples/react/start-basic-cloudflare/src/components/NotFound.tsx
(1 hunks)examples/react/start-basic-cloudflare/src/components/PostError.tsx
(1 hunks)examples/react/start-basic-cloudflare/src/components/UserError.tsx
(1 hunks)examples/react/start-basic-cloudflare/src/routeTree.gen.ts
(1 hunks)examples/react/start-basic-cloudflare/src/router.tsx
(1 hunks)examples/react/start-basic-cloudflare/src/routes/__root.tsx
(1 hunks)examples/react/start-basic-cloudflare/src/routes/_pathlessLayout.tsx
(1 hunks)examples/react/start-basic-cloudflare/src/routes/_pathlessLayout/_nested-layout.tsx
(1 hunks)examples/react/start-basic-cloudflare/src/routes/_pathlessLayout/_nested-layout/route-a.tsx
(1 hunks)examples/react/start-basic-cloudflare/src/routes/_pathlessLayout/_nested-layout/route-b.tsx
(1 hunks)examples/react/start-basic-cloudflare/src/routes/api/users.$userId.ts
(1 hunks)examples/react/start-basic-cloudflare/src/routes/api/users.ts
(1 hunks)examples/react/start-basic-cloudflare/src/routes/customScript[.]js.ts
(1 hunks)examples/react/start-basic-cloudflare/src/routes/deferred.tsx
(1 hunks)examples/react/start-basic-cloudflare/src/routes/index.tsx
(1 hunks)examples/react/start-basic-cloudflare/src/routes/posts.$postId.tsx
(1 hunks)examples/react/start-basic-cloudflare/src/routes/posts.index.tsx
(1 hunks)examples/react/start-basic-cloudflare/src/routes/posts.tsx
(1 hunks)examples/react/start-basic-cloudflare/src/routes/posts_.$postId.deep.tsx
(1 hunks)examples/react/start-basic-cloudflare/src/routes/redirect.tsx
(1 hunks)examples/react/start-basic-cloudflare/src/routes/users.$userId.tsx
(1 hunks)examples/react/start-basic-cloudflare/src/routes/users.index.tsx
(1 hunks)examples/react/start-basic-cloudflare/src/routes/users.tsx
(1 hunks)examples/react/start-basic-cloudflare/src/styles/app.css
(1 hunks)examples/react/start-basic-cloudflare/src/utils/loggingMiddleware.tsx
(1 hunks)examples/react/start-basic-cloudflare/src/utils/posts.tsx
(1 hunks)examples/react/start-basic-cloudflare/src/utils/seo.ts
(1 hunks)examples/react/start-basic-cloudflare/src/utils/users.tsx
(1 hunks)examples/react/start-basic-cloudflare/tailwind.config.mjs
(1 hunks)examples/react/start-basic-cloudflare/tsconfig.json
(1 hunks)examples/react/start-basic-cloudflare/vite.config.ts
(1 hunks)examples/react/start-basic-cloudflare/wrangler.jsonc
(1 hunks)examples/react/start-basic/src/components/PostError.tsx
(1 hunks)examples/react/start-basic/src/components/UserError.tsx
(1 hunks)examples/react/start-basic/src/routes/_pathlessLayout/_nested-layout/route-a.tsx
(1 hunks)examples/react/start-basic/src/routes/_pathlessLayout/_nested-layout/route-b.tsx
(1 hunks)examples/react/start-basic/src/routes/api/users.ts
(1 hunks)examples/react/start-basic/src/routes/posts.index.tsx
(1 hunks)examples/react/start-basic/src/routes/redirect.tsx
(1 hunks)examples/react/start-basic/src/routes/users.$userId.tsx
(2 hunks)examples/react/start-basic/src/routes/users.index.tsx
(1 hunks)examples/react/start-basic/src/routes/users.tsx
(1 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
examples/{react,solid}/**
📄 CodeRabbit inference engine (AGENTS.md)
Keep example applications under examples/react/ and examples/solid/
Files:
examples/react/start-basic-cloudflare/wrangler.jsonc
examples/react/start-basic/src/routes/_pathlessLayout/_nested-layout/route-b.tsx
examples/react/start-basic-cloudflare/tsconfig.json
examples/react/start-basic-cloudflare/src/utils/users.tsx
examples/react/start-basic/src/routes/users.$userId.tsx
examples/react/start-basic-cloudflare/src/routes/customScript[.]js.ts
examples/react/start-basic/src/components/PostError.tsx
examples/react/start-basic-cloudflare/src/routes/_pathlessLayout/_nested-layout.tsx
examples/react/start-basic-cloudflare/src/routes/_pathlessLayout/_nested-layout/route-b.tsx
examples/react/start-basic/src/components/UserError.tsx
examples/react/start-basic-cloudflare/README.md
examples/react/start-basic-cloudflare/src/routes/_pathlessLayout/_nested-layout/route-a.tsx
examples/react/start-basic-cloudflare/postcss.config.mjs
examples/react/start-basic-cloudflare/src/components/PostError.tsx
examples/react/start-basic-cloudflare/src/components/NotFound.tsx
examples/react/start-basic-cloudflare/src/routeTree.gen.ts
examples/react/start-basic-cloudflare/src/routes/users.$userId.tsx
examples/react/start-basic-cloudflare/tailwind.config.mjs
examples/react/start-basic/src/routes/posts.index.tsx
examples/react/start-basic-cloudflare/src/routes/users.index.tsx
examples/react/start-basic-cloudflare/src/routes/posts.index.tsx
examples/react/start-basic-cloudflare/src/router.tsx
examples/react/start-basic-cloudflare/src/routes/posts.tsx
examples/react/start-basic-cloudflare/src/utils/seo.ts
examples/react/start-basic-cloudflare/src/routes/redirect.tsx
examples/react/start-basic/src/routes/users.index.tsx
examples/react/start-basic-cloudflare/src/routes/posts.$postId.tsx
examples/react/start-basic-cloudflare/src/routes/api/users.ts
examples/react/start-basic-cloudflare/src/utils/posts.tsx
examples/react/start-basic/src/routes/api/users.ts
examples/react/start-basic-cloudflare/src/utils/loggingMiddleware.tsx
examples/react/start-basic/src/routes/_pathlessLayout/_nested-layout/route-a.tsx
examples/react/start-basic/src/routes/users.tsx
examples/react/start-basic-cloudflare/src/components/DefaultCatchBoundary.tsx
examples/react/start-basic-cloudflare/src/styles/app.css
examples/react/start-basic-cloudflare/public/site.webmanifest
examples/react/start-basic-cloudflare/src/components/UserError.tsx
examples/react/start-basic-cloudflare/src/routes/_pathlessLayout.tsx
examples/react/start-basic/src/routes/redirect.tsx
examples/react/start-basic-cloudflare/src/routes/__root.tsx
examples/react/start-basic-cloudflare/src/routes/index.tsx
examples/react/start-basic-cloudflare/src/routes/posts_.$postId.deep.tsx
examples/react/start-basic-cloudflare/src/routes/api/users.$userId.ts
examples/react/start-basic-cloudflare/vite.config.ts
examples/react/start-basic-cloudflare/package.json
examples/react/start-basic-cloudflare/src/routes/deferred.tsx
examples/react/start-basic-cloudflare/src/routes/users.tsx
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use TypeScript in strict mode with extensive type safety across the codebase
Files:
examples/react/start-basic/src/routes/_pathlessLayout/_nested-layout/route-b.tsx
examples/react/start-basic-cloudflare/src/utils/users.tsx
examples/react/start-basic/src/routes/users.$userId.tsx
examples/react/start-basic-cloudflare/src/routes/customScript[.]js.ts
examples/react/start-basic/src/components/PostError.tsx
examples/react/start-basic-cloudflare/src/routes/_pathlessLayout/_nested-layout.tsx
examples/react/start-basic-cloudflare/src/routes/_pathlessLayout/_nested-layout/route-b.tsx
examples/react/start-basic/src/components/UserError.tsx
examples/react/start-basic-cloudflare/src/routes/_pathlessLayout/_nested-layout/route-a.tsx
examples/react/start-basic-cloudflare/src/components/PostError.tsx
examples/react/start-basic-cloudflare/src/components/NotFound.tsx
examples/react/start-basic-cloudflare/src/routeTree.gen.ts
examples/react/start-basic-cloudflare/src/routes/users.$userId.tsx
examples/react/start-basic/src/routes/posts.index.tsx
examples/react/start-basic-cloudflare/src/routes/users.index.tsx
examples/react/start-basic-cloudflare/src/routes/posts.index.tsx
examples/react/start-basic-cloudflare/src/router.tsx
examples/react/start-basic-cloudflare/src/routes/posts.tsx
examples/react/start-basic-cloudflare/src/utils/seo.ts
examples/react/start-basic-cloudflare/src/routes/redirect.tsx
examples/react/start-basic/src/routes/users.index.tsx
examples/react/start-basic-cloudflare/src/routes/posts.$postId.tsx
examples/react/start-basic-cloudflare/src/routes/api/users.ts
examples/react/start-basic-cloudflare/src/utils/posts.tsx
examples/react/start-basic/src/routes/api/users.ts
examples/react/start-basic-cloudflare/src/utils/loggingMiddleware.tsx
examples/react/start-basic/src/routes/_pathlessLayout/_nested-layout/route-a.tsx
examples/react/start-basic/src/routes/users.tsx
examples/react/start-basic-cloudflare/src/components/DefaultCatchBoundary.tsx
examples/react/start-basic-cloudflare/src/components/UserError.tsx
examples/react/start-basic-cloudflare/src/routes/_pathlessLayout.tsx
examples/react/start-basic/src/routes/redirect.tsx
examples/react/start-basic-cloudflare/src/routes/__root.tsx
examples/react/start-basic-cloudflare/src/routes/index.tsx
examples/react/start-basic-cloudflare/src/routes/posts_.$postId.deep.tsx
examples/react/start-basic-cloudflare/src/routes/api/users.$userId.ts
examples/react/start-basic-cloudflare/vite.config.ts
examples/react/start-basic-cloudflare/src/routes/deferred.tsx
examples/react/start-basic-cloudflare/src/routes/users.tsx
**/src/routes/**
📄 CodeRabbit inference engine (AGENTS.md)
Place file-based routes under src/routes/ directories
Files:
examples/react/start-basic/src/routes/_pathlessLayout/_nested-layout/route-b.tsx
examples/react/start-basic/src/routes/users.$userId.tsx
examples/react/start-basic-cloudflare/src/routes/customScript[.]js.ts
examples/react/start-basic-cloudflare/src/routes/_pathlessLayout/_nested-layout.tsx
examples/react/start-basic-cloudflare/src/routes/_pathlessLayout/_nested-layout/route-b.tsx
examples/react/start-basic-cloudflare/src/routes/_pathlessLayout/_nested-layout/route-a.tsx
examples/react/start-basic-cloudflare/src/routes/users.$userId.tsx
examples/react/start-basic/src/routes/posts.index.tsx
examples/react/start-basic-cloudflare/src/routes/users.index.tsx
examples/react/start-basic-cloudflare/src/routes/posts.index.tsx
examples/react/start-basic-cloudflare/src/routes/posts.tsx
examples/react/start-basic-cloudflare/src/routes/redirect.tsx
examples/react/start-basic/src/routes/users.index.tsx
examples/react/start-basic-cloudflare/src/routes/posts.$postId.tsx
examples/react/start-basic-cloudflare/src/routes/api/users.ts
examples/react/start-basic/src/routes/api/users.ts
examples/react/start-basic/src/routes/_pathlessLayout/_nested-layout/route-a.tsx
examples/react/start-basic/src/routes/users.tsx
examples/react/start-basic-cloudflare/src/routes/_pathlessLayout.tsx
examples/react/start-basic/src/routes/redirect.tsx
examples/react/start-basic-cloudflare/src/routes/__root.tsx
examples/react/start-basic-cloudflare/src/routes/index.tsx
examples/react/start-basic-cloudflare/src/routes/posts_.$postId.deep.tsx
examples/react/start-basic-cloudflare/src/routes/api/users.$userId.ts
examples/react/start-basic-cloudflare/src/routes/deferred.tsx
examples/react/start-basic-cloudflare/src/routes/users.tsx
**/package.json
📄 CodeRabbit inference engine (AGENTS.md)
Use workspace:* protocol for internal dependencies in package.json files
Files:
examples/react/start-basic-cloudflare/package.json
🧠 Learnings (3)
📚 Learning: 2025-09-23T17:36:12.598Z
Learnt from: CR
PR: TanStack/router#0
File: AGENTS.md:0-0
Timestamp: 2025-09-23T17:36:12.598Z
Learning: Applies to packages/{router-cli,router-generator,router-plugin,virtual-file-routes}/** : Keep CLI, generators, bundler plugins, and virtual file routing utilities in their dedicated tooling package directories
Applied to files:
examples/react/start-basic-cloudflare/.prettierignore
📚 Learning: 2025-09-23T17:36:12.598Z
Learnt from: CR
PR: TanStack/router#0
File: AGENTS.md:0-0
Timestamp: 2025-09-23T17:36:12.598Z
Learning: Applies to **/*.{ts,tsx} : Use TypeScript in strict mode with extensive type safety across the codebase
Applied to files:
examples/react/start-basic-cloudflare/tsconfig.json
📚 Learning: 2025-09-23T17:36:12.598Z
Learnt from: CR
PR: TanStack/router#0
File: AGENTS.md:0-0
Timestamp: 2025-09-23T17:36:12.598Z
Learning: Applies to packages/{react-router,solid-router}/** : Implement React and Solid bindings/components only in packages/react-router/ and packages/solid-router/
Applied to files:
examples/react/start-basic-cloudflare/src/routeTree.gen.ts
🧬 Code graph analysis (21)
examples/react/start-basic-cloudflare/src/routes/customScript[.]js.ts (1)
examples/react/start-basic-cloudflare/src/routes/__root.tsx (1)
Route
(15-63)
examples/react/start-basic-cloudflare/src/routes/_pathlessLayout/_nested-layout.tsx (3)
examples/react/start-basic-cloudflare/src/routes/_pathlessLayout.tsx (1)
Route
(3-5)examples/react/start-basic-cloudflare/src/routes/_pathlessLayout/_nested-layout/route-a.tsx (1)
Route
(3-7)examples/react/start-basic-cloudflare/src/routes/_pathlessLayout/_nested-layout/route-b.tsx (1)
Route
(3-7)
examples/react/start-basic-cloudflare/src/routes/_pathlessLayout/_nested-layout/route-b.tsx (3)
examples/react/start-basic-cloudflare/src/routes/_pathlessLayout.tsx (1)
Route
(3-5)examples/react/start-basic-cloudflare/src/routes/_pathlessLayout/_nested-layout.tsx (1)
Route
(3-5)examples/react/start-basic-cloudflare/src/routes/_pathlessLayout/_nested-layout/route-a.tsx (1)
Route
(3-7)
examples/react/start-basic-cloudflare/src/routes/_pathlessLayout/_nested-layout/route-a.tsx (3)
examples/react/start-basic-cloudflare/src/routes/_pathlessLayout.tsx (1)
Route
(3-5)examples/react/start-basic-cloudflare/src/routes/_pathlessLayout/_nested-layout.tsx (1)
Route
(3-5)examples/react/start-basic-cloudflare/src/routes/_pathlessLayout/_nested-layout/route-b.tsx (1)
Route
(3-7)
examples/react/start-basic-cloudflare/src/components/PostError.tsx (1)
examples/react/start-basic/src/components/PostError.tsx (1)
PostErrorComponent
(4-6)
examples/react/start-basic-cloudflare/src/routeTree.gen.ts (1)
examples/react/start-basic-cloudflare/src/router.tsx (1)
getRouter
(6-16)
examples/react/start-basic-cloudflare/src/routes/users.$userId.tsx (6)
examples/react/start-basic-cloudflare/src/routes/users.tsx (1)
Route
(4-17)examples/react/start-basic-cloudflare/src/routes/api/users.$userId.ts (1)
Route
(5-32)examples/react/start-basic-cloudflare/src/routes/api/users.ts (1)
Route
(41-63)examples/react/start-basic-cloudflare/src/utils/users.tsx (1)
User
(1-5)examples/react/start-basic-cloudflare/src/components/UserError.tsx (1)
UserErrorComponent
(4-6)examples/react/start-basic-cloudflare/src/components/NotFound.tsx (1)
NotFound
(3-25)
examples/react/start-basic-cloudflare/src/routes/users.index.tsx (3)
examples/react/start-basic-cloudflare/src/routes/users.$userId.tsx (1)
Route
(6-26)examples/react/start-basic-cloudflare/src/routes/users.tsx (1)
Route
(4-17)examples/react/start-basic-cloudflare/src/routes/api/users.ts (1)
Route
(41-63)
examples/react/start-basic-cloudflare/src/routes/posts.index.tsx (2)
examples/react/start-basic-cloudflare/src/routes/posts.$postId.tsx (1)
Route
(6-13)examples/react/start-basic-cloudflare/src/routes/posts.tsx (1)
Route
(4-7)
examples/react/start-basic-cloudflare/src/router.tsx (2)
examples/react/start-basic-cloudflare/src/components/DefaultCatchBoundary.tsx (1)
DefaultCatchBoundary
(10-53)examples/react/start-basic-cloudflare/src/components/NotFound.tsx (1)
NotFound
(3-25)
examples/react/start-basic-cloudflare/src/routes/posts.$postId.tsx (6)
examples/react/start-basic-cloudflare/src/routes/posts.index.tsx (1)
Route
(3-5)examples/react/start-basic-cloudflare/src/routes/posts.tsx (1)
Route
(4-7)examples/react/start-basic-cloudflare/src/routes/posts_.$postId.deep.tsx (1)
Route
(5-12)examples/react/start-basic-cloudflare/src/utils/posts.tsx (1)
fetchPost
(10-29)examples/react/start-basic-cloudflare/src/components/PostError.tsx (1)
PostErrorComponent
(4-6)examples/react/start-basic-cloudflare/src/components/NotFound.tsx (1)
NotFound
(3-25)
examples/react/start-basic-cloudflare/src/routes/api/users.ts (4)
examples/react/start-basic-cloudflare/src/routes/users.$userId.tsx (1)
Route
(6-26)examples/react/start-basic-cloudflare/src/routes/users.tsx (1)
Route
(4-17)examples/react/start-basic-cloudflare/src/routes/api/users.$userId.ts (1)
Route
(5-32)examples/react/start-basic-cloudflare/src/utils/users.tsx (1)
User
(1-5)
examples/react/start-basic-cloudflare/src/components/DefaultCatchBoundary.tsx (1)
e2e/react-start/server-routes/src/components/DefaultCatchBoundary.tsx (1)
DefaultCatchBoundary
(10-53)
examples/react/start-basic-cloudflare/src/components/UserError.tsx (1)
examples/react/start-basic/src/components/UserError.tsx (1)
UserErrorComponent
(4-6)
examples/react/start-basic-cloudflare/src/routes/_pathlessLayout.tsx (3)
examples/react/start-basic-cloudflare/src/routes/_pathlessLayout/_nested-layout.tsx (1)
Route
(3-5)examples/react/start-basic-cloudflare/src/routes/_pathlessLayout/_nested-layout/route-a.tsx (1)
Route
(3-7)examples/react/start-basic-cloudflare/src/routes/_pathlessLayout/_nested-layout/route-b.tsx (1)
Route
(3-7)
examples/react/start-basic-cloudflare/src/routes/__root.tsx (5)
examples/react/start-basic-cloudflare/src/routes/customScript[.]js.ts (1)
Route
(3-15)examples/react/start-basic-cloudflare/src/utils/seo.ts (1)
seo
(1-33)examples/react/start-basic-cloudflare/src/components/DefaultCatchBoundary.tsx (1)
DefaultCatchBoundary
(10-53)examples/react/start-basic-cloudflare/src/components/NotFound.tsx (1)
NotFound
(3-25)packages/react-router-devtools/src/TanStackRouterDevtools.tsx (1)
TanStackRouterDevtools
(46-126)
examples/react/start-basic-cloudflare/src/routes/index.tsx (1)
examples/react/start-basic-cloudflare/worker-configuration.d.ts (1)
env
(8972-8972)
examples/react/start-basic-cloudflare/src/routes/posts_.$postId.deep.tsx (2)
examples/react/start-basic-cloudflare/src/utils/posts.tsx (1)
fetchPost
(10-29)examples/react/start-basic-cloudflare/src/components/PostError.tsx (1)
PostErrorComponent
(4-6)
examples/react/start-basic-cloudflare/src/routes/api/users.$userId.ts (3)
examples/react/start-basic-cloudflare/src/routes/users.$userId.tsx (1)
Route
(6-26)examples/react/start-basic-cloudflare/src/routes/api/users.ts (1)
Route
(41-63)examples/react/start-basic-cloudflare/src/utils/users.tsx (1)
User
(1-5)
examples/react/start-basic-cloudflare/src/routes/deferred.tsx (2)
examples/react/start-basic-cloudflare/src/routes/api/users.ts (1)
Route
(41-63)examples/solid/start-basic/src/routes/deferred.tsx (1)
Deferred
(31-62)
examples/react/start-basic-cloudflare/src/routes/users.tsx (4)
examples/react/start-basic-cloudflare/src/routes/users.$userId.tsx (1)
Route
(6-26)examples/react/start-basic-cloudflare/src/routes/api/users.$userId.ts (1)
Route
(5-32)examples/react/start-basic-cloudflare/src/routes/api/users.ts (1)
Route
(41-63)examples/react/start-basic-cloudflare/src/utils/users.tsx (1)
User
(1-5)
🪛 Biome (2.1.2)
examples/react/start-basic-cloudflare/src/routes/deferred.tsx
[error] 43-43: Avoid passing children using a prop
The canonical way to pass children in React is to use JSX elements
(lint/correctness/noChildrenProp)
[error] 53-53: Avoid passing children using a prop
The canonical way to pass children in React is to use JSX elements
(lint/correctness/noChildrenProp)
⏰ 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). (1)
- GitHub Check: Test
🔇 Additional comments (32)
examples/react/start-basic/src/routes/_pathlessLayout/_nested-layout/route-a.tsx (1)
2-2
: Formatting-only change looks goodThe added whitespace keeps the file tidy and doesn’t affect behavior.
examples/react/start-basic/src/routes/_pathlessLayout/_nested-layout/route-b.tsx (1)
2-2
: Formatting-only change looks goodThe spacing tweak is harmless and keeps consistency with neighboring files.
examples/react/start-basic-cloudflare/.gitignore (1)
1-6
: Ignore list covers expected artifactsThe entries align with typical Cloudflare/Vite tooling outputs and keep transient artifacts out of source control. Looks good.
examples/react/start-basic/src/components/UserError.tsx (1)
1-2
: Thanks for splitting the type import.Using a type-only import keeps the runtime bundle clean and aligns with TS strict mode expectations. Looks good.
examples/react/start-basic/src/components/PostError.tsx (1)
1-2
: Appreciate the type-only import cleanup.Separating the
ErrorComponentProps
type import avoids leaking it into the runtime build and matches the updated pattern elsewhere.examples/react/start-basic/src/routes/api/users.ts (1)
6-13
: Cloudflare-compatible middleware update looks goodConfirming the middleware now pulls headers via
getRequestHeaders()
without needing the request arg, which keeps it aligned with the new server context and still sets the outgoing metadata correctly.examples/react/start-basic/src/routes/users.index.tsx (1)
2-2
: LGTM: formatting-only changeNo functional impact.
examples/react/start-basic/src/routes/posts.index.tsx (1)
2-2
: LGTM: formatting-only changeNo functional impact.
examples/react/start-basic-cloudflare/.vscode/settings.json (1)
1-11
: Confirm VS Code version support for files.readonlyInclude — valid since VS Code 1.79 (May 2023); ensure the team’s VS Code baseline is ≥1.79.examples/react/start-basic-cloudflare/src/routes/users.index.tsx (2)
3-5
: LGTMIndex route wiring for /users/ looks correct, and the file is under src/routes as required.
As per coding guidelines
11-16
: Using an anchor for JSON is appropriateLinking to /api/users with an is fine since it returns raw JSON, not a client-routed page.
examples/react/start-basic-cloudflare/.prettierignore (1)
1-3
: LGTMGood ignores for public, lockfile, and generated route tree.
examples/react/start-basic-cloudflare/src/components/UserError.tsx (1)
1-6
: LGTMSimple, typed wrapper around ErrorComponent is correct and consistent with other examples.
examples/react/start-basic-cloudflare/src/routes/_pathlessLayout.tsx (1)
3-16
: LGTMCorrect pathless layout pattern with Outlet; matches file-based routing conventions.
examples/react/start-basic/src/routes/users.$userId.tsx (1)
4-4
: User type export confirmed
TheUser
type is exported in examples/react/start-basic/src/utils/users.tsx, so the import is valid.examples/react/start-basic-cloudflare/src/routes/posts.index.tsx (1)
3-5
: LGTM: Index route wiring is correct for /posts/Trailing-slash path matches index route conventions; component is minimal and fine.
examples/react/start-basic-cloudflare/postcss.config.mjs (1)
1-6
: LGTM: Minimal PostCSS setupESM export with tailwindcss + autoprefixer is standard and should work with Vite.
examples/react/start-basic-cloudflare/src/routes/_pathlessLayout/_nested-layout/route-b.tsx (1)
3-7
: LGTM: Route definition aligns with nested layout structurePath and component naming are consistent with route-a; no issues.
examples/react/start-basic-cloudflare/src/components/PostError.tsx (1)
4-6
: LGTM: Error wrapperSimple pass-through to ErrorComponent is correct and reusable.
examples/react/start-basic-cloudflare/src/router.tsx (1)
6-16
: LGTM: Router factory with sensible defaultsPer-request router creation, default error/not-found components, and scroll restoration are all set appropriately.
examples/react/start-basic-cloudflare/src/routes/_pathlessLayout/_nested-layout/route-a.tsx (1)
3-11
: LGTMRoute registration and component look correct.
examples/react/start-basic-cloudflare/src/routes/posts_.$postId.deep.tsx (1)
5-12
: LGTMLoader, error boundary, and component wiring look correct.
examples/react/start-basic-cloudflare/src/routes/api/users.ts (1)
41-63
: LGTMMiddleware composition, response headers, and GET handler look solid for the example.
examples/react/start-basic-cloudflare/src/components/DefaultCatchBoundary.tsx (1)
10-53
: LGTMError boundary wiring and UX (retry/home/back) look solid for the example.
examples/react/start-basic-cloudflare/src/routeTree.gen.ts (8)
1-10
: LGTM! Generated file header is correctly configured.The file appropriately disables linting and type checking for a generated file, following best practices for auto-generated code.
30-115
: Route configurations look correct.All route updates properly configure:
- Unique IDs matching the path structure
- Correct parent-child relationships
- Proper path definitions for nested and pathless routes
117-233
: Type exports are comprehensive and well-structured.The exported interfaces provide complete type safety for:
- Route lookups by full path, "to" path, and ID
- FileRouteTypes union with all possible paths
- RootRouteChildren for the route tree hierarchy
235-357
: Module augmentation for TanStack Router is properly configured.The declaration merging correctly extends the
@tanstack/react-router
module with typed route metadata, enabling full IntelliSense support for route navigation and parameters.
359-424
: Route children composition follows consistent patterns.The nested route children are properly assembled with correct parent-child relationships, maintaining the expected route tree structure for pathless layouts and nested routes.
425-438
: Route tree export is correctly assembled.The final route tree properly chains
_addFileChildren
and_addFileTypes
to create a fully typed router configuration.
11-28
: Ignore bracketed dot syntax in route imports. ThecustomScript[.]js
pattern is intentionally generated and correctly resolved by TypeScript and the Cloudflare Workers bundler; no changes required.Likely an incorrect or invalid review comment.
440-447
: Augment@tanstack/react-router
instead of@tanstack/react-start
Move yourRegister
declaration intodeclare module '@tanstack/react-router' { interface Register { router: ReturnType<typeof getRouter> } }to match the SSR guide.
⛔ Skipped due to learnings
Learnt from: CR PR: TanStack/router#0 File: AGENTS.md:0-0 Timestamp: 2025-09-23T17:36:12.598Z Learning: Applies to packages/{react-router,solid-router}/** : Implement React and Solid bindings/components only in packages/react-router/ and packages/solid-router/
examples/react/start-basic-cloudflare/src/routes/_pathlessLayout/_nested-layout.tsx
Show resolved
Hide resolved
examples/react/start-basic-cloudflare/src/routes/_pathlessLayout/_nested-layout.tsx
Show resolved
Hide resolved
There was a problem hiding this 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
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
examples/react/start-basic/src/utils/posts.tsx (1)
12-29
: Don’t log entire request context; add runtime validation instead of a blind cast.
- Logging
context
can leak secrets in server logs.as PostType
trusts unvalidated JSON; prefer a type guard.Apply:
- console.log('Request context:', context) + // Avoid logging full request context to prevent leaking secrets - const post = await res.json() - - return post as PostType + const post = await res.json() + if (!isPostType(post)) { + throw new Error('Invalid post payload') + } + return postAdd this helper (outside the handler):
function isPostType(value: any): value is PostType { return ( value && typeof value.id === 'number' && typeof value.title === 'string' && typeof value.body === 'string' ) }
🧹 Nitpick comments (6)
examples/react/start-basic-cloudflare/src/utils/posts.tsx (5)
26-28
: Avoid unsafe type assertion; validate the JSON shapeReplace the blind cast with a minimal runtime check and type guard.
- const post = await res.json() - - return post as PostType + const raw = (await res.json()) as unknown + if (!isPost(raw)) { + throw new Error('Invalid post response') + } + return rawAdd this helper once in the module (outside the selected lines):
function isPost(u: unknown): u is PostType { const p = u as any return ( p && typeof p.id === 'number' && typeof p.title === 'string' && typeof p.body === 'string' ) }As per coding guidelines
38-40
: Validate and narrow the posts list instead of asserting typesPrevents runtime surprises if the API changes.
- const posts = await res.json() - - return (posts as Array<PostType>).slice(0, 10) + const raw = (await res.json()) as unknown + if (!Array.isArray(raw)) { + throw new Error('Invalid posts response') + } + const posts = raw.filter(isPost).slice(0, 10) + return postsAs per coding guidelines
23-24
: Include status details in error messagesHelps debugging without inspecting external logs.
- throw new Error('Failed to fetch post') + throw new Error(`Failed to fetch post: ${res.status} ${res.statusText}`)- if (!res.ok) { - throw new Error('Failed to fetch posts') - } + if (!res.ok) { + throw new Error(`Failed to fetch posts: ${res.status} ${res.statusText}`) + }Also applies to: 34-36
11-11
: Strengthen input validation for post idReject non-numeric ids early.
- .inputValidator((d: string) => d) + .inputValidator((d: string) => { + if (!/^\d+$/.test(d)) { + throw new Error('Invalid post id') + } + return d + })As per coding guidelines
1-1
: Rename file to .ts (no JSX present)Keeps extensions meaningful and avoids unnecessary TSX handling.
examples/react/start-basic/src/utils/posts.tsx (1)
38-41
: Validate the posts array and avoid overfetching; request only 10.
- Guard the JSON shape at runtime.
- Use
_limit=10
to avoid fetching 100 items only to slice.Apply:
- const posts = await res.json() - - return (posts as Array<PostType>).slice(0, 10) + const posts = await res.json() + if (!Array.isArray(posts) || !posts.every(isPostType)) { + throw new Error('Invalid posts payload') + } + return posts.slice(0, 10)Also update the fetch URL (outside this hunk):
const res = await fetch('https://jsonplaceholder.typicode.com/posts?_limit=10')
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
examples/react/start-basic-cloudflare/src/utils/posts.tsx
(1 hunks)examples/react/start-basic/src/utils/posts.tsx
(3 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use TypeScript in strict mode with extensive type safety across the codebase
Files:
examples/react/start-basic-cloudflare/src/utils/posts.tsx
examples/react/start-basic/src/utils/posts.tsx
examples/{react,solid}/**
📄 CodeRabbit inference engine (AGENTS.md)
Keep example applications under examples/react/ and examples/solid/
Files:
examples/react/start-basic-cloudflare/src/utils/posts.tsx
examples/react/start-basic/src/utils/posts.tsx
🧬 Code graph analysis (2)
examples/react/start-basic-cloudflare/src/utils/posts.tsx (1)
examples/react/start-basic/src/utils/posts.tsx (3)
PostType
(4-8)fetchPost
(10-29)fetchPosts
(31-41)
examples/react/start-basic/src/utils/posts.tsx (1)
examples/react/start-basic-cloudflare/src/utils/posts.tsx (1)
PostType
(4-8)
⏰ 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 (2)
examples/react/start-basic-cloudflare/src/utils/posts.tsx (1)
4-8
: PostType shape looks goodMatches JSONPlaceholder and aligns with the sibling start-basic example.
examples/react/start-basic/src/utils/posts.tsx (1)
5-5
: Approve change — confirmed no downstreamid: string
usage in examples/react/start-basic.
There was a problem hiding this 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 (3)
examples/react/start-basic-cloudflare/src/utils/posts.tsx (3)
10-12
: Validate the input id (numeric) in the inputValidatorGuard against invalid ids early to avoid unnecessary network calls and clearer errors.
Apply this diff:
-export const fetchPost = createServerFn({ method: 'POST' }) - .inputValidator((d: string) => d) +export const fetchPost = createServerFn({ method: 'POST' }) + .inputValidator((d: string) => { + if (!/^\d+$/.test(d)) { + throw new Error('Invalid post id') + } + return d + })As per coding guidelines.
25-27
: Avoid unsafe type assertion; validate the post payload at runtimeReplace the
as PostType
cast with a minimal runtime type guard for stricter safety.Apply this diff:
- const post = await res.json() - - return post as PostType + const raw = (await res.json()) as unknown + if (!isPost(raw)) { + throw new Error('Invalid post payload') + } + return rawAdd these helpers near the type definition:
function isPost(u: unknown): u is PostType { return ( !!u && typeof (u as any).id === 'number' && typeof (u as any).title === 'string' && typeof (u as any).body === 'string' ) }As per coding guidelines.
37-39
: Validate and narrow the posts array before slicingPrevents runtime errors if the API shape changes and removes the
as
cast.Apply this diff:
- const posts = await res.json() - - return (posts as Array<PostType>).slice(0, 10) + const data = (await res.json()) as unknown + if (!isPosts(data)) { + throw new Error('Invalid posts payload') + } + return data.slice(0, 10)Add this helper (can be co-located with isPost):
function isPosts(u: unknown): u is Array<PostType> { return Array.isArray(u) && u.every(isPost) }As per coding guidelines.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
examples/react/start-basic-cloudflare/src/utils/posts.tsx
(1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use TypeScript in strict mode with extensive type safety across the codebase
Files:
examples/react/start-basic-cloudflare/src/utils/posts.tsx
examples/{react,solid}/**
📄 CodeRabbit inference engine (AGENTS.md)
Keep example applications under examples/react/ and examples/solid/
Files:
examples/react/start-basic-cloudflare/src/utils/posts.tsx
🧬 Code graph analysis (1)
examples/react/start-basic-cloudflare/src/utils/posts.tsx (1)
examples/react/start-basic/src/utils/posts.tsx (3)
PostType
(4-8)fetchPost
(10-29)fetchPosts
(31-41)
⏰ 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 (1)
examples/react/start-basic-cloudflare/src/utils/posts.tsx (1)
4-8
: PostType shape LGTMMatches the JSONPlaceholder payload and is consistent with the other example.
This adds a
start-basic-cloudflare
example to theexamples/react
directory.Summary by CodeRabbit