home/projects/lodgesandcaravans

LodgesAndCaravans UK Property Listing & Sales Platform

Full-stack property listing and sales marketplace for the UK holiday property market, built with Next.js SSR, geospatial map search, and owner management dashboards.

My Role

Sole Full-Stack Developer (End-to-End Delivery)

Timeline

5 Months

Client / Context

Lodges & Caravans

Category

Full-Stack Web

View Live Deployment
Next.jsNode.jsMongoDBExpressRedisTanStack QueryGoogle Maps APITailwind CSSJWT Auth
LodgesAndCaravans product preview (screenshot 1 of 2)LodgesAndCaravans product preview (screenshot 2 of 2)

The Problem & Engineering Constraints

The Challenge

Why this system needed to be built

The platform needed to render and filter hundreds of property listings scattered across the entire UK on a single interactive map view in real time. Naive approaches caused severe rendering lag from overlapping markers, redundant API calls on every pan/zoom, and full-collection MongoDB scans that ignored the user's visible map area. The core engineering challenge was building a system where the map, filters, and listing results stayed perfectly synchronized without sacrificing load speed or scalability.

Primary Target Users

UK property buyers browsing accommodation, caravan and lodge owners managing property listings, and site administrators.

Real-World Constraints

Non-Negotiables
  • Sole engineer ownership: Responsible for the entire lifecycle from database architecture and auth to frontend SSR, SEO optimization, and deployment.
  • Sub-second page load requirement: Dynamic holiday listing pages needed instant initial render times to maximize conversion from UK organic search traffic.
  • Geospatial query accuracy: Searches needed to handle UK postcodes, radius boundaries, and multi-parameter property filtering simultaneously.

*Every architecture decision was framed strictly around these constraints.

Engineering Challenges & Root-Cause Fixes

Real technical hurdles encountered during production development and how they were solved under the hood.

Frontend Performance & Map Rendering

Map Rendering Collapse with Hundreds of UK-Wide Pins

CASE #1
1. The Failure / Bottleneck (Symptom)

Loading the full UK map view with 170+ property markers caused visible frame drops, overlapping pin labels, and 3-4 second interaction freezes on mobile devices.

2. Technical Root Cause

Every property was rendered as an individual DOM-based marker. The browser was thrashing layout recalculations on pan/zoom with hundreds of absolutely-positioned elements.

3. The Engineered Solution

Implemented Google Maps MarkerClusterer with density-aware grid sizing, lazy marker instantiation outside the visible viewport, and debounced cluster recalculation on zoom-end events. Required tuning cluster grid size and max zoom thresholds per UK region density to balance rural vs. dense coastal parks.

4. Quantified Outcome

Eliminated rendering lag entirely, achieving smooth panning across the full UK map with 170+ active listings and zero visible marker overlap.

Client-Side Caching & Network Optimization

Redundant API Calls on Every Map Pan and Zoom

CASE #2
1. The Failure / Bottleneck (Symptom)

Each map drag or zoom level change fired a fresh API request, causing visible loading spinners, network waterfall congestion, and unnecessary MongoDB load.

2. Technical Root Cause

No client-side caching strategy existed, so every viewport change was treated as a unique, uncached request.

3. The Engineered Solution

Introduced TanStack Query with query keys hashed from rounded viewport bounds and active filter state. Stale-while-revalidate serves previously fetched regions instantly while background refetches sync silently. Cache key granularity was tuned to avoid stale results on broad keys without killing hit rate on narrow viewport shifts.

4. Quantified Outcome

Reduced redundant API calls by ~70% during typical browse sessions; revisiting previously viewed UK regions loads instantly from cache.

Database & Geospatial Indexing

Full-Collection MongoDB Scans Ignoring Visible Map Area

CASE #3
1. The Failure / Bottleneck (Symptom)

Property search API was querying the entire UK listings collection regardless of what portion of the map the user was actually viewing, spiking response times to 1,400ms+ under concurrent load.

2. Technical Root Cause

The original query used $nearSphere with a large radius instead of scoping to the map's actual bounding box. Combined with poorly ordered compound index keys, MongoDB fell back to in-memory filter scans.

3. The Engineered Solution

Refactored the API to accept the map's northeast/southwest bounding coordinates and query with $geoWithin polygon. Restructured compound 2dsphere indexes to place geospatial fields first, followed by faceted filter keys. Added a Redis cache layer for hot geographic corridors.

4. Quantified Outcome

Reduced viewport-scoped query times from 1,400ms to under 95ms; Redis serves repeat corridor queries in <5ms.

Key Features & Implementation Mechanics

Feature #1

UK-Wide Map Search with Marker Clustering

Browse all UK properties on a single interactive map with Google Maps marker clustering that dynamically groups and splits pins as users zoom in and out.

⚙ Under The Hood:

Google Maps MarkerClusterer with density-aware grid sizing, viewport-bound MongoDB $geoWithin queries scoped to visible bounding box, and TanStack Query stale-while-revalidate caching keyed on rounded viewport bounds.

Feature #2

Owner Property & Sales Management Portal

Full-featured owner dashboard to upload gallery images, manage pricing, track buyer inquiries, and view visitor analytics.

⚙ Under The Hood:

Role-based JWT authentication with secure multipart image uploads, automated thumbnail compression, and MongoDB transaction pipelines.

Feature #3

Viewport-Synced Multi-Attribute Filtering

Filter properties across price, capacity, pet rules, amenities, and regions, keeping results synchronized with the visible map area in real time.

⚙ Under The Hood:

URL-driven state management with Next.js shallow routing, debounced viewport-bound API calls, Redis-cached hot corridor results, and compound 2dsphere + faceted MongoDB indexes.

Verified Metrics & Telemetry

<95ms

Viewport Query Speed

Reduced from 1,400ms via viewport-bound 2dsphere indexing and Redis caching for hot geographic corridors.

~70%

Redundant API Calls Eliminated

TanStack Query stale-while-revalidate caching prevents re-fetching previously viewed map regions.

<5ms

Redis Cache Hit Latency

Popular search corridors (Cornwall, Devon, Lake District) served from Redis without MongoDB roundtrips.

Lessons Learned & Architectural Evolution

What Worked Well & Enduring Takeaways

  • ✓Compound index key ordering in MongoDB makes or breaks geospatial performance when paired with faceted filters.
  • ✓Single-engineer delivery succeeds by adhering to high-leverage primitives (Next.js SSR, clean REST contracts, automated image compression) rather than over-engineering microservices.

What I Would Build Differently Today

  • ↺If architecting today, I would implement Meilisearch or Typesense for typo-tolerant location search and instant facet count calculations.
  • ↺I would use Next.js Parallel Routes for modal-based listing previews to preserve search scroll position on mobile devices.