Skip to content
BrandCloud

Campaign landing page: the source

The whole page in 133 lines of Astro. Every section is a free component; the copy is passed in as plain objects.

Back to the live page or set up the kit.

src/pages/recipes/campaign/index.astro

---
/* Recipe: campaign landing page. Tidewell Physio is a made-up business. Free components only. */
import "@fontsource-variable/schibsted-grotesk";
import "../../../styles/recipe.css";
import Base from "../../../layouts/Base.astro";
import RecipeBar from "../../../components/RecipeBar.astro";
import Navbar from "@brandcloud/astro/components/Navbar.astro";
import Hero from "@brandcloud/astro/components/Hero.astro";
import Section from "@brandcloud/astro/components/Section.astro";
import Heading from "@brandcloud/astro/components/Heading.astro";
import Steps from "@brandcloud/astro/components/Steps.astro";
import Faq from "@brandcloud/astro/components/Faq.astro";
import EnquiryFormShell from "@brandcloud/astro/components/EnquiryFormShell.astro";
import CtaBand from "@brandcloud/astro/components/CtaBand.astro";
import Footer from "@brandcloud/astro/components/Footer.astro";
import Icon from "@brandcloud/astro/components/Icon.astro";

const business = "Tidewell Physio";
---
<Base title={`Recipe: campaign landing page (${business}, fictional)`}
  description="A campaign landing page recipe built from free components: a six-week return-to-running programme for a made-up physio clinic." bare brand="harbour">
  <Fragment slot="top">
    <RecipeBar slug="campaign" />
    <Navbar brandName={business} links={[{ label: "The programme", href: "#programme" }, { label: "How it works", href: "#how" }, { label: "Questions", href: "#questions" }]}
      cta={{ label: "Book a place", href: "#book" }} />
  </Fragment>

  <Hero
    variant="field"
    copy={{
      heading: "Back to running by summer, without the knee pain coming back",
      lede: "A six-week return-to-run programme for runners coming back from injury, led by a physiotherapist in Kingsport. Small groups, one plan, and a test run at the end.",
      primary: { label: "Book a place", href: "#book" },
      secondary: { label: "How it works", href: "#how" },
      note: "Spring group starts Monday 1 March 2027.",
    }}
    facts={[
      { label: "Starts", value: "Monday 1 March 2027" },
      { label: "Length", value: "6 weeks, two sessions a week" },
      { label: "Group size", value: "Up to 8 runners" },
      { label: "Price", value: "£180 for the whole programme" },
    ]}
  />

  <Section id="programme" aria-labelledby="who-title">
    <div class="r-sechead" data-split>
      <Heading as="h2" id="who-title">For runners who keep stopping at the same point</Heading>
      <p class="r-lead">You have been told you can run again. Your body has other ideas after twenty minutes. This programme rebuilds the load in steps you can measure.</p>
    </div>
    <div class="r-two">
      <ul class="r-ticks">
        <li><Icon name="check" /><div><strong>Knee, shin or Achilles pain that returns</strong><span>Usually around the same distance or time on your feet.</span></div></li>
        <li><Icon name="check" /><div><strong>Back after a break of three months or more</strong><span>Injury, illness, a new baby or simply life.</span></div></li>
        <li><Icon name="check" /><div><strong>Training for a spring 10K or half</strong><span>And you want to reach the start line in one piece.</span></div></li>
      </ul>
      <div class="r-panel">
        <h3 class="r-panel-title">What the £180 covers</h3>
        <ul class="r-ticks">
          <li><Icon name="check" /><span>A one-to-one assessment in week one</span></li>
          <li><Icon name="check" /><span>Twelve group sessions: strength, then running drills</span></li>
          <li><Icon name="check" /><span>A written plan for the days between sessions</span></li>
          <li><Icon name="check" /><span>A timed test run in week six, with a plan for what comes next</span></li>
        </ul>
      </div>
    </div>
  </Section>

  <Section tone="muted" id="how" aria-labelledby="how-title">
    <Steps
      heading="Six weeks, three stages"
      intro="Each stage starts when you pass the one before, so nobody is pushed past what their legs can take."
      variant="rail"
      steps={[
        { title: "Assess", text: "A one-hour assessment finds what gives way first and sets your starting load.", meta: "Week 1" },
        { title: "Build", text: "Strength work twice a week, with short run intervals that grow each session.", meta: "Weeks 2 to 5" },
        { title: "Test", text: "A timed run on the seafront, then a plan for the months after.", meta: "Week 6" },
      ]}
    />
  </Section>

  <Section id="questions" aria-labelledby="campaign-faq-title">
    <Faq
      id="campaign-faq"
      heading="Before you book"
      items={[
        { question: "Do I need a referral?", answer: "No. Book a place and the assessment in week one decides whether the group is right for you. If it is not, you get your money back." },
        { question: "What if I miss a session?", answer: "Each week has a second slot, so you can swap. Your plan also covers what to do at home." },
        { question: "Can I claim it on health insurance?", answer: "Some insurers cover physiotherapy assessments. We give you a receipt with everything they usually ask for." },
        { question: "Where is it?", answer: "Sessions are at the clinic and on the seafront path nearby, depending on the week." },
      ]}
    />
  </Section>

  <Section tone="raised" id="book" aria-label="Book a place">
    <div class="r-two">
      <div class="s-stack">
        <Heading as="h2">Book a place in the spring group</Heading>
        <p class="r-lead">Tell us a little about your running and we will reply within two working days to arrange your assessment.</p>
        <p class="r-fine">This is a recipe preview. The form does not send anything.</p>
      </div>
      <EnquiryFormShell
        mode="preview"
        previewMessage="Preview only: nothing was sent. On a live page this form posts to your own endpoint."
        layout="panel"
        id="campaign-book"
        fields={["name", "email", "phone", "message"]}
        required={["name", "email"]}
        labels={{ message: "What stops your running at the moment?", submit: "Request a place" }}
        interest={{ label: "Which group?", options: ["Spring group, from 1 March 2027", "A later group"], placeholder: "Choose a group" }}
        consent={{ label: "Email me when future groups open. Optional, and separate from this booking." }}
      />
    </div>
  </Section>

  <CtaBand
    copy={{
      heading: "Not sure the group is right for you?",
      body: "Book the assessment on its own first. If you join the programme afterwards, its cost comes off the price.",
      primary: { label: "Book a place", href: "#book" },
      secondary: { label: "Read the questions", href: "#questions" },
    }}
  />

  <Fragment slot="bottom">
    <Footer variant="simple" brandName={business} links={[{ label: "The programme", href: "#programme" }, { label: "How it works", href: "#how" }, { label: "Book", href: "#book" }]}
      legal={["Tidewell Physio is a made-up business for this recipe.", "Example page built with free components."]} />
  </Fragment>
</Base>

<style>
  .r-panel-title { font-size: 1.375rem; margin-block-end: 1.25rem; }
</style>