Vibecode Creately
track this build4 phases, 12 steps, beginner friendly0%The visible diagramming + whiteboard loop is buildable, but a credible replacement needs more than the first screen. Creately earns its keep through interaction polish, collaboration, so expect a weekend or multi-day build and a narrower personal scope.
You are building a lean indie version of Creately. Create the following project files first, then implement the application by following them. Keep the files updated as decisions change. Do not collapse this into a single README or prompt. ===== README.md ===== # Creately · indie build A structured diagramming tool where the hard part is not drawing but routing: connectors that find their way around shapes, stay attached when things move, and keep a large diagram readable, plus shapes that hold data so a diagram can be a view of something rather than a picture. Estimated effort: **multi-day**. Work `BUILD_PLAN.md` top to bottom · every phase ends in a check that has to pass before the next one starts. ## Stack | Part | Choice | Why | | --- | --- | --- | | Canvas | A scene graph with shapes, ports and connectors as first-class objects | a connector attached to a coordinate detaches the moment anything moves | | Routing | Orthogonal routing with obstacle avoidance | connectors crossing through shapes is what makes diagrams unreadable | | Layout | Automatic arrangement as an option, never as a surprise | auto-layout that runs unasked destroys deliberate placement | | Data | Shapes with typed fields and views derived from them | the difference between a diagram and a picture of one | | Runtime | TypeScript with a local application and file-based documents | a diagram is a document and should behave like one | ## Before you start Have every one of these ready. The plan assumes them from step one. - [ ] **Node.js 22 or newer** · free - Why: Runs the application and the routing. - Get it: nodejs.org, or nvm install 22. - Verify: node --version prints v22 or higher - [ ] **A 2D geometry and pathfinding foundation** · free - Why: Orthogonal routing with obstacle avoidance is a real algorithm and writing it from nothing while also building an editor is two projects. - Get it: A library or a well-understood algorithm for grid-based routing with obstacle costs. - Verify: A path routes around a rectangle with two bends - [ ] **A real diagram with at least eighty shapes** · free - Why: Routing quality, bend counts and canvas performance are all uninteresting on a diagram of ten shapes and become the entire problem at eighty. - Get it: Recreate a real system diagram you have, or import one from an existing tool. - Verify: Eighty shapes exist with connectors that cross and compete for space - [ ] **A dataset matching your shapes** · free - Why: Data-driven styling cannot be evaluated without real data whose values actually vary, and the interesting case is data that changes between imports. - Get it: A file with a key per shape and fields that would drive colour, imported twice with changes between. - Verify: A second import updates shapes rather than duplicating them ## Quick start Follow Phase 1 in `BUILD_PLAN.md`; it creates the project. Then copy `.env.example` to `.env` and fill in the values it documents. ## Honest limits This build deliberately does not replace: - Real-time collaboration. - Large shape libraries. - Reverse engineering from code or infrastructure. - Presentation and animation. - large template libraries - high-fidelity import and export - presentation and enterprise controls - multiplayer cursors and comments If one of those is essential to you, that is the reason to keep paying for Creately, and the README should say so rather than pretend. ===== BRIEF.md ===== # Build brief · Creately The one-shot brief this plan expands. `BUILD_PLAN.md` (or `MILESTONES.md`) is the same sequence broken into steps and checks; where the two disagree, the plan wins. Build me a diagram canvas where connectors route themselves and shapes carry data to replace Creately. Build it in phases, in the order below. Do not write the whole thing in one pass. Finish a phase, run its "Done when" check, fix what fails, and only then start the next phase. ### Stack (fixed, do not substitute) - Canvas: A scene graph with shapes, ports and connectors as first-class objects · a connector attached to a coordinate detaches the moment anything moves - Routing: Orthogonal routing with obstacle avoidance · connectors crossing through shapes is what makes diagrams unreadable - Layout: Automatic arrangement as an option, never as a surprise · auto-layout that runs unasked destroys deliberate placement - Data: Shapes with typed fields and views derived from them · the difference between a diagram and a picture of one - Runtime: TypeScript with a local application and file-based documents · a diagram is a document and should behave like one ### Data model (create this before Phase 1) - documents(id, name, canvas_json, updated_at) - shapes(id, document_id, kind, x, y, width, height, style_json, data_json) - ports(shape_id, name, side, offset) · connectors attach to ports, not to coordinates - connectors(id, document_id, from_port, to_port, route_kind, waypoints_json, label, manual_route) - shape_fields(document_id, kind, field_name, field_type) · the schema for a shape kind's data - views(id, document_id, filter_json, style_rules_json) · styling driven by data rather than set by hand - A connector records whether its route was set manually, because automatic rerouting must never discard a route someone drew deliberately. ### Phase 1 · Connectors that stay attached Build: Shapes with named ports, and connectors bound to ports rather than to coordinates. Moving or resizing a shape updates every attached connector. Deleting a shape handles its connectors explicitly. Trap: Attaching a connector to the coordinate where it was drawn means every shape move leaves lines pointing at empty space, and on a diagram of any size the cleanup takes longer than the drawing did. Bind to ports and recompute the endpoint from the shape's current geometry. Done when: Moving a shape updates every attached connector immediately. Resizing keeps connectors attached at the correct relative position. Deleting a shape removes or orphans its connectors by a stated rule rather than leaving dangling references. A connector between two shapes survives both being moved simultaneously. Do not build yet: No routing, layout or data. ### Phase 2 · Routing around things Build: Orthogonal routing that treats shapes as obstacles, with a limited number of bends. Reroute on change. Keep routing fast enough to be interactive on a diagram with a hundred shapes. Trap: Routing that finds the shortest obstacle-free path will happily produce a connector with eleven bends that is technically correct and unreadable. Penalise bends heavily, prefer a slightly longer path with two, and accept crossing another connector rather than adding turns. Done when: Connectors route around shapes rather than through them on a diagram of a hundred shapes. Routes prefer few bends, verified by counting on a complex diagram. Rerouting after a move is fast enough to feel immediate. A connector with no obstacle-free path is drawn with a stated fallback rather than failing. Do not build yet: No layout, data or export yet. ### Phase 3 · Respecting a route someone drew Build: Let a connector's route be adjusted by hand, marking it manual. Preserve manual routes through shape moves where possible, and tell the user when a move has invalidated one rather than silently replacing it. Trap: Rerouting everything on every change discards the adjustments someone made to get a complex diagram readable, which is often an hour of work, and it happens the instant they nudge one shape. Mark manual routes, preserve them, and surface the ones a change has genuinely broken. Done when: A manually routed connector survives moves of unrelated shapes. A move that genuinely invalidates a manual route surfaces it rather than silently rerouting. Manual routes are visually distinguishable from automatic ones. Resetting a connector to automatic is available and explicit. Do not build yet: No data or layout yet. ### Phase 4 · Shapes that carry data Build: Typed fields per shape kind, edited in a panel. Styling rules driven by field values, so colour and border express data rather than being set by hand. Import data to populate shapes. Trap: Styling set by hand looks the same as styling derived from data until the data changes, at which point the diagram is confidently wrong and nobody can tell which colours mean something. Derive styling from rules where data exists, and make manually styled shapes visually distinguishable in editing. Done when: Shape kinds have typed fields validated on entry. Styling rules driven by field values apply automatically and update when data changes. Manually styled shapes are distinguishable from rule-styled ones while editing. Importing data updates existing shapes rather than duplicating them. Do not build yet: No layout or export yet. ### Phase 5 · Layout, export and large diagrams Build: Automatic layout available as an explicit action, never automatic. Export to vector formats preserving text as text. Handle a diagram of several hundred shapes without the canvas becoming unusable. Trap: Running automatic layout on open, or after an edit, destroys deliberate placement that carried meaning, and undo often does not restore it exactly. Make layout something you invoke, applied with a preview, and always undoable in one step. Done when: Automatic layout runs only when invoked and can be previewed before applying. Undo restores the previous arrangement exactly. Vector export preserves text as text rather than outlines. A diagram of five hundred shapes pans and zooms without becoming unusable. Do not build yet: Nothing after this. ### Out of scope (and why) - Real-time collaboration on one canvas, which is a substantial synchronisation problem in its own right. - The large shape libraries the hosted products ship, which is volume work and most of their perceived value. - Reverse engineering diagrams from code or infrastructure, which is a connector per system and never finished. - Presentation and animation features, which is a different product wearing the same interface. ### README must contain - That connectors attach to ports rather than coordinates, which is what keeps them attached - That routing penalises bends heavily, because a correct eleven-bend route is unreadable - That manual routes are preserved and only surfaced when genuinely invalidated - That styling is derived from shape data where rules exist, so colour means something - That automatic layout runs only when invoked, because placement often carries meaning ===== AGENTS.md ===== # Agent instructions · Creately indie build - Read `README.md` and `BUILD_PLAN.md` before writing code. The stack is fixed: A scene graph with shapes, ports and connectors as first-class objects, Orthogonal routing with obstacle avoidance, Automatic arrangement as an option, never as a surprise, Shapes with typed fields and views derived from them, TypeScript with a local application and file-based documents. Do not substitute. - Work one phase at a time, in order. Do not start a phase until every "Done when" item of the previous one passes. - Prefer the fewest moving parts that satisfy the step. No frameworks, services or dependencies the plan does not name. - Secrets live in `.env`, never in source or logs. Keep `.env.example` current when a variable is introduced. - Do not invent cryptography, security guarantees, APIs or compliance claims. - Add a focused test for every destructive, security-sensitive or data-loss path the plan names. - Run the project checks before declaring a phase complete, and record any deliberate shortcut in the README under "Tradeoffs". ## Known traps - Attaching a connector to the coordinate where it was drawn means every shape move leaves lines pointing at empty space, and on a diagram of any size the cleanup takes longer than the drawing did. Bind to ports and recompute the endpoint from the shape's current geometry. - Routing that finds the shortest obstacle-free path will happily produce a connector with eleven bends that is technically correct and unreadable. Penalise bends heavily, prefer a slightly longer path with two, and accept crossing another connector rather than adding turns. - Rerouting everything on every change discards the adjustments someone made to get a complex diagram readable, which is often an hour of work, and it happens the instant they nudge one shape. Mark manual routes, preserve them, and surface the ones a change has genuinely broken. - Styling set by hand looks the same as styling derived from data until the data changes, at which point the diagram is confidently wrong and nobody can tell which colours mean something. Derive styling from rules where data exists, and make manually styled shapes visually distinguishable in editing. ===== BUILD_PLAN.md ===== # Build plan · Creately A structured diagramming tool where the hard part is not drawing but routing: connectors that find their way around shapes, stay attached when things move, and keep a large diagram readable, plus shapes that hold data so a diagram can be a view of something rather than a picture. Phases are in dependency order. Each ends in a "Done when" list; treat an unticked item as a blocker, not a note. ## Phase 1 · Connectors that stay attached Moving a shape takes its connectors with it. ### Steps 1. Attach to ports, not coordinates The single decision the rest of the build depends on. Files: `src/ports.ts` 2. Recompute endpoints from geometry On move and on resize, both. Files: `src/connectors.ts` 3. Handle shape deletion explicitly A stated rule, not dangling references. Files: `src/delete.ts` ### Done when - [ ] Moving a shape updates its connectors - [ ] Resizing keeps attachment positions correct - [ ] Deletion follows a stated rule - [ ] Simultaneous moves are handled ### Watch out - Attaching a connector to the coordinate where it was drawn means every shape move leaves lines pointing at empty space, and on a diagram of any size the cleanup takes longer than the drawing did. Bind to ports and recompute the endpoint from the shape's current geometry. ## Phase 2 · Routing around things Connectors avoid shapes rather than passing through them. ### Steps 1. Treat shapes as obstacles Passing through a shape is what makes diagrams unreadable. Files: `src/route.ts` 2. Penalise bends heavily Eleven bends is correct and useless. Two is the target. Files: `src/route.ts`, `src/route.test.ts` 3. Keep rerouting interactive A hundred shapes, recomputed on drag. Measure it. Files: `src/route.ts` ### Done when - [ ] Connectors route around shapes - [ ] Routes prefer few bends - [ ] Rerouting feels immediate at a hundred shapes - [ ] An impossible route has a stated fallback ### Watch out - Routing that finds the shortest obstacle-free path will happily produce a connector with eleven bends that is technically correct and unreadable. Penalise bends heavily, prefer a slightly longer path with two, and accept crossing another connector rather than adding turns. ## Phase 3 · Respecting a route someone drew Automatic rerouting never discards a manual adjustment. ### Steps 1. Mark manual routes and preserve them An hour of readability work should survive a nudge. Files: `src/connectors.ts` 2. Surface invalidated routes Rather than silently replacing them. Files: `src/route.ts` 3. Make automatic reset explicit Available, deliberate, never a side effect. Files: `src/connectors.ts` ### Done when - [ ] Manual routes survive unrelated moves - [ ] Invalidated routes are surfaced, not replaced - [ ] Manual routes are visually distinguishable - [ ] Reset to automatic is explicit ### Watch out - Rerouting everything on every change discards the adjustments someone made to get a complex diagram readable, which is often an hour of work, and it happens the instant they nudge one shape. Mark manual routes, preserve them, and surface the ones a change has genuinely broken. ## Phase 4 · Shapes that carry data A diagram can be a view of information rather than a picture of it. ### Steps 1. Define typed fields per shape kind Validated on entry, like any schema. Files: `src/fields.ts` 2. Drive styling from rules So colour means something and updates when the data does. Files: `src/style-rules.ts` 3. Match imports to existing shapes By a key, not by position. Duplicating on every import is the failure. Files: `src/import.ts` ### Done when - [ ] Shape fields are typed and validated - [ ] Styling rules apply and update with data - [ ] Manual styling is distinguishable while editing - [ ] Import updates rather than duplicating ### Watch out - Styling set by hand looks the same as styling derived from data until the data changes, at which point the diagram is confidently wrong and nobody can tell which colours mean something. Derive styling from rules where data exists, and make manually styled shapes visually distinguishable in editing. ## Not in this build - Real-time collaboration. - Large shape libraries. - Reverse engineering from code or infrastructure. - Presentation and animation. ## After v1, if you want it - Swimlanes and containers, which change routing constraints considerably - A data panel showing the diagram as a table, since some questions are easier answered there - Diff between two versions of a diagram, which is what makes them reviewable ===== .env.example ===== # Copy to .env and fill in. Never commit .env; this file documents it. # Required. Diagram files. A diagram is a document and should behave like one. DOCUMENTS_DIR=~/Documents/diagrams # Required. How strongly bends are avoided. High, because readability beats path length. ROUTE_BEND_PENALTY=10 # Required. Routing runs on drag. Beyond this it must fall back rather than stutter. ROUTE_TIMEOUT_MS=16 # Required. Present as a constant. Placement often carries meaning a layout algorithm cannot see. AUTO_LAYOUT_ON_CHANGE=never # Required. An hour of readability work should survive a shape being nudged. PRESERVE_MANUAL_ROUTES=always # Required. Where canvas performance starts to degrade, made explicit rather than discovered. MAX_SHAPES_WARNING=500
You are building a lean indie version of Creately. Create the following project files first, then implement the application by following them. Keep the files updated as decisions change. Do not collapse this into a single README or prompt. ===== README.md ===== # Creately · indie build A structured diagramming tool where the hard part is not drawing but routing: connectors that find their way around shapes, stay attached when things move, and keep a large diagram readable, plus shapes that hold data so a diagram can be a view of something rather than a picture. Estimated effort: **multi-day**. Work `BUILD_PLAN.md` top to bottom · every phase ends in a check that has to pass before the next one starts. ## Stack | Part | Choice | Why | | --- | --- | --- | | Canvas | A scene graph with shapes, ports and connectors as first-class objects | a connector attached to a coordinate detaches the moment anything moves | | Routing | Orthogonal routing with obstacle avoidance | connectors crossing through shapes is what makes diagrams unreadable | | Layout | Automatic arrangement as an option, never as a surprise | auto-layout that runs unasked destroys deliberate placement | | Data | Shapes with typed fields and views derived from them | the difference between a diagram and a picture of one | | Runtime | TypeScript with a local application and file-based documents | a diagram is a document and should behave like one | ## Before you start Have every one of these ready. The plan assumes them from step one. - [ ] **Node.js 22 or newer** · free - Why: Runs the application and the routing. - Get it: nodejs.org, or nvm install 22. - Verify: node --version prints v22 or higher - [ ] **A 2D geometry and pathfinding foundation** · free - Why: Orthogonal routing with obstacle avoidance is a real algorithm and writing it from nothing while also building an editor is two projects. - Get it: A library or a well-understood algorithm for grid-based routing with obstacle costs. - Verify: A path routes around a rectangle with two bends - [ ] **A real diagram with at least eighty shapes** · free - Why: Routing quality, bend counts and canvas performance are all uninteresting on a diagram of ten shapes and become the entire problem at eighty. - Get it: Recreate a real system diagram you have, or import one from an existing tool. - Verify: Eighty shapes exist with connectors that cross and compete for space - [ ] **A dataset matching your shapes** · free - Why: Data-driven styling cannot be evaluated without real data whose values actually vary, and the interesting case is data that changes between imports. - Get it: A file with a key per shape and fields that would drive colour, imported twice with changes between. - Verify: A second import updates shapes rather than duplicating them ## Quick start Follow Phase 1 in `BUILD_PLAN.md`; it creates the project. Then copy `.env.example` to `.env` and fill in the values it documents. ## Honest limits This build deliberately does not replace: - Real-time collaboration. - Large shape libraries. - Reverse engineering from code or infrastructure. - Presentation and animation. - large template libraries - high-fidelity import and export - presentation and enterprise controls - multiplayer cursors and comments If one of those is essential to you, that is the reason to keep paying for Creately, and the README should say so rather than pretend. ===== BRIEF.md ===== # Build brief · Creately The one-shot brief this plan expands. `BUILD_PLAN.md` (or `MILESTONES.md`) is the same sequence broken into steps and checks; where the two disagree, the plan wins. Build me a diagram canvas where connectors route themselves and shapes carry data to replace Creately. Build it in phases, in the order below. Do not write the whole thing in one pass. Finish a phase, run its "Done when" check, fix what fails, and only then start the next phase. ### Stack (fixed, do not substitute) - Canvas: A scene graph with shapes, ports and connectors as first-class objects · a connector attached to a coordinate detaches the moment anything moves - Routing: Orthogonal routing with obstacle avoidance · connectors crossing through shapes is what makes diagrams unreadable - Layout: Automatic arrangement as an option, never as a surprise · auto-layout that runs unasked destroys deliberate placement - Data: Shapes with typed fields and views derived from them · the difference between a diagram and a picture of one - Runtime: TypeScript with a local application and file-based documents · a diagram is a document and should behave like one ### Data model (create this before Phase 1) - documents(id, name, canvas_json, updated_at) - shapes(id, document_id, kind, x, y, width, height, style_json, data_json) - ports(shape_id, name, side, offset) · connectors attach to ports, not to coordinates - connectors(id, document_id, from_port, to_port, route_kind, waypoints_json, label, manual_route) - shape_fields(document_id, kind, field_name, field_type) · the schema for a shape kind's data - views(id, document_id, filter_json, style_rules_json) · styling driven by data rather than set by hand - A connector records whether its route was set manually, because automatic rerouting must never discard a route someone drew deliberately. ### Phase 1 · Connectors that stay attached Build: Shapes with named ports, and connectors bound to ports rather than to coordinates. Moving or resizing a shape updates every attached connector. Deleting a shape handles its connectors explicitly. Trap: Attaching a connector to the coordinate where it was drawn means every shape move leaves lines pointing at empty space, and on a diagram of any size the cleanup takes longer than the drawing did. Bind to ports and recompute the endpoint from the shape's current geometry. Done when: Moving a shape updates every attached connector immediately. Resizing keeps connectors attached at the correct relative position. Deleting a shape removes or orphans its connectors by a stated rule rather than leaving dangling references. A connector between two shapes survives both being moved simultaneously. Do not build yet: No routing, layout or data. ### Phase 2 · Routing around things Build: Orthogonal routing that treats shapes as obstacles, with a limited number of bends. Reroute on change. Keep routing fast enough to be interactive on a diagram with a hundred shapes. Trap: Routing that finds the shortest obstacle-free path will happily produce a connector with eleven bends that is technically correct and unreadable. Penalise bends heavily, prefer a slightly longer path with two, and accept crossing another connector rather than adding turns. Done when: Connectors route around shapes rather than through them on a diagram of a hundred shapes. Routes prefer few bends, verified by counting on a complex diagram. Rerouting after a move is fast enough to feel immediate. A connector with no obstacle-free path is drawn with a stated fallback rather than failing. Do not build yet: No layout, data or export yet. ### Phase 3 · Respecting a route someone drew Build: Let a connector's route be adjusted by hand, marking it manual. Preserve manual routes through shape moves where possible, and tell the user when a move has invalidated one rather than silently replacing it. Trap: Rerouting everything on every change discards the adjustments someone made to get a complex diagram readable, which is often an hour of work, and it happens the instant they nudge one shape. Mark manual routes, preserve them, and surface the ones a change has genuinely broken. Done when: A manually routed connector survives moves of unrelated shapes. A move that genuinely invalidates a manual route surfaces it rather than silently rerouting. Manual routes are visually distinguishable from automatic ones. Resetting a connector to automatic is available and explicit. Do not build yet: No data or layout yet. ### Phase 4 · Shapes that carry data Build: Typed fields per shape kind, edited in a panel. Styling rules driven by field values, so colour and border express data rather than being set by hand. Import data to populate shapes. Trap: Styling set by hand looks the same as styling derived from data until the data changes, at which point the diagram is confidently wrong and nobody can tell which colours mean something. Derive styling from rules where data exists, and make manually styled shapes visually distinguishable in editing. Done when: Shape kinds have typed fields validated on entry. Styling rules driven by field values apply automatically and update when data changes. Manually styled shapes are distinguishable from rule-styled ones while editing. Importing data updates existing shapes rather than duplicating them. Do not build yet: No layout or export yet. ### Phase 5 · Layout, export and large diagrams Build: Automatic layout available as an explicit action, never automatic. Export to vector formats preserving text as text. Handle a diagram of several hundred shapes without the canvas becoming unusable. Trap: Running automatic layout on open, or after an edit, destroys deliberate placement that carried meaning, and undo often does not restore it exactly. Make layout something you invoke, applied with a preview, and always undoable in one step. Done when: Automatic layout runs only when invoked and can be previewed before applying. Undo restores the previous arrangement exactly. Vector export preserves text as text rather than outlines. A diagram of five hundred shapes pans and zooms without becoming unusable. Do not build yet: Nothing after this. ### Out of scope (and why) - Real-time collaboration on one canvas, which is a substantial synchronisation problem in its own right. - The large shape libraries the hosted products ship, which is volume work and most of their perceived value. - Reverse engineering diagrams from code or infrastructure, which is a connector per system and never finished. - Presentation and animation features, which is a different product wearing the same interface. ### README must contain - That connectors attach to ports rather than coordinates, which is what keeps them attached - That routing penalises bends heavily, because a correct eleven-bend route is unreadable - That manual routes are preserved and only surfaced when genuinely invalidated - That styling is derived from shape data where rules exist, so colour means something - That automatic layout runs only when invoked, because placement often carries meaning ===== AGENTS.md ===== # Agent instructions · Creately indie build - Read `README.md` and `BUILD_PLAN.md` before writing code. The stack is fixed: A scene graph with shapes, ports and connectors as first-class objects, Orthogonal routing with obstacle avoidance, Automatic arrangement as an option, never as a surprise, Shapes with typed fields and views derived from them, TypeScript with a local application and file-based documents. Do not substitute. - Work one phase at a time, in order. Do not start a phase until every "Done when" item of the previous one passes. - Prefer the fewest moving parts that satisfy the step. No frameworks, services or dependencies the plan does not name. - Secrets live in `.env`, never in source or logs. Keep `.env.example` current when a variable is introduced. - Do not invent cryptography, security guarantees, APIs or compliance claims. - Add a focused test for every destructive, security-sensitive or data-loss path the plan names. - Run the project checks before declaring a phase complete, and record any deliberate shortcut in the README under "Tradeoffs". ## Known traps - Attaching a connector to the coordinate where it was drawn means every shape move leaves lines pointing at empty space, and on a diagram of any size the cleanup takes longer than the drawing did. Bind to ports and recompute the endpoint from the shape's current geometry. - Routing that finds the shortest obstacle-free path will happily produce a connector with eleven bends that is technically correct and unreadable. Penalise bends heavily, prefer a slightly longer path with two, and accept crossing another connector rather than adding turns. - Rerouting everything on every change discards the adjustments someone made to get a complex diagram readable, which is often an hour of work, and it happens the instant they nudge one shape. Mark manual routes, preserve them, and surface the ones a change has genuinely broken. - Styling set by hand looks the same as styling derived from data until the data changes, at which point the diagram is confidently wrong and nobody can tell which colours mean something. Derive styling from rules where data exists, and make manually styled shapes visually distinguishable in editing. ===== BUILD_PLAN.md ===== # Build plan · Creately A structured diagramming tool where the hard part is not drawing but routing: connectors that find their way around shapes, stay attached when things move, and keep a large diagram readable, plus shapes that hold data so a diagram can be a view of something rather than a picture. Phases are in dependency order. Each ends in a "Done when" list; treat an unticked item as a blocker, not a note. ## Phase 1 · Connectors that stay attached Moving a shape takes its connectors with it. ### Steps 1. Attach to ports, not coordinates The single decision the rest of the build depends on. Files: `src/ports.ts` 2. Recompute endpoints from geometry On move and on resize, both. Files: `src/connectors.ts` 3. Handle shape deletion explicitly A stated rule, not dangling references. Files: `src/delete.ts` ### Done when - [ ] Moving a shape updates its connectors - [ ] Resizing keeps attachment positions correct - [ ] Deletion follows a stated rule - [ ] Simultaneous moves are handled ### Watch out - Attaching a connector to the coordinate where it was drawn means every shape move leaves lines pointing at empty space, and on a diagram of any size the cleanup takes longer than the drawing did. Bind to ports and recompute the endpoint from the shape's current geometry. ## Phase 2 · Routing around things Connectors avoid shapes rather than passing through them. ### Steps 1. Treat shapes as obstacles Passing through a shape is what makes diagrams unreadable. Files: `src/route.ts` 2. Penalise bends heavily Eleven bends is correct and useless. Two is the target. Files: `src/route.ts`, `src/route.test.ts` 3. Keep rerouting interactive A hundred shapes, recomputed on drag. Measure it. Files: `src/route.ts` ### Done when - [ ] Connectors route around shapes - [ ] Routes prefer few bends - [ ] Rerouting feels immediate at a hundred shapes - [ ] An impossible route has a stated fallback ### Watch out - Routing that finds the shortest obstacle-free path will happily produce a connector with eleven bends that is technically correct and unreadable. Penalise bends heavily, prefer a slightly longer path with two, and accept crossing another connector rather than adding turns. ## Phase 3 · Respecting a route someone drew Automatic rerouting never discards a manual adjustment. ### Steps 1. Mark manual routes and preserve them An hour of readability work should survive a nudge. Files: `src/connectors.ts` 2. Surface invalidated routes Rather than silently replacing them. Files: `src/route.ts` 3. Make automatic reset explicit Available, deliberate, never a side effect. Files: `src/connectors.ts` ### Done when - [ ] Manual routes survive unrelated moves - [ ] Invalidated routes are surfaced, not replaced - [ ] Manual routes are visually distinguishable - [ ] Reset to automatic is explicit ### Watch out - Rerouting everything on every change discards the adjustments someone made to get a complex diagram readable, which is often an hour of work, and it happens the instant they nudge one shape. Mark manual routes, preserve them, and surface the ones a change has genuinely broken. ## Phase 4 · Shapes that carry data A diagram can be a view of information rather than a picture of it. ### Steps 1. Define typed fields per shape kind Validated on entry, like any schema. Files: `src/fields.ts` 2. Drive styling from rules So colour means something and updates when the data does. Files: `src/style-rules.ts` 3. Match imports to existing shapes By a key, not by position. Duplicating on every import is the failure. Files: `src/import.ts` ### Done when - [ ] Shape fields are typed and validated - [ ] Styling rules apply and update with data - [ ] Manual styling is distinguishable while editing - [ ] Import updates rather than duplicating ### Watch out - Styling set by hand looks the same as styling derived from data until the data changes, at which point the diagram is confidently wrong and nobody can tell which colours mean something. Derive styling from rules where data exists, and make manually styled shapes visually distinguishable in editing. ## Not in this build - Real-time collaboration. - Large shape libraries. - Reverse engineering from code or infrastructure. - Presentation and animation. ## After v1, if you want it - Swimlanes and containers, which change routing constraints considerably - A data panel showing the diagram as a table, since some questions are easier answered there - Diff between two versions of a diagram, which is what makes them reviewable ===== .env.example ===== # Copy to .env and fill in. Never commit .env; this file documents it. # Required. Diagram files. A diagram is a document and should behave like one. DOCUMENTS_DIR=~/Documents/diagrams # Required. How strongly bends are avoided. High, because readability beats path length. ROUTE_BEND_PENALTY=10 # Required. Routing runs on drag. Beyond this it must fall back rather than stutter. ROUTE_TIMEOUT_MS=16 # Required. Present as a constant. Placement often carries meaning a layout algorithm cannot see. AUTO_LAYOUT_ON_CHANGE=never # Required. An hour of readability work should survive a shape being nudged. PRESERVE_MANUAL_ROUTES=always # Required. Where canvas performance starts to degrade, made explicit rather than discovered. MAX_SHAPES_WARNING=500
You are building a production product version of Creately. Create the following project files first, then implement the application by following them. Keep the files updated as decisions change. Do not collapse this into a single README or prompt. ===== PRODUCT.md ===== # Creately · product brief ## Problem The visible diagramming + whiteboard loop is buildable, but a credible replacement needs more than the first screen. Creately earns its keep through interaction polish, collaboration, so expect a weekend or multi-day build and a narrower personal scope. ## Product outcome A diagram tool whose connectors stay attached and route themselves sensibly, whose manual adjustments survive, and whose colours mean something because they come from the data. ## Target user A builder who needs a maintainable product foundation, not a one-off demo. ## Required capabilities - Node.js 22 - modern browser - no account required ## Explicit non-goals for v1 - Real-time collaboration. - Large shape libraries. - Reverse engineering from code or infrastructure. - Presentation and animation. - large template libraries - high-fidelity import and export - presentation and enterprise controls - multiplayer cursors and comments ## Success criteria - Moving a shape is confirmed to update its connectors - Connectors are confirmed to route around shapes with few bends - Manual routes are confirmed to survive unrelated moves - Data-driven styling is confirmed to update with the data - Automatic layout is confirmed never to run unasked ===== BRIEF.md ===== # Build brief · Creately The one-shot brief this plan expands. `BUILD_PLAN.md` (or `MILESTONES.md`) is the same sequence broken into steps and checks; where the two disagree, the plan wins. Build me a diagram canvas where connectors route themselves and shapes carry data to replace Creately. Build it in phases, in the order below. Do not write the whole thing in one pass. Finish a phase, run its "Done when" check, fix what fails, and only then start the next phase. ### Stack (fixed, do not substitute) - Canvas: A scene graph with shapes, ports and connectors as first-class objects · a connector attached to a coordinate detaches the moment anything moves - Routing: Orthogonal routing with obstacle avoidance · connectors crossing through shapes is what makes diagrams unreadable - Layout: Automatic arrangement as an option, never as a surprise · auto-layout that runs unasked destroys deliberate placement - Data: Shapes with typed fields and views derived from them · the difference between a diagram and a picture of one - Runtime: TypeScript with a local application and file-based documents · a diagram is a document and should behave like one ### Data model (create this before Phase 1) - documents(id, name, canvas_json, updated_at) - shapes(id, document_id, kind, x, y, width, height, style_json, data_json) - ports(shape_id, name, side, offset) · connectors attach to ports, not to coordinates - connectors(id, document_id, from_port, to_port, route_kind, waypoints_json, label, manual_route) - shape_fields(document_id, kind, field_name, field_type) · the schema for a shape kind's data - views(id, document_id, filter_json, style_rules_json) · styling driven by data rather than set by hand - A connector records whether its route was set manually, because automatic rerouting must never discard a route someone drew deliberately. ### Phase 1 · Connectors that stay attached Build: Shapes with named ports, and connectors bound to ports rather than to coordinates. Moving or resizing a shape updates every attached connector. Deleting a shape handles its connectors explicitly. Trap: Attaching a connector to the coordinate where it was drawn means every shape move leaves lines pointing at empty space, and on a diagram of any size the cleanup takes longer than the drawing did. Bind to ports and recompute the endpoint from the shape's current geometry. Done when: Moving a shape updates every attached connector immediately. Resizing keeps connectors attached at the correct relative position. Deleting a shape removes or orphans its connectors by a stated rule rather than leaving dangling references. A connector between two shapes survives both being moved simultaneously. Do not build yet: No routing, layout or data. ### Phase 2 · Routing around things Build: Orthogonal routing that treats shapes as obstacles, with a limited number of bends. Reroute on change. Keep routing fast enough to be interactive on a diagram with a hundred shapes. Trap: Routing that finds the shortest obstacle-free path will happily produce a connector with eleven bends that is technically correct and unreadable. Penalise bends heavily, prefer a slightly longer path with two, and accept crossing another connector rather than adding turns. Done when: Connectors route around shapes rather than through them on a diagram of a hundred shapes. Routes prefer few bends, verified by counting on a complex diagram. Rerouting after a move is fast enough to feel immediate. A connector with no obstacle-free path is drawn with a stated fallback rather than failing. Do not build yet: No layout, data or export yet. ### Phase 3 · Respecting a route someone drew Build: Let a connector's route be adjusted by hand, marking it manual. Preserve manual routes through shape moves where possible, and tell the user when a move has invalidated one rather than silently replacing it. Trap: Rerouting everything on every change discards the adjustments someone made to get a complex diagram readable, which is often an hour of work, and it happens the instant they nudge one shape. Mark manual routes, preserve them, and surface the ones a change has genuinely broken. Done when: A manually routed connector survives moves of unrelated shapes. A move that genuinely invalidates a manual route surfaces it rather than silently rerouting. Manual routes are visually distinguishable from automatic ones. Resetting a connector to automatic is available and explicit. Do not build yet: No data or layout yet. ### Phase 4 · Shapes that carry data Build: Typed fields per shape kind, edited in a panel. Styling rules driven by field values, so colour and border express data rather than being set by hand. Import data to populate shapes. Trap: Styling set by hand looks the same as styling derived from data until the data changes, at which point the diagram is confidently wrong and nobody can tell which colours mean something. Derive styling from rules where data exists, and make manually styled shapes visually distinguishable in editing. Done when: Shape kinds have typed fields validated on entry. Styling rules driven by field values apply automatically and update when data changes. Manually styled shapes are distinguishable from rule-styled ones while editing. Importing data updates existing shapes rather than duplicating them. Do not build yet: No layout or export yet. ### Phase 5 · Layout, export and large diagrams Build: Automatic layout available as an explicit action, never automatic. Export to vector formats preserving text as text. Handle a diagram of several hundred shapes without the canvas becoming unusable. Trap: Running automatic layout on open, or after an edit, destroys deliberate placement that carried meaning, and undo often does not restore it exactly. Make layout something you invoke, applied with a preview, and always undoable in one step. Done when: Automatic layout runs only when invoked and can be previewed before applying. Undo restores the previous arrangement exactly. Vector export preserves text as text rather than outlines. A diagram of five hundred shapes pans and zooms without becoming unusable. Do not build yet: Nothing after this. ### Out of scope (and why) - Real-time collaboration on one canvas, which is a substantial synchronisation problem in its own right. - The large shape libraries the hosted products ship, which is volume work and most of their perceived value. - Reverse engineering diagrams from code or infrastructure, which is a connector per system and never finished. - Presentation and animation features, which is a different product wearing the same interface. ### README must contain - That connectors attach to ports rather than coordinates, which is what keeps them attached - That routing penalises bends heavily, because a correct eleven-bend route is unreadable - That manual routes are preserved and only surfaced when genuinely invalidated - That styling is derived from shape data where rules exist, so colour means something - That automatic layout runs only when invoked, because placement often carries meaning ===== ARCHITECTURE.md ===== # Architecture · Creately ## Stack | Part | Choice | Why | | --- | --- | --- | | Canvas | A scene graph with shapes, ports and connectors as first-class objects | a connector attached to a coordinate detaches the moment anything moves | | Routing | Orthogonal routing with obstacle avoidance | connectors crossing through shapes is what makes diagrams unreadable | | Layout | Automatic arrangement as an option, never as a surprise | auto-layout that runs unasked destroys deliberate placement | | Data | Shapes with typed fields and views derived from them | the difference between a diagram and a picture of one | | Runtime | TypeScript with a local application and file-based documents | a diagram is a document and should behave like one | ## Modules Each module has one owner concern and a documented way to replace it. | Module | Owns | How to replace it | | --- | --- | --- | | Ports | Attachment points on shapes. | Not swappable for coordinate binding, which detaches on the first move. | | Routing | Orthogonal paths with obstacle avoidance. | Any algorithm, provided bends are penalised heavily. | | Manual routes | Preserving deliberate adjustments. | Any implementation, provided automatic rerouting cannot silently discard them. | | Data | Typed shape fields and derived styling. | Any store, provided rule-styled and hand-styled shapes stay distinguishable. | | Layout | Arrangement on request with preview. | Any algorithm, provided it never runs unasked. | ## Configuration Every runtime setting is an environment variable documented in `.env.example`, validated at startup, with a safe local default wherever one exists. - `DOCUMENTS_DIR` · required · Diagram files. A diagram is a document and should behave like one. - `ROUTE_BEND_PENALTY` · required · How strongly bends are avoided. High, because readability beats path length. - `ROUTE_TIMEOUT_MS` · required · Routing runs on drag. Beyond this it must fall back rather than stutter. - `AUTO_LAYOUT_ON_CHANGE` · required · Present as a constant. Placement often carries meaning a layout algorithm cannot see. - `PRESERVE_MANUAL_ROUTES` · required · An hour of readability work should survive a shape being nudged. - `MAX_SHAPES_WARNING` · required · Where canvas performance starts to degrade, made explicit rather than discovered. ## Production baseline - Security: least privilege, input validation at every boundary, secret redaction in logs, rate limits on abuse-prone paths, no invented security primitives. - Data: explicit schema and migrations, transactional writes where integrity matters, backup and restore procedures that have been exercised. - Integrations: adapters around third-party providers, idempotent webhook or job processing, bounded retries, timeouts. - Observability: structured logs with request or operation ids, an error-tracking hook, and health and readiness checks where a server exists. - Quality: unit tests for domain rules, integration tests at module boundaries, one end-to-end test of the critical path. ## Decision records For each dependency in the stack table, keep a short note: why it was chosen, its failure mode, and how it is replaced. Do not add infrastructure until a requirement in `PRODUCT.md` justifies it. ===== AGENTS.md ===== # Agent instructions · Creately product build - Read `PRODUCT.md` and `ARCHITECTURE.md` before changing code. The stack is fixed: A scene graph with shapes, ports and connectors as first-class objects, Orthogonal routing with obstacle avoidance, Automatic arrangement as an option, never as a surprise, Shapes with typed fields and views derived from them, TypeScript with a local application and file-based documents. - Implement milestone by milestone from `MILESTONES.md`; keep each change reviewable and leave the application runnable at every commit. - Treat authentication, payments, encryption, imports, webhooks and destructive actions as high-risk boundaries when present. - Never invent cryptography or silently weaken a requirement to make a check pass. - Put every external service behind an interface with a deterministic fake for tests. - Add migrations and rollback or recovery notes for every persistent data change. - Log useful operational context without credentials, tokens, passwords or personal data. - Update documentation and run every check before completing a milestone. ## Known traps - Attaching a connector to the coordinate where it was drawn means every shape move leaves lines pointing at empty space, and on a diagram of any size the cleanup takes longer than the drawing did. Bind to ports and recompute the endpoint from the shape's current geometry. - Routing that finds the shortest obstacle-free path will happily produce a connector with eleven bends that is technically correct and unreadable. Penalise bends heavily, prefer a slightly longer path with two, and accept crossing another connector rather than adding turns. - Rerouting everything on every change discards the adjustments someone made to get a complex diagram readable, which is often an hour of work, and it happens the instant they nudge one shape. Mark manual routes, preserve them, and surface the ones a change has genuinely broken. - Styling set by hand looks the same as styling derived from data until the data changes, at which point the diagram is confidently wrong and nobody can tell which colours mean something. Derive styling from rules where data exists, and make manually styled shapes visually distinguishable in editing. - Running automatic layout on open, or after an edit, destroys deliberate placement that carried meaning, and undo often does not restore it exactly. Make layout something you invoke, applied with a preview, and always undoable in one step. ===== MILESTONES.md ===== # Delivery milestones · Creately Estimated effort: **multi-day** for the indie phases; the production-only milestones add the trust and operability layer. ## M1 · Connectors that stay attached Moving a shape takes its connectors with it. ### Steps 1. Attach to ports, not coordinates The single decision the rest of the build depends on. Files: `src/ports.ts` 2. Recompute endpoints from geometry On move and on resize, both. Files: `src/connectors.ts` 3. Handle shape deletion explicitly A stated rule, not dangling references. Files: `src/delete.ts` ### Done when - [ ] Moving a shape updates its connectors - [ ] Resizing keeps attachment positions correct - [ ] Deletion follows a stated rule - [ ] Simultaneous moves are handled ### Watch out - Attaching a connector to the coordinate where it was drawn means every shape move leaves lines pointing at empty space, and on a diagram of any size the cleanup takes longer than the drawing did. Bind to ports and recompute the endpoint from the shape's current geometry. ## M2 · Routing around things Connectors avoid shapes rather than passing through them. ### Steps 1. Treat shapes as obstacles Passing through a shape is what makes diagrams unreadable. Files: `src/route.ts` 2. Penalise bends heavily Eleven bends is correct and useless. Two is the target. Files: `src/route.ts`, `src/route.test.ts` 3. Keep rerouting interactive A hundred shapes, recomputed on drag. Measure it. Files: `src/route.ts` ### Done when - [ ] Connectors route around shapes - [ ] Routes prefer few bends - [ ] Rerouting feels immediate at a hundred shapes - [ ] An impossible route has a stated fallback ### Watch out - Routing that finds the shortest obstacle-free path will happily produce a connector with eleven bends that is technically correct and unreadable. Penalise bends heavily, prefer a slightly longer path with two, and accept crossing another connector rather than adding turns. ## M3 · Respecting a route someone drew Automatic rerouting never discards a manual adjustment. ### Steps 1. Mark manual routes and preserve them An hour of readability work should survive a nudge. Files: `src/connectors.ts` 2. Surface invalidated routes Rather than silently replacing them. Files: `src/route.ts` 3. Make automatic reset explicit Available, deliberate, never a side effect. Files: `src/connectors.ts` ### Done when - [ ] Manual routes survive unrelated moves - [ ] Invalidated routes are surfaced, not replaced - [ ] Manual routes are visually distinguishable - [ ] Reset to automatic is explicit ### Watch out - Rerouting everything on every change discards the adjustments someone made to get a complex diagram readable, which is often an hour of work, and it happens the instant they nudge one shape. Mark manual routes, preserve them, and surface the ones a change has genuinely broken. ## M4 · Shapes that carry data A diagram can be a view of information rather than a picture of it. ### Steps 1. Define typed fields per shape kind Validated on entry, like any schema. Files: `src/fields.ts` 2. Drive styling from rules So colour means something and updates when the data does. Files: `src/style-rules.ts` 3. Match imports to existing shapes By a key, not by position. Duplicating on every import is the failure. Files: `src/import.ts` ### Done when - [ ] Shape fields are typed and validated - [ ] Styling rules apply and update with data - [ ] Manual styling is distinguishable while editing - [ ] Import updates rather than duplicating ### Watch out - Styling set by hand looks the same as styling derived from data until the data changes, at which point the diagram is confidently wrong and nobody can tell which colours mean something. Derive styling from rules where data exists, and make manually styled shapes visually distinguishable in editing. ## M5 · Layout, export and large diagrams (production only) Automatic arrangement helps when asked, and the diagram exports cleanly. ### Steps 1. Make layout an explicit action with preview Placement often carries meaning that a layout algorithm cannot see. Files: `src/layout.ts` 2. Export text as text So a diagram can be searched, edited and read by assistive tools. Files: `src/export.ts` 3. Keep the canvas usable at scale Five hundred shapes. Measure pan and zoom, do not assume. Files: `src/canvas.ts` ### Done when - [ ] Layout runs only when invoked, with preview - [ ] Undo restores the previous arrangement exactly - [ ] Export preserves text as text - [ ] Five hundred shapes pan and zoom acceptably ### Watch out - Running automatic layout on open, or after an edit, destroys deliberate placement that carried meaning, and undo often does not restore it exactly. Make layout something you invoke, applied with a preview, and always undoable in one step. ===== OPERATIONS.md ===== # Operations · Creately ## Backup Diagrams are documents and belong wherever your ordinary document backups reach. The data behind data-driven diagrams lives elsewhere and should be backed up with its source rather than here. ## Restore Restore and confirm manual routes survived, since they represent the most human effort in a diagram and their loss is not visible until someone opens the file and finds it messy. Do a restore drill before the first real user, and write the date here when it passes. ## Monitoring For a local tool the measurement that matters is routing time under drag, which degrades as diagrams grow and turns a fluid tool into a stuttering one gradually enough that nobody reports it. ## Incident checklist Connectors detaching or routing through shapes is the visible failure, and it points at either port binding or the obstacle set being stale. Both are reproducible on a saved document rather than needing a live session. 1. Contain the issue without destroying evidence or user data. 2. Record the timeline and affected scope. 3. Rotate exposed secrets and revoke compromised sessions or credentials. 4. Restore from a verified backup when needed. 5. Document the root cause, the remediation and the regression test. ## Release gate - [ ] Moving a shape is confirmed to update its connectors - [ ] Connectors are confirmed to route around shapes with few bends - [ ] Manual routes are confirmed to survive unrelated moves - [ ] Data-driven styling is confirmed to update with the data - [ ] Automatic layout is confirmed never to run unasked ## Launch constraint Do not market omitted Creately capabilities as implemented. The non-goals in `PRODUCT.md` remain user-visible limitations until they are deliberately delivered. ===== .env.example ===== # Copy to .env and fill in. Never commit .env; this file documents it. # Required. Diagram files. A diagram is a document and should behave like one. DOCUMENTS_DIR=~/Documents/diagrams # Required. How strongly bends are avoided. High, because readability beats path length. ROUTE_BEND_PENALTY=10 # Required. Routing runs on drag. Beyond this it must fall back rather than stutter. ROUTE_TIMEOUT_MS=16 # Required. Present as a constant. Placement often carries meaning a layout algorithm cannot see. AUTO_LAYOUT_ON_CHANGE=never # Required. An hour of readability work should survive a shape being nudged. PRESERVE_MANUAL_ROUTES=always # Required. Where canvas performance starts to degrade, made explicit rather than discovered. MAX_SHAPES_WARNING=500
# Creately · indie build A structured diagramming tool where the hard part is not drawing but routing: connectors that find their way around shapes, stay attached when things move, and keep a large diagram readable, plus shapes that hold data so a diagram can be a view of something rather than a picture. Estimated effort: **multi-day**. Work `BUILD_PLAN.md` top to bottom · every phase ends in a check that has to pass before the next one starts. ## Stack | Part | Choice | Why | | --- | --- | --- | | Canvas | A scene graph with shapes, ports and connectors as first-class objects | a connector attached to a coordinate detaches the moment anything moves | | Routing | Orthogonal routing with obstacle avoidance | connectors crossing through shapes is what makes diagrams unreadable | | Layout | Automatic arrangement as an option, never as a surprise | auto-layout that runs unasked destroys deliberate placement | | Data | Shapes with typed fields and views derived from them | the difference between a diagram and a picture of one | | Runtime | TypeScript with a local application and file-based documents | a diagram is a document and should behave like one | ## Before you start Have every one of these ready. The plan assumes them from step one. - [ ] **Node.js 22 or newer** · free - Why: Runs the application and the routing. - Get it: nodejs.org, or nvm install 22. - Verify: node --version prints v22 or higher - [ ] **A 2D geometry and pathfinding foundation** · free - Why: Orthogonal routing with obstacle avoidance is a real algorithm and writing it from nothing while also building an editor is two projects. - Get it: A library or a well-understood algorithm for grid-based routing with obstacle costs. - Verify: A path routes around a rectangle with two bends - [ ] **A real diagram with at least eighty shapes** · free - Why: Routing quality, bend counts and canvas performance are all uninteresting on a diagram of ten shapes and become the entire problem at eighty. - Get it: Recreate a real system diagram you have, or import one from an existing tool. - Verify: Eighty shapes exist with connectors that cross and compete for space - [ ] **A dataset matching your shapes** · free - Why: Data-driven styling cannot be evaluated without real data whose values actually vary, and the interesting case is data that changes between imports. - Get it: A file with a key per shape and fields that would drive colour, imported twice with changes between. - Verify: A second import updates shapes rather than duplicating them ## Quick start Follow Phase 1 in `BUILD_PLAN.md`; it creates the project. Then copy `.env.example` to `.env` and fill in the values it documents. ## Honest limits This build deliberately does not replace: - Real-time collaboration. - Large shape libraries. - Reverse engineering from code or infrastructure. - Presentation and animation. - large template libraries - high-fidelity import and export - presentation and enterprise controls - multiplayer cursors and comments If one of those is essential to you, that is the reason to keep paying for Creately, and the README should say so rather than pretend.
# Build brief · Creately The one-shot brief this plan expands. `BUILD_PLAN.md` (or `MILESTONES.md`) is the same sequence broken into steps and checks; where the two disagree, the plan wins. Build me a diagram canvas where connectors route themselves and shapes carry data to replace Creately. Build it in phases, in the order below. Do not write the whole thing in one pass. Finish a phase, run its "Done when" check, fix what fails, and only then start the next phase. ### Stack (fixed, do not substitute) - Canvas: A scene graph with shapes, ports and connectors as first-class objects · a connector attached to a coordinate detaches the moment anything moves - Routing: Orthogonal routing with obstacle avoidance · connectors crossing through shapes is what makes diagrams unreadable - Layout: Automatic arrangement as an option, never as a surprise · auto-layout that runs unasked destroys deliberate placement - Data: Shapes with typed fields and views derived from them · the difference between a diagram and a picture of one - Runtime: TypeScript with a local application and file-based documents · a diagram is a document and should behave like one ### Data model (create this before Phase 1) - documents(id, name, canvas_json, updated_at) - shapes(id, document_id, kind, x, y, width, height, style_json, data_json) - ports(shape_id, name, side, offset) · connectors attach to ports, not to coordinates - connectors(id, document_id, from_port, to_port, route_kind, waypoints_json, label, manual_route) - shape_fields(document_id, kind, field_name, field_type) · the schema for a shape kind's data - views(id, document_id, filter_json, style_rules_json) · styling driven by data rather than set by hand - A connector records whether its route was set manually, because automatic rerouting must never discard a route someone drew deliberately. ### Phase 1 · Connectors that stay attached Build: Shapes with named ports, and connectors bound to ports rather than to coordinates. Moving or resizing a shape updates every attached connector. Deleting a shape handles its connectors explicitly. Trap: Attaching a connector to the coordinate where it was drawn means every shape move leaves lines pointing at empty space, and on a diagram of any size the cleanup takes longer than the drawing did. Bind to ports and recompute the endpoint from the shape's current geometry. Done when: Moving a shape updates every attached connector immediately. Resizing keeps connectors attached at the correct relative position. Deleting a shape removes or orphans its connectors by a stated rule rather than leaving dangling references. A connector between two shapes survives both being moved simultaneously. Do not build yet: No routing, layout or data. ### Phase 2 · Routing around things Build: Orthogonal routing that treats shapes as obstacles, with a limited number of bends. Reroute on change. Keep routing fast enough to be interactive on a diagram with a hundred shapes. Trap: Routing that finds the shortest obstacle-free path will happily produce a connector with eleven bends that is technically correct and unreadable. Penalise bends heavily, prefer a slightly longer path with two, and accept crossing another connector rather than adding turns. Done when: Connectors route around shapes rather than through them on a diagram of a hundred shapes. Routes prefer few bends, verified by counting on a complex diagram. Rerouting after a move is fast enough to feel immediate. A connector with no obstacle-free path is drawn with a stated fallback rather than failing. Do not build yet: No layout, data or export yet. ### Phase 3 · Respecting a route someone drew Build: Let a connector's route be adjusted by hand, marking it manual. Preserve manual routes through shape moves where possible, and tell the user when a move has invalidated one rather than silently replacing it. Trap: Rerouting everything on every change discards the adjustments someone made to get a complex diagram readable, which is often an hour of work, and it happens the instant they nudge one shape. Mark manual routes, preserve them, and surface the ones a change has genuinely broken. Done when: A manually routed connector survives moves of unrelated shapes. A move that genuinely invalidates a manual route surfaces it rather than silently rerouting. Manual routes are visually distinguishable from automatic ones. Resetting a connector to automatic is available and explicit. Do not build yet: No data or layout yet. ### Phase 4 · Shapes that carry data Build: Typed fields per shape kind, edited in a panel. Styling rules driven by field values, so colour and border express data rather than being set by hand. Import data to populate shapes. Trap: Styling set by hand looks the same as styling derived from data until the data changes, at which point the diagram is confidently wrong and nobody can tell which colours mean something. Derive styling from rules where data exists, and make manually styled shapes visually distinguishable in editing. Done when: Shape kinds have typed fields validated on entry. Styling rules driven by field values apply automatically and update when data changes. Manually styled shapes are distinguishable from rule-styled ones while editing. Importing data updates existing shapes rather than duplicating them. Do not build yet: No layout or export yet. ### Phase 5 · Layout, export and large diagrams Build: Automatic layout available as an explicit action, never automatic. Export to vector formats preserving text as text. Handle a diagram of several hundred shapes without the canvas becoming unusable. Trap: Running automatic layout on open, or after an edit, destroys deliberate placement that carried meaning, and undo often does not restore it exactly. Make layout something you invoke, applied with a preview, and always undoable in one step. Done when: Automatic layout runs only when invoked and can be previewed before applying. Undo restores the previous arrangement exactly. Vector export preserves text as text rather than outlines. A diagram of five hundred shapes pans and zooms without becoming unusable. Do not build yet: Nothing after this. ### Out of scope (and why) - Real-time collaboration on one canvas, which is a substantial synchronisation problem in its own right. - The large shape libraries the hosted products ship, which is volume work and most of their perceived value. - Reverse engineering diagrams from code or infrastructure, which is a connector per system and never finished. - Presentation and animation features, which is a different product wearing the same interface. ### README must contain - That connectors attach to ports rather than coordinates, which is what keeps them attached - That routing penalises bends heavily, because a correct eleven-bend route is unreadable - That manual routes are preserved and only surfaced when genuinely invalidated - That styling is derived from shape data where rules exist, so colour means something - That automatic layout runs only when invoked, because placement often carries meaning
# Agent instructions · Creately indie build - Read `README.md` and `BUILD_PLAN.md` before writing code. The stack is fixed: A scene graph with shapes, ports and connectors as first-class objects, Orthogonal routing with obstacle avoidance, Automatic arrangement as an option, never as a surprise, Shapes with typed fields and views derived from them, TypeScript with a local application and file-based documents. Do not substitute. - Work one phase at a time, in order. Do not start a phase until every "Done when" item of the previous one passes. - Prefer the fewest moving parts that satisfy the step. No frameworks, services or dependencies the plan does not name. - Secrets live in `.env`, never in source or logs. Keep `.env.example` current when a variable is introduced. - Do not invent cryptography, security guarantees, APIs or compliance claims. - Add a focused test for every destructive, security-sensitive or data-loss path the plan names. - Run the project checks before declaring a phase complete, and record any deliberate shortcut in the README under "Tradeoffs". ## Known traps - Attaching a connector to the coordinate where it was drawn means every shape move leaves lines pointing at empty space, and on a diagram of any size the cleanup takes longer than the drawing did. Bind to ports and recompute the endpoint from the shape's current geometry. - Routing that finds the shortest obstacle-free path will happily produce a connector with eleven bends that is technically correct and unreadable. Penalise bends heavily, prefer a slightly longer path with two, and accept crossing another connector rather than adding turns. - Rerouting everything on every change discards the adjustments someone made to get a complex diagram readable, which is often an hour of work, and it happens the instant they nudge one shape. Mark manual routes, preserve them, and surface the ones a change has genuinely broken. - Styling set by hand looks the same as styling derived from data until the data changes, at which point the diagram is confidently wrong and nobody can tell which colours mean something. Derive styling from rules where data exists, and make manually styled shapes visually distinguishable in editing.
# Build plan · Creately A structured diagramming tool where the hard part is not drawing but routing: connectors that find their way around shapes, stay attached when things move, and keep a large diagram readable, plus shapes that hold data so a diagram can be a view of something rather than a picture. Phases are in dependency order. Each ends in a "Done when" list; treat an unticked item as a blocker, not a note. ## Phase 1 · Connectors that stay attached Moving a shape takes its connectors with it. ### Steps 1. Attach to ports, not coordinates The single decision the rest of the build depends on. Files: `src/ports.ts` 2. Recompute endpoints from geometry On move and on resize, both. Files: `src/connectors.ts` 3. Handle shape deletion explicitly A stated rule, not dangling references. Files: `src/delete.ts` ### Done when - [ ] Moving a shape updates its connectors - [ ] Resizing keeps attachment positions correct - [ ] Deletion follows a stated rule - [ ] Simultaneous moves are handled ### Watch out - Attaching a connector to the coordinate where it was drawn means every shape move leaves lines pointing at empty space, and on a diagram of any size the cleanup takes longer than the drawing did. Bind to ports and recompute the endpoint from the shape's current geometry. ## Phase 2 · Routing around things Connectors avoid shapes rather than passing through them. ### Steps 1. Treat shapes as obstacles Passing through a shape is what makes diagrams unreadable. Files: `src/route.ts` 2. Penalise bends heavily Eleven bends is correct and useless. Two is the target. Files: `src/route.ts`, `src/route.test.ts` 3. Keep rerouting interactive A hundred shapes, recomputed on drag. Measure it. Files: `src/route.ts` ### Done when - [ ] Connectors route around shapes - [ ] Routes prefer few bends - [ ] Rerouting feels immediate at a hundred shapes - [ ] An impossible route has a stated fallback ### Watch out - Routing that finds the shortest obstacle-free path will happily produce a connector with eleven bends that is technically correct and unreadable. Penalise bends heavily, prefer a slightly longer path with two, and accept crossing another connector rather than adding turns. ## Phase 3 · Respecting a route someone drew Automatic rerouting never discards a manual adjustment. ### Steps 1. Mark manual routes and preserve them An hour of readability work should survive a nudge. Files: `src/connectors.ts` 2. Surface invalidated routes Rather than silently replacing them. Files: `src/route.ts` 3. Make automatic reset explicit Available, deliberate, never a side effect. Files: `src/connectors.ts` ### Done when - [ ] Manual routes survive unrelated moves - [ ] Invalidated routes are surfaced, not replaced - [ ] Manual routes are visually distinguishable - [ ] Reset to automatic is explicit ### Watch out - Rerouting everything on every change discards the adjustments someone made to get a complex diagram readable, which is often an hour of work, and it happens the instant they nudge one shape. Mark manual routes, preserve them, and surface the ones a change has genuinely broken. ## Phase 4 · Shapes that carry data A diagram can be a view of information rather than a picture of it. ### Steps 1. Define typed fields per shape kind Validated on entry, like any schema. Files: `src/fields.ts` 2. Drive styling from rules So colour means something and updates when the data does. Files: `src/style-rules.ts` 3. Match imports to existing shapes By a key, not by position. Duplicating on every import is the failure. Files: `src/import.ts` ### Done when - [ ] Shape fields are typed and validated - [ ] Styling rules apply and update with data - [ ] Manual styling is distinguishable while editing - [ ] Import updates rather than duplicating ### Watch out - Styling set by hand looks the same as styling derived from data until the data changes, at which point the diagram is confidently wrong and nobody can tell which colours mean something. Derive styling from rules where data exists, and make manually styled shapes visually distinguishable in editing. ## Not in this build - Real-time collaboration. - Large shape libraries. - Reverse engineering from code or infrastructure. - Presentation and animation. ## After v1, if you want it - Swimlanes and containers, which change routing constraints considerably - A data panel showing the diagram as a table, since some questions are easier answered there - Diff between two versions of a diagram, which is what makes them reviewable
# Copy to .env and fill in. Never commit .env; this file documents it. # Required. Diagram files. A diagram is a document and should behave like one. DOCUMENTS_DIR=~/Documents/diagrams # Required. How strongly bends are avoided. High, because readability beats path length. ROUTE_BEND_PENALTY=10 # Required. Routing runs on drag. Beyond this it must fall back rather than stutter. ROUTE_TIMEOUT_MS=16 # Required. Present as a constant. Placement often carries meaning a layout algorithm cannot see. AUTO_LAYOUT_ON_CHANGE=never # Required. An hour of readability work should survive a shape being nudged. PRESERVE_MANUAL_ROUTES=always # Required. Where canvas performance starts to degrade, made explicit rather than discovered. MAX_SHAPES_WARNING=500
# Creately · product brief ## Problem The visible diagramming + whiteboard loop is buildable, but a credible replacement needs more than the first screen. Creately earns its keep through interaction polish, collaboration, so expect a weekend or multi-day build and a narrower personal scope. ## Product outcome A diagram tool whose connectors stay attached and route themselves sensibly, whose manual adjustments survive, and whose colours mean something because they come from the data. ## Target user A builder who needs a maintainable product foundation, not a one-off demo. ## Required capabilities - Node.js 22 - modern browser - no account required ## Explicit non-goals for v1 - Real-time collaboration. - Large shape libraries. - Reverse engineering from code or infrastructure. - Presentation and animation. - large template libraries - high-fidelity import and export - presentation and enterprise controls - multiplayer cursors and comments ## Success criteria - Moving a shape is confirmed to update its connectors - Connectors are confirmed to route around shapes with few bends - Manual routes are confirmed to survive unrelated moves - Data-driven styling is confirmed to update with the data - Automatic layout is confirmed never to run unasked
# Build brief · Creately The one-shot brief this plan expands. `BUILD_PLAN.md` (or `MILESTONES.md`) is the same sequence broken into steps and checks; where the two disagree, the plan wins. Build me a diagram canvas where connectors route themselves and shapes carry data to replace Creately. Build it in phases, in the order below. Do not write the whole thing in one pass. Finish a phase, run its "Done when" check, fix what fails, and only then start the next phase. ### Stack (fixed, do not substitute) - Canvas: A scene graph with shapes, ports and connectors as first-class objects · a connector attached to a coordinate detaches the moment anything moves - Routing: Orthogonal routing with obstacle avoidance · connectors crossing through shapes is what makes diagrams unreadable - Layout: Automatic arrangement as an option, never as a surprise · auto-layout that runs unasked destroys deliberate placement - Data: Shapes with typed fields and views derived from them · the difference between a diagram and a picture of one - Runtime: TypeScript with a local application and file-based documents · a diagram is a document and should behave like one ### Data model (create this before Phase 1) - documents(id, name, canvas_json, updated_at) - shapes(id, document_id, kind, x, y, width, height, style_json, data_json) - ports(shape_id, name, side, offset) · connectors attach to ports, not to coordinates - connectors(id, document_id, from_port, to_port, route_kind, waypoints_json, label, manual_route) - shape_fields(document_id, kind, field_name, field_type) · the schema for a shape kind's data - views(id, document_id, filter_json, style_rules_json) · styling driven by data rather than set by hand - A connector records whether its route was set manually, because automatic rerouting must never discard a route someone drew deliberately. ### Phase 1 · Connectors that stay attached Build: Shapes with named ports, and connectors bound to ports rather than to coordinates. Moving or resizing a shape updates every attached connector. Deleting a shape handles its connectors explicitly. Trap: Attaching a connector to the coordinate where it was drawn means every shape move leaves lines pointing at empty space, and on a diagram of any size the cleanup takes longer than the drawing did. Bind to ports and recompute the endpoint from the shape's current geometry. Done when: Moving a shape updates every attached connector immediately. Resizing keeps connectors attached at the correct relative position. Deleting a shape removes or orphans its connectors by a stated rule rather than leaving dangling references. A connector between two shapes survives both being moved simultaneously. Do not build yet: No routing, layout or data. ### Phase 2 · Routing around things Build: Orthogonal routing that treats shapes as obstacles, with a limited number of bends. Reroute on change. Keep routing fast enough to be interactive on a diagram with a hundred shapes. Trap: Routing that finds the shortest obstacle-free path will happily produce a connector with eleven bends that is technically correct and unreadable. Penalise bends heavily, prefer a slightly longer path with two, and accept crossing another connector rather than adding turns. Done when: Connectors route around shapes rather than through them on a diagram of a hundred shapes. Routes prefer few bends, verified by counting on a complex diagram. Rerouting after a move is fast enough to feel immediate. A connector with no obstacle-free path is drawn with a stated fallback rather than failing. Do not build yet: No layout, data or export yet. ### Phase 3 · Respecting a route someone drew Build: Let a connector's route be adjusted by hand, marking it manual. Preserve manual routes through shape moves where possible, and tell the user when a move has invalidated one rather than silently replacing it. Trap: Rerouting everything on every change discards the adjustments someone made to get a complex diagram readable, which is often an hour of work, and it happens the instant they nudge one shape. Mark manual routes, preserve them, and surface the ones a change has genuinely broken. Done when: A manually routed connector survives moves of unrelated shapes. A move that genuinely invalidates a manual route surfaces it rather than silently rerouting. Manual routes are visually distinguishable from automatic ones. Resetting a connector to automatic is available and explicit. Do not build yet: No data or layout yet. ### Phase 4 · Shapes that carry data Build: Typed fields per shape kind, edited in a panel. Styling rules driven by field values, so colour and border express data rather than being set by hand. Import data to populate shapes. Trap: Styling set by hand looks the same as styling derived from data until the data changes, at which point the diagram is confidently wrong and nobody can tell which colours mean something. Derive styling from rules where data exists, and make manually styled shapes visually distinguishable in editing. Done when: Shape kinds have typed fields validated on entry. Styling rules driven by field values apply automatically and update when data changes. Manually styled shapes are distinguishable from rule-styled ones while editing. Importing data updates existing shapes rather than duplicating them. Do not build yet: No layout or export yet. ### Phase 5 · Layout, export and large diagrams Build: Automatic layout available as an explicit action, never automatic. Export to vector formats preserving text as text. Handle a diagram of several hundred shapes without the canvas becoming unusable. Trap: Running automatic layout on open, or after an edit, destroys deliberate placement that carried meaning, and undo often does not restore it exactly. Make layout something you invoke, applied with a preview, and always undoable in one step. Done when: Automatic layout runs only when invoked and can be previewed before applying. Undo restores the previous arrangement exactly. Vector export preserves text as text rather than outlines. A diagram of five hundred shapes pans and zooms without becoming unusable. Do not build yet: Nothing after this. ### Out of scope (and why) - Real-time collaboration on one canvas, which is a substantial synchronisation problem in its own right. - The large shape libraries the hosted products ship, which is volume work and most of their perceived value. - Reverse engineering diagrams from code or infrastructure, which is a connector per system and never finished. - Presentation and animation features, which is a different product wearing the same interface. ### README must contain - That connectors attach to ports rather than coordinates, which is what keeps them attached - That routing penalises bends heavily, because a correct eleven-bend route is unreadable - That manual routes are preserved and only surfaced when genuinely invalidated - That styling is derived from shape data where rules exist, so colour means something - That automatic layout runs only when invoked, because placement often carries meaning
# Architecture · Creately ## Stack | Part | Choice | Why | | --- | --- | --- | | Canvas | A scene graph with shapes, ports and connectors as first-class objects | a connector attached to a coordinate detaches the moment anything moves | | Routing | Orthogonal routing with obstacle avoidance | connectors crossing through shapes is what makes diagrams unreadable | | Layout | Automatic arrangement as an option, never as a surprise | auto-layout that runs unasked destroys deliberate placement | | Data | Shapes with typed fields and views derived from them | the difference between a diagram and a picture of one | | Runtime | TypeScript with a local application and file-based documents | a diagram is a document and should behave like one | ## Modules Each module has one owner concern and a documented way to replace it. | Module | Owns | How to replace it | | --- | --- | --- | | Ports | Attachment points on shapes. | Not swappable for coordinate binding, which detaches on the first move. | | Routing | Orthogonal paths with obstacle avoidance. | Any algorithm, provided bends are penalised heavily. | | Manual routes | Preserving deliberate adjustments. | Any implementation, provided automatic rerouting cannot silently discard them. | | Data | Typed shape fields and derived styling. | Any store, provided rule-styled and hand-styled shapes stay distinguishable. | | Layout | Arrangement on request with preview. | Any algorithm, provided it never runs unasked. | ## Configuration Every runtime setting is an environment variable documented in `.env.example`, validated at startup, with a safe local default wherever one exists. - `DOCUMENTS_DIR` · required · Diagram files. A diagram is a document and should behave like one. - `ROUTE_BEND_PENALTY` · required · How strongly bends are avoided. High, because readability beats path length. - `ROUTE_TIMEOUT_MS` · required · Routing runs on drag. Beyond this it must fall back rather than stutter. - `AUTO_LAYOUT_ON_CHANGE` · required · Present as a constant. Placement often carries meaning a layout algorithm cannot see. - `PRESERVE_MANUAL_ROUTES` · required · An hour of readability work should survive a shape being nudged. - `MAX_SHAPES_WARNING` · required · Where canvas performance starts to degrade, made explicit rather than discovered. ## Production baseline - Security: least privilege, input validation at every boundary, secret redaction in logs, rate limits on abuse-prone paths, no invented security primitives. - Data: explicit schema and migrations, transactional writes where integrity matters, backup and restore procedures that have been exercised. - Integrations: adapters around third-party providers, idempotent webhook or job processing, bounded retries, timeouts. - Observability: structured logs with request or operation ids, an error-tracking hook, and health and readiness checks where a server exists. - Quality: unit tests for domain rules, integration tests at module boundaries, one end-to-end test of the critical path. ## Decision records For each dependency in the stack table, keep a short note: why it was chosen, its failure mode, and how it is replaced. Do not add infrastructure until a requirement in `PRODUCT.md` justifies it.
# Agent instructions · Creately product build - Read `PRODUCT.md` and `ARCHITECTURE.md` before changing code. The stack is fixed: A scene graph with shapes, ports and connectors as first-class objects, Orthogonal routing with obstacle avoidance, Automatic arrangement as an option, never as a surprise, Shapes with typed fields and views derived from them, TypeScript with a local application and file-based documents. - Implement milestone by milestone from `MILESTONES.md`; keep each change reviewable and leave the application runnable at every commit. - Treat authentication, payments, encryption, imports, webhooks and destructive actions as high-risk boundaries when present. - Never invent cryptography or silently weaken a requirement to make a check pass. - Put every external service behind an interface with a deterministic fake for tests. - Add migrations and rollback or recovery notes for every persistent data change. - Log useful operational context without credentials, tokens, passwords or personal data. - Update documentation and run every check before completing a milestone. ## Known traps - Attaching a connector to the coordinate where it was drawn means every shape move leaves lines pointing at empty space, and on a diagram of any size the cleanup takes longer than the drawing did. Bind to ports and recompute the endpoint from the shape's current geometry. - Routing that finds the shortest obstacle-free path will happily produce a connector with eleven bends that is technically correct and unreadable. Penalise bends heavily, prefer a slightly longer path with two, and accept crossing another connector rather than adding turns. - Rerouting everything on every change discards the adjustments someone made to get a complex diagram readable, which is often an hour of work, and it happens the instant they nudge one shape. Mark manual routes, preserve them, and surface the ones a change has genuinely broken. - Styling set by hand looks the same as styling derived from data until the data changes, at which point the diagram is confidently wrong and nobody can tell which colours mean something. Derive styling from rules where data exists, and make manually styled shapes visually distinguishable in editing. - Running automatic layout on open, or after an edit, destroys deliberate placement that carried meaning, and undo often does not restore it exactly. Make layout something you invoke, applied with a preview, and always undoable in one step.
# Delivery milestones · Creately Estimated effort: **multi-day** for the indie phases; the production-only milestones add the trust and operability layer. ## M1 · Connectors that stay attached Moving a shape takes its connectors with it. ### Steps 1. Attach to ports, not coordinates The single decision the rest of the build depends on. Files: `src/ports.ts` 2. Recompute endpoints from geometry On move and on resize, both. Files: `src/connectors.ts` 3. Handle shape deletion explicitly A stated rule, not dangling references. Files: `src/delete.ts` ### Done when - [ ] Moving a shape updates its connectors - [ ] Resizing keeps attachment positions correct - [ ] Deletion follows a stated rule - [ ] Simultaneous moves are handled ### Watch out - Attaching a connector to the coordinate where it was drawn means every shape move leaves lines pointing at empty space, and on a diagram of any size the cleanup takes longer than the drawing did. Bind to ports and recompute the endpoint from the shape's current geometry. ## M2 · Routing around things Connectors avoid shapes rather than passing through them. ### Steps 1. Treat shapes as obstacles Passing through a shape is what makes diagrams unreadable. Files: `src/route.ts` 2. Penalise bends heavily Eleven bends is correct and useless. Two is the target. Files: `src/route.ts`, `src/route.test.ts` 3. Keep rerouting interactive A hundred shapes, recomputed on drag. Measure it. Files: `src/route.ts` ### Done when - [ ] Connectors route around shapes - [ ] Routes prefer few bends - [ ] Rerouting feels immediate at a hundred shapes - [ ] An impossible route has a stated fallback ### Watch out - Routing that finds the shortest obstacle-free path will happily produce a connector with eleven bends that is technically correct and unreadable. Penalise bends heavily, prefer a slightly longer path with two, and accept crossing another connector rather than adding turns. ## M3 · Respecting a route someone drew Automatic rerouting never discards a manual adjustment. ### Steps 1. Mark manual routes and preserve them An hour of readability work should survive a nudge. Files: `src/connectors.ts` 2. Surface invalidated routes Rather than silently replacing them. Files: `src/route.ts` 3. Make automatic reset explicit Available, deliberate, never a side effect. Files: `src/connectors.ts` ### Done when - [ ] Manual routes survive unrelated moves - [ ] Invalidated routes are surfaced, not replaced - [ ] Manual routes are visually distinguishable - [ ] Reset to automatic is explicit ### Watch out - Rerouting everything on every change discards the adjustments someone made to get a complex diagram readable, which is often an hour of work, and it happens the instant they nudge one shape. Mark manual routes, preserve them, and surface the ones a change has genuinely broken. ## M4 · Shapes that carry data A diagram can be a view of information rather than a picture of it. ### Steps 1. Define typed fields per shape kind Validated on entry, like any schema. Files: `src/fields.ts` 2. Drive styling from rules So colour means something and updates when the data does. Files: `src/style-rules.ts` 3. Match imports to existing shapes By a key, not by position. Duplicating on every import is the failure. Files: `src/import.ts` ### Done when - [ ] Shape fields are typed and validated - [ ] Styling rules apply and update with data - [ ] Manual styling is distinguishable while editing - [ ] Import updates rather than duplicating ### Watch out - Styling set by hand looks the same as styling derived from data until the data changes, at which point the diagram is confidently wrong and nobody can tell which colours mean something. Derive styling from rules where data exists, and make manually styled shapes visually distinguishable in editing. ## M5 · Layout, export and large diagrams (production only) Automatic arrangement helps when asked, and the diagram exports cleanly. ### Steps 1. Make layout an explicit action with preview Placement often carries meaning that a layout algorithm cannot see. Files: `src/layout.ts` 2. Export text as text So a diagram can be searched, edited and read by assistive tools. Files: `src/export.ts` 3. Keep the canvas usable at scale Five hundred shapes. Measure pan and zoom, do not assume. Files: `src/canvas.ts` ### Done when - [ ] Layout runs only when invoked, with preview - [ ] Undo restores the previous arrangement exactly - [ ] Export preserves text as text - [ ] Five hundred shapes pan and zoom acceptably ### Watch out - Running automatic layout on open, or after an edit, destroys deliberate placement that carried meaning, and undo often does not restore it exactly. Make layout something you invoke, applied with a preview, and always undoable in one step.
# Operations · Creately ## Backup Diagrams are documents and belong wherever your ordinary document backups reach. The data behind data-driven diagrams lives elsewhere and should be backed up with its source rather than here. ## Restore Restore and confirm manual routes survived, since they represent the most human effort in a diagram and their loss is not visible until someone opens the file and finds it messy. Do a restore drill before the first real user, and write the date here when it passes. ## Monitoring For a local tool the measurement that matters is routing time under drag, which degrades as diagrams grow and turns a fluid tool into a stuttering one gradually enough that nobody reports it. ## Incident checklist Connectors detaching or routing through shapes is the visible failure, and it points at either port binding or the obstacle set being stale. Both are reproducible on a saved document rather than needing a live session. 1. Contain the issue without destroying evidence or user data. 2. Record the timeline and affected scope. 3. Rotate exposed secrets and revoke compromised sessions or credentials. 4. Restore from a verified backup when needed. 5. Document the root cause, the remediation and the regression test. ## Release gate - [ ] Moving a shape is confirmed to update its connectors - [ ] Connectors are confirmed to route around shapes with few bends - [ ] Manual routes are confirmed to survive unrelated moves - [ ] Data-driven styling is confirmed to update with the data - [ ] Automatic layout is confirmed never to run unasked ## Launch constraint Do not market omitted Creately capabilities as implemented. The non-goals in `PRODUCT.md` remain user-visible limitations until they are deliberately delivered.
# Copy to .env and fill in. Never commit .env; this file documents it. # Required. Diagram files. A diagram is a document and should behave like one. DOCUMENTS_DIR=~/Documents/diagrams # Required. How strongly bends are avoided. High, because readability beats path length. ROUTE_BEND_PENALTY=10 # Required. Routing runs on drag. Beyond this it must fall back rather than stutter. ROUTE_TIMEOUT_MS=16 # Required. Present as a constant. Placement often carries meaning a layout algorithm cannot see. AUTO_LAYOUT_ON_CHANGE=never # Required. An hour of readability work should survive a shape being nudged. PRESERVE_MANUAL_ROUTES=always # Required. Where canvas performance starts to degrade, made explicit rather than discovered. MAX_SHAPES_WARNING=500
$ choose a build depth, inspect the files, then open the complete pack in your agent
Creately: The shapes are easy; customers pay for low-friction editing, reliable exports, collaboration, and a canvas that never fights them.
xlarge template libraries
xhigh-fidelity import and export
xpresentation and enterprise controls
xmultiplayer cursors and comments
Don't feel like building it? These folks already made it free.
no votes, no pay-to-list · just what's real
Creately pricing
| plan | monthly | annual (per mo) | what you get |
|---|---|---|---|
| free | $0/workspace | $0/workspace | 3 infinite workspaces; unlimited canvases and collaborators; 45 items per canvas; 1 folder; 2 imports |
| starter | $8/workspace | $5/workspace | Unlimited canvases; 1,000 items per canvas; 20 active folders; 5 GB storage; unlimited imports; 30-day version history |
| team | $8/user | $5/user | Unlimited canvases; 1,500 items per canvas; 30 active folders; 10 GB storage per user; unlimited imports; 30-day version history |
| business | $149/workspace | $89/workspace | Unlimited users; up to 3,000 items per canvas; 100 active folders; 30 GB storage; 50 databases with 500 items each; 1-year version history |
| enterprise | custom | — | Custom users and deployment; unlimited storage, folders and canvas items; permanent version history; SSO, SCIM, audit and admin controls |
free tier3 infinite workspaces, unlimited canvases/collaborators, 45 items per canvas, 1 folder and 2 imports; numeric storage cap not published
billingfree + monthly and annual self-serve plans; annual Starter/Team are $5 versus $8 monthly, and Business is $89 versus $149 monthly
hidden costsTeam is per user; Enterprise-only capabilities can be sold as Business add-ons; AI usage allowances and add-on prices are not numerically published; taxes may apply
verified 2026-08-14 · source ↗
Vibecode Creately
Kinda. The core of Creately is buildable in a weekend with the prompt on this page, but there are real gaps: large template libraries, high-fidelity import and export. Read the honest list above before committing.
How much does Creately cost?
Creately's pricing is usage-based or varies by plan · The official pricing URL is recorded, but a stable current amount was not safely recoverable in this pass. Do not publish a number until rechecked..
What do I lose by replacing Creately?
Honestly: large template libraries; high-fidelity import and export; presentation and enterprise controls; multiplayer cursors and comments. If any of those are load-bearing for you, keep paying.
Is there an open-source alternative to Creately?
Yes: AFFiNE (Notion and Miro sharing one canvas: collaborative docs, databases, diagrams, whiteboards, and planning views; dedicated PM automation is thinner.) The prompt is for when you want it exactly your way.