start-server-core
Server-side runtime for TanStack Start: createStartHandler, request/response utilities (getRequest, setResponseHeader, setCookie, getCookie, useSession), three-phase request handling, AsyncLocalStorage context.
How do I install this agent skill?
npx skills add https://github.com/tanstack/router --skill start-server-coreIs this agent skill safe to install?
- Gen Agent Trust Hubpass
The skill provides documentation and code examples for TanStack Start's server-side runtime utilities. It demonstrates standard web development practices, including secure session management, cookie handling, and input validation, with no security risks identified.
- Socketpass
No alerts
- Snykpass
Risk: LOW · No issues
What does this agent skill do?
Start Server Core (@tanstack/start-server-core)
Server-side runtime for TanStack Start. Provides the request handler, request/response utilities, cookie management, and session management. All utilities are available anywhere in the call stack during a request via AsyncLocalStorage.
CRITICAL: These utilities are SERVER-ONLY. Import them from
@tanstack/<framework>-start/server, not from the main entry point. They throw if called outside a server request context.CRITICAL: Types are FULLY INFERRED. Never cast, never annotate inferred values.
CRITICAL: Read cookies, headers, request URLs, and runtime environment values inside the active request. Do not capture them at module scope; edge runtimes may inject them per request, and concurrent requests must never share request-derived state.
createStartHandler
Creates the main request handler that processes all incoming requests through three phases: server functions, server routes, then app SSR.
// src/server.ts
// Use @tanstack/<framework>-start for your framework (react, solid, vue)
import { createStartHandler } from '@tanstack/react-start/server'
import { defaultStreamHandler } from '@tanstack/react-start/server'
export default createStartHandler({
handler: defaultStreamHandler,
})
With asset URL transforms (CDN):
export default createStartHandler({
handler: defaultStreamHandler,
transformAssets: 'https://cdn.example.com',
})
Request Utilities
All imported from @tanstack/<framework>-start/server. Available anywhere during request handling — no parameter passing needed.
Reading Request Data
// Use @tanstack/<framework>-start for your framework (react, solid, vue)
import { createServerFn } from '@tanstack/react-start'
import {
getRequest,
getRequestHeaders,
getRequestHeader,
getRequestIP,
getRequestHost,
getRequestUrl,
getRequestProtocol,
} from '@tanstack/react-start/server'
const serverFn = createServerFn({ method: 'GET' }).handler(async () => {
const request = getRequest()
const headers = getRequestHeaders()
const auth = getRequestHeader('authorization')
const ip = getRequestIP({ xForwardedFor: true })
const host = getRequestHost()
const url = getRequestUrl()
const protocol = getRequestProtocol()
return { ip, host }
})
Setting Response Data
// Use @tanstack/<framework>-start for your framework (react, solid, vue)
import { createServerFn } from '@tanstack/react-start'
import {
setResponseHeader,
setResponseHeaders,
setResponseStatus,
getResponseHeaders,
getResponseHeader,
getResponseStatus,
removeResponseHeader,
clearResponseHeaders,
} from '@tanstack/react-start/server'
const serverFn = createServerFn({ method: 'POST' }).handler(async () => {
setResponseStatus(201)
setResponseHeader('x-custom', 'value')
setResponseHeaders({ 'cache-control': 'no-store' })
return { created: true }
})
Cookie Management
// Use @tanstack/<framework>-start for your framework (react, solid, vue)
import { createServerFn } from '@tanstack/react-start'
import {
getCookies,
getCookie,
setCookie,
deleteCookie,
} from '@tanstack/react-start/server'
const serverFn = createServerFn({ method: 'POST' }).handler(async () => {
const allCookies = getCookies()
const token = getCookie('session-token')
setCookie('preference', 'dark', {
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
sameSite: 'lax',
maxAge: 60 * 60 * 24 * 30, // 30 days
path: '/',
})
deleteCookie('old-cookie')
})
Session Management
Encrypted sessions stored in cookies. Requires a password for encryption.
// Use @tanstack/<framework>-start for your framework (react, solid, vue)
import { createServerFn } from '@tanstack/react-start'
import {
useSession,
getSession,
updateSession,
clearSession,
} from '@tanstack/react-start/server'
type SessionData = {
userId?: string
}
function getSessionConfig() {
const password = process.env.SESSION_SECRET
if (!password || password.length < 32) {
throw new Error('SESSION_SECRET must be at least 32 characters')
}
return {
password,
name: 'my-app-session',
maxAge: 60 * 60 * 24 * 7,
cookie: {
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
sameSite: 'lax' as const,
path: '/',
},
}
}
function getDummyPasswordHash() {
// Precompute this with the same algorithm and cost as real password hashes.
const hash = process.env.DUMMY_PASSWORD_HASH
if (!hash) {
throw new Error('DUMMY_PASSWORD_HASH is required')
}
return hash
}
// Full session manager
const getUser = createServerFn({ method: 'GET' }).handler(async () => {
const session = await useSession<SessionData>(getSessionConfig())
if (!session.data.userId) {
return null
}
return db.users.findById(session.data.userId)
})
// Update session
const login = createServerFn({ method: 'POST' })
.validator((data: unknown) => {
if (
typeof data !== 'object' ||
data === null ||
!('email' in data) ||
typeof data.email !== 'string' ||
data.email.trim().length === 0 ||
!('password' in data) ||
typeof data.password !== 'string' ||
data.password.length === 0
) {
throw new Error('Invalid credentials')
}
return {
email: data.email.trim().toLowerCase(),
password: data.password,
}
})
.handler(async ({ data }) => {
const user = await db.users.findByEmail(data.email)
const passwordHash = user?.passwordHash ?? getDummyPasswordHash()
const passwordMatches = await verifyPassword(data.password, passwordHash)
if (!user || !passwordMatches) {
throw new Error('Invalid credentials')
}
await updateSession<SessionData>(getSessionConfig(), {
userId: user.id,
})
return { success: true }
})
// Clear session
const logout = createServerFn({ method: 'POST' }).handler(async () => {
await clearSession(getSessionConfig())
return { success: true }
})
Session Config
| Option | Type | Default | Description |
|---|---|---|---|
password | string | required | Encryption key |
name | string | 'start' | Cookie name |
maxAge | number | undefined | Expiry in seconds |
cookie | false | CookieOptions | undefined | Cookie settings |
Session Manager Methods
const session = await useSession<{ userId: string }>(config)
session.id // Session ID (string | undefined)
session.data // Session data (typed)
await session.update({ userId: '123' }) // Persist session data
await session.clear() // Clear session data
Production Session Rules
- Keep cookie session data small and non-sensitive. Store a stable session or user ID, then load current permissions and account state from the authoritative store on each protected request.
- Use a server-side session record when you need revocation, device tracking, large data, or immediate role changes. Put only its opaque ID in the cookie.
- Rotate the session after login, privilege changes, password changes, and logout.
- Use
HttpOnly,SameSite,Path=/, andSecurein production. Use a__Host-cookie name in production only whenSecure, noDomain, andPath=/are all enforced. - Use the same cookie name and path when clearing a session. Test login, authenticated refresh, expiry, logout, and a replay of the old cookie.
Query Validation
Validate query string parameters using a Standard Schema:
// Use @tanstack/<framework>-start for your framework (react, solid, vue)
import { getValidatedQuery } from '@tanstack/react-start/server'
import { z } from 'zod'
const serverFn = createServerFn({ method: 'GET' }).handler(async () => {
const query = await getValidatedQuery(
z.object({
page: z.coerce.number().default(1),
limit: z.coerce.number().default(20),
}),
)
return { page: query.page }
})
Note:
getValidatedQueryaccepts a Standard Schema validator, not a callback function.
How Request Handling Works
createStartHandler processes requests in three phases:
-
Server Function Dispatch — If URL matches the server function prefix (
/_serverFn), deserializes the payload, runs global request middleware, executes the server function, and returns the serialized result. -
Server Route Handler — For non-server-function requests, matches the URL against routes with
server.handlers. Runs route middleware, then the matched HTTP method handler. Handlers can return aResponseor callnext()to fall through to SSR. -
App Router SSR — Loads all route loaders, dehydrates state for client hydration, and calls the handler callback (e.g.,
defaultStreamHandler) to render HTML.
Common Mistakes
1. CRITICAL: Importing server utilities in client code
Server utilities use AsyncLocalStorage and only work during server request handling. Importing them in client code causes build errors or runtime crashes.
// WRONG — importing in a component file that runs on client
import { getCookie } from '@tanstack/react-start/server'
function MyComponent() {
const token = getCookie('auth') // crashes on client
}
// CORRECT — use inside server functions only
// Use @tanstack/<framework>-start for your framework (react, solid, vue)
import { createServerFn } from '@tanstack/react-start'
import { getCookie } from '@tanstack/react-start/server'
const getAuth = createServerFn({ method: 'GET' }).handler(async () => {
return getCookie('auth')
})
2. HIGH: Forgetting session password for most session operations
useSession, getSession, updateSession, and sealSession all require a password field for encryption. Missing it throws at runtime. clearSession accepts Partial<SessionConfig>, so password is optional for clearing.
3. MEDIUM: Using session without HTTPS in production
Session cookies should use secure: true in production. The default cookie options may not enforce this.
4. CRITICAL: Capturing request or environment state at module scope
Do not create session config from process.env at module load or cache getRequest(), headers, cookies, or session data in a module variable. Create config and read request state inside the handler or middleware callback. This is required for per-request edge environments and prevents cross-request data leaks.
Cross-References
- start-core/server-functions — creating server functions that use these utilities
- start-core/middleware — request middleware
- start-core/server-routes — server route handlers
How can the creator link this skill?
Add the canonical catalog link to the repository README so users can inspect current installs and available audits. The publishing guide covers the complete discovery path.
<a href="https://skillzs.dev/skills/tanstack/router/start-server-core">View start-server-core on skillZs</a>