<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Hareesh Vemasani</title>
    <description>The latest articles on DEV Community by Hareesh Vemasani (@hareesh_vemasani).</description>
    <link>https://dev.to/hareesh_vemasani</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3691403%2Fd9794d57-67f6-4911-90fb-c4f95118092d.jpg</url>
      <title>DEV Community: Hareesh Vemasani</title>
      <link>https://dev.to/hareesh_vemasani</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/hareesh_vemasani"/>
    <language>en</language>
    <item>
      <title>I Built a Canny Alternative — Then Realized the Feedback Board Was the Easy Part</title>
      <dc:creator>Hareesh Vemasani</dc:creator>
      <pubDate>Fri, 24 Jul 2026 11:44:49 +0000</pubDate>
      <link>https://dev.to/hareesh_vemasani/i-built-a-canny-alternative-then-realized-the-feedback-board-was-the-easy-part-pje</link>
      <guid>https://dev.to/hareesh_vemasani/i-built-a-canny-alternative-then-realized-the-feedback-board-was-the-easy-part-pje</guid>
      <description>&lt;p&gt;Almost every customer-feedback product starts with the same three features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A feedback board&lt;/li&gt;
&lt;li&gt;An upvote button&lt;/li&gt;
&lt;li&gt;A public roadmap&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Technically, none of these is particularly difficult to build.&lt;/p&gt;

&lt;p&gt;Create a table for posts. Add a vote count. Display the posts in columns based on their status.&lt;/p&gt;

&lt;p&gt;You now have the first version of a Canny alternative.&lt;/p&gt;

&lt;p&gt;But after running SaaS products and speaking with other founders, we realized that collecting feedback was not the real problem.&lt;/p&gt;

&lt;p&gt;The real problem was everything that happened before and after someone clicked &lt;strong&gt;Submit&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Feedback was arriving through:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Support conversations&lt;/li&gt;
&lt;li&gt;Slack messages&lt;/li&gt;
&lt;li&gt;Customer calls&lt;/li&gt;
&lt;li&gt;Emails&lt;/li&gt;
&lt;li&gt;App reviews&lt;/li&gt;
&lt;li&gt;Sales conversations&lt;/li&gt;
&lt;li&gt;Public feedback boards&lt;/li&gt;
&lt;li&gt;Random screenshots shared internally&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The same request could appear in five different places, written five different ways.&lt;/p&gt;

&lt;p&gt;Then someone had to manually copy it into a spreadsheet, check whether it already existed, decide how important it was, update the roadmap, publish a release note, and remember to tell the original customer that it had shipped.&lt;/p&gt;

&lt;p&gt;Most teams did only the first step.&lt;/p&gt;

&lt;p&gt;So we built &lt;strong&gt;&lt;a href="https://productbridge.io/" rel="noopener noreferrer"&gt;ProductBridge&lt;/a&gt;&lt;/strong&gt; around the entire feedback loop—not just the voting board.&lt;/p&gt;

&lt;h2&gt;
  
  
  What ProductBridge Does
&lt;/h2&gt;

&lt;p&gt;ProductBridge gives SaaS teams one place to:&lt;/p&gt;

&lt;h3&gt;
  
  
  Collect feedback
&lt;/h3&gt;

&lt;p&gt;Customers can submit feedback through public or private boards, in-app widgets, integrations, APIs, and connected support channels.&lt;/p&gt;

&lt;p&gt;Feedback can also be pulled automatically from tools where customer conversations are already happening.&lt;/p&gt;

&lt;h3&gt;
  
  
  Organize it with AI
&lt;/h3&gt;

&lt;p&gt;Incoming feedback is analyzed, categorized, summarized, and checked for duplicates.&lt;/p&gt;

&lt;p&gt;Instead of showing product managers 37 slightly different posts asking for the same thing, the system can connect them to one underlying request.&lt;/p&gt;

&lt;h3&gt;
  
  
  Find patterns
&lt;/h3&gt;

&lt;p&gt;Teams can use Ask AI to explore their customer feedback in natural language.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What are the biggest problems reported by enterprise customers this month?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Or:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Which requests are mentioned by customers at risk of churning?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The goal is not to let AI make the roadmap.&lt;/p&gt;

&lt;p&gt;The goal is to remove the hours of manual work required before a product manager can make a good decision.&lt;/p&gt;

&lt;h3&gt;
  
  
  Build a roadmap
&lt;/h3&gt;

&lt;p&gt;Accepted ideas can move directly into public, private, or customer-segmented roadmaps.&lt;/p&gt;

&lt;p&gt;Teams can show customers what is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Under review&lt;/li&gt;
&lt;li&gt;Planned&lt;/li&gt;
&lt;li&gt;In progress&lt;/li&gt;
&lt;li&gt;Completed&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Publish changelogs
&lt;/h3&gt;

&lt;p&gt;When a feature ships, the team can turn it into a changelog entry and distribute it through a public page, email, or an in-app widget.&lt;/p&gt;

&lt;h3&gt;
  
  
  Close the loop
&lt;/h3&gt;

&lt;p&gt;The people who submitted or voted for the request can be notified automatically when its status changes.&lt;/p&gt;

&lt;p&gt;This sounds like a small feature.&lt;/p&gt;

&lt;p&gt;In practice, it is one of the most important parts of the product.&lt;/p&gt;

&lt;p&gt;Customers do not stop submitting feedback because a company rejected their idea.&lt;/p&gt;

&lt;p&gt;They stop submitting feedback because they believe nobody is listening.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Simplified Architecture
&lt;/h2&gt;

&lt;p&gt;At a high level, ProductBridge has six layers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Feedback sources
      ↓
Ingestion and normalization
      ↓
AI analysis and deduplication
      ↓
Feedback repository
      ↓
Roadmap and delivery workflow
      ↓
Changelog and customer notifications
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each layer solves a different problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Normalize Everything Into One Feedback Model
&lt;/h2&gt;

&lt;p&gt;A message imported from Slack looks nothing like an App Store review.&lt;/p&gt;

&lt;p&gt;A support ticket contains conversation metadata.&lt;/p&gt;

&lt;p&gt;A public-board post contains votes.&lt;/p&gt;

&lt;p&gt;An API submission might contain custom fields from the customer’s CRM.&lt;/p&gt;

&lt;p&gt;Before we can analyze any of this, it needs to be converted into a common internal structure.&lt;/p&gt;

&lt;p&gt;A simplified version looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;FeedbackItem&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;organizationId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nl"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nl"&gt;source&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;portal&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;widget&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;slack&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;support&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;review&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;api&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nl"&gt;sourceReference&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nl"&gt;customerId&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;companyId&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nl"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;new&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;reviewing&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;planned&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;in_progress&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;completed&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nl"&gt;categoryIds&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;
  &lt;span class="nl"&gt;tagIds&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;

  &lt;span class="nl"&gt;sentiment&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;positive&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;neutral&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;negative&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nl"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every ingestion source converts its input into this structure.&lt;/p&gt;

&lt;p&gt;That lets the rest of the system work without needing to understand where the feedback originally came from.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Make Every Integration Idempotent
&lt;/h2&gt;

&lt;p&gt;Integrations retry.&lt;/p&gt;

&lt;p&gt;Webhooks can be delivered twice.&lt;/p&gt;

&lt;p&gt;Users reconnect accounts.&lt;/p&gt;

&lt;p&gt;Background jobs fail halfway through processing.&lt;/p&gt;

&lt;p&gt;Without idempotency, the same support conversation can become three separate feedback posts.&lt;/p&gt;

&lt;p&gt;Every imported item therefore needs a stable external reference:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;existing_item&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;find_by_source_reference&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;organization_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;organization_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;slack&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;source_reference&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;message_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;existing_item&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;update_existing_item&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;existing_item&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;create_feedback_item&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This looks simple, but it becomes more complicated when a single conversation contains several distinct requests.&lt;/p&gt;

&lt;p&gt;One Slack thread might include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A bug report&lt;/li&gt;
&lt;li&gt;A missing integration&lt;/li&gt;
&lt;li&gt;A pricing complaint&lt;/li&gt;
&lt;li&gt;A workaround suggested by support&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Treating that entire conversation as one feedback item makes later analysis much less useful.&lt;/p&gt;

&lt;p&gt;The ingestion layer has to preserve the source while still breaking the conversation into meaningful observations.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Detect Intent, Not Just Matching Words
&lt;/h2&gt;

&lt;p&gt;Keyword-based duplicate detection works when two users write nearly identical requests.&lt;/p&gt;

&lt;p&gt;It fails when one customer says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The dashboard takes forever to load.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And another says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Analytics keeps timing out when I select 90 days.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Different words. Potentially the same underlying problem.&lt;/p&gt;

&lt;p&gt;Our duplicate-detection flow combines semantic similarity with structured information such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Product area&lt;/li&gt;
&lt;li&gt;Customer segment&lt;/li&gt;
&lt;li&gt;Existing categories&lt;/li&gt;
&lt;li&gt;Previously confirmed duplicates&lt;/li&gt;
&lt;li&gt;Request type&lt;/li&gt;
&lt;li&gt;Context from the original conversation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A simplified flow looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;New feedback received
        ↓
Extract the underlying problem or request
        ↓
Retrieve semantically similar existing items
        ↓
Compare intent and product context
        ↓
Attach to an existing request or create a new one
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We still keep the original customer message.&lt;/p&gt;

&lt;p&gt;AI-generated summaries should never erase what the customer actually said.&lt;/p&gt;

&lt;p&gt;The summary helps the team process feedback faster. The source remains available when deeper context is needed.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Keep Multi-Tenancy Boring
&lt;/h2&gt;

&lt;p&gt;ProductBridge is a multi-tenant SaaS application.&lt;/p&gt;

&lt;p&gt;Almost every relevant record belongs to an organization:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;feedback_items&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;organization_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;current_organization_id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That organization boundary must be enforced consistently across:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Feedback&lt;/li&gt;
&lt;li&gt;Votes&lt;/li&gt;
&lt;li&gt;Customers&lt;/li&gt;
&lt;li&gt;Roadmaps&lt;/li&gt;
&lt;li&gt;Changelogs&lt;/li&gt;
&lt;li&gt;Help-center articles&lt;/li&gt;
&lt;li&gt;Integrations&lt;/li&gt;
&lt;li&gt;API keys&lt;/li&gt;
&lt;li&gt;Webhooks&lt;/li&gt;
&lt;li&gt;Uploaded files&lt;/li&gt;
&lt;li&gt;AI queries&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A missing tenant filter is not a minor bug. It is a data-isolation problem.&lt;/p&gt;

&lt;p&gt;We therefore treat organization scoping as part of the data model and service layer rather than relying on individual UI pages to filter records correctly.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Treat Status Changes as Events
&lt;/h2&gt;

&lt;p&gt;Moving a roadmap item from &lt;strong&gt;In Progress&lt;/strong&gt; to &lt;strong&gt;Completed&lt;/strong&gt; is not just a database update.&lt;/p&gt;

&lt;p&gt;It can trigger several actions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Feature marked as completed
        ↓
Update the public roadmap
        ↓
Find related feedback posts
        ↓
Find submitters, voters, and subscribers
        ↓
Generate or request a changelog entry
        ↓
Send customer notifications
        ↓
Emit webhooks to connected systems
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We model important changes as events so that each downstream action can be retried independently.&lt;/p&gt;

&lt;p&gt;Conceptually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nf"&gt;publish_event&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;roadmap_item.completed&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;organization_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;organization_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;roadmap_item_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;roadmap_item_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Consumers can then handle:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Customer notifications&lt;/li&gt;
&lt;li&gt;Changelog preparation&lt;/li&gt;
&lt;li&gt;Integration sync&lt;/li&gt;
&lt;li&gt;Analytics updates&lt;/li&gt;
&lt;li&gt;Webhook delivery&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This prevents one failed email from blocking the underlying roadmap update.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Let AI Assist Without Owning the Decision
&lt;/h2&gt;

&lt;p&gt;Product teams do not need AI to blindly decide what they should build.&lt;/p&gt;

&lt;p&gt;A request with 500 votes is not automatically more important than a request from three high-value customers.&lt;/p&gt;

&lt;p&gt;Votes are only one signal.&lt;/p&gt;

&lt;p&gt;Other signals can include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Number of affected customers&lt;/li&gt;
&lt;li&gt;Account value&lt;/li&gt;
&lt;li&gt;Customer segment&lt;/li&gt;
&lt;li&gt;Churn risk&lt;/li&gt;
&lt;li&gt;Request frequency&lt;/li&gt;
&lt;li&gt;Sentiment&lt;/li&gt;
&lt;li&gt;Strategic alignment&lt;/li&gt;
&lt;li&gt;Implementation effort&lt;/li&gt;
&lt;li&gt;Recent growth in mentions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;AI is useful for extracting and connecting these signals.&lt;/p&gt;

&lt;p&gt;Humans still decide what enters the roadmap.&lt;/p&gt;

&lt;p&gt;That distinction shaped how we built features such as Ask AI.&lt;/p&gt;

&lt;p&gt;The assistant can summarize the evidence:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This request was mentioned by 23 customers, including four enterprise accounts. Mentions increased by 38% this month, and six customers described it as a blocker.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That is far more useful than:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;AI says you should build this.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Building an MCP Server
&lt;/h2&gt;

&lt;p&gt;We also wanted teams to access their product feedback from the AI tools they already use.&lt;/p&gt;

&lt;p&gt;So we added an MCP server.&lt;/p&gt;

&lt;p&gt;This allows compatible AI assistants to retrieve ProductBridge data and perform supported actions through a structured interface.&lt;/p&gt;

&lt;p&gt;The flow looks roughly like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Claude, Cursor, or another MCP client
                ↓
        ProductBridge MCP server
                ↓
 Authentication and organization permissions
                ↓
      ProductBridge application APIs
                ↓
 Feedback, roadmaps, and changelogs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A product manager can ask:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Show me the fastest-growing requests from enterprise customers.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A developer can ask:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Find feedback related to the feature I am currently implementing.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A founder can ask:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Draft a changelog entry for the items completed this week.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The important part is that the AI operates through authenticated tools rather than receiving an unrestricted database connection.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why We Added a Help Center
&lt;/h2&gt;

&lt;p&gt;On July 24, 2026, we launched a &lt;strong&gt;Help Center / Knowledge Base&lt;/strong&gt; inside ProductBridge.&lt;/p&gt;

&lt;p&gt;At first, a knowledge base might sound separate from feedback management.&lt;/p&gt;

&lt;p&gt;We see it as part of the same customer communication loop.&lt;/p&gt;

&lt;p&gt;Before the Help Center, ProductBridge covered:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Customer submits feedback
        ↓
Team analyzes it
        ↓
Team plans the feature
        ↓
Team ships it
        ↓
Customer receives the update
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Help Center adds another layer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Customer has a question
        ↓
Customer finds an answer
        ↓
Customer still submits feedback when needed
        ↓
Recurring questions reveal documentation or product gaps
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This creates useful connections between support content and product feedback.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Repeated support questions can become help articles.&lt;/li&gt;
&lt;li&gt;Feedback can reveal articles that are missing or unclear.&lt;/li&gt;
&lt;li&gt;Changelog entries can link to detailed setup guides.&lt;/li&gt;
&lt;li&gt;Newly released features can immediately have supporting documentation.&lt;/li&gt;
&lt;li&gt;Customers can find answers without opening another support ticket.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A feedback portal tells customers what you might build.&lt;/p&gt;

&lt;p&gt;A roadmap tells them what you are building.&lt;/p&gt;

&lt;p&gt;A changelog tells them what you shipped.&lt;/p&gt;

&lt;p&gt;A Help Center tells them how to use it.&lt;/p&gt;

&lt;p&gt;Together, they form a complete product communication system.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Tech Stack
&lt;/h2&gt;

&lt;p&gt;The simplified ProductBridge stack includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A modern React-based frontend for the application and customer-facing portals&lt;/li&gt;
&lt;li&gt;Python API services for business logic and integrations&lt;/li&gt;
&lt;li&gt;PostgreSQL for relational product and customer data&lt;/li&gt;
&lt;li&gt;Background workers for ingestion, analysis, notifications, and synchronization&lt;/li&gt;
&lt;li&gt;OpenAI and Anthropic models for AI-assisted feedback workflows&lt;/li&gt;
&lt;li&gt;AWS infrastructure in Europe&lt;/li&gt;
&lt;li&gt;Nginx for routing and application delivery&lt;/li&gt;
&lt;li&gt;Resend for transactional email&lt;/li&gt;
&lt;li&gt;REST APIs, OAuth, and webhooks for integrations&lt;/li&gt;
&lt;li&gt;MCP for connecting external AI assistants&lt;/li&gt;
&lt;li&gt;Custom-domain infrastructure for branded portals&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The exact technology behind each layer matters less than maintaining clear boundaries between them.&lt;/p&gt;

&lt;p&gt;Integrations should not write directly into roadmap tables.&lt;/p&gt;

&lt;p&gt;AI jobs should not own customer permissions.&lt;/p&gt;

&lt;p&gt;Notification failures should not roll back product-status changes.&lt;/p&gt;

&lt;p&gt;Public portals should never be able to bypass organization-level access controls.&lt;/p&gt;

&lt;p&gt;The stack helps us ship.&lt;/p&gt;

&lt;p&gt;The architecture prevents shipping quickly from turning into a permanent mess.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Was Actually Difficult?
&lt;/h2&gt;

&lt;p&gt;The voting interface was not difficult.&lt;/p&gt;

&lt;p&gt;The hardest parts were:&lt;/p&gt;

&lt;h3&gt;
  
  
  Resolving customer identity
&lt;/h3&gt;

&lt;p&gt;The same person might appear through Slack, Intercom, email, and a public portal using different identifiers.&lt;/p&gt;

&lt;p&gt;Connecting those interactions without merging the wrong users requires careful identity mapping.&lt;/p&gt;

&lt;h3&gt;
  
  
  Preserving context
&lt;/h3&gt;

&lt;p&gt;A clean AI summary is useful, but the original conversation, source, customer, and surrounding messages must remain accessible.&lt;/p&gt;

&lt;h3&gt;
  
  
  Preventing duplicate imports
&lt;/h3&gt;

&lt;p&gt;Every integration behaves differently. Reliable ingestion requires retries, idempotency, rate-limit handling, and monitoring.&lt;/p&gt;

&lt;h3&gt;
  
  
  Supporting public and private experiences
&lt;/h3&gt;

&lt;p&gt;The same organization may need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A public feedback board&lt;/li&gt;
&lt;li&gt;An internal board&lt;/li&gt;
&lt;li&gt;A private board for selected customers&lt;/li&gt;
&lt;li&gt;A roadmap visible only to one segment&lt;/li&gt;
&lt;li&gt;Anonymous submissions&lt;/li&gt;
&lt;li&gt;Authenticated SSO access&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Permissions become part of the product architecture very quickly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Closing the loop reliably
&lt;/h3&gt;

&lt;p&gt;Notifications need to reach the right people without sending duplicates or exposing information from private roadmap items.&lt;/p&gt;

&lt;h3&gt;
  
  
  Keeping pricing predictable
&lt;/h3&gt;

&lt;p&gt;Feedback tools become more valuable as more customers participate.&lt;/p&gt;

&lt;p&gt;Charging dramatically more because more users submitted feedback creates the wrong incentive.&lt;/p&gt;

&lt;p&gt;ProductBridge therefore uses flat paid plans with unlimited tracked users rather than making teams worry about every new person entering their feedback portal.&lt;/p&gt;

&lt;p&gt;The free plan includes the core workflow for teams getting started, while paid plans begin at $29 per month when billed annually.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Would Do Differently
&lt;/h2&gt;

&lt;p&gt;If I were starting again, I would define the normalized feedback model before building the first integration.&lt;/p&gt;

&lt;p&gt;It is tempting to make every integration work quickly by storing the original provider payload and handling it later.&lt;/p&gt;

&lt;p&gt;“Later” arrives after six integrations, when every feature requires source-specific conditions.&lt;/p&gt;

&lt;p&gt;I would also model major product changes as events from the beginning.&lt;/p&gt;

&lt;p&gt;Notifications, webhooks, integration syncs, analytics, and audit trails all become easier when they subscribe to explicit events instead of being embedded inside one large request handler.&lt;/p&gt;

&lt;p&gt;Finally, I would build customer identity resolution earlier.&lt;/p&gt;

&lt;p&gt;Feedback becomes significantly more valuable once you can answer:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Which accounts are asking for this?&lt;/li&gt;
&lt;li&gt;How much revenue do they represent?&lt;/li&gt;
&lt;li&gt;Is this affecting free users or enterprise users?&lt;/li&gt;
&lt;li&gt;Did the same customer mention it through another channel?&lt;/li&gt;
&lt;li&gt;Has anyone asking for it recently churned?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A vote count alone cannot answer any of those questions.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Business Case
&lt;/h2&gt;

&lt;p&gt;ProductBridge is designed for SaaS teams that have outgrown spreadsheets but do not want feedback software costs to scale unpredictably with seats or tracked users.&lt;/p&gt;

&lt;p&gt;The free plan is intended for teams validating their feedback workflow.&lt;/p&gt;

&lt;p&gt;Paid plans add capabilities such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Unlimited tracked users&lt;/li&gt;
&lt;li&gt;Unlimited feedback boards&lt;/li&gt;
&lt;li&gt;Automatic feedback ingestion&lt;/li&gt;
&lt;li&gt;Ask AI&lt;/li&gt;
&lt;li&gt;Integrations and APIs&lt;/li&gt;
&lt;li&gt;Custom domains&lt;/li&gt;
&lt;li&gt;Advanced access controls&lt;/li&gt;
&lt;li&gt;SSO&lt;/li&gt;
&lt;li&gt;MCP access&lt;/li&gt;
&lt;li&gt;Help Center and Knowledge Base functionality&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Our bet is simple:&lt;/p&gt;

&lt;p&gt;Teams do not need another place where feedback can sit.&lt;/p&gt;

&lt;p&gt;They need a system that moves feedback from scattered conversations to a product decision—and then tells the customer what happened.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try It
&lt;/h2&gt;

&lt;p&gt;ProductBridge is live with a free plan to get started.&lt;/p&gt;

&lt;p&gt;Create a feedback board, connect one of your existing customer channels, or publish your first roadmap.&lt;/p&gt;

&lt;p&gt;And since we launched the Help Center today, you can now manage customer feedback, roadmaps, changelogs, and product documentation from the same platform.&lt;/p&gt;

&lt;p&gt;I would genuinely love feedback from other developers and SaaS founders:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Which part of the customer-feedback workflow is still the most manual inside your company?&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>saas</category>
      <category>ai</category>
      <category>webdev</category>
      <category>startup</category>
    </item>
  </channel>
</rss>
