Tutorials

Contact Form on a Static Site Without a Backend

A static landing page can collect real enquiries without adding an application backend. This guide compares the practical options and shows how to test the full submission flow.

A static landing page can do more than display information. It can collect enquiries, demo requests, quote requests, waitlist signups, and other leads without turning the page into a full web application.

The important distinction is simple: the page itself can remain HTML, CSS, and JavaScript while form submissions are sent to a service that receives, validates, stores, and forwards the data.

That gives you a practical lead-capture workflow while keeping the site simple.

This guide explains the main approaches, what can go wrong, and how to verify that a form actually works after publication.

What a static form needs

A browser form normally starts with familiar HTML:

<form>
  <label>
    Name
    <input type="text" name="name" required>
  </label>

  <label>
    Email
    <input type="email" name="email" required>
  </label>

  <label>
    Message
    <textarea name="message" required></textarea>
  </label>

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

This markup creates the interface, but it does not decide what happens to the submitted data.

For a production form you still need four things:

  1. A destination that receives the submission.
  2. Validation and abuse controls.
  3. A clear success or error state for the visitor.
  4. A place where you can review the enquiry later.

The page can stay static while those responsibilities are handled elsewhere.

Option 1: Use a dedicated form endpoint

One common approach is to send the form to a dedicated form service.

The general pattern looks like this:

<form action="https://example.com/your-form-endpoint" method="POST">
  <input type="text" name="name" required>
  <input type="email" name="email" required>
  <textarea name="message" required></textarea>
  <button type="submit">Send</button>
</form>

This approach is useful when you already have a preferred form provider and only need a simple submission flow.

Before choosing a service, check:

The form is part of the sales path, so quota and failure behavior matter more than decorative features.

Option 2: Submit with JavaScript

A second pattern is to intercept the submit event and send the data with fetch().

<form id="contact-form">
  <input name="name" required>
  <input type="email" name="email" required>
  <textarea name="message" required></textarea>
  <button type="submit">Send</button>
</form>

<p id="form-status" aria-live="polite"></p>

<script>
const form = document.getElementById('contact-form');
const status = document.getElementById('form-status');

form.addEventListener('submit', async (event) => {
  event.preventDefault();
  status.textContent = 'Sending…';

  const payload = Object.fromEntries(new FormData(form));

  try {
    const response = await fetch('YOUR_FORM_ENDPOINT', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(payload)
    });

    if (!response.ok) throw new Error('Submission failed');

    form.reset();
    status.textContent = 'Thanks — your message was sent.';
  } catch (error) {
    status.textContent = 'Something went wrong. Please try again.';
  }
});
</script>

This gives you more control over the user experience. The page does not need to navigate away after submission, and you can show inline status messages.

But more JavaScript also creates more places for an AI edit to introduce a regression. If an assistant later changes the form ID, field names, or endpoint logic, the form can look correct while submissions silently stop working.

That is why form testing should be part of every release check.

Option 3: Let the publication platform collect the enquiry

If your publication workflow already includes forms, you can keep the lead flow inside the same project rather than adding another service.

With Deplion, the useful model is:

That reduces the number of moving parts between the landing page and the enquiry inbox.

A practical prompt to an MCP-connected assistant can be as direct as:

Add a contact form to this landing page with fields for name, email, company, and message.
Keep the existing visual style.
Make every field properly labelled and validate the email field.
Publish the updated version through Deplion, then tell me how to verify that a real submission appears in the project leads.

The assistant remains responsible for editing the page. Deplion handles the published version and the resulting enquiry workflow.

Do not put secrets in the browser

Static JavaScript is visible to visitors.

That means API keys, private tokens, database credentials, and administrative secrets do not belong in the page source.

This is unsafe:

const PRIVATE_API_KEY = 'sk_live_example';

Anything shipped to the browser should be treated as public.

If a service requires a private credential, the request needs to pass through a trusted server-side component or through a form system designed to accept public submissions safely.

Validation: browser checks are useful, but limited

HTML validation improves usability:

<input
  type="email"
  name="email"
  required
  autocomplete="email"
>

You can also add minimum lengths and patterns where appropriate:

<textarea
  name="message"
  required
  minlength="20"
  maxlength="2000"
></textarea>

These rules help legitimate visitors, but they are not a complete abuse-control system. Automated requests can bypass the visible form entirely.

The receiving service should still apply its own validation, rate limits, and spam protections.

Build accessible success and error states

A common mistake is to make the form technically functional but unclear to the user.

After clicking Send, the visitor needs to know what happened.

A simple accessible status element works well:

<p id="form-status" role="status" aria-live="polite"></p>

Good success text is specific:

Thanks — we received your message and will reply by email.

Good error text tells the visitor what to do next:

We could not send the form. Please try again or contact us by email.

Avoid making a disabled button or a color change the only signal.

Test the form as a real visitor

Do not verify a lead form only in the editor or preview.

After publishing, run a real submission from the public page.

Use a test value that is easy to identify:

Name: Form Test 2026-08-20
Email: [email protected]
Message: Production form verification. Please ignore.

Then confirm all of the following:

The final check is the received enquiry, not the animation on the button.

Re-test after AI edits

AI-assisted editing makes iteration fast, but every change should be treated as a new release.

A request such as “make the form more compact” can legitimately cause the assistant to touch HTML structure, CSS selectors, or JavaScript.

The safe pattern is:

  1. Make one focused change.
  2. Preview it.
  3. Publish a new version.
  4. Submit the form once.
  5. Confirm the lead arrived.
  6. Restore the previous version if the workflow regressed.

The ability to restore a known-good version is especially useful when the page is already receiving traffic.

Which approach should you choose?

Use a dedicated form service when you already have one and want to keep it as the central destination for enquiries.

Use a JavaScript submission flow when you need a custom interaction and are comfortable maintaining the client-side logic.

Use an integrated publication-and-lead workflow when you want the AI assistant, published versions, and enquiries to stay attached to the same project.

The right answer is the smallest workflow that gives you reliable submissions and a place to act on them.

Final checklist

Before sending traffic to a static landing page with a form:

A static page does not need a full application backend to collect useful leads. It needs a reliable submission path, clear feedback, and a release process that keeps the form working as the page evolves.