Forms
There are two ways to put a form on a page:
| Form Embed | Form Block | |
|---|---|---|
| What it is | A form you built in another service, placed on your page. | A form you build in Studio, field by field. |
| Where answers go | Into that service, the same as anywhere else you use the form. | Your email inbox (through the email service you connect in your Deep Woods dashboard), or any service that accepts form submissions at a URL (Formspree, Basin, Zapier, Make, n8n, Google Apps Script, …). |
| Looks like | However the service styles it. | Your site: your colors, fonts, and buttons. |
| Best for | Email signups (Klaviyo, Mailchimp, HubSpot), surveys (Typeform, Tally, Jotform, Google Forms). | Contact, quote-request, and simple lead forms. |
Both blocks are in the Deep Woods Forms group of the / menu.
Form Embed: forms from other services
Every form service gives you an embed code (sometimes called a snippet, install code, or HTML code). You can put it in one of two places.
Option 1: an Embeds file (recommended)
Use this for any embed code, and always for codes longer than one line.
Create the embed file
In Content, open embeds, click New file, and name it after the form, for example newsletter.
Paste the code
Fill in:
- Name: a label for your own reference, such as Newsletter signup.
- Embed code: paste the code exactly as the service gives it.
- Notes: optional, for your reference. Like everything in Studio, it can be read by anyone who knows where to look, so keep private details out of it.
Add a Form Embed block to your page
On your page, type /, choose Form Embed, open Edit props, and set Embed to the file name (newsletter).
Embed files are reusable. Point Form Embed blocks on several pages at the same file, then update the file once and every page follows.
Option 2: paste into the block
For short, one-line codes, such as an <iframe …> from Tally or Google Forms, paste the code straight into the Form Embed block's Code field.
Form Embed fields
| Field | What it does |
|---|---|
| Embed | The name of a file in embeds (without .yml). |
| Code | A one-line embed code, used instead of an Embeds file. |
| Align | left, center (default), or right. |
| Max Width | How wide the form can grow: sm, md, lg, xl, 2xl, or full (default). |
::form-embed{embed="newsletter" align="center" max-width="lg"}
::
Services that need a site-wide code too
Some services, Klaviyo for example, ask you to add one script to every page, and then give you a short code for each form. In that case:
- Paste the every-page script into Content → settings → site → Code for the head of every page (or Code for the end of every page if the service says "before
</body>"). - Put the form's own short code in a Form Embed block.
Pop-up and fly-out forms that the service shows on its own usually only need the site-wide code, with no Form Embed block.
What you'll see while editing
- The form loads after the rest of the page, so it may appear a moment later.
- A yellow notice in the preview means the Embed name doesn't match a file in embeds, or nothing has been pasted yet. Visitors never see this notice.
- Some services only show their form on your real domain. If the form is blank in the editor, check it on your preview or live site.
Form Block: build your own form
A Form Block collects answers on your page and either emails them to you or sends them to a URL from a form service you choose. To get them by email, see Get submissions by email below. To send them to a URL, you'll need an account with a service such as Formspree or Basin, or a webhook from Zapier, Make, or n8n, and the steps below.
Get your form service's URL (webhook only)
Create a form (or webhook) in your service and copy the URL it gives you for submissions. It must start with https://.
Tell Studio where to send answers
In Content → forms, edit contact, or click New file to make another (for example quote-request). Fill in:
| Field | What it does |
|---|---|
| Name | For your reference, such as Contact form. |
| Send with | webhook (the default) to send answers to a URL. For email, see Get submissions by email. |
| Send submissions to | The https:// URL from your form service. |
| Format | json works for most services. Choose form-urlencoded for Google Apps Script, or any service that asks for "form data". |
| Success message | Shown in place of the form after it's sent. Default: Thanks! Your message has been sent. |
| Error message | Shown above the form if sending fails. Default: Something went wrong. Please try again. |
| Redirect after sending | Optional. Sends visitors to a page (such as /thank-you) or URL instead of showing the success message. |
| Notes | Optional, for your reference. |
Add a Form Block to your page
Type /, choose Form Block, and set its Form field to the file name (contact).
Add fields inside it
Click inside the Form Block and type / to add a Form Field for each question, then put an input inside each field (see the tables below).
Publish and test
Publish your changes and create a preview. Send a test submission from the preview site and confirm it arrives in your form service.
Get submissions by email
A Form Block can email each submission to you through an email service you already use. Connect the service once in your Deep Woods dashboard, then choose who gets each form's emails in Studio.
Connect an email service in your Deep Woods dashboard
Open your site in the Deep Woods dashboard, go to Form Settings, and click Connect email. Choose your service and follow the steps shown:
- SendGrid, Resend, or Postmark: paste an API key.
- Any other email service (Gmail / Google Workspace, Microsoft 365, Mailgun, Amazon SES, Brevo, Zoho, …): choose Other (SMTP) and enter the server, port, username, and password your service gives you.
Deep Woods checks the details, saves them securely, and updates your site. This takes a minute or two.
Set the form to send by email
In Content → forms, open your form (for example contact) and fill in:
| Field | What it does |
|---|---|
| Send with | Choose email. |
| Notify | Who receives each submission. Separate several addresses with commas. |
| From | The sender address. It must be one your email service allows, such as a verified sender in SendGrid, or an address on a domain you've verified in Resend or Postmark. |
| From name | Optional, such as Website forms. |
| Subject | Optional. Default: New submission: followed by the form's name. |
Publish and test
Publish, then send a test submission from your preview or live site. The email arrives at Notify. Replying to it goes straight to the visitor, as long as the form has a field named email.
Form Block fields
| Field | What it does |
|---|---|
| Form | The name of a file in forms (without .yml). |
| Submit Label | The button text. Default: Submit. |
| Submit Color / Submit Variant / Submit Size | The button's look, the same options as any button. |
| Submit Block | Makes the button full width. |
| Submit Class / Success Class / Class | Style changes for the button, the success message, or the whole form. See Styling. |
Form Field: the label around each input
| Field | What it does |
|---|---|
| Name | The name your form service receives for this answer, such as email or company. Keep it short, lowercase, and unique within the form. |
| Label | The question visitors see, such as Work email. |
| Description | Helper text under the label. |
| Help | Small text under the input. |
| Required | Marks the field required (adds an asterisk). Also turn on Required on the input inside it. |
Inputs: what goes inside a Form Field
| Input | Use it for | Key options |
|---|---|---|
| Form Input | One line of text. | Type: text, email, url, number, password, or search. Also Placeholder, Autocomplete (for example email, name, tel), Required, Leading Icon. |
| Form Textarea | Longer answers. | Rows (height), Placeholder, Required. |
| Form Select | A dropdown. | Items (the choices), Placeholder, Required. |
| Checkbox Group | Pick any number of options. | Items, Legend (a heading), Default Value. |
| Radio Group | Pick exactly one option. | Items, Legend, Default Value. |
| Checkbox | A single yes/no, such as Subscribe to updates. | Label, Description, Value (what's sent when checked), Required. |
| Switch | A single on/off toggle. | Label, Description, Value, Required. |
An input inside a Form Field uses the Form Field's Name automatically. You only need to set Name on the input if it isn't inside a Form Field.
Complete example
Paste this into the code editor to get a working contact form, then adjust it in the visual editor:
::form-block{form="contact" submit-label="Send message" submit-block}
:::form-field{name="name" label="Your name" required}
::::form-input{autocomplete="name" required}
::::
:::
:::form-field{name="email" label="Email" required}
::::form-input{type="email" autocomplete="email" required}
::::
:::
:::form-field{name="topic" label="What can we help with?"}
::::form-select
---
placeholder: Choose a topic
items:
- Sales
- Support
- Partnerships
---
::::
:::
:::form-field{name="message" label="Message"}
::::form-textarea{rows="5" placeholder="Tell us a bit about your project"}
::::
:::
:::form-field{name="updates"}
::::checkbox{label="Send me occasional product updates" value="yes"}
::::
:::
::
Good to know
- Spam protection is built in. Forms include invisible checks that stop most automated spam. You don't need to add a captcha.
- Give every field a different Name. Two fields with the same name arrive as a single list.
- With a webhook, your form service decides what happens next: email notifications, autoresponders, spreadsheets, CRM. Set those up in the service.
- Nothing arrives? If a form set to email shows its error message, check that an email service is connected in Form Settings, and that Notify and From are filled in.