npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

geviert

v0.1.0

Published

Parameterized graphic design on Swiss grid systems: Müller-Brockmann's modular typographic grids, Gerstner's programmes, and seeded, constraint-solved page composition. A page is a constraint.

Readme

Geviert

A page is a constraint, not a canvas.

a page composed by geviert

See it compose itself

geviert.melissawiederrecht.com — a real book, composed in your browser as the page loads. Reroll the seed, roll a new grid, show the grid. The text is live: select it, copy it, search it. Every baseline is measured, not computed, and lands within 0.013 px of the lattice.

das Geviert — the em quad, typography's square module, from the old German verb vieren, "to make four." Pronounced geh-FEERT.

A permissive open-source library for parameterized graphic design on grid systems in the Swiss tradition: Karl Gerstner (Designing Programmes, 1964) and Josef Müller-Brockmann (Grid Systems in Graphic Design, 1981). Built from a full reading of the sources (see research/); the canon is encoded as executable rules and the test suite reproduces the books' own numbers.

Gerstner's thesis is the API: instead of solutions for problems, programmes for solutions. You author constraints; the library enumerates every layout that satisfies them; a seed picks one. Deterministic: same programme + same seed → same layout, forever.

Is this for you?

Read this before anything else, because it will either delight you or send you away, and both are fine.

There is no way to express an off-grid position. Not discouraged — no syntax for it. A picture is a rectangle of whole grid fields; a title stands on whole body lines; a chart's bars are whole lines tall. If your work needs a box nudged 3 pixels left, you need a different tool, and you'll know within one paragraph of the docs rather than on day two.

What that refusal buys: because every legal page is built from countable parts, the set of valid layouts is finite — so layout becomes a search, taste becomes a small object of named weights you can read and change, and a seed can reproduce any book forever. This is a designer in a library: opinionated, citable, deterministic. It is not a layout engine that does what it's told.

If you want: seeded editorial layouts for generative art, print-quality PDFs from data, browser-native paginated documents with live selectable text, or the Swiss canon as an executable specification — you're home.

And to be equally plain about what this is not: it is a page composition engine, print-shaped, composing fixed-size leaves. It is not CSS Grid for your website, it does not lay out existing DOM, and it will not make your app responsive. If "grid" brought you here from web layout, this is the other, older meaning of the word.

Quickstart

npm install geviert

The shortest path is a named programme — a complete commission (grid, registered type system, setting) you can override key by key:

import { composeDocument, programmes, renderPage } from 'geviert';

const { pages } = composeDocument({
  ...programmes.book(),          // MB's own A4 page; also: essay, booklet
  story: myParagraphs,
  seed: 'first',
});
const svg = renderPage({ grid: pages[0].grid, items: pages[0].items });

The full commission, written by hand:

import { composeDocument, grid, style, typeSystem, renderPage } from 'geviert';
import { registerFontFile } from 'geviert/font-file';   // optional peer: opentype.js

await registerFontFile('inter', './Inter-Regular.ttf'); // any TTF/OTF/WOFF, one call

const T = typeSystem({ module: 12, roles: {
  body:    style(9, 3, { font: 'inter' }),
  chapter: style(17, 7, { font: 'inter', weight: 'bold' }),
  caption: style(7, 5, { font: 'inter' }),
}}).roles;                                              // refuses, helpfully, if it can't register

const { pages } = composeDocument({
  grid: ({ side }) => grid({ page: 'A4',
    margins: { inner: 42, head: 46, outer: 50, tail: 78 },
    columns: 4, columnGutter: 13, line: T.body.lineHeight, rows: 8, side }),
  styles: T,
  story: [
    { text: 'ONE', role: 'chapter', rule: true, spaceAfter: 1 },
    'A paragraph. Another sentence of it, with a picture nearby (Fig 1).',
  ],
  figures: [{ anchor: '(Fig 1)', sizes: [{ cols: 2, rows: 2 }], href: 'photo.jpg',
              caption: 'Fig 1. Sized in fields, placed by search.' }],
  seed: 'any-string',
});

const svg = renderPage({ grid: pages[0].grid, items: pages[0].items });

Ships with TypeScript types for the whole surface. Composes ~30 pages/second with figures, justification and Knuth–Plass on an ordinary laptop (280-page benchmark: node tools/bench-book.mjs).

The pieces

  • Units & paper — Didot points, ciceros, mm; ISO 216 exact (MB pp.16-18)
  • Type area (typearea.js) — margin canons (MB 1:1.5:2:3, golden 3:5:5:8), half-page-area construction, craft advisories (MB pp.39-56)
  • Modular grid (grid.js) — the MB grid: field height = whole lines, gutters = whole empty lines, k·m+(k−1)·g = N division arithmetic; ships the three dimensioned A4 reference grids (8/20/32 fields, MB pp.73/77/88) as presets
  • Mobile grid (mobile.js) — Gerstner's compound grid: one square area in line-units carrying simultaneous column divisions; gerstnerNumber() finds the minimal unit count for your divisions (58 for 1..6 at gutter 2)
  • Programme (programme.js) — constraints DSL + exhaustive backtracking solver + seeded selection with taste scoring; solutions(), layout(seed), reroll(seed, {lock})
  • SVG renderer (render/svg.js) — grids, layouts, and mobile-grid figures drawn in the book's own conventions (red hairlines, grey blocks, the proportional diagonal)
  • Typography (type.js) — styles, AFM metrics (Helvetica/Times), ragged line breaking, and typeSystem() enforcing MB's cross-size register: every style's line height must meet the shared module (24pt canon)
  • Typeset pages (render/page.js) — text flowed into fields on the baseline lock (last line stands on the field bottom, MB p.58), images clipped to field rects (or deterministic placeholders), rules and blocks
  • Placement helpers (helpers.js) — folio placement per MB pp.42-44/68, bottom-anchored captions (p.108), subtitle slots (p.106)
  • Mobile programmes (mobileProgramme.js) — the solver over Gerstner's compound grid, with column division and row division chosen independently per item (2-division wide, 6-division deep) — cross-division layouts nobody else ships

Quick taste

import { presets, programme, field, align, below, whitespace, renderSVG } from 'geviert';

const p = programme({
  grid: presets.mb20(),                      // MB's dimensioned 20-field A4 grid
  content: {
    headline: { cols: [2, 4], rows: 1 },
    image:    { cols: [2, 3], rows: [2, 3] },
    body:     { cols: 1, rows: [2, 3] },
    caption:  { cols: 1, rows: 1 },
  },
  constraints: [
    field('headline').inBand('top', 1 / 5),
    below('image', 'headline'),
    align('caption', 'image').leftEdge(),
    below('caption', 'image'),
    whitespace().atLeast(0.15),
  ],
});

const layout = p.layout('edition-7');        // seed → layout, deterministic
const svg = renderSVG(layout);               // book-style drawing
const variants = p.solutions({ limit: 100 }); // or enumerate the space
const re = p.reroll('edition-8', { from: layout, lock: ['headline'] });
import { mobileGrid, gerstnerNumber } from 'geviert';

gerstnerNumber([1, 2, 3, 4, 5, 6], 2);       // → 58. That's why Capital was 58 units.
const mg = mobileGrid({ unit: 10, units: 58 });
mg.field(4, 1, 0, 2, 3);                     // a field on the 4-column division
  • Morphological box (box.js) — Gerstner's enumerable parameter space (KG pp.58-60), with his own typogram box shipped verbatim as GERSTNER_TYPOGRAM; pick(seed) chooses style chains the way layout(seed) chooses placements
  • Caption systemcaptionFit()/gutterCaption() put captions IN the row gutter the grid was constructed to hold (MB p.63); figure() bundles picture + caption into one whole-line extent nothing can crowd
  • Real fontsregisterFont() takes exact widths/metrics + optional embedded data URI; tools/font-metrics.mjs extracts everything from a TTF/OTF (via opentype.js)

Running

npm test             # canon tests — assertions cite book pages
npm run examples     # examples/out/: grids, KG p.61 figure, contact sheet,
                     # plate reproductions, 6 typeset editions, mobile poster
npm run build        # dist/geviert.js (+ .min) browser bundle
node tools/svg-to-pdf.mjs in.svg out.pdf   # print-ready PDF at true size

Escape hatches and honest edges

  • Taste constants are named options with cited defaults, not magic: the justify elastic limits, caption air, title-rule position, pull-quote sizing, the anchor pull, the whole harmony object. Disagree with a number? Pass your own.
  • Register errors teach: break the module and the error names the nearest legal settings for your size instead of just refusing.
  • Optional peers, all opt-in, core stays zero-dependency: opentype.js (font files at runtime), hyphen (TeX hyphenation patterns), @chenglou/pretext (30× faster greedy breaking, eval script included).
  • Book furniture ships: running heads (runningHead), footnotes (notes on a paragraph — set at the foot of the column, never split across pages, refused with arithmetic when they cannot stand), generated contents (report.contents + contentsLeaf()), and cross-references ({page:id} tokens, resolved by recomposition until stable).
  • Right-to-left setting ships (direction: 'rtl'), with one honest condition: joining scripts (Arabic, Syriac) must be measured shaped, so composition happens in a browser or headless Chrome after useBrowserFonts(). Measuring Arabic from width tables is refused with a teaching error, not composed wrong.
  • Justification is by elastic word spaces. Kashida justification is not here yet: proper elongation needs per-typeface knowledge of legal insertion points. The Arabic essay on the site discloses this in print.
  • Not here (yet): tables, line/pie charts, vertical setting, facing-page balance. The canon chapters on exhibition systems and corporate identity are out of scope on purpose.

Status

0.1.0. The library is complete for what it claims and proven by the books on the site's shelf, including a manual it composes about itself. APIs may still move while the version starts with a zero. Maintained as time allows, by one person, with care.

License: MIT. Image sources for every book: CREDITS.md.