ProjektBevis - "Projecr Proof"
Field documentation for construction crews in the field, that needs no app: workers text photos of the job, and the backend sorts each one into their organisation's project in the application web view. Solving in-field administrative requirements, replacing them with a quick five-second process.
Projekt Bevis is a phone-driven field-documentation platform. Construction and trade workers prove work was done without installing anything: photograph the job, text the images in, and the backend files each photo into the sender's private image book or an organisation's project, then texts back a secure login link.
The premise is that the documentation habit already exists. Crews send photos by SMS and MMS all day. What is missing is not another app to learn but somewhere for those photos to land in a structure that still holds up when someone asks for the evidence six months later.
What I built
- Multi-service Python backend — a Flask web UI plus separate FastAPI microservices for the SMS/MMS receiver and the messaging API, orchestrated with Docker Compose.
- The full inbound MMS pipeline — parse carrier messages, dedupe and batch the images, route them by sender to private storage or an organisation project, and reply with a one-time tokenised login link.
- PostgreSQL data model through SQLAlchemy 2.0, with application-level encryption of personal data: phone numbers are encrypted at rest and hashed separately so a lookup never needs the plaintext.
- Token-based passwordless auth — short-TTL, single-use login links, with account setup and organisation roles built on top.
- An Android/Kotlin middleware app that bridges the phone's own SMS/MMS gateway into the backend, built and packaged as a distributable APK.
- Server-rendered, responsive UI — the private image book, batch status views, organisation onboarding, and account settings.
The part that was actually hard
The inbound pipeline, because a carrier is not an API. Messages arrive batched or split, out of order, sometimes duplicated, and with nothing reliable to say where one submission ends and the next begins. A worker sending ten photos of a job does not think of it as ten messages — they think of it as one batch, and the system has to agree with them.
Deciding where a photo belongs is the other half of it. The same phone number can be a private user and a member of several organisations at once, so routing is a per-sender policy question rather than a lookup. Getting it wrong does not produce an error; it produces someone's private photo sitting in a shared project.
Personal data
A phone number is the identity in this system, which makes it the sensitive part. Numbers are encrypted at the application layer and hashed separately for lookup, so the plaintext is never needed to find a sender.