Build Lucidchart
KINDAreplaces $9/mosaves $108/yrback to the verdict
A browser editor with shape libraries whose shapes carry defined connection points, layers you can lock and hide, connectors that stay attached through moves and resizes, and diagrams generated from a spreadsheet so an organisation chart or a network map is regenerated rather than redrawn.
Before step 1
Everything below is assumed from the first step. Tick each one when you actually have it, not when you plan to.
- installfree
Why Runs the build.
Get it nodejs.org, or nvm install 22. open ↗
Verify
node --version prints v22 or higher - installfree
Why Phase 5's export check is meaningless if the only thing you open the file in is the browser that made it.
Get it Inkscape is free and strict, which makes it a good test. open ↗
Verify
You can open an SVG and see whether its fonts survived - have readyfree with open licences
Why Export embeds or outlines fonts, which is redistribution and not permitted by every licence.
Get it Use openly licensed families and keep the licence files.
Verify
Each bundled font's licence permits embedding, or export outlines text - have readyfree
Why Phase 4 is only meaningful against real data, and real organisation data has the awkward cases: someone with two managers, a vacant role, a name that is very long.
Get it Use a real team structure or a network inventory. Thirty rows is enough to see layout problems.
Verify
The spreadsheet loads and includes at least one awkward case - decidefree
Why A general diagram tool needs hundreds of shapes; a specific one needs a dozen. Deciding which diagrams you make keeps the library finite.
Get it Pick the diagram type you draw most and list the shapes it needs. That list is your first library.
Verify
The list exists and is under about twenty shapes
Data model
Create these before the first phase that stores anything. Changing a table later is the expensive kind of change.
- docs(id, title, updated_at), pages(id, doc_id, name, ordinal) - layers(id, page_id, name, ordinal, visible, locked) - shapes(id, page_id, layer_id, library_key, x, y, w, h, rotation, text, style_json, data_key) - connectors(id, page_id, layer_id, from_shape, from_port, to_shape, to_port, label, style_json, waypoints_json) - libraries(id, name, shapes_json) · geometry and named ports per shape, as data rather than code - bindings(id, page_id, source_kind, source_ref, mapping_json, last_generated_at) · what regenerates a data-linked diagram - A connector stores shape and port names. Storing coordinates is what makes edges detach the first time something moves.
Environment variables
These go in a .env file the app reads at startup. The pack's .env.example is this table as a file · copy it, never commit the filled-in version.
| Variable | Needed | Example | Where the value comes from |
|---|---|---|---|
VITE_LIBRARY_DIR | required | /libraries | Where shape library files are served from. Adding a shape is a file here. |
VITE_FONT_DIR | required | /fonts | Self-hosted fonts with their licence files beside them. |
VITE_LAYOUT_DIRECTION | required | DOWN | Default direction for generated hierarchies. |
VITE_SHARE_ENDPOINT | optional | https://share.example.com | Product phase only. Leave unset to keep everything local. |
The build, in order
Shape libraries as data
A shape is a definition anyone can add to, not code you have to change.
Geometry, named ports with relative positions, default style. Written down before implementation.
Files
docs/library-format.mdOne renderer reading the data. No shape-specific code paths.
Files
src/shapes.tsSo two libraries can define a shape with the same name.
Files
src/libraries.ts
done when · tick each as it passeswatch out- Hard coding shapes as drawing functions means every new shape is a code change and a release, which is why diagram tools with rich libraries build them as data. Define the format first, including how a port's position is expressed relative to the shape's size, so a resized shape keeps its ports in the right places.
Connectors that survive editing
Moving or resizing a shape keeps its connectors attached and sensibly routed.
The relationship is the data. Geometry is derived at render time.
Files
src/connectors.tsPerpendicular exit, minimal turns, avoiding the connected shapes' bodies.
Files
src/route.tsDeleting a shape removes its connectors. Test for orphans explicitly.
Files
src/doc.ts
done when · tick each as it passeswatch out- Storing a connector as two points works until the first move, and then every diagram anyone saved is subtly wrong. Store the relationship and derive the geometry, which also makes automatic layout possible later.
Layers
A complex diagram can be worked on one layer at a time.
Ordered, affecting render order as well as interaction.
Files
src/layers.tsHidden and locked layers are excluded before anything is selected, not after.
Files
src/select.tsThe connector references shapes, so this should be free; test it anyway.
Files
src/layers.ts
done when · tick each as it passeswatch out- Letting selection reach a locked layer defeats the point of locking, and it is the most common way a background diagram gets dragged out of place. Filter selection by layer state at the hit test rather than checking after the fact.
Diagrams generated from data
An organisation chart regenerates from a spreadsheet instead of being redrawn.
Columns to text, style and parent relationships, defined once as a mapping.
Files
src/bind.tsSo regeneration is an update rather than a rebuild, which is what preserves manual work.
Files
src/bind.tsLayered layout for hierarchies, with an overlap assertion after.
Files
src/layout.tsterminalnpm install elkjs
done when · tick each as it passeswatch out- Regenerating from scratch discards every manual adjustment, and a diagram nobody can tweak is one people rebuild by hand elsewhere. Key generated shapes to their data rows, so a regeneration updates existing shapes rather than replacing them, and manual overrides survive.
Export that opens elsewhere
An exported diagram is usable in other tools, not just yours.
Embedded or outlined, viewBox set to content bounds.
Files
src/export-svg.tsNever upscale a bitmap. Compare against an upscaled version to confirm.
Files
src/export-png.tsInkscape or a design tool. The browser that made the file is not a test.
done when · tick each as it passeswatch out- An exported SVG referencing a web font renders in a fallback face on any machine that lacks it, which is every machine but yours. Embed the font as data or outline the text, and verify by opening the file in a different application rather than in the browser that made it.
Templates, sharing and honest collaborationproduct builder
Diagrams can be reused and shared, without pretending to be multiplayer.
Marked shapes to fill, the rest fixed design.
Files
src/templates.tsSame rendering, no editing affordances, self-contained.
Files
viewer.htmlIn the interface. Silence reads as a promise you did not make.
Files
README.md
done when · tick each as it passeswatch out- Naive real-time sync over a socket looks fine with one person and loses work with two, and diagram edits are large and hard to merge. Say editing is single-user rather than shipping something that occasionally destroys a colleague's work.
That is the whole plan for Lucidchart. What it deliberately does not cover is below · check the gaps before you call it a replacement.
- Multiplayer cursors and comments.
- Large template and shape catalogues.
- Presentation mode and enterprise governance.
- Import of proprietary diagram formats.
- presentation and enterprise controls
- multiplayer cursors and comments
- large template libraries
- high-fidelity import and export
- Conditional formatting from data, so a shape's colour follows a column
- A second layout algorithm for network rather than hierarchy diagrams
- Round-tripping a diagram to a text format so it can be diffed in version control
Need the files? The project pack on the verdict page hands your agent the whole brief · more diagrams.