An academy management app that works with zero signal.
Mitróo is an offline-first Android app for running a coaching academy — students, attendance and fees — built on a real SQLite database that lives on the phone, with encrypted backups to the owner's own Google Drive. A solo build: product, React client, framework-free PHP API, MySQL schema and Play Store billing, end to end.

Dashboard — active students, attendance and fees at a glance
A real database on the phone, not a wrapper around a spreadsheet.
Mitróo is a single-tenant Android app — one Google Play install maps to one business account, one owner, no staff roles and no admin console. It exists to replace the notebook and the spreadsheet that most small coaching academies still run on.
The client is a React 18.3.1 + TypeScript app built with Vite and packaged as a native Android app through Capacitor. The core decision that shapes everything else: SQLite itself, compiled to WebAssembly, runs inside the app — so attendance, students and fees are stored in a real relational database on the device, not just cached JSON.
A framework-free PHP 8 REST API and a 9-table MySQL database sit behind it, handling authentication, subscription billing and encrypted cloud backups — but the day-to-day workflow of registering a student, marking attendance or logging a fee never has to touch the network at all.
Solo builder, every layer of the stack.
Application Architecture
Designed the offline-first split — an on-device SQLite database for daily workflows, a framework-free PHP API for everything that has to live on a server.
UI & Interaction Design
Designed all 14 screens and the 5-tab bottom navigation, including low-end-device performance gates for animation and list rendering.
Backend API
Built the PHP 8 REST API by hand — 19 routes across 8 controllers, PDO against a 9-table MySQL schema, no ORM or migration tool.
Authentication
Implemented the email-OTP → bcrypt-hashed PIN → hand-rolled JWT session flow, plus optional fingerprint biometric unlock.
Cloud Backup Pipeline
Built the AES-256-CBC encrypted backup flow to a per-user Google Drive folder, with a 12-hour client-driven, server-enforced cadence.
Billing Integration
Integrated Google Play Billing for a non-consumable lifetime purchase, verified server-side against the Android Publisher API.
Native Build & Deployment
Packaged the React client as a native Android app with Capacitor and shipped it to Google Play.
Testing
Validated the offline data layer, sync behavior and billing edge cases by hand across low- and high-end Android devices.
Four real problems, four shipped fixes.
Grounded in the same problem/solution pairs documented in the case study brief.
Attendance and fee records live in a notebook or a spreadsheet, with no backup if the phone or the book is lost.
SolutionA client-side SQLite database, compiled to WebAssembly, gives every academy a real, structured, offline-first database on the phone itself — no dependency on a signal to keep working.
Faster daily operations — attendance and fees get logged the moment they happen, offline.
Spreadsheet tools require a live connection and manual discipline to keep records safe and current.
SolutionAn automatic, AES-256-CBC encrypted backup to the owner's own Google Drive runs every 12 hours, client-driven with a server-enforced minimum interval.
Lower data-loss risk — the owner's records survive a lost, damaged or replaced phone.
Following up on an unpaid fee means digging through a register for a phone number, then dialing manually.
SolutionA one-tap WhatsApp deep link sits directly on a student's fee record.
Frictionless follow-up — collecting a pending fee is a single tap, not a lookup-and-dial.
Moving to a new phone, or onboarding an academy that already has a spreadsheet, means retyping every student by hand.
SolutionBuilt-in CSV bulk import and export, plus a downloadable template, moves a full roster in or out in one action.
Lower switching cost — a full student roster moves in minutes, not hours.
From first sign-up to a phone lost and restored.
The real, end-to-end path an academy owner takes through the app.
Register the business
The owner signs up with a business email — one account, one device, one role.
Verify with a one-time code
A 6-digit OTP, valid for 5 minutes, is sent by email to confirm the account.
Set a 4-digit PIN
The PIN is bcrypt-hashed before storage and becomes the everyday unlock, with optional fingerprint biometric on top.
Configure the academy
Categories, Batches and Timings are defined once, up front, then reused across every student record.
Register students
Personal and academy info is captured per student and written straight to the on-device SQLite database.
Run daily attendance
Present/Absent is marked against the live roster, entirely offline, with a running tally on screen.
Collect and log fees
A payment is recorded with an amount and mode, and the daily total updates instantly.
Check the Dashboard
Active students, today's attendance and this month's fees are visible at a glance.
Export or import in bulk
A full roster or a day's fee sheet moves out as CSV — or a new one moves in — via the native Android share sheet.
Back up automatically
Every 12 hours, an encrypted snapshot of the whole database is pushed to the owner's own Google Drive.
Move to a new phone, or return after a break
The latest backup restores in one action, and the owner picks up exactly where they left off.
Everything the app ships with.
No roadmap items — every card below is live, on Google Play.
Authentication & Device Security
Email OTP, a bcrypt-hashed 4-digit PIN, and optional fingerprint unlock, wrapped in a hand-rolled JWT session.
capacitor-native-biometric · bcrypt · HMAC-SHA256 JWT
Offline Student Registry
A full student roster that reads and writes to an on-device SQLite database — works with zero signal.
sql.js (SQLite via WebAssembly) · localStorage persistence
Daily Attendance
Present/Absent marked against the live roster with a running tally, no connectivity required.
SQLite attendance_records table · hand-rolled list virtualization
Fee Collection & Reporting
Log a payment, pick a mode, and watch the daily and monthly totals update instantly.
SQLite fee_transactions table · CSV export
Cloud Backup & Restore
An AES-256-CBC encrypted snapshot of the whole database, pushed to the owner's own Google Drive every 12 hours.
google/apiclient (PHP) · Google Drive API · per-user folder
CSV Bulk Import / Export
Move a full student roster or a fee sheet in or out in one action, with a downloadable template.
Client-side CSV parsing · native Android share sheet
Academy Taxonomy
Categories, Batches and Timings are defined once, then reused across every student record.
SQLite lookup tables · Manage Academy Setup screen
Subscription & In-App Purchase
A ₹250 one-time, lifetime unlock through Google Play Billing, verified server-side.
cordova-plugin-purchase · Android Publisher API verification
WhatsApp Quick Contact
A one-tap deep link from a student record straight into WhatsApp, for fee follow-ups.
Native WhatsApp deep linking
Customer Support Channel
An in-app support form that emails the owner's message straight to the team.
PHPMailer over SMTP
Every screen, organized by category.
All 14 in-app screens, plus the public help and legal pages — every real screenshot supplied, used once.

PIN Lock
The everyday unlock screen — a 4-digit PIN keypad with an optional fingerprint shortcut.

Forgot / Reset PIN
Recovery flow — the owner enters their registered email to receive a reset code.

Dashboard
Active students, today's attendance and this month's fees, plus quick-access tiles into every core workflow.

Register Student — Personal Info
First name, last name, mobile, email and date of birth for a new student.

Register Student — Academy Info
Gender, Category, Batch and Timing selection, with a note field and Save & Add Another.

Students List — Actions
Per-student context menu — Edit, Mark Inactive or Delete, without leaving the list.

Student Detail
Full record view — mobile, email, date of birth, gender, category, batch and timing.

Edit Student
The registration form, pre-filled, for updating an existing student's details.

Delete Student
A confirmation step that guards against accidentally losing a student's record.

Students — Export
The native Android share sheet, triggered to export the full roster as a CSV file.

Attendance
Mark Present or Absent against the live roster, with a running Present / Absent / Unmarked tally.

Fees — Daily View
The day's total collected, every transaction logged, and a floating action button to add another.

Add Fee
Pick a student, enter the amount, choose a payment mode — logged in seconds.

Fees — Export
The native share sheet, triggered to export a dated CSV of the day's fee transactions.

Settings
Profile details plus links into Import Data, Backup & Restore, Academy Setup, Subscription and Support.

Manage Academy Setup
Where Categories, Batches and Timings are created and edited for the whole academy.

Import Data
Import a CSV file, export the full student list, or download a ready-made CSV template.

Backup & Restore
Cloud backup status and a one-tap Restore Latest action.

Customer Support
A support-ticket composer that emails the owner's message straight to the team.

Mitróo Help Guide
The mobile help site at troo.u2verse.com — Getting Started, Login, Free vs Pro, and a walkthrough of every core screen.

Privacy Policy
The published privacy policy, effective 28 Feb 2026.

Terms & Conditions
The published terms of service governing use of the app.
How the pieces fit together.
Offline-first on the device, server-backed for identity, backup and billing.
Mobile App
A React 18 + TypeScript client, packaged as a native Android app via Capacitor 8.
On-Device SQLite
SQLite compiled to WebAssembly (sql.js), serialized into a single localStorage key — the offline system of record.
PHP REST API
A framework-free PHP 8 API — 19 hand-routed endpoints across 8 controllers, no ORM.
MySQL
9 tables on the server side — users, devices, plans, subscriptions, backups and more.
Google Drive & Play Billing
Encrypted backups via the Google Drive API, and purchase verification via the Android Publisher API.
The decisions that made offline-first actually work.
Offline-first by construction
Not "offline-tolerant" — the entire core workflow works before any network call succeeds.
Framework-free PHP backend
No Laravel or Symfony — a deliberately small, auditable footprint of 19 routes across 8 controllers.
Client-side SQLite via WebAssembly
A real relational database compiled to run inside the WebView, serialized into a single localStorage key.
Self-healing local database
A foreign-key violation triggers an automatic wipe-and-reinitialize instead of a crash.
Legacy-data migration
First launch after an update silently migrates any pre-SQLite localStorage JSON into the new schema.
Server-verified billing
Every purchase is re-checked against the Android Publisher API and auto-acknowledged — the client's own success event is never trusted alone.
Multi-host API failover
Requests race across multiple hosts with a 20-second timeout, so a single DNS or server hiccup can't strand the app.
Hand-rolled JWT sessions
No external JWT library — HMAC-SHA256 signing and verification implemented directly against a 24-hour session model.
Six hard problems, and what shipped.
Every trade-off documented honestly — including the ones taken deliberately.
Offline Data Layer
Give a mobile web app a real, relational, offline database without a native SDK.
Compile SQLite itself to WebAssembly (sql.js) and run it inside the Capacitor WebView.
Three real tables — students, attendance_records, fee_transactions — persisted as a serialized blob in localStorage, with self-healing on corruption.
Performance on Low-End Hardware
Android devices in this market span multiple hardware generations, and a laggy list kills trust in the product.
Detect device capability at runtime (navigator.hardwareConcurrency / deviceMemory) and gate animations accordingly, plus hand-roll list virtualization for Students, Attendance and Fees.
Long rosters stay smooth even on entry-level devices.
Billing Edge Cases
A client-reported "purchase successful" event can't be trusted on its own — Play purchases can fail to acknowledge or be replayed.
Verify every purchase server-side against the Android Publisher API before unlocking anything, with auto-acknowledgement built in.
The lifetime unlock can't be spoofed from the client.
Authentication State
Balance a lightweight, hand-rolled auth stack against real security, without the overhead of a full auth provider.
OTP → bcrypt-hashed PIN → hand-rolled HMAC-SHA256 JWT, with a fixed 24-hour expiry and optional biometric unlock layered on top.
A session model with no external dependency — at the cost of no refresh-token rotation, a documented trade-off rather than an oversight.
Native Integration
Ship a genuinely native-feeling Android experience from a web codebase.
Capacitor wraps the React client, with native plugins for biometrics (capacitor-native-biometric) and in-app purchases (cordova-plugin-purchase).
Fingerprint unlock and Play Billing behave like native features, not web shims.
Backend Design Constraints
Keep the server side simple enough for one person to operate, without an ORM, migration tool or framework.
Framework-free PHP 8 with PDO, 19 hand-routed endpoints across 8 controllers, and 9 explicitly-designed MySQL tables.
A backend with a small, auditable surface area — every route and query is traceable by hand.
Built for the phone actually in the owner's hand.
Optimized for a wide spread of Android hardware — not just the newest devices.
Hand-rolled list virtualization
Only the rows actually on screen are rendered.
Students, Attendance and Fees lists
Low-end device detection
Animation is disabled or simplified on weaker hardware.
Gated by navigator.hardwareConcurrency / deviceMemory
Debounced search
Cuts redundant re-renders while typing.
220ms debounce across search inputs
Memoization
Avoids recomputing expensive derived values on every render.
Component-level React memoization
Optimistic UI
The interface updates before the server confirms.
Attendance and fee actions
Multi-host API failover
A single bad host doesn't stall the app.
Requests race across hosts with a 20s timeout
Serialized single-key persistence
One read/write instead of many.
The entire SQLite database, persisted as one localStorage key
Verification at every entry point.
From account creation to a Google Play purchase, nothing is trusted on the client's word alone.
OTP-gated registration
Every new account is verified with a 6-digit, time-boxed (5-minute) one-time code before it can do anything.
PIN, not a password
Day-to-day unlock uses a 4-digit PIN, hashed with bcrypt before it ever touches storage.
Optional biometric unlock
Fingerprint unlock layers on top of the PIN via capacitor-native-biometric, on devices that support it.
Encrypted cloud backups
Every backup pushed to Google Drive is AES-256-CBC encrypted before it leaves the device.
Server-verified purchases
Every Google Play purchase is independently re-checked against the Android Publisher API — the client's own success event is never trusted alone.
Signed sessions
Every session is a JWT, signed and verified with HMAC-SHA256, with a fixed 24-hour expiry.
Rate-limited verification
OTP verification attempts are capped, so a code can't be brute-forced.
A lean, hand-built stack — no ORM, no framework padding.
React + Capacitor on the device, framework-free PHP and MySQL on the server.
React
18.3.1Core UI library driving all 14 screens.
TypeScript
5.8.3Type safety across the entire client codebase.
Vite
5.4.19Build tooling and dev server.
Capacitor
8.0.2Wraps the React client as a native Android app.
react-router-dom
6.30.1Client-side routing across every screen.
Tailwind CSS
3.4.17Utility-first styling.
shadcn/ui + Radix
~46 primitivesAccessible component primitives underlying the UI.
Framer Motion
12.33.0Screen and micro-interaction animation.
sql.js
1.13.0SQLite compiled to WebAssembly — the on-device database engine.
capacitor-native-biometric
4.2.2Native fingerprint unlock.
cordova-plugin-purchase
13.13.0Google Play Billing integration.
PHP
^8.0 / ^8.1Framework-free REST API — 19 routes across 8 controllers.
MySQL
9 tablesServer of record — users, devices, plans, subscriptions, backups and more.
google/apiclient
v2.19.0Google Drive API integration for encrypted backups.
PHPMailer
v7.0.2Transactional email — OTP codes and support tickets, over SMTP.
The build, in numbers.
Before and after.
Real operational shifts — not invented percentages.
Attendance and fees tracked in a notebook or spreadsheet, with no backup.
A structured, offline-first database with automatic 12-hourly encrypted backups.
No visibility into cash position without manually totalling a register.
A live Dashboard showing today's attendance and this month's fees at a glance.
Losing a phone meant losing every student record.
A one-tap restore from the owner's own encrypted Google Drive backup.
Chasing an unpaid fee meant finding a number and dialing manually.
A one-tap WhatsApp deep link straight from the student's fee record.
Onboarding a new academy meant retyping every student by hand.
A full roster moves in via CSV import in minutes.
No sustainable way to monetize the product.
A server-verified, one-time Google Play purchase — ₹250 for a lifetime unlock.
A real database in your pocket, not just an app.
Mitróo started from a simple observation: most small academies run on a notebook, a spreadsheet, or a memory that only the owner has. That's fragile the moment a phone is lost, a page is torn, or the owner is unreachable.
Building it offline-first meant the hard problem wasn't the UI — it was giving a web-based mobile app a real, structured, relational database that works with zero signal, then keeping that data safe with encrypted, automatic backups the owner never has to think about.
It shipped as a solo build — product design, the React client, the framework-free PHP API, the MySQL schema, native Android packaging and Play Store billing — end to end, and is live on Google Play today.
