SouthpawStrings, my music platform for left-handed guitarists, has a practice Desk. It started as a product feature: theory tools and a practice player in windows that a guitarist can drag, snap into place and keep arranged their way. The code that managed those windows proved itself again and again. It kept windows from overlapping, pulled them into line when dragged close to each other, let people undo changes, and recovered cleanly from bad saved data. In August 2026 I moved it into its own library, @denley/desk-engine. It is written in TypeScript and has zero runtime dependencies (it needs no other packages to run). I publish it to my own npm registry, a private store for JavaScript packages, so my other projects install it like any other package.

The engine handles the parts every desk needs, so no app has to write them again. It arranges windows so that none overlap. It pulls a dragged window into line with its neighbours, and snaps it to half, a quarter or all of the screen when you drag it to an edge. It can keep chosen windows always on top. It has a switcher that lists windows in the order you last used them, and it lets you move between windows by direction (“which window is to my left?”). It also provides undo, a “cloth” drag that makes a window lean and settle as it moves, and a repair step that turns any damaged saved layout back into a working desk. Its animations carry windows into the dock and back, fold them up into their title bars, and close them. The movements are short, can be interrupted, and respect your device’s reduced-motion setting.

Each app that uses the engine supplies only two things. The first is a catalog: the list of windows that can appear on its desk, with their sizes and limits. The second is a small set of rules for its own settings that are saved with the layout (for SouthpawStrings, things like the musical key and instrument). Everything else comes from the library, including the shared React window parts: the frame, dock, switcher and drag handling. So every app that uses it behaves the same way, and none can slowly start to behave differently.

Why it matters

One engine, four products, the same behaviour everywhere

Proven first, shared laterProduct code became a libraryThe desk worked inside one product before I made any of it general. The engine keeps the rules that took effort to get right: how each window is identified, which window sits on top, and how windows pack without overlapping. Each app keeps its own look, window list and data.
Built not to breakBad data in, working desk outThe repair step accepts any saved layout, from any version, and always returns a desk that works. If an app is renamed, the engine maps the old name to the new one, so a saved layout never quietly loses a window.
Shared window partsOne window frame for every appThe frame, dock, Alt-Tab style switcher, dragging (with an optional cloth effect) and keyboard movement between windows all live in the React layer. I moved them there after two apps had each built their own versions, and the two had started to behave differently.
This site is the demoYou are inside itEvery page here is a window. Drag this one by its title bar, throw it at a screen edge, fold it up, minimise it to the dock, take it full screen, or press Ctrl/Cmd+backtick to switch windows.

The development story

From first release to animated windows in five weeks

The engine moved out of SouthpawStrings on 19 August 2026. It reached version 1.9.0 by the end of that month, and 1.16.0 in September. Every feature followed the same rule: prove it inside a real product first, then move it into the library. The shared window frame came after both apps using the engine had built their own frames, and those frames had started to differ. The code that fits the desk to the browser window came when the SouthpawStrings desk stopped scrolling the page. The drag handling, the cloth effect and the stacked-card view for phones each moved from product code into the library, with the lessons learned along the way intact.

Moving between windows with the keyboard shows the pattern best. The geometry (“which window is to my left?”) arrived in 1.7.0 as a standalone calculation, separate from the page. The part that uses it was proven inside the AI Orchestrator’s desk: the focus highlight, the Ctrl+Shift+Arrow shortcuts, and the awkward cases with hidden browser tabs. It moved into the library in 1.8.0, once it worked. 1.9.0 added folded windows (rolled up to their title bar, where they sit) on the same day SouthpawStrings released the feature that needed them. Later releases made dragging to an edge safer, added true full screen, remembered the sizes people choose, and added the close, dock, restore and fold animations running around this page. The changelog reads like an engineering diary. Each entry records what broke, why, and the rule that came out of it. That is because writing the work down while I do it is part of how I build.