Skip to main content

Getting started

Install, derive, and use a theme

xoji derives a complete, internally consistent set of 276 design tokens (surfaces, text, accents, type, spacing, and more) from an algorithm and a few anchor colors. This page covers installing it, deriving a theme, using the result with or without a framework, and writing your own algorithm.

Install

xoji is three packages. @xoji/core is the engine: the derivation, the xoji command line, and the web components (behind the @xoji/core/elements entry). Add a binding only if you build with that framework.

npm install @xoji/core

# optional framework bindings
npm install @xoji/svelte
npm install @xoji/astro
The engine runs anywhere
@xoji/core's main entry has no node:* or DOM dependencies, so it runs in the browser, in Node, and inside xript's sandbox. The DOM-bound pieces sit behind their own entries (@xoji/core/dom, @xoji/core/elements).

Derive a theme

An algorithm maps your anchors and knobs to a full token register. The built-in algorithms ship with the engine under @xoji/core/algorithms; import one and call derive.

import { derive, emit } from "@xoji/core";
import { xojiDefault } from "@xoji/core/algorithms";

const register = derive(xojiDefault, {
  constraints: { "--bg-0": "#0b0d12", "--fg-0": "#e6e9ef", "--accent": "#6ea8fe" },
  knobs: { scheme: "dark", contrastBand: "aa", vibrancy: 0.5 },
});

const css = emit(register, "css");    // a :root { … } block
const json = emit(register, "json");  // a flat token map

Or derive from the command line without writing any code:

npx xoji derive --bg "#0b0d12" --accent "#6ea8fe" --format css > theme.css

The built-in algorithms, each a named export and an id:

Info:xoji-default

xojiDefault

the neutral default

Info:xoji-hc

xojiHc

high contrast

Info:xoji-quiet

xojiQuiet

restrained

Info:xoji-loud

xojiLoud

vibrant

Info:nxi-nite

nxiNite

Day/Night, time-aware

Anchors

anchors is { bg, fg, accent }, each a hex string. They seed the derivation; every other token solves around them. Pass as few or as many as you like. Pin nothing and the algorithm's own defaults fill in, or pin individual tokens through constraints and the rest re-derive to fit.

Knobs

Knobs adjust how an algorithm derives. The common ones, plus any an algorithm declares itself (nxi-nite adds hour):

scheme "dark" or "light"
contrastBand "aa", "aaa", or a numeric target
vibrancy a number from 0 to 1
density "compact", "normal", or "comfortable"
typeScale · radiusScale · accentShiftStep · fonts finer control

Use the theme

A derived theme is plain CSS custom properties. Write the emitted CSS into your page and the cascade applies it; nothing has to be running at view time. In the browser, @xoji/core/dom writes a register straight onto a live element.

import { apply } from "@xoji/core/dom";

apply(register);                          // write onto :root
apply(register, { target: previewEl });   // scope to one element
apply(register, { persistKey: "theme" }); // and persist it

Run the engine live only when an input changes at runtime: a theme editor, or a time-aware algorithm like nxi-nite re-deriving as the hour moves. Otherwise the engine's job ends once the CSS is written.

Components

The token register is the contract: components read it with var(--token) and never raw colors or magic numbers, so any valid theme styles them with no extra work. Use the raw custom elements, or a framework binding.

import "@xoji/core/elements";   // registers <xoji-button>, <xoji-card>, …
import { Button, Card } from "@xoji/svelte";

@xoji/svelte and @xoji/astro wrap the same elements; each depends only on @xoji/core.

Write an algorithm

An algorithm is a xript mod: a directory with a mod-manifest.json and code. Build on the shared xoji derivation with defineXojiAlgorithm (declare taste; the house derivation does the rest), or write one from scratch with defineAlgorithm.

// algorithms/sunrise/mod-manifest.json declares the mod;
// algorithms/sunrise/src/mod.ts defines it:
import { defineXojiAlgorithm } from "@xoji/core/authoring";

defineXojiAlgorithm({
  id: "sunrise",
  anchors: { bg: "#1a1410", accent: "#ff9e5e" },
  vibrancy: 0.7,
});

Drop the directory in, build the mods, and the algorithm loads by id. Same path the built-in algorithms take. An algorithm that derives in stages lists ordered passes; nxi-nite is a worked example, layering a time-of-day shift onto the base derivation.

See it run

The Bench derives a full register from your anchors and knobs in the browser, then applies it to this very site. The fastest way to feel how a theme reshapes around a change.

Questions or contributions live on GitHub (opens in a new tab) .