A design system cut like a mola: flat layers, hard keylines, revealed bands. React components and design tokens for dense internal tools and AI-native interfaces — admin consoles, knowledge bases, agent run monitors — documented in a standalone Storybook.
- Tokens. One CSS file. Two themes declared once with
light-dark(), three densities on one attribute, zero radius. Every contrast pairing, 100+ of them across both themes, is computed from the CSS and enforced by a test. The tokens are exported to W3C design-token JSON for Figma. - 54 components. Actions, forms, overlays, feedback, navigation, data display and an application shell: 145 exported parts, built on Base UI for behaviour and accessibility, and styled with Tailwind v4. Every one has a docs page in the same order: what it is for and its lifecycle phase, when to use it and what to use instead, examples, the keys it answers to and how it is tested, and related components.
- An AI interface layer: 12 more components. Streaming text, message threads, a composer whose send button becomes stop, tool-call cards with human approval, change review with diffs and a decision that needs a reason to say no, long-running agent run timelines with live elapsed time, run failure and recovery that keeps partial output, reasoning disclosure, citations that preview their source on hover, focus or tap, token budgets, and confidence stated in words rather than decimals.
- Patterns. Whole Cayuco screens composed only from the system, each with its decisions written down: a settings page with a save bar and unsaved-changes guard, a list and detail view that collapses to one column on a phone, a filtered table of agent runs, every empty state of a list, a destructive confirm whose request can fail, and an agent handing a task to a person. Each pattern page says when to use it, what it is built from (read from its imports), and where its empty, loading, error and no-permission states are; each component page lists the patterns it is used in.
- A working demo. In the agent console, ask a question and a simulated agent plans, calls two tools and streams a cited answer, with the run timeline and token usage updating beside it.
A mola is the hand-sewn textile of the Guna people of Panama. The word names both the panels and the blouse that Guna women make and wear. Two or more layers of cotton are basted together, a design is cut through the upper layers, and every cut edge is turned under and hemmed by hand to reveal the colour beneath. The technique is passed down from generation to generation, and a single panel can take months to make.
Molas sewn by Guna women. Photograph by Maria Molino on Unsplash.
A mola is more than decoration. In the early twentieth century Panama's government tried to stop Guna women wearing their traditional dress. Making and wearing molas became an act of resistance, and the Guna Revolution of 1925 won the Guna autonomy over their land and their culture. Today the mola is protected under Panama's Law 20 of 2000 as collective intellectual property of the Guna people.
Mola UI is not made by Guna people and does not speak for them. It carries the name out of respect: to its author, the mola is one of the most authentic expressions of Panamanian culture, and a craft that deserves to be honoured, not borrowed lightly. The name also fits what this project tries to be. A mola carries a people's identity into everyday life. Each one is made by hand and is unique, yet every one is recognisably part of the same tradition, because it comes from a shared method. A design system does a humbler version of the same thing: it carries an identity and the knowledge of how to make things well into every product, so each screen is its own while plainly belonging to the same family.
What that respect means in practice:
- We borrow the method, not the motifs. Mola UI takes the grammar of the technique: stacked layers, hard cut edges, the revealed band. It reproduces no Guna designs, symbols or patterns in its interface. The photograph above is there only to show where the name comes from, credited to the women who make molas and to the photographer.
- We claim no rights over the mola. It belongs to the Guna people.
- We name the source wherever the name appears.
- If you want a mola, buy one from Guna artisans, so the craft supports the people who keep it alive.
The mola's method is the system's grammar —
- Every interactive edge is an ink keyline, drawn with
box-shadowso hover can grow a revealed band outward without moving a single neighbour. - Relleno, the filler slits of a mola, is the divider, the empty state, and — moving — the indeterminate "working" state of a long-running step.
- Three typefaces, three speakers: Archivo (on its width axis) for the system, Alegreya for prose a person or a model says to you, Martian Mono for machine literals. A transcript can be scanned for what it said versus what it did from the type alone.
- State is never colour alone: every status is a square mark, a word and a tone.
It began as the design system of mustdopanama.com, an editorial
travel guide, and was carried into product software — the same identity, re-argued for
information density, all-day dark mode and the states AI work produces. The decisions are written
down in docs/adr/.
npm install @demogar/mola-ui @base-ui/react \
@fontsource-variable/archivo @fontsource-variable/alegreya @fontsource-variable/martian-monoimport '@fontsource-variable/archivo/wdth.css'
import '@fontsource-variable/alegreya/wght.css'
import '@fontsource-variable/martian-mono/wdth.css'
import '@demogar/mola-ui/styles.css'
import { ToolCall } from '@demogar/mola-ui'
<main data-theme="dark" data-density="compact">
<ToolCall
name="update_feature_flag"
status="waiting"
args={{ flag: 'help_panel_v2', percent: 100 }}
approval={{
reason: 'Changes a live flag for every new workspace.',
onApprove: approve,
onDeny: deny,
}}
/>
</main>@base-ui/react is a peer dependency: install it beside the package, as above, so your app and
Mola share one copy (Mola re-exports Base UI's DirectionProvider, which only works with one).
The package is ESM only; require() works too, on Node 22.12 or later.
Mount the providers once, at the root: DirectionProvider (keyboard direction for right-to-left),
ToastProvider (useToast() throws without it) and, optionally, TooltipProvider. Getting
started has the app root, a theme switcher with no flash on load, and the Next.js layout; each of
those code blocks is compiled against the packed package in CI.
styles.css includes Tailwind's preflight and styles body, which is what a new app wants. Adding
Mola to an existing app? Import @demogar/mola-ui/components.css instead: the same components,
with the reset scoped to them, so your page keeps its own styles.
Already on Tailwind v4? Import @demogar/mola-ui/tailwind.css into your own build instead. It closes
Tailwind's default palette, radii, shadows, easings and other scales Mola replaces (see Getting started). Not on React?
@demogar/mola-ui/tokens.css is plain custom properties — both themes and all densities work anywhere.
Designing in Figma? tokens/mola.tokens.json is every token in the W3C Design Tokens format (2025.10).
Using VS Code? Copy node_modules/@demogar/mola-ui/snippets/mola-ui.code-snippets into your project's .vscode/ folder and
type mola- in a .tsx file: one snippet per component, generated from its stories.
Browser support: Chrome 123, Edge 123, Firefox 128 and Safari 17.5, or later. Every theme colour
is a light-dark() pair, which those versions are the first to support, and the stylesheet is built
for them with no fallbacks for older browsers.
Mola UI documents itself for coding agents as well as for people, from the same source:
llms.txt, also served from the Storybook root: the index, in the llms.txt format. It points to one file per topic,llms-components.txt,llms-tokens.txt,llms-patterns.txtandllms-rules.txt(the design rules alone, numbered ascheck_codecites them), and tollms-full.txtfor an agent that reads one file.- A Markdown version of every docs page, at
md/<page id>.mdon the Storybook site (the Button page ismd/components-actions-button--overview.md). Each component page has a Copy for LLM button that copies it. docs/ai/components.json: every export with its props, types, defaults, doc comments, cva variants, usage guidance and story links.skills/mola-ui/SKILL.md: a Claude Code skill that teaches an agent the rules, which component to pick and how to use the tokens. Copy the folder into.claude/skills/in your project.mola-ui-mcp, an MCP server that ships in the package. It is read-only and answers from the generated manifest for the version you have installed. Its tools arelist_components,get_component,search,get_tokens,get_rules,get_patternandcheck_code.check_codecloses the loop: an agent passes it the screen it just wrote and gets back each place it breaks a design rule (a border on a control, a radius, a faded disabled state, a hex, a colour that is not a token or a token outside its scope,pl-/left-, a spinner, a hand-rolled dialog, another UI library, an export that does not exist), with the line, the rule and the fix. The check is deterministic, and CI runs it over the library's own source, every story and the docs pages, so it cannot drift from what the components do and the examples you copy meet the same bar. A deliberate exception takes// check_code: allow rule N — the reason; without a reason it is an error.@demogar/mola-ui/eslint, the samecheck_coderules as an ESLint plugin, for your editor and CI. See Lint with the design rules.
In Claude Code, from your project:
claude mcp add mola-ui -- npx -y --package @demogar/mola-ui mola-ui-mcpAdd --scope project to write it to .mcp.json and share it with your team. Any other MCP client
(Claude Desktop, Cursor, VS Code, Windsurf) takes the same command in its JSON config:
{
"mcpServers": {
"mola-ui": {
"command": "npx",
"args": ["-y", "--package", "@demogar/mola-ui", "mola-ui-mcp"]
}
}
}npx uses the copy in your project's node_modules when there is one, so the answers match the
version you build with. The SDK is bundled into the bin, so the server adds no dependency to the
library. The Getting started
page has the same steps.
The package ships the check_code rules as an ESLint plugin (ESLint 9 or later, flat config). It
is the same checker the MCP tool runs, not a second copy, and it reads the manifest of the version
you have installed:
// eslint.config.js
import mola from '@demogar/mola-ui/eslint'
export default [
// …your other configs, with a parser for JSX or TSX (espree, typescript-eslint)
mola.configs.recommended,
]mola-ui/design-rules reports what breaks a rule in every context, as an error;
mola-ui/design-advice reports what is very probably wrong but cannot be proved from the code,
as a warning. Each message starts with the rule's number and ends with the fix. The rules read
the source text, so any parser works, eslint-mdx included. A deliberate exception takes the same
// check_code: allow rule N — the reason as the MCP tool, or an eslint-disable comment. The
plugin imports nothing at run time but Node's builtins, so it adds no dependency to the library.
The manifest, the text files and the Markdown pages are generated by npm run manifest from the TypeScript source
and the stories, and CI fails if they are stale, so an agent never builds from a prop list that
no longer compiles.
npm run check # lint · typecheck · test · deps:audit · tokens:check · manifest:check · evidence:check · build · api:check · size · build-storybookCI runs that list, plus three browser jobs in parallel: the audit, visual regression and consumer smoke tests below. The audit and visual regression are each split across four runners, so the whole run takes about three minutes.
- The contrast contract (
src/tokens/contract.test.ts) resolves every token in both themes —light-dark(),var(), OKLabcolor-mix()— and asserts each promised pairing. It caught a real dark-theme failure during the build (muted ink on the gold wash, 4.00:1) before any screen did. - No hex outside
tokens.css, enforced by a test. - Every story is a test: all 303 stories render through the real Storybook config and pass axe
in the unit suite;
scripts/audit.mjsre-runs axe with colour contrast in a real browser in both themes, checks every story for horizontal overflow at 390px and reflow at 320px (no text clipped or painted over, nothing scrolling sideways without the scroll-edge cue, the composed screens at spacious density too). CI runs it on every pull request against the static build, over every docs page as well as every story, and fails on any finding. - Visual regression. Every story is screenshotted in both themes, and each component's first story in compact density, right-to-left and forced colours (each pattern at spacious density too), against baselines rendered on Linux with the bundled fonts, frozen time and animations off.
- Bundle budgets. size-limit holds the whole library to
170 kB, a tree-shaken
Button+Fieldimport to 15 kB, andstyles.cssandcomponents.cssto 17.5 kB each (minified and brotli-compressed, dependencies included, React excluded). - The public API is reviewed. API Extractor writes every export
and its type signature to
etc/mola-ui.api.md; a change to the API that is not in that file fails CI, so every API change shows up in review as a diff. - Consumers are tested, not assumed. The packed tarball is installed into a Vite app on
styles.css, a Vite app running its own Tailwind v4 ontailwind.css, an existing app oncomponents.csswhose own page must stay unstyled, and a Next.js App Router app rendering the components from a server component, inside the root layout Getting started documents. Each is built and checked in a browser. - Docs can't drift from the code. The design-token JSON and the agent manifest are generated and checked in CI; the component counts in this README are checked against the source; and a test resolves every link into Storybook, so a renamed story fails the build instead of a reader.
- What isn't tested is said. Each component page's testing status is generated from the stories and the test files, and says plainly that no screen reader has been tried by hand yet. The open limitations are on the Known gaps page.
cn()knows the token vocabulary, with a test that fails if a colour token would be read as a size — the silent class-dropping bug this prevents shipped in the system's first home. The merger is Mola's own: tailwind-merge's rules for the families the components write, at half the bytes, and a test compares the two on every pair of utilities.
src/styles/ tokens.css (the only file with hex) · theme.css (Tailwind bridge) · cloth.css (the mola utilities)
src/components/ one folder per component: component, stories, tests, barrel
src/components/ai/ the AI interface layer
src/patterns/ whole screens composed from the system (Storybook only, not in the package)
src/tokens/ colour math + the contrast contract
src/docs/ Storybook docs: introduction, principles, foundations, usage guidance, versioning
tokens/ generated DTCG tokens for Figma
docs/ai/ generated component manifest, tokens and Markdown pages for agents
mcp/ the mola-ui-mcp server (bundled into dist/mcp by vite.mcp.config.ts)
eslint/ the @demogar/mola-ui/eslint plugin over mcp/check.ts (bundled into dist/eslint by vite.eslint.config.ts)
docs/accessibility/ generated testing status for each component page
docs/adr/ architecture decision records
etc/ the API report (generated by npm run api)
test/visual/ visual regression tests and their Linux baselines
test/consumers/ fixture apps that install the packed package
codemods/ scripts that migrate consumer code across breaking changes (index on the Codemods page)
snippets/ generated VS Code snippets, one per component page
skills/mola-ui/ the Claude Code skill
Mola UI's identity, tokens and components are its own. How it is built, run and presented draws on Dan Mall's Design That Scales (Rosenfeld Media, 2023). From the book it takes these practices: grow the system out of real product work rather than designing it in the abstract; keep it a connected, versioned dependency rather than code to copy; show what it builds before its parts; and admit a component only when three use cases need it. The References page in Storybook maps each idea to where it applies, and lists the standards the system follows: WCAG 2.2, the W3C Design Tokens format and Conventional Commits.
Read CONTRIBUTING.md for the gates, the rules a review holds you to, and how releases are cut. Everyone taking part follows the Code of Conduct. Report security issues privately, as described in SECURITY.md. Changes are listed in the changelog. What is planned, what is under consideration and what is not planned is on the Roadmap; propose something new with the proposal template.
Designed, architected and directed by Demóstenes García. Built with Claude Code.
The mola is the textile art of the Guna people; this project borrows its method, not its motifs. Typefaces: Archivo (Omnibus-Type), Alegreya (Juan Pablo del Peral, Huerta Tipográfica), Martian Mono (Evil Martians) — all under the SIL Open Font License.







0 comments
log in to comment.