# Sections

## Sections

**Files:** `src/content/sections/english/` (and `french/`), page content files · **Skill level:** Beginner to edit, light code to add or move

A **section** is one full-width block of a page: the hero, the services, the reviews, the FAQ. Each section is two files that share a name:

```text
src/layouts/components/sections/ReviewsSection.astro   ← how it looks (component)
src/content/sections/english/reviews-section.md        ← what it says (content)
src/content/sections/french/reviews-section.md
```

[How Homio Works](/homio/getting-started/how-homio-works/) explains the idea in full. This page is the practical reference: every section, its file, and the block name a page uses to change it.

### Change A Section Everywhere
Edit its file in `src/content/sections/english/` and the file with the same name in `french/`. The comments in each file list its options and the allowed values.

Section files have no schema, so `npm run astro-check` doesn't catch a wrong value in them, such as a misspelled `layout`. Copy values from the comments, then check the page in the browser.

### Hide A Section
- **Everywhere:** set `enable: false` at the top of its section file.
- **On one page:** add its block to that page's content file with `enable: false`:

  ```yaml
  questionsSection:
    enable: false
  ```

### Change A Section On One Page
Add a **named block** to the page's content file with only the keys you want to change. Homio merges the block over the section file:

- **Objects merge key by key.** A block only needs the fields it changes.
- **Lists replace the whole list.** Repeat every item you want to keep.
- **An empty string (`""`) clears a value**, for example `image: ""` hides a photo.

```yaml
# src/content/pricing/english/-index.md
questionsSection:
  title: "Questions about prices" # replaces the title only
  options:
    layout: "grid" # the other options keep their section defaults
```

Copy block names exactly from the catalog below (they are the keys of `sectionsSchema` in `src/sections.schema.ts`). A block with a wrong name, for example `faqSection:` instead of `questionsSection:`, is ignored without an error.

In collections with a schema, `npm run astro-check` checks the values inside each block before the merge. Most fields are optional there, with these exceptions:

- `contactSection` needs `title`, `description`, `imagePosition`, and `form`. Copy them from `src/content/sections/english/contact-section.md`.
- A nested object keeps its own required fields: a `button` needs a `label`.
- `ctaSection`, `contactSection`, and `clientsSection` are **off unless the block says `enable: true`**. A `ctaSection:` block that changes only the title hides the call to action band on that page. Start these blocks with `enable: true`.

The `contact` collection (`src/content/contact/`) has no schema, so blocks in the contact page file are not checked. Open `/contact/` after each change.

<Aside type="caution">
  A block only works on a page whose route reads it. The table [Blocks Each Page
  Reads](#blocks-each-page-reads) lists them. A block for a section the page
  doesn't show does nothing.
</Aside>

### Blocks Each Page Reads
Every page also reads `ctaSection` (the call to action band above the footer) and, for inner pages, `pageHeader`. Paths are for English; French uses the same file names in `french/`.

| Page | Page file (`src/content/`) | Blocks the page reads |
| --- | --- | --- |
| Main homepage `/` | `homepage/english/-index.md` | `heroSection`, `stepsSection`, `whyUsSection`, `metricsSection`, `servicesSection`, `reviewsSection`, `contactSection`, `questionsSection`, `relatedPostsSection` |
| Cleaning `/home-cleaning/` | `homepage/english/home-cleaning.md` | `heroSection`, `whyUsSection`, `servicesSection`, `plansSection`, `stepsSection`, `featureGridSection`, `reviewsSection`, `bookingSection`, `questionsSection`, `relatedPostsSection`, `areasSection` |
| Commercial `/home-commercial/` | `homepage/english/home-commercial.md` | `heroSection`, `servicesSection`, `whyUsSection`, `featureGridSection`, `reviewsSection`, `teamGridSection`, `relatedPostsSection`, `contactSection` |
| Handyman `/home-handyman/` | `homepage/english/home-handyman.md` | `heroSection`, `trustStrip`, `whyUsSection`, `servicesSection`, `metricsSection`, `featureGridSection`, `stepsSection`, `reviewsSection`, `beforeAfterSection`, `questionsSection`, `relatedPostsSection` |
| Services `/services/` | `services/english/-index.md` | `servicesSection`, `includedSection`, `addOnsSection`, `industriesStrip`, `questionsSection` |
| Service page | `services/english/<service>.md` (plus `detail:` and `templates:` in `-index.md`) | `serviceHeroSection`, `includedSection`, `notCoveredSection`, `addOnsSection`, `estimateSection`, `stepsSection`, `reviewsSection`, `beforeAfterSection`, `questionsSection`, `servicesSection`, `industriesStrip`, `clientsSection`, `contactSection` |
| Pricing `/pricing/` | `pricing/english/-index.md` | `plansSection`, `ratesSection` (the rate sheet), `includedSection`, `addOnsSection`, `estimateSection`, `questionsSection` |
| Book `/book/` | `pages/english/book.md` | `bookingSection`, `trustStrip`, `questionsSection` |
| How it works `/how-it-works/` | `pages/english/how-it-works.md` | `stepsSection`, `trustStrip`, `includedSection`, `valuesSection`, `questionsSection` |
| Areas `/areas/` | `areas/english/-index.md` | `areasSection`, `reviewsSection`, `questionsSection` |
| Area page | `areas/english/<area>.md` | `servicesSection`, `reviewsSection`, `areasSection`, `beforeAfterSection`, `questionsSection` |
| Industries `/industries/` | `industries/english/-index.md` | `contactSection` (the walkthrough form) |
| Industry page | `industries/english/<industry>.md` (plus `detail:` in `-index.md`) | `includedSection`, `servicesSection`, `stepsSection`, `beforeAfterSection`, `questionsSection`, `contactSection` |
| Reviews `/reviews/` | `pages/english/reviews.md` | `reviewsSection` |
| Projects `/projects/` | `projects/english/-index.md` | `beforeAfterSection`, `reviewsSection` |
| About `/about/` | `about-us/english/-index.md` | `aboutHeroSection`, `storySection`, `stepsSection`, `valuesSection`, `teamGridSection`, `careersBandSection` |
| Team `/team/` | `team/english/-index.md` | `teamGridSection`, `careersBandSection` |
| Careers `/careers/` | `careers/english/-index.md` | `valuesSection`, `openRolesSection`, `stepsSection`, `questionsSection` |
| Guarantee `/guarantee/` | `guarantee/english/-index.md` | `trustStrip`, `guaranteeClaimSection`, `stepsSection`, `complianceSection`, `questionsSection` |
| FAQ `/faq/` | `faq/english/-index.md` | `questionsSection` |
| Contact `/contact/` | `contact/english/-index.md` | `contactSection`, `contactOptionsSection`, `questionsSection` |
| Gift cards `/gift-cards/` | `pages/english/gift-cards.md` | `giftCards`, `stepsSection`, `contactSection`, `questionsSection` |
| Referral `/referral/` | `pages/english/referral.md` | `referral`, `stepsSection`, `contactSection`, `questionsSection` |
| Blog `/blog/` | `blog/english/-index.md` | `blogListSection`, `newsletterSection` |
| Text pages (legal) | `pages/english/<page>.md` | `contentPage` (a notice and a summary ticket above the text) |

The section order on each page is set in its route file in `src/pages/[...lang]/`. The demo homepages list their sections in order near the top of the route, for example in `src/pages/[...lang]/home-cleaning.astro`. See [Homepages](/homio/customization/homepages/).

### Section Catalog
Every section, its content file in `src/content/sections/<language>/`, and the block name a page uses to override it. Layout values are in [Section Layouts](/homio/customization/section-layouts/).

#### Homepage And Marketing
| Section (component) | Content file | Page block | Used on |
| --- | --- | --- | --- |
| Hero (`HeroSection`) | `hero-section.md` | `heroSection` | All four homepages |
| Trust strip (`TrustStripSection`) | `trust-strip.md` | `trustStrip` | Handyman homepage, `/book/`, `/how-it-works/`, `/guarantee/`. Its rating also feeds the hero and reviews |
| Services (`ServicesSection`) | `services-section.md` | `servicesSection` | All four homepages, `/services/`, service, area, and industry pages |
| Steps (`StepsSection`) | `steps-section.md` | `stepsSection` | Main, cleaning, and handyman homepages, about, how it works, guarantee, careers, gift cards, referral, service and industry pages |
| Why us (`WhyUsSection`) | `why-us-section.md` | `whyUsSection` | All four homepages |
| Numbers (`MetricsSection`) | `metrics-section.md` | `metricsSection` | Main homepage (inside the why-us block), handyman homepage. Also the numbers on the booking `card` layout |
| Feature rows (`FeatureGridSection`) | `feature-grid-section.md` | `featureGridSection` | Cleaning, commercial, and handyman homepages |
| Reviews (`ReviewsSection`) | `reviews-section.md` | `reviewsSection` | All four homepages, `/reviews/`, `/areas/`, `/projects/`, service and area pages |
| Before/after (`BeforeAfterSection`) | `before-after-section.md` | `beforeAfterSection` | Handyman homepage, `/projects/`, service, area, industry, and project pages |
| Team (`TeamGridSection`) | `team-grid-section.md` | `teamGridSection` | `/team/`, `/about/`, commercial homepage |
| Logos (`Clients`) | `clients.md` | `clientsSection` | Service pages with the `commercial` template (off unless the block turns it on). Also the logo row of the reviews `spotlight` layout |
| Industries strip (`IndustriesStrip` widget) | none: labels in `industries` of `src/i18n/en.json` | `industriesStrip` | `/services/`, service pages |
| Blog teaser (`RelatedPostsSection`) | `related-posts-section.md` | `relatedPostsSection` | All four homepages, under each blog post |
| FAQ (`QuestionsSection`) | `questions-section.md` | `questionsSection` | Most pages: three homepages, FAQ, contact, book, pricing, services, areas, and more |
| Call to action (`CallToAction`) | `call-to-action.md` | `ctaSection` | Above the footer, on pages that turn it on. It ships with `enable: false` in the section file, because the default footer already ends with a call to action |

#### Prices, Booking, And Services
| Section (component) | Content file | Page block | Used on |
| --- | --- | --- | --- |
| Instant estimate (`EstimateSection`) | `estimate-section.md` | `estimateSection` | `/pricing/`, service pages |
| Plans (`PlansSection`) | `plans-section.md` | `plansSection` (and `ratesSection` on `/pricing/`) | `/pricing/`, cleaning homepage |
| Add-ons (`AddOnsSection`) | `add-ons-section.md` | `addOnsSection` | `/pricing/`, `/services/`, service pages |
| What's included (`IncludedSection`) | `included-section.md` | `includedSection` | `/pricing/`, `/services/`, `/how-it-works/`, service and industry pages |
| Booking request (`BookingSection`) | `booking-section.md` | `bookingSection` | `/book/`, cleaning homepage (`card` layout) |
| Service page hero (`ServiceHeroSection`) | `service-hero-section.md` | `serviceHeroSection` | Service pages |
| Not our job (`NotCoveredSection`) | `not-covered-section.md` | `notCoveredSection` | Service pages with the `repair` template |
| Service areas (`AreasSection`) | `areas-section.md` | `areasSection` | `/areas/`, area pages, cleaning homepage |

The estimator, plans, add-ons, and included lists read their prices and tasks from `src/content/pricing/` and `src/content/services/`, never from the section file. See [Pricing & Estimator](/homio/customization/pricing-estimator/), [Booking Request](/homio/customization/booking-request/), [Services & What's Included](/homio/customization/services-included/), and [Service Areas](/homio/customization/service-areas/).

#### Company, Contact, And Blog
| Section (component) | Content file | Page block | Used on |
| --- | --- | --- | --- |
| Contact (`ContactSection`) | `contact-section.md` | `contactSection` | `/contact/`, main and commercial homepages, `/industries/`, industry pages, gift cards, referral, `commercial` service pages |
| Contact options (`ContactOptionsSection`) | `contact-options-section.md` | `contactOptionsSection` | `/contact/` |
| About hero (`AboutHeroSection`) | `about-hero-section.md` | `aboutHeroSection` | `/about/` |
| Story (`StorySection`) | `story-section.md` | `storySection` | `/about/` |
| Values (`ValuesSection`) | `values-section.md` | `valuesSection` | `/about/`, `/how-it-works/`, `/careers/` |
| Careers band (`CareersBandSection`) | `careers-band-section.md` | `careersBandSection` | `/about/`, `/team/` |
| Open roles (`OpenRolesSection`) | `open-roles-section.md` | `openRolesSection` | `/careers/` |
| Guarantee claim (`GuaranteeClaimSection`) | `guarantee-claim-section.md` | `guaranteeClaimSection` | `/guarantee/` |
| Credentials (`ComplianceSection`) | `compliance-section.md` | `complianceSection` | `/guarantee/` |
| Blog list (`BlogListSection`) | `blog-list-section.md` | `blogListSection` | `/blog/`, its pages, category and tag pages |
| Newsletter (`NewsletterSection`) | `newsletter-section.md` | `newsletterSection` | Blog list pages and posts |
| Not found (`NotFoundSection`) | `not-found-section.md` | `notFoundSection` | 404 pages, `/book/thanks/` |

Two names don't follow the pattern: the call to action is `CallToAction` / `call-to-action.md` / `ctaSection`, and the FAQ is `QuestionsSection` / `questions-section.md` / `questionsSection`. The trust strip's block is `trustStrip` (no `Section`).

Two more files in `src/content/sections/` belong to site-wide widgets: `announcement-bar.md`, the optional strip above the header ([Header](/homio/customization/header/)), and `cookie-consent.md`, the cookie banner ([Cookies & Analytics](/homio/customization/cookies-analytics/)).

#### Page-Only Blocks
These blocks have no section file. They exist only in page frontmatter:

| Block | Where | What it sets |
| --- | --- | --- |
| `pageHeader` | Any inner page | The page header: eyebrow, description, buttons, phone line, photo or ticket, and its layout. See [Section Layouts](/homio/customization/section-layouts/#page-header) |
| `contentPage` | Text pages in `src/content/pages/` | `notice` (a callout above the text), `summary` (a ticket of key facts beside it), and `options.numbered` |
| `giftCards` | `pages/english/gift-cards.md` | The gift card amounts and what each one covers |
| `referral` | `pages/english/referral.md` | The give and get amounts of the referral program |
| `layoutGallery` | `pages/english/elements.md` | The copy around the `/elements/` previews |
| `primaryCta` | Any page | The main button on this page only: header button, phone action bar, announcement link, and the footer link to the booking page. See [Common Changes](/homio/customization/common-changes/#change-the-main-button) |

<Aside type="tip">
  Some sections take their items from a collection instead of the section file:
  reviews from `src/content/reviews/`, areas from `src/content/areas/`, team
  members from `src/content/team/`, projects from `src/content/projects/`, and
  posts from the blog. See [Collections](/homio/customization/collections/).
</Aside>

### Add A Section To A Page
This is a small code edit in the page's route file in `src/pages/[...lang]/`.

**On a demo homepage** (`home-cleaning.astro`, `home-commercial.astro`, `home-handyman.astro`), add one line to the `sections` list. The order of the list is the order on the page, and `tone` gives the section a tinted panel (`mint`, `sage`, `sand`, and others listed in `src/layouts/components/HomePage.astro`):

```astro
const sections: HomeSection[] = [
  { block: "heroSection" },
  { block: "trustStrip", tone: "mint", flush: true },
  { block: "estimateSection" },
  // ...
];
```

Then add the block (for example `estimateSection:` with `enable: true`) to the homepage's content file.

**On any other page**, import the component and place it inside `<Base>`:

```astro
---

---
<IncludedSection content={page?.data.includedSection} />
```

The hero, services, steps, plans, reviews, and FAQ are written as `<LayoutVariants section="faq" content={questionsSection} />` in the routes. Keep that wrapper when you move them: it renders the section exactly like a direct import, and lets the demo layout switcher preview it.

Building a brand-new section is a developer task. `AGENTS.md` and the "Add a new section" recipe in `SKILLS.md` explain the rules (one `.astro` component, one content file in each language, and a schema in `src/sections.schema.ts`), so an AI assistant can do it for you.

### Do It With AI
```text
On the page [URL], change the [SECTION] section only for that page: [CHANGES]. Find the page's
content file and the block name in docs or in sectionsSchema of src/sections.schema.ts, add a named
block with only the keys that change (lists must repeat every item I keep), and do the same in the
french/ file. Don't edit src/content/sections/. Then run npm run astro-check.
```

```text
Add the [SECTION, e.g. estimate] section to [PAGE, e.g. /home-handyman/] after the [OTHER] section.
Follow SKILLS.md: for a demo homepage add it to the sections list in its route file, then add the
block with enable: true to the homepage content file in english/ and french/.
```