Static Segment
npx vovk new segment openapi --static # creates a new static segment named "openapi" at src/app/api/openapi/[[...vovk]]/route.tsNext.js can pre-render API endpoints at build time using generateStaticParams . Vovk.ts provides the controllersToStaticParams helper to take advantage of this and emit static API endpoints for minimal latency. Use it to serve OpenAPI definitions, historical datasets (refreshed periodically via CI/CD), or other infrequently changing data. It also works in Static Export mode with the output: 'export' Next.js option:
/** @type {import('next').NextConfig} */
const nextConfig = {
output: 'export',
};
module.exports = nextConfig;All you need to do is implement generateStaticParams and return controllersToStaticParams with your controller list.
// ...
export type Controllers = typeof controllers;
export function generateStaticParams() {
return controllersToStaticParams(controllers);
}
export const { GET } = initSegment({ controllers });When deploying to static hosting (e.g., GitHub Pages), include a .json extension in endpoint paths to ensure proper HTTP headers are served.
import { get, prefix } from 'vovk';
@prefix('hello')
export default class HelloController {
@get('greeting.json')
static async getHello() {
return { greeting: 'Hello world!' };
}
}This produces an endpoint like: https://vovk.dev/api/hello/greeting.json (hosted on GitHub Pages).
If you use a custom slug (e.g., /src/app/api/[[...custom]]/route.ts) instead of the default vovk, pass it as the second argument:
export function generateStaticParams() {
return controllersToStaticParams(controllers, 'custom');
}Static Endpoint Parameters
The @get decorator accepts an options object. One of the options, staticParams, lets you enumerate static parameter combinations to simulate conditional routing. The example below shows a single handler that renders six variants for two parameters: section (a | b) and page (1 | 2 | 3).
import { z } from 'zod';
import { procedure, prefix, get, operation } from 'vovk';
@prefix('static-params')
export default class StaticParamsController {
@operation({
summary: 'Static Params',
description: 'Get the static params: section and page',
})
@get('{section}/page{page}.json', {
staticParams: [
{ section: 'a', page: '1' },
{ section: 'a', page: '2' },
{ section: 'a', page: '3' },
{ section: 'b', page: '1' },
{ section: 'b', page: '2' },
{ section: 'b', page: '3' },
],
})
static getStaticParams = procedure({
params: z.object({
section: z.enum(['a', 'b']),
page: z.enum(['1', '2', '3']),
}),
}).handle(async (_req, { section, page }) => {
return { section, page };
});
}View live example on examples.vovk.dev »
This builds six JSON files: