Inspiration
Florida has over 8,000 licensed home inspectors. Most still rely on paper forms and decade-old software that wasn't designed for mobile. A full home inspection covers 12 sections, dozens of condition items, defect photos, and a professional PDF report — all delivered to the client within hours of leaving the property.
I knew this problem was real through REBS Property Specialist LLC, a 30-year licensed Florida inspector who confirmed at $99/month starting July 2026. I didn't want to build a demo. I used H0 as a forcing function to build the real product.
What it does
InspectIQ is a production-grade, multi-tenant SaaS platform for licensed home inspectors in Florida:
- Field capture: Inspectors document 12 inspection sections on their phone — free-form findings with condition ratings (GOOD/MARGINAL/DEFECTIVE), structured component observations (material types, yes/no metadata), and photos uploaded directly to S3 from the device
- PDF reports: Professional reports generated on demand with tenant branding (logo, colors, custom fonts), section disclaimers, component conditions, and finding photos
- Pre-inspection agreement: InterNACHI-compliant PDF agreement with tenant data
- Multi-tenant isolation: Every inspector's data is completely isolated at the database layer via Row Level Security — not application-level filtering
- Inspection lifecycle: 5-state FSM (DRAFT → IN_FIELD → PENDING_REVIEW → PUBLISHED → DELIVERED) with write-lock on delivered inspections
How we built it
AWS Stack:
- Aurora PostgreSQL Serverless v2 — primary datastore with RLS multi-tenancy.
Tenant context flows from JWT through FastAPI middleware into every SQL query via
SET LOCAL app.current_tenant_id. No application-level filtering. - App Runner — FastAPI backend with auto-scaling
- S3 — photo storage with presigned PUT URLs (photos never touch the backend)
- Cognito — authentication with custom
tenant_idclaims - ECR — container registry
- Secrets Manager — database credentials rotation
Frontend: Next.js 14 on Vercel with App Router. Server Components for data fetching, Client Components with debounced autosave for real-time field updates. Mobile-first — inspectors use their phones in the field.
Schema: 13 migrations, 2 data patterns:
findingstable — free-form observations with condition and photos (JSONB)component_observations+section_metadata— structured condition items with RLS, covering 12 sections and dynamic room arrays for bedrooms/bathrooms
Identity: inspector_id is resolved from the JWT sub on the backend —
the frontend never sends database IDs.
Challenges we ran into
WeasyPrint CSS limitations: WeasyPrint doesn't support display:flex,
object-fit, or floats inside table cells. Every PDF layout required testing
against the actual renderer, not the browser. Side-by-side photos required a
nested table with explicit widths on <td> elements, not <img>.
Aurora migrations with restricted users: The application user has BYPASSRLS but not DDL privileges. Running schema migrations required the master user, accessed via an EC2 bastion through AWS SSM — no SSH, no public IP, no exposed credentials.
Next.js fallback rewrites: The App Router fallback rewrite intercepts non-GET methods on dynamic routes before route handlers run. Workaround: retrieve the auth token server-side, then call the backend directly from the client.
Multi-tenant RLS from day one: Every table, every migration, every query had to be designed with tenant isolation in mind. No shortcuts — a missing RLS policy is a data leak waiting to happen.
Accomplishments that we're proud of
- Real customer confirmed before submission: REBS Property Specialist LLC at $99/month starting July 2026
- Multi-tenant RLS enforced at the database layer across 15+ tables — zero application-level tenant filtering
- Zero-touch photo pipeline: inspector taps, photo goes directly from phone to S3 via presigned URL, URL saved to Aurora, rendered in PDF — backend never handles the file
- Professional PDF with tenant branding, 12 inspection sections, component conditions, and photos — generated in under 3 seconds
- Production deployed on AWS App Runner + Vercel, accessible at https://mcag-h0.vercel.app
What we learned
Building multi-tenant RLS from day one is harder than adding it later — but it's the only correct approach. Every architectural shortcut in week one becomes security debt you carry forever.
Aurora Serverless v2 is genuinely well-suited for early-stage SaaS. Cold start is subsecond, scaling is transparent, and full PostgreSQL compatibility means zero application changes between environments.
The inspector id should never come from the frontend. The backend resolves identity
from the JWT — the client sends business data, not identity data. This principle
applies everywhere in multi-tenant systems.
What's next for InspectIQ
- July 2026: REBS goes live, first charge, 3-5 inspectors from his school onboard
- Month 6: 50 customers, $5,000 MRR — primary channel: REBS inspection school (30-60 graduates/year, near-zero CAC)
- Month 18: 300 customers, $30,000 MRR
- CloudFront + Lambda thumbnails: replace presigned GET URLs with permanent CloudFront URLs for PDF stability
- International expansion: UK RICS, Spain ITE, Germany Energieausweis — same platform, different inspection schemas
This isn't a hackathon project. It's a product.
Built With
- alembic
- amazon-web-services
- aws-app-runner
- aws-aurora-postgresql-serverless-v2
- aws-cognito
- aws-ecr
- aws-secrets-manager
- aws-ssm
- docker
- fastapi
- jinja
- next.js-14
- postgresql
- pydantic
- python
- sqlalchemy
- terraform
- typescript
- vercel
- weasyprint
Log in or sign up for Devpost to join the conversation.