Files
net/complete_schema.sql

200 lines
7.3 KiB
SQL

-- ===================================================================================
-- 🛠️ SPARK PLATFORM: GOLDEN SCHEMA (HARRIS MATRIX ORDERED)
-- ===================================================================================
-- 1. Foundation (Independent Tables)
-- 2. Walls (First-Level Dependents)
-- 3. Roof (Complex Dependents)
-- 4. Directus UI Configuration (Interfaces & Templates)
-- ===================================================================================
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
CREATE EXTENSION IF NOT EXISTS "pgcrypto";
-- ===================================================================================
-- 🏗️ BATCH 1: THE FOUNDATION (Create these FIRST)
-- Dependencies: None
-- ===================================================================================
-- 1. SITES (The Super Parent)
CREATE TABLE IF NOT EXISTS sites (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
status VARCHAR(50) DEFAULT 'active',
name VARCHAR(255) NOT NULL,
url VARCHAR(500),
date_created TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
date_updated TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 2. CAMPAIGN MASTERS (The Content Parent)
-- NOTE: Depends on 'sites' existing!
CREATE TABLE IF NOT EXISTS campaign_masters (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
status VARCHAR(50) DEFAULT 'active',
site_id UUID REFERENCES sites(id) ON DELETE CASCADE, -- 🔗 Link to Site
name VARCHAR(255) NOT NULL,
headline_spintax_root TEXT,
target_word_count INTEGER DEFAULT 1500,
date_created TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
date_updated TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 3-7. INDEPENDENT INTELLIGENCE TABLES
CREATE TABLE IF NOT EXISTS avatar_intelligence (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
status VARCHAR(50) DEFAULT 'published',
name VARCHAR(255),
pain_points JSONB,
demographics JSONB
);
CREATE TABLE IF NOT EXISTS avatar_variants (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
status VARCHAR(50) DEFAULT 'published',
name VARCHAR(255),
prompt_modifier TEXT
);
CREATE TABLE IF NOT EXISTS cartesian_patterns (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
status VARCHAR(50) DEFAULT 'published',
name VARCHAR(255),
pattern_logic TEXT
);
CREATE TABLE IF NOT EXISTS geo_intelligence (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
status VARCHAR(50) DEFAULT 'published',
city VARCHAR(255),
state VARCHAR(255),
population INTEGER
);
CREATE TABLE IF NOT EXISTS offer_blocks (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
status VARCHAR(50) DEFAULT 'published',
name VARCHAR(255),
html_content TEXT
);
-- ===================================================================================
-- 🧱 BATCH 2: THE WALLS (First-Level Children)
-- Dependencies: 'sites' or 'campaign_masters'
-- ===================================================================================
-- 8. GENERATED ARTICLES
CREATE TABLE IF NOT EXISTS generated_articles (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
status VARCHAR(50) DEFAULT 'draft',
site_id UUID REFERENCES sites(id) ON DELETE CASCADE,
campaign_id UUID REFERENCES campaign_masters(id) ON DELETE SET NULL,
title VARCHAR(255),
content TEXT,
slug VARCHAR(255),
schema_json JSONB,
date_created TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 9. GENERATION JOBS
CREATE TABLE IF NOT EXISTS generation_jobs (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
status VARCHAR(50) DEFAULT 'pending',
site_id UUID REFERENCES sites(id) ON DELETE CASCADE,
batch_size INTEGER DEFAULT 10,
progress INTEGER DEFAULT 0
);
-- 10. PAGES
CREATE TABLE IF NOT EXISTS pages (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
status VARCHAR(50) DEFAULT 'published',
site_id UUID REFERENCES sites(id) ON DELETE CASCADE,
title VARCHAR(255),
slug VARCHAR(255),
content TEXT,
schema_json JSONB
);
-- 11. POSTS
CREATE TABLE IF NOT EXISTS posts (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
status VARCHAR(50) DEFAULT 'published',
site_id UUID REFERENCES sites(id) ON DELETE CASCADE,
title VARCHAR(255),
slug VARCHAR(255),
content TEXT,
schema_json JSONB
);
-- 12. LEADS
CREATE TABLE IF NOT EXISTS leads (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
status VARCHAR(50) DEFAULT 'new',
site_id UUID REFERENCES sites(id) ON DELETE SET NULL,
email VARCHAR(255),
name VARCHAR(255),
source VARCHAR(100)
);
-- 13. HEADLINE INVENTORY
CREATE TABLE IF NOT EXISTS headline_inventory (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
status VARCHAR(50) DEFAULT 'active',
campaign_id UUID REFERENCES campaign_masters(id) ON DELETE CASCADE,
headline_text VARCHAR(255),
is_used BOOLEAN DEFAULT FALSE
);
-- 14. CONTENT FRAGMENTS
CREATE TABLE IF NOT EXISTS content_fragments (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
status VARCHAR(50) DEFAULT 'active',
campaign_id UUID REFERENCES campaign_masters(id) ON DELETE CASCADE,
fragment_text TEXT,
fragment_type VARCHAR(50)
);
-- ===================================================================================
-- 🏠 BATCH 3: THE ROOF (Complex Dependents)
-- Dependencies: Multiple tables
-- ===================================================================================
-- 15. LINK TARGETS (Internal Linking Logic)
CREATE TABLE IF NOT EXISTS link_targets (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
status VARCHAR(50) DEFAULT 'active',
site_id UUID REFERENCES sites(id) ON DELETE CASCADE,
target_url VARCHAR(500),
anchor_text VARCHAR(255),
keyword_focus VARCHAR(255)
);
-- ===================================================================================
-- 🎨 DIRECTUS UI CONFIGURATION (The "Glance" Layer)
-- Fixes interfaces, dropdowns, and template issues automatically
-- ===================================================================================
-- 1. Enable 'Select Dropdown' for all Foreign Keys (Fixes "Raw UUID" UI issue)
INSERT INTO directus_fields (collection, field, interface, readonly, hidden, width)
VALUES
('campaign_masters', 'site_id', 'select-dropdown-m2o', 'false', 'false', 'half'),
('generated_articles', 'site_id', 'select-dropdown-m2o', 'false', 'false', 'half'),
('generated_articles', 'campaign_id', 'select-dropdown-m2o', 'false', 'false', 'half'),
('generation_jobs', 'site_id', 'select-dropdown-m2o', 'false', 'false', 'half'),
('pages', 'site_id', 'select-dropdown-m2o', 'false', 'false', 'half'),
('posts', 'site_id', 'select-dropdown-m2o', 'false', 'false', 'half'),
('leads', 'site_id', 'select-dropdown-m2o', 'false', 'false', 'half'),
('headline_inventory', 'campaign_id', 'select-dropdown-m2o', 'false', 'false', 'half'),
('content_fragments', 'campaign_id', 'select-dropdown-m2o', 'false', 'false', 'half'),
('link_targets', 'site_id', 'select-dropdown-m2o', 'false', 'false', 'half')
ON CONFLICT (collection, field)
DO UPDATE SET interface = 'select-dropdown-m2o';
-- 2. Fix the Template Mismatch (The 'campaign_name' vs 'name' bug)
UPDATE directus_collections
SET display_template = '{{campaign_id.name}}'
WHERE collection IN ('content_fragments', 'headline_inventory', 'generated_articles');
-- 3. Set standard display templates for Sites
UPDATE directus_collections
SET display_template = '{{name}}'
WHERE collection IN ('sites', 'campaign_masters');