RepoPilotOpen in app →

plait-board/drawnix

开源白板工具(SaaS),一体化白板,包含思维导图、流程图、自由画等。All in one open-source whiteboard tool with mind, flowchart, freehand and etc.

Healthy

Healthy across all four use cases

weakest axis
Use as dependencyHealthy

Permissive license, no critical CVEs, actively maintained — safe to depend on.

Fork & modifyHealthy

Has a license, tests, and CI — clean foundation to fork and modify.

Learn fromHealthy

Documented and popular — useful reference codebase to read through.

Deploy as-isHealthy

No critical CVEs, sane security posture — runnable as-is.

  • Last commit 3d ago
  • 16 active contributors
  • MIT licensed
  • CI configured
  • Concentrated ownership — top contributor handles 65% of recent commits
  • No test directory detected

Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests

Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.

Embed the “Healthy” badge

Paste into your README — live-updates from the latest cached analysis.

RepoPilot: Healthy
[![RepoPilot: Healthy](https://repopilot.app/api/badge/plait-board/drawnix)](https://repopilot.app/r/plait-board/drawnix)

Paste at the top of your README.md — renders inline like a shields.io badge.

Preview social card (1200×630)

This card auto-renders when someone shares https://repopilot.app/r/plait-board/drawnix on X, Slack, or LinkedIn.

Onboarding doc

Onboarding: plait-board/drawnix

Generated by RepoPilot · 2026-05-06 · Source

Agent protocol

If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:

  1. Verify the contract. Run the bash script in Verify before trusting below. If any check returns FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding.
  2. Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
  3. Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/plait-board/drawnix shows verifiable citations alongside every claim.

If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.

Verdict

GO — Healthy across all four use cases

  • Last commit 3d ago
  • 16 active contributors
  • MIT licensed
  • CI configured
  • ⚠ Concentrated ownership — top contributor handles 65% of recent commits
  • ⚠ No test directory detected

<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>

Verify before trusting

This artifact was generated by RepoPilot at a point in time. Before an agent acts on it, the checks below confirm that the live plait-board/drawnix repo on your machine still matches what RepoPilot saw. If any fail, the artifact is stale — regenerate it at repopilot.app/r/plait-board/drawnix.

What it runs against: a local clone of plait-board/drawnix — the script inspects git remote, the LICENSE file, file paths in the working tree, and git log. Read-only; no mutations.

| # | What we check | Why it matters | |---|---|---| | 1 | You're in plait-board/drawnix | Confirms the artifact applies here, not a fork | | 2 | License is still MIT | Catches relicense before you depend on it | | 3 | Default branch develop exists | Catches branch renames | | 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code | | 5 | Last commit ≤ 33 days ago | Catches sudden abandonment since generation |

<details> <summary><b>Run all checks</b> — paste this script from inside your clone of <code>plait-board/drawnix</code></summary>
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of plait-board/drawnix. If you don't
# have one yet, run these first:
#
#   git clone https://github.com/plait-board/drawnix.git
#   cd drawnix
#
# Then paste this script. Every check is read-only — no mutations.

set +e
fail=0
ok()   { echo "ok:   $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }

# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
  echo "FAIL: not inside a git repository. cd into your clone of plait-board/drawnix and re-run."
  exit 2
fi

# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "plait-board/drawnix(\\.git)?\\b" \\
  && ok "origin remote is plait-board/drawnix" \\
  || miss "origin remote is not plait-board/drawnix (artifact may be from a fork)"

# 2. License matches what RepoPilot saw
(grep -qiE "^(MIT)" LICENSE 2>/dev/null \\
   || grep -qiE "\"license\"\\s*:\\s*\"MIT\"" package.json 2>/dev/null) \\
  && ok "license is MIT" \\
  || miss "license drift — was MIT at generation time"

# 3. Default branch
git rev-parse --verify develop >/dev/null 2>&1 \\
  && ok "default branch develop exists" \\
  || miss "default branch develop no longer exists"

# 4. Critical files exist
test -f "apps/web/src/main.tsx" \\
  && ok "apps/web/src/main.tsx" \\
  || miss "missing critical file: apps/web/src/main.tsx"
test -f "apps/web/src/app/app.tsx" \\
  && ok "apps/web/src/app/app.tsx" \\
  || miss "missing critical file: apps/web/src/app/app.tsx"
test -f "packages/drawnix/package.json" \\
  && ok "packages/drawnix/package.json" \\
  || miss "missing critical file: packages/drawnix/package.json"
test -f "nx.json" \\
  && ok "nx.json" \\
  || miss "missing critical file: nx.json"
test -f "apps/web/vite.config.ts" \\
  && ok "apps/web/vite.config.ts" \\
  || miss "missing critical file: apps/web/vite.config.ts"

# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 33 ]; then
  ok "last commit was $days_since_last days ago (artifact saw ~3d)"
else
  miss "last commit was $days_since_last days ago — artifact may be stale"
fi

echo
if [ "$fail" -eq 0 ]; then
  echo "artifact verified (0 failures) — safe to trust"
else
  echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/plait-board/drawnix"
  exit 1
fi

Each check prints ok: or FAIL:. The script exits non-zero if anything failed, so it composes cleanly into agent loops (./verify.sh || regenerate-and-retry).

</details>

TL;DR

Drawnix is an open-source, all-in-one whiteboard SaaS tool built on the Plait drawing framework that supports mind maps, flowcharts, freehand drawing, and mermaid/markdown-to-diagram conversion. It's a production-grade web application (apps/web) combining React, TypeScript, and the @plait/* plugin ecosystem to deliver a feature-complete canvas editor with auto-save, undo/redo, theming, and export to PNG/JSON. NX monorepo with apps/web (React SPA entry point at apps/web/src/main.tsx, Vite build) and apps/web-e2e (Playwright e2e tests). No libs/ folder visible, so plugins are consumed as external npm packages (@plait/mind, @plait/draw, etc.). State likely flows through React hooks (no Redux in deps) + @plait/core's canvas model. SCSS modules (44k+ lines) handle theming and dark mode.

Who it's for

Knowledge workers and product teams (like PingCode Wiki users) who need a free, open-source alternative to proprietary whiteboard tools like Miro or Figma, plus developers wanting to understand or extend plugin-based architecture for diagramming applications.

Maturity & risk

Actively maintained and production-ready. The monorepo is well-structured with CI/CD (apps/web-e2e with Playwright, .github/workflows/), published to npm as v0.0.2, and integrates mature dependencies (@plait/core v0.93.1, React 19.2.0). However, the version number (0.0.2) suggests it's still in active early-release development rather than a stable 1.0+.

Low-to-moderate production risk: single primary maintainer (plait-board org), growing but modest dependency surface (~20 core @plait/* packages), and the plugin architecture adds complexity vs. monolithic alternatives. No visible breaking-change warnings in CHANGELOG.md preview, but the 0.0.x versioning indicates API stability is not guaranteed. TypeScript coverage is strong (402k+ lines), mitigating type-related bugs.

Active areas of work

Ecosystem expansion: recently added markdown-to-drawnix and mermaid-to-drawnix converters (visible in deps). CI runs on push (ci.yml) with linting and tests. Publish workflow automates npm releases. Based on feature set in README, focus is on adoption (mobile adaptation, plugin extensibility) rather than fundamental new capabilities.

Get running

git clone https://github.com/plait-board/drawnix.git
cd drawnix
npm install
npm start

The dev server starts at http://localhost:4200 (NX default for web app). Build with npm run build:web.

Daily commands:

npm start              # Dev server on http://0.0.0.0:4200
npm run build:web     # Production build
npm test              # Run Jest tests
npm run lint -- --fix # ESLint fix

For e2e: npx playwright test (apps/web-e2e). Docker: docker build -t drawnix . (Dockerfile present).

Map of the codebase

  • apps/web/src/main.tsx — Application entry point where React is mounted and the main app component is rendered.
  • apps/web/src/app/app.tsx — Root application component that orchestrates the whiteboard UI and integrates all core modules.
  • packages/drawnix/package.json — Core drawnix package definition with dependencies on @plait board plugins (mind, draw, layouts).
  • nx.json — Nx monorepo configuration defining workspace structure, build targets, and task execution.
  • apps/web/vite.config.ts — Vite bundler configuration for development and production builds of the web application.
  • package.json — Root workspace package.json with release and publish scripts; defines all shared dependencies.
  • apps/web/tsconfig.json — TypeScript compiler configuration for the web application, including path aliases and strict type checking.

How to make changes

Add a new toolbar button or tool

  1. Create a new tool button component in packages/drawnix/src/components/ (e.g., my-tool-button.tsx) that exports a React component. (packages/drawnix/src/components/tool-button.tsx)
  2. Add the button to the main toolbar by importing and registering it in app-toolbar.tsx menu items. (packages/drawnix/src/components/toolbar/app-toolbar/app-toolbar.tsx)
  3. If the tool needs menu options, create a corresponding menu item in packages/drawnix/src/components/menu/ or extend app-menu-items.tsx. (packages/drawnix/src/components/toolbar/app-toolbar/app-menu-items.tsx)
  4. Wire up the tool's action handler to interact with @plait/core canvas or shape plugins. (apps/web/src/app/app.tsx)

Add a new color picker or styling control

  1. Create a new picker component in packages/drawnix/src/components/ (e.g., stroke-style-picker.tsx) following the color-picker.tsx pattern. (packages/drawnix/src/components/color-picker.tsx)
  2. Add styling SCSS in the same folder (e.g., stroke-style-picker.scss) with consistent class naming. (packages/drawnix/src/components/color-picker.scss)
  3. Integrate the picker into the toolbar's control section via app-toolbar.tsx, ensuring it updates selected shapes. (packages/drawnix/src/components/toolbar/app-toolbar/app-toolbar.tsx)

Add a new dialog or modal confirmation

  1. Create a new dialog component in packages/drawnix/src/components/dialog/ (e.g., confirm-action-dialog.tsx), extending or copying dialog.tsx structure. (packages/drawnix/src/components/dialog/dialog.tsx)
  2. Add corresponding SCSS styling in the same directory for layout and theming. (packages/drawnix/src/components/dialog/dialog.scss)
  3. Trigger the dialog from app.tsx or relevant component state, passing callbacks for confirm/cancel actions. (apps/web/src/app/app.tsx)

Publish a new version of the drawnix package

  1. Update the version in packages/drawnix/package.json following semantic versioning. (packages/drawnix/package.json)
  2. Run npm run release from the root to update version strings and generate changelog. (package.json)
  3. Commit changes and push to develop. GitHub Actions (publish.yml) will build and publish to npm. (.github/workflows/publish.yml)

Why these technologies

  • React + TypeScript — Provides type-safe component composition for complex UI state (toolbars, pickers, dialogs) with familiar ecosystem.
  • Nx Monorepo — Enables code sharing between web app and publishable drawnix package; manages build/test/lint tasks across multiple apps with efficient caching.
  • @plait/core + plugins (@plait/draw, @plait/mind, @plait/layouts) — Abstracts canvas rendering, shape management, and multi-diagram-type support; allows mixing mind maps, flowcharts, and freehand drawing in one workspace.
  • Vite + TypeScript — Fast development server with HMR and optimized production builds; native ESM support reduces bundling complexity.
  • Playwright E2E tests — Automates browser-based testing of interactive canvas workflows without depending on specific DOM selectors; validates user flows across diagram types.
  • GitHub Actions CI/CD — Automates linting, testing, and multi-platform builds; triggers npm publish on version tags for drawnix package distribution.

Trade-offs already made

  • Single monorepo with separate web app + drawnix package

    • Why: Enables rapid prototyping of new features in the web app while publishing a stable, reusable component library for external use.
    • Consequence: Adds complexity to build/publish workflows; requires care to avoid circular dependencies and version mismatches.
  • Depend on external @plait/ packages for canvas & plugins*

    • Why: Avoids reinventing canvas rendering, shape management, and multi-diagram-type support; leverages battle-tested abstractions.
    • Consequence: Less control over low-level rendering; coupled to @plait package release cycles and API stability.
  • Use SCSS for component styling instead of CSS-in

    • Why: undefined
    • Consequence: undefined

Traps & gotchas

No hard env var requirements are documented in the provided files, but be aware: (1) The npm start command binds to 0.0.0.0 (all interfaces), which may conflict in restricted network environments. (2) LocalForage auto-save relies on browser's IndexedDB quota; large documents may hit limits on some browsers. (3) The Plait plugin ecosystem (@plait/core, @plait/draw, etc.) is tightly versioned (all currently 0.93.1); mixing versions can break canvas rendering. (4) Slate v0.116 (editor) is a major version; custom text plugins must follow its immutable API. (5) Mobile detection (mobile-detect) is not reactive; viewport changes after page load may not re-evaluate layouts. (6) The markdown-to-drawnix and mermaid-to-drawnix converters are separate npm packages—they must be explicitly imported if used.

Architecture

Concepts to learn

  • Plugin Architecture — Drawnix's entire feature set (@plait/mind, @plait/draw, @plait/text-plugins) is built as composable plugins; understanding this pattern is critical to extending the tool or contributing new shapes/behaviors
  • Infinite Canvas — The whiteboard allows unbounded panning, zooming, and drawing; requires efficient spatial indexing and viewport culling to avoid rendering the entire document at once
  • CRDT (Conflict-free Replicated Data Type) — Drawnix's document model likely uses or can be extended with CRDT principles for collaborative real-time editing; understanding this enables adding multiplayer features
  • Immutable Slate Editor — The rich-text editor (Slate v0.116) uses immutable data structures and controlled re-renders; this differs from traditional DOM mutation and requires a different debugging/testing mindset
  • Canvas Transformation Matrix — The drawing engine uses matrix math for zoom, pan, and shape rotation; understanding affine transformations (scale, translate, rotate) is essential for debugging rendering bugs or custom tool interactions
  • IndexedDB with localforage Abstraction — Auto-save persists documents to IndexedDB via the localforage library; understanding quota limits, async batch operations, and migration strategies is important for storage-related features
  • Monorepo with NX — Drawnix uses NX for task orchestration across apps/ (web, web-e2e) and manages shared dependencies; NX commands (nx serve, nx build, nx run-many) are the workflow for development and CI

Related repos

  • plait-board/plait — The underlying drawing framework and plugin system that powers Drawnix; contains @plait/core, @plait/mind, @plait/draw packages
  • excalidraw/excalidraw — Major open-source whiteboard alternative with similar freehand/shape drawing, but without the mind-map/flowchart focus; useful for feature inspiration and community comparison
  • mermaid-js/mermaid — The diagram-as-code syntax that Drawnix converts to visual flowcharts via @plait-board/mermaid-to-drawnix
  • PingCode/wiki — PingCode Wiki is the commercial product for which Drawnix's underlying Plait framework was developed; shows real-world deployment of the same technology stack
  • tldraw/tldraw — Another React-based whiteboard framework; different architectural approach (canvas-first) vs. Plait's plugin-first design, useful for learning trade-offs

PR ideas

To work on one of these in Claude Code or Cursor, paste: Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.

Add E2E tests for core whiteboard features in web-e2e

The web-e2e folder only contains a single example.spec.ts file. Given that Drawnix is a complex whiteboard tool with multiple features (mind maps, flowcharts, freehand drawing), there are no E2E tests validating critical user workflows. Adding comprehensive Playwright tests would catch regressions early and improve confidence in releases.

  • [ ] Create apps/web-e2e/src/mind-map.spec.ts testing mind map creation, node addition, and deletion
  • [ ] Create apps/web-e2e/src/flowchart.spec.ts testing flowchart drawing and connection workflows
  • [ ] Create apps/web-e2e/src/drawing.spec.ts testing freehand drawing and eraser tools
  • [ ] Create apps/web-e2e/src/export.spec.ts testing export functionality mentioned in public assets
  • [ ] Update apps/web-e2e/playwright.config.ts if needed to add new test configuration

Add unit tests for color-picker and component utilities

The packages/drawnix/src/components/ directory contains multiple UI components (arrow-mark-picker.tsx, arrow-picker.tsx, color-picker.scss) but there are no visible .spec.ts test files for these components. These are critical UI interactions that should have unit test coverage to prevent regressions in color/arrow selection features.

  • [ ] Create packages/drawnix/src/components/color-picker.spec.tsx with tests for color selection, palette rendering, and color persistence
  • [ ] Create packages/drawnix/src/components/arrow-picker.spec.tsx testing arrow style selection and preview
  • [ ] Create packages/drawnix/src/components/arrow-mark-picker.spec.tsx testing arrow marker selection
  • [ ] Update packages/drawnix/jest.config.ts if needed to ensure proper coverage reporting
  • [ ] Ensure tests use @testing-library/react as shown in devDependencies

Add Dockerfile health check and optimize build layers

The Dockerfile exists but lacks a HEALTHCHECK instruction, which is important for container orchestration and monitoring in production SaaS deployments. Additionally, the monorepo structure with nx suggests the build could be optimized by separating dependency installation and caching layers more effectively.

  • [ ] Review current Dockerfile and add HEALTHCHECK instruction targeting the health endpoint (likely /health or similar)
  • [ ] Restructure Dockerfile build layers to leverage Docker layer caching: separate package installation from source code copying
  • [ ] Add multi-stage build if not present to separate build dependencies from runtime dependencies
  • [ ] Test Dockerfile locally using: docker build -t drawnix:test . && docker run --health-cmd='...' drawnix:test
  • [ ] Document in CFPAGE-DEPLOY.md or create DOCKER.md with deployment best practices for the SaaS platform

Good first issues

  • Add unit tests for the Slate text plugin integration in apps/web (currently no tests visible in jest.config.ts for text handling); mock the @plait/text-plugins API and test undo/redo, copy/paste within text nodes.
  • Implement a 'Recent Files' sidebar feature by extending localforage queries to track last-opened documents and their metadata (title, thumbnail, modified date); wire the UI in app.tsx and add a localStorage migration script for existing users.
  • Document the plugin API in README_en.md by extracting jsdoc from @plait/core exports and creating a 'Custom Plugin Guide' with a runnable example of adding a custom shape tool (e.g., a star or callout box) that can be published as an npm package.

Top contributors

Recent commits

  • e28ba80 — fix: fix break changes after bump @plait/core@0.93.1 (#408) (pubuzhixing8)
  • 66e418a — refactor: remove open-color dependency and replace color variables with hex values (#404) (lurenyang418)
  • f99ca10 — fix(publish): streamline image tag handling by setting tag without 'v' prefix (#401) (lurenyang418)
  • 64e5411 — fix(freehand): improve white preset contrast in dark theme #397 (#399) (nightt5879)
  • e2844f1 — build: add workflow_dispatch (pubuzhixing8)
  • 8ebe650 — build: release 0.4.0 (pubuzhixing8)
  • f806681 — build: bump plait into 0.93.1 (#398) (pubuzhixing8)
  • b808b08 — ci: update base image and github action (#396) (lurenyang418)
  • e6993b0 — feat(copy-clipboard): 新增复制到剪贴板功能(SVG / PNG) (#395) (nightt5879)
  • 14f37bb — fix(size-slider): stop handled key propagation (#391) (nightt5879)

Security observations

  • High · Multi-stage Docker Build Exposes Build Dependencies — Dockerfile (line 1-12). The Dockerfile uses a multi-stage build but the builder stage has no resource limits or security constraints. The intermediate builder image could potentially be exploited if the registry is compromised, and build artifacts may contain sensitive information. Fix: Add security best practices: use specific Node.js version tags (not just 'node:20'), add --no-cache flag, implement minimal final image, remove build tools from final stage (already done), and consider using Docker BuildKit with secrets management.
  • High · Overly Permissive Server Binding — package.json (scripts.start). The start script binds to 0.0.0.0 with 'nx serve web --host=0.0.0.0', exposing the development server to all network interfaces. This is inappropriate for production and development environments. Fix: Bind to localhost (127.0.0.1) for development. For production, use proper environment-based configuration. Update to: 'nx serve web --host=127.0.0.1'
  • High · Inadequate Vulnerability Reporting Process — SECURITY.md. The SECURITY.md file relies solely on Discord for vulnerability reporting, which lacks formal security incident handling. No dedicated security contact email, no public key for encrypted communication, and no defined SLA for response. Fix: Implement a proper vulnerability disclosure policy: add security contact email, establish response SLA, provide PGP key for encrypted submissions, consider using platforms like HackerOne or implement a security.txt file (/.well-known/security.txt).
  • Medium · Missing Security Headers Configuration — Dockerfile (httpd.conf reference) and /home/static/httpd.conf (not provided). The Dockerfile uses a static website server (lipanski/docker-static-website) with default httpd.conf. No evidence of security headers (CSP, X-Frame-Options, X-Content-Type-Options, etc.) being configured. Fix: Configure httpd.conf with security headers: Content-Security-Policy, X-Frame-Options: DENY, X-Content-Type-Options: nosniff, Strict-Transport-Security, X-XSS-Protection.
  • Medium · Dangerously Rendered Content Potential — packages/drawnix/src/components/ (markdown/mermaid converters not visible in provided structure). The codebase includes components for markdown-to-drawnix and mermaid-to-drawnix conversion (@plait-board/markdown-to-drawnix, @plait-board/mermaid-to-drawnix). Without visible sanitization in the component structure, user-provided markdown/mermaid could lead to XSS attacks. Fix: Ensure all user input from markdown and mermaid sources is properly sanitized. Use DOMPurify or similar libraries. Implement Content Security Policy. Validate and escape all rendered content.
  • Medium · React 19 with Potential Unsafe Patterns — packages/drawnix/src/components/. Project uses React 19.2.0. While modern, the codebase includes dangerouslySetInnerHTML-prone components (color-picker, dialog, menu) where user input handling isn't visible in provided structure. Fix: Audit all React components for dangerouslySetInnerHTML usage. Implement strict input validation and sanitization. Use modern React patterns that avoid direct DOM manipulation.
  • Medium · Unspecified Dependency Versions in package.json — package.json (dependencies and devDependencies). Several dependencies use caret (^) and tilde (~) versions, allowing automatic updates to minor and patch versions which could introduce security vulnerabilities without explicit review. Fix: Use exact version pinning for production builds (remove ^ and ~). Implement automated dependency scanning with tools like npm audit, Dependabot, or Snyk. Establish a process for regular security updates.
  • Medium · No Visible Environment Variable Sanitization — project root (missing .env.example or docs). No .env files or environment configuration visible in the structure. If environment variables are used at runtime (common in whiteboard SaaS), there's no evidence of secure handling. Fix: undefined

LLM-derived; treat as a starting point, not a security audit.

Where to read next


Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.

Healthy signals · plait-board/drawnix — RepoPilot