diff --git a/frontend/src/components/admin/content/GeoManager.tsx b/frontend/src/components/admin/content/GeoManager.tsx
index 25e3f35..7a739fa 100644
--- a/frontend/src/components/admin/content/GeoManager.tsx
+++ b/frontend/src/components/admin/content/GeoManager.tsx
@@ -4,32 +4,12 @@ import { getDirectusClient } from '@/lib/directus/client';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Badge } from '@/components/ui/badge';
-export default function GeoManager() {
- const [clusters, setClusters] = useState([]);
- const [loading, setLoading] = useState(true);
+interface Props {
+ initialClusters?: any[];
+}
- useEffect(() => {
- loadData();
- }, []);
-
- const loadData = async () => {
- try {
- const directus = await getDirectusClient();
- const response = await directus.request({
- method: 'GET',
- path: '/items/geo_intelligence'
- });
- setClusters(response.data || []);
- setLoading(false);
- } catch (error) {
- console.error('Error loading geo clusters:', error);
- setLoading(false);
- }
- };
-
- if (loading) {
- return
Loading Geo Intelligence...
;
- }
+export default function GeoManager({ initialClusters = [] }: Props) {
+ const [clusters, setClusters] = useState(initialClusters);
return (
diff --git a/frontend/src/components/admin/content/SpintaxManager.tsx b/frontend/src/components/admin/content/SpintaxManager.tsx
index d144f08..10cd425 100644
--- a/frontend/src/components/admin/content/SpintaxManager.tsx
+++ b/frontend/src/components/admin/content/SpintaxManager.tsx
@@ -4,32 +4,12 @@ import { getDirectusClient } from '@/lib/directus/client';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Badge } from '@/components/ui/badge';
-export default function SpintaxManager() {
- const [dictionaries, setDictionaries] = useState([]);
- const [loading, setLoading] = useState(true);
+interface Props {
+ initialDictionaries?: any[];
+}
- useEffect(() => {
- loadData();
- }, []);
-
- const loadData = async () => {
- try {
- const directus = await getDirectusClient();
- const response = await directus.request({
- method: 'GET',
- path: '/items/spintax_dictionaries'
- });
- setDictionaries(response.data || []);
- setLoading(false);
- } catch (error) {
- console.error('Error loading spintax dictionaries:', error);
- setLoading(false);
- }
- };
-
- if (loading) {
- return
Loading Spintax Dictionaries...
;
- }
+export default function SpintaxManager({ initialDictionaries = [] }: Props) {
+ const [dictionaries, setDictionaries] = useState(initialDictionaries);
return (
diff --git a/frontend/src/pages/admin/content/avatars.astro b/frontend/src/pages/admin/content/avatars.astro
index 12122fe..d161b0a 100644
--- a/frontend/src/pages/admin/content/avatars.astro
+++ b/frontend/src/pages/admin/content/avatars.astro
@@ -2,6 +2,11 @@
---
import Layout from '@/layouts/AdminLayout.astro';
import AvatarManager from '@/components/admin/content/AvatarManager';
+import { getDirectusClient, readItems } from '@/lib/directus/client';
+
+const directus = getDirectusClient();
+const avatars = await directus.request(readItems('avatar_intelligence')).catch(() => []);
+const variants = await directus.request(readItems('avatar_variants')).catch(() => []);
---
@@ -9,6 +14,6 @@ import AvatarManager from '@/components/admin/content/AvatarManager';
Avatar Intelligence
Manage your 10 base avatars, variants, and business niches.
-
+
diff --git a/frontend/src/pages/admin/content/cartesian_patterns.astro b/frontend/src/pages/admin/content/cartesian_patterns.astro
index 301c5b6..8752f1b 100644
--- a/frontend/src/pages/admin/content/cartesian_patterns.astro
+++ b/frontend/src/pages/admin/content/cartesian_patterns.astro
@@ -1,14 +1,17 @@
-
---
import Layout from '@/layouts/AdminLayout.astro';
import CartesianManager from '@/components/admin/content/CartesianManager';
+import { getDirectusClient, readItems } from '@/lib/directus/client';
+
+const directus = getDirectusClient();
+const patterns = await directus.request(readItems('cartesian_patterns')).catch(() => []);
---
Cartesian Patterns
-
Headline and Hook Formulas for the Multiplication Engine.
+
Manage headline and content generation formulas.
-
+
diff --git a/frontend/src/pages/admin/content/geo_clusters.astro b/frontend/src/pages/admin/content/geo_clusters.astro
index f749184..b46a359 100644
--- a/frontend/src/pages/admin/content/geo_clusters.astro
+++ b/frontend/src/pages/admin/content/geo_clusters.astro
@@ -1,14 +1,17 @@
-
---
import Layout from '@/layouts/AdminLayout.astro';
import GeoManager from '@/components/admin/content/GeoManager';
+import { getDirectusClient, readItems } from '@/lib/directus/client';
+
+const directus = getDirectusClient();
+const clusters = await directus.request(readItems('geo_intelligence')).catch(() => []);
---
-
+
-
Geo Clusters
-
Manage Geographic Intelligence (Silicon Valleys, Growth Havens) for localized content.
+
Geo Intelligence
+
Manage your geographic targeting clusters.
-
+
diff --git a/frontend/src/pages/admin/content/spintax_dictionaries.astro b/frontend/src/pages/admin/content/spintax_dictionaries.astro
index 7275b6c..ec2e4a3 100644
--- a/frontend/src/pages/admin/content/spintax_dictionaries.astro
+++ b/frontend/src/pages/admin/content/spintax_dictionaries.astro
@@ -1,14 +1,17 @@
-
---
import Layout from '@/layouts/AdminLayout.astro';
import SpintaxManager from '@/components/admin/content/SpintaxManager';
+import { getDirectusClient, readItems } from '@/lib/directus/client';
+
+const directus = getDirectusClient();
+const dictionaries = await directus.request(readItems('spintax_dictionaries')).catch(() => []);
---
-
+
Spintax Dictionaries
-
Global Search & Replace Dictionaries for content randomization.
+
Manage word variations for automated content generation.
-
+
diff --git a/full-schema-update.sql b/full-schema-update.sql
new file mode 100644
index 0000000..927a823
--- /dev/null
+++ b/full-schema-update.sql
@@ -0,0 +1,137 @@
+-- Spark Platform - Full Schema Update
+-- Adds missing tables for SEO Engine and Cartesian Engine
+
+-- 1. generated_articles (replacing/aliasing posts)
+CREATE TABLE IF NOT EXISTS generated_articles (
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid (),
+ site_id UUID REFERENCES sites (id) ON DELETE CASCADE,
+ title VARCHAR(500) NOT NULL,
+ slug VARCHAR(500) NOT NULL,
+ html_content TEXT,
+ generation_hash VARCHAR(255),
+ meta_desc TEXT,
+ is_published BOOLEAN DEFAULT FALSE,
+ sync_status VARCHAR(50),
+ sitemap_status VARCHAR(50) DEFAULT 'ghost', -- ghost, queued, indexed
+ campaign_id UUID, -- Reference to campaign_masters
+ date_created TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+ date_updated TIMESTAMP DEFAULT CURRENT_TIMESTAMP
+);
+
+-- 2. campaign_masters
+CREATE TABLE IF NOT EXISTS campaign_masters (
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid (),
+ site_id UUID REFERENCES sites (id) ON DELETE CASCADE,
+ name VARCHAR(255) NOT NULL,
+ headline_spintax_root TEXT,
+ niche_variables JSONB,
+ location_mode VARCHAR(50),
+ location_target VARCHAR(255),
+ batch_count INTEGER DEFAULT 0,
+ status VARCHAR(50) DEFAULT 'active',
+ date_created TIMESTAMP DEFAULT CURRENT_TIMESTAMP
+);
+
+-- 3. headline_inventory
+CREATE TABLE IF NOT EXISTS headline_inventory (
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid (),
+ campaign_id UUID REFERENCES campaign_masters (id) ON DELETE CASCADE,
+ final_title_text TEXT NOT NULL,
+ status VARCHAR(50) DEFAULT 'available',
+ used_on_article UUID, -- Reference to generated_articles
+ date_created TIMESTAMP DEFAULT CURRENT_TIMESTAMP
+);
+
+-- 4. content_fragments
+CREATE TABLE IF NOT EXISTS content_fragments (
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid (),
+ campaign_id UUID REFERENCES campaign_masters (id) ON DELETE CASCADE,
+ fragment_type VARCHAR(100),
+ content_body TEXT,
+ word_count INTEGER,
+ date_created TIMESTAMP DEFAULT CURRENT_TIMESTAMP
+);
+
+-- 5. generation_jobs (Cartesian Engine)
+CREATE TABLE IF NOT EXISTS generation_jobs (
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid (),
+ site_id UUID REFERENCES sites (id) ON DELETE CASCADE,
+ target_quantity INTEGER,
+ status VARCHAR(50) DEFAULT 'Pending',
+ filters JSONB,
+ current_offset INTEGER DEFAULT 0,
+ date_created TIMESTAMP DEFAULT CURRENT_TIMESTAMP
+);
+
+-- Register collections
+INSERT INTO
+ directus_collections (
+ collection,
+ icon,
+ note,
+ hidden,
+ singleton,
+ accountability
+ )
+VALUES (
+ 'generated_articles',
+ 'article',
+ 'SEO Generated Articles',
+ false,
+ false,
+ 'all'
+ ),
+ (
+ 'campaign_masters',
+ 'campaign',
+ 'SEO Campaigns',
+ false,
+ false,
+ 'all'
+ ),
+ (
+ 'headline_inventory',
+ 'title',
+ 'Generated Headlines',
+ false,
+ false,
+ 'all'
+ ),
+ (
+ 'content_fragments',
+ 'extension',
+ 'Content Blocks',
+ false,
+ false,
+ 'all'
+ ),
+ (
+ 'generation_jobs',
+ 'engineering',
+ 'Generation Jobs',
+ false,
+ false,
+ 'all'
+ ) ON CONFLICT (collection) DO NOTHING;
+
+-- Register fields for generated_articles
+INSERT INTO directus_fields (collection, field, type, interface, special)
+VALUES
+ ('generated_articles', 'id', 'uuid', 'input', ARRAY['uuid']),
+ ('generated_articles', 'site_id', 'uuid', 'select-dropdown-m2o', NULL),
+ ('generated_articles', 'title', 'string', 'input', NULL),
+ ('generated_articles', 'slug', 'string', 'input', NULL),
+ ('generated_articles', 'html_content', 'text', 'input-rich-text-html', NULL),
+ ('generated_articles', 'is_published', 'boolean', 'boolean', NULL),
+ ('generated_articles', 'sitemap_status', 'string', 'select-dropdown', NULL),
+ ('generated_articles', 'date_created', 'timestamp', 'datetime', ARRAY['date-created'])
+ON CONFLICT (collection, field) DO NOTHING;
+
+-- Register fields for campaign_masters
+INSERT INTO directus_fields (collection, field, type, interface, special)
+VALUES
+ ('campaign_masters', 'id', 'uuid', 'input', ARRAY['uuid']),
+ ('campaign_masters', 'name', 'string', 'input', NULL),
+ ('campaign_masters', 'status', 'string', 'select-dropdown', NULL),
+ ('campaign_masters', 'date_created', 'timestamp', 'datetime', ARRAY['date-created'])
+ON CONFLICT (collection, field) DO NOTHING;
\ No newline at end of file