# Install LUZ

Pick a level, then copy one install command or the CDN tags. Each level needs the ones below it and nothing above.

LUZ is a place to start, not a finished site. The content, the brand and the final decisions are yours: check the result before you publish.

Know what you are building? [Choose your snippet](https://nandovejer.github.io/luz/docs/get-started/snippet/) and copy the lines for it, CDN hashes included.

Loading LUZ from a CDN sends your visitors’ IP addresses to the CDN. If you do not want that, install from npm and serve the files from your own server.

Beta

Names, classes and behaviour can still change before the stable release. Pin an exact version, and read the changelog before you upgrade.

### Which level do I need?

- **A new project:** level 2, tokens and core. `luz.css` styles the HTML you write.
- **A project that already has a design:** level 1, tokens only, to start: it changes nothing you can see. Then [level 2 for an existing project](https://nandovejer.github.io/luz/docs/get-started/#existing-project), with `luz.conditional.css`, one region at a time. [Migrate a project to LUZ](https://nandovejer.github.io/luz/docs/get-started/migrate/) has the steps.
- **Your own components, LUZ’s colours and spacing:** level 1, tokens only.
- **Ready-made buttons, forms, tables and dialogs:** level 2, tokens and core.
- **Whole pages: shell, page header, footer, search:** level 3, the Catalog, all three packages.
- **A landing page, with its header, hero and blocks:** level 3 and [the patterns for that kind of site](https://nandovejer.github.io/luz/docs/get-started/#site-kinds), which are catalog components.

### Level 1: tokens only

CSS custom properties: the colour, space and type scales, the font roles, the breakpoints and the motion durations, and the colours of light, dark and high contrast. No other LUZ package is needed.

`pnpm add @luz-ds/tokens`

CDN tags, level 1
```html
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@luz-ds/tokens@0.3.0/dist/luz-tokens.min.css">
```

With a bundler such as Vite, import the files instead of adding tags. A `href` cannot name a package: these paths are for `import` only.

Bundler imports, level 1
```js
import "@luz-ds/tokens/css";
```

- Running text and headings use ET Book, an MIT-licensed font that ships with the tokens. Controls, labels and tables use the system sans, and code the system mono.
- Bringing your own fonts? Load `dist/tokens.min.css` instead: the same tokens without any `@font-face`.
- Check your own colours against the WCAG ratios with `npx @luz-ds/tokens@0.3.0 check-contrast`, or [in the browser](https://nandovejer.github.io/luz/docs/tokens/contrast/).

### Level 2: tokens and core

The 29 components, the styles of bare HTML elements, and optional JavaScript. Load tokens first.

`pnpm add @luz-ds/tokens @luz-ds/core`

CDN tags, level 2
```html
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@luz-ds/tokens@0.3.0/dist/luz-tokens.min.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@luz-ds/core@0.3.0/dist/luz.min.css">

<!-- Optional: copy buttons, tabs, players, the color mode -->
<script type="module" src="https://cdn.jsdelivr.net/npm/@luz-ds/core@0.3.0/dist/luz.min.js"></script>
```

Bundler imports, level 2
```js
import "@luz-ds/tokens/css";
import "@luz-ds/core/css";

// Optional: copy buttons, tabs, players, the color mode
import "@luz-ds/core";
```

- Every page works without the script. See [what each JavaScript module adds](https://nandovejer.github.io/luz/docs/get-started/javascript/).
- Need a single component? Load `dist/base.min.css` plus the file you want, for example `dist/components/button.min.css`.
- Markup you cannot add classes to, such as Markdown or a CMS? A bare `button`, field or `table` already has its look in `luz.css`. On a page that already has a design, load `luz.conditional.css` instead and mark the zone with `data-luz`.

### Level 2 for a project that already has a design

Load `luz.conditional.css` instead of `luz.css`. It is the same file, with the reset and the bare elements limited to the region you mark with `data-luz`. Load the tokens first, as for any level. From a CDN, link `luz.conditional.min.css` of `@luz-ds/core` in place of `luz.min.css`; with a bundler, import it as below.

Bundler imports, an existing project
```js
import "@luz-ds/tokens/css";
import "@luz-ds/core/conditional.css";
```

- The element with `data-luz` takes the font, color and background of the page. The tokens stay on `:root`.
- Layout objects, components and utilities are not limited to the region: they apply wherever you put their class.
- Your old CSS must not be unlayered, or it beats LUZ. Put it in a layer before `luz`: see [Cascade layers](https://nandovejer.github.io/luz/docs/get-started/layers/) and [Migrate a project to LUZ](https://nandovejer.github.io/luz/docs/get-started/migrate/).

### Level 3, the Catalog: tokens, core and catalog

The site's navigation and the pieces with a script or an identity of their own: navbar, sidebar, terminal, timeline, search, cookie consent, color mode by time of day, language switch, submenu, announcement and FAQ, and the patterns of a kind of site. The catalog needs core and tokens.

The page structure of each kind of site, from the header to the footer, is in the catalog too, one stylesheet per pattern: see [Kinds of site](https://nandovejer.github.io/luz/docs/get-started/#site-kinds).

The catalog has a stylesheet per component: link the ones the page uses, after core.

`pnpm add @luz-ds/tokens @luz-ds/core @luz-ds/catalog`

CDN tags, level 3
```html
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@luz-ds/tokens@0.3.0/dist/luz-tokens.min.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@luz-ds/core@0.3.0/dist/luz.min.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@luz-ds/catalog@0.3.0/dist/components/search.min.css">

<!-- Optional: core behaviours, and the site search and cookie banner -->
<script type="module" src="https://cdn.jsdelivr.net/npm/@luz-ds/core@0.3.0/dist/luz.min.js"></script>
<script type="module" src="https://cdn.jsdelivr.net/npm/@luz-ds/catalog@0.3.0/dist/catalog.min.js"></script>
```

Bundler imports, level 3
```js
import "@luz-ds/tokens/css";
import "@luz-ds/core/css";
import "@luz-ds/catalog/components/search.css";

// Optional: core behaviours, and the site search
import "@luz-ds/core";
import "@luz-ds/catalog";
```

### Kinds of site

To start a landing page, a blog, an app or a documentation site, go to [Kinds of site](https://nandovejer.github.io/luz/docs/kinds/): a prompt for any LLM, and the recipes of each part to copy.

There is no package for a kind of site. Its patterns are components of the catalog, one stylesheet each, named for what the piece is, `<block>.css`. Install level 3, then link the files your page uses, after core:

- **Landing page:** `site-header`, `hero`, `main`, `section`, `stat`, `site-footer` and `glow`: the header, hero, sections and footer.
- **Blog or newspaper, with any CMS:** `site-header` (or `masthead` for a newspaper), `page-header`, `article-header`, `article`, `post-list` and `site-footer`: the header, page header, article header, contents, post list and footer.
- **Web application:** `app-bar`, `dashboard` and, for the panels that show data, `bar-list`, `column-chart`, `stacked-bar`, `ring` and `heat-map`.
- **Documentation site:** `docs-layout`, `doc-header`, `page-rail`, `example`, `do-dont`, `pager` and `page-footer`.

The [catalog](https://nandovejer.github.io/luz/docs/catalog/) has a page for each pattern, and says which kinds of site it fits best.

CDN tags, a landing page
```html
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@luz-ds/tokens@0.3.0/dist/luz-tokens.min.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@luz-ds/core@0.3.0/dist/luz.min.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@luz-ds/catalog@0.3.0/dist/components/site-header.min.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@luz-ds/catalog@0.3.0/dist/components/hero.min.css">
```

Bundler imports, a landing page
```js
import "@luz-ds/tokens/css";
import "@luz-ds/core/css";
import "@luz-ds/catalog/components/site-header.css";
import "@luz-ds/catalog/components/hero.css";
```

- Link the files of a kind in the order of the list above.
- Link `hero` with `section`: the head of a section shares its rules with the hero.
- None has a script. The catalog's script is optional: with the table of contents of a blog, it marks the section in view; with the sidebar of an app, it marks the current link and closes the drawer when a link is followed. Core's script does not do this.

### Before you ship

- npm and pnpm install the lower levels for you. Yarn only warns, so list every package, as above.
- On a CDN, pin an exact version and add an `integrity` hash with `crossorigin="anonymous"`. Compute the hash from the file you load, as below.
- The core and catalog scripts warn in the console when the level below is missing.
- Set `lang` on `<html>`: core's scripts write their text in that language (English and Spanish ship).

Computing the integrity hash
```text
curl -s https://cdn.jsdelivr.net/npm/@luz-ds/core@0.3.0/dist/luz.min.css | openssl dgst -sha384 -binary | openssl base64 -A
```

Write the result as `integrity="sha384-…"` on the tag that loads that file, and repeat it for each file.

A hash on a script covers that file only, not the files it loads later. `catalog.min.js` loads `search.min.js` on a page with a search and `cookie-consent.min.js` on a page with a cookie banner and `theme-time.min.js` on a page with a time of day for the color mode.

Give each one its own hash in an import map, before the first module script. It works in Chrome 127, Safari 18 and Firefox 138 and later; an older browser ignores it and loads the files unchecked.

A `<link rel="modulepreload">` with a hash is not a guard in Safari or Firefox: use it as a performance hint only.

Integrity for the catalog scripts
```html
<script type="importmap">
{
  "integrity": {
    "https://cdn.jsdelivr.net/npm/@luz-ds/catalog@0.3.0/dist/search.min.js": "sha384-…",
    "https://cdn.jsdelivr.net/npm/@luz-ds/catalog@0.3.0/dist/cookie-consent.min.js": "sha384-…",
    "https://cdn.jsdelivr.net/npm/@luz-ds/catalog@0.3.0/dist/theme-time.min.js": "sha384-…"
  }
}
</script>
<script type="module" src="https://cdn.jsdelivr.net/npm/@luz-ds/catalog@0.3.0/dist/catalog.min.js" integrity="sha384-…" crossorigin="anonymous"></script>
```

### Next steps

- [Choose your snippet](https://nandovejer.github.io/luz/docs/get-started/snippet/) for your kind of site and the way you load it.
- [Browse the components](https://nandovejer.github.io/luz/docs/components/) and copy their markup.
- [Set up the color modes](https://nandovejer.github.io/luz/docs/tokens/modes/): light, dark and high contrast.
- [Learn how the tokens work](https://nandovejer.github.io/luz/docs/tokens/) before you write your own components.
- [See how LUZ is organised](https://nandovejer.github.io/luz/docs/get-started/structure/): packages, CSS layers and the page skeleton.

### Frequently asked questions

The short answers. Each links to the page that explains it.

**What is LUZ?**

LUZ is a design system for the web, in three packages: tokens (colors, scales, fonts and three color modes), core (the reset, the style of HTML elements, layout objects, components and optional JavaScript) and the catalog (pieces that act for the whole site, such as search). Use the tokens alone, core with the tokens, or all three. [Working with AI](https://nandovejer.github.io/luz/docs/get-started/ai/) shows how an AI can write a site with it.

**Are HTML tags styled without a class?**

Yes, most of them. Text, links, lists, tables, buttons, form fields, `details` and `dialog` come out styled with no class. Tags that only structure the page, such as `div`, `section`, `header` and `nav`, have no style: the layout is yours. [Which elements have a style with no class](https://nandovejer.github.io/luz/docs/html/#html-styled) lists them all.

**What are the classes for?**

A class adds what HTML cannot say: a link that looks like a button, a role such as danger, a size, a component with markup of its own such as a card, and the layout with the `o-*` objects. The HTML says the rest: `type="button"` makes the secondary button, and `aria-invalid="true"` marks a field with an error. [Browse the components](https://nandovejer.github.io/luz/docs/components/) to see what each class adds.

**Do I need JavaScript?**

No. Most components are CSS only, and the ones with a script work without it too. [JavaScript modules](https://nandovejer.github.io/luz/docs/get-started/javascript/) says what each module adds.

**Can I change the default styles?**

Yes, without fighting them. Change the tokens to change the whole look, or write your own CSS: CSS with no layer beats every layer of LUZ, with no `!important`. What you leave alone stays. [Changing the default styles](https://nandovejer.github.io/luz/docs/html/#html-change) shows the three ways.

**Is LUZ only for new projects?**

No. LUZ fits a new project best, but you can add it to one that already has a design, one region at a time: load `luz.conditional.css` instead of `luz.css` and put `data-luz` on the region. [Level 2 for a project that already has a design](https://nandovejer.github.io/luz/docs/get-started/#existing-project) has the lines to load.

**How do I migrate a project to LUZ?**

Migrate one page at a time, in five steps: the tokens with your brand, the old CSS in a layer before LUZ, a first region, the other pages one by one, and the old CSS removed. An AI does the mechanical work; you decide and check. [Migrate a project to LUZ](https://nandovejer.github.io/luz/docs/get-started/migrate/) has the steps.
