HFU Digital Docs
BoardKit

Getting Started

Install and set up BoardKit in your NestJS backend and React frontend

Prerequisites

  • Bun or Node.js 18+
  • A NestJS application (backend)
  • A React 18/19 application (frontend)

Installation

CalVer pinning required. BoardKit packages are versioned yyyy.mm.version — for example 2026.04.1. Always pin exact versions in your package.json; range operators (^, ~) do not behave like semver across month/year boundaries. All three packages must be pinned to the same version. Replace the version in the snippets below with the latest published release.

Core (shared types and logic)

bun add @hfu.digital/boardkit-core@2026.04.1

The core package has zero runtime dependencies and is automatically installed as a dependency of both the backend and frontend packages.

Backend

bun add @hfu.digital/boardkit-nestjs@2026.04.1

Peer dependencies:

bun add @nestjs/common @nestjs/core @nestjs/websockets @nestjs/platform-socket.io rxjs

Frontend

bun add @hfu.digital/boardkit-react@2026.04.1

Peer dependencies:

bun add react react-dom socket.io-client  # React 18 or 19

Backend Setup

1. Implement Storage Adapters

BoardKit requires four adapter implementations. You can use the included Prisma adapter or write your own.

import { PrismaBoardAdapter } from '@hfu.digital/boardkit-nestjs';
import { PrismaService } from './prisma.service';

const prisma = new PrismaService();

const boardStorage = new PrismaBoardAdapter({
    board: prisma.board,
    page: prisma.page,
    element: prisma.element,
    boardMember: prisma.boardMember,
    shareLink: prisma.shareLink,
});

For AssetStorage and EventLogStorage, see the Storage Interface and Asset Storage docs.

2. Implement an Auth Guard

import { BoardAuthGuard, type AuthenticatedUser } from '@hfu.digital/boardkit-nestjs';

class MyAuthGuard extends BoardAuthGuard {
    async validateConnection(token: string): Promise<AuthenticatedUser | null> {
        // Validate WebSocket connection token
        const user = await verifyToken(token);
        return user ? { userId: user.id, displayName: user.name } : null;
    }

    async validateRequest(token: string): Promise<AuthenticatedUser | null> {
        // Validate HTTP request token
        const user = await verifyToken(token);
        return user ? { userId: user.id, displayName: user.name } : null;
    }
}

3. Register the Module

import { Module } from '@nestjs/common';
import { BoardModule } from '@hfu.digital/boardkit-nestjs';

@Module({
    imports: [
        BoardModule.register({
            storage: boardStorage,
            assetStorage: myAssetStorage,
            eventLogStorage: myEventLogStorage,
            authGuard: new MyAuthGuard(),
        }),
    ],
})
export class AppModule {}

This registers 5 REST controllers (boards, pages, assets, export, sharing) and a Socket.IO WebSocket gateway at the /board namespace.

Frontend Setup

1. Wrap Your App with the Provider

import { BoardKitProvider } from '@hfu.digital/boardkit-react';

function App() {
    return (
        <BoardKitProvider
            config={{
                apiUrl: '/api',
                wsUrl: 'ws://localhost:3000/board',
                authToken: 'your-jwt-token',
            }}
        >
            <WhiteboardPage />
        </BoardKitProvider>
    );
}

2. Use the Canvas and Hooks

import {
    BoardCanvas,
    Toolbar,
    useBoard,
    useCollaboration,
    useTool,
    useKeyboardShortcuts,
} from '@hfu.digital/boardkit-react';

function WhiteboardPage() {
    const { board, loading } = useBoard('board-id');
    const { connectionState } = useCollaboration('board-id');
    const { activeTool, setTool } = useTool();
    useKeyboardShortcuts();

    if (loading) return <p>Loading...</p>;

    return (
        <div style={{ width: '100vw', height: '100vh' }}>
            <Toolbar activeTool={activeTool} onToolChange={setTool} />
            <BoardCanvas />
            <p>Status: {connectionState}</p>
        </div>
    );
}

Next Steps

On this page