-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
docs(solid-start): nitro vite plugin example #5577
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
WalkthroughThis PR adds a comprehensive Solid Start + Nitro example project with file-based routing, error handling components, API routes, utilities, and full build configuration. It also updates documentation configuration and removes the wrangler dependency from an existing example. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~35 minutes The PR introduces 50+ files, but the majority follow homogeneous patterns (route files, configuration boilerplate). Review effort centers on verifying correct project structure, standard patterns in route setup, API middleware configuration, and build tooling. Some API routes and middleware logic add moderate complexity, but the overall scaffolding nature of the changes limits the depth of reasoning required per file. Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 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 da3b7ca
☁️ 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: 12
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
examples/solid/start-basic-netlify/package.json (1)
12-14: Use workspace: protocol for internal dependencies.*The internal TanStack dependencies should use the
workspace:*protocol instead of caret ranges. This ensures the example always uses the latest local version during development.As per coding guidelines
Apply this diff:
- "@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:*",
🧹 Nitpick comments (21)
examples/solid/start-basic-nitro/src/utils/seo.ts (2)
1-11: Add explicit return type annotation for better type safety.The function lacks an explicit return type. Adding one improves clarity and catches potential mistakes.
Apply this diff:
export const seo = ({ title, description, keywords, image, }: { title: string description?: string image?: string keywords?: string -}) => { +}): Array<{ title?: string; name?: string; content?: string }> => {
26-26: Consider setting a default Twitter card type.Twitter card metadata (title, description) is set unconditionally, but
twitter:cardtype is only set when an image exists. Consider specifying a default card type (e.g.,summary) when no image is provided for consistency.Example adjustment:
{ name: 'twitter:title', content: title }, ...(description ? [{ name: 'twitter:description', content: description }] : []), { name: 'twitter:creator', content: '@tannerlinsley' }, { name: 'twitter:site', content: '@tannerlinsley' }, + { name: 'twitter:card', content: image ? 'summary_large_image' : 'summary' }, { 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' }, { property: 'og:image', content: image }, ] : []),examples/solid/start-basic-nitro/src/components/UserError.tsx (1)
4-6: Consider using ErrorComponent directly if no customization is needed.This wrapper adds no additional functionality beyond passing through the error prop. Unless you plan to customize the error display for user routes, you could use
ErrorComponentdirectly in the route configuration.If customization is needed, consider adding it now or adding a comment explaining the wrapper's purpose.
examples/solid/start-basic-nitro/src/components/NotFound.tsx (2)
3-3: Use more specific type for children prop.The
anytype reduces type safety. Consider usingJSX.Elementor a more specific type for the children prop.Apply this diff:
-export function NotFound({ children }: { children?: any }) { +export function NotFound({ children }: { children?: JSX.Element }) {
3-25: Consider extracting shared NotFound component.This component is duplicated across multiple examples (
start-basic-solid-query,start-basic-cloudflare, and nowstart-basic-nitro). While keeping examples self-contained has benefits, a shared component in a common location would reduce maintenance burden.If you prefer to keep examples self-contained, this duplication is acceptable. Otherwise, consider creating a shared component that can be imported across examples.
examples/solid/start-basic-nitro/public/site.webmanifest (1)
2-3: Fill manifest metadata and add start_url/scope.Empty name/short_name hurts install UX; adding start_url/scope improves PWA behavior.
- "name": "", - "short_name": "", + "name": "TanStack Solid Start (Nitro) Example", + "short_name": "SolidStart", + "start_url": "/", + "scope": "/",Optionally add "description" and a maskable icon purpose.
Also applies to: 16-18
examples/solid/start-basic-nitro/tailwind.config.mjs (1)
1-4: Widen content scan and opt into class-based dark mode.Catches classes in index.html and standardizes dark mode behavior.
/** @type {import('tailwindcss').Config} */ export default { - content: ['./src/**/*.{js,jsx,ts,tsx}'], + darkMode: 'class', + content: ['./index.html', './src/**/*.{js,jsx,ts,tsx}'], }examples/solid/start-basic-nitro/package.json (1)
1-10: Declare Node engine (Nitro requires modern Node).Locks CI/dev to a compatible runtime.
{ "name": "tanstack-solid-start-example-basic-nitro", "private": true, "sideEffects": false, "type": "module", + "engines": { + "node": ">=18.17" + }, "scripts": { "dev": "vite dev", "build": "vite build && tsc --noEmit", "preview": "vite preview" },Also applies to: 17-27
examples/solid/start-basic-nitro/vite.config.ts (1)
8-10: Make dev port configurable.Avoid clashes when multiple examples run.
export default defineConfig({ server: { - port: 3000, + port: Number(process.env.PORT) || 3000, },examples/solid/start-basic-nitro/src/routes/api/users.ts (1)
1-64: Optional: move API base URL to a constant/env.Eases swapping the upstream and documenting example intent.
const USERS_API = 'https://jsonplaceholder.typicode.com/users'Use USERS_API in both list and $userId routes for consistency.
examples/solid/start-basic-nitro/src/utils/posts.tsx (1)
27-27: Consider validating API responses at runtime.The type assertions
as PostTypeandas Array<PostType>assume the external API returns the expected shape. If the API changes, this could lead to runtime errors downstream.Consider adding runtime validation using a library like Zod or Valibot to ensure type safety:
import { z } from 'zod' const PostSchema = z.object({ id: z.number(), title: z.string(), body: z.string(), }) // In fetchPost handler: const post = PostSchema.parse(await res.json()) return postAlso applies to: 39-39
examples/solid/start-basic-nitro/README.md (1)
23-27: Consider clarifying deployment options.While Nitro supports multiple deployment targets including Netlify, the current documentation only mentions Netlify deployment. Consider adding context about Nitro's multi-platform support or documenting other deployment options.
examples/solid/start-basic-nitro/src/router.tsx (1)
6-16: Add an explicit return type for strict TS.Improves API clarity and satisfies strict mode.
As per coding guidelines
-export function getRouter() { +export function getRouter(): ReturnType<typeof createRouter> { const router = createRouter({ routeTree, defaultPreload: 'intent', defaultErrorComponent: DefaultCatchBoundary, defaultNotFoundComponent: () => <NotFound />, scrollRestoration: true, }) return router }examples/solid/start-basic-nitro/src/styles/app.css (1)
10-12: A11y: scope outline removal to focus; optional pseudo-element inclusion.
- Only suppress outlines on focus when using mouse to preserve keyboard focus visibility.
- Optionally include pseudo-elements in the border-color rule.
- * { - @apply border-gray-200 dark:border-gray-800; - } + *, ::before, ::after { + @apply border-gray-200 dark:border-gray-800; + } - .using-mouse * { - outline: none !important; - } + .using-mouse *:focus { + outline: none !important; + }Note: Ensure your app toggles the
using-mouseclass on pointer/keyboard events.Also applies to: 19-21
examples/solid/start-basic-nitro/src/routes/posts_.$postId.deep.tsx (1)
1-12: Add a notFoundComponent for 404s (parity with /posts/$postId).Ensures clean 404 rendering when fetchPost throws notFound().
-import { Link, createFileRoute } from '@tanstack/solid-router' +import { Link, createFileRoute } from '@tanstack/solid-router' import { fetchPost } from '../utils/posts' import { PostErrorComponent } from '~/components/PostError' +import { NotFound } from '~/components/NotFound' export const Route = createFileRoute('/posts_/$postId/deep')({ loader: async ({ params: { postId } }) => fetchPost({ data: postId, }), errorComponent: PostErrorComponent, + notFoundComponent: () => <NotFound>Post not found</NotFound>, component: PostDeepComponent, })examples/solid/start-basic-nitro/src/routes/posts.tsx (1)
25-27: Dark-mode active color + ellipsis truncation.Use theme-aware active color and CSS truncation instead of substring.
- activeProps={{ class: 'text-black font-bold' }} + activeProps={{ class: 'font-bold text-gray-900 dark:text-gray-100' }} > - <div>{post.title.substring(0, 20)}</div> + <div class="truncate max-w-[20ch]">{post.title}</div>Optional: For list rendering performance, consider Solid’s
<For>when mapping larger arrays.examples/solid/start-basic-nitro/src/routes/api/users.$userId.ts (2)
11-13: Prefer template literals for URL construction.Using template literals is more readable and maintainable than string concatenation with the
+operator.Apply this diff:
- const res = await fetch( - 'https://jsonplaceholder.typicode.com/users/' + params.userId, - ) + const res = await fetch( + `https://jsonplaceholder.typicode.com/users/${params.userId}`, + )
21-25: Simplify the response object construction.Since the User type already has the exact properties being returned, you can simplify the response.
Apply this diff:
return json({ id: user.id, name: user.name, email: user.email, }) + // Or more simply: + // return json(user)Alternatively, if you want to ensure only specific fields are returned:
- return json({ - id: user.id, - name: user.name, - email: user.email, - }) + const { id, name, email } = user + return json({ id, name, email })examples/solid/start-basic-nitro/src/routes/users.$userId.tsx (2)
2-4: Inconsistent import path styles.The imports mix absolute path aliases (
src/components/) with relative paths (../utils/). Consider using a consistent style throughout the file for better maintainability.Apply this diff to use consistent path aliases:
-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'
9-9: Prefer template literals for URL construction.Using template literals is more readable than string concatenation.
Apply this diff:
- const res = await fetch('/api/users/' + userId) + const res = await fetch(`/api/users/${userId}`)examples/solid/start-basic-nitro/src/routes/posts.$postId.tsx (1)
2-4: Inconsistent import path styles.The imports mix relative paths (
../) with path aliases (~/). Consider using a consistent style throughout the file.Apply this diff to use consistent path aliases:
-import { fetchPost } from '../utils/posts' +import { fetchPost } from '~/utils/posts'
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (8)
examples/solid/start-basic-nitro/public/android-chrome-192x192.pngis excluded by!**/*.pngexamples/solid/start-basic-nitro/public/android-chrome-512x512.pngis excluded by!**/*.pngexamples/solid/start-basic-nitro/public/apple-touch-icon.pngis excluded by!**/*.pngexamples/solid/start-basic-nitro/public/favicon-16x16.pngis excluded by!**/*.pngexamples/solid/start-basic-nitro/public/favicon-32x32.pngis excluded by!**/*.pngexamples/solid/start-basic-nitro/public/favicon.icois excluded by!**/*.icoexamples/solid/start-basic-nitro/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/package.json(1 hunks)examples/solid/start-basic-nitro/.gitignore(1 hunks)examples/solid/start-basic-nitro/.prettierignore(1 hunks)examples/solid/start-basic-nitro/.vscode/settings.json(1 hunks)examples/solid/start-basic-nitro/README.md(1 hunks)examples/solid/start-basic-nitro/package.json(1 hunks)examples/solid/start-basic-nitro/postcss.config.mjs(1 hunks)examples/solid/start-basic-nitro/public/site.webmanifest(1 hunks)examples/solid/start-basic-nitro/src/components/DefaultCatchBoundary.tsx(1 hunks)examples/solid/start-basic-nitro/src/components/NotFound.tsx(1 hunks)examples/solid/start-basic-nitro/src/components/PostError.tsx(1 hunks)examples/solid/start-basic-nitro/src/components/UserError.tsx(1 hunks)examples/solid/start-basic-nitro/src/routeTree.gen.ts(1 hunks)examples/solid/start-basic-nitro/src/router.tsx(1 hunks)examples/solid/start-basic-nitro/src/routes/__root.tsx(1 hunks)examples/solid/start-basic-nitro/src/routes/_pathlessLayout.tsx(1 hunks)examples/solid/start-basic-nitro/src/routes/_pathlessLayout/_nested-layout.tsx(1 hunks)examples/solid/start-basic-nitro/src/routes/_pathlessLayout/_nested-layout/route-a.tsx(1 hunks)examples/solid/start-basic-nitro/src/routes/_pathlessLayout/_nested-layout/route-b.tsx(1 hunks)examples/solid/start-basic-nitro/src/routes/api/users.$userId.ts(1 hunks)examples/solid/start-basic-nitro/src/routes/api/users.ts(1 hunks)examples/solid/start-basic-nitro/src/routes/customScript[.]js.ts(1 hunks)examples/solid/start-basic-nitro/src/routes/deferred.tsx(1 hunks)examples/solid/start-basic-nitro/src/routes/index.tsx(1 hunks)examples/solid/start-basic-nitro/src/routes/posts.$postId.tsx(1 hunks)examples/solid/start-basic-nitro/src/routes/posts.index.tsx(1 hunks)examples/solid/start-basic-nitro/src/routes/posts.tsx(1 hunks)examples/solid/start-basic-nitro/src/routes/posts_.$postId.deep.tsx(1 hunks)examples/solid/start-basic-nitro/src/routes/redirect.tsx(1 hunks)examples/solid/start-basic-nitro/src/routes/users.$userId.tsx(1 hunks)examples/solid/start-basic-nitro/src/routes/users.index.tsx(1 hunks)examples/solid/start-basic-nitro/src/routes/users.tsx(1 hunks)examples/solid/start-basic-nitro/src/styles/app.css(1 hunks)examples/solid/start-basic-nitro/src/utils/loggingMiddleware.tsx(1 hunks)examples/solid/start-basic-nitro/src/utils/posts.tsx(1 hunks)examples/solid/start-basic-nitro/src/utils/seo.ts(1 hunks)examples/solid/start-basic-nitro/src/utils/users.tsx(1 hunks)examples/solid/start-basic-nitro/tailwind.config.mjs(1 hunks)examples/solid/start-basic-nitro/tsconfig.json(1 hunks)examples/solid/start-basic-nitro/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-nitro/src/components/NotFound.tsxexamples/solid/start-basic-nitro/src/routes/_pathlessLayout/_nested-layout/route-a.tsxexamples/solid/start-basic-nitro/src/routes/__root.tsxexamples/solid/start-basic-nitro/src/router.tsxexamples/solid/start-basic-nitro/src/routes/users.$userId.tsxexamples/solid/start-basic-nitro/src/routes/_pathlessLayout/_nested-layout.tsxexamples/solid/start-basic-nitro/src/routes/index.tsxexamples/solid/start-basic-nitro/src/routes/posts.$postId.tsxexamples/solid/start-basic-nitro/src/utils/loggingMiddleware.tsxexamples/solid/start-basic-nitro/vite.config.tsexamples/solid/start-basic-nitro/src/utils/posts.tsxexamples/solid/start-basic-nitro/src/routes/_pathlessLayout/_nested-layout/route-b.tsxexamples/solid/start-basic-nitro/src/routes/users.index.tsxexamples/solid/start-basic-nitro/src/components/DefaultCatchBoundary.tsxexamples/solid/start-basic-nitro/src/utils/seo.tsexamples/solid/start-basic-nitro/src/components/PostError.tsxexamples/solid/start-basic-nitro/src/routes/deferred.tsxexamples/solid/start-basic-nitro/src/components/UserError.tsxexamples/solid/start-basic-nitro/src/routes/redirect.tsxexamples/solid/start-basic-nitro/src/routes/users.tsxexamples/solid/start-basic-nitro/src/routes/posts.tsxexamples/solid/start-basic-nitro/src/routeTree.gen.tsexamples/solid/start-basic-nitro/src/routes/posts_.$postId.deep.tsxexamples/solid/start-basic-nitro/src/utils/users.tsxexamples/solid/start-basic-nitro/src/routes/posts.index.tsxexamples/solid/start-basic-nitro/src/routes/_pathlessLayout.tsxexamples/solid/start-basic-nitro/src/routes/customScript[.]js.tsexamples/solid/start-basic-nitro/src/routes/api/users.$userId.tsexamples/solid/start-basic-nitro/src/routes/api/users.ts
examples/{react,solid}/**
📄 CodeRabbit inference engine (AGENTS.md)
Keep example applications under examples/react/ and examples/solid/
Files:
examples/solid/start-basic-nitro/src/components/NotFound.tsxexamples/solid/start-basic-nitro/src/routes/_pathlessLayout/_nested-layout/route-a.tsxexamples/solid/start-basic-nitro/src/routes/__root.tsxexamples/solid/start-basic-nitro/src/router.tsxexamples/solid/start-basic-nitro/README.mdexamples/solid/start-basic-netlify/package.jsonexamples/solid/start-basic-nitro/postcss.config.mjsexamples/solid/start-basic-nitro/src/routes/users.$userId.tsxexamples/solid/start-basic-nitro/src/routes/_pathlessLayout/_nested-layout.tsxexamples/solid/start-basic-nitro/src/routes/index.tsxexamples/solid/start-basic-nitro/src/routes/posts.$postId.tsxexamples/solid/start-basic-nitro/src/utils/loggingMiddleware.tsxexamples/solid/start-basic-nitro/vite.config.tsexamples/solid/start-basic-nitro/src/utils/posts.tsxexamples/solid/start-basic-nitro/src/routes/_pathlessLayout/_nested-layout/route-b.tsxexamples/solid/start-basic-nitro/src/routes/users.index.tsxexamples/solid/start-basic-nitro/src/components/DefaultCatchBoundary.tsxexamples/solid/start-basic-nitro/src/utils/seo.tsexamples/solid/start-basic-nitro/src/components/PostError.tsxexamples/solid/start-basic-nitro/src/routes/deferred.tsxexamples/solid/start-basic-nitro/src/components/UserError.tsxexamples/solid/start-basic-nitro/src/routes/redirect.tsxexamples/solid/start-basic-nitro/src/routes/users.tsxexamples/solid/start-basic-nitro/src/routes/posts.tsxexamples/solid/start-basic-nitro/src/routeTree.gen.tsexamples/solid/start-basic-nitro/src/styles/app.cssexamples/solid/start-basic-nitro/src/routes/posts_.$postId.deep.tsxexamples/solid/start-basic-nitro/src/utils/users.tsxexamples/solid/start-basic-nitro/src/routes/posts.index.tsxexamples/solid/start-basic-nitro/public/site.webmanifestexamples/solid/start-basic-nitro/tailwind.config.mjsexamples/solid/start-basic-nitro/src/routes/_pathlessLayout.tsxexamples/solid/start-basic-nitro/tsconfig.jsonexamples/solid/start-basic-nitro/src/routes/customScript[.]js.tsexamples/solid/start-basic-nitro/src/routes/api/users.$userId.tsexamples/solid/start-basic-nitro/package.jsonexamples/solid/start-basic-nitro/src/routes/api/users.ts
**/src/routes/**
📄 CodeRabbit inference engine (AGENTS.md)
Place file-based routes under src/routes/ directories
Files:
examples/solid/start-basic-nitro/src/routes/_pathlessLayout/_nested-layout/route-a.tsxexamples/solid/start-basic-nitro/src/routes/__root.tsxexamples/solid/start-basic-nitro/src/routes/users.$userId.tsxexamples/solid/start-basic-nitro/src/routes/_pathlessLayout/_nested-layout.tsxexamples/solid/start-basic-nitro/src/routes/index.tsxexamples/solid/start-basic-nitro/src/routes/posts.$postId.tsxexamples/solid/start-basic-nitro/src/routes/_pathlessLayout/_nested-layout/route-b.tsxexamples/solid/start-basic-nitro/src/routes/users.index.tsxexamples/solid/start-basic-nitro/src/routes/deferred.tsxexamples/solid/start-basic-nitro/src/routes/redirect.tsxexamples/solid/start-basic-nitro/src/routes/users.tsxexamples/solid/start-basic-nitro/src/routes/posts.tsxexamples/solid/start-basic-nitro/src/routes/posts_.$postId.deep.tsxexamples/solid/start-basic-nitro/src/routes/posts.index.tsxexamples/solid/start-basic-nitro/src/routes/_pathlessLayout.tsxexamples/solid/start-basic-nitro/src/routes/customScript[.]js.tsexamples/solid/start-basic-nitro/src/routes/api/users.$userId.tsexamples/solid/start-basic-nitro/src/routes/api/users.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.jsonexamples/solid/start-basic-nitro/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-nitro/.vscode/settings.jsonexamples/solid/start-basic-nitro/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-nitro/tsconfig.json
🧬 Code graph analysis (23)
examples/solid/start-basic-nitro/src/components/NotFound.tsx (2)
examples/solid/start-basic-solid-query/src/components/NotFound.tsx (1)
NotFound(3-25)examples/solid/start-basic-cloudflare/src/components/NotFound.tsx (1)
NotFound(3-25)
examples/solid/start-basic-nitro/src/routes/_pathlessLayout/_nested-layout/route-a.tsx (3)
examples/solid/start-basic-nitro/src/routes/_pathlessLayout.tsx (1)
Route(3-5)examples/solid/start-basic-nitro/src/routes/_pathlessLayout/_nested-layout.tsx (1)
Route(3-5)examples/solid/start-basic-nitro/src/routes/_pathlessLayout/_nested-layout/route-b.tsx (1)
Route(3-7)
examples/solid/start-basic-nitro/src/routes/__root.tsx (4)
examples/solid/start-basic-nitro/src/routes/customScript[.]js.ts (1)
Route(3-15)examples/solid/start-basic-nitro/src/utils/seo.ts (1)
seo(1-33)examples/solid/start-basic-nitro/src/components/DefaultCatchBoundary.tsx (1)
DefaultCatchBoundary(10-53)examples/solid/start-basic-nitro/src/components/NotFound.tsx (1)
NotFound(3-25)
examples/solid/start-basic-nitro/src/router.tsx (2)
examples/solid/start-basic-nitro/src/components/DefaultCatchBoundary.tsx (1)
DefaultCatchBoundary(10-53)examples/solid/start-basic-nitro/src/components/NotFound.tsx (1)
NotFound(3-25)
examples/solid/start-basic-nitro/src/routes/users.$userId.tsx (4)
examples/solid/start-basic-nitro/src/routes/api/users.$userId.ts (1)
Route(5-33)examples/solid/start-basic-nitro/src/utils/users.tsx (1)
User(1-5)examples/solid/start-basic-nitro/src/components/UserError.tsx (1)
UserErrorComponent(4-6)examples/solid/start-basic-nitro/src/components/NotFound.tsx (1)
NotFound(3-25)
examples/solid/start-basic-nitro/src/routes/_pathlessLayout/_nested-layout.tsx (3)
examples/solid/start-basic-nitro/src/routes/_pathlessLayout.tsx (1)
Route(3-5)examples/solid/start-basic-nitro/src/routes/_pathlessLayout/_nested-layout/route-a.tsx (1)
Route(3-7)examples/solid/start-basic-nitro/src/routes/_pathlessLayout/_nested-layout/route-b.tsx (1)
Route(3-7)
examples/solid/start-basic-nitro/src/routes/index.tsx (3)
examples/solid/start-basic-nitro/src/routes/api/users.$userId.ts (1)
Route(5-33)examples/solid/start-basic-nitro/src/routes/api/users.ts (1)
Route(41-64)examples/solid/start-basic-nitro/src/routes/deferred.tsx (1)
Route(18-29)
examples/solid/start-basic-nitro/src/routes/posts.$postId.tsx (3)
examples/solid/start-basic-nitro/src/routes/posts_.$postId.deep.tsx (1)
Route(5-12)examples/solid/start-basic-nitro/src/components/PostError.tsx (1)
PostErrorComponent(4-6)examples/solid/start-basic-nitro/src/components/NotFound.tsx (1)
NotFound(3-25)
examples/solid/start-basic-nitro/src/routes/_pathlessLayout/_nested-layout/route-b.tsx (3)
examples/solid/start-basic-nitro/src/routes/_pathlessLayout.tsx (1)
Route(3-5)examples/solid/start-basic-nitro/src/routes/_pathlessLayout/_nested-layout.tsx (1)
Route(3-5)examples/solid/start-basic-nitro/src/routes/_pathlessLayout/_nested-layout/route-a.tsx (1)
Route(3-7)
examples/solid/start-basic-nitro/src/routes/users.index.tsx (3)
examples/solid/start-basic-nitro/src/routes/api/users.ts (1)
Route(41-64)examples/solid/start-basic-nitro/src/routes/posts.index.tsx (1)
Route(3-5)examples/solid/start-basic-nitro/src/routes/users.$userId.tsx (1)
Route(6-26)
examples/solid/start-basic-nitro/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-nitro/src/utils/seo.ts (1)
scripts/llms-generate.mjs (1)
title(101-101)
examples/solid/start-basic-nitro/src/routes/deferred.tsx (3)
examples/solid/start-basic-nitro/src/routes/index.tsx (1)
Route(4-7)examples/solid/start-basic-nitro/src/routes/posts.$postId.tsx (1)
Route(6-13)examples/solid/start-basic-nitro/src/routes/posts.tsx (1)
Route(4-7)
examples/solid/start-basic-nitro/src/routes/redirect.tsx (2)
examples/solid/start-basic-nitro/src/routes/posts.index.tsx (1)
Route(3-5)examples/solid/start-basic-nitro/src/routes/posts.tsx (1)
Route(4-7)
examples/solid/start-basic-nitro/src/routes/users.tsx (4)
examples/solid/start-basic-nitro/src/routes/api/users.$userId.ts (1)
Route(5-33)examples/solid/start-basic-nitro/src/routes/api/users.ts (1)
Route(41-64)examples/solid/start-basic-nitro/src/routes/users.$userId.tsx (1)
Route(6-26)examples/solid/start-basic-nitro/src/utils/users.tsx (1)
User(1-5)
examples/solid/start-basic-nitro/src/routes/posts.tsx (2)
examples/solid/start-basic-nitro/src/routes/posts.$postId.tsx (1)
Route(6-13)examples/solid/start-basic-nitro/src/utils/posts.tsx (1)
fetchPosts(30-40)
examples/solid/start-basic-nitro/src/routeTree.gen.ts (2)
e2e/react-router/js-only-file-based/src/routeTree.gen.js (12)
PathlessLayoutRoute(21-24)IndexRoute(30-34)PostsIndexRoute(35-39)PostsPostIdRoute(40-44)PathlessLayoutNestedLayoutRoute(45-49)PathlessLayoutNestedLayoutRouteBRoute(50-55)PathlessLayoutNestedLayoutRouteARoute(56-61)PathlessLayoutRouteWithChildren(86-88)PathlessLayoutNestedLayoutRouteWithChildren(77-80)PathlessLayoutNestedLayoutRouteChildren(72-75)PathlessLayoutRouteChildren(82-84)rootRouteChildren(90-94)examples/solid/start-basic-nitro/src/router.tsx (1)
getRouter(6-16)
examples/solid/start-basic-nitro/src/routes/posts_.$postId.deep.tsx (4)
examples/solid/start-basic-nitro/src/routes/posts.$postId.tsx (1)
Route(6-13)examples/solid/start-basic-nitro/src/routes/posts.tsx (1)
Route(4-7)examples/solid/start-basic-nitro/src/utils/posts.tsx (1)
fetchPost(10-28)examples/solid/start-basic-nitro/src/components/PostError.tsx (1)
PostErrorComponent(4-6)
examples/solid/start-basic-nitro/src/routes/posts.index.tsx (3)
examples/solid/start-basic-nitro/src/routes/posts.$postId.tsx (1)
Route(6-13)examples/solid/start-basic-nitro/src/routes/posts.tsx (1)
Route(4-7)examples/solid/start-basic-nitro/src/routes/users.index.tsx (1)
Route(3-5)
examples/solid/start-basic-nitro/src/routes/_pathlessLayout.tsx (3)
examples/solid/start-basic-nitro/src/routes/_pathlessLayout/_nested-layout.tsx (1)
Route(3-5)examples/solid/start-basic-nitro/src/routes/_pathlessLayout/_nested-layout/route-a.tsx (1)
Route(3-7)examples/solid/start-basic-nitro/src/routes/_pathlessLayout/_nested-layout/route-b.tsx (1)
Route(3-7)
examples/solid/start-basic-nitro/src/routes/customScript[.]js.ts (1)
examples/solid/start-basic-nitro/src/routes/__root.tsx (1)
Route(16-64)
examples/solid/start-basic-nitro/src/routes/api/users.$userId.ts (3)
examples/solid/start-basic-nitro/src/routes/api/users.ts (1)
Route(41-64)examples/solid/start-basic-nitro/src/routes/users.$userId.tsx (1)
Route(6-26)examples/solid/start-basic-nitro/src/utils/users.tsx (1)
User(1-5)
examples/solid/start-basic-nitro/src/routes/api/users.ts (3)
packages/start-server-core/src/request-response.ts (1)
getRequestHeaders(77-80)examples/solid/start-basic-nitro/src/routes/api/users.$userId.ts (1)
Route(5-33)examples/solid/start-basic-nitro/src/utils/users.tsx (1)
User(1-5)
🪛 Biome (2.1.2)
examples/solid/start-basic-nitro/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). (2)
- GitHub Check: Preview
- GitHub Check: Test
🔇 Additional comments (23)
examples/solid/start-basic-nitro/tsconfig.json (1)
1-23: Well-configured TypeScript setup for Solid Start example.The configuration enables strict mode, appropriate JSX settings for Solid.js, modern compilation targets, and helpful path aliasing — all aligned with the codebase's type safety guidelines. The
noEmitoption is correct since Vite/Nitro handles compilation, andmoduleResolution: "Bundler"is appropriate for the build setup.examples/solid/start-basic-nitro/.gitignore (1)
1-10: LGTM!The
.gitignoreentries appropriately cover Node.js project artifacts, build outputs, environment configuration, and deployment tooling (.wrangler, .netlify, .nitro) for the Solid Start example.examples/solid/start-basic-nitro/.vscode/settings.json (1)
1-11: LGTM!The VSCode settings appropriately exclude the autogenerated
routeTree.gen.tsfile from watchers, searches, and mark it as readonly. This prevents accidental edits and reduces noise.Based on learnings
examples/solid/start-basic-nitro/src/routes/users.index.tsx (1)
7-16: LGTM!The component correctly uses an HTML anchor tag for the API endpoint link, which will trigger a full navigation to view the JSON response. This is the appropriate approach for non-route endpoints.
docs/start/config.json (1)
337-340: LGTM!The new Nitro Vite Plugin example entry is correctly structured and follows the existing pattern. The placement and labeling are appropriate.
examples/solid/start-basic-nitro/postcss.config.mjs (1)
1-6: LGTM!Standard PostCSS configuration for Tailwind CSS and Autoprefixer. The empty configuration objects will use the default settings from both plugins, which is appropriate for this example.
examples/solid/start-basic-nitro/src/routes/customScript[.]js.ts (1)
3-15: LGTM!The server route correctly demonstrates serving custom JavaScript content with the appropriate
Content-Typeheader. This is a useful example of handling non-HTML responses in file-based routing.examples/solid/start-basic-nitro/src/routes/posts.index.tsx (1)
1-9: LGTM: correct index route for /posts.Matches file-based routing conventions and mirrors users.index.tsx.
examples/solid/start-basic-nitro/vite.config.ts (1)
7-19: Plugin order is correct—no changes needed.The current plugin order matches all other Solid examples in the repository.
tanstackStart()correctly runs beforeviteSolid({ ssr: true })across all variants (basic, cloudflare, netlify, and nitro-based examples).examples/solid/start-basic-nitro/src/utils/loggingMiddleware.tsx (1)
1-41: LGTM! Clean timing middleware implementation.The middleware composition and timing logic are well-structured. The client-server round-trip timing measurements (duration, durationToServer, durationFromServer) are correctly calculated.
examples/solid/start-basic-nitro/src/routes/_pathlessLayout/_nested-layout/route-b.tsx (1)
1-11: LGTM! Consistent with sibling routes.The route definition follows the established pattern and correctly implements a nested layout route.
examples/solid/start-basic-nitro/.prettierignore (1)
1-4: LGTM! Appropriate ignore patterns.The ignore patterns correctly exclude generated files, lock files, and build artifacts from Prettier formatting.
examples/solid/start-basic-nitro/src/utils/users.tsx (1)
1-5: LGTM! Clean type definition.The User type is well-defined and appropriately simple.
examples/solid/start-basic-nitro/src/routes/redirect.tsx (1)
1-9: LGTM! Correct redirect implementation.The redirect route correctly uses the
beforeLoadhook withthrow redirect()pattern.examples/solid/start-basic-nitro/src/routes/_pathlessLayout.tsx (1)
1-16: LGTM! Well-structured layout component.The pathless layout route correctly uses
Outletfor nested routes and follows Solid.js conventions with theclassattribute.examples/solid/start-basic-nitro/src/routes/_pathlessLayout/_nested-layout/route-a.tsx (1)
3-11: LGTM — child route wiring is correct.Path, component export, and file-based route naming match the parent layout.
examples/solid/start-basic-nitro/src/components/PostError.tsx (1)
4-6: LGTM — minimal, typed error wrapper.Straightforward and consistent with other error components.
examples/solid/start-basic-nitro/src/components/DefaultCatchBoundary.tsx (1)
1-53: LGTM! Consistent with other examples.The DefaultCatchBoundary implementation correctly follows the established pattern used in other Solid Start examples (start-basic, start-basic-cloudflare, e2e/solid-start/server-routes), providing appropriate error logging and user-friendly recovery options.
examples/solid/start-basic-nitro/src/routes/users.tsx (1)
25-28: Good test case for error handling.The addition of a non-existent user is a useful demonstration of error handling in the child route. This helps showcase the notFoundComponent and errorComponent behavior.
examples/solid/start-basic-nitro/src/routes/deferred.tsx (1)
41-48: Static analysis warning can be safely ignored.The static analyzer flagged the
childrenprop on theAwaitcomponent, but in Solid.js (unlike React), this is a valid and idiomatic pattern. TheAwaitcomponent from@tanstack/solid-routeris designed to accept children as a render prop.However, if you prefer to align with the analyzer's suggestion, you could use the component's render prop pattern instead:
<Await promise={loaderData().deferredPerson}> {(data) => ( <div data-testid="deferred-person"> {data.name} - {data.randomNumber} </div> )} </Await>But the current usage is perfectly valid for Solid.js.
examples/solid/start-basic-nitro/src/routes/index.tsx (1)
1-24: LGTM! Clean implementation.The home route correctly demonstrates server function usage with
createServerFnand proper data loading through the route's loader. The use ofnavigator.userAgentin the server context is appropriate.examples/solid/start-basic-nitro/src/routes/__root.tsx (1)
117-118: Good demonstration of type-safe routing.The intentional use of
@ts-expect-errorfor a non-existent route effectively demonstrates the type-safety features of TanStack Router.examples/solid/start-basic-nitro/src/routeTree.gen.ts (1)
1-447: Skipping review: Auto-generated fileThis file is auto-generated by TanStack Router and should not be manually modified or reviewed. As stated in the file header (lines 7-9), changes will be overwritten.
Based on learnings
| "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.
🛠️ Refactor suggestion | 🟠 Major
Use workspace: for internal TanStack packages.*
Aligns with repo policy and prevents version skew during local development.
As per coding guidelines.
"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-nitro/package.json around lines 11 to 16, the
internal TanStack dependencies should use workspace:* instead of explicit
versions to follow repo policy and avoid version skew; update the three
@tanstack packages ("@tanstack/solid-router", "@tanstack/solid-router-devtools",
"@tanstack/solid-start") to use "workspace:*" while leaving external packages
like "solid-js" as-is, and save the modified package.json so installs resolve to
the workspace packages during local development.
| "devDependencies": { | ||
| "nitro": "^3.0.1-alpha.0", | ||
| "@types/node": "^22.5.4", |
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
Sanity-check nitro version.
Alpha versions can churn. Confirm 3.0.1-alpha.0 is intended for the example; otherwise prefer a stable 3.x.
🏁 Script executed:
#!/bin/bash
# Compare nitro versions used across examples and check for non-alpha usage.
rg -n --glob 'examples/**/package.json' '"nitro":\s*".*"' -N -C1Length of output: 221
I'll search for information about the current stable nitro version to help assess whether using the alpha version here is appropriate.
Let me check if there's broader context about whether this project is intentionally using Nitro v3 alpha:
Update the example to use Nitro v2 (stable) instead of v3 alpha.
The current stable release is Nitro v2, while Nitro v3 is still under active development and features/APIs can change before final release. Version 3.0.1-alpha.0 was published 11 days ago, confirming active churn. For a foundational example like "start-basic-nitro," using an alpha version introduces unnecessary instability and breaking-change risk for developers learning the framework. Switch to Nitro v2 (the current stable release).
🤖 Prompt for AI Agents
In examples/solid/start-basic-nitro/package.json around lines 17-19, the
devDependency pins "nitro" to an alpha release ("^3.0.1-alpha.0"); replace that
with the stable Nitro v2 range to avoid introducing an unstable alpha into the
example (e.g., change the version string to a v2 stable range like "^2.x" or the
current v2 exact release), update lockfile if present, and run npm/yarn install
to verify no dependency conflicts.
| @@ -0,0 +1,37 @@ | |||
| # 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 title to match directory name.
The README title is "Start Basic Netlify" but the directory is named start-basic-nitro. This creates confusion about what the example demonstrates.
Apply this diff to align the title with the directory name:
-# Start Basic Netlify
+# Start Basic Nitro📝 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.
| # Start Basic Netlify | |
| # Start Basic Nitro |
🤖 Prompt for AI Agents
In examples/solid/start-basic-nitro/README.md around line 1, the heading "Start
Basic Netlify" doesn't match the directory name; change the top-level title to
"Start Basic Nitro" so the README matches the start-basic-nitro directory name
(replace the first line with "# Start Basic Nitro").
| title: | ||
| 'TanStack Start | Type-Safe, Client-First, Full-Stack React Framework', | ||
| description: `TanStack Start is a type-safe, client-first, full-stack React framework. `, |
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.
Title refers to React instead of Solid.
The SEO title and description reference "React Framework" but this is a Solid.js example. Consider updating it to reflect the correct framework.
Apply this diff:
...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. `,
+ 'TanStack Start | Type-Safe, Client-First, Full-Stack Solid Framework',
+ description: `TanStack Start is a type-safe, client-first, full-stack Solid framework. `,
}),📝 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.
| 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. `, |
🤖 Prompt for AI Agents
In examples/solid/start-basic-nitro/src/routes/__root.tsx around lines 27 to 29,
the SEO title and description incorrectly mention "React"; update both strings
to reference "Solid" (e.g., change "TanStack Start | Type-Safe, Client-First,
Full-Stack React Framework" to "TanStack Start | Type-Safe, Client-First,
Full-Stack Solid Framework" and update the description to "TanStack Start is a
type-safe, client-first, full-stack Solid framework."), preserving punctuation
and formatting.
| sizes: '16x16', | ||
| href: '/favicon-16x16.png', | ||
| }, | ||
| { rel: 'manifest', href: '/site.webmanifest', color: '#fffff' }, |
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.
Invalid HTML attribute on manifest link.
The color attribute is not a valid attribute for <link> elements. If you want to set a theme color, use a separate <meta> tag with name="theme-color".
Apply this diff:
- { rel: 'manifest', href: '/site.webmanifest', color: '#fffff' },
+ { rel: 'manifest', href: '/site.webmanifest' },
{ rel: 'icon', href: '/favicon.ico' },If you need a theme color, add it to the meta array:
...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. `,
}),
+ {
+ name: 'theme-color',
+ content: '#fffff',
+ },
],📝 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.
| { rel: 'manifest', href: '/site.webmanifest', color: '#fffff' }, | |
| { rel: 'manifest', href: '/site.webmanifest' }, | |
| { rel: 'icon', href: '/favicon.ico' }, |
🤖 Prompt for AI Agents
In examples/solid/start-basic-nitro/src/routes/__root.tsx around line 51, the
<link rel="manifest"> entry incorrectly includes a nonstandard color attribute;
remove the color property from that link entry and, if a theme color is needed,
add a separate meta entry to the meta array with name="theme-color" and the
desired color value (e.g. "#ffffff"), ensuring the manifest link only contains
valid attributes.
| GET: async ({ request }) => { | ||
| console.info('GET /api/users @', request.url) | ||
| console.info('Fetching users... @', request.url) | ||
| const res = await fetch('https://jsonplaceholder.typicode.com/users') | ||
| if (!res.ok) { | ||
| throw new Error('Failed to fetch users') | ||
| } | ||
|
|
||
| // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion | ||
| const data = (await res.json()) as Array<User> | ||
|
|
||
| const list = data.slice(0, 10) | ||
|
|
||
| return json( | ||
| list.map((u) => ({ id: u.id, name: u.name, email: u.email })), | ||
| ) | ||
| }, |
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.
Harden external fetch: timeout + structured errors.
Prevents hung requests and returns clear 5xx on failures.
- GET: async ({ request }) => {
+ GET: async ({ request }) => {
console.info('GET /api/users @', request.url)
- console.info('Fetching users... @', request.url)
- const res = await fetch('https://jsonplaceholder.typicode.com/users')
- if (!res.ok) {
- throw new Error('Failed to fetch users')
- }
-
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
- const data = (await res.json()) as Array<User>
-
- const list = data.slice(0, 10)
-
- return json(
- list.map((u) => ({ id: u.id, name: u.name, email: u.email })),
- )
+ console.info('Fetching users... @', request.url)
+ const ac = new AbortController()
+ const to = setTimeout(() => ac.abort(), 5000)
+ try {
+ const res = await fetch('https://jsonplaceholder.typicode.com/users', {
+ signal: ac.signal,
+ })
+ if (!res.ok) {
+ return json({ error: 'Upstream error' }, { status: res.status })
+ }
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
+ const data = (await res.json()) as Array<User>
+ const list = (Array.isArray(data) ? data : []).slice(0, 10)
+ return json(list.map((u) => ({ id: u.id, name: u.name, email: u.email })))
+ } catch (e: any) {
+ const status = e?.name === 'AbortError' ? 504 : 502
+ console.error('Fetch users failed:', e)
+ return json({ error: 'Failed to fetch users' }, { status })
+ } finally {
+ clearTimeout(to)
+ }
},📝 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.
| GET: async ({ request }) => { | |
| console.info('GET /api/users @', request.url) | |
| console.info('Fetching users... @', request.url) | |
| const res = await fetch('https://jsonplaceholder.typicode.com/users') | |
| if (!res.ok) { | |
| throw new Error('Failed to fetch users') | |
| } | |
| // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion | |
| const data = (await res.json()) as Array<User> | |
| const list = data.slice(0, 10) | |
| return json( | |
| list.map((u) => ({ id: u.id, name: u.name, email: u.email })), | |
| ) | |
| }, | |
| GET: async ({ request }) => { | |
| console.info('GET /api/users @', request.url) | |
| console.info('Fetching users... @', request.url) | |
| const ac = new AbortController() | |
| const to = setTimeout(() => ac.abort(), 5000) | |
| try { | |
| const res = await fetch('https://jsonplaceholder.typicode.com/users', { | |
| signal: ac.signal, | |
| }) | |
| if (!res.ok) { | |
| return json({ error: 'Upstream error' }, { status: res.status }) | |
| } | |
| // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion | |
| const data = (await res.json()) as Array<User> | |
| const list = (Array.isArray(data) ? data : []).slice(0, 10) | |
| return json(list.map((u) => ({ id: u.id, name: u.name, email: u.email }))) | |
| } catch (e: any) { | |
| const status = e?.name === 'AbortError' ? 504 : 502 | |
| console.error('Fetch users failed:', e) | |
| return json({ error: 'Failed to fetch users' }, { status }) | |
| } finally { | |
| clearTimeout(to) | |
| } | |
| }, |
🤖 Prompt for AI Agents
In examples/solid/start-basic-nitro/src/routes/api/users.ts around lines 45 to
61, the external fetch can hang and returns unclear errors; add an
AbortController-driven timeout (e.g., 5s) around the fetch, wrap the fetch in
try/catch, clear the timeout on success, and convert failures into structured
5xx responses: return a JSON error body and appropriate status (504 for timeout,
502 for upstream non-OK, 500 for other exceptions). Ensure you still parse and
map successful responses the same way, and do not leak the raw thrown Error —
use the framework json response helper with { error: '...' } and status codes.
| export const fetchPost = createServerFn({ method: 'POST' }) | ||
| .inputValidator((d: string) => d) | ||
| .handler(async ({ data }) => { | ||
| console.info(`Fetching post with id ${data}...`) | ||
| const res = await fetch( | ||
| `https://jsonplaceholder.typicode.com/posts/${data}`, | ||
| ) | ||
| if (!res.ok) { | ||
| if (res.status === 404) { | ||
| throw notFound() | ||
| } | ||
|
|
||
| throw new Error('Failed to fetch post') | ||
| } | ||
|
|
||
| const post = await res.json() | ||
|
|
||
| return post as PostType | ||
| }) |
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 GET method for read operations.
fetchPost uses POST method to fetch a post, which violates REST conventions. GET should be used for read operations, while POST is intended for creating resources. This could prevent caching and cause confusion.
Apply this diff:
-export const fetchPost = createServerFn({ method: 'POST' })
+export const fetchPost = createServerFn({ method: 'GET' })
.inputValidator((d: string) => d)
.handler(async ({ data }) => {🤖 Prompt for AI Agents
In examples/solid/start-basic-nitro/src/utils/posts.tsx around lines 10 to 28,
the server function is using method: 'POST' for a read operation; change the
method to 'GET' and adjust the input handling accordingly so the post id is
accepted via the GET input (query/params) rather than implying a body — keep the
same inputValidator for a string id, update any client calls to invoke the GET
endpoint, and ensure the handler still reads the id from the request input
(data) and performs the same fetch and error handling; this preserves REST
conventions and enables caching.
| { name: 'description', content: description }, | ||
| { name: 'keywords', content: keywords }, |
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.
Handle undefined values in meta tag content.
When description or keywords are not provided, these tags will have content: undefined, which may render as empty or literal "undefined" strings in the HTML.
Filter out tags with undefined content:
const tags = [
{ title },
- { name: 'description', content: description },
- { name: 'keywords', content: keywords },
+ ...(description ? [{ name: 'description', content: description }] : []),
+ ...(keywords ? [{ name: 'keywords', content: keywords }] : []),
{ name: 'twitter:title', content: title },
- { name: 'twitter:description', content: description },
+ ...(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 },
- { name: 'og:description', content: description },
+ ...(description ? [{ name: 'og:description', content: description }] : []),Also applies to: 17-17, 22-22
🤖 Prompt for AI Agents
In examples/solid/start-basic-nitro/src/utils/seo.ts around lines 14-15 (and
also address lines 17 and 22), meta tag entries are being created with content
potentially undefined which can render as empty or "undefined" in HTML; ensure
you only include meta objects when their content is defined by either
conditionally adding the { name: 'description', content: description } and {
name: 'keywords', content: keywords } entries only if description/keywords are
non-null/undefined, or build the array then filter out items with undefined
content (e.g., .filter(tag => tag.content != null)) so no meta tag is emitted
with undefined content.
| { name: 'og:type', content: 'website' }, | ||
| { name: 'og:title', content: title }, | ||
| { name: 'og:description', content: description }, |
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 property attribute for Open Graph tags.
Open Graph protocol specifies property instead of name for OG meta tags. Using name may cause these tags to be ignored by social media crawlers.
Apply this diff:
- { 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 },
+ ...(description ? [{ property: 'og:description', content: description }] : []),📝 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.
| { 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 }, | |
| ...(description ? [{ property: 'og:description', content: description }] : []), |
🤖 Prompt for AI Agents
In examples/solid/start-basic-nitro/src/utils/seo.ts around lines 20 to 22, the
Open Graph meta entries use the `name` attribute instead of the required
`property` attribute; update those entries to use `property` keys (e.g., replace
`{ name: 'og:type', ... }` with `{ property: 'og:type', ... }`, and likewise for
`og:title` and `og:description`) so social crawlers recognize them, keeping the
content values unchanged and leaving non-OG meta entries as-is.
| ...(image | ||
| ? [ | ||
| { name: 'twitter:image', content: image }, | ||
| { name: 'twitter:card', content: 'summary_large_image' }, | ||
| { name: 'og:image', content: image }, | ||
| ] | ||
| : []), |
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 property for Open Graph image tag.
Line 27 should use property instead of name for consistency with Open Graph protocol.
Apply this diff:
...(image
? [
{ name: 'twitter:image', content: image },
{ name: 'twitter:card', content: 'summary_large_image' },
- { name: 'og:image', content: image },
+ { property: 'og:image', content: image },
]
: []),🤖 Prompt for AI Agents
In examples/solid/start-basic-nitro/src/utils/seo.ts around lines 23 to 29, the
Open Graph image meta entry is using the `name` key but should use `property` to
conform to the Open Graph protocol; update the object { name: 'og:image',
content: image } to use property: 'og:image' (i.e., replace the `name` key with
`property`) so the generated meta tag uses property="og:image" while leaving the
twitter and card entries unchanged.
Summary by CodeRabbit
New Features
Chores