This folder is the theme gallery. Every theme is a single, validated
*.yaml file describing a set of design tokens — no CSS, no JavaScript. The
build turns each file into a scoped [data-theme] CSS block and a registry entry
(src/data/themes.json). That "themes are data, not
code" rule is what makes it safe to accept a theme from anyone: a theme can't
inject styles or scripts into a forked, GitHub-Pages-hosted card.
Want to use one? Set theme: in libcard.config.yaml
to any slug below, or turn on the switcher to let visitors cycle through them.
Browse them live on the /themes page.
| Theme | Mode | Author | License | Built-in |
|---|---|---|---|---|
Default (default) |
light | @crs48 | MIT | ✅ |
Dawn (dawn) |
light | @crs48 | MIT | ✅ |
Dusk (dusk) |
dark | @crs48 | MIT | ✅ |
Frost (frost) |
light | @crs48 | MIT | ✅ |
Midnight (midnight) |
dark | @crs48 | MIT | ✅ |
Mist (mist) |
light | @crs48 | MIT | ✅ |
Mono (mono) |
light | @crs48 | MIT | ✅ |
Ocean (ocean) |
dark | @crs48 | MIT | ✅ |
Paper (paper) |
light | @crs48 | MIT | ✅ |
Sunset (sunset) |
dark | @crs48 | MIT | ✅ |
Terminal (terminal) |
dark | @crs48 | MIT | ✅ |
This table is generated by
pnpm run gen:themes— don't edit it by hand.
-
Scaffold it (recommended):
pnpm install pnpm run new-theme # interactive — writes themes/<your-slug>.yaml…or copy the template by hand:
cp themes/community-example.yaml themes/aurora.yaml
The filename (minus
.yaml) becomes your theme's slug — keep it lowercase-with-dashes and unique. -
Edit the values. Fill in the metadata (you'll be credited!) and the tokens. Keep
theme.schema.jsonautocomplete on by leaving the# yaml-language-serverline at the top. -
Preview it:
pnpm run gen:themes # regenerate CSS + registry from your file pnpm dev # then set `theme: <your-slug>` and look
-
Check it's accessible:
pnpm run check-contrast # WCAG AA on the key text/background pairs -
Open a pull request. CI validates the file, checks contrast, and posts a rendered preview on the PR. A maintainer reviews and merges — then it's in the gallery for everyone.
A theme provides seven colors (required, hex) plus a font and a corner radius.
| Token | Required | What it styles |
|---|---|---|
bg |
✅ | Page background |
surface |
✅ | Cards & buttons |
fg |
✅ | Primary text |
muted |
✅ | Secondary / muted text |
accent |
✅ | Links, primary buttons, focus rings |
accentContrast |
✅ | Text/icon on top of accent |
border |
✅ | Hairlines, card borders, dividers |
font |
— | sans · serif · mono · rounded (default sans) |
radius |
— | Any CSS length, e.g. 1rem, 8px (default 1rem) |
Accessibility: fg/bg, fg/surface, and accentContrast/accent must
meet WCAG AA (4.5:1). pnpm run check-contrast enforces this and the PR will
fail if a theme falls short — pick slightly stronger colors.
| Field | Required | Notes |
|---|---|---|
name |
✅ | Display name, shown in the picker and footer |
author |
✅ | You — credited as "Theme by <author>" in the footer |
authorUrl |
— | Makes your credit a link |
license |
— | SPDX id, default CC-BY-4.0 |
mode |
— | light or dark (default light) — sets native control colors |
tags |
— | A few keywords for the gallery |
description |
— | One line about the vibe |
Community themes default to CC-BY-4.0, which means the "Theme by <you>"
credit must be kept — a card owner can't turn it off. If you'd rather let people
use your theme with no attribution, set license: MIT or license: CC0-1.0; then
the credit becomes optional for them. Either way, you're always shown by default.
LibCard itself is MIT — the "Powered by LibCard" half of the footer is removable
via footer.poweredBy: false.