Skip to main content

Getting Started

Quick install

Setup Vovk.ts with create-next-app.

npx create-next-app -e https://github.com/finom/vovk-hello-world

Inside the project folder run npm run dev and open http://localhost:3000.

Manual install

1. Create Next.js project with App Router and install Vovk.ts

Follow this instruction to install Next.js. Use TypeScript, App Router and src/ directory.

npx create-next-app

Choices example:

At the newly created folder run:

npm i vovk vovk-client

or

yarn add vovk vovk-client

2. Enable decorators

In your tsconfig.json set "experimentalDecorators" to true.

{
"compilerOptions": {
"experimentalDecorators": true,
// ...
}
}

3. Set up Next.js wildcard route handler and export types read by the client library

Create file /src/app/api/[[...vovk]]/route.ts where [[...vovk]] is a folder name insicating what Next.js documentation calls "Optional Catch-all Segment" that can be customized. This is the core entry point for all Vovk.ts routes.

// /src/app/api/[[...vovk]]/route.ts
import { initVovk } from 'vovk';

export const runtime = 'edge';

const controllers = {};
const workers = {};

// export types used by the client
export type Controllers = typeof controllers;
export type Workers = typeof workers;

export const { GET, POST, PUT, DELETE } = initVovk({ controllers, workers });

Enabling Edge Runtime is optional.

4. Create first controller and add it to the controller object

Create HelloController.ts at /src/modules/hello/ with same-named static class.

// /src/modules/hello/HelloController.ts
import { get, prefix } from "vovk";

@prefix('hello') // prefix is optional
export default class HelloController {
@get('greeting')
static getHello() {
return { greeting: 'Hello world!' };
}
}

And add this class at /src/app/api/[[...vovk]]/route.ts to the controllers object.

// /src/app/api/[[...vovk]]/route.ts
import HelloController from '../../../modules/hello/HelloController';

// ...
const controllers = { HelloController };
// ...

The code above creates GET endpoint to /api/hello/greeting. You can also use named export for the controller if needed.

Create a React component and run vovk dev

Once you run npx vovk dev that replaces the original npx next dev you're going to notice the new file .vovk.json created in the root of your project. This file contains required information to build the client and it needs to be committed. It's going to be updated automatically when your project structure is changed. Open http://localhost:3000.

Alternatively, you can use concurrently to avoid using the wrapper. Use --no-next-dev in order to avoid running next dev internally and provide PORT variable explicitly: PORT=3000 concurrently 'vovk dev --no-next-dev' 'next dev' --kill-others.

Besides .vovk.json the command also generates client .js and .ts files inside node_modules/.vovk that are re-exported by vovk-client module to produce no errors if vovk-client is not installed. This approach is borrowed from Prisma ORM.

Now the client is generated you can safely import your client library from vovk-client.

'use client';
import { useState } from 'react';
import { HelloController } from 'vovk-client';
import type { VovkClientReturnType } from 'vovk';

export default function MyComponent() {
const [serverResponse, setServerResponse] = useState<VovkClientReturnType<typeof HelloController.getHello>>();

return (
<>
<button
onClick={async () => {
const response = await HelloController.getHello();
setServerResponse(response);
}}
>
Get Greeting from Server
</button>
<div>{serverResponse?.greeting}</div>
</>
);
}

Note that if you're using VSCode you're probably going to need to restart TS server each time when you add a new controller or worker service to your app because by the time being TS Server doesn't update types imported from node_modules automatically when they were changed. This is a well-known problem that bothers Prisma ORM developers for long time. In all other scenarios (when you add a new method, change body type, etc) you don't need to do that since TS server reads Controllers and Workers that you export from /src/app/api/[[...vovk]]/route.ts.

Next.js Server Components are also supported but require to define absolute URL (by default all requests are made to /api). Check the Server Component Example for more information.

Methods of the generated library have approximately the following signature:

interface Options extends Omit<RequestInit, 'body' | 'method'> {
reactNative?: { textStreaming: boolean };
prefix?: string;
disableClientValidation?: boolean;
body: VovkClientBody<typeof Controller.method>
params: VovkClientParams<typeof Controller.method>
query: VovkClientQuery<typeof Controller.method>
}

In other words it supports custom Next.js options (Because Next.js extends RequestInit global type) as well as React Native Fetch API.

await HelloController.hello({
body: { foo: 'bar' },
next: { revalidate: 3600 },
});

Build and deploy

Use the regular npx next build to build the project. If the client wasn't generated in node_modules/.vovk before, you going to get compilation errors if vovk-client was imported somewhere in the app. To re-generate client with existing .vovk.json without re-builing the project itself you need to run npx vovk generate that updates node_modules/.vovk folder on deployment or after you've reinstalled your node_modules.

To easily build the project on Vercel you can create "vercel-build" npm script at package.json that is going to generate client before build.

"scripts": {
"vercel-build": "vovk generate && next build"
}

Examples

You can check more examples here.