Design & content
The design tokens, theming, internationalization and accessibility behind the website.
The website deliberately has no UI framework — the look comes from a small set of CSS design tokens, and the content from a single translation dictionary. This keeps the bundle tiny and the visual identity identical to the app.
Design system
Tokens live in src/styles/global.css as CSS custom properties. The brand is the same
MacroMath orange used across the app and this documentation.
Brand palette
| Token | Hex |
|---|---|
--brand | #FF5A1F |
--brand-strong | #F03E0E |
--brand-soft | #FF8A4C |
Macro colours — the same four used by the rings in the app:
| Macro | Hex |
|---|---|
| Protein | #EF4444 |
| Carbs | #F5B70A |
| Fat | #22C55E |
| Water | #3B82F6 |
Beyond colour, the tokens cover typography (Poppins), border radii
(--r-sm … --r-full), shadows (--shadow-sm/md/lg/brand) and motion
(--ease plus --t-fast/base/slow). Because everything references tokens, the light
and dark themes are just two sets of values swapped on the root element.
Theming
The theme (light / dark) is toggled from the navbar and persisted in
localStorage. It is applied before paint by an inline script in the <head>, so
there is no flash of the wrong theme on load. All colours are token-based, so a theme
switch is a single attribute change on <html>.
Internationalization
The site is trilingual — Portuguese, English and Spanish. It does not use routed
locales; instead every translatable element carries a data-i18n="key" attribute
(data-i18n-html for rich content like the legal pages), and a small script swaps the
text from a single dictionary:
- The dictionary is
src/i18n/dict.js— each key maps to{ pt, en, es }. - The language is auto-detected from the browser and saved to
localStorage. - Switching language re-runs the substitution client-side; no page reload.
// src/i18n/dict.js — one entry, three locales
'hero.cta1': { pt: 'Descarregar grátis', en: 'Download free', es: 'Descargar gratis' },<!-- used in any component -->
<span data-i18n="hero.cta1">Download free</span>The dictionary also holds the full legal text (privacy policy and terms) and every string in the account dashboard — see Accounts & billing.
Accessibility & motion
- Semantic markup and a visible focus model throughout.
- Every scroll-driven effect (the sticky Features crossfade, the horizontal scenes,
reveal animations) is gated on
prefers-reduced-motion: reduceand simply shows the static layout when motion is reduced. - The reveal animations use
IntersectionObserverand re-trigger on scroll in both directions.
SEO & social
Layout.astro sets per-page <title> and description, Open Graph and Twitter meta,
and theme-color. The Open Graph share images are pre-generated by the
scripts/make-og.mjs build script.
Development
The website is a standard Astro project (Node ≥ 22.12):
| Command | Action |
|---|---|
npm install | Install dependencies. |
npm run dev | Dev server at http://localhost:4321. |
npm run build | Build the static site to ./dist. |
npm run preview | Serve the production build locally. |
Deploy is trivial because the output is 100% static — Vercel, Netlify, Cloudflare Pages
or GitHub Pages all work with zero or minimal config. The only server-side pieces are
the api/ billing functions, covered in Accounts & billing.