Code by

Mateus

Paula

Loading...

Injury Institute

ROLE / SERVICES

development

COMPANY RELATED

The Casely Group

YEAR

2023

Injury Institute

Overview

Injury Institute is a full-featured medical directory web application connecting personal injury attorneys and patients with healthcare providers across California. The platform features a powerful CMS-driven architecture using Sanity, server-side rendered listings with geographic search capabilities, and a sophisticated filtering system using URL query parameters.

Key Features

1. Dynamic Sanity Schema with Conditional Fields

The platform uses a polymorphic content model where a single "Item" document type dynamically changes its form based on the selected type (Clinic or Doctor).

Elite Sports Medicine - Montebello

Key Implementation Details:

  • Schema composition: Imports and spreads field definitions from clinic.ts and doctor.ts
  • Conditional visibility using Sanity's hidden property with document context
  • Dynamic preview configuration that adapts based on item type
  • Computed fields using custom computedString type for geocoding city names

2. SSR Listing Page with GROQ Query Builder

Listing Page

The listing page uses getServerSideProps for server-side rendering with dynamic GROQ query construction based on filter parameters.

Key Implementation Details:

  • Dynamic GROQ query construction with template literals
  • Geo-spatial filtering using Sanity's geo::distance() function
  • Array membership filtering with dynamic buildArrayFilter helper
  • Pagination with calculated offsets
  • Proximity-based sorting with city priority

3. URL Query Parameter Filtering with Jotai State

Filter Drawer on Listing Page

A comprehensive filtering system using Jotai atoms for state management, synchronized with URL query parameters.

Key Implementation Details:

  • Jotai atoms for each filter dimension (categories, location, proximity, etc.)
  • Bidirectional sync between URL and state
  • Miles-to-meters conversion for geo queries
  • Multi-select category support with comma-separated values

4. Google Maps Integration with Interactive Markers

The listing page features a side-by-side layout with virtualized list and Google Maps integration.

Key Implementation Details:

  • Dynamic loading with next/dynamic to avoid SSR issues
  • Marker clustering support (commented but available)
  • InfoWindow popups with clinic/doctor previews
  • Center tracking on marker selection
  • Key-based re-rendering on items change

5. Static Generation with ISR for Detail Pages

Clinic and doctor detail pages use getStaticPaths with ISR (Incremental Static Regeneration) for optimal performance.

6. Nested Doctor Routing with Clinic Context

A clever URL pattern allows doctors to be viewed both independently and within their clinic context.

Key Implementation Details:

  • Custom URL encoding for nested relationships
  • GROQ array filtering for team member lookup
  • Maintains clinic context for navigation

7. Virtualized List with react-virtuoso

The listing page uses virtualization for smooth scrolling with large datasets.

8. Geocoding with Computed Fields

Automatic city extraction from coordinates using Google Geocoding API in Sanity Studio.

Tech Stack

Architecture

Data Flow

  1. User applies filters in the drawer UI (Jotai state)
  2. State converts to URL query parameters on submit
  3. getServerSideProps parses query params and builds GROQ query
  4. Sanity returns filtered, sorted, paginated results
  5. Google Maps updates markers based on results
  6. Virtuoso efficiently renders the list

Technical Challenges & Solutions

Challenge 1: Polymorphic Content Model

Problem: Need to support both Clinics and Doctors as first-class items while sharing common fields.

Solution: Created a base "Item" schema that conditionally shows nested clinic or doctor fields based on a type selector:

Challenge 2: Geographic Search with Sanity

Problem: Filtering results by proximity to user location using Sanity's GROQ.

Solution: Leveraged Sanity's built-in geo::distance() function with geopoint fields and converted user-friendly miles to meters:

Challenge 3: URL-State Synchronization

Problem: Maintaining filter state across page refreshes and enabling shareable URLs.

Solution: Implemented bidirectional sync between Jotai atoms and Next.js router query params, with SSR reading params directly in getServerSideProps.

Challenge 4: Nested Doctor-Clinic Relationships

Problem: Doctors can exist both as standalone items AND as team members within clinics.

Solution: Created a special URL pattern (doctor-slug___clinic=clinic-slug) that encodes the relationship, with GROQ using array filtering to find the doctor within the clinic's team array.

Screenshots

Clinic Detail Page

Elite Sports Medicine - Montebello

Doctor Detail Page

Matthew Bernstein, DC

What I Learned

  • Sanity CMS Advanced Patterns: Building polymorphic schemas with conditional field visibility, computed fields with async data fetching, and complex GROQ queries with geo-spatial filtering
  • Next.js Data Fetching: Combining SSR (getServerSideProps) for dynamic listings with ISR (getStaticProps + revalidate) for detail pages
  • State Management: Using Jotai atoms with URL query parameter synchronization for a seamless filter experience
  • Map Integrations: Implementing both Google Maps and Leaflet with marker clustering, info windows, and dynamic center tracking
  • Performance Optimization: Virtualized lists with react-virtuoso for handling 400+ items smoothly
My Projects Image
My Projects Image
My Projects Image
My Projects Image
My Projects Image
My Projects Image
My Projects Image
My Projects Image