A design system generated from the dot.
The kolam is not decoration. It is a rule set: a lattice of dots, a fixed loop radius, and — in the looped form this system draws — a line that must never break. Pulli takes those rules literally and derives an entire interface language from them — spacing, geometry, motion, and a pattern engine that emits assets instead of storing them. Why this tradition, and what its mathematics actually says.
What it is
Three things, in one repository, with no build step and no dependencies.
A token model
Three layers — palette, derived primitives, semantic roles. Every geometric value is a function of the pitch. Change one number and the interface re-derives.
A pattern engine
A deterministic kolam generator. Patterns are committed as five numbers, not as binary assets, and are guaranteed continuous and closed.
A component library
Twelve components whose entire box model is expressible in lattice terms, each with states, anatomy, and an accessibility contract.
The seed
Two numbers generate the geometry. Everything else is arithmetic.
Dots sit on a square lattice at pitch P. The line never touches a dot — it curves around it at radius r. For the loops around two adjacent dots to meet without a gap or an overlap, they must meet at the midpoint of the lattice edge between them. That happens at exactly one value:
r = P / 2 P = 8px → r = 4px spacing = nP → 8, 16, 24, 32, 48, 64 radius = n·r → 2, 4, 8, 16 stroke = r/4, r/2, r → 1, 2, 4 type = 16 × √2ⁿ → 11, 16, 23, 32, 45, 64
That one constraint locks the spacing scale and the radius scale to each other permanently. It is why a rounded corner in this system is never approximately right — it is the same curve the pattern engine draws.
current seed · P = 8px · r = 4px
--p on the document root. Every page of this site — padding, corner radii, control heights, switch travel, the token tables — re-derives as you drag it. That is the difference between a system that has a grid and a system made of one.Quick start
Adopt in layers. Each one works without the next.
1 · Tokens only
Link the token layer and consume semantic roles. Nothing else changes.
<link rel="stylesheet" href="assets/tokens.css">
.my-card {
padding: var(--space-inset-lg);
border-radius: var(--radius-panel);
background: var(--color-surface);
border: var(--border-hairline) solid var(--color-border);
}
2 · Pattern engine only
Use the generator for brand assets without adopting the tokens.
<script src="assets/kolam.js"></script> // deterministic — same seed, same kolam, forever const { svg, meta } = Kolam.generate({ dots: 9, symmetry: 'd4', crossing: 0.2, seed: 1729 }); document.querySelector('.hero').innerHTML = svg;
3 · Full system
Tokens, components, and declarative pattern rendering.
<link rel="stylesheet" href="assets/tokens.css">
<link rel="stylesheet" href="assets/system.css">
<script src="assets/kolam.js" defer></script>
<script src="assets/site.js" defer></script>
<button class="btn btn-primary">Draw</button>
<div data-kolam='{"dots":5,"seed":42}'></div>
Map of the system
Read in order if you are adopting it; jump directly if you are looking something up.
Origins
Why a kolam was chosen to carry a design system, the contested chronology, the mathematics behind it, and the threshold traditions elsewhere that arrived at the same constraints.
02Principles
Four rules taken intact from kolam practice, what each one rules out, and what wins when two of them conflict.
03Lattice
The derivation itself: spacing, sizing, layout grid, breakpoints, density tiers, elevation, and where derivation breaks.
04The Line
The half the system originally left out: wrap-or-pass as a selection primitive, enclosure by looping instead of by box, and an honest re-run of the deletion test that forced the correction.
05Tokens
The three-layer model, the full reference, naming grammar, JSON export, and theming rules.
06Generator
Tile set, algorithm, symmetry groups, the boundary-closure proof, API reference, and asset recipes.
07Components
Twelve components with anatomy, states, token specs, and do/don't guidance.
08Motion
The three kolam moves with live curve plots, duration as distance, choreography, the animatable-property rule, and the draw-on spec.
09Accessibility
Measured contrast matrix, focus and motion policy, the pattern-density limits, and cultural handling.
10Governance
Versioning, the derivation-proof review rule, deprecation lifecycle, adoption tiers, and credit.
11Showcase
Five surfaces built from these tokens — dashboard, mobile app, marketing site, web application, and email & print where there are no variables at all. With the forks that themed them and the eight things they broke.
12Readiness
Honest enterprise assessment: what is production-grade, the 46-of-58 component inventory and what still blocks deployment, domain fit for fintech and healthcare, and a phased roadmap with real durations.
13Enterprise subset
A conservative profile for regulated contexts — expressive layer off, conventional controls restored, forced-colors support and a measured AAA high-contrast theme.
14Data grid
The blocker, built. Ten thousand rows with forty in the DOM — sort, filter, resize, frozen columns, bulk select, keyboard navigation and the ARIA that virtualisation breaks.
15Library
Forty-six of fifty-eight components with the reference inventory published in full — and a plain statement of why raising a component count barely moves readiness.
Is this right for you
A system that cannot say who it is wrong for is marketing, not documentation.
Products with a genuine connection to South Indian context. Brands that want a generative identity rather than a fixed one. Teams who want token discipline enforced by arithmetic rather than by code review. Anyone who needs a pattern language that scales to infinite unique assets from one function.
Products with no relationship to the tradition, where kolam will read as texture borrowed for novelty. Dense data applications where the expressive layer has nowhere to live. Teams that need a component library today — this is a foundation with twelve components, not fifty.