Quick start

One package, three commands, one file you edit.

These pages document uxdsl@0.5.0-beta.9. It is a pre-release: an API can still change before 1.0.0, and every change is in the package CHANGELOG.

1. Install

npm i -D uxdsl

postcss (^8.4.31) is a peer dependency, which npm 7 and later install for you.

2. Scaffold

npx uxdsl init

init writes a typed uxdsl.config.cjs, src/styles.uxdsl (the file you edit) and src/uxdsl-entry.uxdsl (the entry, regenerated by uxdsl generate-entry; do not edit it), and adds uxdsl:build and uxdsl:watch scripts. It writes no theme file: the base theme is built in. What it printed in an empty project:

First run in an empty project: `uxdsl init` exit 0
$ uxdsl init
[uxdsl] Initializing...
  -> Created uxdsl.config.cjs
  -> Created src/styles.uxdsl (edit this one)
[uxdsl] Scanning ./src for .uxdsl files...
[uxdsl] Generated entry file at src/uxdsl-entry.uxdsl with 1 @use rule.
  -> Added script(s) to package.json: uxdsl:build, uxdsl:watch

[uxdsl] Initialization complete.
Install it in this project: npm i -D uxdsl
Next steps:
1. Edit src/styles.uxdsl. The entry src/uxdsl-entry.uxdsl is generated: the watch below regenerates it when a .uxdsl file is added or removed; without it, run "npx uxdsl generate-entry".
2. Build: npm run uxdsl:build
   Watch:  npm run uxdsl:watch
3. Import the generated CSS once, from your root layout or app entry (path relative to that file):
   import './src/uxdsl.css';

Editor support: uxdsl.config.cjs is type-checked by your editor (// @ts-check).
For .uxdsl highlighting and completion (VS Code extension, installed from a .vsix)
and theme JSON completion ("$schema"), see "Editor support" in the uxdsl README.

3. Build, and keep building

npx uxdsl build --watch

Import the generated src/uxdsl.css once, from your root layout or app entry. A broken edit is reported with its UXD_* code and line; the last good CSS stays on disk until the next valid save.

The file you edit, and what it becomes

src/styles.uxdsl starts with one rule. With no theme file at all, it compiles to:

UXDSL you write src/styles.uxdsl

.example {
  @ds-surface(contained);
  padding: density(3);
}

CSS you get compiled by uxdsl; :root shows only this token

:root { --uxdsl__density__3: var(--uxdsl__space__3); }
@media (min-width: 768px) { :root { --uxdsl__density__3: var(--uxdsl__space__4); } }
@media (min-width: 1280px) { :root { --uxdsl__density__3: var(--uxdsl__space__5); } }
.example {
  padding: var(--uxdsl__surface__contained-padding);
  border-radius: var(--uxdsl__surface__contained-radius);
  background: var(--uxdsl__surface__contained-bg);
  color: var(--uxdsl__surface__contained-color);
  border: var(--uxdsl__surface__contained-border);
  box-shadow: var(--uxdsl__surface__contained-shadow);
  padding: var(--uxdsl__density__3);
}

To change a token, add uxdsl.theme.json next to the config with only what you change — { "densities": { "3": "xs(space(2)) md(space(4))" } } — and every density(3) follows. The Theme page lists every family.

Your framework

The CLI works with any framework. Next.js, Vite and Webpack can also compile .uxdsl themselves, through the same pipeline.

In a Next.js project init also writes postcss.config.js — Next's own default plugins, which a custom file replaces, then uxdsl/postcss with includeTheme: false — so CSS Modules can use tokens while the theme comes once from the CLI's src/uxdsl.css. Run npm run uxdsl:watch next to next dev, and import src/uxdsl.css from app/layout.tsx.

postcss.config.js, as uxdsl init wrote it
module.exports = {
  plugins: {
    // Next.js's own default PostCSS plugins, with Next's own options. A custom
    // postcss.config.js replaces Next's defaults, so they are named here; these
    // are the modules Next ships and uses for its default configuration. To
    // pin your own versions instead, install postcss-flexbugs-fixes and
    // postcss-preset-env and use those names.
    'next/dist/compiled/postcss-flexbugs-fixes': {},
    'next/dist/compiled/postcss-preset-env': {
      autoprefixer: { flexbox: 'no-2009' },
      stage: 3,
      features: { 'custom-properties': false },
    },
    // The CLI-generated global CSS already contains the theme; the project's
    // uxdsl.theme.json (or uxdsl.theme.js/.cjs), if any, is discovered
    // automatically for everything else.
    'uxdsl/postcss': { includeTheme: false },
  },
};
/* app/card.module.css: compiled by uxdsl/postcss, no :root of its own */
.card { padding: density(4); background: palette(surface.main); }

Next

Language has every function and directive, Theme every family, and Tooling the CLI's flags, multiple entries, source maps and the VS Code extension.