Design — Titen Astro
The look comes from a small set of tokens. Change a token and every page, component and state follows, so you rarely need to touch a component.
See everything first
Section titled “See everything first”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.

Colours
Section titled “Colours”src/design-system/theme.css:
@theme { --color-ink: #121212; /* text, dark buttons, the footer and dark sections */ --color-background: #f5f1e5; /* the page, and the header once you scroll */ --color-sand: #e0dcd7; /* the Projects band on Home, the Beginnings section on About */ --color-accent: #c36036; /* button hovers, award names, accent buttons */ --color-orange: #e8481c; /* the current page in the menu, the rating star */ --color-danger: #e8481c; /* form errors */}Each name becomes a Tailwind class: bg-ink, text-accent, bg-sand. Swap the hex values for your own palette and
the whole site changes. Keep enough contrast between text and its background (at least 4.5:1), or the site becomes hard
to read.
Faded colours are opacity modifiers on the same colour: text-ink/80 (labels), bg-ink/30 (divider lines), bg-white/10
(lines in the footer). They follow the palette when you change the colour.
The header’s colours (transparent at the top of Home, About and project pages, the page background once you scroll)
are in src/components/site/header-state.ts.
The Titen wordmark is drawn as an SVG path in src/design-system/components/brand/Logo.astro, in the current text
colour. That’s why it is black on the page and white on the dark Home, About and project covers and in the footer. To
use your own:
- As an SVG: paste your logo’s path data into
pathand set theviewBoxto your artwork’s size. - As an image file: replace the
<svg>with an<img>of your file.
The header shows it at 62 × 25 px (49 × 20 px on phones) and the footer at 74 × 30 px. Change the class sizes in
src/components/site/Header.astro and Footer.astro to fit your proportions. Its label for screen readers is
site.name.
The browser icons are public/icon.svg and public/apple-icon.png.
The template loads Plus Jakarta Sans with the Astro Fonts API, in astro.config.mjs:
fonts: [ { provider: fontProviders.google(), name: "Plus Jakarta Sans", cssVariable: "--font-jakarta", weights: ["400", "500", "600", "700"], … }, { provider: fontProviders.google(), name: "Inter", cssVariable: "--font-inter", weights: ["500"], … },],To use another Google font, change name and keep cssVariable: name: "Manrope". For a font you have licensed
yourself, use fontProviders.local() with the files in src/assets/fonts/ (see the
Astro fonts guide). Astro downloads the font when the site builds and
serves it from your own domain, so there is no request to Google at runtime.
The second font, Inter, is only for the search panel, as on the original design. To use the site font there instead,
remove font-[family-name:var(--font-inter)] from src/design-system/components/navigation/SearchDialog.astro, and the
Inter entry and its <Font> line in src/layouts/Layout.astro.
Text styles
Section titled “Text styles”src/design-system/tokens/text.ts holds the sizes, weights and line heights, named after the design:
display, h1, h2, h3, h4, h5, h6paragraph, small, tinymenu, buttonEach is a set of Tailwind classes. The headings have the phone size first and the tablet (md:) and desktop (lg:)
sizes after, for example h2: "text-[30px] md:text-4xl lg:text-[42px] leading-[1.2] font-medium". Paragraphs, menu and
button labels are the same at every size; menu and button labels are uppercase with a little letter spacing. 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-white")}.
Breakpoints
Section titled “Breakpoints”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: |
Content is at most 1440 px wide. The side padding is 16 px on phones, 30 px on tablets and 50 px on desktops, and
sections are 60 / 80 / 100 px apart (src/design-system/components/layout/section.ts).
Motion
Section titled “Motion”src/design-system/tokens/motion.ts holds the transitions. The scripts in src/design-system/scripts/ play them with
Motion:
| Token | Used for |
|---|---|
spring |
Arrows turning, menu and link underlines, card hovers, the accordion, the phone menu |
springButton |
Button colours |
springSlide |
The slideshows |
appearWord, appearLine, appearBlock, appearLate |
The appear effects: headings word by word, lines rising, blocks rising when they scroll into view |
Lower a spring’s duration for a snappier feel, or raise bounce for a livelier one.
| Effect | Where to change it |
|---|---|
| The Home testimonials change every 4 seconds | interval={4} on <Slideshow> in src/components/sections/HomeHeroSection.astro |
| Blocks rise in as you scroll | <Reveal>. Replace it with a plain <div> (same class) where you don’t want it. |
| Headings appear word by word | <WordsAppear>; a plain heading with the same class shows at once |
| The header is transparent at the top of Home, About and project pages | hasCover() in src/components/site/header-state.ts; add or remove routes there |
Every animation respects the visitor’s “reduce motion” setting.
Rounded corners, spacing, shadows
Section titled “Rounded corners, spacing, shadows”Titen is square: buttons, form fields and photos have no rounded corners. The exceptions are the testimonial cards
(10 px), the search panel (16 px) and the round icons. Spacing is Tailwind classes on the components (px-5, gap-12).
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.
Components
Section titled “Components”src/design-system/components/ holds the buttons, cards, form fields, the accordion, the service list, the slideshow,
the search panel, the videos and the icons. Their behaviour is in src/design-system/scripts/. The
README lists every component next to the design it comes from, and every script with
what it does. The sections that make up a page are one level up, in src/components/sections/, and are listed in
Pages and sections.
The icons are Phosphor shapes stored as path data in
src/design-system/components/icons/paths.ts, and <Icon name="check" /> draws one in the current text colour. To add
one:
-
Open the icon on phosphoricons.com and copy the SVG.
-
Take the
d="…"of its<path>. -
Add a line:
"my-icon": "M128,24A104,104,0,1,0,…",
Then use <Icon name="my-icon" class="size-5" />. Paths use a 256 × 256 grid, which is what Phosphor exports.