File-Based Routes
Mixing Nitro file-based routes with Vercube controllers
Vercube controllers and Nitro file-based routes coexist without any extra configuration. You can use both patterns in the same project and they will work independently.
Nitro File-Based Routes
Standard Nitro route files work exactly as documented in the Nitro docs. They are handled by Nitro's own routing layer and are completely unaware of Vercube:
import { defineEventHandler } from 'nitro/h3';
export default defineEventHandler(() => {
return { status: 'ok' };
});
import { defineEventHandler, getRouterParam, readBody } from 'nitro/h3';
export default defineEventHandler(async (event) => {
const id = getRouterParam(event, 'id');
const body = await readBody(event);
return { id, ...body };
});
Vercube Controllers
Controllers registered via the vercubeNitro plugin take a different path - they are handled by the Vercube app and go through Vercube's request pipeline:
src/routes/ItemController.ts
import { Controller, Get, Post, Param } from '@vercube/core';
@Controller('/api/items')
export class ItemController {
@Get('/:id')
get(@Param('id') id: string) {
return { id };
}
@Post('/')
create() {
return { created: true };
}
}
Route Priority
When both a Nitro file route and a Vercube controller are registered for the same path, Nitro file routes take precedence. To avoid conflicts, use distinct path prefixes - for example, serve Vercube controllers under /api/ and keep Nitro file routes elsewhere.
Recommended Project Layout
src/
├── middleware/
│ └── AuthMiddleware.ts # Vercube middleware (excluded from Nitro)
├── routes/
│ ├── healthz.get.ts # Nitro file route
│ ├── items/
│ │ └── [id].post.ts # Nitro file route
│ └── ItemController.ts # Vercube controller
└── services/
└── ItemService.ts # Vercube injectable service