Forms — Titen Astro
Titen has three forms, and all of them work as soon as you run the site:
- “Let’s Work Together” at the end of Projects, the category pages and every service page;
- the form on the Contact page;
- the newsletter sign-up in the footer.
Each one checks the required fields, shows a spinner while sending, says “Thank you”, keeps what the visitor typed when something fails, and drops spam with a hidden honeypot field.
Out of the box they run in demo mode: nothing is sent, and the fields are logged in the browser console. That’s fine while you build; pick a destination before you publish.
Choose a mode
Section titled “Choose a mode”| You want | Mode | Hosting |
|---|---|---|
| Submissions by email, with no server to run | Static: a form service (Formspree, Web3Forms, Getform, Basin) | Any static host |
| Submissions in a CRM, a spreadsheet, Slack… | Static: a webhook (Zapier, Make, n8n, Pipedream) | Any static host |
| Mailchimp or Resend directly, no third party | Server: the site’s own route | A host with an Astro adapter |
Most sites want static mode: it keeps the site 100% static and takes two minutes.
Static mode in two minutes
Section titled “Static mode in two minutes”-
Create a form at your service and copy its endpoint URL (Formspree:
https://formspree.io/f/<id>). -
Copy the example settings and paste the URL:
Terminal window cp .env.example .envPUBLIC_FORM_ENDPOINT=https://formspree.io/f/abcdwxyzWeb3Forms also needs
PUBLIC_FORM_ACCESS_KEY. -
Restart
npm run dev, send a test submission, and check that it arrived. -
Set the same variable in your host’s dashboard (or keep
.envif you build locally). The value is baked into the pages at build time, so rebuild after changing it.
All three forms post to the same endpoint; the form and subject fields tell them apart.
Server mode
Section titled “Server mode”For Mailchimp or Resend without a third-party service:
- Add the adapter for your host:
npx astro add vercel(ornetlify,node,cloudflare). - Set
PUBLIC_FORM_MODE=serverand choose where submissions go withFORM_PROVIDER(console,webhook,mailchimp,resend, or several comma-separated), plus that provider’s keys from.env.example. - The forms now post to
/api/forms/contactand/api/forms/newsletteron your own site. Every other page stays static.
Every detail is in Forms reference: what each service needs, the fields sent, Mailchimp consent settings, and writing your own provider.
What the forms ask for
Section titled “What the forms ask for”The project form and the Contact page share their fields:
| Field | Name it arrives under | Required |
|---|---|---|
| First Name | firstName |
yes |
| Last Name | lastName |
|
email |
yes | |
| Phone | phone |
|
| Message | message |
The newsletter sends email only (required).
Every submission also carries form: contact for the project and Contact forms, newsletter for the footer. The two
contact forms add a subject: “New project enquiry” or “New contact enquiry”. In server mode, Resend puts the sender’s
first and last name in the email’s subject, and Mailchimp stores them as FNAME and LNAME.
Changing the forms
Section titled “Changing the forms”The labels, placeholders, button texts (“Submit”, “Thank you”, “Something went wrong”) and subjects are content:
- the project and Contact forms:
projectForminsrc/content/site.json; - the Contact page’s subject:
notificationinsrc/content/pages/contact.json; - the newsletter:
footer.newsletterinsite.json.
A field arrives at your service under its name, so keep the names you already map somewhere.
- To make a field required, set
"required": trueon it inprojectForm.fields(the browser checks it first). For server mode, also add its name torequiredinsrc/lib/forms/definitions.ts. - To add a field, add it to
projectForm.fields, then to the forms insrc/components/sections/ContactFormSection.astroandContactMainSection.astro. Server mode takes every field ofprojectForm.fields.
Testing before launch
Section titled “Testing before launch”- Submit each form on the live site with a real address, and reply to the test.
- Check the “Something went wrong” path once: point the endpoint at a wrong URL in a preview build, submit, and confirm that the visitor’s text is still there.
Spam and privacy
Section titled “Spam and privacy”The honeypot stops the usual bots (a bot that fills the hidden field is shown “Thank you” and nothing is sent), and form services filter spam on their side.
Submissions go only where you point them. Add a privacy page (see Pages and sections) and link it under the forms:
- the project and Contact forms:
projectForm.text; - the newsletter:
footer.newsletter.note.
Ask for consent if you add newsletter subscribers to a marketing audience.