- SPEC: add User Story 0 (Property Setup via Catastro) as P1 entry - SPEC: add catastro_data and catastro_imports tables to data model - PLAN: add Phase 2A (Catastro Integration) with 8 tasks - AGENTS.md: add 3 key decisions (Catastro SSOT, 3DGS hybrid, plan inputs) - Demo v3: Spanish apartment (C/ Altabix 24, 3ºB, Elche), 7 rooms, upload panel for catastro/DXF, proper collisions on all doors
7.4 KiB
InteriorScan MVP — Implementation Plan
For Hermes: Use subagent-driven-development skill to implement this plan task-by-task.
Goal: Build an interior photogrammetry SaaS that turns apartment photos into navigable 3D walkthroughs (Doom-map style).
Architecture: Turborepo monorepo (tpl-next-saas template). Next.js 16 App Router for web UI + dashboard. GPU worker (Node.js) orchestrates COLMAP/OpenMVS processing pipeline. three.js FPS viewer for walkthrough navigation. PostgreSQL + Drizzle for data. Valkey for queues/sessions. Stripe for billing.
Tech Stack: Next.js 16 · Drizzle ORM · PostgreSQL · Valkey · three.js · COLMAP · OpenMVS · Stripe · Biome · Vitest
Constitution Check
| Principle | Status | Notes |
|---|---|---|
| I. Self-Hosted First | ✅ PASS | All infra self-hosted except Stripe |
| II. Progressive Experience | ✅ PASS | WebGL → 360° fallback, mobile tap-to-walk |
| III. FPS-Grade Immersion | ✅ PASS | WASD + mouse primary, tap-to-walk secondary |
| IV. Photo-First Capture | ✅ PASS | Mobile photos as baseline, LiDAR enhancement |
| V. API-First Architecture | ✅ PASS | API endpoints defined before UI |
| VI. TypeScript Strict | ✅ PASS | strict + noUncheckedIndexedAccess |
| VII. Test-First | ⚠ CONDITIONAL | TDD for business logic; 3D viewer tested via Playwright E2E |
| VIII. Open Formats | ✅ PASS | OBJ export in MVP, E57/DXF/IFC in P4+ |
⚠ VII conditional: 3D rendering correctness is validated via E2E visual regression, not unit tests. Business logic (upload, processing, auth) follows strict TDD.
Data Model
See data-model.md (separate document — same directory).
Phase 1: Monorepo Scaffold + Core Infra (Shared)
- T001 Create monorepo from tpl-next-saas template
- T002 Configure Drizzle schema with InteriorScan tables (projects, photos, walkthroughs, processing_jobs, users, teams, subscriptions)
- T003 Run migration:
pnpm db:migrate - T004 [P] Add seed data: 1 user, 1 team, 3 project statuses
- T005 [P] Set up Valkey connection for job queue
- T006 [P] Configure Docker Compose (postgres + valkey + web)
Checkpoint: Migration green, pnpm dev starts without errors, health endpoint returns 200.
Phase 2: Property Setup & Photo Upload (P1) 🎯 MVP Core
2A: Catastro Integration
- T007 Create
packages/catastro/— Catastro client package - T008 Write failing test: address "C/ Altabix 24, Elche" → refcat resolved
- T009 Implement OVK address search (SOAP/REST → refcat)
- T010 Write failing test: refcat → building polygon GML from INSPIRE WFS
- T011 Implement INSPIRE WFS client (GML → GeoJSON polygon)
- T012 Implement GML polygon → wall segments converter (
{x1,z1,x2,z2,height,thickness}) - T13 Write failing test: POST /api/v1/projects with address → catastro_data populated
- T014 Implement project creation with Catastro lookup (address → refcat → footprint → walls)
Checkpoint: Enter "C/ Altabix 24, Elche" → building polygon rendered in minimap → exterior walls in 3D scene.
2B: Photo Upload API
- T007 Write failing test: POST /api/v1/projects with photos returns 201 + project ID
- T008 Implement project creation endpoint with Zod validation
- T009 Write failing test: Upload 3 JPEGs → stored in object storage, DB has photo records
- T010 Implement photo upload with deduplication (perceptual hash)
- T011 Write failing test: GET /api/v1/projects/:id returns status + progress
- T012 Implement project status endpoint
Checkpoint: Upload 40 photos via API → receive project ID → poll status → see "queued".
2B: Processing Worker
- T013 Set up
apps/processor/— Node.js worker with BullMQ/Valkey job queue - T014 Write failing test: Job queued → worker picks up → runs COLMAP SfM → produces sparse point cloud
- T015 Implement COLMAP SfM step (feature extraction + matching + sparse reconstruction)
- T016 Write failing test: SfM output → OpenMVS dense reconstruction → mesh file produced
- T017 Implement OpenMVS dense reconstruction step (MVS + meshing + texturing)
- T018 Write failing test: Mesh + textures → tiled output for three.js streaming
- T019 Implement mesh processing + tiling step (LOD generation, Draco compression, texture atlas)
- T020 Implement progress reporting (Valkey pub/sub → web UI)
- T021 Write failing test: Processing failure → job marked failed → user notified
- T022 Implement error handling + retry logic
Checkpoint: Upload 40 photos → processing completes → produces OBJ mesh + tiled three.js output. Total time <60 min for 100 photos on GPU.
Phase 3: 3D Viewer — FPS Walkthrough (P1) 🎯 MVP Core
- T023 Create
packages/viewer/— three.js + Vite library package - T024 Implement FPS camera controller (WASD + mouse look, collision detection, gravity)
- T025 Implement tap-to-walk controller (mobile: tap destination → navmesh pathfinding)
- T026 Implement mesh loader (tiled LODeD mesh streaming, Draco decompression)
- T027 Implement texture loading (progressive: low-res first, high-res on demand)
- T028 Implement mini-map overlay (bird's eye view with player position)
- T029 Implement measurement overlay toggle (room dimensions on walls/floor)
- T030 Implement WebGL fallback detection → 360° photo carousel mode
- T031 Implement touch controls (gyroscope look, pinch-zoom, two-finger walk)
- T032 Write Playwright E2E test: load walkthrough → verify 3D renders → verify WASD movement → verify tap-to-walk
Checkpoint: Open walkthrough link → walk through reconstructed space at 30+ FPS. WASD works. Click-to-walk works. Mini-map shows position.
Phase 4: Web UI — Dashboard & Sharing (P1 + P2)
- T033 Create project creation flow (multi-step: name/address → photo upload → processing)
- T034 Create processing status page (progress bar, ETA, stage indicator)
- T035 Create walkthrough view page (embedded viewer + share controls)
- T036 Implement share link generation (public, no auth required)
- T037 Implement oEmbed embed code generator
- T038 Create dashboard grid (project cards with thumbnail, status, date)
- T039 Create project settings (edit name, address, delete)
Checkpoint: Agent creates project → uploads photos → sees processing progress → walkthrough appears → shares link → visitor navigates without login.
Phase 5: Auth, Teams & Billing (P3)
- T040 Set up better-auth with email + Google OAuth
- T041 Implement RBAC (owner/admin/member/viewer per team)
- T042 Create subscription tiers (Free: 3/month, Pro: 25/month, Enterprise: unlimited)
- T043 Implement Stripe checkout + webhook
- T044 Implement usage tracking + quota enforcement middleware
Checkpoint: User signs up → creates 3 projects on Free → gets upgrade prompt → pays via Stripe → quota increases.
Phase 6: Polish & Launch
- T045 Landing page with demo walkthrough embedded
- T046 Pricing page with 3 tiers
- T047 Email notifications (processing complete, processing failed, quota warning)
- T048 Mobile-responsive dashboard with bottom nav
- T049 Accessibility audit (WCAG 2.2 AA): keyboard nav, screen reader, contrast
- T050 Performance audit (Core Web Vitals, first mesh load <5s on 4G)
Checkpoint: Real tester (monyi's friends) create walkthrough from phone photos in <1h total. Lighthouse 90+.