Astro components

Reusable components for building service pages and other content. Import these in MDX or Astro files.

PageHero

Full-width hero section with animated background shape. Used at the top of service pages and landing pages.

Import

import PageHero from '../../components/PageHero.astro';

Props

Prop Type Default Description
title string required Main heading text
subtitle string Optional subtitle below the heading
colorScheme string 'fire' Background colour: fire, sunshine, sorbet, gloaming, limestone
shape string 'circle' SVG shape: circle, threecircles, etc.
shapeScale number 1 Visual scale of the shape (1 = 100%, 2 = 200%)
shapeRotation number 0 Initial rotation angle in degrees
shapeSize string '80vw' Orbit container size (affects rotation radius)
shapeTop string '50%' Vertical position of orbit centre
shapeLeft string '50%' Horizontal position of orbit centre
shapeOpacity number 1 Shape opacity (0–1)
shapeOrigin string 'center' Rotation pivot point (CSS transform-origin, e.g. 'center', 'top left', '0 0')
orbitRadius string '10%' Distance from orbit centre. Set '0' to disable drift.
orbitSpeed number 360 Seconds for one full orbit. Set 0 to freeze orbit position.
spinSpeed number 360 Seconds for shape's own rotation. Set 0 to stop spinning.
texture string '/images/ink2.jpg' Path to texture overlay image
textureOpacity number 0.05 Texture opacity (0–1)

Animation behaviour

The shape has two layers of animation:

  • Orbit — The shape drifts around the orbit centre point (shapeTop/shapeLeft), at a distance set by orbitRadius
  • Spin — The shape rotates around its own pivot point (shapeOrigin)

Set speeds to 0 or radius to '0' to disable specific animations for a more static appearance.

Examples

Basic usage

<PageHero 
  title="Essence"
  subtitle="Distilling organisational identity"
  colorScheme="sunshine"
  shape="threecircles"
/>

Positioned shape with custom animation

<PageHero 
  title="Essence"
  subtitle="Distilling organisational identity"
  colorScheme="sunshine"
  shape="threecircles"
  shapeScale={2}
  shapeRotation={10}
  shapeLeft="100%"
  shapeTop="50%"
  orbitRadius="30%"
  spinSpeed={360}
  orbitSpeed={0}
/>

Static shape (no animation)

<PageHero 
  title="About us"
  colorScheme="fire"
  shape="circle"
  orbitRadius="0"
  spinSpeed={0}
  orbitSpeed={0}
/>

Section

Flexible content section component. Supports single column, two-column with image, and numbered layouts.

Import

import Section from '../../components/Section.astro';

Props

Prop Type Default Description
variant 'default' | 'intro' 'default' Section style variant. 'intro' has larger heading and defaults to limestone-dark.
colorScheme ColorScheme 'limestone' Background: limestone, limestone-dark, fire, sorbet, sunshine, gloaming, gloaming-dark
layout 'single' | 'two-column' 'single' Layout mode
image string Image filename from /src/assets/images/ (for two-column)
imageAlt string '' Alt text for the image
imagePosition 'left' | 'right' 'right' Which side the image appears on
number number Large decorative number
borderTop 'solid' | 'paint' | 'torn' Top border decoration style
borderBottom 'solid' | 'paint' | 'torn' Bottom border decoration style

Slots

Slot Description
default Main content (Markdown)
media Custom media content (used if no image prop)

Examples

Simple section

<Section colorScheme="limestone-dark">

## The problem

Traditional brand projects tend to focus on visual identity...

</Section>

Intro section

<Section variant="intro">

## Holistic content-centred solutions

Content is complex, and there are many aspects to planning...

</Section>

The intro variant has larger headings and defaults to limestone-dark. Use for introduction sections after a PageHero.

Two-column with image

<Section layout="two-column" image="onion.png" imageAlt="Onion illustration">

## The solution

By recognising that organisational identity forms through...

</Section>

Numbered section

<Section number={1} colorScheme="gloaming-dark">

## Beyond perception management

Our model isn't just about how an organisation is perceived...

</Section>

Custom media via slot

<Section layout="two-column">

## Heading

Content here...

<video slot="media" src="/videos/demo.mp4" autoplay loop />

</Section>

Decorative borders

<Section borderTop="torn" colorScheme="limestone">

## After the hero

Content with torn paper effect at top...

</Section>

Notes

  • Dark schemes (fire, gloaming, gloaming-dark) automatically get light text
  • Two-column images extend 250% on desktop for dramatic effect
  • Use the media slot for custom media (video, multiple images, etc.)
  • Numbered sections show a large decorative number on the left
  • Border styles: 'solid' (simple line), 'paint' (wavy edge), 'torn' (torn paper effect)

LatestGrid

A reusable “latest items” section used on the homepage. It renders the correct card component based on the type prop.

Import

import LatestGrid from '../../components/LatestGrid.astro';

Usage

<LatestGrid
  title="Latest projects"
  subtitle="Things we've been working on recently."
  items={latestPortfolio}
  type="portfolio"
  viewAllHref="/portfolio"
/>

ServiceCard

Used on the /services index to link to individual services. Typically fed from the services content collection.

Import

import ServiceCard from '../../components/ServiceCard.astro';

Usage

<ServiceCard
  href="/services/strategy"
  heading="Strategy"
  description="Make content ecosystems work better."
  buttonText="Explore"
  icon={service.icon}
/>

PortfolioCard

Card for portfolio/case study listings (used on /portfolio and in “Latest projects”).

Import

import PortfolioCard from '../../components/PortfolioCard.astro';

Usage

<PortfolioCard
  title={item.data.title}
  slug={item.slug}
  featuredImage={item.data.featuredImage}
  excerpt={item.data.excerpt}
  headingLevel="h2"
  serviceKeys={(item.data.services || []).map((service) => service.id)}
/>

ResourceCard

Card for resource listings (used on /resources and in “Latest resources”).

Import

import ResourceCard from '../../components/ResourceCard.astro';

Usage

<ResourceCard
  title={resource.data.title}
  slug={resource.slug}
  heroImage={resource.data.heroImage}
  excerpt={resource.data.excerpt}
  headingLevel="h2"
/>

ThoughtCard

Card for thoughts/blog listings (used on /thoughts and in “Latest thoughts”).

Import

import ThoughtCard from '../../components/ThoughtCard.astro';

Usage

<ThoughtCard
  title={thought.data.title}
  slug={thought.slug}
  heroImage={thought.data.heroImage}
  excerpt={thought.data.excerpt}
  headingLevel="h2"
/>

DeviceScreenshot

Renders a screenshot inside a device frame (monitor/laptop/tablet/phone). Used inside DeviceComposite and elsewhere.

Import

import DeviceScreenshot from '../../components/DeviceScreenshot.astro';

Usage

<DeviceScreenshot device="tablet" screenshot="demo.png" alt="Demo screenshot" />

DeviceComposite

Arranges multiple device screenshots into a composite layout (e.g. monitor + laptop + tablet + phone).

Import

import DeviceComposite from '../../components/DeviceComposite.astro';

Usage

<DeviceComposite
  monitorScreenshot="screenshot-desktop.png"
  laptopScreenshot="screenshot-laptop.png"
  tabletScreenshot="screenshot-tablet.png"
  phoneScreenshot="screenshot-phone.png"
  alt="Product screenshots"
  width="80vw"
/>

Clients

Renders the client logo grid from the clients content collection.

Import

import Clients from '../../components/Clients.astro';

Usage

<Clients />

HowWeCanHelp

Homepage section that lists services from the services content collection in a fixed order.

Import

import HowWeCanHelp from '../../components/HowWeCanHelp.astro';

Usage

<HowWeCanHelp />

QuoteBlock

A full-width quote section with optional decorative borders and background colour token.

Import

import QuoteBlock from '../../components/QuoteBlock.astro';

Usage

<QuoteBlock
  quote="Groundbreaking, strategic, and forward-thinking…"
  attribution="James Wood, former Head of Content, Internet Society"
  background="fire-extra-dark"
  borderBottom="paint"
/>

ProductFeature

A marketing block built on Section + DeviceScreenshot, used to promote products/tools.

Import

import ProductFeature from '../../components/ProductFeature.astro';

Usage

<ProductFeature
  title="Content Health Check"
  content="<p>...</p>"
  buttonText="Get a health check"
  buttonUrl="https://contenthealthcheck.com"
  screenshot="content-health-check-screenshot.png"
  screenshotAlt="Content Health Check tool"
  colorScheme="limestone-dark"
  imagePosition="left"
  backgroundTexture="watercolour"
/>

Subscribe

A full-width newsletter sign-up section with a decorative top border and a device illustration.

Import

import Subscribe from '../../components/Subscribe.astro';

Usage

<Subscribe />

Border

Decorative border used by Section, QuoteBlock, and Subscribe.

Import

import Border from '../../components/Border.astro';

Usage

<Border style="paint" position="top" color="var(--fire)" />

Portfolio case studies

Case studies are stored as Markdown files in the portfolio content collection and rendered with PortfolioLayout and PortfolioCard. This section covers how to add a new case study and tag it with services.

Location

Add or edit files in src/content/portfolio/. Each file becomes a page at /portfolio/<slug>/ and an item on the portfolio index.

Frontmatter

Use this frontmatter shape:

---
title: "Content strategy foundations for Brooke"
subtitle: "Joined-up content strategy foundations for Brooke"
date: 2025-01-17
excerpt: "Short summary used on the portfolio index."
featuredImage: "chang-qing-8oPubUm97Cc-unsplash-400x284.jpg"
services:
  - Essence
  - Strategy
---

## The challenge

Body content here...
  • title and subtitle feed the hero and index card.
  • date is used to sort case studies (newest first).
  • excerpt appears under the title on the index card.
  • featuredImage is the thumbnail on the index grid.
  • services is an array of service names (e.g. Essence, Strategy, System, Product, Know-how).

Images

Place case study thumbnails in src/assets/images/ and reference them by filename via featuredImage. PortfolioCard uses the shared responsive image system (getImage + Image) so new thumbnails automatically benefit from optimisation.

Services and filtering

The services array is used in two places:

  • On /portfolio/ to filter case studies by service (All, Essence, Strategy, System, Product, Know-how).
  • On service pages to surface related case studies, by querying getCollection('portfolio') and filtering where services includes the current service.

A case study can have more than one service. It will appear under every relevant filter, and in multiple "related case studies" lists where appropriate.