Developer/System & Architecture/System Architecture & Data Flows

System Architecture & Data Flows

Architecture

Detailed analysis of Next.js 15 App Router architecture, ISR caching, cart management, and Fourthwall data reshaping.

Last revised: September 2026•Rory Skagen Art Studio Docs

End-to-End Data Flow

The storefront architecture separates product retrieval, cart session storage, and administrative sync into three decoupled layers:

[Visitor Browser]
       │
       ▼
[Next.js 15 App Router Server] ──► (ISR Cache: 3600s / Tag Revalidation)
       │
       ├─► Fourthwall Storefront API (https://storefront-api.fourthwall.com/v1)
       │      │  (When NEXT_PUBLIC_FW_STOREFRONT_TOKEN is active)
       │      ▼
       │   [Live Fourthwall Storefront Service]
       │
       └─► Fallback In-Memory Catalog Engine (lib/fourthwall/index.ts)
              │  (When token is placeholder or API offline)
              ▼
           [lib/fourthwall/rory-artworks-data.json]
              ├── 137 Canonical Fine Artworks
              ├── Cloudinary / Supabase Media CDN
              └── In-Memory Cart Store

Server vs Client Component Boundary

In accordance with Next.js 15 architectural best practices:

  • Server Components (Default):
  • app/[currency]/page.tsx
  • app/[currency]/product/[handle]/page.tsx
  • components/grid/three-items.tsx
  • components/carousel.tsx
  • app/docs/[[...slug]]/page.tsx
  • Benefits: Zero client-side JavaScript overhead for catalog data, superior SEO, fast TTFB.
  • Client Components ('use client'):
  • components/cart/modal.tsx (interactive cart drawer)
  • components/cart/add-to-cart.tsx (optimistic variant selection)
  • app/import/page.tsx (real-time sync dashboard with terminal output)
  • components/layout/navbar/currency.tsx (currency switching dropdown)

Caching & ISR Strategy

Next.js 15 caching primitives are configured for high-traffic scalability:

ts
// lib/fourthwall/index.ts
export async function getCollectionProducts({ collection, currency, limit }) {
  const res = await fourthwallGet(
    `${API_URL}/collections/${collection}/products`,
    { currency, limit },
    { next: { revalidate: 3600, tags: [`collection-${collection}`] } }
  );
  return reshapeProducts(res.body.results);
}
  • Revalidation Window: 3600 seconds (1 hour) background stale-while-revalidate.
  • On-Demand Cache Purging: Server actions call revalidateTag(TAGS.cart, 'default') whenever items are added or modified in the user's cart.

Data Reshaping Pipeline

Raw Fourthwall Storefront API payloads are normalized into uniform internal TypeScript models (lib/types.ts) via lib/fourthwall/reshape.ts:

ts
// Raw Fourthwall Product -> Reshaped Application Product
export function reshapeProduct(product: FourthwallProduct): Product {
  return {
    id: product.id,
    handle: product.slug,
    title: product.name,
    description: product.description,
    descriptionHtml: product.description,
    options: extractProductOptions(product.variants),
    variants: product.variants.map(reshapeVariant),
    images: product.images.map(reshapeImage),
    featuredImage: reshapeImage(product.images[0]),
    priceRange: calculatePriceRange(product.variants),
    tags: extractTags(product),
    updatedAt: product.updatedAt
  };
}