<?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: Lakshan Mihiranga</title>
    <description>The latest articles on DEV Community by Lakshan Mihiranga (@lakshan_mihiranga_05b4f43).</description>
    <link>https://dev.to/lakshan_mihiranga_05b4f43</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3959997%2F5b5b220c-2b0b-49d4-88f3-7efa3c221ac4.jpg</url>
      <title>DEV Community: Lakshan Mihiranga</title>
      <link>https://dev.to/lakshan_mihiranga_05b4f43</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/lakshan_mihiranga_05b4f43"/>
    <language>en</language>
    <item>
      <title>How I Built FlowChat SDK: A Real-Time Customer Support Widget Using Spring Boot, React, MongoDB, and WebSockets</title>
      <dc:creator>Lakshan Mihiranga</dc:creator>
      <pubDate>Sat, 30 May 2026 13:53:32 +0000</pubDate>
      <link>https://dev.to/lakshan_mihiranga_05b4f43/how-i-built-flowchat-sdk-a-real-time-customer-support-widget-using-spring-boot-react-mongodb-2ecm</link>
      <guid>https://dev.to/lakshan_mihiranga_05b4f43/how-i-built-flowchat-sdk-a-real-time-customer-support-widget-using-spring-boot-react-mongodb-2ecm</guid>
      <description>&lt;p&gt;Over the past few weeks, I've been building a side project called FlowChat SDK - a real-time customer support widget designed to help developers add customer communication to their applications in minutes.&lt;/p&gt;

&lt;p&gt;The idea came from a problem I encountered repeatedly while working on web applications.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Problem&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Whenever I wanted to add customer support chat to a project, I found myself facing the same challenges:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Many solutions were too expensive for startups and small businesses.&lt;/li&gt;
&lt;li&gt;Integration often required large SDKs and complex setup processes.&lt;/li&gt;
&lt;li&gt;Most platforms included dozens of features that many projects would never use.&lt;/li&gt;
&lt;li&gt;Customization was often limited or locked behind premium plans.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I wanted something that was:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lightweight&lt;/li&gt;
&lt;li&gt;Easy to integrate&lt;/li&gt;
&lt;li&gt;Real-time&lt;/li&gt;
&lt;li&gt;Customizable&lt;/li&gt;
&lt;li&gt;Developer-friendly&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So I decided to build it myself.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Introducing FlowChat SDK&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;FlowChat is a real-time customer support widget that can be integrated into any website using a simple script tag.&lt;/p&gt;

&lt;p&gt;The goal is straightforward:&lt;/p&gt;

&lt;p&gt;Help developers and startups add modern customer communication to their products without spending days integrating chat systems.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tech Stack&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Backend&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Java 21&lt;/li&gt;
&lt;li&gt;Spring Boot 3&lt;/li&gt;
&lt;li&gt;Spring Security&lt;/li&gt;
&lt;li&gt;JWT Authentication&lt;/li&gt;
&lt;li&gt;Spring WebSocket (STOMP)&lt;/li&gt;
&lt;li&gt;MongoDB Atlas&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Frontend&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;React&lt;/li&gt;
&lt;li&gt;TypeScript&lt;/li&gt;
&lt;li&gt;Tailwind CSS&lt;/li&gt;
&lt;li&gt;Vite&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Deployment&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Vercel&lt;/li&gt;
&lt;li&gt;Cloudflare Pages&lt;/li&gt;
&lt;li&gt;MongoDB Atlas&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;System Architecture&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The platform consists of three main components:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Admin Dashboard&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The admin dashboard allows support agents to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;View conversations&lt;/li&gt;
&lt;li&gt;Respond to users in real time&lt;/li&gt;
&lt;li&gt;Customize widget appearance&lt;/li&gt;
&lt;li&gt;Manage integrations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2. Widget SDK&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The widget can be embedded into any website using a generated script.&lt;/p&gt;

&lt;p&gt;Features include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Floating chat widget&lt;/li&gt;
&lt;li&gt;Real-time messaging&lt;/li&gt;
&lt;li&gt;Mobile responsiveness&lt;/li&gt;
&lt;li&gt;Live customization&lt;/li&gt;
&lt;li&gt;Domain whitelisting&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;3. Spring Boot Backend&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The backend handles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Authentication&lt;/li&gt;
&lt;li&gt;Conversation management&lt;/li&gt;
&lt;li&gt;Message persistence&lt;/li&gt;
&lt;li&gt;WebSocket communication&lt;/li&gt;
&lt;li&gt;Tenant configuration&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Website Visitor&lt;br&gt;
       │&lt;br&gt;
       ▼&lt;br&gt;
 FlowChat Widget&lt;br&gt;
       │&lt;br&gt;
       ▼&lt;br&gt;
WebSocket (STOMP)&lt;br&gt;
       │&lt;br&gt;
       ▼&lt;br&gt;
Spring Boot Backend&lt;br&gt;
       │&lt;br&gt;
       ▼&lt;br&gt;
 MongoDB Atlas&lt;br&gt;
       │&lt;br&gt;
       ▼&lt;br&gt;
 Admin Dashboard&lt;/p&gt;

&lt;p&gt;Why I Chose Spring Boot&lt;/p&gt;

&lt;p&gt;For this project, Spring Boot felt like the right choice because:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Excellent WebSocket support&lt;/li&gt;
&lt;li&gt;Mature security ecosystem&lt;/li&gt;
&lt;li&gt;Easy JWT integration&lt;/li&gt;
&lt;li&gt;Strong MongoDB support&lt;/li&gt;
&lt;li&gt;Familiar development experience&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Implementing real-time messaging using STOMP over WebSockets was surprisingly straightforward once the authentication layer was in place.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;One Challenge: Securing Widget Integrations&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;One concern I had early was:&lt;/p&gt;

&lt;p&gt;What prevents someone from copying another customer's API key and embedding the widget elsewhere?&lt;/p&gt;

&lt;p&gt;To solve this, I implemented domain whitelisting.&lt;/p&gt;

&lt;p&gt;Each widget can only operate on approved domains configured by the customer.&lt;/p&gt;

&lt;p&gt;This provides an additional layer of protection and helps prevent unauthorized usage.&lt;/p&gt;

&lt;p&gt;Improving the Onboarding Experience&lt;/p&gt;

&lt;p&gt;Initially, users needed to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create an account&lt;/li&gt;
&lt;li&gt;Customize their widget&lt;/li&gt;
&lt;li&gt;Copy the embed script&lt;/li&gt;
&lt;li&gt;Download a demo HTML page&lt;/li&gt;
&lt;li&gt;Test the integration manually&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That worked, but it created unnecessary friction.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;So I introduced a feature called:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Launch Hosted Demo&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now the flow is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create an account&lt;/li&gt;
&lt;li&gt;Customize the widget&lt;/li&gt;
&lt;li&gt;Click "Launch Hosted Demo"&lt;/li&gt;
&lt;li&gt;Start chatting instantly&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This allows users to experience the product in minutes without touching any code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;One of the biggest lessons&lt;/strong&gt; from building FlowChat was:&lt;/p&gt;

&lt;p&gt;Reducing onboarding friction often creates more value than adding new features.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Current Features&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Real-time messaging&lt;/li&gt;
&lt;li&gt;WebSocket communication&lt;/li&gt;
&lt;li&gt;Widget customization&lt;/li&gt;
&lt;li&gt;Domain whitelisting&lt;/li&gt;
&lt;li&gt;Admin dashboard&lt;/li&gt;
&lt;li&gt;Multi-tenant architecture&lt;/li&gt;
&lt;li&gt;JWT authentication&lt;/li&gt;
&lt;li&gt;MongoDB persistence&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Lessons Learned&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Simplicity Wins&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It's tempting to build every feature you can think of.&lt;/p&gt;

&lt;p&gt;The biggest progress came from focusing on one problem:&lt;/p&gt;

&lt;p&gt;Customer communication.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Developer Experience Matters&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The easier a product is to integrate, the more likely developers are to adopt it.&lt;/p&gt;

&lt;p&gt;A simple integration flow can be more valuable than dozens of advanced features.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Ship Early&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Many developers spend months planning.&lt;/p&gt;

&lt;p&gt;Building and deploying an MVP quickly generates real feedback and reveals problems you would never discover during planning.&lt;/p&gt;

&lt;p&gt;What's Next?&lt;/p&gt;

&lt;p&gt;Some features I'm considering for future releases:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;File attachments&lt;/li&gt;
&lt;li&gt;AI-powered responses&lt;/li&gt;
&lt;li&gt;Analytics dashboard&lt;/li&gt;
&lt;li&gt;Team collaboration&lt;/li&gt;
&lt;li&gt;Email integration&lt;/li&gt;
&lt;li&gt;WhatsApp integration&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Try FlowChat&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Admin Dashboard:&lt;br&gt;
&lt;a href="https://flow-chat-sable.vercel.app/" rel="noopener noreferrer"&gt;https://flow-chat-sable.vercel.app/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Documentation:&lt;br&gt;
&lt;a href="https://flowchat-8w5.pages.dev/docs" rel="noopener noreferrer"&gt;https://flowchat-8w5.pages.dev/docs&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'm currently looking for &lt;strong&gt;feedback from developers, founders,&lt;/strong&gt; and &lt;strong&gt;anyone building SaaS products&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If you've built something similar or have suggestions for improvement, I'd love to hear your thoughts.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>showdev</category>
      <category>saas</category>
      <category>react</category>
    </item>
  </channel>
</rss>
