Nitro
Anthony FuCommunityCreated by Anthony Fu
- Skill
- Tool integration
- Software development
- MIT
- No issues found
AutoGineer summary
Written by AutoGineer from the skill’s own files, not by the author
Nitro is a server toolkit designed to build and deploy web servers that run on Node.js, Bun, Deno, and various cloud platforms like Cloudflare, Vercel, and Netlify. It provides a unified codebase for server development, featuring filesystem-based routing, a built-in KV storage layer, caching mechanisms, and support for tasks, WebSockets, and OpenAPI documentation. Nitro v3 introduces significant changes including a package rename, the removal of auto-imports, and a shift toward web-standard H3 v2 APIs.
What it does
- Provides filesystem-based routing with H3 v2 event handlers.
- Manages server configuration and runtime settings via nitro.config.ts.
- Handles caching and storage using an unstorage-based KV layer.
- Supports on-demand and scheduled tasks, WebSockets, and SSE.
- Generates OpenAPI specifications automatically from route metadata.
- Enables deployment to multiple runtimes and platforms through presets.
When to use it
- When building a web server that needs to be portable across different deployment environments.
- When you require a unified toolkit for handling routing, storage, and caching in a server project.
- When migrating existing server projects from Nitro v2 to v3.
- When you need to implement server-side tasks, WebSockets, or OpenAPI documentation.
Advantages
- Framework-agnostic design allows for use with or without other frameworks.
- Deployment-agnostic architecture supports a wide range of runtimes and cloud providers.
- Unified storage and caching layer simplifies data management.
- Declarative route rules for handling redirects, headers, and CORS.
- Built-in support for modern web standards via H3 v2.
Usage examples
- “How do I define a basic server route in Nitro v3?”
- You create a file in your server directory and export a handler using defineHandler from the nitro package.
- “How do I access KV storage in my Nitro server?”
- You use the useKV function imported from nitro/kv to interact with your configured storage mount points.
- “What is the correct way to import Nitro utilities in v3?”
- You must use explicit imports from specific subpaths like nitro, nitro/kv, or nitro/h3, as auto-imports are no longer supported.
- “How do I configure public assets in Nitro?”
- You define a publicAssets array in your nitro.config.ts file, specifying the directory and base URL for your assets.
Install
Download the skill as a ZIP:
https://autogineer.com/agent-skills/antfu/nitro/downloadUnzip it into the cross-client skills folder of your project:
mkdir -p .agents/skills && unzip nitro.zip -d .agents/skills
Documentation by Anthony Fu
The skill is based on Nitro v3 (beta, 3.0.260903), generated at 2026-09-25.
Nitro is a framework-agnostic, deployment-agnostic server toolkit powered by H3 v2, unstorage, and Vite/Rolldown/Rollup. It powers Nuxt and works standalone. From one codebase it builds optimized output for Node.js, Bun, Deno, Cloudflare, Vercel, Netlify, and more.
Key capabilities:
Filesystem routing with H3 v2 event handlers, dynamic params, and method suffixes.
Route rules for declarative caching, headers, redirects, proxying, and CORS.
Caching layer (cached handlers/functions, SWR) on top of the unstorage KV layer.
Runtime config overridable via
NITRO_*env vars.Tasks (on-demand + scheduled/cron), WebSockets/SSE, a SQL database layer, and OpenAPI auto-docs.
Plugins & lifecycle hooks, custom renderer/server entry, and portable deployment presets.
Key v3 changes (vs.
nitropackv2): the package is renamednitropack→nitrowith H3 v2 (web-standardRequest/Response); auto-imports are removed (import everything explicitly); directory scanning is opt-in viaserverDir;useStorage→useKV(nitro/kv) and thestorageconfig option →kv; cacheswrnow defaults tofalse. If unsure about v2-vs-v3 APIs, read advanced-migration first.
Core
| Topic | Description | Reference |
|---|---|---|
| Routing | File-based routes, defineHandler, params, middleware, route rules, errors | core-routing |
| Configuration | nitro.config.ts, defineConfig, key options, runtime config | core-configuration |
| Storage | unstorage KV, mount points, drivers, dynamic mounts | core-storage |
| Cache | defineCachedHandler, defineCachedFunction, SWR, invalidation | core-cache |
| Assets | Public assets, compression, server assets via storage | core-assets |
| Rendering | Renderer (HTML/SSR), server entry, framework integration | core-rendering |
Features
| Topic | Description | Reference |
|---|---|---|
| Plugins & Hooks | definePlugin, runtime lifecycle hooks, error capture | features-plugins |
| Tasks | On-demand & scheduled (cron) tasks, runTask | features-tasks |
| WebSocket & SSE | defineWebSocketHandler, pub/sub, namespaces, event streams | features-websocket |
| Database | Built-in SQL layer via db0, useDatabase, connectors | features-database |
| OpenAPI | Auto spec from defineRouteMeta, Scalar/Swagger UIs | features-openapi |
Advanced / Deployment
| Topic | Description | Reference |
|---|---|---|
| Deployment Presets | Runtimes & providers, compatibility dates, platform integration | deploy-presets |
| v2 → v3 Migration | Package rename, nitro/* imports, H3 v2 API, preset changes | advanced-migration |
Files
- ATTRIBUTION.mdAdded by AutoGineer892 B
- GENERATION.md135 B
- LICENSELicence file added by AutoGineer1.1 KiB
- SKILL.md3.7 KiB
- references/advanced-migration.md6.8 KiB
- references/core-assets.md3.7 KiB
- references/core-cache.md7.9 KiB
- references/core-configuration.md5.7 KiB
- references/core-rendering.md5.0 KiB
- references/core-routing.md8.3 KiB
- references/core-storage.md4.4 KiB
- references/deploy-presets.md3.8 KiB
- references/features-database.md3.5 KiB
- references/features-openapi.md3.5 KiB
- references/features-plugins.md3.9 KiB
- references/features-tasks.md4.0 KiB
- references/features-websocket.md3.8 KiB
references/core-cache.md
name: cache description: Cached event handlers, cached functions, SWR, options and invalidation in Nitro
Caching
Nitro's cache layer (powered by ocache) builds on the storage layer. Import helpers from nitro/cache.
v3 note:
swrnow defaults tofalse(v2 defaulted totrue), andmaxAgedefaults to 1 second — always set both explicitly for anything you want cached.
Cached handlers
defineCachedHandler works like defineHandler plus a cache-options argument.
import { defineCachedHandler } from "nitro/cache";
export default defineCachedHandler((event) => {
return "I am cached for an hour";
}, { maxAge: 60 * 60 });Behavior:
Only
GET/HEADare cached (stored under separate entries); other methods and requests with aRangeheader bypass and call the handler.Auto-manages
etag(weak, from body hash),cache-control(synthesized from the enforced lifetime),vary, andx-cache(HIT/STALE/REVALIDATED/MISS) headers, plus304 Not Modifiedfor conditional requests.Concurrent requests for the same key are deduplicated (handler runs once), bounded by
maxResolveTime(30s default).last-modifiedis never synthesized; a handler-setcache-controlis never overwritten.
What the handler can see
On cacheable requests the handler only receives request data covered by the cache key; everything else is stripped so it can't render output the key doesn't distinguish:
Headers are stripped unless in
varies(includesif-none-match/if-modified-since, handled by Nitro).Query params are stripped unless in
allowQuery(default: none;/pageand/page?a=1share one entry).Cookies are stripped unless in
allowCookies;set-cookieis dropped from cached responses.authorization/proxy-authorizationare stripped unlessallowAuthorizationis set.hostis rewritten to the resolved origin host (part of the key), so multi-host handlers get one entry per host.
Use shouldBypassCache for requests that must reach the handler untouched (not stored).
Cached functions
Cache any async function (e.g. an upstream API call) and reuse it across handlers.
import { defineHandler, type H3Event } from "nitro";
import { defineCachedFunction } from "nitro/cache";
const cachedGHStars = defineCachedFunction(async (repo: string) => {
const data = await fetch(`https://api.github.com/repos/${repo}`).then((r) => r.json());
return data.stargazers_count;
}, {
maxAge: 60 * 60,
name: "ghStars",
getKey: (repo: string) => repo,
});
export default defineHandler(async (event) => {
const { repo } = event.context.params;
const stars = await cachedGHStars(repo).catch(() => 0);
return { repo, stars };
});On edge workers the instance is destroyed after each request. Pass
eventas the first argument to the cached function (and togetKey) so Nitro can useevent.waitUntilfor background revalidation; on platforms with no request-carriedwaitUntil, pass thewaitUntiloption instead.
Cached values are JSON-serialized — don't return Symbols, Maps, or Sets (use serialize/transform for special shapes). Byte values (Uint8Array/ArrayBuffer) are handled and always returned as Uint8Array.
Caching via route rules
Wrap handlers in caching by glob pattern without touching handler code:
import { defineConfig } from "nitro";
export default defineConfig({
kv: { redis: { driver: "redis", url: "redis://localhost:6379" } },
routeRules: {
"/blog/**": { swr: 3600 }, // SWR, 1h (swr:true = 1s default)
"/heavy/**": { cache: { maxAge: 3600, base: "redis" } }, // custom mountpoint
"/api/realtime/**": { cache: false }, // disable
},
});Route-rule handlers use the group nitro/route-rules, and the generated name scopes the entry to the route, method and pattern (unique per process — set an explicit name to share entries across workers/restarts with persistent storage).
Options
Shared (defineCachedHandler + defineCachedFunction)
| Option | Default | Description |
|---|---|---|
maxAge | 1 | Seconds the cache is valid. 0 disables caching. |
swr | false | Serve stale while revalidating in background. |
staleMaxAge | — | Extra seconds a stale value is served (only with swr). 0 = never stale; unset = no TTL written. |
base | /cache | Storage base (→ cache: prefix). An array enables multi-tier reads/writes. |
name | inferred | Cache namespace (falls back to a hash of the function source). |
group | nitro/handlers / nitro/functions | Key group. |
getKey(...args) | hash | Compute cache key (does not change request narrowing). |
integrity | code+options hash | Invalidate when changed. |
getMaxAge(entry) | — | Derive lifetime per entry from the resolved value. |
maxResolveTime | 30 | Deadline (s) for one shared resolution. |
storage | cache storage | Override the backend for this handler/function. |
waitUntil(promise) | — | Hand background work to the host runtime. |
shouldInvalidateCache / shouldBypassCache | — | Per-call predicates. |
onError(err) | log | Custom error handling. |
Handler-only
varies (header names in the key / kept on request), allowQuery (boolean \| string[]), allowCookies (string[], emits Vary: Cookie), allowAuthorization, sendCacheControl (default true; false = server-only caching), cacheStatusHeader (default X-Cache), stream, maxBodySize, headersOnly, shouldCache(entry).
Function-only
transform(entry, ...args) (read-side, entry.status = hit/stale/revalidated/miss), serialize(entry, ctx) (write-side), validate(entry, ctx).
What gets cached
Only responses with status 200/203/301/308, a body, no cache-control opt-out (no-store/private/no-cache/zero shared lifetime), and no Vary: * (or Vary naming a header outside the key) are stored. Failing responses are still returned, just not stored — and get no synthesized cache-control. must-revalidate only disables SWR for that response.
Cache keys & invalidation
Key pattern: `${base}:${group}:${name}:${getKey(...args)}.json` (group/name are sanitized; a hash is appended if characters were removed).
Cached functions expose on-demand methods:
await cachedGHStars("unjs/nitro"); // populate
await cachedGHStars.expire("unjs/nitro"); // mark stale (SWR: served while refreshing)
await cachedGHStars.invalidate("unjs/nitro"); // remove entirely
await cachedGHStars.resolveKeys("unjs/nitro"); // storage key(s) for these args
defineCachedHandlerreturns a plain handler and does not expose these methods — move expensive work into adefineCachedFunction(called from a plaindefineHandler) and invalidate the function when you need on-demand invalidation.
Cache storage
Entries live under the cache: prefix. By default they sit in the in-memory root storage (not persisted). Configure a persistent backend by mounting a cache point via the kv option (see core-storage):
import { defineConfig } from "nitro";
export default defineConfig({
kv: { cache: { driver: "redis" /* options */ } },
$development: { kv: { cache: { driver: "fs", base: "./.data/cache" } } },
});Key Points
Import from
nitro/cache;swrandmaxAgeboth default small — set them explicitly.defineCachedFunctioncaches reusable logic (and supports.invalidate()/.expire());defineCachedHandlercaches whole responses.On edge, always thread
eventthrough cached functions forwaitUntil-backed refresh.Persist cache by mounting a
cachepoint via thekvconfig option (not the removedstorage).
<!-- Source references: - https://nitro.build/docs/cache - https://nitro.build/docs/routing#route-rules - https://ocache.unjs.io -->
Requirements and compatibility
Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta
“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.
Security
No issues found by our static scan· No issues found
A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.
Attribution and licence
- Created by
- Anthony Fu
- Publisher
- Anthony Fu (Community)
- Source
- antfu/skills · skills/nitro · commit f63e9ec
- Licence
- MIT License (redistribution allowed)
- LICENSE (added by AutoGineer from LICENSE.md)
- ATTRIBUTION.md (written by AutoGineer)
- Synced
AutoGineer is not affiliated with or endorsed by Anthony Fu or Anthony Fu.
Download ZIP
The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download nitro.zip