Gerstner, powered by Stride.
A type-first layout system for Tailwind v4. One atomic unit, the Stride, drives every column, offset, breakout, and subgrid alignment across the layout field.
Gerstner is not a grid plugin, not a token dump, and not a JavaScript layout engine. It is a programmable system in Karl Gerstner's sense: a small set of rules that makes the right layout resolve itself. The browser does the math. CSS owns the layout. Your project owns the final contract files.
npm install gerstner@import 'gerstner/css';@import 'tailwindcss';
@import 'gerstner/tw4';
@source '../node_modules/gerstner';npx gerstner initGerstner is designed to be adopted incrementally. Each rung builds on the last:
- Shell — Add
g-shellto a section. Get a centered, responsive 12-column grid with frame margins. - Columns — Use
col-1throughcol-12to place elements on the grid. - Rhythm — Use
g-prose,g-display,g-heading,g-uifor type roles with correct leading. - Subgrid — Use
g-subfor exact inherited alignment inside a parent grid. - Breakout — Use
g-content,g-breakout-r,g-breakout-lfor editorial compositions. - Density — Use
g-tight,g-standard,g-loosefor vertical spacing presets. - Presets — Use
.g-editorial,.g-marketing,.g-galleryfor character overrides.
You don't need all seven. Most projects need 1–4.
| Surface | Import | Use When |
|---|---|---|
| Vanilla CSS | gerstner/css |
No Tailwind, any framework |
| Tailwind v4 | gerstner/tw4 |
Using Tailwind v4 |
| Debug | gerstner/debug |
Dev-time overlay (optional) |
| Stride | gerstner/stride |
Raw token access only |
Stride is the single source of truth for all layout geometry:
- Canonical math:
stride/core.ts— pure functions, no DOM - Manifest:
stride/contract.manifest.json— generated artifact bridging TS and CSS - CSS runtime:
stride/index.css—@propertyregistrations +:rootderived tokens - Generated helpers:
css/helpers.css/tw4/helpers.css— emitted from manifest
Authored tokens (--g-cols, --g-gutter, --g-baseline, ...)
↓
Stride derives (--g-rhythm, --g-stride, --g-scale-*, ...)
↓
Surfaces consume via var() — never recompute
- Not a JavaScript layout engine — the browser does the math
- Not a design token dump — every token has a derivation reason
- Not a grid plugin — it's a programmable system
- Not a component library — it provides layout, not UI components
- Not a Tailwind competitor — it's a Tailwind v4 extension
<section class="g-shell">
<div class="g-content">
<h1 class="g-display">Designing programmes, not margins</h1>
<p class="g-prose">
The layout derives from type. The columns derive from stride. The browser resolves the rest.
</p>
</div>
</section>vp install # Install dependencies
cd apps/playground && vp dev # Run the playground
vp check # Format, lint, type-check
cd packages/gerstner && vp test # Run testsGenerated artifacts must not be hand-edited. Regenerate via:
pnpm emit:manifest # stride/contract.manifest.json
pnpm emit:helpers # css/helpers.css
pnpm emit:tw4 # tw4/helpers.css
pnpm emit:debug # debug/labels.json
pnpm emit:reference # reference-fixtures/metadata.jsonMIT