@filekit-studio/sketch
Local-first, interactive whiteboard and architecture diagramming SDK for React and Next.js.
Documentation • Live Playground • Tech Stencils Catalog • FileKit Studio
Features
- Local-First Privacy: Zero server calls, zero database overhead, and zero telemetry. Diagrams run and persist entirely in the client.
- Database Schema & ER Modeling: Typed 2-column database tables (
tableStyle: 'database') with PK/FK icons, automatic type coloring, dynamic row addition/deletion, auto-widening text boxes, and full keyboard navigation (Enter, Shift+Enter, Backspace row removal, arrow traversal). Press M to activate. - Live Animated Data Flow Connectors: Real-time particle pulse and flow simulation across curved, elbow, and straight magnetic connectors with configurable speed, trigger modes, and glow colors.
- Shift-Constrained 15° Angle Snapping: Hold Shift while drawing straight lines or arrows to lock to 15° angular increments (0° horizontal, 90° vertical, 45° diagonal, 30°/60° isometric) with floating degree badges.
- Arrow Badges & Harmonized Palettes: In-place double-click label editing with multi-line wrap (
\n), compact auto-sizing, and single-color tone palettes with dark/light mode optimization. - Magnetic Connection Anchor Suggestions: Real-time 12-point perimeter anchor suggestions on diagram and database table border hover for effortless connector snapping.
- Frame Containment & Anti-Stealing Duplication: Structural frames (
type: 'frame') that act as isolated slide decks or component boundaries. Duplicating or moving a frame clones and shifts all enclosed shapes atomically. - Steganographic Lossless PNG Export: Export raster PNGs with deflated vector scene metadata embedded inside PNG
tEXtchunks (embedScene: true). Re-importing into Sketch restores 100% of editable vectors. - React 18 & 19 / Next.js Ready: Native App Router and Pages Router support with zero SSR hydration mismatches.
- 675+ Production Stencils: Official cloud logos and microservice primitives (AWS, GCP, Azure, Docker, Kubernetes, Next.js, PostgreSQL, Redis, Supabase).
- Obstacle-Avoiding Routing: Hanan Grid $A^*$ orthogonal and curved arrow routing with Minkowski Sum obstacle inflation, corner fillets, and highway lane offsets.
- Presentation Deck Mode: Convert canvas frames into presentation slide decks (
Alt+P) with laser pointer and spotlight focus tools. - Headless Exporters: Serverless and headless export to vector PDF (multi-page auto-paginated), crisp PNG, and standalone SVG.
- Embedded Viewer: Lightweight
<SketchViewer />component for rendering interactive or static diagrams in docs and blogs. - Unified
.sketchFile Format: Fast, portable JSON file format protected by a prototype-pollution and XSS security purifier.
Installation
npm install @filekit-studio/sketch
# or
pnpm add @filekit-studio/sketch
# or
bun add @filekit-studio/sketch
Peer Dependencies
react >= 18.0.0react-dom >= 18.0.0
Required Stylesheet Import
Import the stylesheet in your root layout (app/layout.tsx or pages/_app.tsx):
// Universal modern Tailwind CSS v4 styling (Default)
import '@filekit-studio/sketch/styles.css'
// Or pick an aesthetic variant:
// import '@filekit-studio/sketch/classic.css' // Classic clean wireframe styling
// import '@filekit-studio/sketch/neumorphic.css' // Soft extruded 3D neumorphic styling
Zero CSS Pollution (Strict Scope Isolation):
All styles are strictly scoped under.fk-sketch-root. Importing this stylesheet will never conflict with your app's global CSS, markdown fonts, or Tailwind config.
Quick Start
Import <SketchEditor /> inside a Client Component ('use client'):
'use client'
import React from 'react'
import { SketchEditor } from '@filekit-studio/sketch'
import '@filekit-studio/sketch/styles.css'
export default function WhiteboardPage() {
return (
<main className="w-screen h-screen overflow-hidden">
<SketchEditor
boardName="System Architecture"
storageKey="my_app_whiteboard"
onChange={(doc) => {
console.log('Updated:', doc.elements.length, 'elements')
}}
onSave={(doc) => {
console.log('Saved:', doc)
}}
showGuideButton={true}
guideHref="/docs"
/>
</main>
)
}
Read-Only Diagram Viewer (<SketchViewer />)
Use <SketchViewer /> to embed diagrams in documentation, blog posts, and dashboards with zero editor chrome:
'use client'
import { SketchViewer } from '@filekit-studio/sketch'
import '@filekit-studio/sketch/styles.css'
export function ArchitectureDiagram({ document }) {
return (
<div className="w-full h-[420px] rounded-xl overflow-hidden border">
<SketchViewer
value={document}
theme="system"
autoFit={true}
interactive={true}
showCopyButton={true}
showZoomControls={true}
/>
</div>
)
}
Obstacle-Avoiding Arrow Routing
Route collision-free orthogonal or curved arrows around diagram nodes programmatically:
import { computeNonCollisionRoute, generateFilletSvgPath } from '@filekit-studio/sketch'
const route = computeNonCollisionRoute(
{ x: 100, y: 150 }, // Start point
{ x: 500, y: 350 }, // End point
'right', // Start anchor orientation ('top' | 'right' | 'bottom' | 'left')
'left', // End anchor orientation
obstacles, // Array of { x, y, width, height }
{
margin: 24, // Minkowski Sum obstacle padding
bendPenalty: 40, // Penalize unnecessary turns
filletRadius: 10, // Rounded 90° arc fillets
smoothCurves: false,
}
)
// Generate SVG path string for rendering:
const svgPath = generateFilletSvgPath(route.waypoints, 10)
Headless Export Utilities
Export diagrams without mounting the canvas component via @filekit-studio/sketch/export:
import {
exportToPng,
exportToSvg,
exportWhiteboardToPdf,
} from '@filekit-studio/sketch/export'
import { extractSceneFromPng } from '@filekit-studio/sketch'
// PNG with optional steganographic lossless scene embedding
const pngDataUrl = await exportToPng(elements, {
scale: 2,
backgroundColor: '#ffffff',
embedScene: true, // Injects compressed scene into PNG tEXt chunk
})
// Extract 100% editable vector scene from a FileKit PNG
const recoveredDoc = await extractSceneFromPng(pngFileBlob)
// Vector SVG string
const svgMarkup = exportToSvg(elements, {
includeBackground: true,
})
// Multi-page Vector PDF Blob
const pdfBlob = await exportWhiteboardToPdf(elements, {
title: 'Architecture Specification',
author: 'FileKit Studio',
})
Database Schema & ER Entity Tables
Render typed 2-column database tables with primary keys, datatypes, and automatic palette synchronization:
import { SketchEditor, type SketchBoardElement } from '@filekit-studio/sketch'
const usersTable: SketchBoardElement = {
id: 'table_users',
type: 'table',
tableStyle: 'database', // Activates Database Entity mode
x: 100,
y: 100,
width: 280,
height: 180,
strokeColor: '#3b82f6',
strokeWidth: 2,
strokeStyle: 'solid',
fillColor: '#1e293b',
fillStyle: 'solid',
opacity: 1,
zIndex: 1,
rows: 4,
cols: 2,
colWidths: [150, 130],
rowHeights: [36, 32, 32, 32],
hasHeaderRow: true,
cells: {
'0,0': { text: 'users', bold: true, align: 'left' },
'1,0': { text: 'id', align: 'left' }, // Auto-displays yellow PK key icon
'1,1': { text: 'uuid', align: 'right' },
'2,0': { text: 'name', align: 'left' },
'2,1': { text: 'varchar(100)', align: 'right' },
'3,0': { text: 'email', align: 'left' },
'3,1': { text: 'varchar(255)', align: 'right' },
},
}
- Keyboard Navigation in Cells:
- Enter: Inserts a clean newline without shifting cells. Row height dynamically expands.
- Shift + Enter or Tab: Confirms cell edit and jumps to the next row/column.
- Backspace (when row is empty): Deletes the entire empty row and contracts table height automatically.
- ↑ ↓ → ←: Navigate between adjacent cells.
- Shortcut: Press M to activate the Database Schema Table tool.
Live Animated Data Flow Connectors
Simulate data streaming across connectors in real time:
const animatedStream: SketchBoardElement = {
id: 'stream_1',
type: 'arrow',
arrowType: 'elbow',
x: 280,
y: 150,
width: 140,
height: 80,
strokeColor: '#3b82f6',
strokeWidth: 2,
strokeStyle: 'solid',
fillColor: 'transparent',
fillStyle: 'solid',
opacity: 1,
zIndex: 2,
endArrowhead: 'arrow',
// Live Connector Simulation:
flowAnimation: 'packet-pulse', // 'none' | 'marching-ants' | 'packet-pulse' | 'error-backoff'
flowSpeed: 'normal', // 'slow' (2.4s) | 'normal' (1.4s) | 'fast' (0.7s)
flowTrigger: 'continuous', // 'continuous' | 'hover' | 'click' | 'step'
flowColor: '#60a5fa', // Custom packet glow color
}
Programmatic Controller (SketchController)
Attach a controllerRef to imperatively control the whiteboard canvas:
import React, { useRef } from 'react'
import { SketchEditor, type SketchController } from '@filekit-studio/sketch'
export function ControlledCanvas() {
const controllerRef = useRef<SketchController | null>(null)
const handleAddNote = () => {
controllerRef.current?.addElement({
type: 'sticky',
x: 200,
y: 200,
width: 180,
height: 180,
text: 'Production Note',
fillColor: '#fef08a',
})
}
return (
<div className="w-full h-full relative">
<button onClick={handleAddNote}>+ Add Note</button>
<SketchEditor controllerRef={controllerRef} />
</div>
)
}
Controller Methods
| Method | Description |
|---|---|
loadDocument(doc) | Replaces the active whiteboard document. |
getDocument() | Returns the serializable document state. |
clear() | Resets the whiteboard canvas to an empty state. |
addElement(element) | Programmatically inserts and selects an element. |
updateElement(id, patch) | Partially updates an existing element. |
deleteElements(ids) | Deletes elements by ID list. |
getElements() | Returns current elements array. |
undo() / redo() | Navigates the undo/redo history stack. |
zoomToFit() | Centers and zooms to fit all elements in viewport. |
zoomIn() / zoomOut() | Smooth incremental viewport zooming. |
resetZoom() | Resets zoom scale back to 100%. |
showToast(msg, options) | Triggers in-canvas notification toast banner. |
on(event, handler) | Subscribes to events ('change', 'select', 'clear', 'undo', 'redo', 'camera'). |
Component API Reference
<SketchEditor />
| Prop | Type | Default | Description |
|---|---|---|---|
value | SketchDocument | SketchBoardElement[] | undefined | Controlled document or elements. |
defaultValue | SketchDocument | SketchBoardElement[] | Starter Doc | Initial uncontrolled document state. |
onChange | (doc: SketchDocument) => void | undefined | Callback fired on any element or title change. |
onSave | (doc: SketchDocument) => void | undefined | Callback fired on manual save (Ctrl+S). |
storageKey | string | null | 'filekit_sketch_document_v1' | Key used to persist state to localStorage. Use dynamic keys (storageKey={'board_' + id}) to isolate multi-board workspaces. |
boardName | string | 'My Whiteboard' | Whiteboard title displayed in header. |
readOnly | boolean | false | Disables mutations and hides editing tools. |
theme | 'light' | 'dark' | 'system' | 'system' | Visual color theme mode. |
showThemeToggle | boolean | false | Independent sun/moon canvas theme button in top bar. |
onThemeChange | (theme: 'light' | 'dark') => void | undefined | Callback fired when theme toggle is clicked. |
canvasBackground | string | '#f0f4f8' | Canvas background hex color. |
gridStyle | 'grid' | 'dots' | 'cross' | 'none' | 'grid' | Background grid pattern. |
fontFamily | FontFamily | 'fuzzy' | Default canvas font family. |
panelVariant | 'classic' | 'neumorphic' | 'classic' | Chrome styling variant: flat borders or soft 3D bevels. |
wheelPan | boolean | true | When false, mouse wheel scrolls the host webpage; Ctrl+wheel zooms. |
toastPosition | ToastPosition | 'bottom-center' | Toast banner position ('bottom-center', 'top-right', etc.). |
position | ToastPosition | 'bottom-center' | Direct alias for toastPosition. |
toastDuration | number | 2400 | Auto-dismiss duration in milliseconds for notification toasts. |
saveToastMessage | string | null | 'Document saved successfully' | Custom save toast message (or null to suppress). |
templates | TemplateDefinition[] | undefined | Custom architecture starter templates array. |
controllerRef | React.Ref<SketchController> | undefined | Ref exposing programmatic imperative controls. |
onExit | () => void | undefined | Exit back button handler. If omitted with exitHref, exit button is hidden. |
exitHref | string | undefined | Route navigated to when clicking the exit button. |
onShare | () => void | undefined | Callback fired when user clicks the Share button in the top bar. Automatically mounts the Share button. |
showGuideButton | boolean | false | Mounts a guide help button in the header. |
guideHref | string | undefined | External or internal URL for the guide button. |
onOpenGuide | () => void | undefined | Intercepts click on guide button to trigger custom modal. |
uiConfig | SketchUIConfig | {} | Fine-grained visibility toggles for all 54 toolbars and panels. |
<SketchViewer />
| Prop | Type | Default | Description |
|---|---|---|---|
value / elements | SketchDocument | SketchBoardElement[] | undefined | Document or elements to render. |
theme | 'light' | 'dark' | 'system' | 'system' | Light/dark theme mode. |
autoFit | boolean | true | Centers and scales diagram to fit container. |
interactive | boolean | true | Allows panning and zooming. Set false for static display. |
showCopyButton | boolean | true | 1-click clipboard export button. |
copyFormat | 'elements' | 'image' | 'json' | 'elements' | Format written to the clipboard: 'elements' (paste directly with Ctrl+V into whiteboard), 'image' (2x PNG), or 'json'. |
showZoomControls | boolean | true | Minimal bottom zoom controls (- 100% + Fit). |
canvasBackground | string | '#f0f4f8' | Custom canvas background color hex. |
gridStyle | 'grid' | 'dots' | 'cross' | 'none' | 'dots' | Background grid pattern. |
title | string | undefined | Optional title badge in top-left corner. |
License
MIT © FileKit Studio