All Projects
A comprehensive showcase of my work — from SaaS platforms and AI integrations to web applications and system design.
Kavi - AI Shopping Agent
Overview Kavi is a conversational AI shopping assistant built for the Kapruka Agent Challenge, an open competition where 700+ developers submitted over 200 live, working AI agents. Kavi helps users discover products, get gift recommendations, and complete checkout entirely through natural language — in English, Sinhala, or Tamil. The goal of the challenge was simple to state and hard to execute: build a real, live agent on top of Kapruka's Model Context Protocol (MCP) server, not a prototype or mockup. Kavi is the result — a full end-to-end shopping experience powered by conversational AI. The Problem Traditional e-commerce search relies on filters, dropdowns, and category trees that assume the shopper already knows what they're looking for. Gift shopping in particular often starts with a vague idea ("something for my mom's birthday") rather than a specific product. Kavi was designed to close that gap — letting users describe what they want in plain language and have the agent handle search, recommendation, and checkout from there. What It Does Conversational shopping assistant Powered by Google Gemini, Kavi understands natural-language requests, recommends gifts based on context, searches the product catalog, and walks users through checkout — all through chat. Multi-lingual by design Full UI and conversational support in English, Sinhala (සිංහල), and Tamil (தமிழ்). Language context is dynamically mapped into both the Gemini system instructions and the frontend, so the experience is consistent regardless of language. Live, real-time commerce Product search by keyword, category, price range, and availability, rendered through custom cards, detail drawers, and carousels. Cart management updates totals in real time and enforces sensible limits. Checkout can be completed conversationally or through a guided form, capturing sender, recipient, and delivery details. Orders can be tracked by order number after purchase. Personalization that persists User accounts are backed by Supabase Auth (magic link and Google OAuth), with saved delivery details, a persistent list of frequent recipients that auto-syncs during gifting checkouts, and reminders for birthdays and anniversaries that surface tailored gift suggestions before the date arrives. Grounded in real data Every product, category, and location shown to users is pulled live from the Kapruka Model Context Protocol (MCP) server — not cached or mocked data. Tech Stack AI / LLM: Google Gemini Data layer: Kapruka Model Context Protocol (MCP) server Auth & backend: Supabase (magic link + Google OAuth) Frontend: Custom UI with multi-lingual support (English, Sinhala, Tamil) Outcome Kavi was one of 200+ live agents evaluated by judges in the Kapruka Agent Challenge, out of 700+ developers who entered. It didn't place in the Top 20, but it stands as a fully working, deployed product — handling real product search, multi-lingual conversation, checkout, and personalization end to end. What I Learned Building Kavi meant designing a conversational interface that had to work reliably in three languages, wiring a live MCP integration for real-time data rather than static content, and thinking through the full shopping journey — discovery, recommendation, cart, checkout, and post-purchase tracking — rather than a single isolated feature. It was as much a lesson in product thinking as it was in AI engineering.
Full-Stack E-Commerce Platform for Clothing Brands
Forever is a production-ready e-commerce platform designed for modern clothing retail. It combines a rich, browsable storefront for customers with a full admin and sub-admin system for running the business behind the scenes — everything from products and inventory to orders, promotions, and returns. The project uses a monolith-first, SPA-like architecture powered by Inertia.js, pairing Laravel 13 on the backend with React 19 and TypeScript on the frontend. That combination gives the feel and responsiveness of a single-page app without the overhead of building and maintaining a separate API layer. Storefront Features The customer-facing side includes a dynamic homepage with hero sections, featured collections, and promotional banners. Shoppers can search and filter products by name, gender, category, brand, size, colour, and price, then view detailed product pages with multi-image galleries, variant selection, and live stock indicators. From there, the shopping experience covers a persistent session-based cart, a full checkout flow with address management, promo code validation, and PayHere payment integration, plus a wishlist for saving items. Customers can leave verified-purchase reviews with ratings, track their orders in real time with full status history, and submit return requests down to the individual item level. Account management covers profile details, an address book, and order history. Admin Panel The admin panel centres on a dashboard with sales analytics, revenue charts built with Recharts, recent orders, and key performance indicators. It also handles user management for admins and sub-admins with role-based access, along with global store configuration. Sub-Admin Panel The sub-admin panel is where day-to-day store operations happen. It covers full product management with multi-image uploads and colour-and-size variant handling, brand and hierarchical category management, and curated collections that support optional discount percentages. Inventory is tracked per variant-size combination with a full inventory log, and promotions are managed through coupon codes with percentage or fixed discounts and expiry dates. Order management spans the full lifecycle from pending through shipped, delivered, and cancelled, with a dedicated returns workflow for approving, rejecting, or refunding requests. Sub-admins can also moderate customer reviews and update shipment status and tracking information. Security Security is handled through role-based access control via Spatie Laravel Permission, with two-factor authentication delivered by email OTP for admin and sub-admin logins. OTP tokens are bound to device fingerprints for an extra layer of protection, and authentication scaffolding is built on Laravel Fortify. AI Chatbot An AI-powered chatbot, built on OpenRouter, is integrated directly into the storefront to handle customer support queries. Tech Stack Backend: PHP 8.4, Laravel 13 as the application framework, Inertia.js as the server-driven SPA bridge, Laravel Fortify for authentication, Spatie Laravel Permission for role-based access control, Laravel Wayfinder for type-safe route generation, and Laravel Tinker for development. Frontend: React 19 and TypeScript for a type-safe UI, Inertia.js as the frontend adapter, Tailwind CSS for styling, Radix UI and shadcn/ui for accessible component primitives, Lucide React for icons, Recharts for dashboard charting, DnD Kit for drag-and-drop interactions, Sonner for toast notifications, and Vite as the build tool. Dev Tooling: Pest PHP for testing, Laravel Pint for PHP code style, ESLint and Prettier for JavaScript and TypeScript linting and formatting, Laravel Sail for a Dockerised development environment, and Laravel Pail for real-time log tailing. Payments & Integrations: PayHere for payment processing, OpenRouter for the AI chatbot, and Mailtrap as an email sandbox during development. Why This Stack Pairing Laravel with Inertia and React made it possible to build a genuinely SPA-like storefront and admin experience — fast navigation, no full page reloads — while keeping business logic, validation, and security on the backend where it belongs. Role-based access control and two-factor authentication were built in from the start given how much sensitive operational data flows through the admin and sub-admin panels, and the variant-level inventory system was designed to handle the real complexity of tracking stock across colour and size combinations rather than treating a product as a single unit.
Full-Stack Invoicing and Quotation SaaS App
Invoice SaaS App is a web application that lets freelancers and small business owners create, send, and track professional invoices and quotes without the friction of spreadsheets or generic templates. It covers the full lifecycle of a client transaction, from drafting a quote, to emailing it as a PDF, to converting it into an invoice with a single click once the client approves. The project was built as a complete SaaS product, including its own billing layer: a Stripe-powered credit system that gates paid actions while keeping core utilities like PDF downloads free. Key Features Professional Invoices. Invoices are generated as polished, PDF-ready documents in seconds, with fully customisable line items, taxes, and notes. Once created, they can be emailed straight to a client or downloaded as a PDF at any time. PDF downloads are always free, no credits required. Smart Quotations. Quotes follow the same polish as invoices, complete with PDF attachments sent by email and dynamic status tracking (draft, sent, approved, and so on). The standout feature here is one-click conversion: an approved quote becomes a full invoice with no re-entry of data. Instant Email Delivery. Both invoices and quotes can be emailed directly from the app with the PDF attached, keeping every client communication professional, consistent, and trackable in one place. Client Management. Every invoice and quote is linked to a client record, so the app always has full context, including contact details, history, and status, without needing to look anything up elsewhere. Dashboard Analytics. A central dashboard surfaces the metrics that matter at a glance: total invoices, quotations sent, and remaining credits, plus a feed of recent activity. Credit-Based Billing (Stripe). Rather than a flat subscription, the app uses a lightweight credit system. Creating an invoice, creating a quotation, sending an email, and converting a quote to an invoice each cost 1 credit. Downloading a PDF is always free. Every user starts with 10 free credits per month, no card required, which reset on the 1st. Users can top up anytime with one-time credit packs, and purchased credits never expire, a model designed to keep the barrier to entry low while still supporting monetisation. Authentication & Profiles. Secure registration, login, and password recovery, plus profile settings including preferred currency, so the app adapts to how each user actually invoices. Tech Stack Backend: Laravel 12 for the application framework, routing, auth, and business logic. MySQL or SQLite for the relational data layer. mPDF for server-side PDF generation. Stripe PHP for payment processing and credit-pack purchases. Frontend: React 18 for a component-driven UI. Inertia.js to glue Laravel and React together as a single-page app, without hand-building a separate REST or JSON API. Tailwind CSS for utility-first styling. Vite for a fast dev server and asset bundling. Why This Stack The Laravel, Inertia, and React combination made it possible to build a genuinely SPA-like experience, with instant navigation and no full page reloads, while keeping all business logic, validation, and PDF or email generation on the backend where it belongs. It avoided the overhead of maintaining a separate API layer just to talk to the frontend, which kept development fast without sacrificing the interactivity users expect from a modern dashboard. The credit system was the most interesting piece to design: it needed to feel generous, with free PDF downloads and a monthly free tier, while still creating a clear, fair path to revenue through Stripe-backed top-ups.
Wallet: Building a Full-Stack Expense Tracker with React Native & Express
After my first React Native project, I wanted to push further past a front-end-only app and into something that felt genuinely production-ready. Wallet is the result: a full-stack mobile expense tracker with real authentication, a cloud-hosted database, rate limiting, and a deployment-ready backend behind it. Why This Project A lot of portfolio apps stop at the UI layer pretty screens backed by mock data or local storage. I wanted to build the whole system: an API that handles real users, a database that persists real transactions, and the kind of infrastructure decisions (auth, rate limiting, cloud deployment) that separate a demo from something you could actually ship. Wallet is built to run on both iOS and Android, on simulator or a real device, with a backend that's ready to go live. What It Does Authentication Email-based auth handled through Clerk Six-digit email verification codes for signup Secure signup and login flows, with logout support Wallet Functionality View current balance at a glance Track income and expenses separately Add new transactions Delete transactions, with the balance recalculating automatically Pull-to-refresh, implemented from scratch rather than pulled from a library Mobile Experience Built with React Native and Expo Navigation handled through React Navigation State managed with custom hooks rather than a heavy external library UI tuned to feel native on both Android and iOS Backend & Cloud An Express.js REST API PostgreSQL via Neon for cloud-hosted, serverless-friendly data storage Redis-based rate limiting (via Upstash) to protect the API from abuse Clerk auth middleware and webhooks securing every relevant route An architecture that's ready to deploy, not just run locally The Tech Stack Frontend (Mobile) React Native Expo React Navigation Clerk (Authentication) Axios TypeScript / JavaScript Backend Node.js Express.js PostgreSQL (Neon) Redis (Upstash) Clerk Webhooks & Auth Middleware Rate Limiting What I Learned This project forced me to think like a backend engineer as much as a mobile developer. Wiring up Clerk's auth middleware and webhooks meant understanding how tokens flow between the client, the API, and a third-party auth provider not just calling a login function and trusting it works. Adding Redis-based rate limiting was my first real exposure to protecting an API against abuse rather than just handling the happy path. On the mobile side, implementing pull-to-refresh from scratch instead of reaching for a pre-built component taught me more about React Native's gesture and scroll handling than any tutorial. And keeping the balance in sync every time a transaction was added or deleted meant being deliberate about where state lived and how it updated, rather than letting the UI drift out of sync with the database. Overall, Wallet felt like the first project where I was building a system, not just a screen and that shift in thinking is something I'll carry into everything I build next. Wallet is a full-stack, production-oriented project authentication, database, rate limiting, and deployment-ready architecture, all wired up end to end.
Building My First React Native App: A Real-Time Todo App with Convex
As my first real dive into React Native, I wanted to build something that was simple on the surface but let me stretch into concepts I hadn't touched before - real-time data sync, theme handling, and putting together a mobile experience that actually feels good to use. The result is a Todo App powered by React Native, Expo, and Convex. Why This Project Most "first app" tutorials stop at local state and a hardcoded list. I wanted more than that. I wanted to understand what it actually takes to have data update instantly across multiple devices, to support both light and dark mode properly, and to ship something that felt like a small but complete product rather than a demo. What It Does At its core, this is a todo app - but with a few details that make it feel polished: Todos Add, edit, and delete tasks Mark tasks as complete or incomplete A live progress bar that reflects completion status in real time Instant sync across every connected device Settings Task statistics - total, completed, and remaining A dark mode / light mode toggle Notification and auto-sync toggles (UI groundwork for future functionality) A "delete all tasks" option with a confirmation step, so one accidental tap doesn't wipe your list Real-Time Sync Changes propagate instantly through Convex's real-time database Automatic reconnection handling, so the app recovers gracefully if connectivity drops The Tech Stack React Native for the cross-platform mobile UI Expo to speed up development and testing without fighting native build tooling Convex as the real-time backend and database TypeScript throughout What I Learned The biggest unlock on this project was understanding how Convex handles real-time subscriptions. Instead of manually polling or writing socket logic, Convex lets the UI just react to data changes — which completely changed how I thought about state management in a mobile context. Building the theme system also pushed me to think more intentionally about UI consistency, since every component had to look right in both light and dark mode. It's still a simple app on paper a todo list but building it end to end taught me far more than any tutorial could about how real apps are structured, synced, and shipped. This was my first React Native project, and I'm excited to keep building. If you find it useful, a star on the repo is always appreciated.
Building QuizApp: A Full-Stack Timed Quiz Platform
I recently built and shipped QuizApp, a full-stack quiz application designed for educators and learners who want a clean, competitive quiz experience. Here's a look at what it does and how it's built. What It Does QuizApp lets admins create timed quizzes — both multiple-choice (up to 6 options) and true/false — with configurable time limits. Users browse published quizzes, take them under a live countdown, and get instant, per-question feedback the moment they submit. Scoring follows a simple negative-marking scheme: +1 for a correct answer, -1 for an incorrect one, and 0 for anything skipped. Results feed into a global leaderboard, a per-quiz leaderboard, and a personal score history on each user's profile. The Stack Backend: Laravel 12, Sanctum for cookie-based SPA authentication, MySQL Frontend: React 19, Vite, React Router v7, Tailwind CSS Testing: Pest/PHPUnit, covering auth, role enforcement, quiz CRUD, and scoring logic A Few Details I Cared About Trustworthy timers. The countdown is driven by an expiresAt timestamp from the server, not Date.now() on the client. Refreshing the page or messing with local state doesn't buy extra time — the quiz still auto-submits the moment the server-side deadline passes. Server-side authority. Roles are never trusted from the client; they're always assigned on the backend. The is_correct flag on quiz options is stripped from every API response sent to non-admin users, so there's no way to peek at answers through the network tab. Layered access control. Admin routes are protected twice — once by Sanctum's auth middleware, and again by a dedicated AdminMiddleware — and the whole session model avoids storing any tokens in localStorage. Real test coverage. The scoring logic is tested against all-correct, all-incorrect, all-skipped, and mixed-answer scenarios, alongside leaderboard ranking and role-based access.