Lyra Astro documentation
Colours, fonts and photos
Re-colour Lyra for your brand, change the heading font, and replace the placeholder images with your own photos.
How the colours work
Lyra’s colours come in three layers, all in src/styles/tokens/:
| File | What’s in it |
|---|---|
colors.css |
The colour scales: clay (terracotta), leaf (green), sun (yellow), sky (blue), berry (pink), sand (warm greys) and red, each from 50 (lightest) to 950 (darkest). |
theme.css |
What each colour is for: --brand, --accent, --highlight, the cause colours, text, surfaces and lines, each with a light-mode and a dark-mode value. Blocks only use these names. |
scale.css |
Type sizes, spacing, corners, shadows and page width. |
Every text and background pair meets the WCAG AA contrast standard in both light and dark mode.
Changing your brand colour
The quickest way is to point --brand at a different scale in theme.css. For a green brand with a terracotta accent, swap the two:
--brand: light-dark(var(--leaf-700), var(--leaf-400));
--accent: light-dark(var(--clay-600), var(--clay-400));
Change the -hover, -ink and -soft lines under each one the same way.
Your own colour scale
To match an exact brand colour, generate new scales:
- Open
scripts/palette.mjs. Each scale at the top has ahue(0–360, the colour’s position on the colour wheel) and achroma(how vivid it is, around 0.12–0.16). - Change the
clayhue to your brand’s. Terracotta is 42, red about 25, pink about 0, purple about 300, blue about 250, teal about 190 and green about 145. - Run
node scripts/palette.mjs. It prints the newcolors.cssand checks the contrast of every pair the theme uses. - Paste the output into
src/styles/tokens/colors.css.
Any online “hex to OKLCH” converter tells you your colour’s hue.
Section tones
The eight tones you can give a block (cream, blush, mint, sky, sand, brand, night and default) are at the bottom of theme.css. brand and night are dark: everything inside them, including buttons and cards, switches to its dark-mode colours.
Light and dark mode
The site follows each visitor’s system setting, and the moon button in the header lets them choose. Their choice is remembered on their device.
Heading font
Headings use Bricolage Grotesque, a warm, friendly sans-serif, through Astro’s built-in Fonts API. It’s one 41 KB file served from your own site, with no requests to Google, and a matched fallback stops text from jumping while it loads. Body text uses each device’s system font, which costs nothing to load.
To use a different font, install it from Fontsource:
npm install @fontsource-variable/fraunces
Then, in astro.config.mjs, change name and point src at the new font’s file in node_modules/@fontsource-variable/<font>/files/, usually the one ending latin-wght-normal.woff2. Fontsource lists other files for other alphabets, such as latin-ext or cyrillic.
Logo
The header and footer show a heart icon beside your organisation’s name. To use your own logo, replace the logo-mark icon and the name after it in src/components/Header.astro (two places: the header and the phone menu) and src/components/Footer.astro with an image, for example <img src="/logo.svg" alt="Your charity" width="140" height="40" />, and put the file in public/. Replace public/favicon.svg with your own icon too.
Photos
Photos live in src/assets/images/, and pages and content files refer to them by file name:
image: water-well.jpg
imageAlt: A girl washing her face at a village tap
Lyra resizes every photo when you build, converts it to AVIF and WebP, and gives each visitor only the size their screen needs, so you can upload large, good-quality JPGs straight from your camera or phone.
The placeholder images
The demo uses free-licence photos whose licences don’t allow passing them on, so the download replaces them with coloured placeholders. They’re drawn by scripts/placeholders.mjs before every npm run dev and npm run build, but only for file names that are missing: your own photos are never touched.
Replace them in either of two ways:
- Same names. Save your photo as
src/assets/images/water-well.jpgand it’s used everywhere the placeholder was. - New names. Add
river-project.jpgand changeimage:in the pages that should use it.
Once you’ve replaced them all, you can delete the list in scripts/placeholders.mjs.
Good photo sizes
| Where | Shape | At least |
|---|---|---|
| Hero (split variant) | Portrait, about 4:5 | 1200 × 1500 |
| Hero (overlay), page headers | Landscape | 2000 × 1200 |
| Causes, campaigns, stories, events | Landscape, 3:2 | 1600 × 1070 |
| Team photos | Square | 600 × 600 |
Share image (shareImage) |
Landscape | 1200 × 630 |
Choosing the crop
Page headers show a wide strip of the photo, centred. If heads are cut off, add imagePosition to the page header block or the cause, event or story file: top, center, bottom, or two percentages such as 50% 30% (across, then down).
Describing photos
Write a short imageAlt for every photo, describing what’s in it (“Children carrying water containers past the new well”). Screen readers read it aloud, and search engines use it. Describe the scene, and think about the dignity of the people shown.
Video
The video block plays a YouTube or Vimeo link, or your own file in public/, such as /media/film.mp4. Nothing is loaded from YouTube or Vimeo until the visitor clicks play. The demo clip isn’t included in the download; the block shows its poster photo until you add your own, and the build prints a reminder.
Page width and corners
--wrap in scale.css sets the content width (1200px), and --radius-s to --radius-xl set how rounded cards, buttons and photos are.