| name | full-stack-apps |
| description | Build full-stack Cloudflare apps with Workers, static assets, SSR, API routes, SPA/hybrid rendering, cache headers, and binding-backed data. Use when implementing frontend-plus-backend applications on Cloudflare Workers.
|
| compatibility | Cloudflare Workers TypeScript projects using Wrangler; verify current Cloudflare APIs, limits, and pricing before production use. |
| metadata | {"source":"Architecting on Cloudflare plus official Cloudflare Developer Platform docs","generated":"2026-04-28"} |
Full-Stack Apps
Use this skill when a Cloudflare Worker serves both frontend assets and backend routes.
Rendering decision
| Page type | Prefer | Notes |
|---|
| Marketing/docs/static content | Static assets | Lowest cost and operational complexity |
| Personalized dashboard | SSR or API + SPA | Fetch user data through bindings |
| Highly interactive app | SPA + API routes | Keep data APIs clean and cacheable where possible |
| Mixed site | Hybrid | Static shell with SSR islands or API-backed hydration |
Route layout pattern
export interface Env {
ASSETS: Fetcher;
DB: D1Database;
}
export default {
async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
const url = new URL(request.url);
if (url.pathname.startsWith("/api/")) {
return api(request, env, ctx);
}
return env.ASSETS.fetch(request);
}
} satisfies ExportedHandler<Env>;
API route pattern
async function api(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
const url = new URL(request.url);
if (url.pathname === "/api/todos" && request.method === "GET") {
const todos = await env.DB.prepare(
"SELECT id, title, completed FROM todos ORDER BY created_at DESC LIMIT 100"
).all<Todo>();
return Response.json(todos.results);
}
return Response.json({ error: "not_found" }, { status: 404 });
}
Cache policy
- Static hashed assets: long cache TTL and immutable headers.
- HTML shell/SSR: short TTL or no-store if personalized.
- API responses: cache only when auth, tenant, and freshness rules are explicit.
- Never cache user-specific HTML or JSON without varying by user/session/tenant.
State placement
- D1: relational records for app data.
- Durable Objects: shared live state such as a room, document, cart, or session coordinator.
- R2: uploaded files, generated exports, media.
- KV: cached config, flags, denormalized public reads.
- Queues/Workflows: background jobs triggered by UI actions.
Review checklist