How plait-board/drawnix works
1. Repository shape: a monorepo with layered packages
- This is an Nx-managed TypeScript monorepo.
- The architecture is split into a small deployable web app and several reusable packages:
- apps/web = the shipped browser application shell
- packages/drawnix = the main whiteboard product logic and UI
- packages/react-board = React adapter/view layer for the board
- packages/react-text = text rendering/editing module
- Per-package Vite configs and TS configs indicate each package can be built and tested independently.
2. Product core: packages/drawnix is the main editor subsystem
- This package contains the bulk of the whiteboard experience: canvas tools, toolbars, dialogs, menus, toasts, i18n, styles, and editor hooks.
- It is the domain layer that users actually interact with: drawing, mind maps, flowcharts, freehand, images, links, zoom, theme switching, and export/import features.
- The README’s “all-in-one whiteboard” description matches this package being the heart of the product.
3. Rendering and board integration: packages/react-board
- react-board is the React-facing wrapper around the underlying board engine.
- It provides hooks and plugins for React integration, including event handling and pinch-zoom behavior.
- This is the boundary where React UI code talks to the board/canvas runtime.
4. Text subsystem: packages/react-text
- Text editing and rendering are isolated into a separate package.
- It includes text plugins and link handling, showing that text is treated as a distinct editor capability rather than a simple label field.
- This separation matters because text is a cross-cutting concern across shapes, links, and rich content.
5. Plugin architecture is the main extension boundary
- The repo is explicitly plugin-driven.
- Core plugin families include:
- general behavior plugins (with-common, with-hotkey, with-tool-state-sync)
- drawing/input plugins (with-pencil, freehand plugins, image plugin)
- content plugins (with-text-link, mind extension)
- In architecture terms, user actions are mediated by plugins rather than hard-coded into one monolith.
6. Tooling and UX are organized as independent UI modules
- The components tree under packages/drawnix is heavily modularized: toolbars, popovers, dialogs, menus, pickers, sliders, and toasts.
- These are not just visual widgets; they are the control surface for editor state and tool selection.
- The toolbar/popup/dialog split suggests a clear separation between persistent editor controls and transient editing overlays.
7. Content types and serialization form the data boundary
- The data modules cover blob, filesystem, image, and JSON handling.
- This strongly suggests the application can import/export board state and external assets through dedicated serialization paths.
- The README confirms key outputs: PNG, JSON (.drawnix), and browser-cache autosave.
- In diagrams, this is the persistence/export boundary: board state inside, serialized artifacts outside.
8. Text-to-diagram conversion is a distinct ingestion pipeline
- The ttd-dialog module handles “text to drawnix” flows.
- It includes converters for Mermaid and Markdown into board content.
- This is an important architectural path because it turns external textual specifications into native board objects, rather than requiring manual drawing.
9. App shell and deployment are intentionally minimal
- apps/web is a minimal web app with static assets, redirects, headers, and a single React entry point.
- That suggests the product is delivered as a static frontend rather than a server-rendered app.
- The presence of Cloudflare deployment docs and _headers/_redirects files indicates static hosting/CDN-oriented delivery, likely on Cloudflare Pages.
- Dockerfile and publish scripts support packaging/release, but the runtime is still browser-based.
10. Cross-cutting concerns: localization, themes, and shared styling
- i18n and translation files indicate runtime language switching is a first-class feature.
- Shared SCSS variables and theme files show theme consistency across the UI and board components.
- These cross-cutting layers sit below the UI components but above the board core, so they affect nearly every visible subsystem.
11. Quality gates and validation are split by scope
- Unit/component tests exist in the packages, and apps/web-e2e uses Playwright for end-to-end coverage.
- This mirrors the architecture: package-level behavior is tested close to the code, while the browser app is validated through full UI flows.
- CI workflows and release scripts indicate automated build/test/publish boundaries around the monorepo.
12. Mental model for an architecture diagram
- A good diagram would show: browser app shell → React board adapter → Drawnix core/plugins → board state/data/serialization → export/import and browser persistence.
- Side paths should include: toolbar/dialog UI, text subsystem, freehand/image/diagram converters, localization/theme layers, and external static hosting/release tooling.
- The most important conceptual boundary is between the reusable editor engine (packages/*) and the minimal deployable app (apps/web).
Main entry points: drawnix.tsx Editor shell · plugins Plugins · react-board Board adapter · web Web app
Components 17
App shell
Deployable browser app and end-to-end coverage.
Drawnix core
Main whiteboard editor package with UI, plugins, data, and cross-cutting concerns.
- Editor shell · Top-level Drawnix entry, hooks, and app composition.
packages/drawnix/src/drawnix.tsx - Toolbars · Persistent editor controls for tools, zoom, theme, and creation actions.
packages/drawnix/src/components/toolbar - Dialogs · Transient dialogs, popovers, menus, toasts, and pickers.
packages/drawnix/src/components - Text to diagram · Converts Mermaid or Markdown into native board content.
packages/drawnix/src/components/ttd-dialog - Plugins · Common, hotkey, tool sync, pencil, image, text-link, and mind plugins.
packages/drawnix/src/plugins - Freehand · Stroke generation, smoothing, erasing, and fragment handling.
packages/drawnix/src/plugins/freehand - Data model · Blob, filesystem, image, and JSON boundaries for import/export.
packages/drawnix/src/data - Locale & theme · Translations, theme tokens, and shared styling.
packages/drawnix/src/i18n - Utilities · Common helpers, color, image, property, and pointer utilities.
packages/drawnix/src/utils
Adapters
React-facing integration layers around the board and text subsystems.
- Board adapter · React wrapper and hooks for the board runtime.
packages/react-board - Text module · Isolated text rendering and editing package.
packages/react-text - Board runtime · Underlying board state and event layer exposed through React.
packages/react-board/src/board.tsx - React plugins · React-specific board plugins including pinch zoom and event wiring.
packages/react-board/src/plugins - Text plugins · Text and link plugin layer for rich labels and inline linking.
packages/react-text/src/plugins
Tooling
Monorepo build, test, release, and deployment support.
- Build & release · Nx, Vite, CI, publish scripts, and deployment packaging.
Connections 21
- Web app → Board adapter: mounts · The browser shell renders the reusable board adapter.
- Web app → Editor shell: hosts · The app shell hosts the main editor experience.
- Web e2e → Web app: validates · End-to-end tests exercise the shipped browser app.
- Board adapter → Board runtime: wraps · React hooks and wrappers sit on top of the board runtime.
- Board adapter → React plugins: applies · React integration is extended through board plugins.
- Board adapter → Editor shell: feeds · The adapter provides the runtime boundary used by Drawnix UI.
- Text module → Text plugins: extends · Text rendering and editing are composed via text plugins.
- Text module → Editor shell: supplies · Text editing is consumed by the main editor subsystem.
- Editor shell → Plugins: orchestrates · The editor shell coordinates behavior through plugins.
- Editor shell → Toolbars: presents · The shell exposes the persistent tool and mode controls.
- Editor shell → Dialogs: opens · The shell uses dialogs and popovers for transient editor actions.
- Editor shell → Text to diagram: imports · Text-to-diagram conversion is part of the editor surface.
- Plugins → Freehand: includes · Freehand editing is implemented as a dedicated plugin family.
- Plugins → Data model: serializes · Plugins hand off board content through the data boundary.
- Plugins → Locale & theme: uses · Plugin-driven UI is styled and localized through shared concerns.
- Toolbars → Locale & theme: shares · Toolbars depend on locale and theme assets.
- Dialogs → Data model: imports/exports · Dialogs and menus feed serialization, asset, and file flows.
- Text to diagram → Data model: produces · Converted content becomes native board data.
- Text to diagram → Text module: converts · Markdown and Mermaid are translated into text/board structures.
- Data model → Build & release: packages · Serialized artifacts support publish, export, and deployment flows.
- Web app → Build & release: deployed by · Static hosting and CI/release scripts ship the browser app.