Skip to content

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.2.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 npm (public)
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 public npm packages (scope @dizyx): @dizyx/nockerl-tokens (the CSS custom properties) and @dizyx/nockerl-react (the React components). There is no registry configuration and no token: install them like any other dependency.

Both are published from CI by trusted publishing, so every release carries a provenance attestation linking it back to the commit and workflow that built it. You can check one yourself with npm audit signatures after installing.

  1. Install the packages with Bun (the Nockerl default runtime):

    Terminal window
    bun add @dizyx/nockerl-react @dizyx/nockerl-tokens

    react (>=19) is a peer dependency: the components use React 19 APIs (useId and friends) and read your app’s copy of React. Tokens-only consumers can install just @dizyx/nockerl-tokens.

  2. 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).

  3. 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-mono
    src/main.tsx (your app entry)
    import '@fontsource/outfit/300.css'; // Outfit (sans), thin-forward ramp
    import '@fontsource/outfit/400.css';
    import '@fontsource/outfit/500.css';
    import '@fontsource/space-mono/400.css'; // Space Mono for code / mono
    import '@fontsource/space-mono/700.css';

    Use @fontsource/outfit (family Outfit), not @fontsource-variable/outfit (which registers the family as Outfit Variable and 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-mono resolve to the loaded faces with no further wiring.

  4. 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>
    );
    }
  5. Reference tokens, never raw values in your own chrome. Bind to the variables, including the depth recipe: a neutral drop shadow plus the inset top catch-light, never a glow.

    .card {
    background: var(--color-card-surface1);
    border-radius: var(--radius-card); /* 16px */
    color: var(--color-on-card);
    box-shadow:
    /* neutral drop shadow, standard card rung: the rung token is the y offset,
    the blur is a constant 0, so the shadow is crisp rather than a halo */
    0 var(--elevation-level2) var(--elevation-blur) 0
    color-mix(in srgb, var(--color-shadow-tint) calc(var(--elevation-shadow-tint-alpha-level2) * 100%), transparent),
    /* top catch-light, lit from above */
    inset 0 var(--space-px) 0 var(--color-surface-highlight);
    }

    Swap the --elevation-level* and matching alpha token for a different rung; the other three are listed in Elevation & depth.

Tip

This documentation site is itself themed by the same tokens. It vendors a build snapshot of tokens.css at src/styles/tokens.css (regenerated by bun run build) rather than resolving the package over the registry, a convenience for the docs repo. A product consumer instead pulls the published package with @import “@dizyx/nockerl-tokens/tokens.css” and tracks it like any other dependency.

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);

The per-platform packages follow the same publish-and-consume contract from the same DTCG source. Both are available now at the same 2.2.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). Unlike the npm packages, GitHub Packages Maven requires a read:packages token even to read a public artifact, so every consumer has to authenticate.

~/.gradle/gradle.properties (never commit a token)
gpr.user=<your-github-username>
gpr.key=<a-PAT-with-read:packages>
settings.gradle.kts
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")
}
}
}
}
app/build.gradle.kts
dependencies {
implementation("com.dizyx.nockerl:design-tokens:2.2.0")
implementation("com.dizyx.nockerl:design-components:2.2.0")
}

Then wrap your app in NockerlTheme and use the components; the bundled Outfit font needs no wiring:

import com.dizyx.nockerl.design.tokens.NockerlTheme
import com.dizyx.nockerl.design.tokens.ThemeMode
import 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.

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).