Installation
Clients consume Nockerl Design as versioned packages. They never copy values in by
hand. Pin a version, upgrade deliberately, and a remodel in the framework reaches you on
the next bump. All three platforms ship from one version line (currently 2.0.0): the
web npm packages, the Android Maven artifacts, and the Swift package are published in
lockstep from the same vX.Y.Z tag.
| Platform | Tokens | Components | Registry |
|---|---|---|---|
| Web | @dizyx/nockerl-tokens |
@dizyx/nockerl-react |
GitHub Packages (npm) |
| Android | com.dizyx.nockerl:design-tokens |
com.dizyx.nockerl:design-components |
GitHub Packages (Maven) |
| Swift | NockerlDesign (tokens) |
NockerlDesign (views) |
Swift Package Manager (git tag) |
The web build ships as two published npm packages on GitHub Packages (scope @dizyx):
@dizyx/nockerl-tokens (the CSS custom properties) and @dizyx/nockerl-react (the React
components). You need a one-line registry config and a GitHub token with read:packages
before installing.
-
Point the
@dizyxscope at GitHub Packages. Add an.npmrcto your project (or~/.npmrc):.npmrc @dizyx:registry=https://npm.pkg.github.com//npm.pkg.github.com/:_authToken=${GITHUB_TOKEN}GITHUB_TOKENis read from the environment, a classic PAT (or fine-grained token) withread:packages. Never commit the token; keep it in the environment or a secret store. In CI, the ActionsGITHUB_TOKENalready haspackages: read. -
Install the packages with Bun (the Nockerl default runtime):
Terminal window bun add @dizyx/nockerl-react @dizyx/nockerl-tokensreact(>=19) is a peer dependency: the components use React 19 APIs (useIdand friends) and read your app’s copy of React. Tokens-only consumers can install just@dizyx/nockerl-tokens. -
Import the CSS variables once, at your app’s style entry point:
src/styles/global.css @import '@dizyx/nockerl-tokens/tokens.css';This defines the full token set as CSS custom properties (
--color-*,--space-*,--radius-*,--font-*,--elevation-*, and the typography ramp) under:root(light) and.dark(dark). -
Load the brand fonts. The tokens name Outfit (
--font-family-sans) and Space Mono (--font-family-mono), but a token file cannot ship a typeface. Load the fonts yourself once, or every surface silently falls back to system fonts. Self-host with Fontsource (no CDN runtime dependency; this docs site loads them the exact same way):Terminal window bun add @fontsource/outfit @fontsource/space-monosrc/main.tsx (your app entry) import '@fontsource/outfit/300.css'; // Outfit (sans), thin-forward rampimport '@fontsource/outfit/400.css';import '@fontsource/outfit/500.css';import '@fontsource/space-mono/400.css'; // Space Mono for code / monoimport '@fontsource/space-mono/700.css';Use
@fontsource/outfit(familyOutfit), not@fontsource-variable/outfit(which registers the family asOutfit Variableand would not match the token). Outfit ships weights 100 to 900. The Nockerl ramp is thin-forward (100 to 500), so import the weights you render. The Fontsource family names match the token names, so--font-family-sans/--font-family-monoresolve to the loaded faces with no further wiring. -
Use a component. Each component injects its own scoped
<style>, so there is no stylesheet import and no bundler config beyond the tokens above:import '@dizyx/nockerl-tokens/tokens.css';import { NockerlButton, NockerlSurface } from '@dizyx/nockerl-react';export function Example() {return (<NockerlSurface level={2}><NockerlButton text="Save" variant="primary" onClick={() => {}} /></NockerlSurface>);} -
Reference tokens, never raw values in your own chrome. Bind to the variables:
.card {background: var(--color-card-surface1);border-radius: var(--radius-card); /* 16px */color: var(--color-on-card);box-shadow: 0 6px 18px -8px var(--color-shadow-tint);}
Theming & dark mode
Section titled “Theming & dark mode”Dark is the brand default. Both themes live in the tokens; you activate one with a class
or attribute on a high ancestor (usually <html>):
<html class="dark"> <!-- or: <html data-theme="dark"> -->Light is the :root default; .dark and [data-theme='dark'] both override it, so use
whichever your framework toggles. Nothing switches until one is set. Paint the page surface
with the canvas token (otherwise you get components on default white):
body { background: var(--color-canvas); color: var(--color-on-canvas); }To follow the OS preference, reflect it onto <html> once at startup:
const dark = matchMedia('(prefers-color-scheme: dark)');const apply = => document.documentElement.classList.toggle('dark', dark.matches);apply();dark.addEventListener('change', apply);Android & Swift
Section titled “Android & Swift”The per-platform packages follow the same publish-and-consume contract from the same DTCG
source. Both are available now at the same 2.0.0 version line: tokens and
components.
Status: available. Two Maven artifacts on GitHub Packages: design-tokens (the
NockerlTheme + palettes + typography + shapes, with the Outfit variable font bundled in)
and design-components (the NockerlButton family). GitHub Packages Maven requires a
read:packages PAT even to read, and Gradle cannot route through the the credential store proxy, so
every consumer authenticates directly.
gpr.user=<your-github-username>gpr.key=<a-PAT-with-read:packages>dependencyResolutionManagement { repositories { google() mavenCentral() maven { name = "NockerlDesignGitHubPackages" url = uri("https://maven.pkg.github.com/dizyx/nockerl-design") credentials { username = providers.gradleProperty("gpr.user").orNull ?: System.getenv("GITHUB_ACTOR") password = providers.gradleProperty("gpr.key").orNull ?: System.getenv("GITHUB_TOKEN") } } }}dependencies { implementation("com.dizyx.nockerl:design-tokens:2.0.0") implementation("com.dizyx.nockerl:design-components:2.0.0")}Then wrap your app in NockerlTheme and use the components; the bundled Outfit font
needs no wiring:
import com.dizyx.nockerl.design.tokens.NockerlThemeimport com.dizyx.nockerl.design.tokens.ThemeModeimport com.dizyx.nockerl.design.components.NockerlButton
setContent { NockerlTheme(mode = ThemeMode.DEFAULT) { NockerlButton(text = "Save", onClick = { save() }) }}NockerlTheme is Activity-safe (it no-ops the system-bar sync outside an Activity), so it
works in @Preview and non-Activity hosts. See
packages/compose/README.md
for the full consumer guide.
Status: available. Library NockerlDesign (tokens and views). The repo is itself
a Swift Package (root Package.swift), so you consume it by pinning a git tag on the repo
URL. SPM resolves it straight from GitHub, no separate registry. (The repo is private, so
the consuming machine needs git access to dizyx, exactly as for a clone.)
dependencies: [ .package(url: "https://github.com/dizyx/nockerl-design.git", from: "2.0.0")],targets: [ .target(name: "YourApp", dependencies: ["NockerlDesign"])]Use the shipped components; they compose the tokens for you:
import SwiftUIimport NockerlDesign
struct SaveBar: View { var body: some View { NockerlButton("Save", variant: .primary) { save() } }}And read the tokens directly for your own chrome, never hardcode values:
RoundedRectangle(cornerRadius: NockerlRadius.card) // 16 .fill(NockerlDarkColors.cardSurface1) .shadow(radius: NockerlElevation.level2) // 5v0.6.0 ships NockerlButton / NockerlIconButton / NockerlChip alongside the token
layer: NockerlDarkColors / NockerlLightColors (Color), NockerlRadius /
NockerlElevation / NockerlSpace / NockerlFontSize (CGFloat), and the NockerlType
(Outfit) ramp. Voice (macOS) is canonical visual truth alongside Android.
Upgrading
Section titled “Upgrading”Token and component releases follow semver with a CHANGELOG, and all platforms move on
one version line. Patch and minor bumps are drop-in; a major bump signals a breaking rename
or value change you should review. Pin a version, read the CHANGELOG, and upgrade on your
own cadence. The framework never force-pushes a value into a client. Keep
@dizyx/nockerl-react and @dizyx/nockerl-tokens on the same version (they ship in
lockstep).