Skip to content
AFM Studio
GovernmentPlatformWeb App

Montara

Construction monitoring platform tracking every IKN infrastructure project through a five-role approval workflow

All projects3 min read

Role

Fullstack Developer

Timeframe

May – Jul 2026

Private / internal system
On this page

The problem

IKN Nusantara's construction program spans dozens of contractors building infrastructure at once, and the people tracking it fall into groups with genuinely different needs and different levels of trust. Contractors need to report physical and financial progress on the projects they own. PPK (the government contracting officer) needs to approve or reject what contractors submit — but only for projects under their scope, with an audit trail, because these are government commitments. Compliance staff and executives need aggregate, trustworthy dashboards without wading through raw project data. Nobody had a system that enforced who could change what, with a real approval workflow and an audit log — which is the whole difference between a monitoring platform and a shared spreadsheet.

The approach

Frontend as the source of truth, backend as translation

Rather than designing a database schema from the spec and building both sides in parallel, the frontend was built first — a fully working Next.js prototype running entirely against localStorage, with every role, permission rule, and workflow state machine actually implemented and exercised, not mocked. It went through a formal senior-level audit with tracked remediation items before any backend existed. Only then did the Django backend get built, as a faithful server-side re-implementation of the exact data model and business rules the frontend had already validated. When the original spec and the working frontend disagreed, the frontend won — a deliberate, documented policy, not an accident of sequencing. That's also why the backend build was fast: 20 commits in a single day, because the domain problem had already been solved and proven, not designed under time pressure.

Approval requests, not a status field

Instead of a single draft → submitted → approved state sitting directly on a project, every mutation — create, update, progress submission, delete — is modeled as its own ApprovalRequest entity, with the project's status derived from the latest request. That separation makes it possible to have a full audit trail of who proposed what and who decided it, independent of the entity being changed, and it lets PPK or a super-admin bypass the queue entirely for their own direct edits — an intentional shortcut, logged distinctly rather than hidden.

Concurrency without table locks

Every project carries a revision counter captured when an approval request is filed and re-validated at the moment of approval. A stale approval — one where the project changed after the request was submitted — is rejected server-side rather than silently overwriting newer data. No table-wide locking required.

Archiving that respects government record-keeping

Deleting a project doesn't just flip a flag. It cascades to close all open issues, recording their prior state so a restore can undo it, and a permanent delete previews the full blast radius — per-entity-type counts — before anything is actually destroyed, given how consequential that action is for a government record.

Real-time notifications and a real BIM viewer

The frontend prototype originally recomputed notifications from scratch on every render. The backend deliberately upgraded that to a persisted notifications table populated transactionally on triggering events, with Celery and Redis handling overdue-detection sweeps and scheduled aggregation. On the BIM side, the spec had left the 3D viewer as an open, undecided question — the backend resolved it by implementing real Autodesk Platform Services token exchange rather than shipping only the frontend's simulated viewer as final.

Outcome

The system sits past the integration milestone, pre-production-launch: eight role-gated dashboards (summary, map, budget, progress, risk, compliance, portfolio, contractor performance) with CSV/PDF export, five roles enforced both client- and server-side, a full approval-request workflow with resubmission tracking, and an archive-restore-permanent-delete lifecycle modeled on real record-retention concerns. The frontend carries 111+ tests across its own Vitest suite, including cross-role isolation and resubmission-pipeline integration tests. Across the two repositories: 53 frontend commits over six weeks building and hardening the prototype, then 20 backend commits in a single concentrated day translating that validated design into Django — 37 models, 11 domain apps, and a typed API surface wired up behind a feature flag so the system can still fall back to its original prototype mode during cutover.

Outcomes

Routed pages
18
Models across 11 Django apps
37
Frontend tests
111+
Lines of code
~31.5K

Have a project like this?

If you need a system built with the same care — clear scope, solid execution — let's talk.

Start a project