Write your server once. Deploy to Node.js, Cloudflare Workers, Vercel, Deno, Bun, AWS Lambda, or a plain Docker container. Nitro handles the adapter.
What is Nitro?
Nitro is a universal server engine built by the Nuxt team. It powers Nuxt's server-side rendering, but it's also a standalone framework for building server applications that deploy anywhere.
Why Nitro
1. Universal Deployment
// server/api/hello.ts
export default defineEventHandler((event) => {
return { message: 'Hello from Nitro!' };
});
# Deploy to any platform — zero code changes
NITRO_PRESET=cloudflare-pages npx nitropack build
NITRO_PRESET=vercel npx nitropack build
NITRO_PRESET=node-server npx nitropack build
NITRO_PRESET=deno-server npx nitropack build
NITRO_PRESET=aws-lambda npx nitropack build
NITRO_PRESET=bun npx nitropack build
Same code. Different presets. 15+ deployment targets.
2. File-Based API Routes
server/
├── api/
│ ├── users/
│ │ ├── index.get.ts → GET /api/users
│ │ ├── index.post.ts → POST /api/users
│ │ └── [id].get.ts → GET /api/users/:id
│ └── health.ts → GET /api/health
├── routes/
│ └── feed.xml.ts → GET /feed.xml
└── middleware/
└── auth.ts → Runs on every request
3. Built-in Caching
export default defineCachedEventHandler(async (event) => {
const data = await fetchExpensiveData();
return data;
}, {
maxAge: 60 * 60, // 1 hour
staleMaxAge: 60 * 60 * 24, // Serve stale for 24h while revalidating
swr: true,
});
4. Key-Value Storage
export default defineEventHandler(async (event) => {
const storage = useStorage();
// Works with any backend: memory, Redis, Cloudflare KV, S3
await storage.setItem('user:1', { name: 'Alice' });
const user = await storage.getItem('user:1');
return user;
});
// nitro.config.ts
export default defineNitroConfig({
storage: {
db: { driver: 'redis', url: 'redis://localhost:6379' },
assets: { driver: 'cloudflare-kv-binding', binding: 'ASSETS' },
},
});
5. Auto-Imports
// No imports needed — Nitro auto-imports utilities
export default defineEventHandler(async (event) => {
const body = await readBody(event);
const query = getQuery(event);
const params = event.context.params;
setCookie(event, 'session', 'abc123');
setHeader(event, 'X-Custom', 'value');
return sendRedirect(event, '/dashboard');
});
6. WebSocket Support
// server/api/ws.ts
export default defineWebSocketHandler({
open(peer) {
peer.send('Welcome!');
peer.subscribe('chat');
},
message(peer, message) {
peer.publish('chat', message.text());
},
close(peer) {
peer.unsubscribe('chat');
},
});
Nitro vs Express vs Hono
| Nitro | Express | Hono | |
|---|---|---|---|
| Deploy targets | 15+ presets | Node.js only | Multi (manual) |
| File routing | Built-in | Manual | Manual |
| Caching | Built-in | Manual | Manual |
| Storage | Multi-driver | Manual | Manual |
| Auto-imports | Yes | No | No |
| WebSocket | Built-in | Via ws package | Via adapter |
| TypeScript | Native | Via setup | Native |
Getting Started
npx giget@latest nitro my-server
cd my-server
npm install
npm run dev
The Bottom Line
Nitro decouples your server code from your deployment target. Write once, deploy to 15+ platforms. If you want server portability without lock-in, Nitro is the engine.
Need data solutions? I build scraping tools. Check my Apify actors or email spinov001@gmail.com.
Top comments (0)