Forms
Files: src/config/config.toml, src/content/sections/english/contact-section-two.md · Skill level: Beginner

Ecozen’s main form is the quote request on /contact/, beside a card with your contact details. Ecozen is a static site, so the form sends its answers to a service you choose, which emails them to you or stores them.
The short form in the contact band section and the quote card of the form hero send to the same address. The email sign-up in the newsletter footer has its own address, in [settings.newsletter] (see Footer).
The form has three steps (property, energy use, contact). With JavaScript, visitors see one step at a time, with a progress bar, Next and Back buttons, and “Step 1 of 3”. Next checks the required fields of the current step before it moves on. Without JavaScript, all steps show as one long form that still submits.
Connect The Form
The theme ships with a placeholder address (https://formsubmit.co/[email protected]). Until you replace it, requests go nowhere. Pick a provider and set both lines in config.toml:
Free, no account needed. Requests arrive by email, as a table of the answers.
[settings] contactFormProvider = "formsubmit.co"The first request you send triggers an activation email from Formsubmit. Open it and confirm, or later requests won’t be delivered.
Create a form at formspree.io and copy its endpoint. Requests appear in your Formspree dashboard, and Formspree can email them to you.
[settings] contactFormAction = "https://formspree.io/f/your-form-id" contactFormProvider = "formspree"If Formspree returns an error or doesn’t answer within 5 seconds, the form shows contactForm.fallbackTicketMessage from src/i18n/<language>.json, so put your own email address there.
Only when the site is hosted on Netlify. Netlify detects the form at deploy time.
[settings] contactFormAction = "/" contactFormProvider = "netlify"Turn on form detection in the Netlify dashboard (Forms), deploy, and send a test request. Submissions appear in the dashboard and can be forwarded by email. Check that your test request arrives there before you rely on the form.
After launch, send one real request from the live site to make sure it arrives.
Check The Setup
Ecozen checks both form addresses (contactFormAction with contactFormProvider, and action with provider in [settings.newsletter]) whenever it renders a page that shows that form (the newsletter form shows only in the newsletter footer). It warns when an address is empty, is still a placeholder, names a provider the theme doesn’t know, or doesn’t match the provider, for example a Formspree address with contactFormProvider = "formsubmit.co".
- In the terminal:
npm run devandnpm run buildprint a line that starts with a yellow[forms]tag, names the form (contactornewsletter) and the problem, and says which keys to set. - On the dev server: after you submit the form, a “Dev only · form not connected” note appears inside it with the same reason. It never shows when the page loads, and never on a built or deployed site, so check the terminal before you deploy.
The check knows the shape of each provider’s address: https://formsubmit.co/..., https://formspree.io/f/..., and a path such as / for Netlify. A newsletter with provider = "" can post to any address, so only a placeholder address is reported there. An empty newsletter action hides the sign-up form instead.
Change The Questions
The form lives in src/content/sections/english/contact-section-two.md (and the other language folders), under form. The contact page file can override it with a contactSection block, but ships with enable: true only, so edit the section file.
Steps. form.steps lists the steps in order. Each field has a step number that puts it in that step:
form: emailSubject: "New quote request from the website" # subject of the email you receive (Formsubmit and Formspree) steps: - title: "Property" description: "" - title: "Energy use" description: "" - title: "Contact" description: "" stepNav: stepLabel: "Step" # "Step 1 of 3" ofLabel: "of" nextButton: label: "Next" variant: "fill" backButton: label: "Back" variant: "outline" submitButton: enable: true label: "Send my request" variant: "fill"To make a one-step form, remove steps (or leave one step) and the step numbers.
Fields. Each item of inputs is one field:
inputs: - label: "Full name" placeholder: "Your name" name: "Full name" # the field name in the request you receive autocomplete: "name" required: true halfWidth: true # two fields per row on large screens step: 3 - label: "Message" tag: "textarea" rows: "4" name: "Message" step: 3Choices. Radio buttons and checkboxes are one item per choice. Items with the same group are shown together, and the first one carries the groupLabel (the question) and inline: true (choices in a row):
- label: "Home" name: "Property type" value: "Home" checked: true # selected by default required: true groupLabel: "Property type" group: "property" type: "radio" inline: true step: 1 - label: "Business" name: "Property type" value: "Business" required: true group: "property" type: "radio" step: 1| Field type | How to write it |
|---|---|
| Text | No type, or type: "text" |
| Email, phone, number | type: "email", "tel", or "number" |
| Long text | tag: "textarea" and rows |
| Radio buttons | type: "radio", one item per choice, with a shared group and name |
| Checkboxes | type: "checkbox", one item per choice, each with its own name |
| Dropdown | dropdown: with type (select or search) and items |
Other options: required, placeholder, autocomplete, defaultValue, and id.
The privacy checkbox near the end (id: "privacy-policy") links to your terms and privacy policy in its label. Keep it, and keep the links pointing at your real pages.
Messages. The last two items of inputs are not fields: the one with note: success holds the message shown after a request is sent, and the one with note: deprecated the message shown when sending fails. Edit their content and keep their parentClass:
- note: success parentClass: "hidden text-sm message success" content: "Thank you. We have your request and an energy advisor will contact you within one working day." - note: deprecated parentClass: "hidden text-sm message error" content: "Something went wrong. Please email [[email protected]](mailto:[email protected]) and we will follow up."Replace [email protected] there, and in contactForm.fallbackTicketMessage in each file in src/i18n/, with your own address.
The section file has no schema, so npm run astro-check doesn’t report a mistyped option. Open /contact/, step through the form, and send a test request after each change.
The Contact Details Card
The card beside the form lists phone, email, address, and hours from [settings.contactInfo] in config.toml, as plain lines with a small label above each value. Each item in list of contact-section-two.md picks one with settingFieldName; its title is the label (the icon field is kept in the file but not shown). Set value on an item to show other text instead, for example translated opening hours in the French file:
list: - title: "Opening hours" icon: "Clock" settingFieldName: "hours" value: "Lun–Ven, 8h00–18h00"Do It With AI
Connect the quote form to [Formsubmit with EMAIL | Formspree with form ID | Netlify Forms]: set contactFormAction andcontactFormProvider in src/config/config.toml following its comments. Then change the questions incontact-section-two.md in every language folder of src/content/sections/ to: step 1 [QUESTIONS], step 2[QUESTIONS], step 3 [CONTACT FIELDS]. Keep the steps structure, the privacy checkbox, and the twomessage items, and replace [email protected] with [EMAIL] in the messages and incontactForm.fallbackTicketMessage in every file in src/i18n/.