Case study · Freelance · sole developer
Solar operations platform & field app
Field teams at an electrical company recorded their daily work in diaries, paper records and WhatsApp groups.
- temporary contractors
- 350–400
- staff users
- ~50
Context
The client is an electrical company that also operates and maintains plants for their owners and runs electrical field crews. Before this platform, field staff kept diaries and paper records and reported through WhatsApp groups.
As the sole developer I designed the product, the data model and every layer of the stack: a multi-organisation web platform and an Android field app. Plant teams log and analyse performance, field staff post updates and upload data directly from the app, and managers review, approve and export everything. I continue to maintain it.
What I built
- O&M portal
- Per-plant dashboard, daily inverter entry with Excel import templates, a performance log (curtailment, breakdowns, scheduled offs), ABT meters, module-cleaning cycles, SLDC reconciliation, checklists, spares with low-stock alerts, insurance covers and generated reports.
- People & attendance
- Geofenced clock-in and clock-out with photo capture, team and organisation attendance with Excel export, and expense claims with a review workflow.
- Work reports
- Daily field work reports with task rates, work orders and ledgers, a review and lock workflow, finance roll-ups by financial year or month, and register exports to Excel and PDF.
- Field app
- A Flutter app for Android that covers attendance and all the O&M modules, used daily by field employees.
- Administration
- Organisations and members with Excel bulk import, roles and permissions, per-project access grids with reusable access profiles, SMTP delivery logs, rate limits, telemetry and notifications.
- Correct numbers
- Derived figures such as CUF, kWh/kWp, ABT energy and cleaning cycles are never stored. Pure, unit-tested modules compute them from raw readings, and no write is accepted for a day that hasn't happened yet.
Architecture
Clients
React 19 + Vite SPA
- Tailwind v4 · shadcn/ui
Flutter field app
- Android
- attendance · O&M modules
Application
Express 5 API — N stateless instances
- routes → controller → service → repo (raw SQL)
- zod validation · DTO redaction
- JWT + rotating refresh · e-mail OTP MFA
- permission grants · per-plant access
- append-only audit log · notifications
- idempotent schedulers (claim-then-send)
- Excel / PDF renderers
- readiness/liveness · graceful drain
Data & services
PostgreSQL
- UTC, advisory-locked
Redis
- tokens · atomic rate limits
File storage · SMTP pool
OpenTelemetry → SigNoz
Key decisions
Safe to run as many instances
Rate limiting is atomic in Redis, migrations and seeds take Postgres advisory locks, and background senders claim each due e-mail with INSERT … ON CONFLICT DO NOTHING, so any number of instances never double-send and a restart catches up. Readiness and liveness probes, graceful shutdown and request tracing complete the picture.
Zero-trust access control and an immutable audit trail
Authentication runs on JWT access tokens with refresh-token rotation and e-mail OTP multi-factor authentication. Fine-grained role-based access control (RBAC) with direct permission grants, scoped to the project stages a user is assigned to, is enforced server-side on every request, and least-privilege delegation means no one can grant more than they hold. Every mutation lands in an immutable, append-only audit log enforced by database triggers.
Results
- In production, used by about 50 staff users and 350–400 temporary contractors across site locations.
- Replaced diaries, paper records and WhatsApp groups: field staff post updates and upload data directly from the Android app, which they use daily.
- Built by me as the sole developer, and I continue to maintain it.