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:
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.mdsrc/content/sections/arabic/pricing-section.mdHow 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: falseat the top of its section file. -
On one page: add its block to that page’s file with
enable: false: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.
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..."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:
-
Import the component at the top, between the
---lines:import FaqSection from "@/components/sections/FaqSection.astro"; -
Place it where you want it, inside
<Base>:<FaqSection /> -
To give it page-specific content, read its block from the page file and pass it in:
<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.
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), and monitoring-panel.md, the text and numbers of the <MonitoringPanel /> shortcode (Writing Content).
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.
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): 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.
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/.
options: limit: 3 # number of project cards projects: ["project-1", "project-6", "project-3"] # file names to show first, in this orderWith 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.
options: layout: "list" # list | pills | regions imagePosition: "right" # left | rightareasTitle: "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 buttonbutton: 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:
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:
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 columnsThe 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.
rowsLabel: "Per site" # heading of the row labelsrecommendedLabel: "What we usually advise" # label on the recommended columncolumns: - title: "Grid only" description: "Every kWh bought from your supplier" recommended: false - title: "Solar + battery" description: "250 kWp and a 200 kWh battery" recommended: truerows: - label: "Yearly energy bill" values: ["$88,000", "$33,500"] # one value per column, in column orderfootnote: "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.
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 cardnote: 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.