Merman: A Full-Featured Diagram Editor in a Single HTML File
#worksona#portfolio#mermaid#diagram-editor#vanilla-javascript#local-first
David OlssonWe built Merman as a complete Mermaid diagram editor that ships as one index.html file. Open it in a browser and you have a professional editing environment: a CodeMirror-based syntax editor with custom Mermaid highlighting, a live preview panel, a searchable gallery backed by IndexedDB, 11 diagram themes, and high-resolution SVG and PNG export. No build step, no npm install, no account.
The application is 41,000+ lines of vanilla JavaScript, HTML, and CSS. Every dependency โ CodeMirror, Mermaid.js 11.11.0, Dexie.js โ is embedded. It works offline except for the optional AI assistant, which connects directly from the browser to the OpenAI API without a proxy. All diagram data stays in the user's browser.
The tool supports 12 diagram types: flowcharts, sequence, class, state, entity-relationship, user journey, Gantt, pie, Git graphs, mindmaps, timelines, and Sankey diagrams. Six of the 11 themes are branded variants matching the visual language of GitHub, Slack, Spotify, Discord, Notion, and Figma.
Why single-file, local-first architecture
The alternatives impose costs that compound over time. Cloud SaaS tools store intellectual property on third-party servers, charge per seat, restrict export resolution behind paid tiers, and become unavailable during outages or pricing changes. Framework-based SPAs require a build pipeline, CDN infrastructure, and a deployment process before the first user can load the tool.
Merman's single-file design eliminates all of that. Distribution is copying or emailing a file. Deployment is placing it on any static server. Governance is straightforward: the entire application is one auditable artifact. Because all diagrams live in IndexedDB and never leave the device, there is no data sovereignty question to answer.
The tradeoff is real: a 41,000-line monolith is harder to test and maintain than a modular codebase. We made that choice deliberately, prioritising portability and zero-friction access over internal code organisation.
Traditional SPA Merman
โโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโ
npm install (none)
build & bundle (none)
deploy to CDN copy index.html
user logs in open file in browser
data on vendor server data in browser IndexedDB
How AI-assisted diagram generation works
The AI assistant accepts plain English descriptions and returns syntactically valid Mermaid code. Context-awareness means follow-up requests โ "add an error path" or "convert this to a sequence diagram" โ work against the current diagram without starting a new conversation.
The reliability of the output comes from a two-layer constraint system. First, every prompt is prefixed with MERMAID_GUIDELINES.md โ a 100+ rule domain-specific ruleset covering valid node IDs, correct use of classDef vs. style, diagram-type-specific restrictions, and common anti-patterns. This constrains the LLM to the valid solution space before generation begins.
Second, generated code passes through a preprocessing pipeline before reaching the editor. The pipeline silently fixes unambiguous deprecations, emits warnings for ambiguous patterns, and blocks known syntax errors from reaching the Mermaid rendering engine.
// Preprocessing pipeline (simplified excerpt)
function preprocessMermaidCode(code) {
// Silent auto-fix: deprecated style syntax
code = code.replace(
/style\s+(\w+)\s+fill:(#[\w]+)/g,
(_, id, color) => `classDef style_${id} fill:${color}\n${id}:::style_${id}`
);
// Silent auto-fix: single-% comments
code = code.replace(/(?<!%)%(?!%)/g, '%%');
return code;
}
The result is streamed token-by-token to the UI. When the response completes, valid code is auto-injected into the editor and recorded as a first-class entry in the 50-step undo history.
Where it applies
Merman fits anywhere diagrams are part of the work: system architecture documentation, API sequence flows, data model design, project planning with Gantt charts, and compliance process mapping. Teams with data privacy requirements benefit from the local-first model โ no diagram ever reaches a third-party server unless the user explicitly exports it.
Within the Worksona portfolio, the constrained-LLM-generation pattern demonstrated here โ domain ruleset injected into every prompt, followed by a preprocessing correction layer โ is transferable to any code generation task with well-defined syntax: SQL, GraphQL, Terraform, Kubernetes YAML.