Real Estate Order Portal

A custom order-management and planning portal for a real estate presentation company

A photographer and real-estate presentation business — floor plans, photography and video for estate agents — used to take every order through a Microsoft Forms questionnaire feeding a Power Automate flow into two e-mails. There was no status, no history, and no way to look anything up afterwards; an order with an incomplete owner contact could arrive looking complete, because the check for a usable e-mail address was simply whether it was longer than five characters. We replaced it with a purpose-built portal: agents place orders, owners complete their own contact details through a secure link, and staff plan, track and invoice the work from one place.

Architecture

One PHP application on one server, with one SQLite database, behind Cloudflare — no framework, no build step, and no software from third parties. Everything the portal needs is written by hand, including the OAuth 2.0 client for Google Calendar, the SMTP client with its own retrying mail queue, TOTP two-factor codes, QR code generation, the iCalendar feed, and PDF generation for manuals and price lists. That is deliberate: the app runs on ordinary shared hosting, where a background worker isn't a given, and having nothing from outside also means nothing can update itself out from under the app or bring a supply-chain problem with it — the trade-off is that we maintain all of it ourselves. A single cron line drives a small in-process queue manager that handles mail, the calendar sync and the nightly jobs, so a slow mail server or a Google outage never holds up the page the visitor is looking at.

Deployed through our own CDP pipeline, from a test branch to a production branch, each to its own environment.

Agent places order Product catalogue and pricing per office, address lookup
Owner completes details Single-use link, if the agent didn't have them on hand
Staff plan the appointment Availability, day agenda, conflict checks
Calendar invite Mailed .ics, synced to Google Calendar
Follow-up & status Extra visits, order status, changes after the fact
Invoice details Handled-by office, “invoice to” recorded on the order

Features

🔑Roles & sign-in

Staff sign in with a password plus TOTP or a passkey; estate agents with a mailed sign-in link, a 45-day permanent link, or an optional password of their own choosing. An office can switch on self-enrolment for its own mail domain, so a new agent gets an account without anyone adding them by hand. Office managers see their own colleagues and can revoke a permanent link; property owners get a single-use link tied to exactly one order.

📝Order wizard

A product catalogue and pricing per office, a distance surcharge flagged above 25 km, Dutch postcode address lookup, and one live order per house at a time. An order can be changed after it has been placed instead of being re-entered from scratch, and every order records which office is handling it.

📅Planning

Availability and a day agenda sit next to the planning form, with conflict checks before a slot is confirmed. A follow-up visit can be booked against an existing order, and an appointment's duration can be changed without cancelling and rebooking it. Confirmed appointments go out as calendar invites, sync both ways with Google Calendar, and are also published as an iCalendar feed; holidays and absence — including the out-of-office reply on the mailboxes — are managed from the same place.

✉️Mail

Editable templates with variables and a live preview, a retrying delivery queue instead of a direct send, a typo check on addresses before they're used, and an MX check so mail isn't queued for a domain that can't receive it.

📋Audit log & usage

Every sign-in, change and refused request is logged with who, which office and why. Real usage measurement from actual visitors' browsers, not synthetic benchmarks, drives what gets optimised. A “what's new” changelog is tagged per audience, so an agent only sees the entries that matter to them, and manuals and the price list are available as generated PDFs.

🔒Security & privacy

A Content-Security-Policy with per-request nonces, rate limiting on sign-in and link requests, a trusted-IP allowlist for offices behind a shared connection, a GDPR retention job, and a privacy statement. Reviewed end-to-end against the OWASP Top 10 (see “What we learned” below).

📱Phones & tablets

Tested at phone and tablet widths, not just a narrowed desktop window: tables collapse to one card per row, row actions become icon-only with touch-sized targets, and tab strips scroll instead of wrapping into a stack.

What we found

Built with

PHP SQLite Google Calendar API OAuth 2.0 SMTP iCalendar WebAuthn / Passkeys TOTP Cloudflare

Built together with Claude (Anthropic) as an AI pair-programmer throughout the project.

In production for one client; not publicly available — this page is a write-up, not a demo.