Martlet · Design system specification
Build with Martlet.
Core 2.2.1 · Astro 1.2.1
Martlet’s reusable design comes from jameshoward.us. The core package defines its visual vocabulary; the Astro package supplies layouts and components using those definitions. Your content, identity, navigation, and site behavior belong to your project.
This reference is built from the exact npm releases installed by this website. Token values and font roles below come directly from those packages.
@martlet/theme on npm ↗@martlet/astro on npm ↗Download the specification as JSON ↓
The UI language beyond the package reference
The source audit, experimental grammar, contents/sidebar distinction, independent footer anatomy, interaction obligations and framework support now have a consolidated language reference. Core 2.2.1 and Astro 1.2.1 are experimental releases under the npm next tag; the package versions reported on this page remain the exact installed releases.
Choose what to adopt
For colors or styles in any web project, install the core. Add the Astro package when you want its reusable components.
npm install @martlet/theme | Import | Effect |
|---|---|
@martlet/theme/css | Light and Dark semantic color variables only. |
@martlet/theme/foundation.css | Namespaced typography, spacing, shape, depth, and interaction variables. |
@martlet/theme/typography.css | Text styles inside .martlet; requires foundation variables. |
@martlet/theme/components.css | Optional interface primitives; requires color and foundation variables. |
@martlet/theme/fonts.css | Local font assets through the package’s pinned Fontsource dependencies. |
@martlet/theme/full.css | Colors, foundation, typography, and components. Load fonts separately. |
import '@martlet/theme/full.css';
import '@martlet/theme/fonts.css';<section class="martlet" data-martlet="dark">
<h2>Your content</h2>
</section> Color scopes can coexist on a page. Add class="martlet" to opt into typography and component styling. The core also exports ESM, CommonJS, TypeScript declarations, per-mode JSON, and highlight.js styles. The color reference shows both semantic palettes. Use purpose-based roles such as --martlet-text, --martlet-bg, and --martlet-on-accent together; source colors and semantic roles serve different purposes.
Typography
| Role | Family and weights | Use |
|---|---|---|
--martlet-font-serif | Cambo 400 | Body prose and h1–h3 |
--martlet-font-sans | Lato 400, 700 | Navigation, controls, tables, metadata |
--martlet-font-display | Cinzel 400, 600, 700, 800 | Display accents and h4–h6 |
--martlet-font-mono | IBM Plex Mono 400, 500, 600, 700 | Code, terminal text, keyboard notation |
Display and serif are separate roles even where they use the same family. Monospace changes affect code and terminal roles. Optional font loading uses locally bundled open-source assets; Berkeley Mono is a personal licensed override and is not distributed.
Foundation tokens
These are the installed core’s exact defaults, including text sizes, line heights, spacing, widths, corners, shadows, focus dimensions, and motion. Responsive expressions are preserved as CSS values. Breakpoint tokens, where present, document the scale; ordinary CSS custom properties cannot be substituted directly into media-query conditions.
| CSS variable | Default |
|---|---|
--martlet-color-charcoal | #303030 |
--martlet-color-navy-950 | #07111f |
--martlet-color-navy-900 | #0b1c33 |
--martlet-color-navy-800 | #132b49 |
--martlet-color-navy-700 | #1b3d64 |
--martlet-color-blue-600 | #255f91 |
--martlet-color-gold-700 | #80550f |
--martlet-color-gold-600 | #9a6b15 |
--martlet-color-gold-500 | #c7952f |
--martlet-color-gold-300 | #e6c77d |
--martlet-color-cream | #f8f4e9 |
--martlet-color-slate-900 | #202a35 |
--martlet-color-slate-700 | #566270 |
--martlet-color-slate-500 | #7b8793 |
--martlet-color-slate-400 | #9aa5b1 |
--martlet-color-slate-300 | #c9d0d7 |
--martlet-color-slate-150 | #e4e8ec |
--martlet-color-slate-075 | #f5f7f8 |
--martlet-color-white | #fff |
--martlet-color-ink | #222a33 |
--martlet-color-danger | #a3392e |
--martlet-hero-overlay | linear-gradient(115deg, rgb(7 17 31 / 90%), rgb(12 35 60 / 80%)) |
--martlet-font-display | 'Cinzel', Georgia, serif |
--martlet-font-serif | 'Cambo', Georgia, serif |
--martlet-font-sans | 'Lato', 'Helvetica Neue', Arial, sans-serif |
--martlet-space-1 | .25rem |
--martlet-space-2 | .5rem |
--martlet-space-3 | 1rem |
--martlet-space-4 | 1.5rem |
--martlet-space-5 | 2.5rem |
--martlet-space-6 | 4rem |
--martlet-space-7 | 6rem |
--martlet-space-8 | 8rem |
--martlet-reading-width | 48rem |
--martlet-content-width | 78rem |
--martlet-archive-width | 88rem |
--martlet-radius-sm | .25rem |
--martlet-radius-md | .55rem |
--martlet-radius-lg | .8rem |
--martlet-shadow-sm | 0 2px 12px rgb(7 17 31 / 10%) |
--martlet-shadow-md | 0 10px 30px rgb(7 17 31 / 14%) |
--martlet-shadow-lg | 0 18px 50px rgb(7 17 31 / 22%) |
--martlet-transition-ui | .2s ease |
--martlet-font-mono | 'IBM Plex Mono', ui-monospace, SFMono-Regular, Menlo, Consolas, monospace |
--martlet-text-body | 1.075rem |
--martlet-text-h1 | clamp(2.25rem, 5vw, 4.65rem) |
--martlet-text-h2 | clamp(1.75rem, 3vw, 2.6rem) |
--martlet-text-h3 | clamp(1.25rem, 2vw, 1.65rem) |
--martlet-leading-body | 1.72 |
--martlet-leading-heading | 1.18 |
--martlet-tracking-label | .1em |
--martlet-radius-control | 0 |
--martlet-radius-card | 0 |
--martlet-shadow-card | none |
--martlet-border-width | 1px |
--martlet-focus-width | 3px |
--martlet-focus-gap | 3px |
--martlet-gutter | clamp(1rem, 3vw, 2rem) |
--martlet-section-space | clamp(3rem, 6vw, 6rem) |
--martlet-control-height | 2.8rem |
--martlet-control-padding | .65rem .8rem |
--martlet-button-padding | .65rem 1.1rem |
--martlet-divider-width | 3rem |
--martlet-divider-thickness | 2px |
--martlet-link-underline-offset | .16em |
--martlet-motion-duration | .2s |
--martlet-layout-gap | 1.5rem |
--martlet-layout-gap-small | .75rem |
--martlet-layout-gap-large | 2.5rem |
--martlet-layout-sidebar-width | 16rem |
--martlet-layout-main-min | 30rem |
--martlet-layout-grid-min | 18rem |
--martlet-layout-split-min | 20rem |
--martlet-layout-section-space | clamp(3rem, 6vw, 6rem) |
Source provenance: k3jph/k3jph.github.io at 471abfe. The JSON specification also includes grouped design definitions, both semantic color modes, and host capabilities.
Astro components and starter
The installed wrapper supports astro ^5.14.0 || ^6.0.0 || ^7.0.0 with @martlet/theme ^2.2.1. Install both peer packages in an existing Astro project:
npm install @martlet/theme @martlet/astro---
import { Layout, Container, SectionHeading, Card, Button } from '@martlet/astro';
---
<Layout title="Your website" mode="light">
<Container width="reading">
<h1>Your own identity</h1>
<SectionHeading title="Start here" />
<Card>
<p>Your content, using shared design definitions.</p>
<Button href="/about/">About</Button>
</Card>
</Container>
</Layout> | Component | Contract |
|---|---|
Layout | Required title; optional description, lang, mode, mainId, mainTabindex, class, bodyClass, and skipLabel. Defaults to Light. Slots: head, header, footer, and body-end. Includes a skip link and the core styles and fonts. |
Container | width selects content, reading, or archive; content is the default. Accepts class and a default content slot. |
SectionHeading | Required title. Optional id, eyebrow, description, level (h2 or h3), align (left or center), and class hooks. Includes default and divider slots. |
Card | An article wrapper with a class hook and a default content slot. |
Button | With href, renders a link. Otherwise renders a button, defaulting to type="button". Accepts native attributes, including disabled on buttons, and a default content slot. |
Import components from @martlet/astro or use direct paths such as @martlet/astro/Card.astro. To retain your own document shell, import @martlet/astro/styles.css and apply the core’s class and appearance attributes.
Start a new site
The npm package includes a neutral starter/ directory. From an existing project or a temporary setup directory, install the packages and copy the starter to a new directory. The example below uses a POSIX shell; other systems can copy the same folder with their file manager.
npm install @martlet/theme @martlet/astro
cp -R node_modules/@martlet/astro/starter ./my-martlet-site
cd my-martlet-site
npm install
npm run dev The starter currently uses Astro 7, so use Node 24 or another runtime supported by that Astro release. The starter supplies initial files; the packages supply updates afterward. Replace the sample content and metadata with your own.
Interaction and accessibility
The optional core components provide hover, disabled, and visible keyboard-focus styling. Motion tokens reduce to zero when prefers-reduced-motion: reduce is active. Use native links for navigation and native buttons for actions; retain labels, heading order, and the document skip link.
Pair foreground and background tokens deliberately. Existing contrast checks cover defined pairs, not every possible combination or application. Check normal, hover, focus, and disabled states in both appearances, with enlarged text, narrow viewports, keyboard navigation, and reduced motion. Use labels or symbols as well as color to communicate status.
Layouts and components supply primitives. Menus, dialogs, consent controls, analytics, and their behavior remain the responsibility of the consuming site. A themed page still needs application-level accessibility review.
What each integration applies
| Integration | Applied | Optional or host-specific |
|---|---|---|
| web-core | colors, typography variables, spacing, shape, depth, interaction variables, layout primitives | Optional: font loading, element typography, components. |
| astro | web-core, document shell, container, section heading, card, button, page header, site header, site footer, article layout, landing layout, documentation layout | Site-owned: navigation, content, consent, analytics, personal identity. |
| vim | colors, syntax | Configure separately: monospace font. Outside this integration: web layout, proportional typography. |
| emacs | colors, syntax | Configure separately: font roles. Outside this integration: web layout. |
| terminal | colors | Configure separately: monospace font. Outside this integration: web layout, serif, sans. |
| firefox | browser chrome colors | Outside this integration: fonts, website content, spacing, components. |
| chrome | browser chrome colors | Outside this integration: fonts, website content, spacing, components. |
Browser themes apply browser interface colors. Editor and terminal ports map the roles their hosts support. They do not all reproduce a web layout or change typography automatically.
Customization and releases
Override namespaced variables within your own site scope, loaded after the package styles. This changes your installation without creating another authoritative copy of the theme.
.my-site {
--martlet-reading-width: 44rem;
--martlet-font-mono: 'Your licensed font', monospace;
} The core and Astro packages are versioned independently. The release policy is semantic versioning: compatible fixes are patches, compatible additions are minor releases, and breaking changes to exports, tokens, component APIs, or documented behavior require a major release. Keep a lockfile and review updates against your application. This website pins the versions shown above; the reference changes when those pins change.
Propose shared visual changes in the core repository, with corresponding documentation and verification. Theme software uses the MIT license; fonts retain their bundled license notices. Heraldic artwork, personal identity, and site content are separate from the reusable design system.