Sajjad Mahessar Good Merch Group Free audit
~/sajjad $ cat projects/cleaning-ops-app ← cd ../projects Client work

Cleaning company operations app

Submitted to App ReviewThird iOS app

An iOS app for a commercial cleaning company: cleaners see the jobs assigned to them, clock in on site, work the checklist, capture before-and-after photos and take a customer signature. Forked from the pub staff platform rather than started from scratch — and then rebuilt where the domain differs.

Type
iOS app
Category
Client work
Built with
Swift / SwiftUI · Supabase · PostgreSQL + RLS · Storage · CoreLocation
Project
24 of 37
Three screens: sign-in, the join application, and a new site record
SITE ALARM AND GATE CODES STORED AGAINST THE SITE WHO CAN SEE THEM OTHER CLEANERSNEVER ASSIGNED CLEANER24H BEFORE START ADMINALWAYS ENFORCED IN ROW-LEVEL SECURITY, NOT IN THE APP A LEAKED KEY STILL CANNOT READ A CODE IT IS NOT ENTITLED TO
Sign-in, the application form, and a site record with its access instructions

The access decision

A cleaning company holds alarm codes, gate codes and key details for every site it cleans. That is the most sensitive data in the business, and it sits in a database a phone app talks to directly.

  • Cleaners can read a site’s access codes only if they are assigned to a job there, and only in the 24 hours before that job starts. Outside that window the row simply isn’t returned.
  • The rule lives in row-level security, not in the app. A leaked key, a modified client or a direct API call still can’t read a code it isn’t entitled to — the database refuses, not the interface.
  • Role checks run through helper functions rather than being repeated in every policy, so there is one definition of what an admin is and it can’t drift between tables.

Reused deliberately, isolated deliberately

The app was forked from the pub staff platform rather than started from scratch. Authentication, the clock-in flow, GPS handling, notifications and the component library carried across untouched; customers, sites, jobs, photos, signatures and hazards were rebuilt, because that domain has nothing to do with pub shifts.

The database is a separate project, not a shared one with a tenant column. No shared data, no shared auth, no shared outage — one client’s problem stays theirs. Code reuse doesn’t have to mean infrastructure reuse.

What I built

  • Fifteen domain tables with row-level security on every one, plus role helper functions and update triggers throughout; storage buckets all private with per-bucket size and type limits.
  • Sign-up as an application rather than an open door: someone requests access, an admin approves or rejects with a reason, and approval issues their credentials. Nobody self-serves into a system holding other people’s alarm codes.
  • The cleaner’s day: today’s jobs, site detail with entry instructions and hazards, GPS clock-in, mandatory before-and-after photos, checklist, consumables, customer signature, upload on completion.
  • Auto-exposure of new tables switched off and automatic row-level security switched on at the project level — so a table added in a hurry is private by default rather than public by default.

App Review

Submitted, rejected three times, and resolved each time before approval. One of those was account deletion: Apple requires any app with sign-up to let a user delete their account from inside the app, not by emailing support.

Built as a type-to-confirm sheet that spells out the consequences and calls a database function to do the deletion properly, rather than a button that just signs you out. The requirement was met as a feature rather than as a formality.

Scope, held

The full specification runs to a customer portal, automated invoicing, inventory with low-stock alerts, AI photo comparison, offline mode and a KPI dashboard.

Version one ships the cleaner-facing app only, with administration done through the database console. Everything else is written down and dated for v2 and v3 — a scope list is only useful if something is actually on the other side of the line.
iOS app + web

White-label staff app, second group

The staff app for a second group, now on the web too

Swift / SwiftUISupabasePostgreSQL + RLSCoreLocation
Android app

Rota, wages & profit app for a cleaning company

Rotas, wages and profit per clean

React Native / ExpoTypeScriptSupabasepg_cron
No charge

I’ll find the money before you pay me anything.

Send me your software subscriptions and I’ll come back with what’s replaceable and what it’s worth — free, and yours to keep either way. How it works →

Contact

Want the same done to your cost base?

Open to operations, automation and technical operations roles — and to talking with anyone running a multi-site business who suspects they're paying for software they could own instead.