graphcode-editor
v0.1.0
Published
GraphCode — visual-to-code editor for NestJS, React, and TaroJS
Maintainers
Readme
GraphCode Editor
A visual, zero-code development editor — draw a logic graph, get production-grade code. Supports graph ⇄ code real-time bidirectional sync. Currently ships NestJS code generation; React and TaroJS are on the roadmap.
GraphCode Editor is a visual programming tool for backend developers. Drag nodes, wire relationships, edit properties on a canvas, and the engine generates componentized, modularized code that reads like a senior engineer wrote it. Edit the code and the graph updates back — both directions stay in sync.
It works three ways:
- React component — drop
<GraphCodeEditor />into any React app. - Headless core —
graphcode-editor/corefor code generation, IR, sync, and templates with no React / Monaco / CSS (~1.9 KB). - CLI —
graphcode create | convert | servefor scaffolding and offline code generation.
✨ Features
- 🎨 Pro-grade canvas — React Flow powered: alignment guides, grid snapping, multi-select, zoom/pan, MiniMap with real node-measured sizing and adaptive breakpoints.
- 🔄 Real-time bidirectional sync — graph ⇄ code, 800 ms debounce. Sync failures raise a Toast and never corrupt current state.
- 🧠 Smart codegen — auto-detects dependencies, injects services, wires modules. Componentized, modularized, shared-logic extraction.
- 🤖 AI natural-language generation — any OpenAI-compatible LLM (OpenAI / DeepSeek / GLM / Qwen / Moonshot / Ollama). Three auto-detected modes: subgraph / node-edit / function body. Streaming responses, one-click inject to canvas.
- 🌐 Production-grade API Request node — 6 auth schemes (Bearer / Basic / API Key / OAuth2), 6 body encodings (JSON / Form / XML / Raw / DTO ref), retry, cache, multi-method client. Emits
@nestjs/axios+ RxJS code. - 🧩 Custom nodes & community section — pass
customNodesprops (or callregisterNodeType()). Custom nodes flow through canvas, property panel, and codegen automatically. Supports custom render components, custom icons, readonly display nodes. - 🗂️ Multi-module canvas — one canvas = one NestJS Module. Figma-style module tabs, drag-in-to-create, per-module node/edge filtering.
- 🔧 Function node dual-mode —
pure-ts(standalone exported function) ornestjs(@Injectable()class with DI). - 📑 Template library — sidebar Tab (node library / template library) with 3-tab preview (Nodes / Logic flow / Generated code) before import.
- 🏗️ VS Code-style dockable layout —
dockview-reactpanels, draggable splits, persisted tolocalStorageand restored on reload. - 📝 Monaco editor — the same engine as VS Code. Lazy-loaded: the ~4.7 MB Monaco chunk is only fetched the first time you open the code pane.
- 🌍 i18n —
zh-CNandenout of the box; persisted, browser-detected, switchable at runtime. - 🎨 Themes — light/dark, CSS-variable design system.
- ↩️ Undo/redo (50 steps), 🔍 node search, 📤 JSON import/export, ⌨️ Figma-style shortcuts.
- 📦 NPM-ready — ES + UMD dual format, TypeScript
.d.tsdeclarations,sideEffects-aware,exportsmap with a./coresubpath. - 🛡️ Production-hardened —
ErrorBoundary+SafeGraphCodeEditorfallback, CI/CD, unit tests with coverage.
📦 Installation
npm install graphcode-editor
# or
pnpm add graphcode-editor
# or
yarn add graphcode-editorGraphCode declares its React-centric stack as peer dependencies so you control versions. If they aren't already in your project, install them once:
npm install react react-dom @xyflow/react zustand i18next react-i18next i18next-browser-languagedetectorRequires Node ≥ 20 (see
.nvmrc).
🚀 Quick start
1. Full UI — the all-in-one component
GraphCodeEditor is a ready-to-use whole editor (toolbar + node library + canvas + code editor + property panel + status bar + toasts). Just give it a sized parent.
import { GraphCodeEditor } from 'graphcode-editor';
import 'graphcode-editor/dist/style.css';
export default function App() {
return (
<div style={{ width: '100vw', height: '100vh' }}>
<GraphCodeEditor />
</div>
);
}📖 Full example code is shipped with the package as example.tsx — 6 integration modes: minimal, custom nodes, theme switch, programmatic API, dynamic nodes, imperative registration.
2. With custom nodes (community section)
Pass customNodes to make nodes appear under a Community category (the category string is arbitrary — the palette auto-creates it). Custom nodes integrate into the canvas, property panel, and code generator:
import { GraphCodeEditor, type CustomNodeDefinition } from 'graphcode-editor';
import 'graphcode-editor/dist/style.css';
const customNodes: CustomNodeDefinition[] = [
{
type: 'redis-cache',
label: 'Redis Cache',
category: 'Community',
color: '#dc2626',
icon: 'Database',
description: 'Redis cache service with TTL',
defaultProperties: { ttl: 3600, host: 'localhost' },
propertyFields: [
{ key: 'host', label: 'Host', type: 'text', defaultValue: 'localhost' },
{ key: 'ttl', label: 'TTL (s)', type: 'number', defaultValue: 3600 },
],
generator: (node) => ({
id: `redis-${node.id}`,
name: `${node.name}.redis.ts`,
path: `cache/${node.name}.redis.ts`,
language: 'typescript',
content: `@Injectable()\nexport class ${node.name} {\n // Redis cache\n}\n`,
}),
},
// Read-only display node (no codegen): omit `generator` and set readOnly: true
{
type: 'weather-api',
label: 'Weather API',
category: 'Community',
color: '#0ea5e9',
icon: 'Cloud',
readOnly: true,
defaultProperties: { endpoint: 'https://api.weather.com' },
propertyFields: [{ key: 'endpoint', label: 'Endpoint', type: 'text' }],
},
];
export default function App() {
return (
<div style={{ width: '100vw', height: '100vh' }}>
<GraphCodeEditor customNodes={customNodes} />
</div>
);
}📖 Full field reference and more examples (custom render component, custom icon, imperative API) in the Usage Guide.
3. Headless core — no UI, no React, no Monaco
If you only need IR construction, code generation, bidirectional sync, stores, templates, or the custom-node registry — for a CLI tool, server-side codegen, a custom UI wrapper, a VS Code extension, etc. — import from graphcode-editor/core. It pulls zero React / Monaco / CSS and weighs ~1.9 KB in production.
import {
useProjectStore, useSyncStore, useUIStore, useHistoryStore,
createProject, createNode, generateCode,
syncGraphToCode, syncCodeToGraph,
instantiateTemplate, startupTemplates,
registerNodeType, registerIcon, getCustomNodeType,
applyTheme, toggleTheme,
} from 'graphcode-editor/core';
// Example 1: instantiate a template + generate code (no UI at all)
const project = instantiateTemplate(startupTemplates[0]); // REST API starter
const files = generateCode(project); // [{ id, name, content }, ...]
// Example 2: reuse zustand stores inside your own React host
function MyCustomViewer() {
const { nodes, connections } = useProjectStore((s) => ({
nodes: s.project.nodes, connections: s.project.connections,
}));
return <GraphOfYourChoice nodes={nodes} edges={connections} />;
}💡 Why the size difference? The full UI entry bundles Monaco Editor for the code pane — even if you never open it, Monaco loads on first paint (~4.7 MB gzipped). Two optimizations fix this:
./coresubpath — pure-logic consumers bypass all UI deps, ~1.9 KB.- Monaco lazy-load — in the full UI entry, Monaco is fetched via dynamic
import()only when the code pane is first opened (with a spinner placeholder).Combined, a typical "draw-only, never touch code" session drops first-screen payload from ~17 MB to ~1 MB (17× smaller).
🖥️ CLI
The package ships a graphcode binary (configured via the bin field in package.json). After installing, run any of:
# Scaffold a new project from a template (NestJS / React / TaroJS)
graphcode create my-app
graphcode create my-app --framework react --template react-basic
# Convert a GraphCode project JSON into code files (no editor launched)
graphcode convert ./project.json ./out
# Launch the interactive Playground editor (Vite dev server)
graphcode serve --port 5173
graphcode --version
graphcode --help| Command | Description |
|---------|-------------|
| create <name> | Interactive scaffolder. --framework nestjs\|react\|tarojs, --template <id>. Writes package.json, .gitignore, README.md, and starter source files. |
| convert <input.json> <outdir> | Reads a GraphCode project JSON and writes generated code files to <outdir>. Pure Node, no editor. |
| serve [--port <num>] | Starts the bundled Playground (Vite, vite.config.playground.ts) at http://localhost:<port>. |
📚 API & Exports
The package exposes two entry points. Below is a categorized overview — see docs/api-reference.md for full signatures.
Main entry — graphcode-editor (full UI)
| Category | Exports |
|----------|---------|
| Components | GraphCodeEditor, ErrorBoundary, SafeGraphCodeEditor, Toolbar, NodePalette, GraphEditor, CodeEditor, PropertyPanel, ContextMenu, SearchPanel, StatusBar, Toast, LanguageSwitcher, SettingsPanel |
| Common UI | Button, Input, Select |
| Stores | useProjectStore, useUIStore, useHistoryStore, useSyncStore |
| IR types | IRNode, IRNodeType, IRConnection, IRProject |
| IR builders | createProject, createModuleNode, createControllerNode, createServiceNode, createDtoNode, createEntityNode, createFunctionNode, createClassNode, createInterfaceNode, createEnumNode, createMiddlewareNode, createGuardNode, createDecoratorNode, createComponentNode, createHookNode, createRouteNode, createApiRequestNode, createConnection |
| IR constants | nodeColors, nodeIcons, httpMethodColors, typeScriptTypes, nestJsDecorators |
| Sync | syncGraphToCode, syncCodeToGraph, detectConflicts |
| Generator | generateCode |
| Layout | findAlignmentLines, snapToGrid, snapToLines, alignNodes, calculateNodePositions |
| Registry | registerNodeType, registerNodeTypes, unregisterNodeType, getCustomNodeType, getAllCustomNodeTypes, isCustomNodeType, getNodeTypeMeta, getNodeIcon, getNodeColor, getNodeDefaultProperties, generateCustomNodeCode, useRegistryVersion, getIcon, registerIcon, getAvailableIconNames |
| Registry types | CustomNodeDefinition, CustomPropertyField, NodeTypeMeta |
| Theme | applyTheme, toggleTheme, getStoredTheme |
| i18n | i18n (default), SUPPORTED_LANGUAGES, LanguageCode |
| Canvas export | useExportCanvas, ExportCanvasOptions |
| Monaco | setupMonaco (manual eager init) |
Subpath — graphcode-editor/core (headless)
Everything above except React components, Monaco, and common UI — plus:
| Category | Exports |
|----------|---------|
| Templates | startupTemplates, instantiateTemplate; types StartupTemplate, ProjectTemplate |
| AI (pure logic) | DEFAULT_AI_CONFIG, MAX_SUBGRAPH_NODES, streamChatCompletion, parseAIOutput, sanitizeTemplate, extractCodeBlock, buildSystemPrompt, FULL_SCHEMA_DOC, useAIStore, isAIConfigured; types AIConfig, AIChatMessage, AIMode, AIGenResult, AIContext, AIStreamCallbacks |
🎨 Theming & 🌍 i18n
import { applyTheme, toggleTheme, getStoredTheme, i18n } from 'graphcode-editor';
// Theme
applyTheme('dark');
toggleTheme(); // flips light ↔ dark, persisted to localStorage
const current = getStoredTheme();
// i18n — zh-CN and en ship built-in
i18n.changeLanguage('en');- Theme is driven by CSS variables; both light and dark are first-class.
- Language preference is persisted and browser-detected (order:
localStorage→navigator→htmlTag→querystring); fallbackzh-CN. Only UI strings are translated — user data (node names, method names) is untouched. - Use the built-in
<LanguageSwitcher />component for a ready-made switcher.
🛠️ Tech stack
| Category | Tech | Version | |----------|------|---------| | Language | TypeScript | ^5.3 | | UI framework | React | ^18 | | Graph canvas | @xyflow/react | ^12 | | Code editor | @monaco-editor/react | ^4.6 (Monaco = VS Code's engine) | | State | Zustand | ^4.5 | | Styling | TailwindCSS | ^3.4 | | Dockable layout | dockview-react | ^8 | | i18n | i18next + react-i18next | ^26 / ^17 | | Icons | Lucide React | ^0.292 | | Build | Vite | ^5 |
📁 Project structure
graphcode-editor/
├── src/
│ ├── components/ # UI components
│ │ ├── common/ # UI primitives (Button / Input / Select / LanguageSwitcher)
│ │ ├── GraphEditor/ # React Flow canvas + CustomNodes + CustomEdges + MiniFlowThumbnail
│ │ ├── CodeEditor/ # Monaco editor (lazy-loaded, 800 ms debounced sync)
│ │ ├── PropertyPanel/ # Property editor (universal dropdowns, safe sync)
│ │ ├── NodePalette/ # Node library / template library dual-Tab
│ │ ├── TemplateLibrary/ # Template 3-tab preview (nodes / logic / code)
│ │ ├── DockviewLayout/ # VS Code-style customizable dock panels
│ │ ├── ModuleTabBar/ # Figma-style multi-module tabs
│ │ ├── FunctionModeModal/ # pure-ts / nestjs mode picker
│ │ ├── AIPanel/ # Natural-language generation panel
│ │ ├── SettingsPanel/ # Settings
│ │ ├── TesterPanel/ # Node testing
│ │ ├── FileExplorer/ # File tree
│ │ ├── NewProjectModal/ # Onboarding / template picker
│ │ ├── Toolbar / StatusBar / ContextMenu / SearchPanel / Toast
│ │ ├── ErrorBoundary / SafeCodeZeroEditor
│ ├── core/ # Pure-logic core (no React)
│ │ ├── ir/ # Intermediate Representation (types / builder / validator)
│ │ ├── generator/ # NestJS codegen (module/controller/service/dto/entity/function/api-request)
│ │ ├── parser/ # NestJS code parser (reverse: code → graph)
│ │ ├── analyzer/ # Duplicate detection / component extraction / module optimization
│ │ ├── sync/ # Bidirectional sync engine (graphToCode / codeToGraph / conflictDetector)
│ │ ├── registry/ # Custom node + icon registry (dual-layer)
│ │ ├── layout/ # Alignment guides / auto-layout / grid snap
│ │ ├── templates/ # Built-in starter templates
│ │ └── ai/ # AI natural-language generation (schema / promptBuilder / parser / provider)
│ ├── store/ # Zustand stores + persist (project / ui / history / sync / ai)
│ ├── i18n/ # i18next init + locales (zh-CN, en)
│ ├── styles/ # Design system (reset / CSS vars / theme)
│ ├── hooks/ # useExportCanvas etc.
│ ├── cli/ # `graphcode` CLI (create / convert / serve)
│ ├── App.tsx # GraphCodeEditor main component
│ ├── main.tsx # Playground entry
│ ├── index.ts # NPM main entry (UI + logic + types)
│ ├── core.ts # NPM `./core` subpath entry (headless)
│ └── index.css # Global styles + Tailwind tokens
├── docs/ # Documentation (see below)
├── example.tsx # 6 shipped integration examples
├── package.json # Package config (ES + UMD + d.ts, exports map, bin)
├── vite.config.ts # Library build (ES + UMD + d.ts)
├── vite.config.playground.ts # Playground build (manual chunks)
├── tsconfig.json / tailwind.config.js / vercel.json / .nvmrc
└── .github/workflows/ # ci.yml + release.yml📖 Documentation
- Architecture — system design, IR model, sync mechanism
- API Reference — core type and function signatures
- Usage Guide — in-depth tutorial (install, custom nodes, programmatic API, FAQ)
- Feature Log — full implementation history
- Production Readiness — audit + fixes (entry points, Monaco workers, error boundaries)
- AGENT.md — AI-agent collaboration guide for contributors
🔧 Local development
git clone <repository-url>
cd graphcode-editor
pnpm install
pnpm dev # dev server (Playground)
pnpm build # library production build → dist/ (ES + UMD + d.ts + core + style.css)
pnpm build:playground # static Playground site → dist-playground/ (for Vercel etc.)
pnpm typecheck # tsc --noEmit
pnpm lint # ESLint
pnpm test # vitest run
pnpm test:watch # vitest watch mode
pnpm test:coverage # coverage report → coverage/Build outputs
| File | Format | Purpose |
|------|--------|---------|
| dist/index.es.js | ES Module | Main entry — full UI |
| dist/index.umd.js | UMD | Main entry — full UI (CDN / require) |
| dist/index.d.ts | TypeScript | Main entry type declarations |
| dist/core.es.js | ES Module | ./core subpath — headless logic |
| dist/core.d.ts | TypeScript | ./core type declarations |
| dist/style.css | CSS | Styles (the only declared side effect) |
🚀 CI/CD & deployment
- CI (
.github/workflows/ci.yml) — on push / PR:lint → typecheck → test:coverage → build, uploads coverage and build artifacts. Concurrency cancels superseded runs. - Release (
.github/workflows/release.yml) — on pushing av*tag: runs the full gate, publishes to npm (needsNPM_TOKENsecret), creates a GitHub Release with auto notes. - Playground deploy —
vercel.jsonis preconfigured (build:pnpm build:playground, output:dist-playground). Import the repo into Vercel for one-click deploy; or hostdist-playground/on any static host (Netlify, GitHub Pages). Main bundle ~329 KB (87 KB gzip); Monaco language workers load on demand.
📦 Publishing
pnpm build # builds dist/ (prepublishOnly runs this automatically)
npm publish # or: npm publish --access publicprepublishOnly runs npm run build for you. The files field ships only dist/, example.tsx, README.md, and LICENSE.
🤝 Contributing
- Fork → branch (
git checkout -b feature/AmazingFeature) - Follow existing code style; run
pnpm lint && pnpm typecheck && pnpm test - Every significant change updates docs (see AGENT.md) and docs/feature-log.md
- Open a Pull Request
📄 License
MIT — see LICENSE.
🔗 Related
- React Flow · Monaco Editor · NestJS · Zustand · dockview
📋 Changelog
[0.1.0] — 2026-08-19 — First public npm release
First npm publication. Bundles the full visual-to-code editor, headless core, and CLI.
Added
- 🎨 React Flow canvas with alignment guides, grid snap, multi-select, zoom/pan, adaptive MiniMap.
- 🔄 Real-time graph ⇄ code bidirectional sync (800 ms debounce, non-destructive on failure).
- 🧠 Smart NestJS codegen — Module / Controller / Service / DTO / Entity / Function / API Request, with dependency injection and module wiring.
- 🤖 AI natural-language generation for any OpenAI-compatible LLM — subgraph / node-edit / function-body modes, streaming inject.
- 🌐 Production-grade API Request node — 6 auth schemes, 6 body encodings, retry, cache, multi-method client.
- 🧩 Custom nodes & community section via
customNodesprops orregisterNodeType(). - 🗂️ Multi-module canvas with Figma-style module tabs.
- 🔧 Function node dual-mode (
pure-ts/nestjs). - 📑 Template library with 3-tab preview (nodes / logic / code).
- 🏗️ VS Code-style dockable layout (
dockview-react) persisted tolocalStorage. - 📝 Monaco editor (lazy-loaded on first code-pane open).
- 🌍 i18n (
zh-CN,en), 🎨 light/dark themes. - ↩️ Undo/redo (50 steps), node search, JSON import/export, Figma-style shortcuts.
- 🖥️
graphcodeCLI —create/convert/serve. - 📦 NPM packaging: ES + UMD dual format,
.d.tsdeclarations,exportsmap with./coresubpath,sideEffects-aware. - 🛡️
ErrorBoundary+SafeGraphCodeEditorfallback, CI/CD (lint → typecheck → test → build → release), unit tests with coverage.
Pre-release development history (internal versions 0.0.1 → 0.11.0) is recorded in docs/feature-log.md.
