DraftThis article is currently in draft mode

Design Engineering Rectangles

October 15, 2025

Design Engineering Rectangles#

[S1] Hook: Rectangle hydra problem#

Hi, my name is Cole. I work at Phosphor where we are tackling extremely dense UI problems. At previous companies, I had experienced very similar things. But the scale out was always a challenge I had gone from in my career I've gone from a basic view-model-controller patterns to a form of MVVM (model-view-view-model) and then at my previous start-up, I ventured into an architecture that was in Rust. While writing in Rust, we found that the ease due to how the borrow checker was working made it the easiest way to do this is to write it in Rust.

The most easy way to do things like reactivity was through a pattern called entity-component-systems, which allow you to create detached components from entities where entities are themselves just IDs that you use to look up components in a sparse set or... a type map.

What this yielded was that in files that needed to do some kind of complex logic, instead of importing an entire AST structure, you had a parsed version and type checking and errors all as separate components, so one system could handle the raw structure too. Parsed form. Then another system could take parsed form too. The two errors and suggestions and a separate system could handle the parsed form to suggestions. Yet another system says, "Okay, now let's map those suggestions to UI notifications", and each one of these systems was able to sort of build on each other in an extremely scoped way where they own each system individually only cared about the components between them.

I had previously used this pattern not just because I was in Rust previously, but I grew to love the pattern for the properties that gave me for testing and reasoning. I had the suspicion early on here at Phosphor that we could leverage this pattern to improve our UI building because every rectangle has a lot of complexity behind it and you have to figure out how you're going to scale out that complexity.


Let me take that step back and tell you kind of like, well, see if I can paint the picture of the problem that you know we're experiencing at Phosphor. If we start with one input box, you're going to imagine there's a little there's some hooks, there's some state management, there might be some persistence involved, and you kind of start. Then we add a little bit more. We add validation, and validation will report if there's an error or something. This is where you're thinking now I need system-wide undo and redo, which is going to touch a few files and need to link things together. Then you say, "Okay, well, I have a shit. I need to also support collaborative editing so multiple people can see what each other are doing and maintain kind of a collaborative feature." This is going to touch a bunch of files because now we're talking about the way you present things and it's the talking about your sync layer. Your front-end needs to maybe be reworked so that the sync layer is actually the hook that you're using and not some other persistence thing. You refactor that. "Okay, cool, normal things." But we start to notice that unless you adopt a full sync engine tool, say like Yjs or Loro + Loro-Mirror, the problem becomes very big already.

[hole] - example of components

But things don't stop there. All we've categorized so far is very basic, like features for any authorable environment. These are table stakes basics. Maybe some authorable environments don't need validation pieces, but let's continue because now we have to talk about the things that are expensive at Phosphor. We go from what we just described to having a number of additional features like comparisons, so you are comparing a single value in that input to another value, and where does that other value come from? For us, it comes from a version control state. We maintain a version-controlled graph of all the changes and groups of changes with proposals and where every change came from, and we present information about every value's origin in the UI. Right here, you start to wonder, "Okay, well, if I'm going to present all this information in the UI, how am I going to manage that complexity? I have undo/redo, I didn't even mention key bindings yet, which is another thing you need to consider. Then we're talking about diff views that we're seeing like before and afters, and that has its own set of layers that we don't have to get into, but it's a lot. I'm not even sure I could continue. We could talk about keyboard maps and customizable key bindings, and we can talk about selection state, where you have multiple things that are selected, and then you have copy/paste. You have that, the yada yada, a lot that ends up going into this, and that's how we found ourselves here.

And here forward, I'm thinking to myself, "Well, I know how we scaled the complexity at Story.ai, and that was through this ECS pattern. How will that adapt to my favorite approach to UI state management today, which is the view model pattern?" I started thinking about that because I practically maintained our company's ECS crate that we were specifically using and we had a lot of opinions about how to build up that crate and make it have better errors and make it more usable and so forth. I thought, "Okay, well, maybe we could adapt a lot of that idea into a library that we can use here at Phosphor," and that is where I started with WorldState. WorldState is a set of tools that allows you to build up a UI state without any reliance on React and with this sort of decoupled approach that I liked from structuring things as view models and vs. views and things that I like from ECS. Right now, our WorldState is backed by Jotai Atoms, which is just a reactive container of some kind and reactive values, right? Signals and so forth. We're considering adapting WorldState to use Livestore as our reactivity graph next.

[S2] ECS solution translated to UI#

So I was thinking to myself, "What are the characteristics going to be like? Because unlike Rust, we have these reactive containers and we don't have the frame-by-frame computation thing that most games have. We just have components that contain atoms, and when we want to create the equivalent of a system, we are going to create a plugin. A plugin will base on the fact that if there's an entity created with these components, then I can provide these components and there's never a need to add or remove components from it. You just simply have this sort of plugin architecture."

Game developers faced this exact problem a decade ago and found an elegant solution: entities, components, and systems. The pattern translates directly to UI engineering.

[hole]("Example of a plugin")

The key insight: add features by adding plugins and components, not by editing old code. Your existing validation logic never changes when you add collaborative cursors. Your undo system remains untouched when you introduce AI suggestions.

WorldState isn't a game engine—it's an ECS-inspired approach for expressing UI concerns as composable data and behavior.

[S3] Interactive proof: Scrolly feature accumulation#

[Interactive scrollytelling demo showing rectangle gaining features step by step]

Watch a simple rectangle evolve: Base → validation → undo → diffs → presence → focus → commands → AI → inline visualization.

Each step demonstrates additive architecture. The validation plugin doesn't know about undo. The undo plugin doesn't know about presence. The presence plugin doesn't know about AI suggestions. Yet they all compose cleanly because they operate on shared entity state through well-defined component interfaces.

Toggle the layer chips at the bottom to see how features compose. Turn validation off and on—notice how it doesn't break undo or cursors. Enable all layers simultaneously—no conflicts, no special coordination code needed.

Reality check: if your app is a simple contact form, you don't need this. But if your rectangles feel like living systems with multiple interacting concerns, this architecture prevents the coupling nightmare.

[S4] Interactive proof: Keyboard/focus composition#

[Working demo: grid navigation with context-sensitive actions palette]

This demo shows three complex UI concerns working in harmony: selection, focus, and context-sensitive commands.

Selection (what's highlighted) and focus (where keyboard input goes) are different concepts that can diverge then sync. In this grid, you can select multiple cells with Shift+click while focus remains on a single cell for typing. The selection and focus plugins coordinate through shared component state, not direct coupling.

Navigate with arrow keys—the focus moves, and the actions palette updates to show contextually relevant commands. Hit Spacebar to select the focused cell. Use Shift+arrows to extend selection. Each behavior is handled by a separate plugin responding to component state changes.

The power emerges from composition: KeyboardPlugin + SelectionPlugin + ActionsPlugin working together without knowing about each other's implementation details.

[S5] When to use vs avoid#

This architecture shines for certain types of applications and can be overkill for others.

Great fit if you're building:

  • Collaborative editors where multiple people edit the same document simultaneously
  • Dashboards with cross-panel effects where selecting data in one chart filters others
  • Complex modeling tools with multiple overlapping interaction modes
  • Professional workflows requiring deep keyboard navigation and shortcuts

Probably overkill if:

  • You're building a basic CRUD application with standard forms
  • Your UI is mostly static content with minimal interactivity
  • You have a small team and simple requirements

Design engineers welcome: The more interaction layers your application has, the more this pattern will help. If you find yourself building "features that affect other features," you're in the sweet spot.

The architecture pays for its complexity by preventing coupling debt. Early investment in entity-component structure pays dividends when you need to add the fifth, sixth, and seventh layers of interaction.

[S6] Community engagement conclusion#

Your rectangle doesn't have to be a hydra.

We're collecting UI engineering war stories and solutions like this one. What's your rectangle horror story? What tools have you discovered that tame coupling nightmares in complex interfaces?

Share your dev tooling discoveries with us—we'll feature the best ones and build a knowledge base of battle-tested patterns for UI engineers.

Send us a DM, or check out our careers page if you're the kind of engineer who sees these patterns and wants to build tools that make them easier to implement.

The future of UI engineering is compositional. Let's build it together.