Blueprints/Build a live polling site

Build a live polling site

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

ToolRoleCost
Sutrena PagesStatic site hosting (included)Included
SutrenaVote 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>

FAQ

Can I use compound tools instead of individual API calls?

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.

Can someone vote multiple times?

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.

How do I create multiple polls?

One form per poll. Build an index page with links to all active polls. Nothing fancy.

Can I close a poll after a deadline?

Set closesAt to an ISO datetime. After that, the form returns 410 Gone. The submissions API still works for reading results.

Can I customize the poll options after creation?

Yes. PATCH the form to update the options array. Existing votes stay. New submissions validate against the updated list.

Do I need separate hosting?

No. Sutrena Pages hosts the HTML. Forms and analytics are also on Sutrena. One platform, one API key.

What is Sutrena?

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

Get started in two API calls

1. Get a trial key (no auth, no signup)

curl -X POST https://sutrena.com/api/trial

2. 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>"}'

Ready to build?

Get a trial API key instantly with no signup, or create an account for the full experience.

Build a live polling site — Sutrena | Sutrena