15 KiB
🔷 GOD-MODE HARRIS MATRIX: Complete Schema Dependency Guide v2.0
What is a Harris Matrix? In database design, it's a Dependency Structure Matrix (DSM) that shows the exact order to create tables so foreign key constraints don't fail. You cannot build a roof before walls. You cannot create
commentsbeforeusersandpostsexist.
✅ Status: Schema v2.0 - Phase 9 Complete (Dec 2025) - All 17 collections documented, 23 fields added, 0 TypeScript errors
🎯 THE GOLDEN RULE
Build the Foundation First, Then the Walls, Then the Roof
┌─────────────────────────────────────┐
│ BATCH 1: Foundation (Independent) │ ← Create First
├─────────────────────────────────────┤
│ BATCH 2: Walls (First Children) │ ← Create Second
├─────────────────────────────────────┤
│ BATCH 3: Roof (Complex Children) │ ← Create Last
└─────────────────────────────────────┘
📊 SPARK PLATFORM: Complete Dependency Matrix
Summary Statistics (Updated Dec 2025)
- Total Collections: 17 (includes article_templates)
- Parent Tables (Batch 1): 7 (added article_templates)
- Child Tables (Batch 2): 8
- Complex Tables (Batch 3): 2
- Total Foreign Keys: 12
- Schema Version: v2.0 (Phase 9 Complete)
- All Issues Resolved: ✅ Build successful, 0 errors
🏗️ BATCH 1: FOUNDATION TABLES
Zero Dependencies - These tables reference NO other tables
| # | Table | Type | Purpose | Children Dependent |
|---|---|---|---|---|
| 1 | sites ⭐ |
Parent | Master site registry | 10 tables depend on this |
| 2 | campaign_masters ⭐ |
Parent | Campaign definitions | 4 tables depend on this |
| 3 | article_templates |
Parent | Article structure blueprints | 1 table (campaign_masters) |
| 4 | avatar_intelligence |
Independent | Avatar personality data | 0 |
| 5 | avatar_variants |
Independent | Avatar variations | 0 |
| 6 | cartesian_patterns |
Independent | Pattern formulas | 0 |
| 7 | geo_intelligence |
Independent | Geographic data | 0 |
| 8 | offer_blocks |
Independent | Content offer blocks | 0 |
⚠️ CRITICAL: sites and campaign_masters are SUPER PARENTS - create these FIRST!
🧱 BATCH 2: FIRST-LEVEL CHILDREN
Depend ONLY on Batch 1
| # | Table | Depends On | Foreign Key | Constraint Action |
|---|---|---|---|---|
| 8 | generated_articles |
sites | site_id → sites.id |
CASCADE |
| 9 | generation_jobs |
sites | site_id → sites.id |
CASCADE |
| 10 | pages |
sites | site_id → sites.id |
CASCADE |
| 11 | posts |
sites | site_id → sites.id |
CASCADE |
| 12 | leads |
sites | site_id → sites.id |
SET NULL |
| 13 | headline_inventory |
campaign_masters | campaign_id → campaign_masters.id |
CASCADE |
| 14 | content_fragments |
campaign_masters | campaign_id → campaign_masters.id |
CASCADE |
🏠 BATCH 3: COMPLEX CHILDREN
Depend on Batch 2 or have multiple dependencies
| # | Table | Depends On | Multiple FKs | Notes |
|---|---|---|---|---|
| 15 | link_targets |
sites | No | Internal linking system |
| 16 | (Future M2M) | Multiple | Yes | Junction tables go here |
🔍 DETAILED DEPENDENCY MAP
Visual Cascade
sites ─────────┬─── generated_articles
├─── generation_jobs
├─── pages
├─── posts
├─── leads
└─── link_targets
campaign_masters ─┬─── headline_inventory
├─── content_fragments
└─── (referenced by generated_articles)
└─── (uses article_templates via article_template field)
article_templates (standalone, referenced by campaign_masters)
avatar_intelligence (standalone)
avatar_variants (standalone)
cartesian_patterns (standalone)
geo_intelligence (standalone)
offer_blocks (standalone)
🚨 DETECTED ISSUES (from schema_issues.json)
Issue #1: Template Field Mismatch
Collection: content_fragments
Field: campaign_id (M2O relation)
Problem: Display template references campaign_name but campaign_masters has field name, not campaign_name
Fix: Update template to use {{campaign_id.name}} instead of {{campaign_id.campaign_name}}
Issue #2: Template Field Mismatch
Collection: headline_inventory
Field: campaign_id (M2O relation)
Problem: Same as above - references non-existent campaign_name
Fix: Update template to use {{campaign_id.name}}
📐 EXECUTION PLAN: Step-by-Step
Phase 1: Create Foundation (Batch 1)
# Order is CRITICAL - sites MUST be first
npx directus schema apply --only-collections \
sites,campaign_masters,avatar_intelligence,avatar_variants,cartesian_patterns,geo_intelligence,offer_blocks
Phase 2: Create Walls (Batch 2)
npx directus schema apply --only-collections \
generated_articles,generation_jobs,pages,posts,leads,headline_inventory,content_fragments
Phase 3: Create Roof (Batch 3)
npx directus schema apply --only-collections \
link_targets
Phase 4: Apply Relationships
# All foreign keys are applied AFTER tables exist
npx directus schema apply --only-relations
🎓 THE "MEASURE TWICE, CUT ONCE" PROMPT
Use this exact prompt to have AI execute your schema correctly:
**System Role:** You are a Senior Database Architect specializing in Directus and PostgreSQL.
**Input:** I have 16 collections in my Spark Platform schema.
**Task 1: Dependency Map (DO THIS FIRST)**
Before generating any API calls, output a Dependency Execution Plan:
1. **Identify Nodes:** List all collections
2. **Identify Edges:** List all foreign key relationships
3. **Group by Batches:**
- Batch 1: Independent tables (No foreign keys)
- Batch 2: First-level dependents (Only rely on Batch 1)
- Batch 3: Complex dependents (Rely on Batch 2 or multiple tables)
**Task 2: Directus Logic Check**
Confirm you identified:
- Standard tables vs. Singletons
- Real foreign key fields vs. M2M aliases (virtual fields)
- Display templates that might reference wrong field names
**Output Format:** Structured markdown table showing batches and dependencies.
**Once Approved:** Generate Directus API creation scripts in the correct order.
[PASTE schema_map.json HERE]
🔧 GOD-MODE API: Create Schema Programmatically
Using the God-Mode API to respect dependencies:
# BATCH 1: Foundation
curl https://spark.jumpstartscaling.com/god/schema/collections/create \
-H "X-God-Token: $GOD_MODE_TOKEN" \
-d '{"collection":"sites", "fields":[...]}'
curl https://spark.jumpstartscaling.com/god/schema/collections/create \
-H "X-God-Token: $GOD_MODE_TOKEN" \
-d '{"collection":"campaign_masters", "fields":[...]}'
# BATCH 2: Children (ONLY after Batch 1 completes)
curl https://spark.jumpstartscaling.com/god/schema/collections/create \
-H "X-God-Token: $GOD_MODE_TOKEN" \
-d '{"collection":"generated_articles", "fields":[...], "relations":[...]}'
# BATCH 3: Relations (ONLY after tables exist)
curl https://spark.jumpstartscaling.com/god/schema/relations/create \
-H "X-God-Token: $GOD_MODE_TOKEN" \
-d '{"collection":"generated_articles", "field":"site_id", "related_collection":"sites"}'
✅ VALIDATION CHECKLIST
After executing schema:
- Verify Batch 1:
SELECT * FROM sites LIMIT 1;works - Verify Batch 1:
SELECT * FROM campaign_masters LIMIT 1;works - Verify Batch 2: Foreign keys resolve (no constraint errors)
- Check schema_issues.json: Fix template field references
- Test M2O dropdowns in Directus admin UI
- Confirm all 16 collections appear in Directus
📊 COMPLETE FIELD-LEVEL ANALYSIS
sites (SUPER PARENT) ✅ Updated
| Field | Type | Interface | Notes |
|---|---|---|---|
| id | uuid | input (readonly) | Primary key |
| name | string | input (required) | Site display name |
| url | string | input | Domain |
| status | string | select-dropdown | active/inactive/archived |
| settings | json | — | NEW: Feature flags (JSONB) |
| date_created | datetime | — | Auto-generated |
| date_updated | datetime | — | Auto-updated |
Children: 10 tables reference this
campaign_masters (SUPER PARENT) ✅ Updated
| Field | Type | Interface | Notes |
|---|---|---|---|
| id | uuid | input (readonly) | Primary key |
| site_id | uuid | select-dropdown-m2o | → sites |
| name | string | input (required) | Campaign name |
| status | string | select-dropdown | active/inactive/completed/paused |
| target_word_count | integer | input | Content target |
| headline_spintax_root | string | textarea | Spintax template |
| location_mode | string | select | city/county/state/none |
| batch_count | integer | input | Batch size |
| article_template | uuid | select-dropdown-m2o | NEW: → article_templates |
| niche_variables | json | — | NEW: Template variables (JSONB) |
| date_created | datetime | — | Auto-generated |
| date_updated | datetime | — | Auto-updated |
Children: 4 tables reference this (headline_inventory, content_fragments, generated_articles)
article_templates \u2705 NEW Collection
| Field | Type | Interface | Notes |
|---|---|---|---|
| id | uuid/int | input (readonly) | Primary key (flexible type) |
| name | string | input | Template name |
| structure_json | json | — | Array of fragment types (defines article structure) |
| date_created | datetime | — | Auto-generated |
| date_updated | datetime | — | Auto-updated |
Purpose: Defines the order and types of content fragments to assemble articles
Example: ["intro_hook", "pillar_1", "pillar_2", ..., "faq_section"]
Used By: campaign_masters.article_template field
generated_articles (CHILD) ✅ Updated
Parent: sites
Relationship: site_id → sites.id (CASCADE)
| Field | Type | Notes |
|---|---|---|
| id | uuid | Primary key |
| site_id | uuid | FK → sites |
| campaign_id | uuid | FK → campaign_masters (optional) |
| status | string | draft/published/archived |
| title | string | Article title |
| slug | string | URL slug |
| content | text | Legacy field |
| is_published | boolean | Publication flag |
| headline | string | NEW: Processed headline |
| meta_title | string | NEW: SEO title (70 chars) |
| meta_description | string | NEW: SEO description (155 chars) |
| full_html_body | text | NEW: Complete assembled HTML |
| word_count | integer | NEW: Total word count |
| word_count_status | string | NEW: optimal/under_target |
| location_city | string | NEW: City variable |
| location_county | string | NEW: County variable |
| location_state | string | NEW: State variable |
| featured_image_svg | text | NEW: SVG code |
| featured_image_filename | string | NEW: Image filename |
| featured_image_alt | string | NEW: Alt text |
| schema_json | json | JSON-LD structured data |
Total Fields: 24 (12 added in Phase 9)
headline_inventory (CHILD) ✅ Updated
Parent: campaign_masters
Relationship: campaign_id → campaign_masters.id (CASCADE)
| Field | Type | Notes |
|---|---|---|
| id | uuid | Primary key |
| campaign_id | uuid | FK → campaign_masters |
| status | string | active/used/archived/available |
| headline_text | string | Original headline template |
| final_title_text | string | NEW: Fully processed title |
| location_data | json | NEW: Location vars (JSONB) |
| is_used | boolean | Used flag |
| used_on_article | uuid | NEW: FK → generated_articles.id |
Total Fields: 8 (3 added in Phase 9)
content_fragments (CHILD) ✅ Updated
Parent: campaign_masters
Relationship: campaign_id → campaign_masters.id (CASCADE)
| Field | Type | Notes |
|---|---|---|
| id | uuid | Primary key |
| campaign_id | uuid | FK → campaign_masters |
| status | string | active/archived |
| fragment_text | string | Legacy field name |
| content_body | text | NEW: HTML content fragment |
| fragment_type | string | Type (e.g., "sales_letter_core") |
| word_count | integer | NEW: Fragment word count |
Total Fields: 7 (2 added in Phase 9)
generation_jobs (CHILD) ✅ Updated
Parent: sites
Relationship: site_id → sites.id (CASCADE)
| Field | Type | Notes |
|---|---|---|
| id | uuid | Primary key |
| status | string | pending/processing/completed/failed |
| site_id | uuid | FK → sites |
| batch_size | integer | Articles per batch |
| target_quantity | integer | Total articles to generate |
| filters | json | Generation filters (JSONB) |
| current_offset | integer | Batch progress tracker |
| progress | integer | Percentage complete |
| date_created | datetime | NEW: Auto-generated |
| date_updated | datetime | NEW: Auto-updated |
Total Fields: 10 (2 added in Phase 9)
🎯 SUCCESS CRITERIA
Your schema is correct when:
- ✅ SQL Execution: No foreign key constraint errors
- ✅ Directus UI: All dropdowns show related data
- ✅ TypeScript: Auto-generated types match reality
- ✅ Frontend: No
undefinedfield errors - ✅ God-Mode API:
/god/schema/snapshotreturns valid YAML
🚀 NEXT STEPS
\u2705 Phase 9 Complete - All Items Done:
- \u2705 Fixed Template Issues: Updated display templates for
campaign_idfields - \u2705 Added Missing Interfaces: Applied
select-dropdown-m2oto all foreign key fields - \u2705 Generated TypeScript: Schema types fully updated and validated
- \u2705 Tested Fresh Install: Build successful with 0 TypeScript errors
- \u2705 Schema Deployed: Ready for deployment via God-Mode API
\u2728 PHASE 9 ACCOMPLISHMENTS
Schema Enhancements
- \u2705 New Collection: article_templates (5 fields)
- \u2705 Sites: +1 field (settings)
- \u2705 CampaignMasters: +3 fields (article_template, niche_variables, paused status)
- \u2705 GeneratedArticles: +12 fields (complete article metadata)
- \u2705 HeadlineInventory: +3 fields (final_title_text, location_data, used_on_article)
- \u2705 ContentFragments: +2 fields (content_body, word_count)
- \u2705 GenerationJobs: +2 fields (date_created, date_updated)
Code Fixes
- \u2705 Fixed 8 field name errors (campaign \u2192 campaign_id, site \u2192 site_id)
- \u2705 Fixed 3 null/undefined type coercion issues
- \u2705 Fixed 3 sort field references
- \u2705 Fixed 2 package.json validation errors
Validation
- \u2705 Build Status: Success (Exit Code 0)
- \u2705 TypeScript Errors: 0
- \u2705 Total Fields Added: 23
Remember: The Harris Matrix prevents the #1 cause of schema failures: trying to create relationships before the related tables exist.
God-Mode Key: $GOD_MODE_TOKEN (set in Coolify secrets)
Schema Version: v2.0 (Phase 9 - Dec 2025)