Skip to content

Making it look like your brand

The look comes from a small set of tokens. Change a token and every page, component and state follows — you rarely need to touch a component.

Run npm run dev and open http://localhost:4321/style-guide. It shows the colours, text styles, buttons, form fields, cards and every other component with its name. When you want to know what a change will affect, look there.

src/design-system/theme.css:

@theme {
--color-ink: #101010; /* text, buttons, dark surfaces */
--color-canvas: #f6f6f6; /* page background */
--color-line: #d9d9d9; /* dividers, menu hover */
--color-muted: #818181; /* secondary text, icons */
--color-accent: #fc5000; /* accent */
--color-star: #fdca49; /* rating stars */
--color-danger: #ff2244; /* form errors */
}

Each name becomes a Tailwind class: bg-ink, text-muted, border-line. Swap the hex values for your own palette and the whole site changes. Keep enough contrast between --color-ink and --color-canvas — dark text on a light background, at least 4.5:1, or the site becomes hard to read.

Inter is loaded through Astro’s Fonts API in astro.config.mjs:

fonts: [
{
provider: fontProviders.google(),
name: "Inter",
cssVariable: "--font-inter",
weights: ["100 900"],
styles: ["normal"],
subsets: ["latin"],
fallbacks: ["sans-serif"],
},
],

Change name to another Google font and keep cssVariable as it is — the rest of the site uses that variable. Astro downloads the files at build time and serves them from your own domain, so nothing is requested from Google while someone reads your site. For a font you have licensed yourself, use the local provider as described in Astro’s fonts guide; the variable name stays the same.

If a font has no variable version, list the weights you use (weights: [400, 500, 700]) instead of the range.

src/design-system/tokens/text.ts holds the sizes, weights and line heights, named after the design:

h01, h02, h2, h3, h4, h5, h6
hugeParagraph, largeParagraph, paragraph, smallParagraph
button, menu

Each is a set of Tailwind classes with the phone size first and the tablet (md:) and desktop (lg:) sizes after: h2: "text-[32px] md:text-[36px] lg:text-[42px] leading-[1.2] font-medium". Change the numbers here rather than in the components, and headings stay consistent across the site.

Use them as class={text.h2} or combine: class={cn(text.h6, "text-muted")}.

Three sizes, set in theme.css:

Width Tailwind prefix
Phone below 810 px (none)
Tablet 810–1199 px md:
Desktop 1200 px and up lg:

src/design-system/tokens/motion.ts holds the springs and the reveal used by menus, accordions, sliders and hover states; the behaviour itself is in src/design-system/scripts/ (one small file per interaction: accordion.ts, slideshow.ts, cursor.ts, parallax.ts, …). Lower the stiffness for a softer feel, raise the damping to settle faster. Everything respects the visitor’s “reduce motion” setting.

These are Tailwind classes on the components (rounded-2xl, px-5, gap-10). Tailwind’s scale is 4 px per step, so p-5 is 20 px. Change them where you see them; the style guide shows the result immediately.

src/design-system/components/ — buttons, form fields, cards, sliders, the cursor, the icons. Its README explains the folders and how the pieces fit together. The sections that make up a page are one level up, in src/components/sections/, and are listed in Pages and sections.

The SVG files are in public/icons/ (Phosphor Icons plus a few drawn for Nitip) and src/design-system/components/icons/icons.ts lists them by name. To add one, drop my-icon.svg next to the others, add "my-icon": { dark: "my-icon.svg" } to the map, and use <Icon name="my-icon" />. A light file is the white version; when only one file exists, the other tone is produced with a CSS filter.

The custom cursor follows the pointer on desktop and turns into a label on cards (“View”, “Read”). It is in src/design-system/components/cursor/. To remove it, delete <Cursor /> from src/layouts/Layout.astro; nothing else depends on it.