A Library-Agnostic Geometry Editor That Runs Without a UI
Frontend Universal Interactive Geometry Editor: Design Series Guide
1. Why Write This
Most frontend developers have encountered the requirement to "draw something on a map." Drawing a point, connecting a line, or outlining an area seems simple, but turning it into an editor that can be integrated by business systems and extended by others is where most available tools fall short:
- Some are deeply coupled with a specific UI — the editor lives inside its own panel, making it impossible for the business to reskin or embed it.
- Some only support a single map library — locked to Leaflet or Cesium, requiring a rewrite for a different scenario.
- Some pile drawing, editing, undo, and layer tree logic together, where changing one part breaks another, making developers increasingly afraid to touch it.
What they lack is not functionality, but an engineering aesthetic: making an editor as trustworthy as a library — with clear boundaries, unidirectional dependencies, composability, replaceability, and long-term maintainability.
Thus came this skill (geometry-interactive-editor) and this series of articles.
https://github.com/maanfa/skills/tree/master/skills/geometry-interactive-editor
They essentially do two things:
- Propose applicable scenarios: An interactive geometry editor is not just for "maps" — 2D canvases, 3D scenes, and any canvas geometry editing are its stage; it should exist cross-library, UI-less, and purely imperative.
- Summarize lessons learned: These are the design trade-offs forced by years of developing editing features, stepping into pitfalls, refactoring, and being pushed by "integration requirements." If it can help readers and fellow practitioners avoid detours, that would be an honor for me.
There is no mysticism in this series, only "why it's divided this way, and when you can skip it."
2. Overall Design Overview
First, look at a "master diagram"; each subsequent article will expand on it:
Key points for reading the diagram:
- The dashed box = the boundary of the "reusable library" delivered by this design: The host (above) and the map library (below) are outside the box. The library has only two interfaces to them — external events / imperative API, and coordinate contract / rendering adaptation.
- The Facade class is the sole entry point: The host only faces it; it assembles a set of controllers, where hotkeys and cursors are optional.
- Drawers / Modifiers combine capabilities through the Strategy pattern, and Elements gain "hoverable / editable" capabilities via
Hoverable / Editablemarkers (not expanded in the diagram, see articles 3 and 4). - The Adapter sits at the outermost layer: It implements coordinate conversion, translating the core into rendering for a specific map library — this is the boundary of "library-agnosticism."
3. Two Classic Flows
Here's a sneak peek at two "minimum closed loops" to feel what the interaction between the host and the library looks like (full versions in articles 4 and 5).
Drawing a polygon:
sequenceDiagram
actor U as User
participant F as Facade
participant D as Drawer
participant A as MapAdapter
U->>F: startDraw('polygon')
loop Each vertex click
U->>D: leftdown (via MouseManager)
D->>D: Strategy appends vertex
end
U->>D: doubleclick to finish
D-->>F: draw:finished
F->>A: updateElement (incremental render)
Dragging a vertex:
sequenceDiagram
actor U as User
participant F as Facade
participant M as Modifier
participant A as MapAdapter
U->>F: select(id) + startEdit(id)
F->>M: Create vertex handles
U->>M: Drag handle
M-->>F: edit:vertex-dragged
F->>A: updateElement (incremental render)
A common flavor in both: the host only touches the Facade, drawing/editing logic never directly touches the map library, and rendering always goes through the adapter.
4. Series Articles
- Article 1 - The Entry Object and Its Members The role of the Facade, controller assembly, Cesium / MapLibre examples | What exactly does the host face?
- Article 2 - Interaction Event Flow Mouse event manager, hotkey context, global event mechanism | How are inputs and events organized?
- Article 3 - Data Object Design Static data objects, no selection/hover state, snapshots | What should a data object look like?
- Article 4 - Drawing, Hovering, and Editing Vertical design of strategy objects + horizontal arbitration of race conditions | How do multiple modes coexist?
- Article 5 - Auxiliary Element Design Extensibility brought by the editing auxiliary role layer | How do handles and transformers grow out?
- Article 6 - Supporting Facilities and Engineering Style specifications, multi-library adaptation, coordinates, logging, cursors, engineering | How are supporting facilities defined?
- Article 7 - Design Patterns and Principles Sweeping across the entire series, converging into rules | What are the patterns and principles behind this design?
5. Reading Order
1 → 2 → 3 → 4 → 5 → 6 → 7. Each article is independently readable, but later ones will reference concepts from earlier ones; each article ends with "When to use / When not to" — because good design also knows when to stop where it's not needed.
6. Diagram Legend Conventions
All diagrams in the text are mermaid:
flowchart: Process / Data flowsequenceDiagram: SequencestateDiagram: State machine
May this body of work spare a fellow practitioner, agonizing late at night over "how to get this editor integrated," a little bit of struggle.