Public board (roadmap, voting, changelog)

The public board is the Canny-style, public-facing part of Usero. Turn it on and you get a page anyone can reach where they submit feature requests, upvote what others posted, and follow a roadmap of what you are building. You publish a changelog there to announce what shipped.

The board is separate from the rest of Usero. A board post is not the input that becomes an AI-authored pull request today; the PR pipeline runs off feedback from the widget, Slack, forms, GitHub issues, the API, and notes left on changelog entries. Treat the board as your public roadmap, not as the source of truth for what to build.

What it does

  • Public submissions. Anyone reaches usero.io/b/<slug>/submit, writes a request (a title and optional description, with an optional category and email), and it appears on the board. No account required.
  • Voting with no signup. Visitors upvote any post. Votes are deduped per browser (a long-lived __portal_voter cookie), so a count reflects distinct people rather than repeat clicks. Clicking the upvote again removes the vote.
  • Comments, with official replies. Each post has a comment thread anyone can join. A reply from your team is marked as official so it stands out.
  • A roadmap. You move each post through statuses you control. The ones you flag as roadmap render as the public columns at /roadmap.
  • A changelog. Announce what shipped at /changelog. Entries are authored by you, not auto-generated.
  • Your own domain (Pro and Team). The board lives at usero.io/b/<slug> by default; paid tiers let you point a custom domain at it.

Enable the board

  1. Open your project and go to the public board settings.
  2. Toggle the board on. Usero generates a board slug from your project name (you can change it; it must be unique). Your board is now live at usero.io/b/<slug>.
  3. On first enable, Usero seeds a default set of statuses and categories (below) so the board works immediately. You can edit them afterwards.

That is the whole setup for the hosted URL. Pointing a custom domain at the board is a separate step covered below.

Statuses and the roadmap

Statuses are how you run the board. Each post sits in exactly one status, and you move it as work progresses. The seeded defaults are:

Status On the roadmap? Meaning
Open No New, not yet triaged
Under Review No You are considering it
Planned Yes Committed, not started
In Progress Yes Being built now
Complete Yes (done) Shipped
Closed No Declined or a duplicate

A status flagged as a roadmap status appears as a column on the public /roadmap view. By default that is Planned, In Progress, and Complete, which gives a visitor the three-column "what is coming" picture they expect. You can add a status, rename one, delete one, and change a post's status from the board settings.

Categories (Feature Request, Bug Report, Improvement, and so on) are a separate axis for tagging what a post is about. They are also seeded on first enable and fully editable.

Target month

A target month is the month you aim to ship a post. Set it per post from the Public Board page: every row in Awaiting reply and All posts has a Target select with this month and the next twelve, plus "No target" to clear it. Once a month is set, a Public checkbox appears beside it, on by default. Turn it off to keep that post's month to yourselves without losing it.

Voters see the month as a chip next to the status on the post page, on each card on the board, and on each card on the roadmap. The chip has three states:

  • Upcoming: "Target Nov 2026". The month has not passed yet.
  • Running late: "Target Nov 2026, running late". The month has passed and the post is not in a done status. A passed month is never shown as if it were still current.
  • Moved: "Was Nov 2026, now Jan 2027", with the old month struck through. The previous month stays on record. If the new month passes too, the chip reads "Was Nov 2026, now Jan 2027, running late".

A post in a done status shows no chip; the changelog entry carries the date it shipped. Posts with Public off, or no target, show nothing.

Nothing is cleared or bumped for you when a month passes. The Public Board page shows a quiet notice, "3 posts are past their target month", listing each post with a Move link that jumps to its row so you can pick a new month or clear it. Every move shows to voters as "was X, now Y".

From an agent, set_board_post_target on the MCP server sets, moves or clears the month (YYYY-MM or null) and takes targetPublic; list_unanswered_board_posts rows include the current target and the month it moved from.

Submissions, votes, and comments

  • Submitting. The submit page asks for a title (5 to 200 characters), an optional description, an optional category, and an optional email. As the visitor types a title, the page shows similar existing posts so they can upvote instead of filing a duplicate.
  • Voting. One click to upvote, one to remove it. The per-browser cookie is the dedup key, so the count is a reasonable proxy for distinct interested people. It is not login-gated, by design: the lower the bar, the more honest the count.
  • Comments. Anyone can comment on a post. Your team's replies are marked official so users can tell an answer from the product team apart from community chatter. Use this to answer "why not" once, in public.

Hold posts for review

By default a visitor's post is public the moment they submit it. If you would rather see it first (sensitive bug reports, spam, duplicates of something already on the board), turn on Hold new posts for review in the board settings. From then on:

  • New visitor posts and comments are held. They do not show on the board, the roadmap, in search, or in vote counts until you approve them. Posts that were already public stay public.
  • The visitor sees an "Awaiting review" banner. After submitting, they land on their post's page with a note that the team reviews new posts before they appear. Only the submitter (identified by the same browser cookie that dedupes votes) can open a held post at its URL; anyone else gets a 404. A held comment shows only to its author, with an "Awaiting review" label.
  • You review from the queue. An "Awaiting review" section at the top of the public board settings lists each held post (title, excerpt, author, category, submitted time) and each held comment with the post it belongs to. For a post you can Approve, Reject, or mark it a Duplicate of an existing public post. Comments get Approve or Reject.
  • Approving publishes it. The post goes live, gets mirrored into your feedback inbox like any other board post (so it clusters and becomes PR-eligible), and if the author left an email they get a short "your post is now live" note with a link.
  • Rejecting hides it without deleting. Rejected posts sit in a collapsed list under the queue with a Back to queue action that puts them back in the queue. Nothing is emailed on reject.
  • Duplicates are closed, not shown. Marking a held post as a duplicate points it at the post you chose and keeps it off the board; it leaves the queue without being mirrored into the inbox.

Agents can work the same queue over MCP: list_pending_board_posts returns what is waiting, and moderate_board_post approves or rejects a post or comment.

Awaiting reply

The Public Board page in your project opens on an Awaiting reply list: the public posts nobody on your team has answered yet, most voted first, each with its vote count and how many days it has waited. Every row has a reply box. A reply posts on the public thread as an official response, signed with your board name, and the post drops off the list. Changing a post's status also counts as an answer. Switch to All posts for the full table.

A post is awaiting reply when all four hold: it is public, it has not been merged into another post, your team has never changed its status, and it has no official reply. Internal notes do not count.

Under Board Settings, Remind us about unanswered posts emails everyone on the workspace once when a post has had no reply for the number of days you set (7 by default, 1 to 90). Each post is included in one reminder only, and you get at most one email a day. It is off until you turn it on.

From an agent, list_unanswered_board_posts on the MCP server returns the same list with public URLs, days silent and the reminder setting. Posts held for review are not on this list; they show in the Awaiting review queue above until approved.

Vote on behalf of a user

Most requests never reach the board. They arrive in a support ticket, a sales call or an email, and the person who asked has no idea a board post already exists. Add voter logs that person as a voter on the post so the count reflects them and they hear back when the status changes. Nothing is sent at the moment you add them.

  • Where: board settings. On the Public Board page, every post shows n voters. Open it to see the list and the Add voter form: email, name (optional), a priority and a one-line note. Voters your team added show who added them and when, and can be removed; votes people cast on the board themselves cannot, so the public count stays honest.
  • Where: a feedback item. In the inbox, a feedback item with an email has Add as voter on a board post in its Actions. Pick the post, set a priority and note, done: the request that came in by email is now on the board with the person attached, and the vote points back at the original feedback. Feedback with no email cannot be added, since there is nobody to vote for.
  • Priority is three values, admin-only and off by default: Nice to have, Important, Must have. It is for your own roadmap argument ("four Must have votes from paying accounts"), not shown on the public board.
  • Note is one line, private to your team, and lives on the vote itself: "asked on the renewal call", "ticket #1182". It is the why, kept next to the who.
  • What the voter receives, and when. When you change a post's status, the settings page asks Email all n voters about this (on by default) with an optional note. Every voter with an email gets one "status update to voters" message naming the board, the post, the old and new status and your note, with a link to the post and an unsubscribe link. The same status twice never sends twice, and an unsubscribed address is never written to again. The email says "a request you're following", not "your post", because the voter may not have written it.
  • Public board. The count goes up. Names are never listed on the public post, for board votes or added ones.
  • Demand. Voters with an email count toward cluster demand, so a request logged from three tickets weighs like three people, because it is.

From an agent, the same two actions are MCP tools: add_post_vote (postId, email, optional name, priority, note, sourceFeedbackId) and list_post_voters (postId). Example, from Claude Code or Cursor with the Usero MCP connected:

text
Add priya@northwind.app as a Must have voter on the "Dark mode" post, note: asked on the renewal call.

The agent calls add_post_vote and reports the new count, or alreadyVoter: true if she was already on it. See the MCP docs for the full tool table.

Votes by company

For a B2B product, twenty votes from one customer is a different signal from twenty votes across twenty customers. Votes by company shows both. On the Public Board page every post reads 14 voters, 6 companies, the All posts list sorts by Most companies, and opening a post's voters groups them by company with the people underneath: "14 voters from 6 companies, 9 must-have". Switch to Everyone for the flat list.

How a voter gets a company:

  • identify() traits first. If you identify users with the widget or SDK, Usero reads the first of company, companyName, company_name or organization. Send companyId (or company_id) too and people are grouped by that id, so "Acme" and "Acme Inc" stay one company.
  • Then the work email domain. A voter with no company trait is grouped by their email domain (sam@globex.com joins globex.com), marked "from email domain".
  • Free-mail addresses count as individuals. gmail.com, outlook.com and the like are never treated as a company. Those voters sit under Individuals, and votes cast on the board with no email sit under Anonymous.
  • MRR once per company. If you send MRR with identify(), each company shows it once (for example $1.2k/mo), so three people from one account never triple its revenue.
  • Live, not frozen at vote time. Companies and MRR are read from your people data every time you open the page, so a customer who upgrades after voting shows their current MRR.
  • Admin only. Companies never appear on the public board. list_post_voters on the MCP server returns each voter's company and the same per-company summary.

Demand on the ticket

Every post submitted on the board also lands in your inbox as a feedback item. Once its post has 2 or more votes, any issue or pull request Usero writes for that item carries a Demand section right under the user's comment, so the engineer sees who asked without opening Usero. It goes into Create issue on the feedback page, create_issue on the MCP server, issues created automatically, and AI pull requests.

On Linear, Jira and private GitHub repos it shows the whole picture:

text
### Demand

**14 votes from 6 companies** on the public board, $4k MRR (as of 19 Oct 2026)

Must have 5 · Important 2 · Nice to have 1

Companies: Northwind Traders ($2.5k), Acme ($1.2k, 3 votes), Umbrella Corp ($300), globex.com (2 votes), hooli.com, +1 more

Also 3 voters with no company, 2 anonymous

> "We can't pass our security review without SSO." Maya, Acme

[Public post] · [All 14 voters in Usero]
  • Companies and MRR follow the votes by company rules above (MRR once per company), sorted by MRR, then votes, top 5.
  • Quotes are the two most recent comments from people outside your team, word for word, with first name and company.
  • No email addresses, ever. An address someone typed into a comment shows as [email removed].
  • A snapshot. The "as of" date says when it was written. The issue is not updated as more votes come in.

On a public GitHub repo, or one whose visibility Usero cannot check, it shows counts only, because a company name in a public issue tells the world who your customers are:

text
### Demand

**14 votes from 6 companies** on the [public board post](...) (as of 19 Oct 2026)

Who voted and what they pay: [view in Usero](...) (team only)

The Create issue modal says what went in, under the description: "Includes demand from 14 voters. No names or MRR, since the repo is public." Edit or delete the section before you create the issue if you like. Over MCP, demandDetail: "counts" or "none" asks for less; nothing adds company detail to a public repo.

Changelog

The changelog at /changelog is where you announce shipped work. Entries have a type (feature, improvement, fix, or announcement) and are published by your team from the changelog admin in your project. Marking a post Complete does not automatically create a changelog entry; the two are separate so you control exactly what gets announced and how it is worded.

Published entries also feed the What's new tab in the feedback widget, so users can read them in your app without visiting the board.

Reactions and notes on entries

Every published entry collects engagement, with no setup:

  • Reactions. Each entry (on the changelog index and on its own page) shows a three-way reaction row: Great, Okay, Not for me. Reacting is anonymous and one click, deduped per browser; clicking again changes or withdraws the reaction. Zero counts are hidden on the public page.
  • Written notes. Under the reactions on the entry page is a note box with optional email and name fields. A submitted note arrives in your feedback inbox as an item with source Changelog, linked to the entry it was left on. From there it behaves like any other feedback: it clusters with related reports and can go to an AI-drafted pull request. The reader sees a confirmation saying the note went to your inbox, and if they left an email, replies and requester notifications can reach them.
  • Engagement on the admin page. The changelog admin shows a per-entry line with reaction counts by sentiment and the number of notes the entry sent to the inbox.

Drafts and unpublished entries collect nothing.

Drafting from shipped pull requests

If your project has a connected GitHub repo, the changelog admin shows every merged Usero pull request that has not been announced yet. Tick the ones you want, click Draft changelog entry, and Usero writes a draft grouped by type, with each change traced back to the request that caused it. The draft is unpublished, so you edit the wording before anyone sees it.

Entry bodies are markdown. Headings, bullets, bold, links, inline code, and tables all render on the public entry page. Raw HTML in the body is shown as text rather than markup, and link URLs are limited to http, https and mailto.

Telling the people who asked

When you publish an entry, Usero emails the users whose feedback led to the work. It follows the chain the data already has: entry → the merged pull requests linked to it → the feedback that caused each one → the email on that feedback.

  • You see the list before you send. Each draft in the changelog admin shows how many distinct people publishing would email and a sample of the addresses. The publish button reads Publish & notify N, and asks for a confirm.
  • One email per person, not per request. Someone who filed three of the shipped items gets a single email listing all three, quoting their own words back to them, with a link to the public entry.
  • Nobody is emailed twice. Two guards run: the entry itself is stamped once its announcement goes out, so unpublishing and republishing does not re-send, and each piece of feedback is stamped once it has been announced, so a later entry that links the same feedback skips that person.
  • Requesters who left no email address are skipped. Anonymous feedback has nobody to write to, so it is not counted in the preview.
  • Recipients can unsubscribe. Every email carries an unsubscribe link, and an unsubscribed address is never written to again from any Usero notification.

Turning it off. Requester emails share the "notify submitters" opt-in in your project settings with the "your feedback was resolved" email, so one switch controls whether Usero may write to your end users at all. With it off, publishing is silent and the changelog admin says so on any draft that has requesters behind it.

Replies go to your team. Set a reply-to address in project settings, or Usero uses the account owner's email.

Email subscriptions

Anyone can follow your changelog by email, not just the people whose requests shipped. The public changelog page shows a subscribe field (when the "notify submitters" opt-in above is on; with it off, the form is hidden so there is never a subscribe button that goes nowhere).

  • Confirmation first. Entering an email sends a confirmation link. Only confirmed addresses are subscribed, so a typo or a prank never signs someone up. The page shows the same "check your inbox" message whether or not the address was already subscribed, so the form cannot be used to probe who is on the list.
  • What subscribers receive. Each published entry, as one email: the title, the summary, and a link to the entry on your changelog. Subscribers whose own feedback shipped in the entry are deduped out and get the personal requester email instead.
  • The counts are visible before you publish. The publish confirmation shows requesters and subscribers separately, and the button totals them: Publish & notify N.
  • One-click unsubscribe. Every subscriber email has an unsubscribe link that works in one click and offers resubscribe in case it was a misfire. Unsubscribed addresses are never written to again, and resubscribing requires a fresh confirmation.

Weekly digest

Subscriber emails are a cadence choice on the changelog admin page: on every publish (the default, described above) or as a weekly digest, one release notes email bundling the week's published entries on the day you pick. Never both, so switching cadence can never double-email anyone. Requester emails are unaffected: people whose own feedback shipped still get the personal email at publish time.

  • A draft lands first. The evening before the send day, the project owner receives the digest exactly as subscribers will see it, with the recipient count and a one-click skip link. Skipping needs no login and can be undone until the send hour.
  • Empty weeks send nothing. No published entries, or no confirmed subscribers, means no draft and no digest. The admin page says so instead of going quiet.
  • The state lives in the product, not your inbox. The changelog admin page always shows the next digest (send day, entries queued so far, subscriber count, when the draft goes out) and the last outcome: sent to N, skipped, or nothing to publish.
  • A digest that could not send within 48 hours of its scheduled time is dropped, never sent late.

RSS feed

Every board publishes its changelog as RSS 2.0 at /b/<slug>/changelog/rss.xml (or the same path on your custom domain). There is an RSS button on the changelog page. The feed carries the 50 most recent published entries, newest first, with the title, permalink, publish date, entry type as the category, the author, and the full rendered body. Nothing is gated: readers, Slack RSS apps, and Zapier can subscribe without an account.

Custom domain (Pro and Team)

On the Pro and Team plans you can serve the board from your own domain instead of usero.io/b/<slug>:

  1. In the project settings, open the custom domain panel and enter the hostname you want (for example feedback.yourapp.com).
  2. Usero gives you a DNS record to add at your registrar. Add it, then return and let Usero verify it.
  3. Once the hostname is verified, your board is reachable on your domain. The board must be enabled and have a slug for the domain to resolve to it.

Your domain serves only your own public pages: your board at /b/<slug> (with its roadmap, changelog, posts, submit page and RSS feed) and your Usero forms at /f/<form-slug>. The bare domain (/) redirects to the board, and so does any other path, such as /pricing or another project's board. If the board is off, those other paths return a plain "not available" page, and your forms still work. Usero's own site never appears on your domain.

The custom domain is gated to the paid tiers. The free board uses the usero.io URL.

Where the board fits (and where it does not)

The board is the public roadmap. It is the right tool for showing users their request is logged, letting them vote, and closing the loop with a changelog. It is the wrong tool for deciding what to build on its own: most users never post on a board, so the vote count over-weights the vocal minority. Read it as one input among several, and get the quiet majority from the widget, support, and reaching out to users directly.

Board posts are also not connected to the AI-PR pipeline. Feedback that clusters and can open a GitHub pull request comes from the widget, Slack, forms, GitHub issues, the API, and notes on changelog entries, not from board posts. See feedback clustering and the GitHub integration for that path.

Next