FMCG Distribution · Live · Trivandrum
AdoniBook — From paper notebooks to one live app
Built alongside Adoni Traders, a Trivandrum distributor that delivers soaps, biscuits, snacks and everyday goods to hundreds of small shops. What started as their internal tool is now a product any route-based distributor can run.
The challenge
Every day a salesman takes orders on the beat, the office makes bills, the godown packs and loads vehicles, the delivery team drops goods and collects money, and the owner keeps track of who still owes what. All of it ran on paper notebooks, Excel sheets and phone calls. Entries went missing between stages, totals didn't match, credit lived in a notebook, and the owner couldn't see the day until it was already over.
What we built
One Flutter app for the whole team, on Android and the web. Everyone logs in with their phone number and sees only the screens their job needs, while the owner sees everything live. The order-to-cash pipeline is chained so that each stage creates the next stage's work — nobody passes paper to the warehouse again.
A normal day in the app
- Plan — the owner assigns each salesman's beat, the vehicle, driver and delivery man, and any special task; staff acknowledge it on their home screen.
- Take orders — the salesman sees today's shops in visiting order and records the order, any payment, or a skip with a reason. No signal? Entries save on the phone and sync on reconnect.
- Bill, pack, load — each bill lands on the packing list automatically; packing and loading notify the owner when a route is done.
- Deliver & collect — the delivery man sees only the bills loaded on their vehicle and records cash, UPI, cheque, credit or part payment, with a warning before a shop crosses its credit limit.
- Close the day — an end-of-day submission goes to the owner, who approves it in one go or line by line. Anything unpaid moves into the credit ledger.
Who uses it
- Owner — daily assignments, collection approval, credit ledger, cheque tracker, staff, payroll and reports.
- Field & office staff — salesman, billing, packing, godown, delivery man and driver, each with a home screen built for that job.
- Everyone — a personal "Me" tab to mark attendance, apply for leave and download a PDF payslip.
Engineering decisions
- Money moves once. A shop's balance updates inside a Firestore transaction at the point of entry; the owner's approval verifies it but never counts it again. Cheque bounces add the amount back automatically.
- Nothing important is erased. Security rules block hard deletes on shops, routes, orders, collections and the ledger, and every edited entry keeps its previous version.
- Roles are data, not code. Every screen and button is gated on one of around 40 permissions, so the owner can invent a job type — or give one driver extra loading duties — with no app update. Changes apply instantly.
- Built to be resold. A multi-tenant data model and white-label build config let one Android app and one web app serve many distributor companies, each seeing only its own data.
- Reports owners actually use. Daily and weekly summaries by route, exported to PDF or Excel, or copied as a ready-to-send WhatsApp message.
Flutter
Flutter Web
Firebase Firestore
Offline-first
Role-based access
Multi-tenant
PDF & Excel
Notebooks, Excel sheets and phone calls replaced end to end — from the salesman's beat to the owner's credit book. Running daily at Adoni Traders, and now available to distributors in FMCG, pharma, dairy, hardware and agri-inputs as AdoniBook.
B2B FMCG Network · Pilot · Thiruvananthapuram
AdoniHub — Every brand. One order. The right distributor.
A three-sided ordering network we designed, built and run, connecting FMCG brands, their authorised distributors and the retail shops they supply. One rule holds it together: for any product in any delivery area, exactly one distributor may sell it.
The challenge
FMCG distribution in Kerala still runs on salesman visits, phone calls and WhatsApp. Shops juggle a different salesman, visit day and number for every brand, face minimum order quantities, and only discover short supply when the van arrives. Distributors re-type orders from diaries and settle territory disputes by argument or price cuts. Brands have no reliable map of who sells which product where — and demand from areas nobody covers never shows up anywhere.
What we built
A Flutter shop app for Android and iPhone, a Flutter Web panel for brands and distributors, and a separate control room for the platform team. Shops order every brand they stock from one cart; the platform splits it into one sub-order per distributor and routes each line to the one distributor the brand has authorised for that product in the shop's area.
How an order flows
- Drop a pin — a shop signs up with a phone one-time code and marks its location (or enters its PIN code), placing it in exactly one delivery area drawn on the map.
- One cart — the catalogue shows every active product with a clear status: order now, waiting for the distributor's approval, or the platform will assign a distributor. No minimum quantity.
- Split & route — each line resolves by a single lookup: this product, in this shop's area, today gives the authorised distributor.
- Confirm what's real — each distributor edits lines to what it can supply, so the shop sees "ordered 24, confirmed 12" before dispatch. Then accept, dispatch, deliver, with GST invoices raised automatically.
- Capture the gaps — lines nobody covers wait as "awaiting routing" and open a conflict for the platform team, while brands see that unmet demand as coverage gaps by area.
Who uses it
- Brands — authorise distributors per product or brand-wide, hold prices between MRP and a floor, schedule territory handovers, and see sales and coverage gaps by area.
- Distributors — receive orders already routed to them, claim areas on the map, approve shops, set per-shop credit limits, take COD, credit or prepaid, handle returns, and give order-desk staff their own logins.
- Shops — grocery, supermarket, bakery, medical and wholesale: order any quantity, track each distributor's part of the order, cancel, return and raise support requests, with push notifications.
- Platform team — draw delivery areas, verify distributors and shops, grant and transfer authorisations, and resolve four kinds of conflict from one desk.
Engineering decisions
- Business rules live in the database. Around 170 PostgreSQL procedures handle validation, pricing, tax, state machines and exclusivity. The Node.js API is a thin gateway for auth, OTP, rate limits and push.
- Exclusivity is enforced, not promised. Unique indexes make it impossible for two distributors to hold the same product in the same area; overlapping claims become conflicts for a person to decide.
- Resolve early, freeze at order. Order lines keep the price, tax and authorisation they were placed with, so a later territory transfer never rewrites history.
- No silent fallback. A declined line is shown to the shop, never quietly rerouted to someone else.
- Tenant fences everywhere. Each procedure re-checks that the caller owns the rows it touches, and every change lands in an audit log. Every endpoint and role is covered by API tests that also generate the OpenAPI docs.
Flutter
Flutter Web
PostgreSQL 16
Node.js / Express
Firebase Cloud Messaging
OpenStreetMap
OpenAPI
Now piloting in Thiruvananthapuram, Kerala, and onboarding brands, distributors and shops. One cart in, the right distributor out — and demand in uncovered areas is captured instead of lost. See AdoniHub.
Own product · Live on Google Play
Teky Card — A business card that never goes out of date
Teky Card is the digital business card inside QR Teky, our offline-first QR app. One permanent link holds your contact details and links. Share it as a QR code, an NFC tap or a plain link, and the person on the other end needs no app and no account.
The challenge
Paper business cards run out, go stale the day you change your number, and get thrown away. Most digital-card apps fix one of those problems and create another: the recipient has to install something, the QR changes every time you edit, or a simple scanner quietly sends your history to a server. We wanted a card you set up once, keep current forever, and that opens instantly on any phone, inside a QR app that stays private by default.
What we built
A Flutter app for Android and iOS with three everyday tools — scan, generate and history — that run entirely on the device and never ask for an account. Teky Card, Teky Letters and history backup sit behind an optional sign-in that nothing else depends on. The recipient side is a deliberately plain HTML, CSS and JavaScript site at qrteky.appteky.com, so a card opens in one round trip even on weak mobile signal.
How a Teky Card works
- See it first — a labelled sample card shows exactly what a recipient gets before you're asked to sign in.
- Add your details — name, role, company and a short bio, then phone, email, location, website and optional WhatsApp, LinkedIn or Instagram links, with a live preview as you type.
- Pick a look — Personal or Business styles, with themed previews and a designer that frames your QR for printing or posting.
- Share it your way — show a full-screen QR, share the link, or write it to an NFC tag.
- Edit any time — every QR, tag and link already out there keeps pointing to the same card, now showing your new details. Recipients can save you as a contact (VCF) in one tap.
Also in QR Teky
- QR Studio — templates for website, Wi-Fi, email, phone and SMS; six palettes, custom shapes and a logo overlay, exported as high-resolution PNGs.
- Fast scanning — live camera scanning with torch and camera switch, results in a bottom sheet, and links opened in a built-in browser.
- Teky Letters — a private message that unlocks with a secret word and types itself out for the recipient, plus occasion templates for birthdays, invitations and thank-yous.
- Saved cards & history — cards you receive are kept on the phone and searchable, alongside your last 100 scanned and generated codes.
Engineering decisions
- One canonical URL. Every QR, NFC tag and share link is built from a single constant, and older hostnames stay recognised, so codes printed before the custom domain still resolve.
- Private by default. QR content and history never leave the phone unless you sign in and switch on backup. A cold start touches no cloud service at all.
- Real end-to-end encryption. Letters are encrypted on the phone (PBKDF2-SHA256 with 210,000 iterations into AES-256-GCM). Firestore only ever stores ciphertext; the recipient's browser decrypts it with WebCrypto.
- A tiny recipient page. Page, styles, scripts and data client add up to about 24 KB — less than the Firebase JS SDK alone.
- Tested across languages. The Dart and JavaScript crypto are pinned to one shared test fixture, so the app and the web page can never drift apart.
Flutter
Firebase
ML Kit scanning
NFC
AES-256-GCM
WebCrypto
Vanilla JS web
Live on Google Play as part of QR Teky — free, with no ads and no account needed. One link to keep up to date, and every code you have ever printed keeps working.
Own product · Marketplace · Early access
YoloPets — Pet care, bookings and a pet store in one app
A pet-care marketplace and community with four parts: a mobile app for pet owners, a web panel for stores and service providers, an admin console for the platform team, and a marketing site where businesses apply to become partners — all on one API.
The challenge
Pet owners keep vaccination dates in their heads, book grooming over the phone, buy food from a different shop again, and post lost-pet alerts in WhatsApp groups that scroll away in an hour. Groomers, vets, trainers and pet shops each run their own bookings and stock with no shared place to be found. We wanted one app for the owner and one panel for the business, with the marketplace rules enforced on the server.
What we built
A Flutter app for Android and iPhone, one Flutter Web codebase that builds both the Store Panel and the Admin Panel, a single-page marketing site with a partner application form, and a Node.js API on MongoDB with Socket.IO for live updates.
What a pet owner can do
- Keep health records — vaccinations, check-ups and surgeries per pet, with the next vet visit on the home screen and a "needs attention" flag when it is overdue.
- Book services — find vets, groomers, trainers and boarding sorted by distance or on a map, then pick a real free slot built from the store's hours, service length and capacity.
- Shop — browse products with live stock, check out once, and the cart splits into one order per store.
- Join the community — post photos, comment, report a lost pet with last-seen details, and chat live with other owners.
- Ask the assistant — an AI pet-care assistant, built on Google Gemini, answers everyday questions.
Who uses it
- Pet owners — the mobile app: pets, bookings, orders, community, chat and push notifications.
- Stores & service providers — the Store Panel: services, slots, products and stock, bookings, orders, reports and reviews, with live alerts for new work.
- Platform team — the Admin Panel: partner applications, stores, catalogue, users, orders, bookings, community moderation and reports.
- New partners — apply on the website; one approval creates the store and gives the owner a panel login.
Engineering decisions
- The server owns the money. Prices and totals come from the database, stock is reserved atomically at checkout, and a booking must match a free slot, so double bookings can't happen.
- Sessions that can be revoked. Phone OTP sign-in issues one-hour access tokens and 30-day refresh tokens; reusing an old refresh token signs that user out everywhere.
- Live by default. Chat, orders and bookings arrive over Socket.IO in the app and panels, and as push notifications on phones.
- Abuse limits built in. Rate limits on OTP, posts, messages, uploads and AI, and a honeypot that drops spam partner applications.
- Covered by tests. 107 documented endpoints with integration tests and a matching Postman collection, all run in CI on every push.
Flutter
Flutter Web
Node.js / Express
MongoDB
Socket.IO
Firebase Cloud Messaging
Google Gemini
The app, Store Panel, Admin Panel, API and partner site are all live, with the app in early access. See YoloPets.
Own product · SaaS · Live
Adoni One — A catalogue and storefront in minutes
A multi-tenant catalogue platform built in Flutter Web. We enrol a business, it shapes its own catalogue around the way its trade works, and it gets a branded storefront link to share with customers — who reach it over WhatsApp, call or email.
The challenge
Small businesses that sell over WhatsApp send product photos one by one and retype prices every time someone asks. Generic store builders force everyone into the same "price, size, colour" form, which doesn't fit a property dealer listing carpet area or a restaurant listing dishes. They needed a catalogue that speaks their trade, looks like their brand, and lives at one link.
What we built
One Flutter Web app with three parts: a hidden super-admin console where we enrol businesses, a business dashboard for categories, products, theme and settings, and a public storefront at its own link that customers browse without logging in.
How a business gets online
- Request — the business fills in a short form on the landing page; we get an email.
- Enrol — we enrol it from the admin console and receive its storefront link, dashboard login and a temporary password to hand over.
- Start from a template — categories and custom fields are seeded for the trade: fashion, real estate, restaurant or electronics.
- Build the catalogue — the product form shows the right fields for each category automatically, with image upload.
- Brand and share — pick colours, fonts and corner style, choose WhatsApp, call, email or a cart for each product, and share one link.
Who uses it
- Business owners — manage categories, custom fields, products, storefront theme, contact details and an optional cart.
- Customers — search and browse by category, see product details, and contact the business in one tap.
- Platform team — review requests, enrol businesses, switch tenants on or off, and see platform stats.
Engineering decisions
- Fields are data, not code. Each category defines its own fields, and a form generator renders them, so a new kind of business needs no new screens.
- Tenant isolation in the rules. Every business's data lives under its own tenant path, and Firestore security rules allow writes only from that owner or the super admin, while storefront reads stay public.
- Onboarding by hand, on purpose. Self-registration is off; every business is reviewed and set up for them, which keeps quality high in the early days.
- Role-aware routing. Separate route shells for storefront, dashboard and admin, with redirect guards that check the signed-in user's role.
Flutter Web
Firebase Auth
Cloud Firestore
Multi-tenant
Cloudinary
go_router
Live and onboarding businesses hands-on — each one gets a branded catalogue on its own link, set up for them. See Adoni One.
Client work · Retail promotions · UAE
Sharjah Promotions — Mall campaigns and lucky draws
A bilingual Flutter app for a city-wide retail promotion in Sharjah. Shoppers browse campaigns across malls, upload their purchase receipts and receive coupons for lucky draws. AppTeky took over ongoing development of the live app and has shipped regular releases since.
The challenge
A promotion that spans many malls lives or dies on trust and turnout. Shoppers need to see what's running and enter in seconds, in English or Arabic. Organisers need every receipt checked before it earns a coupon, without staff typing in each one. And the campaign changes every season — new events, offers and workshops — so the app has to keep up without a rebuild each time.
What we built
A Flutter app for Android, iOS and the web, fully localised in English and Arabic with right-to-left layouts. Campaigns, offers, participating malls and workshops come from the backend, so organisers can change the season without an app update. Receipt entries are checked by AI before they count.
How a shopper enters
- Browse — a home carousel of active digital raffles, each campaign with its offers, malls and workshops.
- Upload a receipt — snap or pick the receipt and enter the invoice details.
- AI checks the receipt — the image is read by Google Gemini through a Cloud Function, and each field the shopper typed, such as the amount, is compared with what the AI found.
- Get coupons — valid entries turn into coupon codes the shopper can preview, with the date they uploaded.
- Follow the draw — event details, draw dates and the shopper's own entries, all in one place.
What we've shipped
- Campaign detail — participating customers, coupon statuses and auto-scrolling coupon details.
- Lucky draws — event tokens, event details and seasonal theme colours.
- Content — an owner's message, an "About" section, a summer theme, and scrollable workshop cards.
- Store hygiene — in-app update prompts, safer handling of missing user data, and in-app account deletion as the app stores require.
Engineering decisions
- AI that checks, not decides. Validation compares what the shopper typed with what the AI read field by field, and flags mismatches instead of silently trusting either side.
- Keys stay off the device. The AI call goes through a Firebase Cloud Function, so the app never needs to hold the model key.
- Bilingual from the ground up. Every string goes through ARB localisation files in English and Arabic, with right-to-left layouts.
- Clean feature modules. BLoC state and dependency injection with separate data, domain and UI layers per feature, so several developers can ship features in parallel.
Flutter
BLoC
Firebase
Cloud Functions
Google Gemini
English & Arabic
Live on Android, iOS and the web, and moved through the 1.2 release line with new campaign, coupon and lucky-draw features each season.