7 Sep 2026

The first system built on our shared toolkit found four things wrong with it

Abstract composition of scattered translucent rectangles on the left resolving into fewer, larger, aligned rectangles on the right.
A mock Systems Catalogue page showing a grid of product cards: Voyager, Cargo Bay, Beacon, and Habitat. Voyager's card shows a live Deployed badge; the other three show Coming soon.
Voyager is the first system built on a toolkit that was meant to make every one after it faster.

We build each new internal product on a shared set of building blocks: login and access control, permissions, a common look and feel for every screen — the pieces every system needs on day one, so nobody builds them from scratch each time. Before Voyager, our first sales CRM, those building blocks existed and looked finished. They were tagged, versioned, and already copied into a couple of earlier apps. What they hadn’t had was a new app actually built on top of them under real pressure to ship. Voyager was that test, and it didn’t fully pass.

Reuse looks real until the first app actually leans on it

Most of the apps using these shared building blocks were pulling in whatever the latest version happened to be, rather than a version locked in place — which meant a change to any one of them could quietly break every app relying on it the next time it was installed. Several of these building blocks had exactly one real app actually using them, despite being built as “shared” for everyone. One had no real users at all.

Building Voyager forced the point. Along the way, five of these shared building blocks went through a genuine compatibility check for a major framework upgrade — something none of them had actually had to survive before. Three passed cleanly and shipped. Two were deliberately held back rather than rushed through, because a separate, unrelated system elsewhere needed its own upgrade decision made first. Reuse that only works in theory doesn’t get caught by looking at it. It gets caught by building something real on top of it.

A dependency diagram showing five shared package boxes pointing into a single Voyager app box, each connection labelled unpinned dev-main, with two packages flagged by a warning icon.
Five shared packages, one real consumer to actually test most of them.

The parts that looked shared weren’t

The shared screen layout had the same problem in a different shape. Two apps that were supposed to be using the shared version had each quietly built their own near-identical copy of the page frame, navigation, and loading screens instead. It looked shared because the pieces had the same names. It wasn’t shared, because fixing one copy did nothing for the other.

We pulled that shared layout out properly, once, rather than adding a third copy for Voyager. It paid off almost immediately: a login page crash that showed up shortly after launch traced back to that same shared layer, and because there was now one real copy instead of three, the fix landed everywhere at once instead of needing to be found and reapplied app by app.

A package changelog panel showing three version bumps in sequence, v2.4.0, v2.5.0, and v2.5.1, each tagged Shipped.
Three fixes to the same shared layer in four days, each one landing in every app that used it.

Two bugs that only existed once something real was built on top

A later piece of work needed Voyager to accept requests from an automated script, not just a person logging in through a browser. Building that surfaced a real gap: the shared login system had never actually been given everything it needed to support that kind of automated access. It had worked so far only because nothing had tried to use it that way yet. We fixed it properly at the shared level, not worked around inside Voyager, so the next system that needs the same thing won’t hit the same wall. The fix itself needed a second correction days later, once we noticed it only worked inside that one building block’s own project, not when used the normal way inside another app — exactly the same class of problem as everything above: it looked fine until something real used it.

A second bug hid behind the first: every permission check silently failed for that new kind of access, blocking even admin users from anything. It traced back to two of the shared building blocks disagreeing about how to tell which kind of login was in use — invisible until automated access was a real thing happening, not just a hypothetical.

Final thoughts

Voyager itself, the actual CRM, went from a standing start to genuinely live in about three to four days. That’s the number the whole idea of a systems catalogue depends on: each new system getting faster to build once the shared foundation underneath it is solid. But most of those days went somewhere other people might expect. Not into building the CRM itself. Into making four things in the foundation underneath it actually true, instead of just assumed.

That’s the part worth saying plainly rather than glossing over. “Reuse” isn’t real until the first thing built on it either survives or breaks it. Ours mostly survived, and where it didn’t, the next system doesn’t have to find out the same way.

Curious what building on a real shared toolkit could look like for you?

Voyager is live, and everything underneath it is a little more solid than it was a week ago. If you’re weighing up whether a system like this could be built quickly for your business, we’re happy to talk through what that would actually take.

← Back to the blog