## 6. Data Layer — Content Source Pattern (Local → Supabase)

นี่คือ **หัวใจของสถาปัตยกรรมข้อมูล** ของ mimoth.com

### Content Source Interface

```typescript
// src/lib/content/types.ts
export type ContentSource = {
  getToolCategories(): ToolCategory[];
  getAllTools(): Tool[];
  getFeaturedTools(limit?: number): Tool[];
  getToolBySlug(slug: string): Tool | undefined;
  getAllGuides(): Guide[];
  getGuideBySlug(slug: string): Guide | undefined;
  getAllNewsPosts(): NewsItem[];
  getAllDeals(): Deal[];
  getRelatedToolsForTool(toolSlug: string): Tool[];
  getRelatedGuidesForTool(toolSlug: string): Guide[];
  getRelatedDealsForTool(toolSlug: string): Deal[];
  getRelatedGuidesForGuide(guideSlug: string): Guide[];
  getSuggestedToolsForGuide(guideSlug: string): Tool[];
};
```

### Dual Source Pattern (Repository)

```typescript
// src/lib/content/repository.ts
async function getAllTools() {
  return withContentFallback(
    () => supabaseContentSource.getAllTools(),
    () => localContentSource.getAllTools()
  );
}

// Fallback logic
async function withContentFallback<T>(
  supabaseRead: () => Promise<T>,
  localRead: () => T
): Promise<T> {
  if (!shouldTrySupabase()) return localRead();
  try {
    const value = await supabaseRead();
    if (hasUsableValue(value)) return value;
  } catch { /* fallback silently */ }
  return localRead();
}
```

### Local Content Files

ข้อมูลจริงเก็บในไฟล์ TypeScript ที่ `/src/data/`:

```
src/data/
├── placeholders.ts        # Main data (2338 lines!) — tools, guides, news, deals
├── prompts.ts             # Prompt templates
├── news-auto.json         # Auto-published news
└── *いろんな guide ไฟล์*    # Individual guide data files
```

### Data Types (ตัวอย่าง)

```typescript
type Tool = {
  slug: string;
  name: string;
  category: string;
  price: string;           // "ฟรี", "Pro $20/เดือน", etc.
  pricingNote: string;
  summary: string;         // English summary
  thaiSummary: string;     // สรุปภาษาไทย
  useCase: string;         // use case จริง
  bestFor: string;         // เหมาะกับใคร
  notFor?: string;         // ไม่เหมาะกับใคร
  tags: string[];
  score: string;
  affiliateCta: string;
  featured?: boolean;
  quickVerdict?: { suitableFor, strength, caution, startPlan };
  pros?: string[];
  cons?: string[];
  internalLinks?: { href, label, description }[];
};
```

> 📌 **ข้อดีของ Local-first:** ไม่ต้องพึ่ง database ในการ dev, deploy บน Vercel เร็ว, SEO friendly, CI ไม่พังเพราะ DB