Design System
How this documentation site looks, where the tokens live, and the rules to keep when you change it.
This page is for people changing the docs site, not people using MeowKit. It says where each part of the design lives so you edit the real thing rather than a description of it.
The site runs on Fumadocs on the Next.js App Router. Layout, sidebar, search, and the MDX component set come from fumadocs-ui. Everything below is what MeowKit changes on top.
Where the design actually lives
| What | File |
|---|---|
| Colour tokens, light and dark themes, display typography | app/global.css |
| Fonts loaded and applied | app/layout.tsx |
| Sidebar, nav, shared layout options | lib/layout.shared.tsx |
| Home page | app/(home)/page.tsx, components/home/ |
| MDX components available inside pages | components/mdx.tsx, components/mdx/ |
| Navigation order and section labels | content/docs/**/meta.json |
app/global.css is the source of truth for the palette. This page deliberately does not restate the values, because a second copy of a colour ramp is a copy that goes stale and the CSS is readable on its own.
The system in one paragraph
Cool paper, one blue signal accent, and a display/body/code type stack: Space Grotesk for display, Inter for body, the platform mono for code. Colour is the Fumadocs ocean preset. Neutrals are blue-tinted slate rather than true grey, which is what keeps the light theme from reading as clinical white and the dark theme from reading as flat black. The accent is navy in light and pale blue in dark.
Rules worth keeping
These are decisions, not defaults. Changing one is fine; changing one by accident is not.
- The accent is a signal, not a surface. Blue marks links, active states, and focus rings. It does not fill sections. Once it fills things it stops meaning anything.
- No gradients. Hierarchy comes from weight, spacing, and hairline rules.
- Three type families is the ceiling. No fourth face. Emphasis is weight or accent, never italic headings.
- Motion is functional only. Hover and focus transitions, opacity and border-colour and transform, 150–250ms. No reveal animations, no celebratory motion, no lift-and-glow on cards. Under reduced-motion, transitions collapse to a short opacity fade.
- Success is silent. Nothing congratulates the reader.
- Components reference tokens. An inline hex or
oklch()in a component is the design system being bypassed.
Changing it
Colour arrives as a whole palette, not as a list of values:
- Retheme by swapping the preset import in
app/global.css, currently@import 'fumadocs-ui/css/ocean.css'. Fumadocs ships eleven of these; each sets every--color-fd-*slot for light and dark at once. One line moves the entire site. - Re-map one role by declaring that single
--color-fd-*slot below the import. It wins on cascade order, so an override is deliberate and visible rather than a whole second palette shadowing the first.
Overriding every slot is how you end up with a preset that loads and does nothing. Reaching past both to style a component directly is how a design system stops being one.
Run npm run dev in packages/docs to see changes. npm run build is what CI runs.