Design system · v0.1
Quiet by default.
Violet when
it matters.
Inkwell is the system behind this portfolio: lilac paper by day, ink by night, and a single violet that only speaks when it has something to say. Every colour, curve and motion on sanjeevkujur.dev starts here.
- 70 Violet
- 20 Cream
- 10 Peach
Try the toggle in the corner. This whole page is the specimen.
Ten chapters.
- 01PrinciplesThe beliefs behind every pixel.Design decisionsCommit historyRead →
- 02ColorSeventy percent violet. Twenty cream. Ten peach.CSS variablescolor-mix()Tailwind @themeRead →
- 03TypographyFive voices, each with exactly one job.next/fontFrauncesSynonymJetBrains MonoRead →
- 04Shape & surfacePaper, ink, and the space between them.Tailwind @theme radiiHairline bordersLayered surfacesRead →
- 05Layout & spacingFew breakpoints, few widths, one rhythm.Tailwind breakpointsmax-widthGuttersRead →
- 06MotionNothing moves without a reason.Framer MotionCSS transitionsLenisRead →
- 07ComponentsSmall pieces, loosely held together.shadcn/uiRadix UIcvaRead →
- 08AccessibilityMeasured contrast, and where it falls short.WCAG 2 contrastprefers-reduced-motionFocusRead →
- 09ThemingOne attribute flips the whole world.data-themelocalStorageInline boot scriptRead →
- 10Use itHand the system to the next person, or agent.DESIGN.mdDesign tokensCSS variablesRead →
How it is built
Three layers. One source of truth.
Primitives
Raw palette values. The only place a hex code is allowed to live.
Semantic
What the interface actually uses: background, primary, border. Each theme points these at primitives.
Component
Narrow tokens for specific widgets, built from the layer above. Change one, nothing else moves.
What it is made from
Every chapter shows its workings.
Nothing here is a screenshot. Each specimen is the real component running on the real tokens, next to the code and the reasoning that produced it.
- Next.js 16
- App Router. This page is a route in the portfolio, served on its own subdomain by a host rewrite.
- Tailwind CSS v4
- Tokens are exposed through @theme inline, so utilities like bg-primary read live CSS variables.
- CSS custom properties
- Three layers (primitive, semantic, component) with a single data-theme attribute for dark.
- shadcn/ui + Radix
- new-york style primitives, composed with class-variance-authority and tailwind-merge.
- Framer Motion, CSS, Lenis
- Framer Motion for entrances and state, plain CSS for hover and loaders, Lenis for smooth scroll.
- next/font
- Fraunces, Synonym, Amulya, Bespoke Stencil and JetBrains Mono, self-hosted and swapped in.
Passing it on
A system is only as good as its next reader.
Sooner or later someone opens the project who has never seen it. Often it is a coding assistant. It cannot guess that violet is rare, or that hex lives in one place. So the system is written down, in one file, and three small commands carry that file into any project.
1
Write it down once
Start from the Inkwell file: tokens, rules and what never to do, in a single DESIGN.md at the root of the project.
npx @sanjeevsaniel/inkwell-skill template2
Teach the assistant
Install the skill so a coding assistant reads that file before it touches a colour, a size or a curve.
npx @sanjeevsaniel/inkwell-skill init3
Keep it honest
Check the file against the real CSS and type scale. When the two drift apart, it says exactly where, and fails.
npx @sanjeevsaniel/inkwell-skill check
All three come from one package, @sanjeevsaniel/inkwell-skill. The template is Inkwell's own file, so swap in your tokens before you rely on it.