Most of what makes a theme yours takes a few lines in two places: src/styles/theme.css for the look and src/config/ for the words and links. Run npm run dev while you edit and the browser updates as you save.
Change the brand color
The brand color is used for primary buttons, links, highlights, and soft tinted backgrounds. It’s five lines in src/styles/theme.css:
@theme {
--color-brand: oklch(72% 0.14 220); /* main color */
--color-brand-hover: oklch(50% 0.14 220); /* on hover */
--color-brand-active: oklch(45% 0.13 220); /* when pressed */
--color-brand-soft: oklch(95% 0.04 220); /* pale tint */
--color-brand-fg: oklch(16% 0.02 260); /* text on brand */
}
Colors are written in OKLCH, which takes three numbers: lightness (0–100%), chroma or intensity (0 is gray, around 0.2 is vivid), and hue (0–360 around the color wheel). The easy way to recolor is to change only the last number in all four brand lines: 25 is red, 145 green, 220 blue, 290 violet. The hover, pressed, and soft versions stay in step automatically.
Prefer hex? Any CSS color works in theme.css, so --color-brand: #e11d48; is fine. Pick your own darker hex for -hover and -active, and a very pale one for -soft. oklch.com converts between the two.
Then check --color-brand-fg. It’s the text color on brand buttons, so use a dark value on a light brand color and a light value (oklch(98% 0.01 0) or #fff) on a dark one.
Change the accent colors
Most themes also use secondary and tertiary colors for badges, highlights, and supporting buttons. They follow the same five-line pattern as the brand color, so recolor them the same way.
Change the background and text colors
@theme {
/* Surfaces, from the page background to borders */
--color-bg: oklch(99% 0.002 260);
--color-surface: oklch(97% 0.004 260);
--color-elevated: oklch(95% 0.006 260);
--color-line: oklch(90% 0.008 260);
--color-line-soft: oklch(93% 0.006 260);
/* Text, from lightest to darkest */
--color-muted: oklch(53% 0.02 260);
--color-soft: oklch(42% 0.025 260);
--color-text: oklch(28% 0.02 260);
--color-strong: oklch(16% 0.02 260);
}
For a warmer, cream-colored page, raise the chroma a touch and move the hue to around 80: --color-bg: oklch(98% 0.012 80);. Keep each surface step only slightly darker than the one before so cards and borders still read.
Keep enough contrast between --color-text and --color-bg. If body text gets hard to read on your phone in daylight, darken the text tokens.
Change the fonts
Fonts are installed from Fontsource, so they’re served from your own site. To switch to a different font, such as Inter:
-
Install it:
npm install @fontsource-variable/inter -
In
src/styles/theme.css, replace the font import at the top:@import "@fontsource-variable/inter/wght.css"; -
In
src/config/identity.ts, set the font stacks.displayis used for headings andsansfor everything else:fonts: { sans: '"Inter Variable", ui-sans-serif, system-ui, sans-serif', display: '"Inter Variable", ui-sans-serif, system-ui, sans-serif', mono: 'ui-monospace, "SF Mono", Menlo, monospace', }, -
In
src/components/global/Seo.astro, point the font preload at the new file so text doesn’t flash on load:import fontWoff2 from "@fontsource-variable/inter/files/inter-latin-wght-normal.woff2?url";Rename the variable where it’s used further down in the file. The font’s Fontsource page lists the exact file names.
To use a second font for headings only, install both, import both, and give display the other font’s name.
Round or square the corners
Buttons, form fields, and anything using rounded-md share one token in theme.css:
--radius-md: 0.5rem; /* default */
--radius-md: 0; /* square */
--radius-md: 999px; /* pill-shaped buttons */
Change the site name and logo
Set name in src/config/identity.ts. It’s the name in the navbar, browser tabs, search results, and link previews.
The navbar shows the name as text. To use an image logo instead:
-
Save your logo as an SVG in
public/images/, for examplepublic/images/logo.svg. -
Open your theme’s navbar in
src/blocks/navbar/and find the home link near the top. It contains{siteConfig.name}. -
Replace
{siteConfig.name}with the image, keeping the text for screen readers:<img src="/images/logo.svg" alt={siteConfig.name} width="120" height="32" />
Set width and height to your logo’s proportions so the page doesn’t shift while it loads.
Edit the navigation
The menu lives under navigation in src/config/identity.ts:
navigation: {
sticky: true, // stays at the top while scrolling
dropdownTrigger: "hover", // or "click"
links: [
{ label: "Work", href: "/#work" },
{ label: "Blog", href: "/blog/" },
{
label: "Company", // a dropdown
children: [
{ label: "About", href: "/about/" },
{ label: "Contact", href: "/contact/" },
],
},
],
cta: { label: "Book a call", href: "/contact/", size: "md" },
},
Add, remove, or reorder links in the list. A link with children becomes a dropdown. Change the button on the right with cta.
Edit the footer
The footer reads from a few places:
| What | Where |
|---|---|
| Tagline, copyright line | footer.tagline and footer.copyright in identity.ts |
| Link columns | footer.groups in identity.ts. Each group’s label is the column heading |
| Terms, Privacy, and other small links | footer.legal in identity.ts |
| Email address | author.email in identity.ts |
| Social icons | seo.sameAs in src/config/integrations.ts. Add your profile URLs and the matching icons appear |
The privacy, terms, and accessibility pages are plain Markdown in src/pages/. Edit the text there.
Change the words on a page
Headings, intros, and button labels for the built-in pages are in src/config/pages.ts. Copy for the theme’s sections (the hero, services, FAQ, and so on) is in src/config/blocks.ts, one entry per section. Change the text there rather than in the page files, so updates to the theme don’t overwrite your edits. See Configuration for the full list.
Replace the favicon
Replace public/favicon.svg with your own icon. If it isn’t an SVG, save it in public/, then set favicon in identity.ts to its path, for example "/favicon.png".
The color of the browser bar on phones is seo.themeColor in src/config/integrations.ts. Set it to your background or brand color as a hex value.
Replace the social image
The social image is the picture that appears when someone shares your link. The build draws it fresh each time from scripts/generate-og.mjs, along with the home-screen icon (apple-touch-icon.png). That means replacing public/og.png by hand won’t last.
- To keep the generated card, edit the title, subtitle, and colors in
scripts/generate-og.mjs. - To use your own design, delete the
"prebuild"line inpackage.json, then replacepublic/og.png(1200 × 630 pixels) andpublic/apple-touch-icon.png(180 × 180).
To point the whole site at a differently named file, set seo.ogImage in src/config/integrations.ts.
Check your changes
Before you publish, run:
npm run build
If it finishes, the site is ready to publish. It also warns about pages with missing or duplicate descriptions and images without alt text. Then deploy as usual.
If you’d rather describe the change than make it, the theme includes instructions that let an AI coding agent make these edits the same way. See Working with AI agents.