Guidelines
Poimandres is a distributed design system: nothing is installed from npm. It ships as a shadcn preset and a shadcn registry, so every pmndrs app gets the same colours by copying code in. shadcn's tokens are the base; Material Design 3 colour roles are additive, for what shadcn has no name for.
In code, one add brings the whole theme (the palette, the colour machinery under it and the mono font): npx shadcn@latest add pmndrs/design-system/theme#v0.9.0.
Colour
No colour is picked by hand. A few seeds go in and Material Design 3 computes every role from them, for light and dark alike.
colorMatch is Material Theme Builder's "stay true to my color inputs": each seed keeps its chroma and lands in its container role. The two neutral seeds look nothing like the grey ramps they produce, by design: a neutral ramp takes an eighth of its seed's chroma.
- Never write a hex. Use a role; if the palette must change, change the seed and recompute.
- Reach for the shadcn token first:
background,foreground,card,popover,primary,secondary,muted,accent,destructive,border,input,ring. Use an--md-sys-color-*role only where shadcn has no equivalent (--md-sys-color-surface-dim,--md-sys-color-tertiary-container,--md-sys-color-on-surface-variant). - Never build with
--md-ref-palette-*shades directly. They are the tonal ramps the roles alias, and they do not change between schemes. - Every fill has the role meant to go on it. Put
primary-foregroundonprimary,secondary-foregroundonsecondary,accent-foregroundonaccent,--md-sys-color-on-<role>on--md-sys-color-<role>, and--md-sys-color-on-<role>-containeron--md-sys-color-<role>-container. - Set body text in
foregroundand lower-emphasis text inmuted-foreground, onbackground,card,popoverormuted. secondaryandaccentare the MD3 secondary container (--md-sys-color-secondary-container), not--md-sys-color-secondary.- Draw control boundaries with
input.borderis decorative: it is too faint (under 2:1 onbackground) to be the only thing marking a control. - Draw focus with
ring. - Colour chart series with
chart-1tochart-5, in that order. They are the fixed roles, so a chart keeps its colours in light and dark. - The seed hex itself is the container role:
--md-sys-color-primary-containeris the lime.primaryis a dark olive in light and white in dark, so use the container where the brand colour itself must show. --md-sys-color-secondaryand--md-sys-color-tertiaryare generated but intentionally unused as accents: the named brand colours take their place.- The dark scheme is the
darkclass on<html>. - Designers get the same palette as Figma tokens, light and dark as two modes of one variable collection:
npx shadcn@latest add pmndrs/design-system/figma-tokens#v0.9.0. The same item carries type, spacing, radius and motion as a second collection, and the text and shadow styles as a file for Tokens Studio.
shadcn tokens and the roles they point at
The sidebar-* tokens follow their counterparts: sidebar-foreground is foreground, sidebar-primary is primary, sidebar-primary-foreground is primary-foreground, sidebar-accent is accent, sidebar-accent-foreground is accent-foreground, sidebar-border is border, sidebar-ring is ring.
Brand colours
The seven brand colours are declared next to the seed as custom colours, none of them blended: each stays its exact hex. Each becomes four roles: --md-sys-color-<name>, -on-<name>, -<name>-container, -on-<name>-container.
- Lime is also the
sourceseed, and red also drives the error role:destructiveand--md-sys-color-redare the same colour. - For the brand hex as a fill, use
--md-sys-color-<name>-containerwith--md-sys-color-on-<name>-containeron it. - Their shade utilities (
bg-purple-500) take over Tailwind's stock palettes of the same names.
Alert colours
Five semantic custom colours follow the brand ones, for alerts, hints, badges and statuses. They are seeded with GitHub's alert hues and, unlike the brand colours, blended toward the source seed, so they keep their meaning and still sit in the palette. Same four roles each.
- Style an alert with
--md-sys-color-<name>-containerand--md-sys-color-on-<name>-container, and its accent (border, icon, title) with--md-sys-color-<name>. - Never use a brand colour for an alert level:
cyanis notnote,redis notcaution.
Type
- The preset's font is Inter (
sans), and headings inherit it. Never hardcode a font family in a block. - The type scale is Tailwind's default:
text-xstotext-9xl, inherited, not yet a pmndrs decision. Set UI text intext-smand body copy intext-base; choose weight with Tailwind'sfont-*utilities. monois Inconsolata, from thefont-monoregistry item thatthemedepends on. It is scoped tocode, kbd, samp, pre: those elements use it without a class, and the rest of the UI keeps Inter. In app code, addfont-monoto any other element that should be monospace; a block never does.- Headings, paragraphs, lists and inline code follow shadcn's Typography class recipe (inline code:
font-mono text-sm font-semiboldonbg-muted). No element is styled by default.
Spacing, radii and shadows
Poimandres is shadcn-based, so outside colour, fonts and the base radius it embraces Tailwind's defaults. The repository's docs say which is which: the radius is a pmndrs decision; spacing and shadows are inherited from Tailwind v4.
- Space with the Tailwind scale, multiples of
--spacing(0.25rem): step 1 (p-1,gap-1) is 0.25rem, step 4 (p-4) is 1rem; never an arbitrary pixel value. - Every corner derives from one value,
--radius(0.625rem), from the preset. Its base-luma style multiplies it:--radius-smis ×0.6,--radius-lgis--radiusitself,--radius-4xlis ×2.6. Round withrounded-smtorounded-4xl; change--radiusand every corner rescales.rounded-xs(--radius-xs) is Tailwind's own step, outside that scale. - Elevate with
shadow-2xstoshadow-2xl, recess withinset-shadow-2xstoinset-shadow-sm, and shadow shapes that are not boxes (icons, SVGs) withdrop-shadow-xstodrop-shadow-2xl. Shadows are black at low opacity in both schemes; in dark, set surfaces apart with the--md-sys-color-surface-container-*steps instead.
Components
Poimandres is a distributed architecture based on shadcn blocks: any pmndrs/* repository can contribute blocks, each installed with a single shadcn add command, plus shared defaults (colours, radius, every shadcn token) that stay overridable by the consumer app. It is fully shadcn-compatible: every shadcn component is supported as is, and takes the palette through the shadcn tokens. The system adds no component library of its own.
- Start from a shadcn primitive (
npx shadcn@latest add button). Never restyle one with hardcoded colours; it already readsprimary,border,ringand the rest. - pmndrs' own components are blocks, distributed through shadcn's GitHub registries: any public
pmndrs/*repository with aregistry.jsonat its root is a registry. Install one by address:npx shadcn@latest add pmndrs/docs/keypoints#v4.22.0. - Always pin a ref (a tag or a sha). Refs are not inherited: every entry in
registryDependenciescarries its own. - A block depends on a shadcn primitive by bare name (
registryDependencies: ["button"]) and on another pmndrs block by its full pinned address (pmndrs/docs/mdx-prose#v1.0.0). A bare name never means a same-repo item. - A block that uses colour depends on
pmndrs/design-system/theme, so one add pulls the block and the colour layer with it, and the mono font throughfont-mono.themeis the single install target: it depends onmd3-base(the colour machinery and the seed) andfont-mono. Installmd3-basealone only to compute a palette of your own. - A block lives in the repository it was born in. It is promoted to
pmndrs/design-systemonly once it has shipped in its own repository and a second repository reuses it. There is always exactly one source of truth; promotion moves it. - Blocks are copied code, not a package: the consuming app owns the files and may override any shadcn token.
- A registry item is a set of files, so the same mechanism ships more than UI: a shader, a helper, a
SKILL.md. - Keypoints is the first block, born in
pmndrs/docs, the generator behind several hundred pages of documentation across the pmndrs libraries. It is released at that repository'sv4.22.0tag:npx shadcn@latest add pmndrs/docs/keypoints#v4.22.0. The same registry also holds Color, swatches of the MD3 roles:npx shadcn@latest add pmndrs/docs/color#v4.22.0. Both pin the colour layer, the pmndrs theme, atpmndrs/design-system/theme#v0.6.0; in a new app the current one ispmndrs/design-system/theme#v0.9.0. Planned, not yet available: shaders frompmndrs/drei, assets frompmndrs/assets, and blocks from otherpmndrs/*repositories. Do not assume a block exists; check the owning repository'sregistry.json, or the registry catalog on the docs site, before installing.
Logo
- Use
logo_complete.svgas the mark, as an image.logo_idle.svgis its resting state. - Both paint their own black square background; there is no transparent variant. Never recolour, crop or redraw the mark.
- In code,
npx shadcn@latest add pmndrs/design-system/logo#v0.9.0writes all four states (logo_complete,logo_idle,logo_animated,logo_loading) topublic/pmndrs/. - MIT, like the rest of pmndrs/design-system. No attribution required.
Iconography
- Icons are
lucide, the pmndrs baseline, taken from the app'scomponents.jsoniconLibrary. The repository ships no icon files.
Voice
- British spelling: "colour", "harmonizes".
- Short declarative sentences that state a fact and its consequence: "No colour is picked by hand.", "Nothing mounted: the palette is baked into the CSS.", "Always pin a ref".
- Lowercase
pmndrsandshadcnin running text; "Poimandres" when naming the collective. No emoji.