Accueil
Blog

How I built a trilingual design system in one evening

LAUSANNE, Switzerland —

One night, one backported module, three brands. Here’s the story.


The starting point

April 22nd, 6 PM. I receive a screenshot — a tidy folder with 25 HTML pages (colors, buttons, cards, forms…) alongside a 468-line colors_and_type.css, 52 self-hosted .woff2 fonts and a SKILL.md manifest for AI agents.

It’s the ACiD Studio design system, extracted from production code. A brand playbook for the designers, developers and AIs that work on the project.

A technical file, not a showcase. Question: what if we put it online?

The bet

A public design system is a serious signal. Stripe, Vercel, Shopify publish theirs — because it’s part of their sales pitch. “See, we have a real system, not a copy-pasted theme.”

For a one-person agency with a CHF 2,999 entry ticket, showing acidstudio.ch/design-system/ flips the perception immediately: “they’re structured like a real company.”

Constraint: ship it in one evening, without breaking the homepage, without bloating the site, in the three languages (FR / EN / ES) of the site.

The architecture

Phase 1 — Static publishing

Instead of a separate subdomain or dedicated repo, I copied the design system folder straight into frontend/public/design-system/. Astro automatically serves public/ at root → acidstudio.ch/design-system/buttons.html works without config.

Win: zero DNS, zero SSL, zero extra deployment pipeline.

Phase 2 — Astro landing page

An Astro page src/pages/design-system.astro that:

  • Reuses the site Layout (navbar + footer unchanged)
  • Displays a giant “CODE & BOLDNESS” hero in the brand typography
  • Shows the 25 previews in a grid, each in a scaled 50% iframe
  • Closes with a dark CTA featuring the site’s signature acid radial orb

No static screenshots, no image build — the original HTML previews are loaded as-is, just miniaturized. A change in any preview appears automatically in the grid.

Phase 3 — Internationalization

Three versions: /design-system/ (FR), /en/design-system/ (EN), /es/design-system/ (ES).

Pattern used — the same as the project’s BlogListing.astro:

  1. A shared DesignSystemPage.astro component with a lang prop
  2. Three 10-line wrappers in src/pages/, src/pages/en/, src/pages/es/
  3. All strings translated via a labels object keyed by language

Translated hero: CODE & AUDACE (FR) / CODE & BOLDNESS (EN) / CODE & AUDACIA (ES).

The small technical hells

The unreadable TOC

First render: black background, white Outfit text, 14px, weight 600. On macOS Retina, letters appear blurry and distorted — an anti-aliasing halo creates a bizarre script effect.

Diagnosis: Outfit (display font) is optimized for large sizes. At 14px, it’s less readable than Inter (UI font) with the same weight.

Fix: font swap + text-rendering: optimizeLegibility + generous letter-spacing (0.02em) + horizontal padding bumped to 22px.

Clashing CSS tokens

The project uses shadcn/ui which defines --color-accent in HSL. My component also used --color-accent, but with the acid value #c8f135. Silent conflict — shadcn won.

Fix: module-specific namespace. All my tokens become --ds-* with chained fallbacks:

background: var(--ds-accent, var(--acid, #c8f135));

Three fallback levels: project override, native ACiD token, hardcoded value. The project can override at any level without touching the component.

The backport — from one-shot to reusable module

When a feature deserves to live in 2+ projects, it moves out into acid-starter — the template repo that centralizes all reusable modules.

I created modules/design-system/v1.0.0 with:

  • The shared DesignSystemPage.astro component
  • The three Astro wrappers [lang]/design-system.astro
  • A design-system.config.json with every configurable field
  • A README covering install and configuration

Configurable: brand name, accent text (AUDACE vs BOLDNESS vs AUDACIA), active languages (FR-only or trilingual), CTA hrefs, preview list, logo.

Generic by design: zero hardcoded colors, everything flows through CSS variables. The accent becomes amber for a restaurant, magenta for a therapy brand, acid for the mother agency — automatically.

The outcome

In 4 hours:

  • acidstudio.ch/design-system/ → trilingual, 25 components, stats, commercial CTA
  • design-system v1.0.0 module in acid-starter
  • Deployments on two client projects tuned to their brand: alaclasse-restaurant.ch/design-system/ (gold + Playfair/Cormorant) and magnetismetherapeutique.ch/design-system/ (violet + DM Serif/Raleway in dark theme)

Commercial deliverable: every future ACiD Studio client gets their public design system to share. Not “like Stripe’s”. Theirs, with their colors and vocabulary.

Takeaways

  1. Publishing a technical showcase remains the cheapest marketing tool for an agency: the work is already done, you just need to package it.
  2. Leveraging existing project conventions (BlogListing.astro pattern, CSS tokens, import aliases) saved me 50% of the time. The fewer decisions, the faster I code.
  3. The moment a one-shot becomes reusable is precise — if 2+ projects will want it, head to acid-starter from v1.0.

The ACiD Studio design system is here: acidstudio.ch/en/design-system.

If you’re starting a web project and want your own, get in touch.

FR EN ES