# How do I add a contact form to a static site built with AI?

Load the Siteon script with one line, add the attribute data-sitekit-form to your existing form, and declare its fields in schema.json. Submissions are stored, the business is notified by email and Slack, and the customer gets an automatic thank-you email, with no server, no JavaScript and no separate form service. It works free on the Free plan while you build, and from $4/month per site on your live domain.

URL: https://siteon.dev/guides/add-contact-form-to-static-site
Updated: 2026-10-26

## What you need

- The site as HTML files (built with AI, by hand, or exported from a generator). How it was made doesn't matter
- A Siteon site ID. Sign up with your email address and a Free site is created for you (or run `siteon sites create`)
- No server, no form endpoint of your own, and no hidden fields

## Steps

### 1. Add the script tag

Put one line before `</body>`, or in `<head>` with `defer`. Replace `hanaya` with your site ID.

```html
<script src="https://cdn.siteon.dev/sitekit.js" data-site="hanaya" defer></script>
```

### 2. Mark the form

Add `data-sitekit-form` to the `<form>` you already have. Keep the hidden `_hp` input: it is the bot trap, and it is required.

```html
<form data-sitekit-form="contact">
  <label>Name <input name="name" required autocomplete="name"></label>
  <label>Email <input type="email" name="email" required autocomplete="email"></label>
  <label>Message <textarea name="message"></textarea></label>

  <!-- Bot protection. Place it where people can't see it (required) -->
  <input type="text" name="_hp" tabindex="-1" autocomplete="off"
         style="position:absolute;left:-9999px" aria-hidden="true">

  <button type="submit">Send</button>
</form>

<div data-sitekit-success role="status" aria-live="polite" hidden>Thank you for your inquiry.</div>
<div data-sitekit-error role="status" aria-live="polite" hidden></div>
```

### 3. Declare the fields in schema.json and apply it

`forms[].key` must match the `data-sitekit-form` value, and each `fields[].key` must match an input's `name`.

```json
{
  "forms": [
    { "key": "contact", "label": "Contact", "fields": [
      { "key": "name", "label": "Name", "type": "text", "required": true },
      { "key": "email", "label": "Email address", "type": "email", "required": true },
      { "key": "message", "label": "Message", "type": "textarea" }
    ] }
  ]
}
```

```sh
siteon schema push --site hanaya        # validate and apply
siteon forms test contact --site hanaya # send a test notification
```

### 4. Turn on notifications and the thank-you email

In the [dashboard](https://app.siteon.dev), open "Settings → Notifications → each form". Add the email addresses to notify, a Slack Incoming Webhook URL if you use Slack, and switch on the thank-you email (auto-reply). The thank-you email goes to the address in the form's `type: "email"` field.

### 5. Publish

Publish the folder with `siteon deploy ./dist --site hanaya` (first time: `siteon hosting enable --site hanaya`). You can also keep your current hosting: the form works with the script tag alone.

## What it costs

Prices are per site. The form, notifications, auto-replies and spam protection are included on every plan.

| | Free | Lite | Standard | Business |
|---|---|---|---|---|
| Monthly | $0 | $4 | $12 | $39 |
| Form submissions | 50/mo | 500/mo | 1K/mo | 5K/mo |

- The Free plan works on development and preview domains (`localhost`, `*.pages.dev` and similar) and on its Siteon hosting subdomain (`<name>.siteun.com`). Move the site to a paid plan to take inquiries on your own domain. Register the domain of the page with the form in the site's allowed origins (otherwise submissions get `403 origin_not_allowed`; see [Registering allowed origins and fixing it](https://siteon.dev/docs/domains#allowed-origins))
- Bookings count as form submissions
- Going slightly over a paid limit doesn't stop submissions immediately: you get email alerts at 80% and 100%. See [Plans and limits](https://siteon.dev/docs/plans)

## Limits and what's coming

- A field with several inputs sharing one `name` (checkbox groups, `select multiple`) only sends the last value. Use one key per choice
- The error messages the script shows are currently in Japanese. Put your own wording in the success element
- Test submissions are saved as real inquiries and count toward the limit. Delete them in the dashboard afterwards
- Logging inquiries to a spreadsheet (coming soon)
- Publishing on your own domain with Siteon hosting (coming soon) (until then, the site is served on `https://<subdomain>.siteun.com/`, or you keep your current hosting; steps are in [Custom domains](https://siteon.dev/docs/domains#custom-domain))

## Related docs

- [Forms](https://siteon.dev/docs/forms): every option, redirects after submission, GTM events
- [Writing schema.json](https://siteon.dev/docs/schema): field types and constraints
- [The script tag](https://siteon.dev/docs/script): what the one line does
- [Hand off to an AI agent](https://siteon.dev/docs/agents): instructions to paste into Claude Code or Cursor

---

Siteon is infrastructure for AI-built websites: it adds hosting, a CMS your client can edit, contact forms, analytics and control from AI agents (CLI and MCP) around static HTML built with AI or by hand, so it is ready to ship.
