CLI tool
StackExchange/Stacks avatar
StackExchange/Stacks

Stacks is Stack Overflow's design system, published as npm workspaces

Stack Overflow’s Design System

678 stars106 forksTypeScriptMIT

At a glance

What is it?
The StackExchange Stacks repository holds Stack Overflow's design system as a monorepo of npm workspaces: a Classic CSS and JavaScript implementation, a Svelte port with its own documentation site, and the docs project itself. It is a real product team's system, so adopting it means adopting their decisions too.
Who is it for?
Adopt Stacks if you want the visual language of Stack Overflow's products, with a Classic build for plain CSS and JavaScript and a Svelte build for component work, plus a documented system behind it. Do not adopt it if you need a small dependency, if your product needs its own brand language, or if a multi package monorepo with changesets, a visual regression suite and a migration guide is more structure than your team wants to own.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 2 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

One system, three workspaces, two implementations

Stacks is described in the README as Stack Overflow's design system, the shared foundation of components, styles and guidelines used across Stack Overflow's products, and the repository points to a usage guidelines page for how to use it. The interesting part for an outside engineer is how the system is packaged, because the repository is a monorepo with npm workspaces and the packages are not interchangeable.

Three workspaces are described. Stacks Classic contains the css and js sources that define and power the design system, and its documentation lives in the separate Stacks Docs workspace, which is the project hosted at stackoverflow.design. Stacks Svelte is a Svelte implementation of the same design system, and unlike Classic it defines its documentation site inside its own workspace, reachable at svelte.stackoverflow.design. Stacks Docs is that documentation project itself.

So there are two ways to consume the same visual language: the Classic build if you write plain CSS and JavaScript, and the Svelte build if you write Svelte components. The README is explicit that the Svelte package is an implementation of the Stacks Classic design system rather than a separate system, which is the point of keeping them in one repository.

The repository also carries the artefacts of a system used in production at scale. There is a MIGRATION_GUIDE.md, a directory of adrs/ for architecture decision records, a .changeset/ directory, a CODE_OF_CONDUCT.md, an eslint.config.mjs, a stylelint configuration and a prettier configuration. Nothing about that list is exotic, but the presence of it tells you the project is run like a product rather than a sample.

The root scripts fan out to every workspace

The root package.json is marked private and declares its workspaces as packages/*, with the name stacks and the MIT license. The interesting part is the script section, because the root scripts do almost nothing themselves and instead delegate to each workspace with the -workspaces and -if-present flags.

Build is npm run build -workspaces -if-present, and the same pattern applies to format, lint and test. The release script runs a build and then changeset publish, while the version script runs changeset version followed by a package-lock-only install, which is the standard changesets flow for versioning packages independently. There is also a test:release script that runs a node test file for the release tooling itself.

The practical effect is that a contributor learns four commands and they work everywhere. The npm start command is the exception, since it delegates specifically to the docs workspace with npm run dev -w packages/stacks-docs, which is what brings up the documentation site locally.

Two details show how the release process is treated as a first class concern. The publish step is guarded by a prepublishOnly hook that builds all workspaces first, so a package cannot be published with a stale build. And a separate test:release script checks the changesets tooling, which is a small sign that the release pipeline itself is covered by tests.

Visual regression tests need git lfs, docker and pwsh

The Stacks Classic workspace carries a test suite with four distinct parts, and the visual regression one has the heaviest prerequisites: git lfs, docker, pwsh, and a git config change so that image diffs work as expected. That is a demanding setup for a library of styles, and it is the clearest signal of how seriously the team treats visual regressions.

The mechanism uses the Web Test Runner visual regression plugin, and the tests are files ending in *.visual.test.ts. Running them locally is a workspace scoped command:

sh
npm run test:visual -w packages/stacks-classic

After a first run, failing snapshots overwrite the baseline images on disk, in a directory laid out as /screenshots/<browser>/baseline/<name>.png. The README explains why: the diff is easier to read in an editor when only the failing snapshots are regenerated, and the team recommends a VS Code image diff extension for the same reason.

The CI behaviour is worth knowing. The visual regression suite runs only when a pull request or commit touches Stacks Classic styles, runtime code, visual tests or fixtures, baselines, direct dependency manifests, or the visual test infrastructure. For an unrelated change the required check still completes successfully, it simply does not execute the suite. That is a sensible optimisation, but it means a green CI badge does not always mean the pixels were checked.

The unit and component tests are the conventional part of the story. They use DOM Testing Library, and the suite runs in a real browser through Web Test Runner and Playwright rather than a simulated DOM, which is the right call for a component library.

Less is the source, CSS is the build output

There is an experimental suite whose job is to test the generation of CSS from Less files, with test files ending in *.less.test.ts. Two commands drive it:

sh
npm run test:less -w packages/stacks-classic

and, to update the CSS snapshots:

sh
npm run test:less:update -w packages/stacks-classic

This is a structural fact about the Classic package that the README does not spell out but the test suite makes obvious. Less is the authoring format, CSS is generated output, and there are snapshot tests guarding that generation. The snapshots are the contract between the two.

The consequence for a consumer is that the CSS in the published package is a build artifact, and a change in the Less sources can change the CSS output without any obvious edit in the compiled file. It also means the project treats its own build pipeline as something to test, which is more than many design systems do.

The suite is described as experimental, which is worth holding onto when you weigh the risk. A snapshot of generated CSS will change whenever the Less is reorganised, and an experimental suite is the first thing likely to be reshaped.

The rest of the Classic quality tooling is conventional and split by concern: a format script running prettier, a lint script, a lint:css script running stylelint on the styles, a lint:ts script running eslint on the TypeScript sources, and a lint:format script for the formatting check. Each is scoped to the workspace with the -w flag.

Stacks Svelte ships its own docs and a Storybook loop

The Svelte workspace follows a different working rhythm. Its documentation site lives inside the workspace, at svelte.stackoverflow.design, rather than in the shared docs project, and local development runs through Storybook:

bash
npm run storybook -w packages/stacks-svelte

The Storybook server reflects changes to component stories in real time. Stories are written in Svelte syntax using the addon-svelte-csf addon, and a file has to carry the *.stories.svelte extension for it to be picked up, which is a small detail that catches people the first time they add a component.

The testing story matches Classic, which is the point of the shared repository. Stacks Svelte uses Web Test Runner and Playwright to run tests in a real browser context, with the same workspace scoped test command:

bash
npm run test -w packages/stacks-svelte

and a watch mode variant is documented alongside it.

Looking at the dependency list in the root package.json, the Svelte side is where the modern toolchain sits: the Svelte Vite plugin, the Svelte package, Storybook with its Svelte and Vite integrations, the accessibility, docs and links addons, and the Svelte testing library alongside the DOM testing library. The icons are also published as separate packages, @stackoverflow/stacks-icons at version 7 with a legacy alias pinned to the 6.9 line.

That legacy alias is a useful detail for anyone migrating. It means an application can move from the old icon package to the current one without a flag day, and the repository keeps a major version behind for exactly that reason.

Getting a workspace running locally

The local development setup is short. Install every dependency once at the root, and because the repository uses npm workspaces that covers all packages at the same time:

sh
npm i

To work on the documentation project, start the dev server:

sh
npm start

That command pulls up a local dev server at http://localhost:5173/. If you are working on the Classic library instead, the workspace scoped commands are the ones you want:

sh
npm run format -w packages/stacks-classic
npm run lint -w packages/stacks-classic
npm run test -w packages/stacks-classic

The unit and component tests have their own entry point if you want to run just those, and a watch mode is available for iterating:

sh
npm run test:unit -w packages/stacks-classic

Contributing to the project is documented separately. The README points at a contribution guide that covers where to report bugs or request features, how to set up and submit pull requests, the merge requirements including required approvals and deployment rules, and the code guidelines for formatting and style. Those merge requirements are the interesting part for an outside contributor, because they tell you what a change has to clear before it lands.

What it costs to adopt a design system built by another company

The honest limits of this project are about adoption rather than about code.

First, you are adopting Stack Overflow's product decisions. The components, spacing, colour and typography are the ones their products use, which is exactly what you want if you are building something in that idiom and exactly what you do not want if your product needs its own brand. A design system is a set of decisions, and a public one is a set of decisions you did not make.

Second, the package is not small in organisational terms. The Stacks Classic package pulls in the css and js sources, and the workspace brings a Storybook loop, a Less build with snapshot tests, a visual regression suite that needs git lfs, docker and pwsh, and a changesets based release process. That is a real amount of tooling to adopt, even though it is all well chosen.

Third, the release signal is thinner than the repository suggests. The recent releases in the history are all Svelte packages, @stackoverflow/stacks-svelte at 1.0.4 from 2026-09-28, 1.0.3 from 2026-09-18 and 1.0.2 from 2026-09-03, while the last push was on 2026-10-16. The Classic package is not visible in that list, so if you are consuming the CSS and JavaScript build, the tag history is not a good way to track what changed.

The alternative approach is to write your own components against your own tokens. The difference in approach is ownership: your own library gives you a design language that matches your product and a dependency graph you control, at the cost of building the component set, the accessibility work, the visual regression suite and the release pipeline that this repository already contains. Stacks is the cheaper path if its visual language suits you, and the more expensive one if it does not.

The licence is MIT, recorded both in the package.json and in the LICENSE.MD file at the repository root, so there is no fee and no per-product obligation. Read the usage guidelines and the MIGRATION_GUIDE.md file before you commit.

Editorial conclusion

Adopt Stacks if you want the visual language of Stack Overflow's products, with a Classic build for plain CSS and JavaScript and a Svelte build for component work, plus a documented system behind it. Do not adopt it if you need a small dependency, if your product needs its own brand language, or if a multi package monorepo with changesets, a visual regression suite and a migration guide is more structure than your team wants to own. Before installing, read the usage guidelines at stackoverflow.design, check the MIGRATION_GUIDE.md file in the repository, and confirm that the package you need is published, since the tagged releases in the history are the Svelte packages at 1.0.4 from 2026-09-28.

Frequently asked questions

What is Stacks from Stack Overflow?

Stacks is Stack Overflow's design system, the shared foundation of components, styles and guidelines used across Stack Overflow's products. The repository publishes it as npm workspaces covering the Classic CSS and JavaScript implementation, a Svelte implementation and the documentation project.

How do I build the Stacks documentation site locally?

Install dependencies with `npm i` at the repository root, then run `npm start`, which starts the dev server for the docs workspace at http://localhost:5173/. The Svelte package instead has its own documentation site and uses `npm run storybook -w packages/stacks-svelte` for local component work.

What do I need to run the Stacks visual regression tests?

The prerequisites are git lfs, docker and pwsh, plus running `git config diff.lfs.textconv cat` so image diffs work. The suite runs with `npm run test:visual -w packages/stacks-classic` and the files are named with the *.visual.test.ts suffix.

Is the Stacks design system open source?

Yes. The root package.json declares the MIT license and the repository includes a LICENSE.MD file, so there is no fee and no per-product usage obligation, though you still need to read the usage guidelines before adopting the components as your own.

Official sources

  1. License: MIT
  2. Project website
  3. README
  4. Releases
  5. StackExchange/Stacks on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/stackexchange-stacks.svg)](https://hysenlabs.com/projects/stackexchange-stacks)

Was this useful?