<?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: Eesuola Opeyemi</title>
    <description>The latest articles on DEV Community by Eesuola Opeyemi (@wurldguy).</description>
    <link>https://dev.to/wurldguy</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%2F3595460%2F548311bb-a3fb-446e-80fa-0532c71f4358.png</url>
      <title>DEV Community: Eesuola Opeyemi</title>
      <link>https://dev.to/wurldguy</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/wurldguy"/>
    <language>en</language>
    <item>
      <title>Building a Scalable Notification System with RabbitMQ and Microservices</title>
      <dc:creator>Eesuola Opeyemi</dc:creator>
      <pubDate>Sat, 15 Nov 2025 04:10:30 +0000</pubDate>
      <link>https://dev.to/wurldguy/building-a-scalable-notification-system-with-rabbitmq-and-microservices-1a9f</link>
      <guid>https://dev.to/wurldguy/building-a-scalable-notification-system-with-rabbitmq-and-microservices-1a9f</guid>
      <description>&lt;p&gt;Ever wondered how apps like Slack, WhatsApp, or Gmail send millions of notifications without breaking a sweat? The secret lies in asynchronous message queues.&lt;/p&gt;

&lt;p&gt;In this article, I'll write about my learning and insight through building a production-ready notification system using RabbitMQ, Node.js, Fastify, Docker and SendGrid as part of my HNG Internship project.&lt;/p&gt;

&lt;p&gt;*&lt;em&gt;But, why we need message queue.? *&lt;/em&gt;&lt;br&gt;
This below is call without queue message, I mean it is Synchronous in nature. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;app.post('/send-notification', async (req, res) =&amp;gt; {&lt;br&gt;
  await sendEmail(req.body);&lt;br&gt;
  res.send('Email sent');&lt;br&gt;
});&lt;br&gt;
&lt;/code&gt;&lt;br&gt;
But this can cause problems if service(email) is down, the the request will fail immediately. Also, API response is slow (waits for email to send), No retry logic in place and Can't scale email sending independently.&lt;/p&gt;

&lt;p&gt;Below is with queue message i.e Asynchronous = don’t wait, continue working with another task. &lt;/p&gt;

&lt;p&gt;`// Publish to queue - returns immediately&lt;br&gt;
app.post('/send-notification', async (req, res) =&amp;gt; {&lt;br&gt;
  await publishToQueue(req.body);&lt;br&gt;
  res.send('Notification queued'); // Instant response&lt;br&gt;
});&lt;/p&gt;

&lt;p&gt;// Separate consumer processes the queue&lt;br&gt;
consumeQueue(async (message) =&amp;gt; {&lt;br&gt;
  await sendEmail(message);&lt;br&gt;
});`&lt;/p&gt;

&lt;p&gt;Just like I stated above the problems in Synchronous approach. The asynchronous is just the opposite; Fast API responses, retry logic, persistence of message and etc&lt;/p&gt;

&lt;p&gt;Key Learnings&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Asynchronous is Better
Message queues allow services to work independently without blocking each other.&lt;/li&gt;
&lt;li&gt;Always Retry
Transient failures are common. Automatic retries with exponential backoff are essential.&lt;/li&gt;
&lt;li&gt;Monitor Everything
Track queue length, processing time, and error rates to catch issues early.&lt;/li&gt;
&lt;li&gt;Design for Failure
Services will fail. Build systems that gracefully handle and recover from failures&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Learning progress&lt;/strong&gt;&lt;br&gt;
I had ZERO experience with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;RabbitMQ (message queues)&lt;/li&gt;
&lt;li&gt;Fastify (Node.js framework)&lt;/li&gt;
&lt;li&gt;Microservices architecture&lt;/li&gt;
&lt;li&gt;Asynchronous messaging patterns&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So I decided to get hands on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I completed a 35-minute Fastify crash course from Traversy Media.&lt;/li&gt;
&lt;li&gt;I Studied RabbitMQ fundamentals through YouTube tutorials and documentations&lt;/li&gt;
&lt;li&gt;I built, broke, and rebuilt the system several times.
&amp;gt; I strongly recommend reading documentations with YouTube tutorials.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;I also recommend using an email address that belongs to your own domain for smooth delivery on SendGrid. I used my Hostinger domain email, and it worked well. SendGrid won’t accept Gmail or other public email providers because I don’t own those domains. "So, I’d advise using an email address from a domain you own."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;WHAT I BUILT:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Email Service consuming from RabbitMQ queues&lt;/li&gt;
&lt;li&gt;Retry logic with exponential backoff (2s, 4s, 8s)&lt;/li&gt;
&lt;li&gt;Dead letter queue for failed messages&lt;/li&gt;
&lt;li&gt;Integration with SendGrid for email delivery&lt;/li&gt;
&lt;li&gt;Docker containerization for deployment&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The end result ? here you go;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Handles 1,000+ notifications/minute&lt;/li&gt;
&lt;li&gt;99.5% delivery success rate&lt;/li&gt;
&lt;li&gt;Automatic retries prevent message loss&lt;/li&gt;
&lt;li&gt;Services scale independently&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;The magic of RabbitMQ: If my Email Service crashes and restarts, messages wait patiently in the queue. Nothing is lost. This is how apps like Slack, WhatsApp, and Gmail handle millions of messages daily!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The best part was seeing messages flow through RabbitMQ, get processed, and arrive in my inbox just seconds later. That first successful test felt like pure magic!&lt;/p&gt;

&lt;p&gt;Huge thanks to HNG Internship (@HNG Internship) for providing hands-on, real-world projects that push you to learn, adapt, and deliver!&lt;/p&gt;

&lt;p&gt;Let's Connect!&lt;br&gt;
If you found this helpful or have questions, drop a comment below! I'd love to hear about your experiences with message queues and microservices&lt;br&gt;
&lt;a href="https://x.com/wurldguy" rel="noopener noreferrer"&gt;X&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.linkedin.com/in/opeyemi-eesuola-b80717b5/?skipRedirect=true" rel="noopener noreferrer"&gt;linkedin&lt;/a&gt;&lt;/p&gt;

</description>
      <category>fastify</category>
      <category>microservices</category>
      <category>node</category>
      <category>redis</category>
    </item>
    <item>
      <title>Supabase Functions vs Firebase Cloud Functions — Why we Switched for our Eventra Project</title>
      <dc:creator>Eesuola Opeyemi</dc:creator>
      <pubDate>Sat, 08 Nov 2025 10:32:48 +0000</pubDate>
      <link>https://dev.to/wurldguy/supabase-functions-vs-firebase-cloud-functions-why-we-switched-for-our-eventra-project-230m</link>
      <guid>https://dev.to/wurldguy/supabase-functions-vs-firebase-cloud-functions-why-we-switched-for-our-eventra-project-230m</guid>
      <description>&lt;h1&gt;
  
  
  Supabase Functions vs Firebase Cloud Functions — Why we Switched for our Eventra Project
&lt;/h1&gt;

&lt;p&gt;While building &lt;strong&gt;Eventra&lt;/strong&gt;, an event management and ticketing platform, we used &lt;strong&gt;Supabase Functions&lt;/strong&gt; and honestly, I was impressed.  &lt;/p&gt;

&lt;p&gt;They handled almost everything I needed without me spinning up a separate backend server:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; Creating new event orders
&lt;/li&gt;
&lt;li&gt;Verifying payments through Paystack webhooks
&lt;/li&gt;
&lt;li&gt;Generating tickets after successful payment
&lt;/li&gt;
&lt;li&gt;Sending automated emails and confirmations
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All these were simple &lt;strong&gt;serverless functions&lt;/strong&gt; deployed directly from Supabase.&lt;/p&gt;




&lt;h2&gt;
  
  
  What are Supabase Functions?
&lt;/h2&gt;

&lt;p&gt;Supabase Functions are &lt;strong&gt;serverless functions&lt;/strong&gt; that run on &lt;strong&gt;Deno&lt;/strong&gt; (not Node.js).&lt;br&gt;&lt;br&gt;
They let you write backend logic in TypeScript or JavaScript and deploy them directly to the Supabase Edge network.&lt;/p&gt;

&lt;p&gt;That means they’re fast, secure, and automatically scale without any infrastructure setup.&lt;br&gt;&lt;br&gt;
They integrate tightly with &lt;strong&gt;Supabase Auth, Database, and Storage&lt;/strong&gt;, making them feel like a natural part of your backend.&lt;/p&gt;




&lt;h2&gt;
  
  
  Supabase Functions in My Project
&lt;/h2&gt;

&lt;p&gt;Here’s what I built with them in &lt;strong&gt;Eventra&lt;/strong&gt; &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;create-order&lt;/strong&gt; : Handles new event orders. Validates data and stores order info in the database.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;payment-webhook&lt;/strong&gt; : Listens for Paystack payment events, verifies transactions, and updates order statuses.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;generate-ticket&lt;/strong&gt; : Creates unique event tickets after payment confirmation.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;send-mail&lt;/strong&gt; : Sends confirmation and ticket delivery emails automatically.
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Together, these four functions automated the entire transaction flow without a dedicated backend server.&lt;/p&gt;




&lt;h2&gt;
  
  
  Supabase Functions vs Firebase Cloud Functions
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Supabase Functions&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Firebase Cloud Functions&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Runtime&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Deno (TypeScript, modern JS, Web APIs)&lt;/td&gt;
&lt;td&gt;Node.js only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Deployment&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;supabase functions deploy&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;firebase deploy --only functions&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Database Integration&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Native Postgres (SQL)&lt;/td&gt;
&lt;td&gt;Firestore or Realtime DB (NoSQL)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Auth Integration&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Built-in with Supabase Auth JWTs&lt;/td&gt;
&lt;td&gt;Needs Firebase Auth setup&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Speed &amp;amp; Performance&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Edge-deployed (low latency, almost no cold starts)&lt;/td&gt;
&lt;td&gt;Can experience cold starts&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Openness&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Fully open-source&lt;/td&gt;
&lt;td&gt;Proprietary&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Local Testing&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;supabase functions serve&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Firebase emulator suite&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Why I Think Supabase Is Better (for My Use Case)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Runs at the Edge:&lt;/strong&gt; Functions execute close to users super fast.&lt;br&gt;&lt;br&gt;
 &lt;strong&gt;SQL-Powered:&lt;/strong&gt; Works seamlessly with Supabase’s Postgres database.&lt;br&gt;&lt;br&gt;
 &lt;strong&gt;Simple Workflow:&lt;/strong&gt; No external setup I can build, test, and deploy from one place.&lt;br&gt;&lt;br&gt;
 &lt;strong&gt;Open Source:&lt;/strong&gt; Easier to customize and self-host compared to Firebase.  &lt;/p&gt;

&lt;p&gt;It’s like having a full backend platform that feels modern, fast, and transparent.&lt;/p&gt;




&lt;h2&gt;
  
  
  💬 Final Thoughts
&lt;/h2&gt;

&lt;p&gt;While &lt;strong&gt;Firebase Cloud Functions&lt;/strong&gt; remain solid for Node.js and NoSQL projects,&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Supabase Functions&lt;/strong&gt; give developers a cleaner, faster, and more flexible option especially if you love SQL and want everything in one place.&lt;/p&gt;

&lt;p&gt;In my case, using them for &lt;strong&gt;Eventra&lt;/strong&gt; made the backend process smoother, cheaper, and a bit friendly to work with it.&lt;/p&gt;




&lt;h3&gt;
  
  
  Tags
&lt;/h3&gt;

&lt;h1&gt;
  
  
  supabase #serverless #firebase #deno #webdev #backend #opensource #javascript
&lt;/h1&gt;




&lt;h3&gt;
  
  
  What do you think?
&lt;/h3&gt;

&lt;p&gt;Have you tried &lt;strong&gt;Supabase Functions&lt;/strong&gt; yet?&lt;br&gt;&lt;br&gt;
What’s your experience compared to &lt;strong&gt;Firebase Cloud Functions&lt;/strong&gt;?&lt;/p&gt;

</description>
      <category>supabase</category>
      <category>database</category>
      <category>firebase</category>
      <category>functions</category>
    </item>
    <item>
      <title>Building Eventra: My First Hackathon Journey with Hedera The Challenge</title>
      <dc:creator>Eesuola Opeyemi</dc:creator>
      <pubDate>Fri, 07 Nov 2025 01:05:45 +0000</pubDate>
      <link>https://dev.to/wurldguy/building-eventra-my-first-hackathon-journey-with-hedera-the-challenge-592b</link>
      <guid>https://dev.to/wurldguy/building-eventra-my-first-hackathon-journey-with-hedera-the-challenge-592b</guid>
      <description>&lt;p&gt;The Challenge&lt;/p&gt;

&lt;p&gt;When I joined my first hackathon with Hedera, I had no idea what I was getting into. Grouped with talented individuals, we faced the ultimate challenge: solve a real problem, benefit the community, and leverage Hedera’s technology—all while learning entirely new technologies from scratch.&lt;/p&gt;

&lt;p&gt;The Problem We Tackled&lt;/p&gt;

&lt;p&gt;In Nigeria, 10.3% of the population owns or uses cryptocurrency, but most don’t know how to use it for everyday purchases like event tickets. We asked ourselves: How do we build a platform that serves both Web3 natives and complete beginners?&lt;/p&gt;

&lt;p&gt;Enter Eventra - a fraud-proof, fast, and fair event ticketing platform built on Hedera Hashgraph.&lt;/p&gt;

&lt;p&gt;What is Eventra? &lt;br&gt;
creates a transparent, low-cost event management platform that:&lt;/p&gt;

&lt;p&gt;• Prevents ticket fraud - Every ticket is an NFT, impossible to duplicate&lt;/p&gt;

&lt;p&gt;• Enables dual payments - Users can pay with Hedera (HBAR) or traditional methods (Paystack)&lt;/p&gt;

&lt;p&gt;• Provides permanent proof of attendance - NFT certificates for participants&lt;/p&gt;

&lt;p&gt;• Fair resale marketplace - Organizers earn 5% royalty on resales&lt;br&gt;
• Rewards system - Points for ticket purchases&lt;br&gt;
• Comprehensive analytics - Detailed event reports for organizers&lt;/p&gt;

&lt;p&gt;Why Hedera?&lt;/p&gt;

&lt;p&gt;Hedera made this possible through:&lt;/p&gt;

&lt;p&gt;• Ultra-low fees(~$0.0001 per transaction)&lt;br&gt;
• Lightning-fast finality (3-5 seconds) for instant verification&lt;br&gt;
• Carbon-negative network - environmentally sustainable&lt;br&gt;
• Enterprise governance - trusted by universities, corporations, and governments&lt;/p&gt;

&lt;p&gt;My Learning Journey (The Real Story)&lt;/p&gt;

&lt;p&gt;Here’s the thing: I had zero experience with TypeScript, Solidity, or Supabase before this hackathon. When Firebase started requiring credit cards, I switched to Supabase—a tool I’d barely touched.&lt;/p&gt;

&lt;p&gt;Week 1-2: Crash Course Mode&lt;/p&gt;

&lt;p&gt;• Dove into Solidity documentation&lt;br&gt;
• Binge-watched &lt;a href="https://www.youtube.com/@nazdumanskyy" rel="noopener noreferrer"&gt;Naz Dumanskyy’s tutorials&lt;/a&gt; (absolute lifesaver!)&lt;br&gt;
• Built micro-projects to test my knowledge&lt;br&gt;
• YouTube and AI became my debugging partners&lt;/p&gt;

&lt;p&gt;The Reality Check&lt;/p&gt;

&lt;p&gt;I was the only backend developer on the team. The pressure was real. I encountered:&lt;/p&gt;

&lt;p&gt;• Supbase Functions issues&lt;br&gt;
• Countless TypeScript bugs&lt;br&gt;
• Moments of what did I get myself into?&lt;/p&gt;

&lt;p&gt;But here’s what I learned: asking “ridiculous” questions is how you grow. The community, documentation, and fellow developers were incredibly supportive.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Backend: TypeScript + Supabase (Functions &amp;amp; Database)
Blockchain: Hedera Hashgraph (Smart Contracts in Solidity)
Payments: Hedera Token Service + Paystack Integration
NFTs: Hedera Token Service for ticket minting
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Key Features Implemented&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Dual Payment System&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Integrated both Hedera (crypto) and Paystack (fiat) to ensure accessibility for everyone.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;NFT Ticketing&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Every ticket is minted as an NFT on Hedera blockchain with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Permanent proof of ownership&lt;/li&gt;
&lt;li&gt;Impossible to counterfeit&lt;/li&gt;
&lt;li&gt;Transferable on our marketplace&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;Fair Resale Marketplace&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Transparent pricing&lt;/li&gt;
&lt;li&gt;Organizers earn 5% royalty automatically&lt;/li&gt;
&lt;li&gt;Prevents scalping while maintaining liquidity&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;Proof of Attendance NFTs&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Attendees receive permanent certificates they can showcase in their Web3 portfolios.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Analytics Dashboard&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Organizers get comprehensive insights into ticket sales, attendance patterns, and revenue.&lt;/p&gt;

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

&lt;ol&gt;
&lt;li&gt;Don’t be afraid to start from zero - Two weeks ago, I couldn’t write a line of Solidity&lt;/li&gt;
&lt;li&gt;Community matters - Hackathons are collaborative, not competitive&lt;/li&gt;
&lt;li&gt;Build micro-projects first - Testing knowledge before diving into production saves time&lt;/li&gt;
&lt;li&gt;AI is a tool, not a crutch - Use it to understand, not just copy-paste&lt;/li&gt;
&lt;li&gt;Team diversity is strength - Different skill sets create better solutions&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;This hackathon taught me that the best way to learn is by building something that matters. Eventra isn’t just a project it’s a solution to real problems in event management and Web3 accessibility.&lt;/p&gt;

&lt;p&gt;Resources That Helped Me&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.hedera.com" rel="noopener noreferrer"&gt;Hedera Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/@nazdumanskyy" rel="noopener noreferrer"&gt;Naz Dumanskyy’s YouTube Channel&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Supabase Documentation&lt;/li&gt;
&lt;li&gt;The amazing Hedera developer community&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;To anyone considering their first hackathon: Do it. You’ll learn more in a few weeks than months of tutorials. The discomfort means you’re growing.&lt;/p&gt;

&lt;p&gt;What was your first hackathon experience like? Drop a comment below!&lt;/p&gt;

&lt;h1&gt;
  
  
  Hedera #Web3 #Hackathon #Blockchain #TypeScript #FirstTimer
&lt;/h1&gt;

</description>
      <category>web3</category>
      <category>hackathon</category>
      <category>dlt</category>
      <category>nft</category>
    </item>
    <item>
      <title>Booksy Agent — Your AI Reading Companion</title>
      <dc:creator>Eesuola Opeyemi</dc:creator>
      <pubDate>Tue, 04 Nov 2025 10:03:22 +0000</pubDate>
      <link>https://dev.to/wurldguy/booksy-agent-your-ai-reading-companion-1l0a</link>
      <guid>https://dev.to/wurldguy/booksy-agent-your-ai-reading-companion-1l0a</guid>
      <description>&lt;p&gt;Introduction&lt;/p&gt;

&lt;p&gt;Reading is an incredible way to grow, but keeping track of what you’ve read, where you stopped, and what you learned can quickly get messy  especially for avid readers. That’s the problem I wanted to solve with Booksy Agent.&lt;/p&gt;

&lt;p&gt;Booksy Agent is an AI-powered reading companion that helps you manage your books, summarize chapters, track reading progress, and generate personalized recommendations, all through a conversational interface.&lt;/p&gt;

&lt;p&gt;What problem I solved&lt;/p&gt;

&lt;p&gt;Readers often lose track of progress, forget book insights, and have no structured way to manage reading goals. Booksy solves this by combining AI summarization, note-taking, and reading analytics into one smart assistant.&lt;/p&gt;

&lt;p&gt;Why I chose this agent&lt;/p&gt;

&lt;p&gt;I chose to build a reading focused agent because it’s relatable and practical. Everyone reads whether it’s for learning or leisure and this agent makes reading more intentional and intelligent. It also demonstrates how AI can enhance everyday habits using automation, structured data, and context-aware conversation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Tech Stack&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Mastra Framework — the backbone for agent creation, orchestration, and routing.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Google Gemini AI — powers smart summaries, insights, and recommendations.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Open Library &amp;amp; Google Books APIs — fetch book metadata, cover images, and author info.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;TypeScript — ensures type safety and maintainable, scalable code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Telex.im Integration — connects the agent to Telex via the A2A (Agent-to-Agent) protocol.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Building the Agent&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Setting Up Mastra
Mastra provides an elegant way to define agents, tools, and AI models.
Here’s the core setup for the Booksy Agent:
import { Agent } from "@mastra/core/agent";
import { bookManagementTool, bookSearchTool, bookSummaryTool } from "../tools/book-tools";
import { readingProgressTool, readingStreakTool, readingNotesTool } from "../tools/reading-tools";
import { Memory } from '@mastra/memory';
import { LibSQLStore } from '@mastra/libsql';&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;export const booksyAgent = new Agent({&lt;br&gt;
  name: "Booksy Reading Companion",&lt;br&gt;
  instructions: `&lt;br&gt;
    You're a helpful AI reading companion that helps users manage their reading journey.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;**Your capabilities:**
- Track reading progress across multiple books
- Generate chapter summaries and key takeaways
- Maintain reading streaks and motivation
- Take and organize reading notes
- Provide personalized book recommendations
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;model: "google/gemini-2.5-flash",&lt;br&gt;
  tools: {&lt;br&gt;
    bookManagementTool,&lt;br&gt;
    bookSearchTool,&lt;br&gt;
    bookSummaryTool,&lt;br&gt;
    readingProgressTool,&lt;br&gt;
    readingStreakTool,&lt;br&gt;
    readingNotesTool,&lt;br&gt;
  },&lt;br&gt;
  memory: new Memory({&lt;br&gt;
     storage: new LibSQLStore({&lt;br&gt;
       url: 'file:../mastra.db', // path is relative to the .mastra/output directory&lt;br&gt;
     }),&lt;br&gt;
   }),&lt;br&gt;
});&lt;br&gt;
This setup defines the agent’s identity and binds its tools — giving it the ability to handle book management and reading progress commands.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Creating Tools&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Tools are how the agent performs specific actions like adding books, tracking progress, or taking notes.&lt;br&gt;
Example: A simple book management tool.&lt;br&gt;
import { createTool } from "@mastra/core";&lt;br&gt;
import { z } from "zod";&lt;br&gt;
import { bookStorage } from "../utils/storage";&lt;br&gt;
import { Book, BookStatus } from "../utils/definitions";&lt;/p&gt;

&lt;p&gt;export const bookManagementTool = createTool({&lt;br&gt;
  id: "manage-book",&lt;br&gt;
  description: "Add, update, or retrieve books in the user's library",&lt;br&gt;
  inputSchema: z.object({&lt;br&gt;
    action: z.enum(["add", "update", "get", "list"]).describe("Action to perform"),&lt;br&gt;
    bookId: z.string().optional().describe("Book ID for update/get operations"),&lt;br&gt;
    title: z.string().optional().describe("Book title"),&lt;br&gt;
    author: z.string().optional().describe("Book author"),&lt;br&gt;
    totalChapters: z.number().optional().describe("Total number of chapters"),&lt;br&gt;
    currentChapter: z.number().optional().describe("Current chapter number"),&lt;br&gt;
    genre: z.string().optional().describe("Book genre"),&lt;br&gt;
    status: z.enum(["reading", "completed", "want-to-read"]).optional(),&lt;br&gt;
  }),&lt;br&gt;
  outputSchema: z.object({&lt;br&gt;
    success: z.boolean(),&lt;br&gt;
    message: z.string(),&lt;br&gt;
    book: z.any().optional(),&lt;br&gt;
    books: z.array(z.any()).optional(),&lt;br&gt;
  }),&lt;br&gt;
Each tool is modular, easy to test, and can be reused or expanded.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;AI Integration&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Booksy uses Google Gemini AI to automatically generate chapter summaries, key takeaways, and book recommendations.&lt;br&gt;
Here’s a simplified example of AI summarization:&lt;br&gt;
import { Agent } from "@mastra/core/agent";&lt;/p&gt;

&lt;p&gt;export interface SummaryOptions {&lt;br&gt;
  bookTitle: string;&lt;br&gt;
  author: string;&lt;br&gt;
  chapter: number;&lt;br&gt;
  length: "short" | "medium" | "long";&lt;br&gt;
  userNotes?: string[];&lt;br&gt;
  context?: string;&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;export interface ChapterSummary {&lt;br&gt;
  summary: string;&lt;br&gt;
  keyTakeaways: string[];&lt;br&gt;
  actionableInsights: string[];&lt;br&gt;
  quotes?: string[];&lt;br&gt;
  relatedConcepts?: string[];&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;export class AISummaryService {&lt;br&gt;
  private summaryAgent: Agent;&lt;/p&gt;

&lt;p&gt;constructor() {&lt;br&gt;
    // Create a specialized agent for summarization&lt;br&gt;
    this.summaryAgent = new Agent({&lt;br&gt;
      name: "Summary Generator",&lt;br&gt;
      instructions: `&lt;br&gt;
        You are an expert book summarization assistant. Your role is to create &lt;br&gt;
        insightful, actionable summaries of book chapters.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    **Guidelines:**
    - Focus on key concepts and main ideas
    - Extract actionable insights the reader can apply
    - Identify memorable quotes if provided
    - Connect ideas to broader themes
    - Be concise but comprehensive
    - Use clear, accessible language

    **Summary Lengths:**
    - SHORT: 2-minute read (150-200 words) - Just the essentials
    - MEDIUM: 5-minute read (400-500 words) - Balanced detail
    - LONG: 10-minute read (800-1000 words) - Comprehensive analysis

    Always structure your response as JSON with:
    {
      "summary": "Main summary text",
      "keyTakeaways": ["point 1", "point 2", "point 3"],
      "actionableInsights": ["action 1", "action 2"],
      "quotes": ["quote 1", "quote 2"],
      "relatedConcepts": ["concept 1", "concept 2"]
    }
  `,
  model: "google/gemini-2.5-flash", // Fast and cost-effective
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This gives users the ability to explore and add real books seamlessly.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Telex.im Integration&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To make Booksy usable within Telex, I implemented the A2A (Agent-to-Agent) protocol for communication between Booksy and other agents.&lt;br&gt;
import { registerApiRoute } from "@mastra/core/server";&lt;br&gt;
import { randomUUID } from "crypto";&lt;/p&gt;

&lt;p&gt;export const a2aAgentRoute = registerApiRoute("/a2a/agent/:agentId", {&lt;br&gt;
  method: "POST",&lt;br&gt;
  handler: async (c) =&amp;gt; {&lt;br&gt;
    try {&lt;br&gt;
      const mastra = c.get("mastra");&lt;br&gt;
      const agentId = c.req.param("agentId");&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  // Parse JSON-RPC 2.0 request
  const body = await c.req.json();
  const { jsonrpc, id: requestId, method, params } = body;

  // Validate JSON-RPC 2.0 format
  if (jsonrpc !== "2.0" || !requestId) {
    return c.json(
      {
        jsonrpc: "2.0",
        id: requestId || null,
        error: {
          code: -32600,
          message:
            'Invalid Request: jsonrpc must be "2.0" and id is required',
        },
      },
      400
    );
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This allows Booksy to respond to AI-driven messages inside the Telex.im ecosystem.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Challenges &amp;amp; Solutions&lt;/strong&gt;&lt;br&gt;
What worked well&lt;/p&gt;

&lt;p&gt;Mastra’s structure made it simple to define and organize tools.&lt;/p&gt;

&lt;p&gt;Gemini AI handled summarization and recommendations impressively.&lt;/p&gt;

&lt;p&gt;The A2A integration connected smoothly with Telex.&lt;/p&gt;

&lt;p&gt;What was difficult&lt;/p&gt;

&lt;p&gt;Managing API rate limits from Google Books.&lt;/p&gt;

&lt;p&gt;Maintaining state between reading sessions.&lt;/p&gt;

&lt;p&gt;Fine-tuning AI summaries to stay accurate and concise.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How I solved problems&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Implemented a caching layer for API results.&lt;/p&gt;

&lt;p&gt;Used in-memory storage for temporary session tracking.&lt;/p&gt;

&lt;p&gt;Adjusted prompt templates for better summarization balance.&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%2Fz2sr7idin79zx58qp2ck.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%2Fz2sr7idin79zx58qp2ck.png" alt=" " width="800" height="426"&gt;&lt;/a&gt;&lt;br&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%2F97h1g7gfeswy4ddm2tv3.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%2F97h1g7gfeswy4ddm2tv3.png" alt=" " width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Conclusion&lt;br&gt;
What I learned&lt;/p&gt;

&lt;p&gt;Building Booksy taught me how to combine AI reasoning, API integrations, and conversational interfaces into one coherent system. It also deepened my understanding of Mastra’s modular design and Telex’s agent ecosystem.&lt;/p&gt;

&lt;p&gt;Future improvements&lt;/p&gt;

&lt;p&gt;Integrate Goodreads or Notion export.&lt;/p&gt;

&lt;p&gt;Add a “Reading Goals” tracker.&lt;/p&gt;

&lt;p&gt;Support audiobooks and sync reading across devices.&lt;/p&gt;

&lt;p&gt;Introduce a leaderboard for reading streaks.&lt;/p&gt;

&lt;p&gt;Links&lt;/p&gt;

&lt;p&gt;🔗 GitHub Repo: [&lt;a href="https://github.com/eesuola/Booksy-Agent" rel="noopener noreferrer"&gt;https://github.com/eesuola/Booksy-Agent&lt;/a&gt;]&lt;/p&gt;

&lt;p&gt;🌐 Live Demo: &lt;a href="https://red-melodic-sunset-40618f2d-c6b7-4294-bd35-4883323b8e26.mastra.cloud/a2a/agent/booksyAgent" rel="noopener noreferrer"&gt;https://red-melodic-sunset-40618f2d-c6b7-4294-bd35-4883323b8e26.mastra.cloud/a2a/agent/booksyAgent&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🤖 Telex Agent Link:[&lt;a href="https://telex.im/telex-ai-intergration/home/colleagues/019a4d37-ff96-797a-a07e-1e5652a7e124/019a4d37-eae8-7979-b4a6-769b60698c78" rel="noopener noreferrer"&gt;https://telex.im/telex-ai-intergration/home/colleagues/019a4d37-ff96-797a-a07e-1e5652a7e124/019a4d37-eae8-7979-b4a6-769b60698c78&lt;/a&gt;]&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>telex</category>
      <category>api</category>
      <category>typescript</category>
    </item>
  </channel>
</rss>
