The design system that stayed local on purpose

J05N remained a personal system across my own applications, which made its claims smaller, its evidence inspectable, and its limits part of the design.

By the end of 2017, J05N had the shape of a design system and none of the institutional story usually used to justify one.

It contained semantic tokens, accessible component contracts, TypeScript declarations, migration adapters, browser fixtures, visual comparisons, and release notes. It appeared in five personal applications. It had no dedicated team, executive sponsor, adoption target, or company-wide mandate.

That absence was not a gap to fill with invented authority.

J05N began because C62Y, T04P, X8B6, M31V, and R7K1 kept rediscovering the same interface mistakes. I wanted each new project to inherit more judgment than the last without forcing the projects to become one application. The system's legitimate scope was the software I maintained and the synthetic fixtures I built to stress its migration contracts.

Keeping J05N local made its claims more precise. I could say which dialog implementation had moved, which old token alias had disappeared, and which domain component remained outside the package. I could not claim that it transformed an organization or standardized work I had never done.

The smaller story turned out to contain a harder and more useful question: what does governance mean when the maintainer, consumer, and policy author are mostly the same person?

One maintainer still has conflicting incentives

It is tempting to assume that a personal system needs no governance because one person can make every decision. In practice, I occupied several roles with different goals.

As J05N maintainer, I wanted a narrow, coherent API. As M31V maintainer, I wanted to finish a publishing change without an unrelated migration. As R7K1 maintainer, I wanted truthful operation states that did not fit a generic spinner. As the person returning months later, I wanted old exceptions explained rather than preserved through memory.

These conflicts were enough to produce familiar system problems:

  • A clean component nobody adopted.
  • Compatibility wrappers without exits.
  • Breaking changes justified by API aesthetics.
  • Shared patterns that absorbed application behavior.
  • Tests optimized for the package rather than consumer tasks.

Governance gave those roles a negotiation protocol. A shared proposal named consumers and limits. A migration had a rollback and removal condition. An exception recorded why the local application retained ownership.

The process did not resolve disagreement among people. It resolved disagreement among timescales and responsibilities held by one person.

That was sufficient reason to make decisions durable.

Scope was a maintained boundary

J05N did not aim to centralize everything visible across the applications. It maintained four broad categories:

semantic visual roles
general interaction contracts
composition primitives
migration and verification methods

It did not own domain state. X8B6's reconciliation workflow stayed in X8B6. R7K1's environment lifecycle stayed in R7K1. M31V's publishing authority stayed in M31V. J05N could provide fields, dialogs, status vocabulary, focus behavior, and layout decisions used to present those domains.

The boundary was tested through a question:

Can J05N decide this behavior without understanding the application's domain consequence?

If not, the behavior remained local. The application could still use shared primitives underneath it.

This was not a permanent ban. A repeated domain-shaped behavior could reveal a more general contract later. It entered J05N only after the shared decision could be described independently and at least one migration proved the boundary.

Scope therefore changed through evidence rather than ambition. The package did not grow to demonstrate completeness.

Five applications were not five independent teams

J05N had multiple consumers, but they did not supply independent organizational validation. I controlled their roadmaps and could change their source. Treating them as five teams would exaggerate adoption difficulty and social proof.

They still supplied real technical diversity.

C62Y was an older responsive web experiment with historical CSS. T04P stressed data density, tables, and freshness. X8B6 cared about durable operation state. M31V combined server rendering and editorial forms. R7K1 exposed asynchronous infrastructure and review status.

The applications produced different state models, browser assumptions, content shapes, and migration histories. A component surviving them had encountered more than a catalogue. It had not encountered independent budget owners, external product priorities, or a large contributor community.

J05N documentation kept those categories separate:

demonstrated: cross-project technical reuse under one maintainer
not demonstrated: broad organizational adoption or governance at scale

This distinction improved design. I did not add voting procedures, contribution councils, or adoption dashboards to imitate a larger system. I built lightweight records and checks proportional to actual coordination.

The work became more credible when it stopped borrowing scale it did not possess.

Synthetic consumers tested transitions, not popularity

Some migration cases did not exist naturally in the five applications or were too dangerous to reproduce there first. J05N used small synthetic consumers.

One fixture contained global CSS collisions, old prop shapes, and a form with delayed server errors. Another tested a dialog whose opener disappeared after deletion. A third installed the packed J05N package into plain JavaScript and TypeScript builds. A browser fixture represented the Grid baseline without modern support.

These consumers were valuable because they made edge conditions deterministic. They did not count as adoption.

The distinction appeared in the consumer ledger:

real application consumer
synthetic migration fixture
catalogue contract example

A synthetic fixture could prove that a compatibility wrapper translated one known shape, that focus returned through a deletion path, or that the published declarations resolved. It could not show that a real task remained understandable over months of use.

J05N required both kinds of evidence for important contracts: controlled stress at the boundary and at least one genuine application migration.

Synthetic work supported technical credibility without becoming a fake user story.

The catalogue did not become a product showroom

The visual catalogue was J05N's easiest artifact to show. It therefore risked becoming the system's public identity even though the project remained local.

I kept it intentionally practical. It displayed states, hostile content, keyboard instructions, contract boundaries, migration notes, and known limitations. It did not present fictional customer logos, adoption numbers, or a brand campaign for an internal platform that did not exist.

Component pages named their consumer evidence:

used in: M31V settings, R7K1 controls
excluded cases: non-modal help panel, domain reconciliation flow
legacy paths remaining: X8B6 field adapter
manual checks: keyboard, screen reader, zoom, long error

This made the catalogue less timeless and more accountable. A visitor could see that a component was part of a changing system rather than a perfect set of primitives delivered from nowhere.

The catalogue remained useful for visual exploration. It did not pretend that isolated rendering was the achievement.

Personal code often relies on memory as an invisible database. J05N was specifically meant to outlive my memory of why a decision had been made.

The minimum record for a shared contract included:

  • The problem and known consumers.
  • The behavior J05N maintained.
  • The behavior applications retained.
  • Accessibility and browser expectations.
  • Migration and rollback paths.
  • Compatibility surface and removal condition.
  • Tests and manual scenarios.
  • Known limitations and rejected alternatives.

These records were short enough to maintain. A large template would encourage copied filler and make small changes ceremonious.

Documentation earned its cost when it prevented a future change from repeating an old investigation. The decision to keep links and action buttons separate deserved a record because visual similarity would repeatedly tempt recombination. The choice to leave a ledger workflow local deserved a note because its panels looked reusable.

Local systems need documentation for temporal collaboration: the conversation between the person who understood the context today and the same person who will not remember it next season.

J05N was not a widely published package, but versioned releases still mattered. The five applications updated at different times. A package change could alter CSS, focus behavior, or declarations across more than one build.

Each release included the packed artifact, contract changes, consumer migration status, and compatibility plan. Versions made application state reproducible. An M31V issue could be traced to J05N 0.7 rather than whatever happened to exist in a linked checkout.

Release discipline remained proportional. A documentation typo did not require ceremony. A dialog focus change or token remapping did. Breaking changes waited for consumer evidence even though I technically could update every repository in one afternoon.

This restraint preserved learning. Staged releases exposed whether the first migration revealed an incomplete contract. A flag-day local update would reduce scheduling friction and increase the chance that all applications shared the same hidden mistake.

The absence of external consumers shortened communication windows. It did not eliminate compatibility as an engineering concern.

Accessibility remained a shared obligation

J05N centralized difficult mechanics such as dialog focus and field relationships. It could not make the applications accessible through package membership.

Each consumer still chose heading structure, content language, validation timing, status priority, and workflow focus. A correct component could be composed into an incoherent page. A visual token could be used for the wrong semantic role. An operation status could announce every update and overwhelm the task.

The system documented both guarantees and obligations:

J05N guarantees: label/error relationships are rendered as declared
consumer provides: useful label, correct error timing, form-level focus policy

Manual test instructions traveled with migrations. A receipt named what had actually been exercised. Automated checks caught certain omissions but never produced an overall accessibility score used as absolution.

This limit was especially important in a personal project. Without separate reviewers, the system could easily become self-certifying. Explicit manual scenarios forced the interface to be experienced outside the implementation view.

J05N centralized knowledge and reduced repeat defects. It did not centralize responsibility away from the application.

The system had no adoption target

An adoption percentage would be easy to calculate and misleading. Not every local component should move into J05N. Some old routes were stable and did not justify migration. Some visually similar patterns belonged to different domains. Some applications could adopt tokens without adopting React components.

J05N tracked per-contract states instead:

migrated
eligible but unscheduled
temporarily adapted
intentionally local
obsolete with route removal
unknown, needs inventory

The goal was not 100 percent package use. It was zero unexplained divergence for decisions J05N claimed to govern.

A local button could remain if its contract was genuinely different and documented. A deprecated J05N wrapper could not remain without an owner and exit. An obsolete route could disappear instead of being modernized to improve a metric.

This changed prioritization. The highest-value work addressed harmful inconsistency, migration debt, and unclear ownership. Converting harmless markup for an adoption graph ranked low.

The system existed to make the applications better and easier to change. The applications did not exist to validate the system.

Maintenance capacity limited abstraction

Every exported component created work: browser behavior, accessibility review, type declarations, fixtures, visual states, documentation, migration support, and later changes.

With one main maintainer, J05N could not responsibly own a large surface. I deleted catalogue components without consumers and rejected abstractions whose test matrix exceeded their reuse value.

The core stayed focused on high-consequence, stable patterns:

  • Buttons and links with correct semantics.
  • Fields and messages with explicit relationships.
  • Dialog focus and dismissal mechanics.
  • Operation state vocabulary.
  • Semantic visual roles.
  • A few composition primitives.

Domain-rich components lived in their applications. Experimental patterns stayed outside the stable entry point until their behavior survived real use.

This limitation improved the architecture. A dedicated team might still choose a narrow core, but local capacity made the cost impossible to ignore.

An abstraction is not free after it is written. Its maintenance surface is part of its design.

Success appeared as deletion and boring reuse

J05N did not produce a launch moment. Its most convincing outcomes were quieter.

M31V's old field structure and styles disappeared after migration. The polymorphic button left the package once links and actions separated. Deprecated raw color aliases reached zero consumers and were removed. Dialog focus behavior stopped being independently reimplemented in each project. A T04P layout adopted Grid without adding an old-browser imitation.

New routes reused semantic roles and field contracts without reopening their basic decisions. That reuse was boring in the best way: the component did not become the subject of the feature.

Failures remained visible. Some visual snapshots were noisy. The TypeScript boundary did not protect JavaScript consumers without runtime checks. Compatibility wrappers briefly grew too comfortable. A card abstraction was withdrawn after domain ownership became obvious.

The system's value was not perfection. It was accumulated correction that future work could inherit.

Deletion mattered because it showed that change paths ended. Boring reuse mattered because it showed that shared decisions reduced cognitive load without demanding attention.

Local scope preserved portability

J05N could have grown application-specific assumptions until all five projects depended on one hidden platform. Keeping its contract narrow made reuse optional and replacement possible.

Components emitted ordinary HTML and CSS. Tokens compiled to static values with custom-property enhancements. Public state models were serializable. Applications retained domain logic. The package did not require a proprietary service or global runtime to render a field.

This meant a project could take J05N selectively or leave it. C62Y used visual roles and layout guidance without adopting the full React layer. A future application could implement the same dialog contract differently if its framework changed.

Portability was another form of honest scope. J05N stored decisions in code, but it did not claim ownership over every environment in which those decisions might be useful.

The design system could influence work without becoming an irreversible platform commitment.

J05N was the first project in this journey where the main challenge was no longer making one artifact work. It was coordinating change across several existing artifacts with different histories.

That is an organizational problem in the broad sense: ownership, compatibility, sequencing, evidence, and maintenance. It did not require inventing an employer or team structure to become technically substantial.

The project taught me to ask:

  • Who owns the decision and its consequences?
  • Which consumers actually share it?
  • How can new and old behavior coexist?
  • What evidence permits retirement?
  • Which complexity belongs centrally and which belongs locally?
  • How much process can the maintainer sustain?

Those questions would return in later systems involving privacy, distributed operations, collaboration, and migration. J05N exercised them at a scale where every assumption could be inspected.

The work became a bridge from component craft to system stewardship without pretending that stewardship occurred inside a fictional enterprise.

Staying local was a positive decision

I considered publishing J05N as a general-purpose library. The prospect encouraged generic naming, broader APIs, and compatibility promises for consumers I did not know. It also shifted attention toward installation and promotion rather than the applications that had created the problems.

I kept it local.

That choice did not mean the ideas had no wider relevance. It meant the package would make claims only against evidence it possessed. Articles could explain the contracts and migration lessons. Source could remain inspectable. The maintained release policy would serve known projects rather than speculate about every possible use.

If J05N later earned external consumers, governance could expand with them. Designing imaginary scale in advance would add ceremony and abstraction without feedback.

Local scope kept the feedback loop tight: a component changed because a real route exposed a need; a migration changed because an actual adapter failed; a token changed because a supported pair lacked contrast.

The system grew from consequences, not from the appearance of maturity.

The limit made the story true

J05N ended 2017 as a personal design system with serious engineering inside a deliberately small claim.

It demonstrated that accessible contracts could be reused across different applications. It showed that migration, compatibility, and deletion belonged to API design. It used tokens to name decisions, TypeScript to strengthen boundaries, Grid to stage platform capability, and visual diffs to make selected consequences reviewable.

It did not demonstrate enterprise adoption, independent team governance, broad market use, or universal component coverage. Those absences remain part of the record.

The local scope was enough to create constant growth. Earlier projects had taught me to build an interface or reliable workflow. J05N taught me to change several existing interfaces without pretending their histories were blank.

That lesson depended on honesty about the setting. If I inflated five personal applications into an organization, the strongest evidence would become suspect. By keeping the claim small, the technical reasoning could stay large.

J05N did not need to be everywhere to matter. It needed to preserve decisions worth sharing, expose the ones that stayed local, and make each transition observable enough that the next project could inherit judgment instead of only code.