Skip to main content
Prakriti Bista

Project dossier / Design + Engineering

Oceania

A registry-first React design system that ships editable shadcn-compatible components with Figma-sourced tokens included.

Role

Designed and built the registry, token layer, component source, docs site, and verification flow.

2026

Result signals

  • shadcn-compatible registry
  • Figma-sourced CSS tokens
  • 12 installable UI primitives
  • Fresh-install verification

Evidence board

A registry-first design system where tokens, component source, and install paths are designed as one product surface.

2026Design + Engineering

Question

What was the hard part?

Component libraries should not become black boxes after install.

System

Design + Engineering

React / Next.js / TypeScript / Radix UI

Evidence

shadcn-compatible registry

Twelve primitives can be installed as editable source with the token layer included.

Decision

Constraint shaped the interface

A shadcn-compatible registry forced tokens, utilities, dependencies, and file targets to ship together.

Artifacts linked above

Oceania

The component library problem I kept circling

Most component libraries solve the first week of a project beautifully. You install a package, import a button, and move fast. Then the real product starts pushing back.

The button needs one behavior the package does not expose. The input needs to match a Figma state that is not part of the theme API. The team wants the component to feel native to their app, but the code lives somewhere else, behind versioning, wrappers, overrides, and a mental model nobody fully owns.

Oceania started from that irritation. I wanted a design system where the install path did not separate teams from the code they were expected to use every day.

Design Decision

Installed UI should feel owned by the team that installs it.

Registry-first, not package-first

The core decision was to follow the shadcn model: components install as editable source, not as a sealed runtime dependency. Oceania hosts registry JSON files at oceania.praks.me/r/*.json. When someone runs the CLI command, the component file lands inside their app.

That changes the relationship between the design system and the product team. Oceania provides the starting point, the tokens, the dependency list, and the expected behavior. The consuming app keeps the final authority.

The workspace is split around that idea:

packages/ui holds the React source: Button, Input, Select, Tabs, Tooltip, and the other primitives. This is the code the registry eventually hands to the consuming app.

apps/registry is both docs site and distribution surface. It previews components, explains install commands, and publishes schema-valid shadcn registry files.

Visual Evidence

Image

Oceania registry homepage showing the install command and files written by the CLI
The registry landing page makes the install path visible: component source, tokens, utilities, and the CLI command are shown as one system.

Tokens had to travel with the component

A component copied without its tokens is only half portable. The button might render, but its color, radius, typography, disabled state, and focus ring are still floating somewhere else.

So Oceania treats tokens as a registry item too. The tokens.json entry writes app/oceania-tokens.css into the consuming app. Components reference those variables directly through Tailwind arbitrary values, which keeps the contract simple: install the component, import the token file, then tune the system from CSS variables.

12
installable UI primitives

The first set covers the pieces I reach for constantly: Button, Input, Textarea, Checkbox, Radio Group, Switch, Slider, Select, Tabs, Breadcrumb, Pagination, and Tooltip. Not flashy. Very deliberate. These are the controls where state, focus, spacing, and disabled behavior quietly decide whether an interface feels built or assembled.

Behavior belongs to primitives

I did not want Oceania to hand-roll interaction behavior for controls that already have mature primitives. Select, Checkbox, Radio Group, Switch, Slider, Tabs, and Tooltip lean on Radix where keyboard interaction and accessibility semantics matter.

That let the design work stay where it should: visual grammar, states, composition, and install ergonomics.

The Button preserves asChild composition through Radix Slot. Form controls share border grammar across default, hover, focus, error, and disabled states. Select mirrors Input so it feels like part of the same system instead of a dropdown imported from another planet.

The registry became the product

At first, the registry app could have been a thin docs page. But the more I built, the more obvious it became that the registry itself was the product surface.

Visual Evidence

Image

Oceania install section showing shadcn-compatible registry commands
The docs are not separate from distribution. The page explains what each command writes, what files travel together, and how the component can be inspected before install.

The build script generates each registry item from the component source. It injects dependencies, registry dependencies, docs notes, and target paths. That means button.json is not a hand-maintained artifact; it is the published shape of the component source.

The useful boring files matter here: fresh-install verification, browser QA notes, registry schema references, and a local pnpm verify gate. A design system can look polished and still fail at the moment someone tries to install it. Oceania treats that install moment as part of the design.

What this taught me about design systems

Oceania made me think about design systems less like component collections and more like delivery systems.

The visual layer matters, of course. The tokens need taste. The components need good spacing and state behavior. But the deeper question is operational: can another project actually receive this system without losing control?

For Oceania, the answer is registry-first. Ship the source. Ship the tokens. Make the generated files inspectable. Let the consuming app keep ownership.

That feels closer to how I want to build product UI: opinionated enough to create momentum, open enough that the people using it can keep going after the install finishes.

What Worked

  • Registry-first installs keep ownership inside the consuming app
  • Radix primitives handle keyboard and accessibility behavior while Oceania owns the visual grammar
  • Tokens ship as CSS variables, so teams can tune the system without rewriting every component

What Didn't

  • A registry has more moving parts than a normal npm package: generated JSON, hosted files, install paths, and fresh-install QA
  • The first version covers core primitives, but complex data components still need their own pass

Built with

ReactNext.jsTypeScriptRadix UITailwind CSSshadcn Registry