I want to start with a concrete picture. A growth analyst opens a dashboard every morning. She scrolls past four blocks that have nothing to do with her job to reach the one chart that runs her entire day. She has done this for two years. The app greets her like a stranger every single time. The layout is operating exactly as designed and still failing her completely.
The root problem is architectural. A fixed layout is a static assertion that every user has the same priorities. That assertion is false the moment a second user logs in. A B2B product analytics tool might have eight widgets. The developer who built it checks the API error log first. The marketing manager checks acquisition charts. The support lead checks ticket volume. The layout reflects whoever wrote the design spec. Every other user pays a small tax on every single session.
Internal tools are worse. Finance, HR, and engineering share an admin panel built for whoever made the loudest request when the panel got built. I have seen internal tools where entire sections go untouched by entire teams for months. The surface area of the product is wrong for almost everyone using it.
The same problem shows up in onboarding flows. New users land and see the full product at once. The blocks they return to tell you what their workflow actually is. The blocks they scroll past tell you what to move down. A layout that responds to those signals by session three feels faster to navigate, because it is.
Creator tools surface the clearest version of this. A writing platform with a writing editor, a distribution panel, an analytics board, and a monetization section. Most writers regularly use two of those four. The layout has no way to know which two without watching where attention actually goes.
I built a three-layer system to solve this. The first layer is a CLI tool. A CLI (command-line interface) tool is a program you run in your terminal during the build process. It scans your component tree and tags every block with a deterministic identifier derived from the file path and element position in the source. Deterministic means the identifier stays identical across re-runs and across team members. The tags survive deploys.
The second layer is a browser SDK. An SDK (software development kit) is a set of pre-written functions you import into your project. This one attaches event listeners to every tagged block and measures two things: click events and dwell time. Dwell time is how long a user's viewport overlaps with a block during an active session. The SDK sends these events to your own API route, a server endpoint you own, on your infrastructure.
The third layer is a scoring engine that runs server-side. It takes the raw engagement events and produces a score for each block per user. Recent behavior weights heavier than old behavior through a time-decay formula. The formula multiplies each event's contribution by a coefficient that shrinks as the event ages. A click from yesterday matters more than a click from three weeks ago. The engine re-ranks the block order every time the user loads the interface.
The privacy model is a first-class design decision. All event data routes through the developer's own server. There are zero third-party recipients. Deletion is built into account deletion, so when a user removes their account, their personalization data goes with it. I made that a requirement because it removes an entire class of compliance conversation.
The developer experience was the hardest thing to get right. I wanted install time under ten minutes. The system ships as three npm packages, two API routes, and no hosted backend to manage. You install the packages, wire the two routes, wrap your layout component, and the default layout serves every user who has zero history. Personalization activates on the first session and updates from there.
The identifier system deserves its own explanation because it is what makes the whole thing maintainable at team scale. Each block's ID is derived from where it lives in the source code. When a developer on your team rebuilds the project or adds a new block, every existing identifier resolves to the same value it had before. There is no migration step and no manual ID management.
A fixed layout bets that the person who wrote the spec and the person sitting in the chair share the same job. A layout that watches behavior and responds to it serves the actual person, not the imagined one. The code is small enough to read in an afternoon, runs entirely on infrastructure you already own, and the architecture is open to extend. Install instructions and the full documentation are at to.omrajguru.com/Hwp2.
Top comments (0)