Skip to main content
2026

Concept Dash Property Platform

A config-driven Next.js platform that runs six separate real-estate developer websites — 3D streams, 360° tours and live unit inventory — from one codebase.

Showcase of Concept Dash Property Platform

Role

Full-Stack Developer (lead)

Client

Concept Dash

Duration

Dec 2025 – Aug 2026 (~9 months)

Real-estate developers each want their own branded sales website, and each one wants roughly the same things: a cinematic hero, a 3D walkthrough, a 360° tour of the show unit, a live availability list, and a lead form. Building six of those as six projects means six codebases drifting apart. This repo is the answer to that: a single Next.js App Router application where `NEXT_PUBLIC_SITE_VARIANT` picks one entry out of `app/config/siteConfig.js` at build time, and that entry *is* the site. The config's `layout` array is a list of section descriptors; `HomePageClient` maps each `type` through a `SECTION_COMPONENTS` lookup and renders them in order, handing `section.data` straight to the component. Adding a customer is one config entry and one data file — no routing work, no new pages. Six variants ship from it today, across developments in Canada and the UAE.

The interesting engineering is in the 360° layer. `app/components/panorama/` wraps Photo Sphere Viewer into nine focused modules driven entirely by a data object: a viewer that handles pano transitions and hotspot navigation, a debounced inventory search with full keyboard navigation, a minimap whose compass cone is driven by `requestAnimationFrame` against the live camera yaw, floor switching, and a cinematic loading overlay. Because placing hotspots by hand in a JSON file is miserable, the repo also contains `PanoCalibrator` — an in-app authoring mode that lets you aim the camera at a doorway, click, and copy the resulting JSON to the clipboard. It is gated off public builds. The commit history records the grind that tool made possible: 87 markers calibrated across a two-floor property.

Beyond the tour there is a neighbourhood explorer built on Leaflet with a deliberately server-side places layer: `app/api/places/nearby/route.js` proxies every lookup so the Google key never reaches the browser, responses are cached so cost is independent of visitor count, and a provider outage degrades to a committed snapshot instead of a broken page. Live unit availability comes from Supabase with realtime channels and deep-linkable `?unitId=` URLs; enquiries go through a multipart form route into AWS SES with hand-built HTML email templates. A separate `build:static` script produces a credential-free static export for client demos, sitting alongside the normal server build without polluting `next.config.ts`.

The repo also carries a genuinely unusual amount of written reasoning — `docs/architecture.md` documents the stack *as installed* rather than as intended, flags that the README is stale, and names the module that is the problem child and why.

Tech Stack

Next.js 16 (App Router)React 19Tailwind CSS v4Framer MotionSupabase (PostgreSQL + Realtime)@photo-sphere-viewer/core 5.15.1@photo-sphere-viewer markers / autorotate / gyroscope / stereo pluginsreact-photo-sphere-viewerthree.jsLeafletRadix UI (Dialog, Select, Checkbox)embla-carousel-reactreact-hook-formreact-phone-number-inputNodemailer + AWS SESlenislucide-reactnext-themesArcware / StreamPixel pixel streaming

Features

  • Config-driven multi-tenancyOne environment variable selects a site config whose `layout` array is rendered section-by-section through a component lookup, so a new property site is a config entry rather than a new codebase.
  • Modular 360° tour engineNine composable panorama modules — viewer, controls, search, minimap, floor switch, loader, shortcuts — all driven from a single tour data object, so seven of them need no change between properties.
  • In-app hotspot calibratorAn authoring mode that lets an operator aim the camera at a doorway, click to place a marker, and copy the generated JSON to the clipboard; it is excluded from public builds.
  • Live inventory with deep linksSupabase realtime channels keep unit availability in sync, and `?unitId=` search params open the site directly on a specific unit's enquiry state.
  • Cached, key-safe neighbourhood explorerA Leaflet map fed by a server-side places proxy that keeps the API key off the client, caches responses so cost does not scale with traffic, and falls back to a committed snapshot when the provider is down.
  • Lead capture into AWS SESA multipart contact route with file attachments, country lookup and unit-booking context, rendered into custom HTML email templates and delivered through Nodemailer over SES.
  • Credential-free static exportA dedicated `build:static` script produces a static bundle for client demos without touching the committed Next config, with Netlify headers and Node version pinned.
Available for work

Let's create your next big idea.