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

@withseismic/grid

v0.1.0

Published

Both axes are twelfths. A layout system where a page is right when its parts sum to twelve in each direction.

Readme

@withseismic/grid

Both axes are twelfths.

The page is twelve columns wide. A row is twelve units tall. The two axes take the same seven names — full, 2-3, half, third, quarter, sixth, 12th — and the same arithmetic. A row's cells must sum to twelve across; a split's cells must sum to twelve down.

That is the whole system, and the point of it is that a layout stops being a matter of taste. It is right when it sums, and you can check that by counting instead of by looking.

pnpm add @withseismic/grid
import "@withseismic/grid/grid.css";
import { Page, Row, Cell, Split, Rest, Movement, Hero, GridOverlay } from "@withseismic/grid";

<Page>
  <GridOverlay />

  <Hero
    no="00"
    title="Twelve columns, twelve units tall."
    support={<p className="t-1 copy">No page margin. No gutter.</p>}
  >
    <Split w="half">
      <Cell v="2-3" media={<Plate />} label="IMAGE:" note="2/3" />
      <Cell v="third" label="THE LADDER:" note="1/3">
        <span className="t-2">FULL — 2-3 — HALF — THIRD</span>
      </Cell>
    </Split>
  </Hero>

  <Movement no="I" title="A page is a sequence of movements." />
  <Row h="3rd">
    <Cell w="half" label="A:" note="1/2">…</Cell>
    <Cell w="quarter" label="B:" note="1/4">…</Cell>
    <Cell w="quarter" label="C:" note="1/4">…</Cell>
  </Row>
  <Rest h="12th" />
</Page>

Two numbers, one inset

Twelve columns and a 12px unit. There is no page margin and no gutter: the cell's own padding (2 units) is the only inset in the system. A margin, a gutter and a padding are three mechanisms for one job, and two of them make the third unreadable — with the other two at zero, a column is exactly page / 12 with no remainder, and the column edge, the hairline and the padding edge are one line.

Both are available as one-class experiments (html.margins, html.gutters) because being able to remove them without anything else moving is the argument for the system, not for the setting.

The unit is also the baseline

12px. Cell padding is 2 baselines, a vertical twelfth is 8, a page is 96. So a line of type in one cell lands on the same line as type in the cell beside it — not merely inside a box of the same height, which is the difference between aligned and coincidentally similar.

The type scale runs on root two: 14, 20, 28, 40, 56, 80, 112, 158, with line boxes in whole baselines. Alternate steps are exact doubles, which is the only ratio where extending the scale cannot make it drift. Half-leading is trimmed, so the padding you set is the padding you see.

Hierarchy is countable

A page is a sequence of movements. One opens full width with a single statement, divides, and closes with a rest. What ranks a row is how many cells it has, and height agrees with it: inside a movement the cell count strictly increases and the height never increases.

Two adjacent rows divided the same way is the anti-pattern — it reads as one region cut in half for no stated reason. If two rows want the same division, they are one row.

Press G and every row prints its own count. A movement is right when the numbers only climb.

Continuity

A grid of closed rows hands the eye off at every boundary — correct for apparatus, wrong for anything meant to be looked at. Media can cross the line:

<Row h="3rd">
  <Cell w="third" media={<Plate />} bleed="6th" label="/ 01" />
  <Cell w="2-3" label="…">…</Cell>
</Row>
<Row h="6th" ruled={false}>
  <Cell w="third" />           {/* left empty to receive the bleed */}
  …
</Row>

The hairline continues to either side and the picture passes in front of it. Only media bleeds, only downward, one per row. Consecutive bleeds alternate sides — left, right, left — so the page acquires a route rather than a sequence: each hand-off throws the eye across the full measure to pick up the next. Two on the same side send it straight down one column, which is the path it would take anyway. The overlay measures each bleed's side and flags any that repeats.

ruled={false} is the other half: two rows that are one field rather than two subjects.

/flow on the docs site is the system used as a page rather than described as one — four pictures, four crossings, one Z.

Overlays

Nothing in this system is asserted that cannot be looked at.

| key | shows | |---|---| | G | the twelve columns, the vertical ladder, and each row's cell count | | B | the baseline, every 12px, brighter every eight | | R | rules off — the honest test of whether the grid is doing its job | | ← / → | density: tight / normal / loose — inner air and the narrowest allowed fraction | | ↑ / ↓ | the page unit — vertical scale, in multiples of 144 |

Margin and gutter remain as html.margins / html.gutters classes for comparison; they are no longer on keys, because the answer is decided.

Rules off is worth the key it takes. The hairlines are the system made visible, and a page that only works with them on is held together by its own diagram. Turn them off: if the regions are still legible from alignment and air alone, the grid is doing its job. It works by setting the rule colour to the ground rather than removing borders, so nothing moves by a pixel — the only way the comparison means anything.

Two knobs, not one

Looseness is two independent things and they are on different arrows.

Density (← / →) is inner air. Tight is 1X padding, normal 2X, loose 4X — and loose also bans the narrow end of the ladder: no quarters, sixths or twelfths. A page restricted to halves and thirds with double the padding cannot be busy; it can only be well or badly proportioned, which is a much easier problem. The ban is checked rather than enforced, because silently promoting a quarter to a third would break every row it appears in — four quarters make twelve and four thirds make sixteen.

Vertical scale (↑ / ↓) is the page unit. Every named height is a fraction of it, so raising it makes every region taller without changing a single fraction in the source. It steps in multiples of 144 because a twelfth must stay a whole number of 12px baselines: 1152/12 = 96 and 1440/12 = 120 both work, 1200/12 = 100 does not.

That heights are derived from one property rather than listed is what makes this a single line of code instead of a second set of layout rules.

Without React

grid.css is the whole system; the components are a convenience over it. In Astro, plain HTML, a Webflow export or anything else, use the classes directly — the arithmetic does not care what rendered the markup.

<main class="wsg">
  <section class="frame row h-3rd" data-cells="3">
    <div class="cell w-half">
      <div class="cell__tl mono mono--dim">A:</div>
      <div class="cell__tr mono mono--dim">1/2</div>
      <div class="cell__main"><p class="t-4">…</p></div>
      <div class="cell__br mono">6</div>
    </div>
    <div class="cell w-quarter">…</div>
    <div class="cell w-quarter">…</div>
  </section>
  <div class="frame rest h-12th"></div>
</main>

The class vocabulary mirrors the components exactly: .row + .h-*, .cell + .w-* / .v-*, .split, .rail, .rest, .stack--*, .plate, .t-1.t-8. The only thing you give up is data-cells being counted for you — set it yourself if you want the overlay to check your rows.

Fonts

The package names families and never ships a typeface. --sans and --mono are custom properties; point them wherever your licence allows. A layout system that carries someone's foundry licence around with it is a liability rather than a convenience.

The docs site sets --mono to Tronica Mono (© 2021 ATK Studio, Radinal Riki) under WithSeismic's own licence for it. It is a licensed face, so it lives in the docs app and never in the package.

Theming

grid.css is layout only. Colour and the two faces are custom properties with neutral defaults — override them, or import theme-spec.css for the dark technical look the system was designed against.

Docs

https://docs-production-de45.up.railway.app — the spec, and /flow, which is the system used as a page rather than described as one.

pnpm docs:dev runs it locally on 3200. The documentation is the system documenting itself, which is the only honest test of it.

Artwork on /flow is this alcohol-ink painting from Pexels, one image in three crops. <Ink> in the package generates abstract figures with SVG turbulence when you have no artwork yet.

Releasing

Releases happen in CI, not from a laptop — the same rule as the Hogsend repo, and here it is also a necessity: the npm account has 2FA set to auth-and-writes, so an interactive publish demands a one-time password and an automation token does not.

Once: create an Automation token on npmjs.com, then

gh secret set NPM_TOKEN --repo dougwithseismic/withseismic-grid

After that a release is two commands:

npm version patch     # or minor / major
git push --follow-tags

.github/workflows/release.yml type-checks, builds, asserts the tag matches package.json, and publishes with provenance.

License

MIT.