Design system
Architecture
3 min read
The few rules that keep everything in Nightgrid looking like one design, and where to find the full guide.
Nightgrid has one visual language: dark, calm, monochrome plus one accent. This page is the short version. The full guide is DESIGN.md in the root folder of the theme, and it is the one to follow when you build something new.
Tip
Working with an AI coding assistant? The theme ships an
AGENTS.mdfile in its root folder. It tells the assistant to readDESIGN.mdbefore it changes how anything looks, so new work follows the same rules.
Where the design lives
| File | Holds |
|---|---|
src/theme.config.ts |
The preset: accent, surface tint, borders, corners, button shape, glow, fonts |
src/styles/global.css |
Every token: colors, type sizes, spacing steps, radii, motion |
src/components/ui/ |
The shared parts every page is built from |
DESIGN.md |
How to use all of the above |
Values are not repeated here. Read them in global.css, where each token has a note about its job.
The rules in brief
- Tokens only. Colors, sizes, radii and shadows come from the tokens (
bg-surface,text-ink-body,border-line,rounded-card). Tailwind’s default palette is switched off. A hard-coded value breaks the presets. - One accent mark per section. The accent is for links, focus and one small mark: a badge, a glyph or the border of the featured card. It is never a background.
- Headings go through components.
Headingfor document headings,Titlefor card and row titles,Textfor copy.Heading size="lg"is the usual heading of a section. - Six spacing steps.
section,section-wide,heading,stack,textandheader. A section sets the space above itself and nothing below. - Hairline lists before cards. A set of items is rows divided by
border-line. A card is for a self-contained object such as a plan or a quote. - Still by default. Nothing fades or slides in on scroll. A looping animation can be paused and stops with the “reduce motion” setting.
- Text lives in
src/data/. A component holds no copy of its own.
The shared parts
| Part | Use it for |
|---|---|
Section |
Every page section: gutter, width and the space above |
SectionHeader |
A section title with an optional label and description |
Heading, Title, Text |
All type |
Button, ArrowLink |
Actions and links with an arrow |
MotionToggle |
The pause button of a looping animation |
Monogram, DemoNote |
Initials in place of a missing photo; the small “demo content” line |
Card |
Self-contained objects |
Badge |
The one accent label of a section |
Field |
Form inputs with label, hint and error |
Callout |
Notes, tips and cautions in long text |
Each file in src/components/ui/ starts with its props, so open the file to see what a part accepts.
A small example
---
import Heading from '../../ui/Heading.astro';
import Section from '../../ui/Section.astro';
import Text from '../../ui/Text.astro';
---
<Section width="md">
<Text variant="eyebrow" class="mb-4">Label</Text>
<Heading size="lg" class="mb-text">A plain section title.</Heading>
<Text size="lg" class="mb-heading">One line about it.</Text>
<!-- content -->
</Section>Imports are relative paths. DESIGN.md has a complete section built this way, and a checklist to run before you call new work done.