Create new TanStack Router routes with loaders, type-safe params, and proper file structure for Tanstack Start projects
Generate TanStack Router routes with server-side loaders, type-safe parameters, and error boundaries for Tanstack Start projects. Use this when creating new routes that need Cloudflare Workers integration and proper TypeScript typing.
/plugin marketplace add hirefrank/hirefrank-marketplace/plugin install edge-stack@hirefrank-marketplace<command_purpose> Generate TanStack Router routes with server-side loaders, type-safe parameters, error boundaries, and proper file structure for Tanstack Start projects on Cloudflare Workers. </command_purpose>
<role>Senior Routing Engineer with expertise in TanStack Router, server-side data loading, and Cloudflare Workers integration</role>
/es-tanstack-route <route-path> [options]
<route-path>: Route path (e.g., /users/$id, /blog, /api/users)[options]: Optional flags:
--loader: Include server-side loader (default: true for non-API routes)--api: Create API route (server function)--layout: Create layout route--params <params>: Dynamic params (e.g., id,slug)--search-params <params>: Search params (e.g., page:number,filter:string)# Create static route
/es-tanstack-route /about
# Create dynamic route with loader
/es-tanstack-route /users/$id --loader
# Create API route
/es-tanstack-route /api/users --api
# Create route with search params
/es-tanstack-route /users --search-params page:number,sort:string
Convert route path to file path:
| Route Path | File Path |
|---|---|
/ | src/routes/index.tsx |
/about | src/routes/about.tsx |
/users/$id | src/routes/users.$id.tsx |
/blog/$slug | src/routes/blog.$slug.tsx |
/api/users | src/routes/api/users.ts |
Standard Route with Loader:
// src/routes/users.$id.tsx
import { createFileRoute } from '@tanstack/react-router'
import { z } from 'zod'
export const Route = createFileRoute('/users/$id')({
loader: async ({ params, context }) => {
const { env } = context.cloudflare
const user = await env.DB.prepare(
'SELECT * FROM users WHERE id = ?'
).bind(params.id).first()
if (!user) {
throw new Error('User not found')
}
return { user }
},
errorComponent: ({ error }) => (
<div className="p-4">
<h1 className="text-2xl font-bold text-red-600">Error</h1>
<p>{error.message}</p>
</div>
),
pendingComponent: () => (
<div className="p-4">
<Loader2 className="animate-spin" />
<span>Loading...</span>
</div>
),
component: UserPage,
})
function UserPage() {
const { user } = Route.useLoaderData()
return (
<div className="max-w-4xl mx-auto p-6">
<h1 className="text-3xl font-bold">{user.name}</h1>
<p className="text-gray-600">{user.email}</p>
</div>
)
}
API Route:
// src/routes/api/users.ts
import { createAPIFileRoute } from '@tanstack/start/api'
export const Route = createAPIFileRoute('/api/users')({
GET: async ({ request, context }) => {
const { env } = context.cloudflare
const users = await env.DB.prepare('SELECT * FROM users').all()
return Response.json(users)
},
POST: async ({ request, context }) => {
const { env } = context.cloudflare
const data = await request.json()
await env.DB.prepare(
'INSERT INTO users (name, email) VALUES (?, ?)'
).bind(data.name, data.email).run()
return Response.json({ success: true })
},
})
Route with Search Params:
// src/routes/users.tsx
import { createFileRoute } from '@tanstack/react-router'
import { z } from 'zod'
const searchSchema = z.object({
page: z.number().int().positive().default(1),
sort: z.enum(['name', 'date']).default('name'),
filter: z.string().optional(),
})
export const Route = createFileRoute('/users')({
validateSearch: searchSchema,
loaderDeps: ({ search }) => search,
loader: async ({ deps: search, context }) => {
const { env } = context.cloudflare
const offset = (search.page - 1) * 20
const users = await env.DB.prepare(
`SELECT * FROM users ORDER BY ${search.sort} LIMIT 20 OFFSET ?`
).bind(offset).all()
return { users, search }
},
component: UsersPage,
})
function UsersPage() {
const { users, search } = Route.useLoaderData()
const navigate = Route.useNavigate()
return (
<div>
<h1>Users (Page {search.page})</h1>
{/* ... */}
</div>
)
}
// src/types/routes.ts
export interface UserParams {
id: string
}
export interface UsersSearch {
page: number
sort: 'name' | 'date'
filter?: string
}
Ensure route is registered in router.
Task tanstack-routing-specialist(generated route):
✅ Route file generated in correct location ✅ Loader implemented with Cloudflare bindings ✅ Error boundary included ✅ Pending state handled ✅ TypeScript types defined ✅ Search params validated (if applicable)