Back to Explore
GuideVibeFix 编辑部Updated Oct 19, 2026

Stop Getting Chased by "When?": Public Roadmaps and Voting Walls for Vibe Projects

A public roadmap turns 'when will you build X?' from a support nightmare into a trust engine. This guide covers the five-state request lifecycle, voting-wall rules (one-vote vs weighted, anti-gaming, cold start), request dedup and merging, kanban vs timeline layouts, biweekly/monthly update cadence with changelog linking, three graceful rejection scripts, a three-table Prisma data model, and the four pitfalls that turn roadmaps into promise lists.

Photo of a planning wall covered in colorful sticky notes labeled PLAN, GOAL and PLAN B, a hand pinning a new note to the wall

Why Make Your Roadmap Public

Every vibe coder who has shipped a product knows the same nightmare: the DMs, the comments, the community chat, all repeating one sentence — "when will you support X?" The first time you answer carefully. By the tenth time you're copy-pasting. By the hundredth, you just stop reading them. Worse, users start inventing answers themselves: "the author said last month it was in progress," "the competitor already has it" — and then a wave of one-star reviews hits when you least expect it.

A public roadmap doesn't solve a planning problem. It solves an information-asymmetry problem. It kills three kinds of support cost in one move:

  • Repeated questions. "Are you building X?" gets one canonical, checkable answer. Users check the roadmap before asking, and question volume typically drops by half or more.
  • Expectation management. When users see their request sitting in "Under consideration" instead of vanishing into a void, their patience stretches dramatically. Silence is the most expensive option — it forces users to confirm you're still alive with bad reviews.
  • Decision cover. When you decline a much-requested feature, "we evaluated it, and the roadmap explains why not" beats any on-the-spot justification.

But there's a precondition: only open the roadmap after you have PMF signals. If daily actives are still under a hundred and the core flow is being rewritten every week, you'll overturn your own roadmap weekly. Going public too early is digging your own grave — users will read "Planned" as "promised," and you haven't even figured things out yet. The practical test: when people keep asking "what's next" instead of "what is this thing for," it's time.

One boundary to draw first: the roadmap is about "what we're going to build," the changelog is about "what we already shipped." The former manages expectations, the latter proves delivery. They connect to each other, but they must never be mixed into one stew — stuffing a roadmap full of shipped features destroys its value as a window into the future.

The Roadmap State Machine: A Request's Life

The most common failure mode of a public roadmap is vague states. An item labeled "considering" sits there for eight months, users ask about it and get "still considering," and eventually nobody believes a word. The fix is a strict state machine: every state has a crisp definition, transition rules, and user-facing copy:

  • Under consideration — the request is received; we're collecting votes and discussion. User-facing copy: "We see it. We're watching how many people need it — votes and comments directly affect priority." Transitions: graduates to "Planned" when votes/discussion cross the bar; moves to "Declined" when it clearly conflicts with product direction.
  • Planned — accepted and queued, but work hasn't started. User-facing copy: "Confirmed. In the queue. Note: planned is not a ship-date promise." Transitions: "In progress" when work starts; can be demoted back to "Under consideration" if interest stays cold, or moved to "Declined" on strategy shifts.
  • In progress — being built. User-facing copy: "In development. Detail suggestions are welcome in the discussion thread; the big decisions are frozen." Transitions: "Shipped" on release; "Declined" if it turns out unbuildable (technical blocker, strategy pivot) — with the reason spelled out.
  • Shipped — terminal. The item is archived automatically and linked back to the matching changelog entry, forming a complete "request → shipped" evidence chain.
  • Declined — terminal, but not a trash can. Every declined request keeps a public reason. This is the highest-trust-density part of the whole system, covered in its own section below.

The only allowed backflows are the two dashed lines: In progress → Planned (rework, rescheduling) and Planned → Under consideration (interest cooled, demoted). Shipped and Declined are terminal — no resurrections. Want to redo it? Open a new request and reference the old one. This iron rule keeps the roadmap from becoming an erasable draft.

Roadmap state machine diagram: Under consideration, Planned, In progress, and Shipped as the main states, with a Declined branch and downgrade/rework loops

Five states total — fewer is better. I've seen people build a dozen ("reviewing," "designing," "integrating"…), and maintenance cost explodes until nobody updates it after three months. Five is the ceiling, matching the five questions users actually care about: did you see it? will you build it? did you start? is it live? why not?

Building the Voting Wall: More Votes Isn't Better

The voting wall is the roadmap's input. The engineering is easy; the rules are hard — get the rules wrong and the votes become noise.

Data model: requests and votes are separate

Requests and votes must be two tables. Don't take the shortcut of storing votes as a bare number on the request. The request table holds content and status; the vote table holds "who voted for which request." Only then can you answer the questions that matter: how many of these 200 votes are from paying users? How many are from accounts registered three days ago? Are votes arriving in a burst or a steady stream? The answers determine whether the count is credible.

One person, one vote vs. weighted voting

Default to one person, one vote: simple, explainable, hard to call unfair. But pure one-person-one-vote has a fatal flaw: voters aren't payers. Free users are loud; paying users are quiet but fund the whole thing. The compromise is weighted voting: 1 vote for regular users, 3 (or 5) for paying users — with the weighting rules published right next to the wall. The moment hidden weights get discovered, it's a trust incident.

A more radical option: monthly vote budgets. Each user gets N votes per month; spend them and they're gone until next month. This specifically cures "drive-by voting" — when votes are scarce, people actually think about whether a feature deserves one. It's a variation on what veteran tools like Canny have long practiced.

Cold start: the first 50 requests are the hardest

The awkward moment for any new voting wall: it's empty, and nobody wants to be the first to post. The fix is "seeding": turn the real requests you've received via DMs, comments, and chat over the past three months into 20–30 initial posts, attributed as "compiled from user feedback." Once users see "everyone's asks are already here," the participation barrier collapses. Never fake vote counts, though — seeded requests start at zero and grow real votes. Getting caught inflating seed votes zeroes out the wall's credibility instantly.

Anti-gaming: three lines of defense is enough

Voting walls attract more gaming than you'd think: competitors, people angling for free enterprise features, plain troublemakers. Three defenses, cheapest first:

  • Account bar. Voting requires login, and the account must be older than 7 days (or email-verified). New accounts get 0.1 vote weight or don't count toward the public total. This stops ninety percent of bot accounts.
  • Rate limits. Max 10 votes per hour per account; max 3 voting accounts registered per IP per day. Note: "limit," not "ban" — the cost of false-positiving a real user far exceeds letting a few gamers through.
  • Behavioral CAPTCHA. Only triggers on anomaly patterns (20 votes in a minute). A normal user should never see one in their life. Making CAPTCHAs the default is the fastest way to drive real users away.

And one more rule: never publish the full list of who voted for what. Publish the count and optionally anonymized voter composition ("38% from paying users"). A full voter list is raw material for harassment and social engineering.

Request Dedup and Merging: The Daily Grind

In the first week of your voting wall you'll notice: the same feature requested five times by five people in five different wordings, votes scattered across five requests, each with a dozen votes, none looking important. Dedup and merging is the most routine — and most data-quality-critical — operational work on the wall.

Merge strategy for similar requests

Merging is not deleting. The merged request keeps its page but its status becomes "Merged," pointing prominently at the master request; its votes fold into the master (weighted votes carry their weight over, one-person-one-vote adds up directly). Every merge must leave a trail: who merged A into B, when, and why. The trail is public — what the merged submitter cares about most is "was my voice swallowed," and the trail is the answer.

The merge criterion is "solves the same problem," not "reads similar." Don't merge "export to PDF" with "export to Excel" — different effort, different users. But "dark mode" and "night theme" must merge. When in doubt, don't merge: a wrong merge damages trust more than a duplicate request, because the former feels like you're papering over things.

Auto-suggesting "already on the roadmap"

When a user submits a new request, the frontend should run a live similarity search and surface the 3 most similar existing requests (or roadmap items), asking: "Is this what you mean? Vote for it instead of opening a new one." This intercepts at least a third of duplicate submissions. You don't need vector search for this: title tokenization plus keyword-overlap ranking is plenty for a few thousand items; reach for embeddings only past ten thousand.

The moderator merge workflow

A solo team has no moderation team — merging is 20 minutes of your week. Fixed routine: scan new requests weekly → flag suspected duplicates → confirm each merge or keep → send the merged submitter an in-app message (template in the next section). Don't batch it monthly: the longer duplicates sit, the more scattered the votes get, and the more controversial the "vote migration" becomes.

Roadmap Page Architecture: Timeline vs. Kanban

Two mainstream layouts, each with its own trap.

Timeline suits products with a large user base and steady release cadence — one glance shows "what's coming this quarter." But its toxicity: every date on a timeline is read as a promise. A Q3 item slipping to Q4 earns you not "understanding" but "you broke your word." If you use a timeline, pair it with a disclaimer and keep the granularity coarse — "second half of 2026" is far safer than "September 2026."

Kanban (columns by state: Under consideration / Planned / In progress / Shipped) suits the vast majority of vibe projects. It promises states, not dates — an order of magnitude easier for expectation management. GitHub Projects, Trello, or Notion give you this with zero development cost. My recommendation: default to kanban, unless someone is dedicated to maintaining the schedule.

The "near / mid / far" three-horizon format

If the kanban gets too many columns, fold it into three horizons: near-term (within a month), mid-term (within a quarter), far-term (exploratory). Word the far-term column with extreme care: "exploratory directions, not commitments," never "future plans." The far-term column is where you're allowed to paint a vision — but the paint must be labeled as paint.

Required fields on every card

Roadmap cards aren't a title list. Every item needs at least these three fields, or it's a pretty piece of waste paper:

  • Problem statement (one sentence). Not "build export," but "users spend 2 hours a month manually reconciling bills; export should compress that to 5 minutes." Stating "whose problem this solves" filters out half of all impulsive asks.
  • Target users. "All users" means nothing. Write "heavy report users (~20% of paying accounts)" so readers can judge for themselves whether they're in scope.
  • Success criteria. "Shipped = success" isn't a criterion. "15% of paying users try it once within 30 days of launch" is. Success criteria are written for your future self — so you don't celebrate a launch nobody uses.

Optional but recommended: a link to the source request (so voters can trace it to the end) and an owner name. On a solo team, write your own name — a name earns more trust than "the team."

A complete card, as an example. Title: "CSV bulk import (near-term)". Problem: "users migrating from competitors re-enter 500 records by hand — two full days — and many abandon the migration halfway." Target users: "trial users migrating from competitors, ~15% of new signups." Success criteria: "within 60 days of launch, 30% of new signups use import; migration completion rate up 10 points." A card like this tells users at a glance "does this concern me," and tells you three months later "why we built it."

Communication Cadence: Frequency Beats Content

The roadmap's biggest enemy isn't wrong planning — it's going stale. A roadmap untouched for three months is worse than no roadmap: it tells users plainly that the author can't even be bothered to pretend.

Update biweekly or monthly — pick one. Biweekly suits fast-shipping products; monthly suits side projects. Which one doesn't matter; fixed and public does: "roadmap updates on the 1st of every month," printed at the top of the page, then never missed. Once the cadence is fixed, users develop a "check back on the day" habit instead of nagging you daily.

Each update does three things: newly promoted items (consideration → planned), state changes (in progress → shipped), and declined items with reasons. No essays needed — a list plus one-line notes. Short and punctual beats long and random.

Linking with the changelog

The moment an item moves from "In progress" to "Shipped," automatically attach the changelog link to the roadmap card, and reference "from request #128's votes" back in the changelog entry. This two-way link is the trust amplifier of the whole mechanism: users watch "a feature 230 people voted for actually ship," and next round's participation looks completely different. Implementation-wise it's one column — changelog_entry_id on roadmap_items, backfilled at publish time.

How to talk about delays and cuts

Delays will happen; the wording decides whether they cost trust or earn it. The template is three sentences: what happened ("building X hit a harder-than-expected dependency Y"), what the new expectation is ("pushed from this month to early next quarter"), and what users can do now ("if you can't wait, workaround Z gets you there — tutorial here"). Never announce "delayed" without the reason and the new date. An unexplained delay gets imagined as "the author quit"; a dateless delay gets imagined as "never happening."

Cutting a feature (planned → declined) is more sensitive — it gets its own section next.

Graceful Rejection: Three Ways to Say No

Saying no is the highest-skill part of a public roadmap. The data is clear: a "Declined" with a written reason damages community trust far less than an "Under consideration" left to rot in silence. Three scripts for three real situations:

One: wrong direction. "We evaluated this seriously, but it conflicts with the product's core: we're a lightweight tool for individual users, and this feature would drag the product toward enterprise complexity. We're not doing it, and won't reconsider in the future." The key: say "won't reconsider" explicitly. A clean no is kinder than a dull "maybe later."

Two: too expensive. "Building this requires rewriting the sync engine — roughly 3 months of full-time work. At our team size, taking it on means killing the other three features slated for Q3. We're keeping those three." The key: show the opportunity cost. Users don't mind hearing "we can't afford it"; they mind hearing no reason. Do the math in public — they make trade-offs too.

Three: there's already a workaround. "This scenario is actually solvable today: setting A plus workflow B covers about 80% of it — tutorial here. We're holding off on a dedicated feature; if enough people use this combo, we'll re-evaluate." The key: reject with an exit. Users want the problem solved, not necessarily solved their way.

All three share one trait: you're rejecting the proposal while affirming the problem behind it. Never write "this request has no value" — you can overrule the priority and the approach, never the user's judgment.

Also keep a "not now" record, tech-debt style: some requests aren't happening today but you know they'll be back ("revisit SSO at 100k users"). Give them a special "declined — conditional" record with the trigger spelled out: "re-evaluate when enterprise accounts exceed 50." That's not painting a vision — it's publishing your decision logic, and you'll be held to it when the condition hits.

Data Model: Three Core Tables

Every rule above eventually lands in a schema. Three tables, no more:

ER diagram of the voting wall data model: feature_requests, votes and roadmap_items tables with their relations
  • feature_requests — feature requests. status is an enum matching the state machine's five states; merged_into_id is a self-referencing FK where merged requests point at the master; vote_count is a denormalized counter maintained transactionally, so you don't COUNT(*) the whole table on every read.
  • votes — votes. UNIQUE(request_id, user_id) is the last hard line against double voting — app-layer checks can all be raced, a unique constraint can't; the weight column supports paid-user weighting.
  • roadmap_items — roadmap entries. Promoted from feature_requests, with source_request_id preserving lineage; problem_statement / target_users / success_criteria are the card's three required fields; horizon stores near/mid/far.

Reference Prisma schema (adapt naming to your project):

model FeatureRequest {
  id           String   @id @default(uuid())
  title        String
  description  String   @db.Text
  status       RequestStatus @default(CONSIDERATION)
  authorId     String
  mergedIntoId String?
  mergedInto   FeatureRequest? @relation("Merge", fields: [mergedIntoId], references: [id])
  mergedFrom   FeatureRequest[] @relation("Merge")
  voteCount    Int      @default(0)
  votes        Vote[]
  roadmapItems RoadmapItem[]
  createdAt    DateTime @default(now())
}

model Vote {
  id        String   @id @default(uuid())
  requestId String
  request   FeatureRequest @relation(fields: [requestId], references: [id], onDelete: Cascade)
  userId    String
  weight    Int      @default(1)
  createdAt DateTime @default(now())

  @@unique([requestId, userId])
}

model RoadmapItem {
  id               String   @id @default(uuid())
  title            String
  problemStatement String   @db.Text
  targetUsers      String
  successCriteria  String
  status           RoadmapStatus
  horizon          Horizon  // NEAR | MID | FAR
  sourceRequestId  String?
  sourceRequest    FeatureRequest? @relation(fields: [sourceRequestId], references: [id])
  changelogEntryId String?
  updatedAt        DateTime @updatedAt
}

enum RequestStatus { CONSIDERATION PLANNED IN_PROGRESS SHIPPED DECLINED }
enum RoadmapStatus { PLANNED IN_PROGRESS SHIPPED }
enum Horizon { NEAR MID FAR }

Vote writes must be transactional: insert the Vote row, bump voteCount by weight, let the unique constraint catch conflicts — three steps, atomic. The pseudocode is one sentence: insert into votes first, let @@unique block duplicates, then increment voteCount. Reverse the order (bump the counter, then insert) and concurrency will hand you dirty data.

Common Pitfalls: A Roadmap Is Not a Wishing Well

Pitfall one: the roadmap becomes a "promise list." The biggest one, with both legal and expectation risk. Users screenshotting your "Planned" column to demand refunds or dragging you on social media has happened. The three-part defense: a "the roadmap is our current plan, not a commitment, subject to change" notice at the top of the page; "Planned" copy never paired with specific dates; major items expressed as horizons instead of dates. The notice can't be a one-liner buried in the footer — it has to sit where every roadmap visitor sees it.

Pitfall two: competitors copying your homework. A public roadmap hands your product direction to competitors for free. The trade: the roadmap's value (trust, votes, support savings) usually dwarfs the copying risk — because the roadmap says what you're building, while the real moat is how well and how fast you build it. For genuinely killer features, keep them off the public roadmap and on the internal one. Maintaining separate public and internal versions is standard practice for mature teams; a solo team should at least keep the two versions separate in their head.

Pitfall three: votes hijacked by a loud minority. Voting walls structurally favor the loud: they campaign, flood chat, manufacture momentum. Countermeasure: votes are one input, not the decision. Publish the decision formula on the roadmap page, e.g. "vote heat 40% + paying-user share 30% + strategic fit 30%." The formula can be rough, but it must be public — a public formula lets losers lose with dignity; an unpublished "holistic assessment" makes everyone suspect a rigged game. Also do a quarterly review of "high votes but not built," with the reasons published — that's what keeps the voting mechanism alive.

Pitfall four: stuffing the roadmap to look busy. More roadmap items make the page look "active," tempting people to list "changed a button color" as a roadmap item. A roadmap is a strategy communication tool, not a work log. The test: is this item worth a user clicking into? If not, leave it out. Keep the roadmap at 10–20 items; past 30, nobody reads it.

Three Steps Starting Today

Don't try to ship the voting wall + roadmap + auto-linking all at once. The solo-team way is three steps:

  1. This week: build a five-state kanban in Notion / GitHub Projects, lay out the 10 things already in your head as Under consideration / Planned / In progress, each with problem statement, target users, and success criteria. Publish the link. Done.
  2. Next month: add minimal voting — GitHub Discussions 👍 reactions are enough, or a "want this" button on each card. Get it running, collect real vote data, then decide whether you need weights and anti-gaming.
  3. After 100 real votes: build the standalone voting wall on this article's data model, adding dedup merging, auto-suggest, anti-gaming, and changelog linking one at a time.

A public roadmap's essence is turning "I'm seriously building this product" into a verifiable fact. Users don't need every request fulfilled — they need three things: my voice was heard, decisions have reasons, promises get answers. Deliver those, and the roadmap becomes your cheapest growth tool.

Views 0Comments 0

Comments (0)

ME
0/1000
Loading comments...
Browse projectsPublish your project

Related articles

Leaderboard product UI screenshot showing user rankings, points and badge displays
Guide
Gamification for Vibe Projects: Points, Badges, Leaderboards, and Anti-Cheat

Points, badges, leaderboards, streaks: a solo-dev playbook for making users come back on their own — append-only ledgers, idempotent awards, Redis Sorted Set boards, timezone-safe streaks, three-layer anti-cheat, and a shutdown plan.

Backend EngineeringIndie DevelopmentProduct Strategy
Photo of a security researcher at work, with bug bounty related content on the computer screen
Guide
Bug Bounty Operations for Vibe Projects: From Pricing to Payout

A bounty program burns budget to save you from incidents. This guide covers when to launch, how to price, how to write scope, how to set up disclosure channels, how to choose a platform, how to triage and deduplicate, how to filter AI slop reports, how to communicate with hunters, and how to set remediation SLAs — a complete, ready-to-run bounty operations playbook for vibe projects.

DeploymentProject BuildingStartup Journey
A customer holding a smartphone with five gold stars, a smiley face, and a checkmark icon floating above it — a five-star rating satisfaction concept
Guide
Trust by the Numbers: Engineering a Rating & Review System for Vibe Projects

The little '4.8 stars' line is one of the highest-converting UI elements on your site — and the easiest to fake. This guide covers the four aggregation algorithms (simple, Bayesian, Wilson, time-decay), one-review-per-user writes, verified-purchase write-backs, four-layer anti-gaming, review moderation, and a launch SOP for ratings you can trust.

PerformanceDatabaseBackend Engineering