Letting readers compare the diagrams themselves
My Digital Platform · in progress
- Spreadsheet
- ContainsBlue Sheet Event
- Role
- Editorial direction, interaction design, SVG rendering, shared component architecture, and animation/export workflow.
- Timeframe
- 2026
- Technologies
- React
- TypeScript
- SVG
- Storybook
- Skills
- Interaction design
- Component architecture
- Data visualization
- Animation
- Accessibility
Built a shared SVG renderer for diagrams with explicit layouts and reader-controlled states. Static figures and timed animations use the same components, with interaction added where the comparison needs it.
About the project
My sites, shared interface components, and content publishing system. The engineering site, gideonjr.dev, is one application within the platform. The wider scope includes the consulting and creative-practice surfaces and the components they can share.
- Timeframe
- Current
Overview
Showing the change behind a decision
I organized this site around individual engineering decisions so someone considering me for a role could see how I approached the work. Explaining those decisions often means showing a change: which part of a system I moved, which relationship I renamed, or who gained control over an interaction.
Product screenshots help establish what an interface looked like and what someone could do with it. They do not always show the model underneath it, and some of the work has no imagery I can publish. I needed a way to make those changes visible alongside the writing.
I chose diagrams with explicit layouts and selectable states, so readers could compare the relevant parts of a system at their own pace.
Keeping the comparison in place
The Blueprint domain-model decision gave me a concrete requirement. The container and its child changed from Spreadsheet and Blue Sheet Event to Main Event and Activation. The relationship between them stayed the same. The curation types, Bluelist and Bluelist Item, kept their names.
For that explanation, the reader needs to recognize the same records under different names. If changing a label also rearranges the diagram, they have to locate everything again before they can compare it. Movement would suggest a structural change that the rename did not make.
Two static figures could show both versions. With enough room, that would work. I wanted each version to use the available width while preserving the positions of the elements shared between them. Readers could switch back to check a detail.
That requirement shaped the renderer: stable identities, explicit positions and dimensions, and changes authored separately from the base layout. Some decisions need a node to move or a relationship to disappear. Those changes should be deliberate parts of the explanation.
Solution
Drawing the system as authored states
The implementation started with an animated Blueprint model diagram. I composed it from React components that rendered SVG nodes, field rows, labels, and connectors. That gave me direct control over the layout and produced artwork I could render in the browser or sample for a video.
I had originally expected to start with React Flow. I did not run a comparative evaluation against it. The SVG experiment already gave me a working approach for the diagrams I was authoring, and I could reuse its composition for export. I continued from that implementation.
In the shared renderer, a scene defines the nodes and relationships, then each state specifies what changes. A rename can change a label while retaining the node’s identity and position. Another state can add a node, remove a connection, or show a different field list. The renderer also supports explicit boundaries and annotations, so those details do not have to become part of the node itself.
The first idea was a two-state toggle. Reviewing the requirements for thirteen planned decision diagrams revealed that two states would not cover all arguments. Some compare versions, some compare alternatives, and some need a sequence of three steps. I kept those distinctions in the scene model and left the choice of controls with the page using it.
- Spreadsheet
- ContainsBlue Sheet Event
Separating playback from inspection
The animated reel introduced the model without asking anyone to operate it. An inspection view needed a different relationship with time: readers should be able to stay on a state, return to the previous one, and compare details without waiting for the animation to come around again.
I separated the drawing from the clock. The same components can render one static state, respond to a state selector, or display a frame from an authored timeline. Animation does not need a second set of diagram components.
The timeline accepts an explicit time, which also lets the export workflow render frames without recording the screen. Playback adds a clock on top of that sampler. The examples include play, pause, and seek controls, as well as a reel with no visible controls.
Reduced motion stops automatic playback. A page can show a complete static state or let the reader switch states immediately. The explanation still needs to be available when nothing is moving.
Building the common pieces once
I needed the same drawing capabilities for Blueprint models, the two Black Wall Street Journey content models, and other system decisions. That made the boundary of the shared code important.
I put the canvas, node frames, connectors, boundaries, state resolution, and timing into a package. The consumer owns the actual models, coordinates, captions, and sequence. A custom node can replace the standard field body or supply its own SVG shape without adding a project-specific component to the renderer.
I also chose to build that common foundation before making separate implementations for the first decision pages. Building each figure independently and extracting the overlap later would mean revisiting the same diagrams as their own components were replaced.
The first package used the @diagrams/react namespace. Its examples live in one Storybook for the platform, where I can inspect static scenes, version changes, custom nodes, and playback together. That gives the shared behavior a place to be checked as the consumers develop.
The package does not decide whether a diagram’s relationships are correct or whether its sequence explains the decision. Those remain authoring responsibilities. It also leaves video encoding outside the React components.
Keeping the labels readable
The Blueprint reel exposed a more immediate constraint. I wanted space around the diagram, similar to the padding around a pair of product cards in another composition. When I reduced the diagram to make that space, the labels became too small to read.
I enlarged it again and kept the warm grey canvas. I also increased the playback speed after the earlier version felt slow. Those revisions came from looking at the composition at its intended 1600 × 1000 output size.
A model diagram has a different reading load from a product card. Its labels and connections have to remain legible together. I could adjust the surrounding treatment, but the amount of whitespace had to follow the content.
Reflection
Making the comparison readable
The Blueprint experiment gave me a rendering approach I could carry into a shared component package. Building static scenes, reader controls, and timed playback on the same artwork also gave me a way to choose the presentation for each explanation without rebuilding its nodes and connectors.
That reuse comes with work I now own. Layouts and routes need attention when the argument changes, custom shapes need to fit their content, and controls need to remain usable alongside the diagram. A shared renderer reduces duplication; it does not remove those decisions from each page.
The implementation has working examples, and I verified state switching, playback, pause, and seeking in the browser. This page now uses the Blueprint rename as a concrete reader-controlled comparison. I have not evaluated whether readers understand the decisions better with these diagrams.
The question I want to test is whether someone can identify the relevant change and explain why it mattered after using the comparison. A working toggle is only one part of that. If a static figure communicates the same point more clearly, I can use the static state the renderer already provides.