687 lines
10 KiB
Plaintext
687 lines
10 KiB
Plaintext
0. GOAL
|
|
|
|
When this refactor is complete:
|
|
|
|
You enter keywords in Planner.
|
|
|
|
Clusters and ideas are created.
|
|
|
|
Writer generates tasks and content.
|
|
|
|
Content Manager becomes the single source of truth.
|
|
|
|
One click publish sends content to WordPress.
|
|
|
|
All mappings (cluster, taxonomies, site) are correct.
|
|
|
|
Linker, Optimizer, IGNY8 hosted sites stay out of scope for now.
|
|
|
|
This spec assumes all earlier decisions you made about models and statuses are final.
|
|
|
|
1. END TO END FLOW (KEYWORD TO PUBLISH)
|
|
1.1 High level flow
|
|
|
|
Planner
|
|
|
|
Input keywords
|
|
|
|
Generate clusters
|
|
|
|
Generate ideas per cluster
|
|
|
|
Convert ideas into Writer tasks
|
|
|
|
Writer
|
|
|
|
Tasks created with content_type and content_structure
|
|
|
|
AI generates draft content
|
|
|
|
Task marked completed
|
|
|
|
Content saved as draft entry
|
|
|
|
Content Manager
|
|
|
|
Lists all content for a site (imported and AI written)
|
|
|
|
You edit, assign cluster and taxonomies if needed
|
|
|
|
You click publish for selected content
|
|
|
|
Publish to WordPress
|
|
|
|
IGNY8 sends content HTML and metadata to WP via REST
|
|
|
|
WP creates or updates post / page / product
|
|
|
|
WP returns ID and URL
|
|
|
|
IGNY8 saves external_id and external_url
|
|
|
|
Content status goes from draft to published
|
|
|
|
Task status already completed when content was generated
|
|
|
|
Only Content has draft/published.
|
|
Only Task has queued/completed.
|
|
Planner and Writer do not track sync.
|
|
|
|
2. BACKEND DATA MODEL (FINAL)
|
|
|
|
This is the corrected model set the whole system is built on.
|
|
|
|
2.1 Cluster
|
|
|
|
Pure topic. Parent of everything else.
|
|
|
|
Not tied to a content type.
|
|
|
|
Fields:
|
|
|
|
id
|
|
|
|
site
|
|
|
|
sector
|
|
|
|
name
|
|
|
|
description
|
|
|
|
created_at
|
|
|
|
updated_at
|
|
|
|
Remove: context_type, dimension_meta.
|
|
|
|
2.2 Task
|
|
|
|
Planner → Writer contract for content creation.
|
|
|
|
Fields:
|
|
|
|
id
|
|
|
|
site
|
|
|
|
sector
|
|
|
|
cluster (FK → Cluster, required)
|
|
|
|
content_type (Article, Page, Product, Taxonomy)
|
|
|
|
content_structure (Review, Comparison, Tutorial, Listicle, Landing Page, Archive Page, etc)
|
|
|
|
taxonomy_term (FK → ContentTaxonomy, optional, used when targeting a taxonomy archive)
|
|
|
|
keywords (M2M → Keyword)
|
|
|
|
status (queued, completed)
|
|
|
|
created_at
|
|
|
|
updated_at
|
|
|
|
Remove: cluster_role, sync_status.
|
|
|
|
2.3 Content
|
|
|
|
Writer output and imported WP content, managed in Content Manager.
|
|
|
|
Fields:
|
|
|
|
id
|
|
|
|
site
|
|
|
|
sector
|
|
|
|
cluster (FK → Cluster, required)
|
|
|
|
content_type (Article, Page, Product, Taxonomy)
|
|
|
|
content_structure
|
|
|
|
title
|
|
|
|
content_html
|
|
|
|
taxonomy_terms (M2M → ContentTaxonomy)
|
|
|
|
external_id (WP post_id, nullable)
|
|
|
|
external_url (WP permalink, nullable)
|
|
|
|
status (draft, published)
|
|
|
|
source (igny8, wordpress)
|
|
|
|
created_at
|
|
|
|
updated_at
|
|
|
|
Remove: cluster_role, sync_status.
|
|
|
|
2.4 ContentTaxonomy
|
|
|
|
WordPress taxonomies and IGNY8 cluster-like taxonomies.
|
|
|
|
Fields:
|
|
|
|
id
|
|
|
|
site
|
|
|
|
sector
|
|
|
|
name
|
|
|
|
slug
|
|
|
|
taxonomy_type (category, tag, product_category, product_attribute, cluster, service_category if you keep it)
|
|
|
|
external_taxonomy (WP taxonomy slug, e.g. category, post_tag, product_cat, pa_size; null for cluster)
|
|
|
|
external_id (WP term_id; null for igy8 custom terms and clusters)
|
|
|
|
created_at
|
|
|
|
updated_at
|
|
|
|
Remove: sync_status.
|
|
|
|
3. WORDPRESS ↔ IGNY8 DATA FLOWS
|
|
3.1 WordPress → IGNY8 (import / sync)
|
|
Plugin endpoints
|
|
|
|
WordPress plugin provides:
|
|
|
|
/wp-json/igny8/v1/site-metadata
|
|
|
|
/wp-json/igny8/v1/posts
|
|
|
|
/wp-json/igny8/v1/taxonomies
|
|
|
|
Possibly specific endpoints like /post-by-task-id, /post-by-content-id
|
|
|
|
Plugin responsibilities:
|
|
|
|
Export posts, pages, products with:
|
|
|
|
post_id
|
|
|
|
post_type
|
|
|
|
post_title
|
|
|
|
post_content
|
|
|
|
permalink
|
|
|
|
taxonomies (term_ids + taxonomy slugs)
|
|
|
|
meta keys for any IGNY8 links (optional)
|
|
|
|
Export taxonomies:
|
|
|
|
term_id
|
|
|
|
name
|
|
|
|
slug
|
|
|
|
taxonomy
|
|
|
|
IGNY8 backend behaviour
|
|
|
|
When importing posts:
|
|
|
|
Create Content rows:
|
|
|
|
site, sector inferred from site record
|
|
|
|
cluster: null initially (to be assigned later)
|
|
|
|
content_type mapped from WP post_type:
|
|
|
|
post ⇒ Article
|
|
|
|
page ⇒ Page
|
|
|
|
product ⇒ Product
|
|
|
|
content_structure: optional default (e.g. ImportedArticle, ImportedPage)
|
|
|
|
title, content_html from WP
|
|
|
|
external_id = post_id
|
|
|
|
external_url = permalink
|
|
|
|
status = draft
|
|
|
|
source = wordpress
|
|
|
|
Link taxonomy terms:
|
|
|
|
For each term on the WP post:
|
|
|
|
upsert ContentTaxonomy by external_id + external_taxonomy
|
|
|
|
attach to Content.taxonomy_terms
|
|
|
|
When importing taxonomies:
|
|
|
|
For each WP term:
|
|
|
|
Create ContentTaxonomy if it does not exist:
|
|
|
|
name
|
|
|
|
slug
|
|
|
|
taxonomy_type derived from taxonomy (category, tag, product_category, product_attribute)
|
|
|
|
external_taxonomy = WP taxonomy slug
|
|
|
|
external_id = term_id
|
|
|
|
No sync_status is needed.
|
|
Imported items are identified by source=wordpress and external_id present.
|
|
|
|
3.2 IGNY8 → WordPress (publish)
|
|
|
|
Publishing is done only from Content Manager, not from Planner or Writer.
|
|
|
|
Backend publishing service
|
|
|
|
Given a Content id:
|
|
|
|
Load Content:
|
|
|
|
ensure status = draft
|
|
|
|
ensure site record configured with WP endpoint and auth
|
|
|
|
Prepare payload:
|
|
|
|
post_type based on content_type
|
|
|
|
post_title from Content.title
|
|
|
|
post_content from Content.content_html
|
|
|
|
tax_input from Content.taxonomy_terms mapped through external_taxonomy and external_id
|
|
|
|
Call WordPress REST:
|
|
|
|
POST /wp-json/wp/v2/{post_type}
|
|
|
|
On success:
|
|
|
|
response.id ⇒ Content.external_id
|
|
|
|
response.link ⇒ Content.external_url
|
|
|
|
Content.status ⇒ published
|
|
|
|
Do not touch Task; Task was marked completed when content was generated.
|
|
|
|
If the Content row already has an external_id, publishing should update that post instead of creating a new one.
|
|
|
|
WordPress plugin side
|
|
|
|
Accept incoming POST from IGNY8:
|
|
|
|
Validate token / key
|
|
|
|
Create or update the post:
|
|
|
|
set post_title, post_content, post_type, post_status=publish
|
|
|
|
set taxonomies based on term IDs
|
|
|
|
Return:
|
|
|
|
id
|
|
|
|
link
|
|
|
|
Plugin may optionally store meta keys like _igny8_content_id or _igny8_cluster_id, but this is optional.
|
|
|
|
4. CONTENT MANAGER AS SOURCE OF TRUTH
|
|
|
|
Content Manager is the last part of the flow.
|
|
|
|
4.1 Role
|
|
|
|
Content Manager:
|
|
|
|
Shows all content for a site:
|
|
|
|
imported from WP
|
|
|
|
generated by Writer
|
|
|
|
Allows editing and assigning:
|
|
|
|
cluster
|
|
|
|
taxonomy_terms
|
|
|
|
Controls publish to WordPress.
|
|
|
|
Reflects the final status for each content item:
|
|
|
|
draft
|
|
|
|
published
|
|
|
|
All other modules are upstream.
|
|
They feed into Content Manager, but do not override its status.
|
|
|
|
4.2 Content Manager data model usage
|
|
|
|
Content listing uses:
|
|
|
|
Content.id
|
|
|
|
Content.title
|
|
|
|
Content.content_type
|
|
|
|
Content.content_structure
|
|
|
|
Content.cluster
|
|
|
|
Content.taxonomy_terms
|
|
|
|
Content.status
|
|
|
|
Content.external_id
|
|
|
|
Content.external_url
|
|
|
|
Content.source
|
|
|
|
Content.created_at / updated_at
|
|
|
|
4.3 Content Manager UX requirements
|
|
|
|
Table columns:
|
|
|
|
Title
|
|
|
|
Type (Article / Page / Product / Taxonomy)
|
|
|
|
Structure (Review, Landing Page, Archive Page, etc)
|
|
|
|
Cluster (with link to cluster detail)
|
|
|
|
Taxonomies (comma separated list of taxonomy term names)
|
|
|
|
Status (draft/published)
|
|
|
|
Source (IGNY8, WordPress)
|
|
|
|
URL (clickable if published)
|
|
|
|
Actions (Edit, Publish, View in WordPress)
|
|
|
|
Filters:
|
|
|
|
content_type
|
|
|
|
status
|
|
|
|
cluster
|
|
|
|
taxonomy_type (optional)
|
|
|
|
source
|
|
|
|
Row actions:
|
|
|
|
Edit:
|
|
|
|
Opens editor on Content:
|
|
|
|
edit title
|
|
|
|
edit content_html
|
|
|
|
attach or change cluster
|
|
|
|
attach or change taxonomy_terms
|
|
|
|
Publish:
|
|
|
|
Calls backend publish service
|
|
|
|
On success:
|
|
|
|
status becomes published
|
|
|
|
external_id and external_url are filled
|
|
|
|
View in WordPress:
|
|
|
|
Opens external_url in new tab
|
|
|
|
4.4 Cluster and taxonomy assignment rules
|
|
|
|
New content generated from tasks:
|
|
|
|
cluster is assigned automatically from the Task.cluster
|
|
|
|
taxonomy_terms can be empty initially
|
|
|
|
Imported content from WordPress:
|
|
|
|
cluster must be manually assigned in Content Manager or via auto mapping later
|
|
|
|
taxonomy_terms are imported automatically
|
|
|
|
Content Manager must allow:
|
|
|
|
batch cluster assignment:
|
|
|
|
select multiple rows
|
|
|
|
assign one cluster
|
|
|
|
batch taxonomy assignment:
|
|
|
|
select rows
|
|
|
|
attach a taxonomy term
|
|
|
|
5. FRONTEND MODULES ALIGNED WITH THIS FLOW
|
|
5.1 Planner
|
|
|
|
Key UI responsibilities:
|
|
|
|
Keywords input and cluster generation
|
|
|
|
Idea generation per cluster
|
|
|
|
Create tasks that are passed to Writer
|
|
|
|
Data it needs to pass to Writer:
|
|
|
|
cluster_id
|
|
|
|
content_type
|
|
|
|
content_structure
|
|
|
|
primary_keyword
|
|
|
|
any extra parameters (tone, target country etc)
|
|
|
|
5.2 Writer
|
|
|
|
Key UI responsibilities:
|
|
|
|
List tasks with status (queued/completed)
|
|
|
|
For each task:
|
|
|
|
show cluster
|
|
|
|
content_type
|
|
|
|
content_structure
|
|
|
|
primary_keyword
|
|
|
|
Actions:
|
|
|
|
Generate draft content
|
|
|
|
View generated draft
|
|
|
|
Writer does not publish and does not talk to WordPress directly.
|
|
|
|
5.3 Sites
|
|
|
|
For this DDAY refactor, keep only:
|
|
|
|
grid view of sites
|
|
|
|
for each site card:
|
|
|
|
Dashboard button
|
|
|
|
Content Manager button
|
|
|
|
Settings button
|
|
|
|
Active/inactive toggle at the top
|
|
|
|
Remove:
|
|
|
|
Pages button and its backend logic
|
|
|
|
Sectors button from card (moved into Site Settings tab)
|
|
|
|
Site builder and blueprints buttons (out of scope)
|
|
|
|
The Content Manager for a site is reachable from the site card.
|
|
|
|
5.4 Cluster Detail Page
|
|
|
|
When clicking a cluster:
|
|
|
|
Show:
|
|
|
|
cluster name and description
|
|
|
|
tabs or sections per content_type:
|
|
|
|
Articles
|
|
|
|
Pages
|
|
|
|
Products
|
|
|
|
Taxonomy Pages
|
|
|
|
each section listing content entries linked to that cluster
|
|
|
|
This view can internally reuse the Content Manager data but filtered by cluster.
|
|
|
|
6. STATE MACHINE SUMMARY
|
|
6.1 Task
|
|
|
|
queued:
|
|
|
|
created from Planner or manually
|
|
|
|
completed:
|
|
|
|
AI content generated and saved to Content table
|
|
|
|
Task never changes when publish happens.
|
|
|
|
6.2 Content
|
|
|
|
draft:
|
|
|
|
created from Writer completion or from WordPress import
|
|
|
|
published:
|
|
|
|
after successful publish to WordPress
|
|
|
|
There is no separate sync_status in this refactor.
|
|
If external_id is present and status is published, it is live.
|
|
|
|
7. IMPLEMENTATION CHECKLIST
|
|
|
|
To actually complete this DDAY refactor:
|
|
|
|
Backend
|
|
|
|
Update models:
|
|
|
|
Remove fields: cluster_role, sync_status, context_type, dimension_meta, ContentTaxonomy.sync_status
|
|
|
|
Add or rename fields: taxonomy_term on Task, taxonomy_terms M2M on Content if not already consistent
|
|
|
|
Regenerate migrations.
|
|
|
|
Update serializers:
|
|
|
|
Remove removed fields
|
|
|
|
Add or rename fields accordingly
|
|
|
|
Review all viewsets and services:
|
|
|
|
Task creation and listing
|
|
|
|
Content creation, listing, edit
|
|
|
|
WordPress import service
|
|
|
|
WordPress publish service
|
|
|
|
Confirm WordPress plugin endpoints match expected payloads.
|
|
|
|
Frontend
|
|
|
|
Planner:
|
|
|
|
Ensure ideas create tasks with cluster_id, content_type, content_structure.
|
|
|
|
Writer:
|
|
|
|
Only show queued/completed status.
|
|
|
|
No sync related fields.
|
|
|
|
Link to open draft in Content Manager (optional but helpful).
|
|
|
|
Sites:
|
|
|
|
Remove builder-related buttons.
|
|
|
|
Only show Dashboard, Content, Settings.
|
|
|
|
Move toggle and sectors UI as per your earlier 18 points.
|
|
|
|
Content Manager:
|
|
|
|
Implement table with final columns and filters.
|
|
|
|
Implement Edit and Publish actions as defined.
|
|
|
|
Ensure every content row came from Content model only.
|
|
|
|
Integrate cluster and taxonomy selectors.
|
|
|
|
Cluster detail:
|
|
|
|
Filter Content list by cluster_id and group by content_type |