<?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>Forem: Tolulope Gbenga</title>
    <description>The latest articles on Forem by Tolulope Gbenga (@tophepzz1).</description>
    <link>https://forem.com/tophepzz1</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%2F264224%2Fbc494e76-d94d-4b4c-a18e-3de75b8f38ed.jpg</url>
      <title>Forem: Tolulope Gbenga</title>
      <link>https://forem.com/tophepzz1</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/tophepzz1"/>
    <language>en</language>
    <item>
      <title>I Summoned a Production-Grade SaaS Stack using AI (Go, gRPC, Next.js) 👻</title>
      <dc:creator>Tolulope Gbenga</dc:creator>
      <pubDate>Fri, 05 Dec 2025 21:31:30 +0000</pubDate>
      <link>https://forem.com/tophepzz1/i-summoned-a-production-grade-saas-stack-using-ai-go-grpc-nextjs-17nj</link>
      <guid>https://forem.com/tophepzz1/i-summoned-a-production-grade-saas-stack-using-ai-go-grpc-nextjs-17nj</guid>
      <description>&lt;p&gt;A Kiroween Post-Mortem: How Spec-Driven AI Development cured my fear of the "Blank Repo".&lt;br&gt;
Tags: #go #microservices #ai #nextjs #hackathon&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Nightmare of the Blank Repo&lt;/strong&gt;&lt;br&gt;
We all know the horror story. You have a brilliant idea for a SaaS. You open your IDE. You create a new folder. And then... the dread sets in.&lt;/p&gt;

&lt;p&gt;Before you can write a single line of unique business logic, you have to build the "Skeleton":&lt;/p&gt;

&lt;p&gt;💀 Authentication (and oh god, RBAC)&lt;/p&gt;

&lt;p&gt;💀 Billing &amp;amp; Subscriptions (Stripe webhooks are scary)&lt;/p&gt;

&lt;p&gt;💀 Feature Flags (so you don't break prod)&lt;/p&gt;

&lt;p&gt;💀 Real-time Sockets (because REST is dead)&lt;/p&gt;

&lt;p&gt;💀 AI Integration (because it's 2025)&lt;/p&gt;

&lt;p&gt;This boilerplate graveyard is where side projects go to die.&lt;/p&gt;

&lt;p&gt;For the Kiroween Hackathon, I decided to face this fear. I wanted to play Dr. Frankenstein and stitch together a "chimera" of the industry's most robust technologies—Go, gRPC, GraphQL, and Next.js—and breathe life into them using Kiro, an AI-powered IDE.&lt;/p&gt;

&lt;p&gt;The result? The Haunted SaaS Skeleton. Here is how I built a 6-service distributed system without losing my mind.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The "Frankenstein" Tech Stack ⚡️&lt;/strong&gt;&lt;br&gt;
I didn't want a simple monolithic template. I wanted a stack that could scale from "Hello World" to IPO.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Body (Backend)&lt;/strong&gt;: Go (Golang) 1.21&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Nerves (Communication)&lt;/strong&gt;: gRPC (Internal) &amp;amp; GraphQL (Public Gateway)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Face (Frontend)&lt;/strong&gt;: Next.js 14 (App Router) + Tailwind + Glassmorphism UI&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Brain (AI)&lt;/strong&gt;: OpenAI (via a custom Gateway)&lt;/p&gt;

&lt;p&gt;The Tools: Docker, Postgres, Redis, Stripe, Unleash.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqq0f3igimkdw5u2n2fem.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqq0f3igimkdw5u2n2fem.png" alt=" " width="800" height="523"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Shutterstock&lt;br&gt;
The Methodology: Spec-Driven Development (Not Just Vibe Coding)&lt;br&gt;
Most people use AI to "write a function." I used Kiro to orchestrate an ecosystem.&lt;/p&gt;

&lt;p&gt;I discovered that "Vibe Coding" (chatting with AI) works best when you give the AI a rigid structure to cling to. I used a Spec-Driven approach:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. The Seance (Steering)&lt;/strong&gt;&lt;br&gt;
I started with a steering.md file. This acted as the "Laws of Physics" for the project. It enforced rules like: "All services must verify JWTs via the user-auth-service" and "Use the Dataloader pattern for GraphQL."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. The Incantation (Specs)&lt;/strong&gt;&lt;br&gt;
Instead of writing code immediately, I wrote contracts in Markdown. I defined six core microservices in /.kiro/specs/. For example, for the Billing Service, I didn't write Go code; I wrote:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Requirement 3: The service must expose a public HTTP endpoint for Stripe Webhooks. It must handle the checkout.session.completed event idempotently by checking the event_id in Redis before provisioning access.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;3. The Summoning&lt;/strong&gt;&lt;br&gt;
With the specs in place, I commanded Kiro to implement them. The result was startling. Kiro generated production-ready Go code, including GORM models, mutex-locked caches, and structured logging, because it had the context of the full architecture.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Anatomy of the Skeleton 🦴&lt;/strong&gt;&lt;br&gt;
Here are the six organs I built, and the cool tech inside them:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. The Gatekeeper (user-auth-service)&lt;/strong&gt;&lt;br&gt;
This isn't just "email/password." It's a full Role-Based Access Control (RBAC) system.&lt;/p&gt;

&lt;p&gt;Cool Factor: It issues RS256-signed JWTs. The API Gateway validates these tokens via gRPC before any resolver even runs.&lt;/p&gt;

&lt;p&gt;Tech: bcrypt, jwt-go, Redis sessions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. The Treasurer (billing-service)&lt;/strong&gt;&lt;br&gt;
This service handles the scary part: Money.&lt;/p&gt;

&lt;p&gt;Cool Factor: Transactional Webhooks. I built a handler that saves the Stripe Event to the DB before processing it. This ensures we never double-provision a subscription, even if Stripe sends the webhook twice.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. The Brain (llm-gateway-service) 🧠&lt;/strong&gt;&lt;br&gt;
This is my favorite part. Instead of hardcoding prompts in Go code, I built a "Prompt-as-Code" architecture.&lt;/p&gt;

&lt;p&gt;How it works: Prompts are .yaml files in a /prompts directory.&lt;/p&gt;

&lt;p&gt;The Magic: The service uses fsnotify to watch that directory. If I edit a prompt file, the service hot-reloads it into memory instantly. No redeploy required to change the AI's personality!&lt;/p&gt;

&lt;p&gt;Go&lt;/p&gt;

&lt;p&gt;&lt;code&gt;// Snippet of the Hot-Reload Logic&lt;br&gt;
func (l *PromptLoader) watchLoop() {&lt;br&gt;
    for {&lt;br&gt;
        select {&lt;br&gt;
        case event := &amp;lt;-l.watcher.Events:&lt;br&gt;
            if event.Op&amp;amp;fsnotify.Write == fsnotify.Write {&lt;br&gt;
                l.logger.Info("Prompt file modified, reloading...", zap.String("file", event.Name))&lt;br&gt;
                l.loadPrompt(event.Name) // Updates the thread-safe cache&lt;br&gt;
            }&lt;br&gt;
        }&lt;br&gt;
    }&lt;br&gt;
}&lt;/code&gt;&lt;br&gt;
&lt;strong&gt;4. The Nervous System (notifications-service)&lt;/strong&gt;&lt;br&gt;
A SaaS feels dead without real-time feedback.&lt;/p&gt;

&lt;p&gt;Tech: Socket.IO. I chose this over raw WebSockets because of its automatic HTTP long-polling fallback, ensuring it works on restrictive corporate networks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. The Shapeshifter (feature-flags-service)&lt;/strong&gt;&lt;br&gt;
Tech: A proxy for Unleash. It caches flags in memory, allowing the rest of the app to check permissions in microseconds without network calls.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. The Interface (graphql-api-gateway)&lt;/strong&gt;&lt;br&gt;
This stitches it all together.&lt;/p&gt;

&lt;p&gt;The Win: End-to-end type safety.&lt;/p&gt;

&lt;p&gt;Postgres Schema -&amp;gt; Go Structs&lt;/p&gt;

&lt;p&gt;Go Structs -&amp;gt; GraphQL Schema&lt;/p&gt;

&lt;p&gt;GraphQL Schema -&amp;gt; TypeScript React Hooks (via graphql-codegen)&lt;/p&gt;

&lt;p&gt;My frontend code looks like this, and it's 100% type-safe:&lt;/p&gt;

&lt;p&gt;TypeScript&lt;/p&gt;

&lt;p&gt;&lt;code&gt;const { login } = useLoginMutation();&lt;br&gt;
// TypeScript knows exactly what 'login' accepts and returns!&lt;/code&gt;&lt;br&gt;
Horror Stories: Challenges I Ran Into 😱&lt;br&gt;
It wasn't all smooth sailing.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Dependency Hell: Building a monorepo with 6 Go services inside Docker is tricky. I kept getting missing go.sum entry errors.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Fix: I learned that Docker build contexts matter. I had to configure docker-compose.yml to isolate each service's context so they didn't invalidate each other's build caches.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The N+1 Nightmare: Stitching 6 microservices into one GraphQL graph is risky. If you request a list of 50 users, you don't want to make 50 gRPC calls to the Auth service.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Fix: I implemented Dataloaders in the Gateway. It batches those 50 IDs into a single ListUsers gRPC call.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion: The Skeleton is Alive&lt;/strong&gt;&lt;br&gt;
The Haunted SaaS Skeleton started as a hackathon entry, but it evolved into a genuine startup foundation.&lt;/p&gt;

&lt;p&gt;What I learned from Kiroween is that AI coding tools aren't just for autocomplete. When you combine them with Systems Thinking and Detailed Specs, you can operate like a Senior Architect and a Dev Team simultaneously.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;The blank repo isn't scary anymore. In fact, it's kind of exciting.&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Check out the repo here: &lt;a href="https://github.com/toluwagbemiga/kiroween" rel="noopener noreferrer"&gt;https://github.com/toluwagbemiga/kiroween&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Happy Vibe Coding! 🎃&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If you enjoyed this breakdown of Go microservices and AI architecture, drop a like or comment below!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>AI assistant/chatbot for use/support</title>
      <dc:creator>Tolulope Gbenga</dc:creator>
      <pubDate>Sun, 23 Jun 2024 19:25:14 +0000</pubDate>
      <link>https://forem.com/tophepzz1/ai-assistantchatbot-for-usesupport-jei</link>
      <guid>https://forem.com/tophepzz1/ai-assistantchatbot-for-usesupport-jei</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/twilio"&gt;Twilio Challenge &lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;I built an SMS/whatsapp/call Assistant that you can chat with and it will still retain context, a conversational AI.&lt;br&gt;
it keeps an history of the conversation so in as much as you use it for AI chatting purposes, it can also be used as a support system as it has a chat channel for the admin to make use of and the admin can check message History between the bot and the user then the admin can take over, the prompt to allow an admin take over is &lt;br&gt;
on the frontend too, it contains a page for the admin to send forth personalized bulk SMS to all their contacts, it has a way of managing contacts and a preview of all the contacts &lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/twilio-hackathon"&gt;Github url&lt;/a&gt;&lt;br&gt;
A &lt;a href="https://twilio.spartapp.ng/admin"&gt;demo link&lt;/a&gt; for this demo, there is a page to set your env and details then you can set the webhook to &lt;a href="https://twilio.spartapp.ng/webhook/sms-whatsapp"&gt;https://twilio.spartapp.ng/webhook/sms-whatsapp&lt;/a&gt; for both whatsapp and SMS&lt;br&gt;
&lt;a href="https://twilio.spartapp.ng/webhook/sms-whatsapp"&gt;https://twilio.spartapp.ng/webhook/sms-whatsapp&lt;/a&gt;&lt;br&gt;
&lt;a href="https://twilio.spartapp.ng/webhook/voice/incoming"&gt;https://twilio.spartapp.ng/webhook/voice/incoming&lt;/a&gt; for the voice call&lt;br&gt;
to set environment variables go to &lt;a href="https://twilio.spartapp.ng/environment"&gt;https://twilio.spartapp.ng/environment&lt;/a&gt;&lt;br&gt;
please set ENV variables before testing because i ran into problem with the whatsapp sender.i couldn't set it up&lt;/p&gt;

&lt;h2&gt;
  
  
  Twilio and AI
&lt;/h2&gt;

&lt;p&gt;i added the functionality of AI powered auto-responder based on previous message so it still retains context, it also includes twilios API for direct messaging and bulk messaging, also for the voice autoresponder which automatically responds to calls from users&lt;/p&gt;

&lt;h2&gt;
  
  
  Additional Prize Categories
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Twilio times two i used both voice, whatsapp and sms API&lt;/li&gt;
&lt;li&gt;Impactful Innovators: with this when advanced, company and organizations can take control of their customer service while giving the users opportunity to interact with AI which can drive sales&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Generate Messaage&lt;br&gt;
(&lt;a href="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b8a5m5ykmsu62wmex92u.png"&gt;https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b8a5m5ykmsu62wmex92u.png&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;the generated message&lt;br&gt;
(&lt;a href="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x86mbgua4q0r99y2puu7.png"&gt;https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x86mbgua4q0r99y2puu7.png&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;the sent message&lt;br&gt;
(&lt;a href="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gazkx3wgx234v5x3c8uv.jpg"&gt;https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gazkx3wgx234v5x3c8uv.jpg&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;the contacts management section&lt;br&gt;
(&lt;a href="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/352cnrl2f7e79cri982s.png"&gt;https://dev-to-uploads.s3.amazonaws.com/uploads/articles/352cnrl2f7e79cri982s.png&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;&amp;lt;!-- Thanks for participating! →&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>twiliochallenge</category>
      <category>ai</category>
      <category>twilio</category>
    </item>
  </channel>
</rss>
