BoardKitFrontend
Frontend Overview
Overview of the @hfu.digital/boardkit-react package
The @hfu.digital/boardkit-react package provides a complete React frontend for collaborative whiteboards, including a canvas rendering engine, input pipeline, hooks, and pre-built components.
What's Included
| Category | Exports |
|---|---|
| Context | BoardKitProvider, useBoardKit |
| Hooks | useBoard, useCollaboration, useTool, useViewport, useHistory, usePageNavigation, usePresence, useGrid, useFollowMode, useImageImport, useExport, useErrorRecovery, useKeyboardShortcuts |
| Components | BoardCanvas, Toolbar, PageNavigator, SelectionHandles, TextEditor, ParticipantList, CursorOverlay, ShareDialog, ExportDialog, Minimap, DropZone |
| Engine | Canvas2DRenderer, InputPipeline, viewport utilities, element renderers |
| Gestures | GestureRecognizer, MouseHandler, TouchHandler, PenHandler |
| Store | BoardStore (mutable store with slice-based pub/sub) |
Peer Dependencies
{
"react": "^18.0.0 || ^19.0.0",
"react-dom": "^18.0.0 || ^19.0.0"
}Quick Start
import {
BoardKitProvider,
BoardCanvas,
Toolbar,
useBoard,
useCollaboration,
useTool,
useKeyboardShortcuts,
} from '@hfu.digital/boardkit-react';
function App() {
return (
<BoardKitProvider config={{ apiUrl: '/api', wsUrl: 'ws://localhost:3000/board' }}>
<Whiteboard />
</BoardKitProvider>
);
}
function Whiteboard() {
const { board, loading } = useBoard('my-board-id');
const { connectionState } = useCollaboration('my-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 />
</div>
);
}Architecture
The frontend follows a mutable-store-outside-React architecture:
- BoardStore lives outside React state. It holds all board data, scene state, viewport, tool state, and collaboration data.
- Hooks bridge the store into React via
useSyncExternalStoreand slice-based subscriptions. - Canvas2DRenderer renders directly to two stacked
<canvas>elements — no React reconciliation for drawing. - InputPipeline translates DOM pointer events into normalized
InputEvents that feed into the active tool.
This architecture avoids React re-renders during rapid drawing operations.