Why we extracted Desk Engine

SouthpawStrings puts several practice tools on one desk. A player can move, resize, minimise, and reopen their windows while keeping the arrangement they want. Making those actions behave consistently became a substantial piece of software in its own right.

Desk Engine takes that window behaviour out of the guitar application so another application can use it too. A layout fix can then be made in one library and adopted by its consumers through a versioned update.

What belongs in the engine

The engine handles window geometry, layout packing, snapping, keyboard navigation, undo, and the reading and cleaning of saved state. It does not need to know what a guitar scale is or what an engineering task contains.

The host supplies a catalogue describing its apps and their sizing rules. It also supplies the rules for its own shared settings. This keeps product knowledge in the application while giving each consumer the same window behaviour.

The main TypeScript entry has no framework dependency. Applications that use React can opt into a separate entry for shared frames, controls, and hooks. That separation lets the React interface grow without making React a requirement for the underlying geometry and state functions.

How the extraction was approached

The first extraction moved the existing layout, magnetism, keyboard, undo, and state logic with its tests. SouthpawStrings kept adapters so saved desks and established import paths did not have to change all at once.

Subsequent releases added shared window controls, sections that fold away, viewport fitting, drag behaviour, and directional focus. Consumer updates remain separate changes: publishing the library does not prove that every host has adopted or verified it.

Several details protect people's saved layouts. Invalid state falls back to safe defaults. Content-sized windows do not keep a stale fixed height. Renamed apps need an explicit legacy mapping so an existing saved window is not silently lost.

Scope and limits

The engine and its consumers have separate release histories. A library change reaches an application through an explicit dependency update and that application's own verification.

Continue reading

Read the case study for the extraction story — or just look around: the window you may be reading this in runs on it.

From the project’s documentation set. Internal runbooks and deployment records stay private — How I Build explains the boundary.