Manual Install
Create a Next.js project with App Router and TypeScript
npx create-next-app my-app --ts --app --src-dircd my-appThe src directory is optional but recommended, as it keeps the root directory clean.
Install “vovk” and “vovk-client”
npm i vovk vovk-clientCreate an empty config file (optional)
Create vovk.config.mjs at the root of the project with the following content:
// @ts-check
/** @type {import('vovk').VovkConfig} */
const vovkConfig = {};
export default vovkConfig;Install a validation library and enable client-side validation
For Zod validation on the server side and Ajv on the client side, install the following packages:
npm i zod vovk-zod vovk-ajvModify the validateOnClient import in your config file to enable client-side validation:
// @ts-check
/** @type {import('vovk').VovkConfig} */
const vovkConfig = {
outputConfig: {
imports: {
validateOnClient: 'vovk-ajv',
},
},
};
export default vovkConfig;Update the “dev” script and create a “prebuild” NPM script
There are two ways to run Vovk.ts and the Next.js server concurrently: explicitly and implicitly. The explicit way is to install the concurrently package and run both scripts with it, which requires the PORT variable to be set. The implicit way is to have the Vovk.ts CLI run the Next.js server itself. In this case, vovk-cli will assign the port automatically.
The prebuild script will run vovk generate before next build to generate the client library before building the Next.js app.
Explicit
Install concurrently:
npm i -D concurrentlyUpdate the “dev” script in package.json:
"scripts": {
"build": "next build",
"dev": "PORT=3000 concurrently 'vovk dev' 'next dev' --kill-others",
"prebuild": "vovk generate"
}Enable decorators
In your tsconfig.json, set "experimentalDecorators" to true.
{
"compilerOptions": {
"experimentalDecorators": true
// ...
}
}Create a controller
Create HelloController.ts at /src/modules/hello/ with a same-named static class.
import { get, prefix } from 'vovk';
@prefix('greetings') // prefix is optional
export default class HelloController {
@get('greeting')
static getHello() {
return { greeting: 'Hello, World!' };
}
}Create a root segment
Create the root segment /src/app/api/[[…vovk]]/route.ts, where [[…vovk]] is a folder name indicating what the Next.js documentation calls an “Optional Catch-all Segment” (the slug can be any valid slug, such as
In the code below, HelloRPC indicates the name of the generated RPC module, and HelloController is the controller module created above.
import { initSegment } from 'vovk';
import HelloController from '../modules/hello/HelloController';
const controllers = { HelloRPC: HelloController };
// export types that are inferred by the client
export type Controllers = typeof controllers;
// export Next.js route handlers
export const { GET, POST, PUT, DELETE } = initSegment({ controllers });Run “vovk dev”
Run npm run dev to start Vovk.ts and Next.js concurrently.
npm run devNavigate to http://localhost:3000/api/greetings/greeting to see the result.
Create a React component
Now that the client is generated, you can safely import your client library from vovk-client.
'use client';
import { useState } from 'react';
import { HelloRPC } from 'vovk-client';
import type { VovkReturnType } from 'vovk';
export default function MyComponent() {
const [serverResponse, setServerResponse] = useState<VovkReturnType<typeof HelloController.getHello>>();
return (
<>
<button
onClick={async () => {
const response = await HelloController.getHello();
setServerResponse(response);
}}
>
Get Greeting from Server
</button>
<div>{serverResponse?.greeting}</div>
</>
);
}Open http://localhost:3000 to see the result.
Note that if you’re using VSCode, you’ll probably need to restart the TS
server each time you add a new
controller class to your app. Changing the controller list is the only case when you may need to restart the TS server
manually; other changes, such as adding new methods or changing validation, will be picked up automatically.