All work
Multi-Tenant SaaS · POSEnterprise SaaSCase study

Haazir Billing — GST Billing & Inventory Platform

Runs an Indian shop's billing, GST and stock across a desktop, a phone, a POS terminal and the web — from one shared codebase.

Multi-tenant GST billing, inventory, sales/purchase, returns and reporting for Indian businesses. One Fastify API serves a Flutter app family (Windows desktop, Android/iOS mobile, Android POS), a Next.js responsive web app and a super-admin panel — five surfaces from a single shared core.

Microsoft StoreSource private
Haazir Billing — GST Billing & Inventory Platform interface
Industry
Retail / SMB
Role
Architect & Full-Stack Engineer
Type
SaaS Platform
Year
2025 — present
Status
Maintained
5 from one core
Surfaces
Per-shop scoped
Tenancy
Microsoft Store
Published

Overview

Haazir Billing is a multi-tenant billing and inventory platform for Indian retail, grocery, medical, hardware and wholesale businesses. It covers GST invoicing, estimates, purchases and receive-stock, credit and debit notes, party ledgers and discounts, bank accounts and transactions, expenses, staff permissions and reporting.

The architecture is what makes five surfaces maintainable by one person. The three Flutter apps — Windows desktop, Android/iOS mobile and Android POS — are thin shells over a single shared core package that holds every model, service, provider, screen and the theme; each app's entry point is one line. A Next.js web app replicates the desktop experience for the browser, and a separate Next.js super-admin panel manages the platform. All of them speak to one Fastify API over JWT plus a shop-id header, so a feature lands once and appears everywhere.

Multi-tenancy is per-shop: every request is scoped by shop id, with admin and staff roles carrying per-feature permissions. Sessions and hot data sit in Redis; MySQL via Sequelize holds the domain. Login is OTP over WhatsApp, and the same WhatsApp integration delivers invoices, with Firebase handling push.

The Windows build is published on the Microsoft Store, and the desktop and POS surfaces keep working through connectivity gaps — which for a counter is the difference between trading and not.

The problem

The same billing product was needed on a shop desktop, a phone, a touch POS terminal and the web. Building four applications separately would have meant four codebases drifting apart, and a feature request landing four times — while the business still needed GST compliance, stock and party ledgers to agree across all of them.

Discovery

Separated what is genuinely platform-specific — window chrome, printer access, touch target sizing — from what is not, and found almost everything else (models, services, state, screens, theme) was identical across the three Flutter targets.

The solution

Put every model, service, provider, screen and the theme into one shared Flutter core package and reduced each of the three apps to a one-line entry point. A Next.js web app replicates the desktop experience for the browser, and all surfaces — plus a super-admin panel — talk to one Fastify API scoped per shop.

Technical stack

Frontend

  • Flutter
  • Riverpod
  • Next.js 16
  • React 19
  • TypeScript
  • Tailwind CSS 4
  • TanStack Query

Backend

  • Fastify 5
  • Node.js
  • Sequelize

Data

  • MySQL
  • Redis

Infrastructure

  • Docker

System architecture

  1. 1

    Fastify 5 REST API at /api/v1 over MySQL (Sequelize) with Redis for sessions and cache

  2. 2

    JWT bearer auth plus an x-shop-id header — every request is tenant-scoped

  3. 3

    Three Flutter apps (Windows, Android/iOS, Android POS) as thin shells over one shared core package

  4. 4

    Next.js 16 responsive web app mirroring the desktop surface

  5. 5

    Separate Next.js super-admin panel for platform-level management

  6. 6

    WhatsApp Business API for OTP login and invoice delivery; Firebase FCM for push

  7. 7

    Consistent response envelope with top-level pagination on list endpoints

Engineering challenges

Challenge

Four client applications meant every feature had to be built and fixed four times, and they drifted apart in the gaps.

How I solved it

Collapsed the three Flutter targets onto one shared core package holding all UI and logic, leaving each app as a one-line shell — so a screen is written once and ships to desktop, mobile and POS together.

Challenge

Tenant scoping spread across handlers is one forgotten filter away from a shop seeing another shop's sales.

How I solved it

Made the shop id part of the request contract as a required header alongside the JWT, so scoping is applied at the boundary rather than remembered per query.

Challenge

Shopkeepers do not reliably have email, and password resets over SMS were an extra vendor and cost.

How I solved it

Used WhatsApp for OTP login and for delivering invoices — one integration covering both authentication and customer delivery on the channel the users already live in.

Core features

  • Five surfaces from one shared core — Windows, Android, iOS, POS and web
  • Multi-tenant: every request scoped by shop, with admin/staff per-feature permissions
  • GST billing, estimates, credit and debit notes
  • Inventory, receive-stock, purchases and returns
  • Party contacts with ledgers and per-party discounts
  • Bank accounts, transactions and expense tracking
  • Reporting across sales, purchases, stock and money
  • OTP login over WhatsApp; invoices delivered on the same channel
  • Redis-backed sessions and caching behind a Fastify REST API
  • Super-admin panel for platform-level shop management
  • Published on the Microsoft Store

Results & impact

One codebase serves five surfaces, so a shop can bill on a desktop, a phone, a POS terminal or the browser and see the same stock and ledgers. The Windows build is on the Microsoft Store, and the counter keeps trading through connectivity gaps.

Screenshots

Haazir Billing — GST Billing & Inventory Platform screenshot 1
Haazir Billing — GST Billing & Inventory Platform screenshot 2
Haazir Billing — GST Billing & Inventory Platform screenshot 3
Haazir Billing — GST Billing & Inventory Platform screenshot 4
Haazir Billing — GST Billing & Inventory Platform screenshot 5
Haazir Billing — GST Billing & Inventory Platform screenshot 6

What I learned

  • A shared core with thin platform shells is what makes a four-surface product maintainable by a small team.
  • Putting the tenant key in the request contract beats trusting every handler to scope its own queries.
  • Choosing the channel users already use — WhatsApp — removed both a vendor and a support burden.

Related work

All projects
Next step

Have a system like this to build?

I take projects from the first conversation through to production, and stay on for the support that follows.