DSharp Design System
The shared UI substrate for a multi-product data-modelling platform: three packages, a contract per component, and domain semantics encoded as atoms instead of styling variants.
Approach
1. Contracts & guardrails
- Four files per component
- Scaffolder, never hand-written
- Validator pre-push
- Status lifecycle gates
2. Tokens
- DTCG JSON as Layer 0
- Style Dictionary transforms
- Semantic palettes per mode
- 14-step space scale
3. Atoms, molecules, organisms
- Domain semantics as atoms
- Molecules combine atoms
- Workbench-shaped organisms
- CVA variants + Radix primitives
4. Patterns & templates
- Layout primitives
- Product workflow templates
- Headless mechanics, owned visual
- Rhythmguard closes the gap
Tokens before components
Base layer is platform-agnostic JSON
The first commitment was that the brand, the rhythm, and the semantic palettes had to exist before the first button. The tokens ship as W3C DTCG JSON in @dsharp/tokens with no runtime dependencies; Style Dictionary transforms them into CSS custom properties and typed TypeScript constants for the web in @dsharp/tokens-css. A Windows or mobile target later becomes a sibling transform package, not a fork of the source.
An early lesson came from the logo atom. Its first version bound the mark to a primitive brand token, which flattened it when the surface inverted in dark mode; DTCG primitives, by design, do not theme-switch. The fix was a dedicated semantic alias that resolves per mode, and a rule that travelled with it: brand-as-decoration uses primitives, brand-as-content uses semantics.
The medallion problem
Domain vocabulary belongs in the type system
DSharp’s data work is organised around two closed vocabularies. The medallion architecture sorts every table into one of four layers, source, bronze, silver, or gold, depending on how far it has moved from raw ingest. Every concept is one of four archetypes, moment, party, description, or role. These show up in tables, navigation, diagrams, mapping screens, and forty-odd other surfaces.
The shortest path would have been a generic Badge with variant=“bronze”. The longer path we took was LayerBadge, QualityBadge, and ArchetypeBadge as separate atoms with string-literal unions. The type system refuses unknown values, the validator confirms every variant is covered by a story, and downstream AI agents have one authoritative source for what bronze means and where it can appear.
LayerBadge, QualityBadge, ArchetypeBadge, and ModeSwitch, sit alongside as separate atoms with closed string-literal unions rather than variants of a generic Badge.A contract per component
The file AI agents read
Every component in @dsharp/react ships four files: the React source, a JSON manifest, a markdown spec, and Storybook stories. The manifest is the file built for agents. It declares the component’s tier and group, its variants and slots, the stories that must exist, the tokens it is allowed to reference, and its accessibility-review state. A scaffolder generates all four files pre-wired; the team rule is that no component is ever hand-written.
A validator runs on every push and on every CI build. It enforces parity between the CVA variant definition and the manifest, story coverage for every declared variant, and a status lifecycle that gates promotion: beta requires a Figma URL, stable requires accessibility review. The contract is also what made it possible to add Rhythmguard alongside the system instead of after; once allowed tokens are listed in the manifest, the linter has a closed set to check against.
LayerBadge and QualityBadge instead of restyling them; the form field uses the same primary accent the button uses; the alert pulls from the same status tokens.Composition, continued
Organisms encode the work, not the page
Scout is a task-based workbench rather than a CRUD app, which puts more weight on the organism layer than on the templates above it. LayerNav, ConceptCard, Inspector, AIToolbar, MappingGrid, ConceptDiagram, and LineageGraph carry across every modelling surface because they encode the work, not the page. A modelling template assembles a sidebar, a canvas, an inspector, and a toolbar; a refinement template assembles the same parts in a different proportion.
Inside the heavier organisms, the work split is DSharp-owned visual, library-owned mechanics. DataTable wraps TanStack Table; ConceptDiagram and LineageGraph wrap @xyflow/react. The headless libraries handle sorting, virtualisation, node dragging, and edge routing. DSharp owns the typography, the badge composition, the archetype tints, and the focus rules. The split keeps the system small without rebuilding solved problems.
Closing the gap
Where the rhythm could still leak
One discipline did not survive the move from tokens to composition. Rhythmguard, the Stylelint plugin built alongside the system, enforces the 14-step space scale in CSS declarations and Tailwind class strings. It rejects off-scale literals on padding, margin, gap, inset, and transform translations, and autofixes to the nearest valid step. The values in the spec sheet and the values in the code stay in agreement.
Stylelint cannot reach JSX inline styles or Tailwind arbitrary brackets, so spacing could still leak through composition. The answer was a small set of layout primitives, Stack, Row, Grid, and Container, that take space-scale tokens as props rather than arbitrary numbers. With the lint rule on the styling side and the primitives on the composition side, the rhythm has no path left to drift.
112+ components
Across five tiers: atoms, molecules, organisms, patterns, templates. Each under the same four-file contract.
5 packages
@dsharp/tokens, @dsharp/tokens-css, @dsharp/react, @dsharp/cli, and @dsharp/mcp. Published on a project-scoped Azure Artifacts feed.
2 consumer apps
Scout renders organisms from @dsharp/react in its UI shell. Studio consumes the same package inside its desktop surface. PathFinder is porting in, view by view.
0.1.0 -> 0.59.0
First packaged release shipped April 2026.
Interested in working together?
Let's discuss how design systems, AI and thoughtful UX can elevate your product.