# Sections

## Sections

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

A **section** is one full-width block of a page: a hero, a pricing table, an FAQ. Each section is two files that share a name:

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

[How Ecozen Works](/ecozen/getting-started/how-ecozen-works/) explains the idea in full. This page is the practical reference.

### Change A Section Everywhere
Edit its file in `src/content/sections/english/` (and the other language folders). The comments in each file list its options and 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 file with `enable: false`:

  ```yaml
  faqSection:
    enable: false
  ```

- **On one page, for good:** delete its line in the page's route file in `src/pages/[...lang]/`.

A page block can also turn a section back **on** for one page when the section file has `enable: false`.

### Change A Section On One Page
Add a **named block** to the page's content file, with `enable: true` and only the keys you want to change. The block name is in the table below. Remember the merge rules: objects merge key by key, lists replace the whole list, and `""` clears a value.

Copy the block name exactly. A block with a wrong name, for example `faqsSection:` instead of `faqSection:`, is ignored without an error. `npm run astro-check` checks the values inside a correctly named block, except in the page files of `src/content/about-us/`, `contact/`, `faq/`, `pricing/`, and `calculator/`, which have no schema.

```yaml
# src/content/calculator/english/-index.md
faqSection:
  enable: true
  badge: "Questions"
  title: "About your estimate"
  list:
    - enable: true
      title: "How accurate is the estimate?"
      content: "It is a fair starting point for a typical roof..."
```

<Aside type="caution">
  A block only works on pages whose route passes it to the section
  (`content={...}` in the route file). The main homepage passes only
  `ctaSection`, and the blog pages pass none, so to change any other section
  there, edit its section file.
</Aside>

### Blocks Each Page Reads
| Page                    | Page file                                    | Blocks the route reads                                  |
| ----------------------- | -------------------------------------------- | ------------------------------------------------------- |
| Main homepage `/`       | `homepage/english/-index.md`                 | `ctaSection`                                            |
| Commercial and farm `/home-two/` | `homepage/english/home-two.md`      | `heroSection`, `companySection`, `comparisonSection`, `benefitsSection`, `impactSection`, `processSection`, `servicesSection`, `projectsSection`, `careersBandSection`, `blogSection`, `ctaSection` |
| Renewable energy `/home-three/` | `homepage/english/home-three.md`     | `heroSection`, `logoStripSection`, `statementSection`, `bentoSection`, `missionSection`, `featureSliderSection`, `impactSection`, `testimonialSection`, `blogSection`, `contactBandSection` |
| EV and batteries `/home-four/` | `homepage/english/home-four.md`       | `heroSection`, `tabsSection`, `chargeSpeedSection`, `pricingSection`, `projectsSection`, `faqSection`, `ctaSection` |
| About                   | `about-us/english/-index.md`                 | `aboutIntroSection`, `missionSection`, `valuesSection`, `impactSection`, `whyUsSection`, `testimonialSection`, `ctaSection` |
| Services overview       | `services/english/-index.md`                 | `servicesSection`, `benefitsSection`, `testimonialSection`, `ctaSection` |
| Service page            | `services/english/<entry>.mdx`               | `ctaSection`                                            |
| Projects                | `projects/english/-index.md`                 | `ctaSection` (also used by every project page)          |
| Project page            | `projects/english/<entry>.mdx`               | `ctaSection`                                            |
| Pricing                 | `pricing/english/-index.md`                  | `pricingSection`, `benefitsSection`, `faqSection`, `ctaSection` |
| Calculator              | `calculator/english/-index.md`               | `calculatorSection`, `faqSection`, `ctaSection`         |
| Team                    | `team/english/-index.md`                     | `teamSection`, `ctaSection`                             |
| Careers                 | `careers/english/-index.md`                  | `benefitsSection`, `careersListSection`, `ctaSection`   |
| FAQ                     | `faq/english/-index.md`                      | `faqSection`, `ctaSection`                              |
| Contact                 | `contact/english/-index.md`                  | `contactSection`, `coverageSection`, `ctaSection`       |
| Text pages              | `pages/english/<page>.md`                    | `ctaSection`                                            |

On `/home-four/`, the testimonials section reads `testimonial-section.md` directly: its route passes no block. Some blocks are read by the route but not set in the shipped homepage file, so those sections show their section files: the cost comparison and careers band on `/home-two/`, the statement, bento grid, feature slider, and contact band on `/home-three/`, and the charging speeds on `/home-four/`.

### Add A Section To A Page
This is a small code edit in the page's route file:

1. Import the component at the top, between the `---` lines:

   ```astro
   import FaqSection from "@/components/sections/FaqSection.astro";
   ```

2. Place it where you want it, inside `<Base>`:

   ```astro
   <FaqSection />
   ```

3. To give it page-specific content, read its block from the page file and pass it in:

   ```astro
   <FaqSection content={page?.data.faqSection} />
   ```

Building a brand-new section is a developer task: `AGENTS.md` explains the conventions (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.

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

#### Homepage And Marketing
| Section (component)                  | Content file              | Page block           | Used on                                         |
| ------------------------------------ | ------------------------- | -------------------- | ----------------------------------------------- |
| Hero (`HeroSection`)                 | `hero-section.md`         | `heroSection`        | All four homepages                              |
| Logo strip (`LogoStripSection`)      | `logo-strip-section.md`   | `logoStripSection`   | Main and renewable energy homepages             |
| About (`CompanySection`)             | `company-section.md`      | `companySection`     | Main and commercial homepages                   |
| Services (`ServicesSection`)         | `services-section.md`     | `servicesSection`    | Main and commercial homepages, `/services/` (as its page header) |
| Benefits (`BenefitsSection`)         | `benefits-section.md`     | `benefitsSection`    | Main and commercial homepages, services, pricing, careers |
| How it works (`ProcessSection`)      | `process-section.md`      | `processSection`     | Main and commercial homepages                   |
| Testimonials (`TestimonialSection`)  | `testimonial-section.md`  | `testimonialSection` | Main, renewable energy, and EV homepages, about, services |
| Results (`ImpactSection`)            | `impact-section.md`       | `impactSection`      | Main, commercial, and renewable energy homepages, about |
| Projects (`ProjectsSection`)         | `projects-section.md`     | `projectsSection`    | Commercial and EV homepages                     |
| Service area (`CoverageSection`)     | `coverage-section.md`     | `coverageSection`    | Main homepage, `/contact/`                      |
| Cost comparison (`ComparisonSection`) | `comparison-section.md`  | `comparisonSection`  | Commercial homepage                             |
| Charging speeds (`ChargeSpeedSection`) | `charge-speed-section.md` | `chargeSpeedSection` | EV homepage                                  |
| Statement (`StatementSection`)       | `statement-section.md`    | `statementSection`   | Renewable energy homepage                       |
| Bento grid (`BentoSection`)          | `bento-section.md`        | `bentoSection`       | Renewable energy homepage                       |
| Feature slider (`FeatureSliderSection`) | `feature-slider-section.md` | `featureSliderSection` | Renewable energy homepage                |
| Product tabs (`TabsSection`)         | `tabs-section.md`         | `tabsSection`        | EV homepage                                     |
| Why choose us (`WhyUsSection`)       | `why-us-section.md`       | `whyUsSection`       | Main homepage, about                            |
| FAQ (`FaqSection`)                   | `faq-section.md`          | `faqSection`         | Main and EV homepages, pricing, calculator, FAQ |
| Blog preview (`BlogSection`)         | `blog-section.md`         | `blogSection`        | Main, commercial, and renewable energy homepages |
| Careers band (`CareersBandSection`)  | `careers-band-section.md` | `careersBandSection` | Commercial homepage                             |
| Contact band (`ContactBandSection`)  | `contact-band-section.md` | `contactBandSection` | Renewable energy homepage                       |
| Call to action (`CTASection`)        | `cta-section.md`          | `ctaSection`         | Most pages, above the footer. Off on the main and commercial homepages |

#### Pages
| Section (component)                  | Content file              | Page block           | Used on                |
| ------------------------------------ | ------------------------- | -------------------- | ---------------------- |
| Pricing (`PricingSection`)           | `pricing-section.md`      | `pricingSection`     | `/pricing/`, EV homepage |
| Savings calculator (`CalculatorSection`) | `calculator-section.md` | `calculatorSection` | `/calculator/`, main homepage |
| Contact and quote form (`ContactSectionTwo`) | `contact-section-two.md` | `contactSection` | `/contact/`        |
| About intro (`AboutIntroSection`)    | `about-intro-section.md`  | `aboutIntroSection`  | `/about/`              |
| Mission (`MissionSection`)           | `mission-section.md`      | `missionSection`     | `/about/`, renewable energy homepage |
| Values (`ValuesSection`)             | `values-section.md`       | `valuesSection`      | `/about/`              |
| Team (`TeamSection`)                 | `team-section.md`         | `teamSection`        | `/team/`               |
| Open roles (`CareersListSection`)    | `careers-list-section.md` | `careersListSection` | `/careers/`            |
| Project grid (`ProjectsListSection`) | none: options in `projects/english/-index.md` | none | `/projects/` |
| Not found (`NotFoundSection`)        | none: text in `notFound` in the i18n files | none | 404 pages      |

Two names don't follow the pattern: the contact section's file is `contact-section-two.md` but its block is `contactSection`, and the about section on the homepages is `CompanySection` / `companySection`.

Two more files in `src/content/sections/` belong to widgets: `cookie-consent.md`, the site-wide cookie banner ([Cookies & Analytics](/ecozen/customization/cookies-analytics/)), and `monitoring-panel.md`, the text and numbers of the `<MonitoringPanel />` shortcode ([Writing Content](/ecozen/customization/writing-content/#monitoring-panel)).

<Aside type="tip">
  Some sections take their list from a collection instead of the section file:
  testimonials from `src/content/testimonial/english/-index.md` (unless the
  block has its own `list`), the team from `src/content/team/english/-index.md`,
  and services, projects, open roles, and posts from their own folders. See
  [Collections](/ecozen/customization/collections/).
</Aside>

### Newer Sections In Detail
These sections came with the four homepages. Each one is a component in `src/layouts/components/sections/` and a content file in `src/content/sections/english/` (and the other language folders), and any route can use it.

#### Statement
File: `statement-section.md` · Block: `statementSection`

One large centered paragraph with small photos set inside the sentence. `{1}` and `{2}` in `text` mark where `images[0]` and `images[1]` go; a marker without a matching image is dropped. As the paragraph scrolls into view, the words turn from muted to ink one by one. With reduced motion on, the text shows in full ink.

```yaml
text: "For 18 years we have built and run wind farms {1} and solar parks on land that stays in farming. Together with our battery sites {2} they send clean power to more than 400,000 homes."
images:
  - image: "/images/photos/slide-wind-unsplash-H3fy5XIq9LM.jpg"
    imageAlt: "Wind turbines in open farmland"
  - image: "/images/photos/slide-storage-pexels-37061421.jpg"
    imageAlt: "Equipment cabin beside a solar park"
```

#### Bento Grid
File: `bento-section.md` · Block: `bentoSection`

A heading, then one tall photo card beside icon cards. `card` holds the photo card: `title`, `image`, `imageAlt`, and a `button`. `list` holds the icon cards, each with `icon`, `title`, and `description`; four fill the grid.

#### Feature Slider
File: `feature-slider-section.md` · Block: `featureSliderSection`

A centered heading, then a text column with previous and next arrows beside a photo that changes with each item. `subtitle` is the heading at the top of the text column, and `prevLabel` and `nextLabel` are the screen-reader names of the arrows. Each item of `list` has a `title`, a `description`, and its own `image` (required) with `imageAlt`.

#### Contact Band
File: `contact-band-section.md` · Block: `contactBandSection`

A full-width photo (`image`, `imageAlt`) with a heading and text on the left and a white card with a short enquiry form on the right. `form` uses the same fields as the quote form (see [Forms](/ecozen/customization/forms/)): `emailSubject`, `submitButton`, and `inputs`, including the two message items at the end. It sends through `contactFormAction` and `contactFormProvider` in `config.toml`, like the contact page.

A page can have the contact band and the quote form together: each form works on its own.

#### How It Works
File: `process-section.md` · Block: `processSection`

Numbered steps (plain numbers: 1, 2, 3) with a `badge`, `title`, `description`, and an optional `button`. Each item of `list` has a `title`, a `description`, a short `meta` note (for example "Within 2 working days"), and an optional `image` and `imageAlt` for the step card. Two layouts: `steps` (a row of cards) and `timeline` (a numbered list beside the section's sticky `image`). See [Section Layouts](/ecozen/customization/section-layouts/#how-it-works).

#### Product Tabs
File: `tabs-section.md` · Block: `tabsSection`

A heading, then tab buttons and one panel per tab. `tabsLabel` is the screen-reader name of the tab list. Each item of `list` has a `label` (the tab button), a `title`, a `description`, a check-mark `list`, an `image` with `imageAlt`, and a `button`. Without JavaScript, every panel shows, one below the other.

#### Projects
File: `projects-section.md` · Block: `projectsSection`

Case-study cards from `src/content/projects/`, each with its photo, title, and key facts, plus a `button` to `/projects/`.

```yaml
options:
  limit: 3                  # number of project cards
  projects: ["project-1", "project-6", "project-3"]   # file names to show first, in this order
```

With `projects` empty, the section shows the projects with the lowest `weight`. Use the file name (`project-1`), not the `customSlug`.

#### Service Area
File: `coverage-section.md` · Block: `coverageSection`

Where you install: a heading and text, a list of towns or areas, a response-time line, a button, and a photo.

```yaml
options:
  layout: "list"          # list | pills | regions
  imagePosition: "right"  # left | right
areasTitle: "Towns and areas we cover"
areas:
  - "Riverside"
  - "Oak Park"
responseTime:
  icon: "Clock"
  text: "**Typical response:** a reply within one working day and a home survey within 5 working days."
askText: "Not on the list?"   # shown before the button
button:
  enable: true
  label: "Ask us"
  url: "/contact/"
image: "/images/photos/project-home-unsplash-VX0ZEZSwqnY.jpg"
imageAlt: "Bungalow with a full array of solar panels on its roof"
```

`list` shows the areas as a check-mark list; `pills` shows them as rounded tags. `imagePosition` puts the photo on the left or the right. The sample towns are placeholders: list the places you really cover, and keep them in step with `[seo.localBusiness] areaServed`.

**Towns by region.** The `regions` layout groups your towns under a heading per region. It reads `regions` instead of `areas`:

```yaml
options:
  layout: "regions"
regions:
  - name: "North district"
    areas: ["Northgate", "Pine Ridge", "Cedar Hills", "Highfield"]
  - name: "Central area"
    areas: ["Riverside", "Oak Park", "Fairview", "Millbrook"]
```

Each region becomes a column with its `name` as a heading. Four regions fit one row when the section has no photo. The contact page uses this layout with `image: ""`, so the regions sit in four columns, and points its button at the quote form on the same page. In `src/content/contact/english/-index.md`:

```yaml
coverageSection:
  enable: true
  options:
    layout: "regions"   # list | pills | regions
  badge: "Areas we serve"
  title: "Towns we cover, by region"
  areasTitle: ""
  askText: "Don't see your town?"
  button:
    enable: true
    label: "Get a quote"
    url: "#contact-form"
    variant: "fill"
  image: ""   # no photo, so the regions sit in four columns
```

The regions themselves come from `coverage-section.md`, so you keep one list of towns for the whole site. The sample regions are placeholders too. To hide the section on the contact page, set `enable: false` in this block.

#### Cost Comparison
File: `comparison-section.md` · Block: `comparisonSection`

A table that compares options side by side, with a `footnote` for the assumptions and a `button`. From the `md` breakpoint up it is a table; on phones each column becomes a card.

```yaml
rowsLabel: "Per site"                       # heading of the row labels
recommendedLabel: "What we usually advise"  # label on the recommended column
columns:
  - title: "Grid only"
    description: "Every kWh bought from your supplier"
    recommended: false
  - title: "Solar + battery"
    description: "250 kWp and a 200 kWh battery"
    recommended: true
rows:
  - label: "Yearly energy bill"
    values: ["$88,000", "$33,500"]         # one value per column, in column order
footnote: "Assumptions: ..."
```

Give every row one value per column. The shipped figures are examples for a sample warehouse: replace them with figures you can stand behind, and keep the footnote's assumptions true.

#### Charging Speeds
File: `charge-speed-section.md` · Block: `chargeSpeedSection`

One card per charger type, a `button`, and an optional `note` at the bottom.

```yaml
labels:
  range: "Range added per hour"
  topUp: "Time to add 60 kWh"
  suits: "Suits"
list:
  - icon: "PlugZap"
    title: "Home wallbox"
    power: "7 kW"
    range: ["About 30 miles", "About 50 km"]   # one line each
    topUp: "About 9 hours"
    suits: "Most homes with one or two cars. Full by morning on a night tariff."
    recommended: true                           # dark card
note:
  enable: true
  icon: "Moon"
  title: "Off-peak:"
  text: "a 6-hour night window on a 7 kW wallbox adds about 40 kWh..."
```

`labels` are the headings of the rows on every card. `range` is a list, so you can give miles and kilometres, or one line only. Mark one card `recommended`. The `description` above the cards states the assumptions behind the figures; keep it in step with them.