# Content Data Flow & Architecture

## System Overview

```
┌─────────────────────────────────────────────────────────────┐
│                     CONTENT LAYER                            │
│  (JSON Files - Easy to Edit, Version Controlled)            │
├─────────────────────────────────────────────────────────────┤
│                                                              │
│  📄 chapters.json           📄 insights.json                 │
│  ├─ Chapter 1               ├─ Witness Account              │
│  ├─ Chapter 2               ├─ Historical Document          │
│  ├─ Chapter 3               └─ Photo Gallery                │
│  ├─ Chapter 4                                               │
│  ├─ Chapter 5               📁 Asset Files                  │
│  └─ Chapter 6               ├─ /video/*.mp4                 │
│                             └─ /insight/[id]/*.jpg           │
└─────────────────────────────────────────────────────────────┘
                             ⬇️
┌─────────────────────────────────────────────────────────────┐
│                     TYPE LAYER                               │
│  (TypeScript - Validation & Type Safety)                    │
├─────────────────────────────────────────────────────────────┤
│                                                              │
│  📘 content.ts                                               │
│  ├─ interface Chapter      { id, number, title... }         │
│  ├─ interface Insight      { id, title, gallery... }        │
│  ├─ validateChapters()     ✅ Ensure valid structure        │
│  ├─ validateInsights()     ✅ Catch errors early            │
│  └─ mapChapterData()       🔄 Convert to component format   │
│                                                              │
└─────────────────────────────────────────────────────────────┘
                             ⬇️
┌─────────────────────────────────────────────────────────────┐
│                     STORE LAYER                              │
│  (Svelte Stores - Centralized State Management)             │
├─────────────────────────────────────────────────────────────┤
│                                                              │
│  🗄️ contentStore.ts                                         │
│  ├─ chapters writable<Chapter[]>                            │
│  ├─ insights writable<Insight[]>                            │
│  ├─ loadChapters() → fetch & validate                       │
│  ├─ loadInsights() → fetch & validate                       │
│  ├─ getChapterByNumber(n) → derived store                   │
│  └─ getInsightsForChapter(n) → derived store                │
│                                                              │
│  📡 Single Load, Shared Across All Components                │
│                                                              │
└─────────────────────────────────────────────────────────────┘
                             ⬇️
┌─────────────────────────────────────────────────────────────┐
│                   COMPONENT LAYER                            │
│  (Svelte Components - Display & Interaction)                │
├─────────────────────────────────────────────────────────────┤
│                                                              │
│  🎨 App.svelte                                               │
│     onMount → loadAllContent()   (load once at startup)     │
│                                                              │
│  🎨 ChapterView.svelte                                       │
│     $: chapterData = $chapters.find(ch => ch.number === n)  │
│     ├─ TitleScreen (title, description)                     │
│     ├─ VideoPlayer (video srcs, speakers)                   │
│     └─ Insights (insight IDs)                               │
│                                                              │
│  🎨 Insights.svelte                                          │
│     $: selectedInsight = $insights.find(i => i.id === id)   │
│     └─ Gallery (images, quotes, links)                      │
│                                                              │
│  🎨 Timeline.svelte                                          │
│     Renders based on chapter count                          │
│                                                              │
└─────────────────────────────────────────────────────────────┘
```

## Data Relationships

```
Chapter 1 ──────────┐
                    │
         ┌──────────▼──────────┐
         │  videos: {          │
         │    primary: {...}   │────► Video File: 01-Rose-intro.mp4
         │    secondary: {...} │────► Video File: 01-Murray-school.mp4
         │  }                  │
         └──────────┬──────────┘
                    │
         ┌──────────▼──────────┐
         │  insights: [        │
         │    "witness-ksiazek"│────┐
         │  ]                  │    │
         └─────────────────────┘    │
                                    │
                    ┌───────────────▼───────────────┐
                    │  Insight: witness-ksiazek     │
                    │  ├─ gallery: [...]            │
                    │  │   └─ url: img.jpg          │
                    │  ├─ quote: [...]              │
                    │  └─ links: [...]              │
                    └───────────────────────────────┘
```

## Component Data Flow

```
User Opens Chapter 3
         │
         ▼
┌────────────────────┐
│  Timeline.svelte   │
│  onClick(3)        │────► viewState.selectChapter(3)
└────────────────────┘
         │
         ▼
┌────────────────────┐
│  App.svelte        │
│  selectedChapter=3 │
└────────┬───────────┘
         │
         ▼
┌─────────────────────┐
│ ChapterView.svelte  │
│ chapterNumber={3}   │
└────────┬────────────┘
         │
         ├──► Get from Store: $chapters.find(ch => ch.number === 3)
         │                     ▼
         │              ┌──────────────────────┐
         │              │ Chapter 3 Data       │
         │              │ ├─ title            │
         │              │ ├─ description      │
         │              │ ├─ videos.primary   │
         │              │ └─ insights[]       │
         │              └──────────────────────┘
         │                     │
         ├─────────────────────┼──────────────────────┐
         │                     │                      │
         ▼                     ▼                      ▼
┌────────────────┐   ┌────────────────┐   ┌─────────────────┐
│ TitleScreen    │   │ VideoPlayer    │   │ Insights        │
│ title={...}    │   │ videoSrc={...} │   │ id={...}        │
│ description    │   │ speaker={...}  │   │ (loads own data)│
└────────────────┘   └────────────────┘   └─────────────────┘
```

## Loading Sequence

```
App Initialization
    │
    ├── 1. App.svelte mounts
    │      └─► loadAllContent() called
    │
    ├── 2. Fetch chapters.json
    │      ├─► GET /include/content/chapters.json
    │      ├─► Validate data structure
    │      ├─► chapters.set([...])  ✅ Store updated
    │      └─► All subscribers notified
    │
    ├── 3. Fetch insights.json
    │      ├─► GET /include/content/insight/insights.json
    │      ├─► Validate data structure
    │      ├─► insights.set([...])  ✅ Store updated
    │      └─► All subscribers notified
    │
    └── 4. Components Reactive Update
           ├─► ChapterView: $chapters changes → re-render
           ├─► Insights: $insights changes → re-render
           └─► Timeline: Uses store values
```

## Error Handling Flow

```
Fetch chapters.json
    │
    ├─── ✅ Success (200 OK)
    │    ├─► Parse JSON
    │    ├─► Validate structure
    │    │   ├─── ✅ Valid → chapters.set(data)
    │    │   └─── ❌ Invalid → chaptersError.set("Invalid structure")
    │    └─► chaptersLoading.set(false)
    │
    └─── ❌ Failure (404, 500, etc.)
         ├─► chaptersError.set("HTTP 404")
         ├─► chapters.set([])  ← Empty array prevents crashes
         └─► chaptersLoading.set(false)

Component Rendering
    │
    ├─── if $chaptersLoading → Show loading spinner
    ├─── if $chaptersError → Show error message
    └─── if $chapters.length > 0 → Render normally
```

## File Location Mapping

```
chapters.json entry:
{
  "videos": {
    "primary": {
      "src": "./include/content/video/01-Hb-Rose-houseintro_480.mp4"
    }
  }
}
         │
         ▼
Actual file system:
/include/content/video/01-Hb-Rose-houseintro_480.mp4
         │
         ▼
Served at runtime:
http://localhost:5173/include/content/video/01-Hb-Rose-houseintro_480.mp4
         │
         ▼
Loaded by VideoPlayer component
```

## Store Subscription Pattern

```svelte
<!-- ChapterView.svelte -->
<script>
  import { chapters } from '../stores/contentStore';
  export let chapterNumber = 1;

  // Reactive statement - auto-updates when store changes
  $: chapterData = $chapters.find(ch => ch.number === chapterNumber);

  // Alternative: Derived store
  const currentChapter = derived(
    chapters,
    $chapters => $chapters.find(ch => ch.number === chapterNumber)
  );
</script>

<!-- Access with $ prefix for auto-subscription -->
<TitleScreen title={chapterData?.title} />
<!-- or -->
<TitleScreen title={$currentChapter?.title} />
```

## Content Update Cycle

```
1. Content Editor Updates chapters.json
   └─► Edit description field, save file

2. Version Control
   └─► git commit -m "Update chapter 1 description"

3. Deploy / Refresh
   └─► Browser loads new chapters.json

4. Store Automatically Updates
   └─► chapters.set(newData)

5. All Subscribed Components Re-render
   └─► TitleScreen, VideoPlayer, etc. get new data

No Code Changes Needed! ✨
```

## Memory & Performance

```
Without Store (Every Component Fetches):
  ChapterView.svelte     ──► GET chapters.json (50KB)
  AnotherComponent.svelte ──► GET chapters.json (50KB)
  ThirdComponent.svelte   ──► GET chapters.json (50KB)

  Total: 150KB transferred, 3 HTTP requests

With Store (Single Fetch, Shared):
  App.svelte ──► GET chapters.json (50KB)
       │
       ├──► ChapterView (subscribes)
       ├──► AnotherComponent (subscribes)
       └──► ThirdComponent (subscribes)

  Total: 50KB transferred, 1 HTTP request ✅
```

---

## Summary

**Content Layer**: JSON files (easy to edit)
↓
**Type Layer**: TypeScript validation (catch errors)
↓
**Store Layer**: Centralized loading (single fetch)
↓
**Component Layer**: Reactive UI (auto-updates)

This architecture separates **what** (content) from **how** (display), making the application easier to maintain and scale.
