Skip to content
Back to skills

Start Middleware

ASecurity

Use when composing cross-cutting server logic in TanStack Start with createMiddleware — chaining, context, auth factories.

  • 29 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added September 6, 2026
ai-agentstypescriptrustreactapi

Works with

  • cli
  • api

Security analysis

A100/100

Pro scans all 6 files and shows the line behind each finding

Scanned September 29, 2026

npx -y skills add fusengine/agents --skill start-middleware --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Start Middleware?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Start Middleware
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/fusengine-start-middleware/badge)](https://www.skillsdirectory.com/skills/fusengine-start-middleware)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: start-middleware
description: Use when composing cross-cutting server logic in TanStack Start with createMiddleware — chaining, context, auth factories.
version: 1.0.0
user-invocable: true
references: references/types.md, references/context.md, references/global.md, references/templates/auth-authorization.md, references/templates/client-middleware.md
---

<objective>
Covers composing cross-cutting server logic in TanStack Start with createMiddleware: request middleware vs server-function middleware, chaining via .middleware([...]), sharing context with next({ context }), passing client-to-server context with sendContext, client-side middleware (.client()), global middleware declared via createStart in src/start.ts, parameterized authorization factories, and staticFunctionMiddleware ordering. Targets @tanstack/react-start v1.168.58.

Critical rules enforced: the method chain order is fixed (.middleware() → .validator() → .client() → .server()); shape-validated sendContext data is NOT authorization — always re-check access against the server-trusted session before using a client-sent value as a query key, filter, or path param; client context is never sent to the server unless explicitly opted in, and the client can lie about anything it sends; .client() runs on the server during SSR, so browser-only APIs need a typeof window guard; and staticFunctionMiddleware must always be last in the chain.

Includes templates for an auth + permission-based authorization factory and for client-side middleware (headers, custom fetch, telemetry).

Do NOT use this skill for defining the RPC itself (use start-server-functions), raw HTTP endpoints (use start-server-routes), or route-level UX guards (use router beforeLoad).
</objective>

# TanStack Start Middleware

Middleware customizes the behavior of server functions and server routes. It is
composable — one middleware can depend on others to form an ordered chain.
Import `createMiddleware` from `@tanstack/react-start`. This skill targets
`@tanstack/react-start` **v1.168.58**.

## Agent Workflow (MANDATORY)

Before implementing, verify current APIs against Context7
(`/websites/tanstack_start_framework_react`) + Exa, then explore the target
codebase. After changes, run `fuse-ai-pilot:sniper`.

## Critical Rules (read first)

1. **TypeScript enforces method order:** `.middleware()` → `.validator()` →
   `.client()` → `.server()`. Any other order is a type error.
2. **Shape validation is NOT authorization.** A parsed UUID from `sendContext`
   is a well-formed identifier, not an authorized one. Always re-check access
   against the session principal before using a client-sent value as a query
   key, filter, or path param.
3. **Client context is not sent to the server by default.** You must opt in with
   `next({ sendContext })`. Anything the client sends, the client can lie about
   — derive the session from a server-trusted source (cookie + DB), never from
   `sendContext`.
4. **`.client()` runs on the server during SSR.** Guard browser-only APIs
   (`localStorage`, `window`) with `typeof window !== 'undefined'`.
5. **`staticFunctionMiddleware` must be LAST** in the chain (from
   `@tanstack/start-static-server-functions`, experimental).

## Overview

| Feature | Request Middleware | Server Function Middleware |
|---------|--------------------|-----------------------------|
| Created with | `createMiddleware()` | `createMiddleware({ type: 'function' })` |
| Scope | All server requests (SSR, routes, functions) | Server functions only |
| Methods | `.server()` | `.client()`, `.server()` |
| Input validation | No | Yes (`.validator()`) |
| Client-side logic | No | Yes |

Request middleware cannot depend on server function middleware; server function
middleware can depend on both.

## Architecture

```
src/
├── start.ts              # createStart → global request/function middleware
├── middleware/
│   ├── auth.ts           # authMiddleware (request) + authorization factory
│   └── logging.ts        # request logging
```

→ See [auth-authorization.md](references/templates/auth-authorization.md)

## Reference Guide

### Concepts

| Topic | Reference | Load when |
|-------|-----------|-----------|
| Types & chaining | [types.md](references/types.md) | Choosing request vs function middleware, attaching to fns/routes |
| Context passing | [context.md](references/context.md) | Sharing data via next(), sendContext client↔server, headers/fetch |
| Global & static | [global.md](references/global.md) | Global middleware, execution order, staticFunctionMiddleware |

### Templates

| Template | When to Use |
|----------|-------------|
| [auth-authorization.md](references/templates/auth-authorization.md) | Auth + permission-based authorization factory |
| [client-middleware.md](references/templates/client-middleware.md) | Client-side headers, custom fetch, telemetry |

## Quick Reference

### Request middleware

```tsx
import { createMiddleware } from '@tanstack/react-start'

const logging = createMiddleware().server(async ({ next, request }) => {
  console.log(request.url)
  return next()
})
```

### Server function middleware with context

```tsx
const auth = createMiddleware().server(async ({ next, request }) => {
  const session = await getSession(request.headers)
  if (!session) throw new Error('Unauthorized')
  return next({ context: { session } }) // typed downstream
})

const fn = createServerFn().middleware([auth]).handler(async ({ context }) =>
  db.orders.findMany({ where: { userId: context.session.userId } }),
)
```

→ See [context.md](references/context.md) for sendContext and header merging

## Best Practices

### DO
- Load the session in a request middleware from a server-trusted cookie
- Re-check access (membership/role) before trusting any client-sent id
- Use a factory for parameterized authorization (permissions per function)
- Keep method chains in the enforced order

### DON'T
- Trust `sendContext` shape as authorization
- Call `localStorage`/`window` in `.client()` without an SSR guard
- Place `staticFunctionMiddleware` anywhere but last

Files in this skill

  • SKILL.md6 KB
  • references/context.md4 KB
  • references/global.md3.4 KB
  • references/templates/auth-authorization.md3.2 KB
  • references/templates/client-middleware.md2.3 KB
  • references/types.md3.3 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…