An HTML contact form needs somewhere to send its messages. With Pagelet Pro, your published page can send them directly to a private inbox inside Pagelet. You can receive enquiries, registrations or booking requests without building a server or connecting another form service.
Pro includes 500 accepted submissions per calendar month, shared across all sites in your account, plus optional email notifications. The allowance resets on the first day of each month at 00:00 UTC.
1. Enable reception on your site
Start with an HTML site you own in your Pagelet dashboard. If you haven't published one yet, follow our HTML hosting guide.
- Find the site and open More actions → Form submissions.
- Enable Accept form submissions on this site.
- Leave Email me when a submission arrives checked if you want notifications.
- Click Save settings.
You need an active Pro plan to enable reception. PDF publications cannot contain an HTML form; publish an HTML page if you need to collect responses.
2. Copy the form HTML
The Connect your form section gives you a ready-to-copy example with the correct receiving address for that specific site. Use that example, or adapt the complete page below.
Replace YOUR_SITE_ID in the action address with your site's ID, using the exact address shown in your dashboard. This is a site ID, not your subdomain name. The receiving address continues to work if you rename the site's subdomain.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Contact us</title>
<style>
body { font: 16px/1.6 system-ui, sans-serif; margin: 0; background: #f7f7f7; color: #393737; }
main { max-width: 540px; margin: 48px auto; padding: 24px; }
label { display: block; margin: 18px 0; }
input, textarea, button { box-sizing: border-box; width: 100%; padding: 12px; font: inherit; }
input, textarea { display: block; border: 1px solid #ccc; border-radius: 12px; }
button { border: 0; border-radius: 999px; background: #393737; color: white; cursor: pointer; }
</style>
</head>
<body>
<main>
<h1>Contact us</h1>
<p>Tell us what you have in mind and we will get back to you.</p>
<form id="contact-form" action="https://pagelet.host/forms/YOUR_SITE_ID" method="POST">
<input type="hidden" name="__pagelet_form" value="Contact">
<input type="text" name="__pagelet_honeypot" hidden
tabindex="-1" autocomplete="off">
<label>Your name
<input name="name" autocomplete="name" maxlength="200" required>
</label>
<label>Email address
<input name="email" type="email" autocomplete="email" maxlength="254" required>
</label>
<label>Message
<textarea name="message" rows="5" maxlength="4000" required></textarea>
</label>
<button type="submit">Send message</button>
</form>
<p id="form-status" role="status" aria-live="polite"></p>
</main>
</body>
</html>
Save it as index.html and publish it to the same Pagelet site whose receiving address you copied. For an existing page, update its form HTML in your source file and save it back to that site.
Every field you want to receive needs a name attribute. Its name becomes the field label in your inbox. A field with only an id will not be sent. Repeated names, such as multiple checked options, are kept together.
The hidden __pagelet_form field names the form. Use names such as Contact, Class registration or Booking request to distinguish several forms on one site. Keep the __pagelet_honeypot field empty and hidden; it helps discard automated spam.
If you are replacing FormSubmit or another service, update the action and remove any old JavaScript that intercepts submission and sends data elsewhere. Changing the action alone does not replace a JavaScript form handler.
3. Test from your published page
Open the page on its Pagelet address or its verified custom domain. Fill in the form with test information and click Send message.
For a standard HTML form, Pagelet displays a confirmation page after the message is stored. There is no need to install a script. Submitting a local file or a copy hosted on another website will fail the published-origin check.
Return to More actions → Form submissions. You should see the form's name, the received time in UTC and every submitted text field. Your test counts as one accepted submission.
If notifications are enabled and email delivery is available, Pagelet emails the account owner a link to the private inbox. Submitted field values stay in the inbox rather than appearing in the notification email. A delayed email does not remove a saved submission.
4. Read and export responses
The inbox is private to the account that owns the site. Use Mark read to clear a message's New badge, Export CSV to download that site's responses, or Delete to permanently remove a message.
Messages are shown newest first, with Older and Newer controls when there are more than 25. The usage counter covers your whole account, even when you are looking at one site's inbox.
Deleting a message or a site does not replenish the monthly allowance. When the account reaches 500 accepted submissions, further sends receive an error and are not stored. Reception becomes available again after the monthly reset, provided Pro and the site's reception setting remain active.
Ask ChatGPT or Claude to adapt your form
Copy the receiving address from your site's Form submissions page and use this prompt:
Adapt the HTML form on this page to receive submissions with Pagelet. Use the exact receiving address I provide as the form action and method POST. Give every field a name attribute. Add a hidden __pagelet_form field named Contact and an empty hidden __pagelet_honeypot input. Remove any existing JavaScript submission handler or third-party form endpoint. Keep my page's design and use a standard HTML form without JavaScript. Here is my receiving address: [paste the address from my Pagelet dashboard].
Then publish the updated HTML and run the test above. You can also follow our guides to create a website with ChatGPT or publish with Claude.
Optional: keep visitors on your page with JavaScript
Send Accept: application/json to receive JSON instead of a confirmation page. This example uses FormData to preserve repeated fields; the same address also accepts a JSON object of text fields. The complete HTML example above already has the contact-form and form-status IDs used here:
const form = document.getElementById('contact-form');
const status = document.getElementById('form-status');
const button = form.querySelector('button[type="submit"]');
form.addEventListener('submit', async (event) => {
event.preventDefault();
if (!form.reportValidity()) return;
button.disabled = true;
status.textContent = 'Sending…';
try {
// FormData preserves repeated field names, such as checkbox groups.
const response = await fetch(form.action, {
method: 'POST',
headers: { Accept: 'application/json' },
body: new FormData(form)
});
const result = await response.json();
if (!response.ok || !result.received) {
throw new Error(result.error || 'Your message could not be sent.');
}
status.textContent = 'Thank you. Your message has been received.';
form.reset();
} catch (error) {
status.textContent = error.message || 'Please try again later.';
} finally {
button.disabled = false;
}
});
Add this script before </body>. If you are adapting your own page, give the form id="contact-form" and add <p id="form-status" role="status" aria-live="polite"></p> below it. Use either the standard HTML flow or this optional handler, and test from the site's published address.