A select field, a form, and a results page. That is the whole poll. Nothing else to it.
Updated March 2026
You need a quick vote on something. Team decision, audience question, social content. Define poll options as a select field, collect anonymous votes, and show results by fetching submission counts via the public API. No backend, no real-time infrastructure. One form, one results page. Sutrena Pages hosts the site -- included with your plan. `sutrena_collect` creates each poll form and webhooks in one call.
Architecture
| Tool | Role | Cost |
|---|---|---|
| Sutrena Pages | Static site hosting (included) | Included |
| Sutrena | Vote collection, public results API | $0 (free) / $29/mo (Pro) |
Total cost: $0-$29/mo
Pro is $29/month for 100 projects and all your other work too. Build five blueprints on Pro and it is still $29/month. That is where the value is — at scale.
Each poll is a Sutrena form with a single select field. publicResults is on so anyone can fetch results. A static HTML page deployed on Sutrena Pages presents the voting interface. Fetch submission counts via the public API to display vote distribution.
Want multiple polls? Make multiple forms. Each gets its own results page. Build an index page that lists your active polls with links.
Form Definition
One required select field with the poll options. publicResults is on. No uniqueBy for anonymous polls, but you can add it if you want to limit one vote per person.
{
"name": "Community Poll",
"fields": [
{
"name": "vote",
"label": "Your Vote",
"type": "select",
"options": [
"Option A",
"Option B",
"Option C",
"Option D"
],
"required": true
}
],
"publicResults": true
}Frontend Integration
Clickable option cards with a vote button. After voting, users can see the results. Replace the form ID with yours.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Community Poll</title>
<style>
body { font-family: system-ui, sans-serif; max-width: 480px; margin: 2rem auto; padding: 0 1rem; }
.option { display: block; padding: 0.75rem 1rem; margin: 0.5rem 0; border: 2px solid #ddd;
border-radius: 8px; cursor: pointer; transition: border-color 0.2s; }
.option:hover { border-color: #2563eb; }
.option.selected { border-color: #2563eb; background: #eff6ff; }
button { width: 100%; padding: 0.75rem; margin-top: 1rem; font-size: 1rem;
cursor: pointer; background: #111; color: #fff; border: none; border-radius: 8px; }
button:disabled { opacity: 0.5; cursor: not-allowed; }
</style>
</head>
<body>
<h1>What should we build next?</h1>
<p>Pick one option. Results update live.</p>
<div id="options">
<label class="option"><input type="radio" name="vote" value="Option A" hidden /> Option A</label>
<label class="option"><input type="radio" name="vote" value="Option B" hidden /> Option B</label>
<label class="option"><input type="radio" name="vote" value="Option C" hidden /> Option C</label>
<label class="option"><input type="radio" name="vote" value="Option D" hidden /> Option D</label>
</div>
<button id="vote-btn" disabled>Vote</button>
<p id="status"></p>
<p><a href="#results">See live results</a></p>
<script>
const FORM_ID = "frm_YOUR_FORM_ID";
let selected = null;
document.querySelectorAll(".option").forEach((label) => {
label.addEventListener("click", () => {
document.querySelectorAll(".option").forEach((l) => l.classList.remove("selected"));
label.classList.add("selected");
selected = label.querySelector("input").value;
document.getElementById("vote-btn").disabled = false;
});
});
document.getElementById("vote-btn").addEventListener("click", async () => {
if (!selected) return;
document.getElementById("vote-btn").disabled = true;
const res = await fetch(
`https://sutrena.com/api/forms/${FORM_ID}/submit`,
{
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ vote: selected }),
}
);
document.getElementById("status").textContent = res.ok
? "Vote recorded. Check the live results."
: "Something went wrong. Try again.";
});
</script>
</body>
</html>Yes. sutrena_collect creates the form and webhooks in one call. sutrena_launch deploys pages with analytics. The code examples below show primitive APIs for full control, but compound tools handle most setups faster.
With no uniqueBy, yes. Sutrena rate-limits per IP to slow down rapid abuse. For stricter controls, add uniqueBy or require auth. Depends on how much you care about accuracy.
One form per poll. Build an index page with links to all active polls. Nothing fancy.
Set closesAt to an ISO datetime. After that, the form returns 410 Gone. The submissions API still works for reading results.
Yes. PATCH the form to update the options array. Existing votes stay. New submissions validate against the updated list.
No. Sutrena Pages hosts the HTML. Forms and analytics are also on Sutrena. One platform, one API key.
Sutrena is the web runtime for AI agents. Forms, Pages, Analytics, Webhooks, Automations — all through 67 MCP tools and one REST API. Your agent creates web artifacts, humans interact with them, and your agent gets the data back. Use any one feature or all of them together.
Pages
Deploy HTML instantly
Forms
Collect structured data
Automations
DSL-based pipelines with 14 step types
Analytics
Privacy-first, no cookies
Webhooks
Slack, Discord, Telegram
1. Get a trial key (no auth, no signup)
curl -X POST https://sutrena.com/api/trial2. Create anything — a page, form, automation, or analytics site
# Create a form
curl -X POST https://sutrena.com/api/forms \
-H "Authorization: Bearer st_trial_xxx" \
-H "Content-Type: application/json" \
-d '{"name": "waitlist", "fields": [{"name": "email", "label": "Email", "type": "email", "required": true}]}'
# Or deploy a page
curl -X POST https://sutrena.com/api/pages \
-H "Authorization: Bearer st_trial_xxx" \
-H "Content-Type: application/json" \
-d '{"slug": "index", "title": "My Site", "html": "<h1>Live</h1>"}'Get a trial API key instantly with no signup, or create an account for the full experience.