-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
solid-start netlify vite plugin example #5575
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
Conversation
WalkthroughAdds a complete Solid Start example targeted for Netlify: project/config files, Vite/Tailwind/PostCSS setup, generated route tree and router, many file-based routes (pages + APIs), shared UI/error components, utilities (posts, users, seo, logging middleware), and docs/ignore updates. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant Browser
participant DevServer as Vite/Netlify Dev
participant Router as Solid Router (getRouter)
participant Middleware as logMiddleware
participant ServerFn as Server Functions / API
participant Route as File Route (loader/component)
Note left of Browser: navigate to /posts/123
Browser->>DevServer: HTTP GET /posts/123
DevServer->>Router: route match -> resolve Route
Router->>Middleware: run middleware (preLog) [client→server timing]
Router->>Route: invoke loader
Route->>ServerFn: call fetchPost / API (/api/users or external)
ServerFn-->>Route: returns data (or error)
Router-->>DevServer: render response (HTML / hydration)
DevServer-->>Browser: HTML + assets
Browser->>Middleware: client-side logging reads durations (durationToServer, durationFromServer)
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches🧪 Generate unit tests (beta)
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. Comment |
|
View your CI Pipeline Execution ↗ for commit 559a376
☁️ 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-router-ssr-query
@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: 14
🧹 Nitpick comments (15)
examples/solid/start-basic-netlify/public/site.webmanifest (1)
2-3: Consider providing example values for the manifest name fields.The
nameandshort_namefields are empty. For a complete example, consider adding placeholder values like:
"name": "Solid Start Netlify Example""short_name": "Start Netlify"examples/solid/start-basic-netlify/src/components/PostError.tsx (1)
4-6: Consider if this wrapper component is necessary.
PostErrorComponentsimply forwards the error prop toErrorComponentwithout adding any logic. This pattern appears in other examples but could be simplified by usingErrorComponentdirectly in routes where this is used, unless there's a specific reason to maintain consistency across examples.examples/solid/start-basic-netlify/src/utils/posts.tsx (2)
10-28: Consider input validation and response type checking.Two areas for improvement:
Input validation (Line 11): The input validator simply passes the string through without validating it's a valid post ID. Consider validating it's numeric.
Type assertion (Line 27): The API response is cast to
PostTypewithout runtime validation. If the external API changes its shape, this could cause issues downstream.Example improvement for input validation:
-export const fetchPost = createServerFn({ method: 'POST' }) - .inputValidator((d: string) => d) +export const fetchPost = createServerFn({ method: 'POST' }) + .inputValidator((d: string) => { + const id = parseInt(d, 10) + if (isNaN(id) || id <= 0) { + throw new Error('Invalid post ID') + } + return d + }) .handler(async ({ data }) => {
30-40: Type assertion without validation applies here too.The same type assertion pattern from
fetchPostapplies here (Line 39). Consider runtime validation as mentioned above.examples/solid/start-basic-netlify/src/routes/api/users.$userId.ts (1)
18-19: Remove the eslint-disable; the assertion is fine or replace with runtime validationThe cast from unknown/any to User is expected here; drop the rule suppression. Optionally, validate shape (e.g., with zod) before returning.
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion - const user = (await res.json()) as User + const user = (await res.json()) as Userexamples/solid/start-basic-netlify/src/components/NotFound.tsx (1)
1-4: Type children precisely (strict TS) and keep API consistentPrefer Solid’s JSX type over any. As per coding guidelines.
import { Link } from '@tanstack/solid-router' +import type { JSX } from 'solid-js' -export function NotFound({ children }: { children?: any }) { +export function NotFound({ children }: { children?: JSX.Element }) {examples/solid/start-basic-netlify/src/routes/api/users.ts (1)
53-60: Minor polish: drop eslint-disable, and add light caching on static example data
- The type assertion is reasonable; the rule suppression can be removed.
- Add Cache-Control to make the example nicer for demos.
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion - const data = (await res.json()) as Array<User> + const data = (await res.json()) as Array<User> @@ - return json( - list.map((u) => ({ id: u.id, name: u.name, email: u.email })), - ) + return json( + list.map((u) => ({ id: u.id, name: u.name, email: u.email })), + { headers: { 'Cache-Control': 'public, max-age=60' } }, + )examples/solid/start-basic-netlify/src/routes/_pathlessLayout/_nested-layout.tsx (1)
for semantics and accessibility
11-28: Optional: useWrap the link row in a nav with an aria-label.
- <div class="flex gap-2 border-b"> + <nav class="flex gap-2 border-b" aria-label="Nested layout navigation"> @@ - </div> + </nav>examples/solid/start-basic-netlify/src/routes/users.tsx (2)
25-44: Keep loader data type‑pure; render the placeholder separatelyMixing
{ id: 'i-do-not-exist', ... }(string id) withUser[]weakens type guarantees under strict mode. Render the “non‑existent” item as its own<li>to keepusers()typed asUser[].- <ul class="list-disc pl-4"> - {[ - ...users(), - { id: 'i-do-not-exist', name: 'Non-existent User', email: '' }, - ].map((user) => { - return ( - <li class="whitespace-nowrap"> - <Link - to="/users/$userId" - params={{ - userId: String(user.id), - }} - class="block py-1 text-blue-800 hover:text-blue-600" - activeProps={{ class: 'text-black font-bold' }} - > - <div>{user.name}</div> - </Link> - </li> - ) - })} - </ul> + <ul class="list-disc pl-4"> + {users().map((user) => ( + <li class="whitespace-nowrap"> + <Link + to="/users/$userId" + params={{ userId: String(user.id) }} + class="block py-1 text-blue-800 hover:text-blue-600" + activeProps={{ class: 'text-black font-bold' }} + > + <div>{user.name}</div> + </Link> + </li> + ))} + <li class="whitespace-nowrap"> + <Link + to="/users/$userId" + params={{ userId: 'i-do-not-exist' }} + class="block py-1 text-blue-800 hover:text-blue-600" + activeProps={{ class: 'text-black font-bold' }} + > + <div>Non-existent User</div> + </Link> + </li> + </ul>
5-15: Tighten loader typing; avoidasMake the return type explicit to keep strict type‑safety.
- loader: async () => { + loader: async (): Promise<Array<User>> => { const res = await fetch('/api/users') if (!res.ok) { throw new Error('Unexpected status code') } - const data = await res.json() - return data as Array<User> + const data: Array<User> = await res.json() + return data },examples/solid/start-basic-netlify/src/routes/users.$userId.tsx (1)
14-17: Avoidascast; keep typed JSON- const data = await res.json() - return data as User + const data: User = await res.json() + return dataexamples/solid/start-basic-netlify/src/utils/seo.ts (1)
12-30: Skip undefined meta to avoidcontent="undefined"Guard optional fields so only provided tags render.
- const tags = [ - { title }, - { name: 'description', content: description }, - { name: 'keywords', content: keywords }, - { name: 'twitter:title', content: title }, - { name: 'twitter:description', content: description }, - { name: 'twitter:creator', content: '@tannerlinsley' }, - { name: 'twitter:site', content: '@tannerlinsley' }, - { name: 'og:type', content: 'website' }, - { name: 'og:title', content: title }, - { name: 'og:description', content: description }, - ...(image - ? [ - { name: 'twitter:image', content: image }, - { name: 'twitter:card', content: 'summary_large_image' }, - { name: 'og:image', content: image }, - ] - : []), - ] + const tags = [ + { title }, + ...(description ? [{ name: 'description', content: description }] : []), + ...(keywords ? [{ name: 'keywords', content: keywords }] : []), + { name: 'twitter:title', content: title }, + ...(description ? [{ name: 'twitter:description', content: description }] : []), + { name: 'twitter:creator', content: '@tannerlinsley' }, + { name: 'twitter:site', content: '@tannerlinsley' }, + { name: 'og:type', content: 'website' }, + { name: 'og:title', content: title }, + ...(description ? [{ name: 'og:description', content: description }] : []), + ...(image + ? [ + { name: 'twitter:image', content: image }, + { name: 'twitter:card', content: 'summary_large_image' }, + { name: 'og:image', content: image }, + ] + : []), + ]examples/solid/start-basic-netlify/src/routes/posts.tsx (1)
15-32: PreservePost[]typing; render the fake item separatelyAvoid mixing a string id with real posts to keep types clean.
- {[...posts(), { id: 'i-do-not-exist', title: 'Non-existent Post' }].map( - (post) => { + {posts().map((post) => { return ( <li class="whitespace-nowrap"> <Link to="/posts/$postId" params={{ postId: String(post.id), }} class="block py-1 text-blue-800 hover:text-blue-600" activeProps={{ class: 'text-black font-bold' }} > <div>{post.title.substring(0, 20)}</div> </Link> </li> - ) - }, - )} + ) + })} + <li class="whitespace-nowrap"> + <Link + to="/posts/$postId" + params={{ postId: 'i-do-not-exist' }} + class="block py-1 text-blue-800 hover:text-blue-600" + activeProps={{ class: 'text-black font-bold' }} + > + <div>Non-existent Post</div> + </Link> + </li>examples/solid/start-basic-netlify/src/routes/__root.tsx (1)
27-30: Correct SEO title: this example is Solid, not React- title: - 'TanStack Start | Type-Safe, Client-First, Full-Stack React Framework', - description: `TanStack Start is a type-safe, client-first, full-stack React framework. `, + title: + 'TanStack Start | Type-Safe, Client-First, Full-Stack Solid Framework', + description: `TanStack Start is a type-safe, client-first, full-stack Solid framework.`,examples/solid/start-basic-netlify/src/routes/deferred.tsx (1)
41-49: Use JSX children for<Await>instead of thechildrenpropRefactor to the canonical JSX children form to satisfy lint and improve readability.
- <Suspense fallback={<div>Loading person...</div>}> - <Await - promise={loaderData().deferredPerson} - children={(data) => ( - <div data-testid="deferred-person"> - {data.name} - {data.randomNumber} - </div> - )} - /> - </Suspense> + <Suspense fallback={<div>Loading person...</div>}> + <Await promise={loaderData().deferredPerson}> + {(data) => ( + <div data-testid="deferred-person"> + {data.name} - {data.randomNumber} + </div> + )} + </Await> + </Suspense> - <Suspense fallback={<div>Loading stuff...</div>}> - <Await - promise={loaderData().deferredStuff} - children={(data) => <h3 data-testid="deferred-stuff">{data}</h3>} - /> - </Suspense> + <Suspense fallback={<div>Loading stuff...</div>}> + <Await promise={loaderData().deferredStuff}> + {(data) => <h3 data-testid="deferred-stuff">{data}</h3>} + </Await> + </Suspense>Also applies to: 51-55
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (8)
examples/solid/start-basic-netlify/public/android-chrome-192x192.pngis excluded by!**/*.pngexamples/solid/start-basic-netlify/public/android-chrome-512x512.pngis excluded by!**/*.pngexamples/solid/start-basic-netlify/public/apple-touch-icon.pngis excluded by!**/*.pngexamples/solid/start-basic-netlify/public/favicon-16x16.pngis excluded by!**/*.pngexamples/solid/start-basic-netlify/public/favicon-32x32.pngis excluded by!**/*.pngexamples/solid/start-basic-netlify/public/favicon.icois excluded by!**/*.icoexamples/solid/start-basic-netlify/public/favicon.pngis excluded by!**/*.pngpnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (41)
docs/start/config.json(1 hunks)examples/solid/start-basic-netlify/.gitignore(1 hunks)examples/solid/start-basic-netlify/.prettierignore(1 hunks)examples/solid/start-basic-netlify/.vscode/settings.json(1 hunks)examples/solid/start-basic-netlify/README.md(1 hunks)examples/solid/start-basic-netlify/netlify.toml(1 hunks)examples/solid/start-basic-netlify/package.json(1 hunks)examples/solid/start-basic-netlify/postcss.config.mjs(1 hunks)examples/solid/start-basic-netlify/public/site.webmanifest(1 hunks)examples/solid/start-basic-netlify/src/components/DefaultCatchBoundary.tsx(1 hunks)examples/solid/start-basic-netlify/src/components/NotFound.tsx(1 hunks)examples/solid/start-basic-netlify/src/components/PostError.tsx(1 hunks)examples/solid/start-basic-netlify/src/components/UserError.tsx(1 hunks)examples/solid/start-basic-netlify/src/routeTree.gen.ts(1 hunks)examples/solid/start-basic-netlify/src/router.tsx(1 hunks)examples/solid/start-basic-netlify/src/routes/__root.tsx(1 hunks)examples/solid/start-basic-netlify/src/routes/_pathlessLayout.tsx(1 hunks)examples/solid/start-basic-netlify/src/routes/_pathlessLayout/_nested-layout.tsx(1 hunks)examples/solid/start-basic-netlify/src/routes/_pathlessLayout/_nested-layout/route-a.tsx(1 hunks)examples/solid/start-basic-netlify/src/routes/_pathlessLayout/_nested-layout/route-b.tsx(1 hunks)examples/solid/start-basic-netlify/src/routes/api/users.$userId.ts(1 hunks)examples/solid/start-basic-netlify/src/routes/api/users.ts(1 hunks)examples/solid/start-basic-netlify/src/routes/customScript[.]js.ts(1 hunks)examples/solid/start-basic-netlify/src/routes/deferred.tsx(1 hunks)examples/solid/start-basic-netlify/src/routes/index.tsx(1 hunks)examples/solid/start-basic-netlify/src/routes/posts.$postId.tsx(1 hunks)examples/solid/start-basic-netlify/src/routes/posts.index.tsx(1 hunks)examples/solid/start-basic-netlify/src/routes/posts.tsx(1 hunks)examples/solid/start-basic-netlify/src/routes/posts_.$postId.deep.tsx(1 hunks)examples/solid/start-basic-netlify/src/routes/redirect.tsx(1 hunks)examples/solid/start-basic-netlify/src/routes/users.$userId.tsx(1 hunks)examples/solid/start-basic-netlify/src/routes/users.index.tsx(1 hunks)examples/solid/start-basic-netlify/src/routes/users.tsx(1 hunks)examples/solid/start-basic-netlify/src/styles/app.css(1 hunks)examples/solid/start-basic-netlify/src/utils/loggingMiddleware.tsx(1 hunks)examples/solid/start-basic-netlify/src/utils/posts.tsx(1 hunks)examples/solid/start-basic-netlify/src/utils/seo.ts(1 hunks)examples/solid/start-basic-netlify/src/utils/users.tsx(1 hunks)examples/solid/start-basic-netlify/tailwind.config.mjs(1 hunks)examples/solid/start-basic-netlify/tsconfig.json(1 hunks)examples/solid/start-basic-netlify/vite.config.ts(1 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use TypeScript in strict mode with extensive type safety across the codebase
Files:
examples/solid/start-basic-netlify/src/routes/redirect.tsxexamples/solid/start-basic-netlify/src/routes/posts.tsxexamples/solid/start-basic-netlify/src/components/PostError.tsxexamples/solid/start-basic-netlify/src/components/NotFound.tsxexamples/solid/start-basic-netlify/src/routes/customScript[.]js.tsexamples/solid/start-basic-netlify/src/routes/_pathlessLayout/_nested-layout.tsxexamples/solid/start-basic-netlify/src/utils/seo.tsexamples/solid/start-basic-netlify/src/components/UserError.tsxexamples/solid/start-basic-netlify/src/utils/loggingMiddleware.tsxexamples/solid/start-basic-netlify/src/routes/posts.index.tsxexamples/solid/start-basic-netlify/src/components/DefaultCatchBoundary.tsxexamples/solid/start-basic-netlify/src/routes/users.$userId.tsxexamples/solid/start-basic-netlify/src/routes/deferred.tsxexamples/solid/start-basic-netlify/src/router.tsxexamples/solid/start-basic-netlify/src/routes/posts_.$postId.deep.tsxexamples/solid/start-basic-netlify/src/routes/api/users.$userId.tsexamples/solid/start-basic-netlify/src/routes/users.tsxexamples/solid/start-basic-netlify/src/routes/api/users.tsexamples/solid/start-basic-netlify/src/utils/posts.tsxexamples/solid/start-basic-netlify/src/routes/index.tsxexamples/solid/start-basic-netlify/src/utils/users.tsxexamples/solid/start-basic-netlify/src/routes/__root.tsxexamples/solid/start-basic-netlify/src/routes/_pathlessLayout.tsxexamples/solid/start-basic-netlify/src/routes/posts.$postId.tsxexamples/solid/start-basic-netlify/src/routes/_pathlessLayout/_nested-layout/route-b.tsxexamples/solid/start-basic-netlify/src/routes/_pathlessLayout/_nested-layout/route-a.tsxexamples/solid/start-basic-netlify/src/routes/users.index.tsxexamples/solid/start-basic-netlify/vite.config.tsexamples/solid/start-basic-netlify/src/routeTree.gen.ts
**/src/routes/**
📄 CodeRabbit inference engine (AGENTS.md)
Place file-based routes under src/routes/ directories
Files:
examples/solid/start-basic-netlify/src/routes/redirect.tsxexamples/solid/start-basic-netlify/src/routes/posts.tsxexamples/solid/start-basic-netlify/src/routes/customScript[.]js.tsexamples/solid/start-basic-netlify/src/routes/_pathlessLayout/_nested-layout.tsxexamples/solid/start-basic-netlify/src/routes/posts.index.tsxexamples/solid/start-basic-netlify/src/routes/users.$userId.tsxexamples/solid/start-basic-netlify/src/routes/deferred.tsxexamples/solid/start-basic-netlify/src/routes/posts_.$postId.deep.tsxexamples/solid/start-basic-netlify/src/routes/api/users.$userId.tsexamples/solid/start-basic-netlify/src/routes/users.tsxexamples/solid/start-basic-netlify/src/routes/api/users.tsexamples/solid/start-basic-netlify/src/routes/index.tsxexamples/solid/start-basic-netlify/src/routes/__root.tsxexamples/solid/start-basic-netlify/src/routes/_pathlessLayout.tsxexamples/solid/start-basic-netlify/src/routes/posts.$postId.tsxexamples/solid/start-basic-netlify/src/routes/_pathlessLayout/_nested-layout/route-b.tsxexamples/solid/start-basic-netlify/src/routes/_pathlessLayout/_nested-layout/route-a.tsxexamples/solid/start-basic-netlify/src/routes/users.index.tsx
examples/{react,solid}/**
📄 CodeRabbit inference engine (AGENTS.md)
Keep example applications under examples/react/ and examples/solid/
Files:
examples/solid/start-basic-netlify/src/routes/redirect.tsxexamples/solid/start-basic-netlify/netlify.tomlexamples/solid/start-basic-netlify/src/routes/posts.tsxexamples/solid/start-basic-netlify/src/components/PostError.tsxexamples/solid/start-basic-netlify/src/components/NotFound.tsxexamples/solid/start-basic-netlify/src/routes/customScript[.]js.tsexamples/solid/start-basic-netlify/src/routes/_pathlessLayout/_nested-layout.tsxexamples/solid/start-basic-netlify/src/utils/seo.tsexamples/solid/start-basic-netlify/public/site.webmanifestexamples/solid/start-basic-netlify/src/components/UserError.tsxexamples/solid/start-basic-netlify/src/utils/loggingMiddleware.tsxexamples/solid/start-basic-netlify/src/routes/posts.index.tsxexamples/solid/start-basic-netlify/src/components/DefaultCatchBoundary.tsxexamples/solid/start-basic-netlify/src/routes/users.$userId.tsxexamples/solid/start-basic-netlify/src/routes/deferred.tsxexamples/solid/start-basic-netlify/README.mdexamples/solid/start-basic-netlify/src/router.tsxexamples/solid/start-basic-netlify/src/routes/posts_.$postId.deep.tsxexamples/solid/start-basic-netlify/src/routes/api/users.$userId.tsexamples/solid/start-basic-netlify/src/routes/users.tsxexamples/solid/start-basic-netlify/src/routes/api/users.tsexamples/solid/start-basic-netlify/src/utils/posts.tsxexamples/solid/start-basic-netlify/package.jsonexamples/solid/start-basic-netlify/src/styles/app.cssexamples/solid/start-basic-netlify/src/routes/index.tsxexamples/solid/start-basic-netlify/src/utils/users.tsxexamples/solid/start-basic-netlify/postcss.config.mjsexamples/solid/start-basic-netlify/src/routes/__root.tsxexamples/solid/start-basic-netlify/src/routes/_pathlessLayout.tsxexamples/solid/start-basic-netlify/src/routes/posts.$postId.tsxexamples/solid/start-basic-netlify/src/routes/_pathlessLayout/_nested-layout/route-b.tsxexamples/solid/start-basic-netlify/src/routes/_pathlessLayout/_nested-layout/route-a.tsxexamples/solid/start-basic-netlify/src/routes/users.index.tsxexamples/solid/start-basic-netlify/tsconfig.jsonexamples/solid/start-basic-netlify/tailwind.config.mjsexamples/solid/start-basic-netlify/vite.config.tsexamples/solid/start-basic-netlify/src/routeTree.gen.ts
docs/{router,start}/**
📄 CodeRabbit inference engine (AGENTS.md)
Place router docs under docs/router/ and start framework docs under docs/start/
Files:
docs/start/config.json
**/package.json
📄 CodeRabbit inference engine (AGENTS.md)
Use workspace:* protocol for internal dependencies in package.json files
Files:
examples/solid/start-basic-netlify/package.json
🧠 Learnings (2)
📚 Learning: 2025-10-01T18:31:35.420Z
Learnt from: schiller-manuel
PR: TanStack/router#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:
examples/solid/start-basic-netlify/.vscode/settings.jsonexamples/solid/start-basic-netlify/src/routeTree.gen.ts
📚 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/solid/start-basic-netlify/tsconfig.json
🧬 Code graph analysis (24)
examples/solid/start-basic-netlify/src/routes/redirect.tsx (3)
examples/solid/start-basic-netlify/src/routes/posts.$postId.tsx (1)
Route(6-13)examples/solid/start-basic-netlify/src/routes/posts.index.tsx (1)
Route(3-5)examples/solid/start-basic-netlify/src/routes/posts.tsx (1)
Route(4-7)
examples/solid/start-basic-netlify/src/routes/posts.tsx (3)
examples/solid/start-basic-netlify/src/routes/posts.$postId.tsx (1)
Route(6-13)examples/solid/start-basic-netlify/src/routes/posts.index.tsx (1)
Route(3-5)examples/solid/start-basic-netlify/src/utils/posts.tsx (1)
fetchPosts(30-40)
examples/solid/start-basic-netlify/src/components/PostError.tsx (2)
examples/solid/start-basic/src/components/PostError.tsx (1)
PostErrorComponent(3-5)examples/solid/start-basic-solid-query/src/routes/posts.$postId.tsx (1)
PostErrorComponent(7-9)
examples/solid/start-basic-netlify/src/components/NotFound.tsx (3)
examples/solid/start-basic-cloudflare/src/components/NotFound.tsx (1)
NotFound(3-25)examples/solid/start-basic-solid-query/src/components/NotFound.tsx (1)
NotFound(3-25)examples/solid/start-basic/src/components/NotFound.tsx (1)
NotFound(3-25)
examples/solid/start-basic-netlify/src/routes/customScript[.]js.ts (1)
examples/solid/start-basic-netlify/src/routes/__root.tsx (1)
Route(16-64)
examples/solid/start-basic-netlify/src/routes/_pathlessLayout/_nested-layout.tsx (3)
examples/solid/start-basic-netlify/src/routes/_pathlessLayout.tsx (1)
Route(3-5)examples/solid/start-basic-netlify/src/routes/_pathlessLayout/_nested-layout/route-a.tsx (1)
Route(3-7)examples/solid/start-basic-netlify/src/routes/_pathlessLayout/_nested-layout/route-b.tsx (1)
Route(3-7)
examples/solid/start-basic-netlify/src/components/UserError.tsx (1)
examples/solid/start-basic/src/components/UserError.tsx (1)
UserErrorComponent(3-5)
examples/solid/start-basic-netlify/src/routes/posts.index.tsx (4)
examples/solid/start-basic-netlify/src/routes/index.tsx (1)
Route(4-7)examples/solid/start-basic-netlify/src/routes/posts.$postId.tsx (1)
Route(6-13)examples/solid/start-basic-netlify/src/routes/posts.tsx (1)
Route(4-7)examples/solid/start-basic-netlify/src/routes/users.index.tsx (1)
Route(3-5)
examples/solid/start-basic-netlify/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/src/components/DefaultCatchBoundary.tsx (1)
DefaultCatchBoundary(10-53)
examples/solid/start-basic-netlify/src/routes/users.$userId.tsx (4)
examples/solid/start-basic-netlify/src/routes/api/users.$userId.ts (1)
Route(5-33)examples/solid/start-basic-netlify/src/utils/users.tsx (1)
User(1-5)examples/solid/start-basic-netlify/src/components/UserError.tsx (1)
UserErrorComponent(4-6)examples/solid/start-basic-netlify/src/components/NotFound.tsx (1)
NotFound(3-25)
examples/solid/start-basic-netlify/src/routes/deferred.tsx (1)
examples/solid/start-basic/src/routes/deferred.tsx (2)
Deferred(31-62)deferredStuff(19-27)
examples/solid/start-basic-netlify/src/router.tsx (3)
examples/solid/start-basic-netlify/src/components/DefaultCatchBoundary.tsx (1)
DefaultCatchBoundary(10-53)examples/solid/start-basic-netlify/src/components/NotFound.tsx (1)
NotFound(3-25)examples/solid/start-basic-cloudflare/src/router.tsx (1)
getRouter(6-16)
examples/solid/start-basic-netlify/src/routes/posts_.$postId.deep.tsx (3)
examples/solid/start-basic-netlify/src/routes/posts.$postId.tsx (1)
Route(6-13)examples/solid/start-basic-netlify/src/utils/posts.tsx (1)
fetchPost(10-28)examples/solid/start-basic-netlify/src/components/PostError.tsx (1)
PostErrorComponent(4-6)
examples/solid/start-basic-netlify/src/routes/api/users.$userId.ts (3)
examples/solid/start-basic-netlify/src/routes/api/users.ts (1)
Route(41-64)examples/solid/start-basic-netlify/src/routes/users.$userId.tsx (1)
Route(6-26)examples/solid/start-basic-netlify/src/utils/users.tsx (1)
User(1-5)
examples/solid/start-basic-netlify/src/routes/users.tsx (3)
examples/solid/start-basic-netlify/src/routes/api/users.ts (1)
Route(41-64)examples/solid/start-basic-netlify/src/routes/users.$userId.tsx (1)
Route(6-26)examples/solid/start-basic-netlify/src/utils/users.tsx (1)
User(1-5)
examples/solid/start-basic-netlify/src/routes/api/users.ts (3)
packages/start-server-core/src/request-response.ts (1)
getRequestHeaders(77-80)examples/solid/start-basic-netlify/src/routes/api/users.$userId.ts (1)
Route(5-33)examples/solid/start-basic-netlify/src/utils/users.tsx (1)
User(1-5)
examples/solid/start-basic-netlify/src/routes/index.tsx (4)
examples/solid/start-basic-netlify/src/routes/api/users.ts (1)
Route(41-64)examples/solid/start-basic-netlify/src/routes/customScript[.]js.ts (1)
Route(3-15)examples/solid/start-basic-netlify/src/routes/deferred.tsx (1)
Route(18-29)examples/solid/start-basic-netlify/src/routes/posts.tsx (1)
Route(4-7)
examples/solid/start-basic-netlify/src/routes/__root.tsx (9)
examples/solid/start-basic-netlify/src/routes/index.tsx (1)
Route(4-7)examples/solid/start-basic-netlify/src/routes/_pathlessLayout/_nested-layout/route-a.tsx (1)
Route(3-7)examples/solid/start-basic-netlify/src/routes/customScript[.]js.ts (1)
Route(3-15)examples/solid/start-basic-netlify/src/routes/deferred.tsx (1)
Route(18-29)examples/solid/start-basic-netlify/src/routes/posts.tsx (1)
Route(4-7)examples/solid/start-basic-netlify/src/routes/users.$userId.tsx (1)
Route(6-26)examples/solid/start-basic-netlify/src/utils/seo.ts (1)
seo(1-33)examples/solid/start-basic-netlify/src/components/DefaultCatchBoundary.tsx (1)
DefaultCatchBoundary(10-53)examples/solid/start-basic-netlify/src/components/NotFound.tsx (1)
NotFound(3-25)
examples/solid/start-basic-netlify/src/routes/_pathlessLayout.tsx (3)
examples/solid/start-basic-netlify/src/routes/_pathlessLayout/_nested-layout.tsx (1)
Route(3-5)examples/solid/start-basic-netlify/src/routes/_pathlessLayout/_nested-layout/route-a.tsx (1)
Route(3-7)examples/solid/start-basic-netlify/src/routes/_pathlessLayout/_nested-layout/route-b.tsx (1)
Route(3-7)
examples/solid/start-basic-netlify/src/routes/posts.$postId.tsx (4)
examples/solid/start-basic-netlify/src/routes/posts_.$postId.deep.tsx (1)
Route(5-12)examples/solid/start-basic-netlify/src/utils/posts.tsx (1)
fetchPost(10-28)examples/solid/start-basic-netlify/src/components/PostError.tsx (1)
PostErrorComponent(4-6)examples/solid/start-basic-netlify/src/components/NotFound.tsx (1)
NotFound(3-25)
examples/solid/start-basic-netlify/src/routes/_pathlessLayout/_nested-layout/route-b.tsx (3)
examples/solid/start-basic-netlify/src/routes/_pathlessLayout.tsx (1)
Route(3-5)examples/solid/start-basic-netlify/src/routes/_pathlessLayout/_nested-layout.tsx (1)
Route(3-5)examples/solid/start-basic-netlify/src/routes/_pathlessLayout/_nested-layout/route-a.tsx (1)
Route(3-7)
examples/solid/start-basic-netlify/src/routes/_pathlessLayout/_nested-layout/route-a.tsx (3)
examples/solid/start-basic-netlify/src/routes/_pathlessLayout.tsx (1)
Route(3-5)examples/solid/start-basic-netlify/src/routes/_pathlessLayout/_nested-layout.tsx (1)
Route(3-5)examples/solid/start-basic-netlify/src/routes/_pathlessLayout/_nested-layout/route-b.tsx (1)
Route(3-7)
examples/solid/start-basic-netlify/src/routes/users.index.tsx (3)
examples/solid/start-basic-netlify/src/routes/api/users.ts (1)
Route(41-64)examples/solid/start-basic-netlify/src/routes/posts.index.tsx (1)
Route(3-5)examples/solid/start-basic-netlify/src/routes/users.$userId.tsx (1)
Route(6-26)
examples/solid/start-basic-netlify/src/routeTree.gen.ts (1)
examples/solid/start-basic-netlify/src/router.tsx (1)
getRouter(6-16)
🪛 Biome (2.1.2)
examples/solid/start-basic-netlify/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). (3)
- GitHub Check: Preview
- GitHub Check: Test
- GitHub Check: autofix
🔇 Additional comments (23)
examples/solid/start-basic-netlify/.prettierignore (1)
1-4: LGTM!The ignore patterns are appropriate for this example project, correctly excluding generated files, lock files, build artifacts, and static assets from Prettier formatting.
examples/solid/start-basic-netlify/.gitignore (1)
1-9: LGTM!The ignore patterns appropriately exclude build artifacts, dependency folders, environment files, and Netlify-specific directories.
examples/solid/start-basic-netlify/netlify.toml (1)
1-3: LGTM!The Netlify build configuration correctly specifies the Vite build command and the appropriate publish directory for client assets.
examples/solid/start-basic-netlify/.vscode/settings.json (1)
1-11: LGTM!The VS Code settings appropriately exclude the auto-generated
routeTree.gen.tsfrom file watching and search, and mark it as read-only to prevent accidental modifications. This aligns with best practices for generated files.Based on learnings
examples/solid/start-basic-netlify/public/site.webmanifest (1)
6-13: The icon files referenced in the manifest are present and correctly located.Both
android-chrome-192x192.pngandandroid-chrome-512x512.pngexist in theexamples/solid/start-basic-netlify/public/directory. The manifest references are valid, and no action is required.Likely an incorrect or invalid review comment.
examples/solid/start-basic-netlify/src/routes/users.index.tsx (1)
1-16: LGTM!The route definition and component implementation are correct. The use of
<a href>for the API endpoint is appropriate here, as it allows users to navigate directly to view the JSON response.examples/solid/start-basic-netlify/tailwind.config.mjs (1)
1-4: LGTM!The Tailwind configuration is minimal but complete for this example. The content pattern correctly targets all TypeScript and JavaScript source files.
examples/solid/start-basic-netlify/postcss.config.mjs (1)
1-6: LGTM!Standard PostCSS configuration with Tailwind CSS and Autoprefixer plugins. This correctly supports the styling infrastructure for the example.
examples/solid/start-basic-netlify/tsconfig.json (1)
1-23: LGTM!The TypeScript configuration correctly enables strict mode and is properly set up for Solid.js with preserved JSX and the correct import source. The path alias configuration and module settings are appropriate for this example.
Based on learnings
examples/solid/start-basic-netlify/src/components/UserError.tsx (1)
1-6: LGTM!The error component correctly wraps the framework's ErrorComponent with proper typing. While this duplicates the pattern from
examples/solid/start-basic/src/components/UserError.tsx, maintaining self-contained examples is appropriate for ease of use.examples/solid/start-basic-netlify/src/routes/customScript[.]js.ts (1)
1-15: LGTM!The route correctly demonstrates serving custom JavaScript content with the appropriate Content-Type header. This is a valid pattern for dynamically generated assets in the framework.
examples/solid/start-basic-netlify/src/components/DefaultCatchBoundary.tsx (1)
1-53: LGTM! Consistent error boundary implementation.The component follows the established pattern from other Solid Start examples and provides appropriate error handling with navigation options.
examples/solid/start-basic-netlify/src/routes/redirect.tsx (1)
1-9: LGTM! Standard redirect implementation.The route correctly uses
beforeLoadwiththrow redirect()to perform a redirect to/posts.examples/solid/start-basic-netlify/src/utils/users.tsx (1)
1-5: LGTM! Clean type definition.The User type is properly structured and used consistently across the route files.
examples/solid/start-basic-netlify/src/router.tsx (1)
1-16: LGTM! Standard router configuration.The router is properly configured with route tree, error handling, and scroll restoration following the established pattern from other examples.
examples/solid/start-basic-netlify/src/routes/posts.index.tsx (1)
1-9: LGTM! Standard index route.The posts index route follows the expected pattern and provides a simple placeholder message.
examples/solid/start-basic-netlify/src/routes/_pathlessLayout.tsx (1)
1-16: LGTM! Correct pathless layout implementation.The layout properly uses
Outletto render nested routes and follows the expected pattern for pathless routes.examples/solid/start-basic-netlify/src/styles/app.css (1)
1-22: LGTM! Standard Tailwind configuration with dark mode.The CSS properly sets up Tailwind directives and provides sensible dark mode defaults. The
.using-mouseclass is a good UX pattern for removing focus outlines during mouse interaction.examples/solid/start-basic-netlify/src/routes/_pathlessLayout/_nested-layout/route-a.tsx (1)
1-11: LGTMStraightforward route; matches the nested path and renders as expected.
examples/solid/start-basic-netlify/src/routes/_pathlessLayout/_nested-layout/route-b.tsx (1)
3-11: LGTMRoute and component are correct and consistent with
route-a.examples/solid/start-basic-netlify/src/routes/posts.$postId.tsx (1)
6-13: Route wiring, loader, and notFound are solidLoader, error boundary, and notFound integration look correct. The deep-link target matches the generated full path. Nice.
examples/solid/start-basic-netlify/src/routes/posts_.$postId.deep.tsx (1)
5-12: LGTM: Deep route loader and error boundaryLoader/error wiring and route path mapping look correct for the deep view.
examples/solid/start-basic-netlify/src/routeTree.gen.ts (1)
1-10: Autogenerated: no manual review
routeTree.gen.tsis generated by TanStack Router; skip manual edits/review.
Based on learnings
| { | ||
| "label": "Cloudflare Vite Plugin", | ||
| "to": "framework/solid/examples/start-basic-netlify" |
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.
Fix the incorrect label for the Netlify example.
The label says "Cloudflare Vite Plugin" but points to start-basic-netlify. This creates a duplicate label (line 330 already has "Cloudflare Vite Plugin") and misrepresents the example's purpose.
Apply this diff to correct the label:
{
- "label": "Cloudflare Vite Plugin",
+ "label": "Netlify Vite Plugin",
"to": "framework/solid/examples/start-basic-netlify"
}📝 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.
| { | |
| "label": "Cloudflare Vite Plugin", | |
| "to": "framework/solid/examples/start-basic-netlify" | |
| { | |
| "label": "Netlify Vite Plugin", | |
| "to": "framework/solid/examples/start-basic-netlify" |
🤖 Prompt for AI Agents
In docs/start/config.json around lines 333 to 335, the menu item incorrectly
uses the label "Cloudflare Vite Plugin" while linking to the Netlify example;
update the label to "Netlify" (or "Netlify Example"/"Netlify Adapter" per repo
convention) so it correctly describes the target and avoids duplicating the
Cloudflare label; keep the "to" value as
"framework/solid/examples/start-basic-netlify".
| "dependencies": { | ||
| "@tanstack/solid-router": "^1.133.20", | ||
| "@tanstack/solid-router-devtools": "^1.133.20", | ||
| "@tanstack/solid-start": "^1.133.20", | ||
| "solid-js": "^1.9.5" |
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.
Use workspace protocol for internal TanStack dependencies.
The internal @tanstack/* dependencies should use the workspace:* protocol instead of version ranges. This ensures proper monorepo linking and consistency.
As per coding guidelines
Apply this diff:
"dependencies": {
- "@tanstack/solid-router": "^1.133.20",
- "@tanstack/solid-router-devtools": "^1.133.20",
- "@tanstack/solid-start": "^1.133.20",
+ "@tanstack/solid-router": "workspace:*",
+ "@tanstack/solid-router-devtools": "workspace:*",
+ "@tanstack/solid-start": "workspace:*",
"solid-js": "^1.9.5"
},📝 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.
| "dependencies": { | |
| "@tanstack/solid-router": "^1.133.20", | |
| "@tanstack/solid-router-devtools": "^1.133.20", | |
| "@tanstack/solid-start": "^1.133.20", | |
| "solid-js": "^1.9.5" | |
| "dependencies": { | |
| "@tanstack/solid-router": "workspace:*", | |
| "@tanstack/solid-router-devtools": "workspace:*", | |
| "@tanstack/solid-start": "workspace:*", | |
| "solid-js": "^1.9.5" |
🤖 Prompt for AI Agents
In examples/solid/start-basic-netlify/package.json around lines 11 to 15, the
@tanstack/* dependencies use version ranges instead of the workspace protocol;
update those entries to use "workspace:*" for "@tanstack/solid-router",
"@tanstack/solid-router-devtools", and "@tanstack/solid-start" so they resolve
to the monorepo workspace packages (leave "solid-js" unchanged).
| ## Accessing bindings | ||
|
|
||
| You can access Cloudflare bindings in server functions by using importable `env`: | ||
|
|
||
| ```ts | ||
| import { env } from 'cloudflare:workers' | ||
| ``` | ||
|
|
||
| See `src/routes/index.tsx` for an example. |
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.
Incorrect documentation: Cloudflare references in Netlify example.
This section references Cloudflare bindings and cloudflare:workers, but this is a Netlify example. The content appears to be copied from the Cloudflare example and needs to be updated with Netlify-specific documentation.
Remove or replace this section with Netlify-specific documentation. If Netlify has similar environment variable or binding access patterns, document those instead.
-## Accessing bindings
-
-You can access Cloudflare bindings in server functions by using importable `env`:
-
-```ts
-import { env } from 'cloudflare:workers'
-```
-
-See `src/routes/index.tsx` for an example.
+## Netlify Environment Variables
+
+You can access environment variables in server functions using Netlify's runtime:
+
+```ts
+// Access environment variables in server functions
+const value = process.env.YOUR_ENV_VAR
+```🤖 Prompt for AI Agents
In examples/solid/start-basic-netlify/README.md around lines 29 to 37, the
section incorrectly references Cloudflare bindings and the import statement
`import { env } from 'cloudflare:workers'`; remove that Cloudflare-specific
content and replace it with Netlify-specific guidance: delete the incorrect
import and wording, and add a brief "Netlify Environment Variables" subsection
that explains accessing environment variables in server functions via
process.env and points to the example usage in src/routes/index.tsx for
reference.
| { rel: 'manifest', href: '/site.webmanifest', color: '#fffff' }, | ||
| { rel: 'icon', href: '/favicon.ico' }, | ||
| ], |
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.
Remove invalid color on manifest link; add theme-color meta
link[rel="manifest"] doesn’t support color, and the value #fffff is invalid. Use a meta[name="theme-color"] instead.
- { rel: 'manifest', href: '/site.webmanifest', color: '#fffff' },
+ { rel: 'manifest', href: '/site.webmanifest' },- meta: [
+ meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
+ { name: 'theme-color', content: '#ffffff' },
...seo({
title:Also applies to: 18-31
🤖 Prompt for AI Agents
In examples/solid/start-basic-netlify/src/routes/__root.tsx around lines 51-53
(and also apply same change for lines 18-31), remove the invalid color attribute
from the manifest link (link[rel="manifest"] does not support a color property
and the value "#fffff" is an invalid hex), and instead add a meta tag
meta[name="theme-color"] with a valid hex value such as "#ffffff" (placed inside
the head alongside other meta tags); ensure the manifest link only includes rel
and href, and use a correctly formatted 6-digit hex for theme-color.
| <head> | ||
| <HydrationScript /> | ||
| </head> | ||
| <body> | ||
| <HeadContent /> | ||
| <div class="p-2 flex gap-2 text-lg"> | ||
| <Link |
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.
Place <HeadContent /> in <head> (not body)
Head elements should render inside <head> for correct SSR/CSR hydration.
<head>
- <HydrationScript />
+ <HydrationScript />
+ <HeadContent />
</head>
<body>
- <HeadContent />Also applies to: 73-74
🤖 Prompt for AI Agents
In examples/solid/start-basic-netlify/src/routes/__root.tsx around lines 69 to
75 (also applies to lines 73-74), the <HeadContent /> component is incorrectly
rendered inside the <body>; move the <HeadContent /> component into the <head>
element (so head contains both <HydrationScript /> and <HeadContent />) to
ensure head elements are rendered during SSR/CSR hydration, and remove the
<HeadContent /> instance from the body.
| @@ -0,0 +1,45 @@ | |||
| import { createFileRoute } from '@tanstack/solid-router' | |||
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.
🛠️ Refactor suggestion | 🟠 Major
Handle 404 with router’s notFound to use notFoundComponent
Right now any non‑OK throws a generic error, so errorComponent renders and notFoundComponent never triggers. Throw router notFound() on 404.
-import { createFileRoute } from '@tanstack/solid-router'
+import { createFileRoute, notFound } from '@tanstack/solid-router'- if (!res.ok) {
- throw new Error('Unexpected status code')
- }
+ if (!res.ok) {
+ if (res.status === 404) throw notFound()
+ throw new Error('Unexpected status code')
+ }Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In examples/solid/start-basic-netlify/src/routes/users.$userId.tsx around line
1, the route currently throws a generic error on any non-OK fetch which causes
the router to show errorComponent instead of the notFoundComponent; add an
import for the router helper (notFound) from '@tanstack/solid-router' and change
the 404 handling to throw notFound() when response.status === 404, leaving other
non-OK responses to throw the generic error so notFoundComponent is used for
404s.
| import { NotFound } from 'src/components/NotFound' | ||
| import { UserErrorComponent } from 'src/components/UserError' |
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.
🧩 Analysis chain
Unify import aliases; src/* may not resolve
Elsewhere (e.g., __root.tsx) imports use ~/*. Use the same alias (or a relative path) to avoid Vite/TS path resolution issues.
-import { NotFound } from 'src/components/NotFound'
-import { UserErrorComponent } from 'src/components/UserError'
+import { NotFound } from '~/components/NotFound'
+import { UserErrorComponent } from '~/components/UserError'Run to verify aliases:
🏁 Script executed:
#!/bin/bash
# Check tsconfig path aliases include "src/*" or "~/*"
rg -nC2 '"paths"\s*:' tsconfig*.json
rg -n "'src/\*'|'~/\*'" tsconfig*.json -C1Length of output: 0
🏁 Script executed:
#!/bin/bash
# Find all tsconfig files in the repository
fd -n tsconfig examples/solid/start-basic-netlify/ || true
fd -n tsconfig . --type f --max-depth 3 | head -20
# Check if path alias config exists in the example directory
cat examples/solid/start-basic-netlify/tsconfig.json 2>/dev/null || echo "No tsconfig in example root"
# Also check vite config for path resolution
fd -n vite.config examples/solid/start-basic-netlify/ || trueLength of output: 1236
🏁 Script executed:
#!/bin/bash
# Check the actual imports in the file under review
cat examples/solid/start-basic-netlify/src/routes/users.\$userId.tsx
# Also check __root.tsx to confirm the pattern
cat examples/solid/start-basic-netlify/src/routes/__root.tsx | head -20Length of output: 1758
Fix import aliases to use ~/ — src/ is not configured
The tsconfig.json only defines "~/*": ["./src/*"] as a path alias. Imports using src/* directly will fail to resolve. Align with the pattern used in __root.tsx and other files.
-import { NotFound } from 'src/components/NotFound'
-import { UserErrorComponent } from 'src/components/UserError'
+import { NotFound } from '~/components/NotFound'
+import { UserErrorComponent } from '~/components/UserError'📝 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.
| import { NotFound } from 'src/components/NotFound' | |
| import { UserErrorComponent } from 'src/components/UserError' | |
| import { NotFound } from '~/components/NotFound' | |
| import { UserErrorComponent } from '~/components/UserError' |
🤖 Prompt for AI Agents
In examples/solid/start-basic-netlify/src/routes/users.$userId.tsx around lines
2-3, the file imports use the non-existent alias "src/"; replace those with the
configured path alias "~/" so imports read from "~/components/NotFound" and
"~/components/UserError" respectively to match tsconfig.json and other project
files.
| const preLogMiddleware = createMiddleware({ type: 'function' }) | ||
| .client(async (ctx) => { | ||
| const clientTime = new Date() | ||
|
|
||
| return ctx.next({ | ||
| context: { | ||
| clientTime, | ||
| }, | ||
| sendContext: { | ||
| clientTime, | ||
| }, | ||
| }) | ||
| }) | ||
| .server(async (ctx) => { | ||
| const serverTime = new Date() | ||
|
|
||
| return ctx.next({ | ||
| sendContext: { | ||
| serverTime, | ||
| durationToServer: | ||
| serverTime.getTime() - ctx.context.clientTime.getTime(), | ||
| }, | ||
| }) | ||
| }) |
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.
Add null checks and TypeScript types for safer middleware.
The server handler accesses ctx.context.clientTime without verifying it exists. If context propagation fails, line 23 will throw a runtime error. Additionally, this file lacks TypeScript type annotations, violating the coding guideline for strict type safety.
Apply this diff to add safety checks and types:
+interface TimingContext {
+ clientTime?: Date
+ serverTime?: Date
+ durationToServer?: number
+}
+
-const preLogMiddleware = createMiddleware({ type: 'function' })
+const preLogMiddleware = createMiddleware<TimingContext>({ type: 'function' })
.client(async (ctx) => {
const clientTime = new Date()
return ctx.next({
context: {
clientTime,
},
sendContext: {
clientTime,
},
})
})
.server(async (ctx) => {
+ if (!ctx.context.clientTime) {
+ console.warn('clientTime not found in context')
+ return ctx.next()
+ }
+
const serverTime = new Date()
return ctx.next({
sendContext: {
serverTime,
durationToServer:
serverTime.getTime() - ctx.context.clientTime.getTime(),
},
})
})As per coding guidelines.
🤖 Prompt for AI Agents
In examples/solid/start-basic-netlify/src/utils/loggingMiddleware.tsx around
lines 3 to 26, the server middleware reads ctx.context.clientTime without safety
or TypeScript types; add explicit TypeScript generics for the middleware context
shape (e.g., clientTime?: Date and serverTime?: Date), type the createMiddleware
call and its client/server handlers, and add null/undefined checks in the server
handler so you only call ctx.context.clientTime.getTime() when clientTime is a
valid Date (otherwise compute durationToServer as undefined or 0). Ensure the
client handler sets a typed clientTime Date, validate/guard ctx.context before
use on the server, and update return types to reflect optional durationToServer.
| export const logMiddleware = createMiddleware({ type: 'function' }) | ||
| .middleware([preLogMiddleware]) | ||
| .client(async (ctx) => { | ||
| const res = await ctx.next() | ||
|
|
||
| const now = new Date() | ||
| console.log('Client Req/Res:', { | ||
| duration: now.getTime() - res.context.clientTime.getTime(), | ||
| durationToServer: res.context.durationToServer, | ||
| durationFromServer: now.getTime() - res.context.serverTime.getTime(), | ||
| }) | ||
|
|
||
| return res | ||
| }) |
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.
Add defensive checks for context properties.
The client handler accesses multiple context properties (clientTime, durationToServer, serverTime) without verifying they exist. If any timing data is missing from the response context, lines 35-37 will throw runtime errors.
Apply this diff to add safety checks and types:
-export const logMiddleware = createMiddleware({ type: 'function' })
+export const logMiddleware = createMiddleware<TimingContext>({ type: 'function' })
.middleware([preLogMiddleware])
.client(async (ctx) => {
const res = await ctx.next()
+ if (res.context.clientTime && res.context.serverTime && res.context.durationToServer != null) {
- const now = new Date()
- console.log('Client Req/Res:', {
- duration: now.getTime() - res.context.clientTime.getTime(),
- durationToServer: res.context.durationToServer,
- durationFromServer: now.getTime() - res.context.serverTime.getTime(),
- })
+ const now = new Date()
+ console.log('Client Req/Res:', {
+ duration: now.getTime() - res.context.clientTime.getTime(),
+ durationToServer: res.context.durationToServer,
+ durationFromServer: now.getTime() - res.context.serverTime.getTime(),
+ })
+ } else {
+ console.warn('Incomplete timing data in response context')
+ }
return res
})As per coding guidelines.
Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In examples/solid/start-basic-netlify/src/utils/loggingMiddleware.tsx around
lines 28 to 41, the client handler assumes res.context and its timing fields
exist; add defensive checks and simple types so missing timing data won't throw.
Update the handler to (1) validate res and res.context before using them, (2)
guard access to clientTime and serverTime and compute durations only when those
Dates exist (use optional chaining and fallback numeric values or skip that
part), (3) treat durationToServer as possibly undefined and provide a fallback
or omit it from the log, and (4) narrow the middleware client context type so
these fields are optional (e.g., Date | undefined, number | undefined) to force
compile-time checks; log a clear message when timing data is absent instead of
accessing properties unconditionally.
| plugins: [ | ||
| tsConfigPaths({ | ||
| projects: ['./tsconfig.json'], | ||
| }), | ||
| netlify(), | ||
| tanstackStart(), | ||
| viteSolid({ ssr: true }), | ||
| ], |
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.
🧩 Analysis chain
Verify the plugin order with Netlify documentation.
Vite plugin order can affect behavior. Please confirm that the current order (tsConfigPaths → netlify → tanstackStart → viteSolid) aligns with Netlify's recommended configuration for TanStack Start projects.
🌐 Web query:
What is the recommended Vite plugin order for @netlify/vite-plugin-tanstack-start with TanStack Solid Start?
💡 Result:
Use tanstackStart() first, then @netlify/vite-plugin-tanstack-start, then vite-plugin-solid. Example:
plugins: [
tanstackStart(),
netlify(),
viteSolid({ ssr: true }),
]
Sources: Netlify TanStack Start docs and TanStack Solid hosting guide. [1][2]
References
[1] Netlify — TanStack Start setup.
[2] TanStack Start (Solid) — Hosting (shows same plugin order).
Fix plugin order: tanstackStart() must come before netlify().
The recommended Vite plugin order is tanstackStart(), netlify(), then viteSolid, but the current code places netlify() before tanstackStart(). This reversed order may cause build or runtime issues. Update to:
plugins: [
tsConfigPaths({
projects: ['./tsconfig.json'],
}),
tanstackStart(),
netlify(),
viteSolid({ ssr: true }),
],
🤖 Prompt for AI Agents
In examples/solid/start-basic-netlify/vite.config.ts around lines 11 to 18, the
Vite plugin order is incorrect: netlify() is placed before tanstackStart(),
which can cause build/runtime issues; reorder the plugins so tanstackStart()
appears before netlify() (keeping tsConfigPaths first and viteSolid({ ssr: true
}) last).
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 (1)
docs/start/framework/react/guide/hosting.md (1)
119-129: Minor documentation clarity issue: Duplicate "Netlify" section header.Lines 119 and 129 both define the same "Netlify" section header. Consider consolidating them or using distinct subheadings (e.g., "Netlify ⭐ Official Partner" for setup and "Netlify Configuration" for the technical details) to improve clarity.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
docs/start/framework/react/guide/hosting.md(1 hunks)docs/start/framework/solid/guide/hosting.md(1 hunks)
✅ Files skipped from review due to trivial changes (1)
- docs/start/framework/solid/guide/hosting.md
🧰 Additional context used
📓 Path-based instructions (2)
docs/**/*.{md,mdx}
📄 CodeRabbit inference engine (AGENTS.md)
Use internal docs links relative to the docs/ folder (e.g., ./guide/data-loading)
Files:
docs/start/framework/react/guide/hosting.md
docs/{router,start}/**
📄 CodeRabbit inference engine (AGENTS.md)
Place router docs under docs/router/ and start framework docs under docs/start/
Files:
docs/start/framework/react/guide/hosting.md
⏰ 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)
docs/start/framework/react/guide/hosting.md (1)
151-153: LGTM! The Netlify dev configuration looks good.The addition of the
[dev]section correctly specifies the dev command and port for local development via the Netlify CLI. This aligns with the PR's goal of providing end-to-end Netlify workflow guidance across frameworks.
Summary by CodeRabbit
New Features
Documentation
Style
Chores