MacroMath
Website

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

TokenHex
--brand#FF5A1F
--brand-strong#F03E0E
--brand-soft#FF8A4C

Macro colours — the same four used by the rings in the app:

MacroHex
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: reduce and simply shows the static layout when motion is reduced.
  • The reveal animations use IntersectionObserver and 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):

CommandAction
npm installInstall dependencies.
npm run devDev server at http://localhost:4321.
npm run buildBuild the static site to ./dist.
npm run previewServe 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.

On this page