Data Fetching Architecture
Comprehensive guide to NextMedal's multi-layer data fetching architecture with Sanity CMS, including routing, collections, and fallback strategies.
NextMedal uses a sophisticated multi-layer data fetching architecture built on Next.js 16 App Router + Sanity CMS with comprehensive fallback strategies, multi-language support, and performance optimizations.
Overall System Architecture
Page Data Fetching Flow
Here's how a typical page request flows through the system:
Collection Registry System
Collections are managed through a build-time generated registry for zero runtime overhead:
Multi-Language Routing
The routing system handles multiple locales with locale-specific collection slugs:
Fallback Strategy Hierarchy
The system implements a comprehensive fallback strategy for error handling:
Collection Architecture
The application supports 5 collection types with different translation strategies:
Data Fetching Layers
The data fetching architecture is organized in layers with different configurations:
Static Generation Flow
At build time, Next.js pre-renders all pages using the generateStaticParams function:
Key Architectural Patterns
Server Components First
All pages use Server Components by default, with Client Components only for interactivity ('use client' directive). Data fetching happens at server level via fetchSanityLive.
Collection Registry Pattern
Build-time generation creates the registry from Sanity frontpage modules with zero runtime overhead. The registry provides pure synchronous lookups with no API calls, full TypeScript support, and locale-aware slug mapping (e.g., 'articles' vs 'artikler').
URL Resolution Strategy
Server-side async resolveUrl() for Server Components and client-side sync resolveUrlSync() for Client Components. Both are registry-based using collection registry for dynamic paths with support for query string parameters (filters, pagination).
Translation Approaches
Document-level: Separate documents per language (articles, docs) filtered by language field in GROQ and related via _id in translations[] array. Field-level: Single document with internationalized fields (changelog, events, newsletter) where each field has {en: 'value', nb: 'verdi', ar: 'قيمة'}.
Error Categorization
Expected errors (site not configured, missing optional content) log warnings and don't report. Transient errors (network failures, 5xx) retry with backoff. Unexpected errors log errors and report to Sentry.
Performance Optimizations
Image URLs are resolved client-side, not in GROQ. Reverse lookups query articles then extract categories. Selective projections fetch only needed fields. All pages are pre-rendered at build time with 90-day ISR revalidation and on-demand updates via <SanityLive>.
Critical Files
Entry Points
src/app/(frontend)/[locale]/page.tsx - Homepage route
src/app/(frontend)/[locale]/[...slug]/page.tsx - Dynamic pages + collections
Data Fetching Core
src/sanity/lib/live.ts - Main fetch functions (fetchSanityLive, fetchSanityStatic)
src/sanity/lib/fetch.ts - Public API (getSiteOptional, getHeaderSettings)
src/sanity/lib/queries.ts - All GROQ queries (80+ fragments)
URL & Metadata
src/lib/sanity/resolve-url-server.ts - Server-side URL builder
src/lib/sanity/process-metadata.ts - SEO metadata generator
Collections
src/lib/collections/registry.ts - Collection metadata API
src/lib/collections/context.tsx - React context provider
src/lib/collections/generated/collections.generated.ts - Build-time config
Unique Architectural Strengths
1. Build-time Collection Registry - Zero runtime API calls for collection lookups
2. Dual Translation Strategy - Mix document-level (content-heavy) and field-level (metadata-heavy)
3. Intelligent Fallbacks - Multi-tier fallbacks with context-aware setup guides
4. Error Categorization - Don't report expected errors (reduces Sentry noise)
5. URL Resolution Flexibility - Same API works in Server Components (async) and Client Components (sync)
6. Locale-aware Collections - Same collection type can have different slugs per language
7. Draft Mode Auto-detection - No manual draftMode() checks needed
8. Retry with Categorization - Only retry network/5xx errors, not client errors
9. Static Generation at Scale - Pre-render all pages across all locales in parallel
10. Metadata Generation Pipeline - Consistent SEO/OG/JSON-LD across all content types
