@boundaryboard/renderer
v1.0.1
Published
Interactive Domain Model DSL diagram renderer with React Flow. Create and edit DDD diagrams with a visual canvas.
Maintainers
Readme
@boundaryboard/renderer
Interactive Domain Model DSL diagram renderer with React Flow. Create and edit DDD (Domain-Driven Design) diagrams with a visual canvas.
Features
- DSL-Based: Define diagrams using a simple, human-readable DSL
- Interactive Canvas: Pan, zoom, and navigate diagrams
- Optional Editing: Enable node editing, adding, and deletion
- Multiple Node Types: Entity, Value Object, Domain Event, Aggregate, Bounded Context, and more
- Relationship Mapping: Visualize relationships between domain elements
- Export: Export diagrams as SVG
- Standalone or React: Use as a script tag or React component
Installation
npm install @boundaryboard/renderer
# or
yarn add @boundaryboard/renderer
# or
pnpm add @boundaryboard/rendererQuick Start
React Component (Recommended)
import { EditableBoundaryBoardCanvas } from '@boundaryboard/renderer';
import '@boundaryboard/renderer/styles.css';
const dsl = `
domainModel "Order Management" {
context OrderContext {
entity Order {
attributes {
id: string
status: OrderStatus
}
}
valueObject Money {
attributes {
amount: number
currency: string
}
}
event OrderPlaced {
attributes {
orderId: string
}
}
}
relationships {
Order -> Money {}
}
}
`;
function DiagramViewer() {
return (
<div style={{ width: '100%', height: '600px' }}>
<EditableBoundaryBoardCanvas
dsl={dsl}
showGrid={true}
showControls={true}
/>
</div>
);
}Editable Canvas
import { useState } from 'react';
import { EditableBoundaryBoardCanvas } from '@boundaryboard/renderer';
import '@boundaryboard/renderer/styles.css';
function DiagramEditor() {
const [dsl, setDsl] = useState(initialDSL);
return (
<EditableBoundaryBoardCanvas
dsl={dsl}
onChange={(newDsl, ast) => {
setDsl(newDsl);
// Optionally persist to backend
}}
editable={true} // Enable editing
allowAdd={true} // Right-click to add nodes
allowDelete={true} // Delete button in popovers
allowEdgeEditing={true} // Edit edge labels
allowConnect={true} // Connect nodes to create edges
/>
);
}Script Tag Usage
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="https://unpkg.com/@boundaryboard/renderer/dist/boundaryboard-renderer.css">
</head>
<body>
<div id="diagram" style="width: 100%; height: 600px;"></div>
<script src="https://unpkg.com/@boundaryboard/renderer/dist/boundaryboard-renderer.standalone.js"></script>
<script>
const renderer = new BoundaryBoardRenderer.BoundaryBoardRenderer('#diagram');
renderer.render(`
domainModel "Example" {
entity Order {
attributes {
id: string
}
}
}
`);
</script>
</body>
</html>DSL Syntax
Basic Structure
domainModel "Model Name" {
// Bounded contexts
context ContextName {
// Elements...
}
// Standalone elements
entity EntityName { }
// Relationships
relationships {
Source -> Target {}
}
}Element Types
// Entity
entity Order {
description: "A customer order"
attributes {
id: string
status: OrderStatus
total: number
}
}
// Aggregate root entity
root entity Order {
attributes { id: string }
}
// Value Object
valueObject Money {
attributes {
amount: number
currency: string
}
}
// Domain Event
event OrderPlaced {
description: "Fired when order is placed"
color: "#fbbf24"
attributes {
orderId: string
timestamp: Date
}
}
// Sticky Note
stickyNote "Important" {
description: "Remember to validate input"
}
// Domain Service
domainService PricingService {
description: "Calculates prices"
}
// Repository
repository OrderRepository {
description: "Persists Order aggregates"
}
// Factory
factory OrderFactory {
description: "Creates Order instances"
}Relationships
relationships {
// Simple relationship
Order -> Customer {}
// With label
Order -> Money {
label: "has total"
}
// Context mapping
OrderContext -> PaymentContext {
label: "Upstream"
type: customer_supplier
}
}Context Mapping Types
customer_supplierconformistanticorruption_layershared_kernelpublished_languageopen_host_servicepartnershipseparate_ways
API Reference
EditableBoundaryBoardCanvas Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| dsl | string | required | DSL source code |
| onChange | (dsl: string, ast: DomainModelAST) => void | - | Callback when DSL changes |
| editable | boolean | false | Enable editing mode |
| allowAdd | boolean | false | Allow adding new nodes |
| allowDelete | boolean | false | Allow deleting nodes/edges |
| allowEdgeEditing | boolean | false | Allow editing edges |
| allowConnect | boolean | false | Allow connecting nodes |
| interactive | boolean | true | Enable pan & zoom |
| fitOnRender | boolean | true | Auto-fit diagram |
| showGrid | boolean | true | Show grid background |
| gridType | 'dots' \| 'lines' | 'dots' | Grid style |
| showControls | boolean | true | Show zoom controls |
| showMinimap | boolean | false | Show minimap |
| background | string | '#fafafa' | Background color |
Programmatic API
import {
parseDSL,
generateDSL,
calculateLayout,
convertToReactFlow
} from '@boundaryboard/renderer';
// Parse DSL to AST
const parseResult = parseDSL(dslString);
if (parseResult.errors.length === 0) {
const ast = parseResult.model;
// Calculate layout
const layout = calculateLayout(ast);
// Convert to React Flow format
const { nodes, edges } = convertToReactFlow(layout);
// Generate DSL from AST
const newDsl = generateDSL(ast, { includeLayout: true });
}Styling
The package includes default styles. Import them in your app:
import '@boundaryboard/renderer/styles.css';Or link in HTML:
<link rel="stylesheet" href="https://unpkg.com/@boundaryboard/renderer/dist/boundaryboard-renderer.css">TypeScript Support
Full TypeScript support with exported types:
import type {
DomainModelAST,
EditableBoundaryBoardCanvasProps,
NodeUpdates,
EdgeUpdates,
} from '@boundaryboard/renderer';Browser Support
- Chrome (latest)
- Firefox (latest)
- Safari (latest)
- Edge (latest)
License
MIT
Links
- BoundaryBoard - Full-featured DDD modeling platform
- GitHub - Source code
- Issues - Bug reports
