A diagram in a README answers one question: what connects to what? An editor has to answer the next one: what can I change without breaking the rest?
That gap is why I added Mermaid import to Codelit.
translates supported Mermaid source into a graph model, calculates positions, and renders editable nodes and edges on a React canvas.
I made import converge on Codelit's existing graph model. That is the payoff: a reader can bring a diagram from their docs into the same editor used for generated architecture, instead of starting from a blank canvas.
Why not just render Mermaid in the app?
Mermaid rendering is enough when the goal is to display documentation. Codelit needs nodes with editable properties, selection state, and the same tools used by generated diagrams. Importing into the application graph makes those interactions consistent across input formats.
Mermaid is not inherently unclickable: its flowchart documentation supports links and callbacks. The distinction is an editable node-based interface, not interactivity versus no interactivity.
That is also why the React Flow canvas sits downstream of import. The editor should not need a separate implementation for every way a diagram arrives.
What does the current importer actually handle?
Codelit's current importer recognizes basic graph and flowchart input, collects nodes by ID, and extracts supported edges. It maps familiar shapes and labels into component types. It does not implement the full Mermaid grammar, so a successful parse is not evidence of complete fidelity.
This is a useful starting input:
There are five nodes here, not six. Both services refer to the same database, E. Losing that identity changes the architecture even if the picture still looks plausible.
| Input feature | What the importer must decide | Boundary to make visible |
|---|---|---|
| Node declarations | ID, label, and a component-type guess | A shape does not prove a service's role |
| Repeated node IDs | One node with multiple references | Do not silently split a shared component |
| Arrows and labels | Endpoints and relationship metadata | Unsupported arrow semantics may be lost |
| Subgraphs | Membership, nesting, and cross-group edges | Basic flowchart support is not group support |
| Styles and classes | Which presentation properties can survive | Current parsing skips styling directives |
| Other diagram families | Whether a separate grammar is needed | Sequence and class diagrams are not flowcharts |
The implementation stays small by collecting nodes in a map and passing a common architecture object downstream. That shared shape also powers repository analysis: different inputs, one editing workflow.
Where should parsing end and layout begin?
Parsing should produce a graph with stable IDs and valid connections before layout assigns any coordinates. Keeping those stages separate makes failures explainable: an absent edge is a parsing issue, while two overlapping nodes are a geometry issue.
A fuller importer has five responsibilities:
- Recognize the diagram family and supported syntax.
- Build a canonical map of nodes and edges.
- Validate references and report anything omitted.
- Translate the graph into the editor's data model.
- Calculate positions and render the result.
These are architectural boundaries, not a claim that the current lightweight parser is a complete compiler. Splitting them clearly is how I would extend it without making every new syntax case affect rendering.
How do you map a Mermaid shape to an architecture component?
Shape mapping provides a starting guess, not a reliable classifier. A cylinder often represents storage, but a rectangle could be a client, a service, or an external dependency. Keep the original label and let the user correct the inferred role.
The graph contract matters more than a clever heuristic. Codelit's prompt-to-diagram pipeline and the Mermaid importer should converge on a model the editor can validate, regardless of where the initial guess came from.
What should a round-trip test prove?
A round-trip test should compare graph meaning, not screenshot similarity. Import a supported document, export it, import the export, and compare the node IDs, labels, and connections that the format promises to preserve. Layout coordinates can change without changing connectivity.
Test one shared database, a disconnected node, quoted labels, multiple incoming edges, and unsupported syntax. Each case should either preserve the declared meaning or explain the limitation. Quietly drawing half a graph is the failure to avoid.
The boundary extends to infrastructure exports. A diagram can produce a useful starter file; it cannot prove that the resulting infrastructure is safe to deploy.
Would I keep a hand-written parser?
A hand-written parser is reasonable for a deliberately small syntax subset. As the supported grammar grows, a parser library or a maintained upstream parser becomes more attractive. The decision should follow the compatibility contract, not the appeal of owning a compiler.
I would spend the next hour on fixtures before spending it on another diagram family. One small importer that preserves meaning is worth more than broad support that quietly drops an edge.
Try a basic flowchart in Codelit, then check the connections against your source. That comparison is the real acceptance test.
Questions people actually ask
- Can you turn a Mermaid diagram into a React Flow canvas?
- Yes. Parse supported Mermaid source into nodes and edges, map those records to the application's graph model, and compute positions for the editor. Mermaid's SVG renderer can support links and callbacks, but it does not provide the draggable React editor that Codelit needs.
- Which Mermaid diagram types does Codelit import?
- The importer reviewed for this article handles a subset of graph and flowchart syntax: basic node declarations, recognized shapes, and several arrow forms. It is not a full Mermaid implementation. Sequence diagrams, class diagrams, nested groups, and styling should not be assumed to survive an import.
- Should imported node IDs be prefixed by subgraph?
- Not automatically. A repeated Mermaid node ID refers to the same node, even when it is mentioned in different groups. An importer must preserve that identity. If the target editor needs internal IDs, keep one consistent mapping and rewrite every connected edge through it.
- Why does a diagram importer need its own layout step?
- The source describes connections, not the coordinates expected by the editor. React Flow renders the positions it receives. A layout library can calculate those positions from the graph, but the importer still owns dimensions, direction, grouping, and the conversion between coordinate conventions.
- Can Mermaid import and export be lossless?
- Only for syntax and properties represented by both sides. A basic graph can preserve node identity and connectivity, while classes, annotations, styling, or unsupported diagram families may be lost. Test round trips against a declared supported subset, rather than promising that every Mermaid document will survive unchanged.