Workers & Cloud Functions: Server-Side Power for Static WebHaste Sites

Static sites are fast, secure, and easy to host — exactly the kind of output WebHaste is built for. But even the best static site eventually runs into a “wait… I need a server for that” moment.
That might be as simple as processing a contact form. Or it might be more advanced: pulling live data from a third-party API, showing database-driven content, or running business logic you don’t want exposed in front-end JavaScript.
That’s where workers and cloud functions come in.
A Note About Simplicity
Many "I need a server to do something" issues can be handled by incorporating third-party services for things like email opt-in, forms and even database listings. We'd generally recommend looking at these off-the-shelf services, which can be added to your site via an embed or iFrame, before creating your own worker.
What are workers and cloud functions?
At a high level, they’re small server-side scripts you deploy to a hosting provider. Your static site calls them when it needs something dynamic.
For this article, we’ll be Cloudflare-first (the concepts apply broadly), and we’ll keep it generic so you can use the same pattern no matter what you’re hosting.
The pattern is the same:
- Your WebHaste site stays static (HTML/CSS/JS).
- A form submit or JavaScript request calls an endpoint.
- The worker/function runs server-side code.
- It returns a response (JSON, HTML, redirect, etc.).
A security note: keep your worker close to your site
To prevent cross-site security issues, it’s best to run your worker on the same hosting provider as your main website (Cloudflare, Netlify, Google, etc.).
In some cases, you may want to attach the worker to a subdomain of your main site, like:
actions.mysite.comapi.mysite.com
This keeps your requests “same-site” (or at least same-parent-domain), which makes CORS, cookies, and security policies easier to manage.
When do you actually need server-side code?
A good rule of thumb:
- Use static when the content is the same for everyone and can be generated at publish time.
- Use a worker/function when you need to accept input, keep secrets, or fetch data at request time.
Common “you need a worker” triggers:
- Form submissions (contact, newsletter, quote requests)
- Calling third-party APIs that require a secret key
- Reading/writing database data
- Webhooks and integrations
The simplest real-world use case: handling a form POST
A classic static-site problem: you can build a form in HTML, but you need something to receive the submission.
In WebHaste, you’d typically add the form markup as a block, then in code view set the form’s
action to your worker endpoint.
Here’s an example form:
<form action="https://your-worker.your-subdomain.workers.dev" method="POST">
<label for="name">Name:</label>
<input type="text" id="name" name="name" required />
<label for="email">Email:</label>
<input type="email" id="email" name="email" required />
<label for="message">Message:</label>
<textarea id="message" name="message" required></textarea>
<button type="submit">Send</button>
</form>
When the user hits Send, the browser makes a POST request to your worker.
What should the worker do?
Your worker can:
- Validate the input
- Store it in a database
- Send an email notification
- Push it into a CRM
- Trigger a webhook
…then send the user back to your static site with a clean redirect to a thank-you page.
Example: a Cloudflare Worker script to process the form
Below is a simple JavaScript worker that:
- Handles
OPTIONS(useful if you later submit viafetch()/ AJAX) - Accepts
POSTform submissions - Validates required fields
- Redirects to a static “submitted” page
export default {
async fetch(request, env, ctx) {
// Handle CORS preflight requests if submitting via fetch/AJAX
if (request.method === "OPTIONS") {
return new Response(null, {
headers: {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "POST",
"Access-Control-Allow-Headers": "Content-Type",
},
});
}
if (request.method === "POST") {
try {
const formData = await request.formData();
const name = formData.get("name");
const email = formData.get("email");
const message = formData.get("message");
// Perform basic validation
if (!name || !email || !message) {
return new Response("Missing required fields", { status: 400 });
}
// Process your data here (send email, save to database, etc.)
// Redirect the user to your static thank-you page
return Response.redirect("https://mysite.com/submitted", 303);
} catch (err) {
return new Response("Invalid form data", { status: 400 });
}
}
return new Response("Method not allowed", { status: 405 });
},
};
Why redirect with a 303?
A 303 See Other redirect is a nice touch for form handling. It tells the browser:
“Thanks, now go GET this page.”
That helps avoid accidental re-submits if the user refreshes.
Where this goes next (beyond forms)
Once you’re comfortable with the pattern, workers/functions unlock a lot of “dynamic” capabilities while keeping your site static:
- Pulling live pricing, inventory, or event data from an API
- Rendering personalized content (carefully—avoid leaking private data)
- Creating lightweight search endpoints
- Generating signed URLs for downloads
- Running scheduled tasks (depending on provider)
Quick checklist: using workers with a WebHaste static site
- Put your HTML on the static site (WebHaste output)
- Deploy a worker/function on your hosting provider
- Prefer the same provider and/or a subdomain like
actions.mysite.com - Point your form
action(or yourfetch()call) at the worker endpoint - Validate input server-side
- Return JSON or redirect to a static thank-you page
Get started (free)
If you want to build a static website that can use workers for server-side processing — WebHaste is a great workflow.
Download the free extension: https://chromewebstore.google.com/detail/webhaste/ofblooflocfdegjjpgjfbefnjmjmbapa
Learn more: https://chromecms.com/
Next article
What are the best practices for website manager new to WebHaste? Next, read: Your First WebHaste Site: A Simple Checklist (coming soon).
Recent Articles