Skip to content
BrandCloud

Offer 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/offer/index.astro

---
/* Recipe: offer page. Bramble and Rye is a made-up business. Free components only. */
import "@fontsource-variable/source-serif-4";
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 Button from "@brandcloud/astro/components/Button.astro";
import Steps from "@brandcloud/astro/components/Steps.astro";
import Faq from "@brandcloud/astro/components/Faq.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 = "Bramble and Rye";
const flavours = [
  { name: "Lemon and elderflower", note: "Sharp curd, soft sponge" },
  { name: "Dark chocolate and cherry", note: "Rich, not too sweet" },
  { name: "Carrot and walnut", note: "Spiced, with cream cheese" },
  { name: "Raspberry and white chocolate", note: "A summer favourite" },
  { name: "Salted caramel", note: "Brown butter sponge" },
  { name: "Vanilla and strawberry", note: "The classic, done properly" },
];
---
<Base title={`Recipe: offer page (${business}, fictional)`} description="An offer page recipe built from free components: a wedding cake tasting box from a made-up bakery." bare
  brand="orchard">
  <Fragment slot="top">
    <RecipeBar slug="offer" />
    <Navbar brandName={business} links={[{ label: "The box", href: "#box" }, { label: "How it works", href: "#how" }, { label: "Terms", href: "#terms" }]}
      cta={{ label: "Order a box", href: "#order" }} />
  </Fragment>

  <Hero
    variant="editorial"
    copy={{
      heading: "Taste six wedding cake flavours at home before you choose",
      lede: "A tasting box with six slices, a card for your notes and a booked call with the baker. Order by Monday, taste it at the weekend.",
      primary: { label: "Order a tasting box, £24", href: "#order" },
      secondary: { label: "See what is inside", href: "#box" },
      note: "The £24 comes off your cake if you book it within 60 days.",
    }}
  />

  <Section tone="muted" id="box" aria-labelledby="box-title">
    <div class="r-two">
      <div class="s-stack">
        <Heading as="h2" id="box-title">What is in the box</Heading>
        <p class="r-lead">Six generous slices, each labelled, packed to travel and good for three days in the fridge.</p>
        <ul class="r-ticks o-flavours">
          {flavours.map((f) => <li><Icon name="check" /><div><strong>{f.name}</strong><span>{f.note}</span></div></li>)}
        </ul>
      </div>
      <div class="r-panel" id="order">
        <p class="o-label">Wedding cake tasting box</p>
        <p class="r-price">£24</p>
        <p class="r-price-note">Delivered across Wessex on Thursdays, or collect from the bakery.</p>
        <ul class="r-ticks">
          <li><Icon name="check" /><span>Six labelled slices for two people</span></li>
          <li><Icon name="check" /><span>A tasting card to note what you liked</span></li>
          <li><Icon name="check" /><span>A 20-minute call with the baker to plan the cake</span></li>
        </ul>
        <div class="o-actions">
          <Button size="lg" block href="#order">Order for this Thursday</Button>
        </div>
        <p class="r-fine">Order by midnight on Monday for Thursday delivery. Recipe preview: this button does not take payment.</p>
      </div>
    </div>
  </Section>

  <Section id="how" aria-labelledby="offer-how-title">
    <Steps
      id="offer-how"
      heading="From the box to a booked cake"
      variant="list"
      steps={[
        { title: "Order by Monday", text: "Choose delivery or collection. You get a confirmation email straight away.", meta: "Takes two minutes" },
        { title: "Taste at the weekend", text: "The box arrives on Thursday. Taste together and fill in the card.", meta: "Keeps for three days" },
        { title: "Plan it on a call", text: "Talk through flavours, size and design with the baker. You get a written quote afterwards.", meta: "20 minutes" },
        { title: "Book your cake", text: "Book within 60 days and the £24 is taken off the price.", meta: "Credited in full" },
      ]}
    />
  </Section>

  <Section tone="raised" id="terms" aria-labelledby="terms-title">
    <div class="r-sechead" data-split>
      <Heading as="h2" id="terms-title">The terms in plain words</Heading>
      <p class="r-lead">No small print hidden in an email later. This is all of it.</p>
    </div>
    <ul class="r-rows">
      <li><h3>Credit</h3><p>The £24 comes off any wedding cake booked within 60 days of your tasting.</p><span class="r-from">£24 back</span></li>
      <li><h3>Allergies</h3><p>Every slice is labelled with its allergens. Gluten-free versions of four flavours are available on request.</p><span class="r-from">Ask first</span></li>
      <li><h3>Cancelling</h3><p>Cancel before Tuesday and you pay nothing. After that the box is already being baked.</p><span class="r-from">Until Tuesday</span></li>
    </ul>
  </Section>

  <Section aria-labelledby="offer-faq-title">
    <Faq
      id="offer-faq"
      heading="Questions about the box"
      variant="stacked"
      items={[
        { question: "Can we choose different flavours?", answer: "Yes. Swap up to two of the six for anything on the full menu when you order." },
        { question: "Is it enough for two people?", answer: "Each slice is cut to share between two, with some left for a second taste." },
        { question: "Do you make cakes for small weddings?", answer: "Yes, from two tiers for about forty guests." },
      ]}
    />
  </Section>

  <CtaBand
    variant="card"
    copy={{
      heading: "Taste first, decide after",
      body: "Order a box this week and plan your cake with the baker who will make it.",
      primary: { label: "Order a tasting box, £24", href: "#order" },
      secondary: { label: "Read the terms", href: "#terms" },
    }}
  />

  <Fragment slot="bottom">
    <Footer variant="simple" tone="muted" brandName={business} links={[{ label: "The box", href: "#box" }, { label: "Terms", href: "#terms" }, { label: "Order", href: "#order" }]}
      legal={["Bramble and Rye is a made-up business for this recipe.", "Example page built with free components."]} />
  </Fragment>
</Base>

<style>
  .o-label { font-weight: 650; margin-block-end: 0.75rem; }
  .o-actions { margin-block-start: 1.5rem; }
  .o-flavours { margin-block-start: 1.5rem; }
</style>