---
title: "Design a lazysite theme with an AI designer"
subtitle: "A guide to give an AI designer, such as Claude design, so the theme it makes goes onto a lazysite site unchanged."
---

An AI designer can produce a convincing design in minutes. Whether it can be used on your site depends on whether it was made for how the site is built. A lazysite site keeps its words, its page structure and its look apart, and a theme only changes the look. A design made with that in mind goes on as it is; one made as a free-standing page has to be rebuilt.

This page is the guide to give the designer. It explains the three layers, the tokens a theme is made of, light and dark with the visitor's choice, the brand mark and icons, fonts, the states every theme must style, and the exact folder to send back.

## How to use it

1. **Give the designer this guide.** Paste the link to this page, or the plain text at [/guides/design-a-theme-with-ai.md](/guides/design-a-theme-with-ai.md), into the conversation before you describe the look you want.
2. **Give it your site's real pages.** The rules apply to the markup your pages actually produce. A design kit from your site's maintainer holds them ready (see below); otherwise give the designer your site's address, or connect it to your site over MCP, where `read_page` and `preview_page` show it real pages in your layout.
3. **Describe the look**, and any design system or brand book you work from. Ask for both light and dark.
4. **Ask for the folder in "What to send back".** Nothing else is needed.
5. **Install it beside your current theme.** Upload the theme as a zip on the manager's Themes page (`theme.json` at the root of the zip), put the files from `site/` at your site's root, preview, then switch it on. The current theme stays installed, so you can switch back.

### With or without a design kit

A design kit is a small folder prepared from a live site: this guide, a brief about the site, and the site's real markup. The guide refers to its files; without a kit, the same things come from the site itself:

| In a kit | Without one |
|----------|-------------|
| `specimen.html` - every element in its real markup | A page of your own holding headings, lists, tables, code, quotations, images and a form, read in your layout |
| `pages/` - real pages as served | Your home page and the pages your site uses most |
| `STATES.md` - states a still page cannot show | The section "Every element, every state" below |
| `css/tokens.css` - the theme's tokens | Your current theme's `theme.json` (the MCP tool `theme_tokens` lists the names) |
| `BRIEF.md` - this site's layout, theme and switcher | Your layout's name and whether it has a colour-scheme switcher |

## The guide

### How a lazysite site is put together

Three layers, kept apart:

Content
: Markdown pages written by people and AI agents. Their markup is whatever the Markdown converter and the engine's own components produce - every case is in `specimen.html` and `pages/`. Authors cannot add classes or HTML structure of their own, so a design that depends on extra markup in pages will not survive real content.

Layout
: One template (`layout.tt`) that wraps every page: the header, navigation, page title, footer, and any hero. It can carry a small `<style>` block of its own, which loads after the theme.

Theme
: `theme.json` (the colours and fonts, as tokens) and one stylesheet, `assets/main.css`, with bundled fonts. A site can switch themes without touching its content or layout, so a theme must work with the markup that is there.

Your work is the theme. Where the design needs something only a layout can give (a different header arrangement, a new hero, a component), describe it in `NOTES.md`; it is built as a layout change, separately.

### Tokens

Every value in `theme.json` under `config` becomes a CSS custom property: `config.colours.primary` is `--theme-colours-primary`, `config.dark.primary` is `--theme-dark-primary`, `config.fonts.body` is `--theme-fonts-body`. The engine writes them; your stylesheet only reads them.

- Colours live only in `theme.json`. Write no colour value in `main.css` outside the block that maps tokens to short names.
- Map the tokens onto short names of your own at the top of `main.css` (`--surface: var(--theme-colours-surface);`) and style everything through those. Switching scheme is then one block that remaps the short names.
- Keep every token name the kit lists in `css/tokens.css`: the layout and other parts of the site read them. A name your design does not use still needs a sensible value. Add roles the design needs.
- Spacing, the type scale and line heights are CSS, set as relationships (one spacing step reused; headings at a ratio of the body). There are no tokens for them.

### Light, dark and the visitor's choice

Design both schemes. A site can follow the device, and its layout may also offer a switcher that lets the visitor choose. The switcher records the choice as an attribute on the root element: `data-theme="light"` or `data-theme="dark"`, and no attribute for "follow the device". A theme must answer all three:

```css
:root { /* light: map every short name from config.colours */ color-scheme: light dark; }

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) { /* dark: remap every short name from config.dark */ }
}
:root[data-theme="dark"] { color-scheme: dark; /* the same dark mapping */ }
:root[data-theme="light"] { color-scheme: light; }
```

- Put every short name in the light block first; the dark blocks only remap them.
- Write the dark mapping twice (inside the media query and on `[data-theme="dark"]`), identically.
- Never set a colour directly inside a scheme block on a component; components read the short names.
- Give dark the same care as light: check contrast in both, and keep the accent working on both grounds.
- If the layout has a switcher (look in `specimen.html` for a control that changes the scheme, such as `.scheme-toggle`), style it like the other header controls, with a visible focus state and a target of at least 44 pixels.

### The brand mark and icons

Browser tabs, bookmarks and phone home screens show the site's icon. Design it with the theme so it belongs to it:

- A simple mark that still reads at 16 pixels: one or two bold shapes, no text, no thin lines. Shapes on whole pixels at 16 and 32 stay sharp.
- `site/favicon.svg`: the mark, square `viewBox`, no external references, coloured for both schemes with a style block inside the SVG:
  `<style>.m{fill:#...}@media (prefers-color-scheme: dark){.m{fill:#...}}</style>`
- `site/apple-touch-icon.png`: 180 by 180 pixels, the mark on a solid background (no transparency; the phone rounds the corners).
- Optionally `site/favicon.ico` with 16, 32 and 48 pixel images, drawn at each size. If it is left out, it is made from the SVG.
- If the layout shows a mark beside the site name (often drawn in CSS, for example `.site-name a::before`), make the icon the same mark.

These are site files, not theme files: they are installed at the site's root, which is why they go in a `site/` folder.

### Fonts

Bundle the fonts: `.woff2` files in `assets/fonts/`, loaded with `@font-face` from your stylesheet, with each family's licence file beside them. Use typefaces under the SIL Open Font License or the Apache licence; the Fontsource packages (`@fontsource/<family>` on npm) carry both the files and the licence text. No Google Fonts link or any other external resource: the site refuses them, and a font from another server tells that server about every visitor.

### Every element, every state

- Style everything in `specimen.html`, `pages/` and `STATES.md`: every heading level, inline element, list, table, code block, quotation, image, box, form field and form message, in each variant shown, and every state a still page cannot show (hover, focus, visited, disabled, invalid, placeholder, checked, open, the form's messages, a form in steps, both schemes, reduced motion).
- Style only what is there. Each selector should match something in the specimen, the pages or `STATES.md`.
- The layout's own `<style>` block loads after your stylesheet. Where you restyle what it styles, use a more specific selector (for example prefix it with `body`). `BRIEF.md` lists the custom properties it reads, which you must define.

### Accessible by default

- Text contrast at least 4.5:1, large text and control edges at least 3:1, in both schemes.
- A visible focus state on every link and control.
- Touch targets at least 44 pixels.
- Status never shown by colour alone.
- Works at 360 pixels wide with no sideways scrolling; the navigation stays usable there.
- Motion respects `prefers-reduced-motion`.

### What to send back

One folder, named for the theme in lower case:

```
<theme-name>/
  theme.json            name, layouts (as BRIEF.md gives), config: colours, dark, fonts, ...
  NOTES.md              see below
  assets/
    main.css
    fonts/              .woff2 files and each family's licence
  site/
    favicon.svg
    apple-touch-icon.png
    favicon.ico         optional
```

`NOTES.md` holds: the token table (name, light value, dark value, use); the type scale and spacing step; anything you chose to leave as the browser draws it, and why; assumptions you made; and anything that needs a layout change. Nothing else is needed: no screenshots, no copies of the specimen.

### Previewing your work

Open `specimen.html` and the files in `pages/` in a browser with your stylesheet in place of the current one (they load `css/tokens.css` and then the theme stylesheet in `css/`). Write your own `theme.json` values into `css/tokens.css` in the same shape (`--theme-<group>-<key>: value;` inside `:root`), since on the site the engine writes that file from `theme.json`. To see a scheme the device is not set to, add `data-theme="dark"` or `data-theme="light"` to the `<html>` element. The pages carry no scripts, so a menu that opens by script is seen by adding the class the layout uses (`BRIEF.md` names it) to `<body>`.


## Related

- [Layouts and themes](/docs/layouts) - how layouts and themes are installed and switched.
- [Onboard an AI agent](/docs/onboard-ai-agent) - connecting an assistant to your site, so it can read and preview pages.
- [AI briefing: layouts and themes](/docs/ai-briefing-layouts) - the briefing an assistant reads before it changes a layout or theme.
- [Integrations: Figma](/docs/integrations/figma) - taking a design from Figma onto a lazysite theme.
