# Phase 3 Build Plan — WordPress Ecosystem (4 Docs) **Purpose:** This is a single instruction set for Claude Code to build all 4 Phase 3 execution documents. Read this entire file, then build each doc one at a time. --- ## CRITICAL BASELINE RULES (from V2-Execution-Docs-Updated) Before writing ANY doc, internalize these codebase-verified facts: ### Primary Keys - ALL models use `BigAutoField` (integer PKs, NOT UUIDs) - `DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'` - Every ID in API requests/responses is an integer ### Model Names (PLURAL) - `Clusters` (not Cluster), `Keywords` (not Keyword), `Tasks` (not Task) - `ContentIdeas` (not ContentIdea), `Images` (not Image), `Content` (stays singular) ### App Structure - Project root: `igny8_core/` - SAG app: `igny8_core/sag/` - App labels: `igny8_core_auth`, `planner`, `writer`, `automation`, `integration`, etc. - All tables use `igny8_` prefix (e.g., `igny8_content`, `igny8_clusters`) ### Frontend Stack - TypeScript (`.tsx` files, NOT `.jsx`) - Zustand for state management (NOT Redux) - Vite ^6.1.0 as build tool - React ^19.0.0 - Vitest + Playwright for testing (NOT Selenium/Cypress) ### Verified Codebase Versions (what actually runs today) - Python 3.11-slim (Dockerfile) - Django >=5.2.7 (requirements.txt) - Node 18-alpine (Dockerfile.dev) - Celery >=5.3.0 - WP Plugin: IGNY8 WordPress Bridge v1.5.2 - These are CURRENT versions. Upgrade targets (Python 3.14, Django 6.0, etc.) are in 00B but are SEPARATE tasks. ### Model Inheritance - `AccountBaseModel` provides: `account` FK, `created_by`, `created_at`, `updated_at` - `SiteSectorBaseModel` extends AccountBaseModel with: `site` FK, `sector` FK - `SoftDeletableModel` mixin provides soft delete via `SoftDeleteManager` ### Source of Truth - Start every doc with: `**Source of Truth:** Codebase at /data/app/igny8/` - Codebase overrides any planning doc --- ## DOC STRUCTURE STANDARD Every doc MUST follow this structure: ``` # [Phase.Sub] — Title **Source of Truth:** Codebase at `/data/app/igny8/` **Version:** 1.0 **Date:** 2026-03-23 ## 1. Current State What exists today relevant to this sub-phase. ## 2. What to Build Complete scope. ## 3. Data Models & APIs New/modified models, endpoints, serializers, database tables. ## 4. Implementation Steps Ordered steps with exact commands, file paths, code snippets. ## 5. Acceptance Criteria Testable checkboxes. ## 6. Claude Code Instructions Specific execution guidance — file creation order, test commands, verification. ``` --- ## EXISTING WORDPRESS PLUGIN CONTEXT The IGNY8 WordPress Bridge Plugin v1.5.2 ALREADY EXISTS. Key facts: - Location: `/data/app/igny8/plugins/wordpress/source/igny8-wp-bridge/` - Current capabilities: Content sync from IGNY8 → WordPress, site data collection, basic REST endpoints - Already has: API key authentication, connection management, content push endpoint - Plugin headers: `IGNY8 WordPress Bridge`, version 1.5.2 - Existing REST namespace: `/wp-json/igny8/v1/` - Authentication: `X-IGNY8-API-KEY` header validation Phase 3 docs describe building the NEXT GENERATION plugin (v2) which is a completely new plugin, not a patch to v1.5.2. The v1.5.2 bridge becomes deprecated once v2 is deployed. --- ## EXISTING IGNY8 BACKEND CONTEXT (relevant to WordPress integration) ### Models that WordPress interacts with: - `Content` (writer app) — content_type: post/page/product/taxonomy; content_structure: article/guide/comparison/review/listicle/landing_page/etc. - `Tasks` (writer app) — writing tasks, status: pending/generating/completed/failed - `Images` (writer app) — generated images for content - `Clusters` (planner app) — keyword clusters, linked to SAGCluster via optional FK - `SAGBlueprint`, `SAGAttribute`, `SAGCluster` (sag app) — Phase 1 models - `SiteIntegration` (integration app) — stores WordPress connection details - `SyncEvent` (integration app) — logs sync operations - `PublishingSettings`, `PublishingRecord` (publishing app) ### Backend endpoints the plugin consumes: - `GET /api/v1/writer/content/?site_id=X&status=approved` — content ready for sync - `GET /api/v1/writer/content/{id}/` — single content with HTML, images, taxonomy data - `GET /api/v1/planner/clusters/?site_id=X` — cluster data - `GET /api/v1/sag/blueprints/?site_id=X` — SAG blueprint (Phase 1) - `POST /api/v1/integration/sync-events/` — log sync results - `POST /api/v1/publishing/records/` — log publishing ### Backend endpoints the plugin exposes (plugin → IGNY8): - `POST /wp-json/igny8/v1/sync/push` — content push from IGNY8 - `POST /wp-json/igny8/v1/sag/sync-blueprint` — SAG blueprint sync - `POST /wp-json/igny8/v1/sag/create-taxonomies` — taxonomy creation - `POST /wp-json/igny8/v1/event` — webhook events ### WordPress Requirements: - Minimum: WordPress 5.9+, PHP 7.4+ - GPL v2+ license - WordPress.org coding standards compliance - All user-facing strings translatable via `igny8` text domain - Sanitize all inputs (`sanitize_text_field`, `wp_kses_post`), escape all outputs (`esc_html`, `esc_attr`, `esc_url`) - Use WP APIs (Settings API, REST API, WP_Query) — no direct DB queries where WP functions exist --- ## DOC 03A: wp-plugin-standalone.md **File:** `V2-Execution-Docs/03A-wp-plugin-standalone.md` **Scope:** 10 standalone modules that work WITHOUT an IGNY8 SaaS subscription — a complete free SEO plugin. **Depends On:** 02D (Linker internal — IGNY8 backend linking logic feeds plugin's linking module), 02G (Rich Schema — IGNY8 schema generation feeds plugin's schema module) ### Source Material: - temp/IGNY8-Project-Files/IGNY8-Plugin-Build-Plan.md - temp/IGNY8-Project-Files/DocC-WordPress-Ecosystem-Dev-Guide.md ### What to Cover: **1. Current State:** - WP Bridge v1.5.2 exists but is sync-only (no standalone SEO features) - No standalone SEO capabilities currently - Users currently rely on Yoast/RankMath alongside IGNY8 **2. What to Build — 10 Standalone Modules:** **Module 1: SEO Core** - Focus keyword per post/page/product (primary + secondary keywords) - SEO title + meta description editor with live SERP preview - Content analysis: keyword density, heading structure, readability score (Flesch-Kincaid) - Title tag templates (per post type, taxonomy, author, date archives) - Breadcrumbs (shortcode `[igny8_breadcrumbs]` + function `igny8()->seo->get_breadcrumbs()`) - Open Graph meta tags (Facebook: og:title, og:description, og:image, og:type) + Twitter Cards (twitter:card, twitter:title, twitter:description, twitter:image) - Robots meta per post (noindex, nofollow, noarchive) - Canonical URL override - Webmaster verification codes (Google, Bing, Yandex, Pinterest) - Frontend head output: consolidate all ``, meta description, OG tags, robots, canonical, schema into single `wp_head` hook at priority 1 Classes: - `IGNY8_SEO_Module` — module bootstrap, hook registration - `IGNY8_Meta_Box` — post editor meta box UI + save handler - `IGNY8_Title_Tag` — `<title>` management, template system via `document_title_parts` filter - `IGNY8_Meta_Tags` — output `<meta>` description, robots, canonical in `<head>` - `IGNY8_Content_Analysis` — real-time SEO scoring in admin JS - `IGNY8_Breadcrumbs` — breadcrumb HTML generation + BreadcrumbList schema - `IGNY8_OpenGraph` — OG + Twitter Card meta tags - `IGNY8_Robots_Txt` — virtual robots.txt manager - `IGNY8_Verification` — webmaster verification code output Hooks: - Actions: `wp_head` (priority 1), `add_meta_boxes`, `save_post`, `document_title_parts` - Filters: `igny8_title_parts`, `igny8_title_separator`, `igny8_meta_description`, `igny8_robots_meta`, `igny8_canonical_url`, `igny8_breadcrumbs`, `igny8_seo_score` Post meta keys (all `_igny8_` prefixed): ``` _igny8_focus_keyword, _igny8_secondary_keywords (JSON array), _igny8_seo_title, _igny8_meta_description, _igny8_canonical_url, _igny8_robots_index, _igny8_robots_follow, _igny8_og_title, _igny8_og_description, _igny8_og_image (attachment ID), _igny8_twitter_title, _igny8_twitter_description, _igny8_seo_score (0-100), _igny8_content_score (0-100), _igny8_readability_score (Flesch-Kincaid), _igny8_last_analysis (timestamp) ``` Term meta keys (all `_igny8_term_` prefixed): ``` _igny8_term_seo_title, _igny8_term_meta_description, _igny8_term_robots_index, _igny8_term_og_image ``` Options keys (all `igny8_` prefixed): ``` igny8_seo_settings (JSON: title templates, separator, defaults) igny8_social_profiles (JSON: {facebook, twitter, linkedin, youtube, instagram, pinterest}) ``` **Module 2: Schema (JSON-LD)** - Auto-detect schema type per post type - Supported types: Article/BlogPosting, Organization/Person, WebPage/CollectionPage, BreadcrumbList, FAQPage, HowTo, LocalBusiness, Service, Product (WooCommerce), WebSite+SearchAction - Custom schema editor (raw JSON-LD) - Schema validation against Google Rich Results requirements - Global settings: Organization vs Person, default types per post type - Single `<script type="application/ld+json">` block in head (merged from all types) Classes: - `IGNY8_Schema_Module`, `IGNY8_Schema_Generator` (main dispatcher) - Type-specific: `IGNY8_Schema_Article`, `IGNY8_Schema_LocalBusiness`, `IGNY8_Schema_Product`, `IGNY8_Schema_FAQ`, `IGNY8_Schema_HowTo`, `IGNY8_Schema_Organization`, `IGNY8_Schema_WebPage`, `IGNY8_Schema_Breadcrumb`, `IGNY8_Schema_Service`, `IGNY8_Schema_Custom` Methods: `get_json_ld($post_id)`, `render_schema($post_id)`, `detect_schema_type($post_id)`, `get_organization_schema()`, `get_breadcrumb_schema($post_id)` Post meta: `_igny8_schema_type`, `_igny8_schema_custom`, `_igny8_schema_faq` (connected), `_igny8_schema_howto` (connected) Options: `igny8_schema_settings` (JSON: org type, name, logo, knowledge graph) Hooks: `igny8_schema_types`, `igny8_schema_{type}`, `igny8_json_ld` **Module 3: Sitemap (XML)** - Sitemap index + sub-sitemaps per post type and taxonomy - Image sitemaps - XSL stylesheet for human-readable view - Respects noindex settings - Auto-ping search engines on update - Exclusion rules (specific posts, taxonomies) Classes: `IGNY8_Sitemap_Module`, `IGNY8_Sitemap_Index`, `IGNY8_Sitemap_Posts`, `IGNY8_Sitemap_Taxonomies`, `IGNY8_Sitemap_Images`, `IGNY8_Sitemap_XSL` Rewrite rules: ``` /sitemap_index.xml → sitemap index /sitemap-{post_type}.xml → post type sitemaps /sitemap-{taxonomy}.xml → taxonomy sitemaps /sitemap-images.xml → image sitemap /sitemap.xsl → XSL stylesheet ``` Options: `igny8_sitemap_settings` (JSON: included post types, taxonomies) Hooks: `igny8_sitemap_post_types`, `igny8_sitemap_taxonomies`, `igny8_sitemap_excluded_urls` **Module 4: Redirects** - CRUD for 301/302/307 redirects - 404 monitoring with hit counts, referrer, user agent (hashed IP for privacy) - Auto-redirect on slug change via `post_updated` hook - CSV import/export - Regex redirect support (advanced) - One-click redirect creation from 404 log Classes: `IGNY8_Redirects_Module`, `IGNY8_Redirect_Manager`, `IGNY8_404_Monitor`, `IGNY8_Auto_Redirect` Methods: `add_redirect($source, $target, $type)`, `log_404($url, $referrer)`, `create_redirect_from_404($url, $target)` Options: `igny8_redirect_settings` (JSON: auto-redirect on slug change) Database tables: ```sql {prefix}igny8_redirects id BIGINT AUTO_INCREMENT PRIMARY KEY source_url VARCHAR(500) NOT NULL target_url VARCHAR(500) NOT NULL type SMALLINT DEFAULT 301 -- 301, 302, 307 hits INT DEFAULT 0 last_hit DATETIME NULL created_at DATETIME NOT NULL is_active TINYINT(1) DEFAULT 1 INDEX idx_source (source_url(191)) {prefix}igny8_404_log id BIGINT AUTO_INCREMENT PRIMARY KEY url VARCHAR(500) NOT NULL referrer VARCHAR(500) NULL user_agent VARCHAR(500) NULL ip_hash VARCHAR(64) NULL -- SHA-256 hash for privacy hits INT DEFAULT 1 first_hit DATETIME NOT NULL last_hit DATETIME NOT NULL is_resolved TINYINT(1) DEFAULT 0 redirect_id BIGINT NULL -- FK to igny8_redirects INDEX idx_url (url(191)) ``` **Module 5: Site Intelligence** - Site audit runner (WP Cron weekly + manual trigger) - Orphan page detection (no internal links pointing to it) - Thin content scanner (configurable word count threshold, default 300) - Empty taxonomy term detection - Duplicate title/meta description finder - Keyword cannibalization detection (multiple pages targeting same keyword) - Auto-cluster detection (topic grouping across posts via keyword similarity) - Dashboard with severity badges (critical/warning/info) and actionable fix suggestions - Connected mode adds: SAG gap analysis, cluster health scoring Classes: `IGNY8_Intelligence_Module`, `IGNY8_Site_Audit`, `IGNY8_Orphan_Detector`, `IGNY8_Thin_Content`, `IGNY8_Empty_Terms`, `IGNY8_Cannibalization`, `IGNY8_Duplicate_Meta`, `IGNY8_Cluster_Detector`, `IGNY8_Gap_Analysis` (connected), `IGNY8_Cluster_Health` (connected) Methods: `run_full_audit()`, `get_audit_results($args)`, `get_orphan_pages()`, `get_thin_content()`, `detect_clusters($posts)` Options: `igny8_intelligence_settings` (JSON: audit schedule, thresholds, exclusions) Database table: ```sql {prefix}igny8_audit_results id BIGINT AUTO_INCREMENT PRIMARY KEY audit_type VARCHAR(50) NOT NULL -- orphan, thin, empty_term, cannibalization, duplicate_meta post_id BIGINT NULL term_id BIGINT NULL severity VARCHAR(20) NOT NULL -- critical, warning, info message TEXT NOT NULL data LONGTEXT NULL -- JSON extra data audit_date DATETIME NOT NULL is_resolved TINYINT(1) DEFAULT 0 INDEX idx_type_date (audit_type, audit_date) ``` **Module 6: Internal Linking** - Full site link crawl + link map stored in `{prefix}igny8_link_map` - Per-post link audit: outbound count, inbound count, orphan status - Link suggestions: "This post should link to X" based on content similarity - Link equity visualization (which pages pass authority) - Orphan content detection (pages with zero inbound internal links) - Connected mode adds: auto-link insertion based on keyword rules from IGNY8 Classes: `IGNY8_Linking_Module`, `IGNY8_Link_Auditor`, `IGNY8_Link_Suggestions`, `IGNY8_Orphan_Links`, `IGNY8_Link_Graph`, `IGNY8_Auto_Linker` (connected), `IGNY8_Link_Rules` (connected) Methods: `crawl_links()`, `get_post_links($post_id)`, `get_link_suggestions($post_id)`, `get_orphan_pages()`, `auto_link_content($post_id)` (connected) Post meta: `_igny8_related_links` (JSON: [{post_id, anchor_text, priority}]), `_igny8_link_suggestions` (JSON) Options: `igny8_linking_settings` (JSON: auto-link rules, max links per post) Database table: ```sql {prefix}igny8_link_map id BIGINT AUTO_INCREMENT PRIMARY KEY source_post_id BIGINT NOT NULL target_post_id BIGINT NOT NULL anchor_text VARCHAR(500) NULL is_follow TINYINT(1) DEFAULT 1 link_position VARCHAR(20) NULL -- content, sidebar, footer last_crawled DATETIME NOT NULL INDEX idx_source (source_post_id) INDEX idx_target (target_post_id) ``` **Module 7: Google Search Console** - OAuth 2.0 connection flow to Google - Search performance dashboard: clicks, impressions, CTR, avg position - Keyword position tracking over time - Date range filtering - Top pages by performance - Data stored locally for historical tracking - Connected mode adds: URL Inspection API, indexing requests, status sync from IGNY8 backend Classes: `IGNY8_GSC_Module`, `IGNY8_GSC_Auth`, `IGNY8_GSC_Dashboard`, `IGNY8_GSC_Keywords`, `IGNY8_GSC_Indexing` (connected), `IGNY8_GSC_URL_Inspection` (connected) Methods: `authorize_gsc()`, `get_search_metrics($args)`, `get_keyword_positions($args)`, `inspect_url($url)` (connected), `request_indexing($url)` (connected) Options: `igny8_gsc_token` (encrypted), `igny8_gsc_property` (selected GSC property URL) **Module 8: Socializer** - Pure CSS/JS share buttons (<5KB total, no external scripts) - Position options: floating sidebar, above content, below content, inline - Networks: Facebook, X/Twitter, LinkedIn, Pinterest, WhatsApp, Telegram, Email, Copy Link - Social profile management (org social URLs) - Share count display (optional, via API) - Connected mode adds: auto-post on publish, Twitter API, Facebook Pages API, LinkedIn API, dynamic OG image generation Classes: `IGNY8_Socializer_Module`, `IGNY8_Share_Buttons`, `IGNY8_Social_Profiles`, `IGNY8_Auto_Poster` (connected), `IGNY8_Twitter_API` (connected), `IGNY8_Facebook_API` (connected), `IGNY8_LinkedIn_API` (connected), `IGNY8_OG_Image_Generator` (connected) Methods: `render_share_buttons($post_id)`, `get_social_profiles()`, `post_to_social($post_id)` (connected) Options: `igny8_share_settings` (JSON: networks, position, style), `igny8_social_profiles` Frontend assets: `share-buttons.css` (<3KB), `share-buttons.js` (<2KB) — conditionally enqueued only when enabled **Module 9: Analytics + SMTP** - GA4 measurement ID connector (script injection via `wp_head`) - Google Tag Manager container ID - Facebook Pixel, TikTok Pixel, Pinterest Tag - Custom header/footer scripts (with placement control) - SMTP mail override (host, port, user, pass, encryption SSL/TLS) - Email delivery log with status tracking - Test email sender Classes: - Analytics: `IGNY8_Analytics_Module`, `IGNY8_GA_Connector`, `IGNY8_GTM_Connector`, `IGNY8_Pixel_Manager`, `IGNY8_Script_Manager` - SMTP: `IGNY8_SMTP_Module`, `IGNY8_SMTP_Mailer`, `IGNY8_Email_Log`, `IGNY8_Email_Test` Options: `igny8_analytics_settings` (JSON: GA ID, GTM ID, pixel IDs, custom scripts), `igny8_smtp_settings` (JSON: host, port, user, pass, encryption, from_name, from_email) Database table: ```sql {prefix}igny8_email_log id BIGINT AUTO_INCREMENT PRIMARY KEY to_email VARCHAR(320) NOT NULL subject VARCHAR(500) NOT NULL status VARCHAR(20) NOT NULL -- sent, failed error_message TEXT NULL sent_at DATETIME NOT NULL ``` SMTP hooks: `wp_mail` (override), `wp_mail_from`, `wp_mail_from_name` **Module 10: Import (Migration)** - One-click import from: Yoast SEO, RankMath, All in One SEO - Imports: focus keywords, SEO titles, meta descriptions, robots settings, redirects, schema settings - Pre-import preview showing what will be migrated (dry run mode) - Rollback capability (stores original values before overwrite) Classes: `IGNY8_Importer` (base), `IGNY8_Yoast_Importer`, `IGNY8_RankMath_Importer`, `IGNY8_AIOSEO_Importer` Meta key mapping (Yoast → IGNY8): ``` _yoast_wpseo_focuskw → _igny8_focus_keyword _yoast_wpseo_title → _igny8_seo_title _yoast_wpseo_metadesc → _igny8_meta_description _yoast_wpseo_canonical → _igny8_canonical_url _yoast_wpseo_meta-robots-noindex → _igny8_robots_index _yoast_wpseo_opengraph-title → _igny8_og_title _yoast_wpseo_opengraph-description → _igny8_og_description ``` Similar mappings for RankMath (`rank_math_*`) and AIOSEO (`_aioseo_*`). **3. Data Models & APIs (WordPress side):** 6 custom database tables total (listed above under each module): 1. `{prefix}igny8_redirects` 2. `{prefix}igny8_404_log` 3. `{prefix}igny8_link_map` 4. `{prefix}igny8_audit_results` 5. `{prefix}igny8_email_log` 6. `{prefix}igny8_sync_queue` (table created in standalone for connected mode readiness) REST API endpoints (public, for theme + external consumers): - `GET /wp-json/igny8/v1/related/{post_id}` — related content links - `GET /wp-json/igny8/v1/cluster/{cluster_id}` — cluster content list - `GET /wp-json/igny8/v1/term/{term_id}/content` — rich term content - `GET /wp-json/igny8/v1/audit/summary` — site audit results - `GET /wp-json/igny8/v1/structure/overview` — site structure summary **4. Architecture:** ``` igny8/ ├── igny8.php # Plugin header, bootstrap, constants ├── readme.txt # WordPress.org readme ├── uninstall.php # Full cleanup on uninstall ├── includes/ │ ├── class-igny8.php # Main singleton class │ ├── class-module-manager.php # Register/activate/deactivate modules │ ├── class-api-client.php # IGNY8 SaaS API client (connected mode) │ ├── class-connection.php # API key validation, connection status │ ├── class-utils.php # Shared utilities │ ├── class-rest-api.php # Plugin REST endpoints │ ├── class-compatibility.php # Detect Yoast/RankMath conflicts │ ├── modules/ │ │ ├── seo/ # Module 1 (9 class files) │ │ ├── schema/ # Module 2 (12 class files) │ │ ├── sitemap/ # Module 3 (6 class files) │ │ ├── redirects/ # Module 4 (4 class files) │ │ ├── site-intelligence/ # Module 5 (10 class files) │ │ ├── linking/ # Module 6 (7 class files) │ │ ├── gsc/ # Module 7 (6 class files) │ │ ├── socializer/ # Module 8 (8 class files) │ │ ├── analytics/ # Module 9a (5 class files) │ │ ├── smtp/ # Module 9b (4 class files) │ │ ├── content-sync/ # Module 11 [CONNECTED] (6 class files) │ │ └── sag/ # Module 12 [CONNECTED] (6 class files) │ ├── admin/ │ │ ├── class-admin-menu.php │ │ ├── class-dashboard.php │ │ ├── class-setup-wizard.php │ │ ├── class-compatibility-notice.php │ │ ├── views/ (wizard steps, dashboard, connect prompt) │ │ └── assets/ (admin.css, admin.js, meta-box.css, meta-box.js) │ ├── frontend/ │ │ ├── class-head-output.php # All <head> tag consolidation │ │ ├── class-share-output.php # Share button rendering │ │ └── assets/ (share-buttons.css, share-buttons.js) │ ├── data/ │ │ ├── class-installer.php # Create all DB tables on activation │ │ ├── class-migrator.php # Version-based migration handler │ │ └── class-importer.php # SEO data importer │ └── integrations/ │ ├── class-woocommerce.php # WooCommerce SEO + schema │ └── class-theme-bridge.php # Communication with companion theme └── languages/ └── igny8.pot # Translation template ``` Module Manager pattern: - Each module: `register()`, `activate()`, `deactivate()`, `is_active()`, `boot()` - Public API: `igny8()` returns singleton, `igny8()->seo->get_title()`, `igny8()->schema->get_json_ld()`, etc. - All modules toggleable from Settings → Modules Admin menu structure: ``` IGNY8 (top-level, dashicons-chart-area) ├── Dashboard (overview + quick actions) ├── SEO (meta box settings, title templates) ├── Schema (default types, organization settings) ├── Sitemaps (post type/taxonomy inclusion) ├── Redirects (CRUD + 404 monitor) ├── Site Intelligence (audit dashboard) ├── Internal Links (link map, suggestions) ├── Search Console (GSC dashboard) ├── Socializer (buttons, profiles) ├── Analytics (GA4, GTM, pixels) ├── SMTP (mail settings, log) ├── Import (migration wizard) └── Settings (modules toggle, general settings) ``` Setup Wizard (6 steps, runs on first activation): 1. Site Type — Blog, Business, eCommerce, Local Business, SaaS, Portfolio 2. SEO Import — Detect existing Yoast/RankMath/AIOSEO, offer import 3. Site Basics — Site name, Organization/Person, logo, title separator 4. Social Profiles — Social URLs + default sharing image 5. Connect to IGNY8 — API key (optional, clear skip button) 6. Done — Summary, run first audit CTA **5. Performance Rules:** | Rule | Implementation | |------|---------------| | Zero CSS on frontend unless share buttons enabled | Conditional enqueue check | | Zero JS on frontend unless interactive features | Conditional enqueue check | | All `<head>` output in single hook at priority 1 | `class-head-output.php` consolidation | | Schema as single JSON-LD block | `class-schema-generator.php` merges all types | | Admin assets only on IGNY8 admin pages | `get_current_screen()` check | | Meta box assets only on post editor | Screen check before enqueue | | Site audit via WP Cron, never on page load | `wp_schedule_event()` weekly | | Link crawl as background process | WP Cron, batch processing | | Connected API calls never block page requests | WP Cron queue, async | | Option reads via object cache | `wp_cache_get/set` wrapping | **6. WordPress.org Compliance:** - GPL v2+ license - No phone-home without explicit user consent - All user-facing strings translatable via `igny8` text domain - Sanitize all inputs, escape all outputs - Use WP APIs everywhere (Settings API, REST API, WP_Query) - No direct database queries where WP functions exist - Min requirements: WordPress 5.9+, PHP 7.4+ **7. Build Sequence (10 phases):** - Phase 1 (Days 1-3): Foundation — skeleton, module manager, admin menu, setup wizard, DB tables, REST API base - Phase 2 (Days 4-7): SEO Core — meta box, title tags, content analysis, OG, breadcrumbs, robots - Phase 3 (Days 8-10): Schema + Sitemap + Redirects - Phase 4 (Days 11-13): Site Intelligence (all audit types + dashboard) - Phase 5 (Days 14-15): Internal Linking (crawl + map + suggestions) - Phase 6 (Days 16-18): Socializer + Analytics/SMTP + GSC - Phase 7 (Days 19-20): Import (Yoast, RankMath, AIOSEO) - Phase 8-9: Reserved for connected mode (doc 03B) - Phase 10 (Days 28-30): WordPress.org compliance, readme, screenshots, i18n **Cross-references:** 02D (Linker internal — IGNY8 backend linking logic feeds plugin's linking module), 02G (Rich Schema — IGNY8 schema generation feeds plugin's schema module), 03B (connected mode extends this), 03C (theme consumes plugin API) --- ## DOC 03B: wp-plugin-connected.md **File:** `V2-Execution-Docs/03B-wp-plugin-connected.md` **Scope:** 2 connected-mode modules that require an IGNY8 SaaS subscription. These extend the standalone plugin from 03A. **Depends On:** 03A (standalone base required) + 01G (SAG health monitoring — blueprint data) ### Source Material: - temp/IGNY8-Project-Files/IGNY8-Plugin-Build-Plan.md - temp/IGNY8-Project-Files/DocC-WordPress-Ecosystem-Dev-Guide.md ### What to Cover: **1. Current State:** - WP Bridge v1.5.2 already does basic content sync - v2 connected mode replaces and extends v1.5.2 capabilities - Requires standalone plugin (03A) installed and active **2. What to Build — 2 Connected Modules:** **Module 11: Content Sync** Content push from IGNY8 → WordPress with queue + review workflow. Content Type Mapping: | IGNY8 content_type | WP post_type | Notes | |---|---|---| | post | post | Default blog post | | page | page | Standard page | | product | product | Requires WooCommerce | | service | service | Requires theme CPT | | company_page | page | page-company template | | taxonomy_landing | — | Written to term description (not a post) | | cluster_hub | page | Landing page preset applied | | comparison | post | Standard post with comparison structure | | brand_page | page | Standard page | Classes: - `IGNY8_Sync_Module` — module entry, webhook receiver - `IGNY8_Content_Puller` — fetch content from IGNY8 SaaS API - `IGNY8_Content_Mapper` — map IGNY8 content_type → WP post_type - `IGNY8_Image_Downloader` — download AI images → `wp_upload_dir()`, `wp_insert_attachment()` - `IGNY8_Sync_Queue` — sync queue DB table management - `IGNY8_Publish_Scheduler` — review queue, scheduled publishing workflow Methods: `push_content_to_queue($data)`, `process_sync_queue()`, `map_content_type($igny8_type)`, `create_post_from_content($data)`, `download_images($content)`, `schedule_publish($post_id, $date)`, `get_review_queue()` Content Sync Flow: ``` IGNY8 SaaS publishes content → POST /wp-json/igny8/v1/sync/push {igny8_content_id, content_type, title, content_html, excerpt, featured_image, meta: {focus_keyword, secondary_keywords, cluster_id, taxonomies: {service_category: [...], cluster: [...]}}} → Plugin creates igny8_sync_queue entry (status: pending) → WP Cron processes queue: 1. Download images → wp_upload_dir(), wp_insert_attachment() 2. Map content_type → WP post_type 3. wp_insert_post() or wp_update_post() 4. Set post meta (_igny8_content_id, _igny8_cluster_id, _igny8_sync_status) 5. wp_set_object_terms() for taxonomy assignment 6. Status: 'review' (manual mode) or 'synced' (auto-publish mode) → Plugin POSTs confirmation to IGNY8 /api/v1/integration/sync-events/ ``` Database table: ```sql {prefix}igny8_sync_queue id BIGINT AUTO_INCREMENT PRIMARY KEY igny8_content_id VARCHAR(100) NOT NULL content_type VARCHAR(50) NOT NULL sync_status VARCHAR(20) NOT NULL -- pending, synced, failed, review wp_post_id BIGINT NULL wp_term_id BIGINT NULL data LONGTEXT NULL -- JSON payload from IGNY8 created_at DATETIME NOT NULL synced_at DATETIME NULL error_message TEXT NULL INDEX idx_status (sync_status) ``` Post meta (connected mode): ``` _igny8_content_id -- int, links WP post to IGNY8 Content record _igny8_cluster_id -- int, links WP post to IGNY8 SAGCluster _igny8_sync_status -- pending/synced/failed/modified _igny8_last_sync -- timestamp _igny8_related_links -- JSON: [{post_id, anchor_text, priority}] _igny8_link_suggestions -- JSON: AI-generated link suggestions ``` Hooks: - Actions: `wp_scheduled_event` (igny8_process_sync_queue), `rest_api_init` - Filters: `igny8_content_before_sync`, `igny8_post_mapped`, `igny8_sync_status_updated` **Module 12: SAG Structure (Blueprint Sync)** Receive SAG blueprint → create taxonomies → create terms → map clusters → visualize. Classes: - `IGNY8_SAG_Module` — module entry - `IGNY8_Blueprint_Sync` — receive + cache SAG blueprint from IGNY8 - `IGNY8_Taxonomy_Builder` — `register_taxonomy()` from SAG attributes - `IGNY8_Term_Builder` — `wp_insert_term()` from attribute values with hierarchy - `IGNY8_Cluster_Manager` — map clusters → hub pages/terms - `IGNY8_Structure_Visualizer` — visual site structure admin page Methods: `sync_blueprint($json)`, `create_taxonomies_from_blueprint($bp)`, `create_terms_from_blueprint($bp)`, `map_cluster_to_page($cluster_id, $page_id)`, `get_blueprint()`, `get_structure_overview()` SAG Blueprint Sync Flow: ``` IGNY8 confirms blueprint → POST /wp-json/igny8/v1/sag/sync-blueprint {blueprint: {dimensions: [{id, name, slug, attributes: [{id, name, slug}]}], clusters: [{id, name, dimension_ids, hub_page_id, recommended_content_count}]}} → Plugin stores in option igny8_sag_blueprint → Admin sees "Blueprint Review" notice → User clicks "Approve Blueprint": 1. Loop dimensions → register_taxonomy() if not exists 2. Loop attribute values → wp_insert_term() with parent hierarchy 3. Set term meta (_igny8_term_sag_attribute, _igny8_term_sag_level) 4. Loop clusters → create/link hub pages → POST confirmation back with {term_ids_map, hub_page_ids_map} ``` Term meta (connected mode, all `_igny8_term_` prefixed): ``` _igny8_term_content -- rich HTML content for term landing page _igny8_term_faq -- JSON: [{question, answer}] _igny8_term_related_terms -- JSON: [term_id, term_id, ...] _igny8_term_sag_attribute -- attribute name from SAG _igny8_term_sag_level -- primary/secondary/tertiary _igny8_term_cluster_id -- linked SAGCluster ID (int) _igny8_term_igny8_id -- ID in IGNY8 platform (int) _igny8_term_seo_title -- SEO title for term archive _igny8_term_meta_description -- meta description for term archive _igny8_term_robots_index -- index/noindex _igny8_term_og_image -- OG image attachment ID ``` Options (connected mode): ``` igny8_api_key -- API key for IGNY8 SaaS (encrypted) igny8_api_connected -- boolean igny8_api_url -- base URL (default: https://api.igny8.com/api/v1/) igny8_site_id -- IGNY8 Site record ID (int) igny8_last_sync -- timestamp igny8_sag_blueprint -- JSON: full blueprint data ``` REST endpoints (inbound from IGNY8, all validate `X-IGNY8-API-KEY`): ``` POST /wp-json/igny8/v1/sync/push -- content push POST /wp-json/igny8/v1/sag/sync-blueprint -- blueprint sync POST /wp-json/igny8/v1/sag/create-taxonomies -- taxonomy creation POST /wp-json/igny8/v1/terms/{id}/content -- term content push POST /wp-json/igny8/v1/schema/bulk-update -- schema JSON-LD bulk push POST /wp-json/igny8/v1/gsc/status-sync -- GSC index statuses POST /wp-json/igny8/v1/event -- webhook events ``` Endpoint payloads (documented with full request/response JSON): `POST /sync/push` request: ```json { "igny8_content_id": 12345, "content_type": "post", "title": "Content Title", "content": "<p>HTML content...</p>", "excerpt": "Short excerpt", "featured_image": "https://cdn.igny8.com/image.jpg", "meta": { "focus_keyword": "main keyword", "secondary_keywords": ["kw2", "kw3"], "cluster_id": 123, "taxonomies": {"service_category": ["emergency-plumbing"], "cluster": ["drain-services"]} } } ``` `POST /sag/sync-blueprint` request: ```json { "blueprint": { "dimensions": [ {"id": 1, "name": "Service Type", "slug": "service_type", "attributes": [{"id": 1, "name": "Emergency Plumbing", "slug": "emergency-plumbing"}]} ], "clusters": [ {"id": 1, "name": "Emergency Drain Cleaning", "dimension_ids": [1, 2], "hub_page_id": null, "recommended_content_count": 12} ] } } ``` `POST /terms/{id}/content` request: ```json { "term_id": 1001, "content": "<p>HTML content for term landing page</p>", "faq": [{"question": "Q1?", "answer": "A1"}], "related_terms": [1002, 1003], "meta": {"seo_title": "Custom title", "meta_description": "Custom description"} } ``` `POST /schema/bulk-update` request: ```json { "schemas": [ {"post_id": 123, "schema_type": "Article", "schema_data": {"@context": "https://schema.org", ...}} ] } ``` `POST /gsc/status-sync` request: ```json { "statuses": [ {"url": "https://example.com/post", "index_status": "Indexed", "coverage_state": "Submitted and indexed", "last_checked": "2026-03-22T12:00:00Z"} ] } ``` **3. API Client (class-api-client.php):** - Handles all outbound requests to IGNY8 SaaS API - Base URL from `igny8_api_url` option (default: `https://api.igny8.com/api/v1/`) - Authentication: `Authorization: Bearer {igny8_api_key}` - Methods: `get($endpoint, $params)`, `post($endpoint, $data)`, `put($endpoint, $data)`, `delete($endpoint)` - Error handling: WP_Error wrapping, log failures - Rate limiting: respect 429 responses with exponential backoff (1s → 2s → 4s → 8s) - Connection test: `GET /api/v1/system/status/` **4. Admin UI additions (connected mode):** ``` IGNY8 (top-level) ├── ... (all standalone modules from 03A) ├── Content Sync (sync queue, review queue, settings, sync log) └── SAG Structure (blueprint review, cluster manager, structure visualizer) ``` **Cross-references:** 03A (standalone base required), 01G (SAG health monitoring — blueprint data), 01A (SAG models — data source), 01D (setup wizard — blueprint generation triggers sync), 02B (taxonomy term content — generates content pushed via /terms/{id}/content) --- ## DOC 03C: companion-theme.md **File:** `V2-Execution-Docs/03C-companion-theme.md` **Scope:** Full Site Editing (FSE) block theme optimized for IGNY8 + SAG architecture. 7 CPTs, 9 taxonomies, term landing page templates, cluster hub templates, 15 landing page section types, 50+ block patterns, 5 site-type starters, 6 interlinking display components. **Depends On:** 03B (connected mode: term meta, blueprint data) ### Source Material: - temp/IGNY8-Project-Files/Theme-Build-Plan.md - temp/IGNY8-Project-Files/DocC-WordPress-Ecosystem-Dev-Guide.md ### What to Cover: **1. Current State:** - No IGNY8 companion theme exists - Users use generic themes (Astra, GeneratePress, etc.) - Plugin provides data (SEO, schema, links) but can't control template rendering **2. What to Build:** **7 Custom Post Types:** **CPT 1: `service`** - Archive enabled, supports: title, editor, thumbnail, excerpt, revisions, page-attributes - Taxonomies: service_category, service_area, service_attribute, cluster - Rewrite: `/services/%service_category%/%postname%/` - Templates: `single-service.html`, `archive-service.html` - 10 meta fields: ``` _theme_service_price_range -- "$150 - $500" _theme_service_duration -- "2-4 hours" _theme_service_process_steps -- JSON: [{step_number, title, desc, icon}] _theme_service_outcomes -- JSON: [{title, description}] _theme_service_faqs -- JSON: [{question, answer}] _theme_service_cta_text -- button text _theme_service_cta_url -- button URL _theme_service_areas_served -- JSON: geographic areas _theme_service_gallery -- JSON: attachment IDs _theme_service_related_services -- JSON: post IDs ``` **CPT 2: `landing_page`** - NO archive, does NOT support editor (section meta box instead) - Rewrite: `/l/%postname%/` - Template: `single-landing_page.html` - Section-based rendering from `_theme_landing_sections` repeater meta - 15 section types + 8 presets (detailed below) **CPT 3: `portfolio`** - Archive enabled, supports: title, editor, thumbnail, excerpt, revisions - Taxonomies: portfolio_category, portfolio_tag, service_category (shared) - Rewrite: `/portfolio/%portfolio_category%/%postname%/` - Templates: `single-portfolio.html`, `archive-portfolio.html` - 8 meta fields: ``` _theme_portfolio_client -- client name _theme_portfolio_date -- YYYY-MM-DD _theme_portfolio_url -- live project URL _theme_portfolio_results -- JSON: [{metric, value, description}] _theme_portfolio_technologies -- comma-separated _theme_portfolio_testimonial_id -- linked testimonial post ID _theme_portfolio_gallery -- JSON: attachment IDs _theme_portfolio_before_after -- JSON: {before_img, after_img} ``` **CPT 4: `team_member`** - Archive enabled (team page), supports: title, editor, thumbnail - Rewrite: `/team/%postname%/` - Templates: `single-team-member.html`, `archive-team-member.html` - 6 meta fields: ``` _theme_team_position, _theme_team_email, _theme_team_phone, _theme_team_social (JSON: {linkedin, twitter, facebook, website}), _theme_team_order (int), _theme_team_department ``` **CPT 5: `testimonial`** - Public: false (displayed via blocks/shortcodes only, no individual pages) - Supports: title, editor, thumbnail - 8 meta fields: ``` _theme_testimonial_author_name, _theme_testimonial_author_title, _theme_testimonial_company, _theme_testimonial_rating (1-5 int), _theme_testimonial_image (attachment ID), _theme_testimonial_featured (bool), _theme_testimonial_service_id (linked service), _theme_testimonial_product_id ``` **CPT 6: `faq`** - Archive enabled, supports: title, editor (title=question, editor=answer) - Taxonomies: faq_category, cluster - Rewrite: `/faq/%faq_category%/%postname%/` - Templates: `single-faq.html`, `archive-faq.html` - 2 meta fields: `_theme_faq_order` (int), `_theme_faq_schema_enabled` (bool) **CPT 7: `documentation`** - Archive enabled, hierarchical (parent/child docs) - Supports: title, editor, thumbnail, page-attributes - Taxonomies: doc_category - Rewrite: `/docs/%doc_category%/%postname%/` - Templates: `single-documentation.html`, `archive-documentation.html` - 4 meta fields: ``` _theme_doc_sidebar_enabled (bool), _theme_doc_toc_enabled (bool), _theme_doc_last_reviewed (date), _theme_doc_related_docs (JSON: post IDs) ``` Note: WooCommerce taxonomies (product_cat, product_tag, pa_*) are NOT registered by theme. Theme provides rich templates for them. Theme registers `cluster` for `product` post type. **9 Custom Taxonomies:** | # | Slug | For CPTs | Hierarchical | SAG Mapping | Rewrite | |---|------|----------|-------------|-------------|---------| | 1 | `service_category` | service, portfolio | yes | Primary attribute | `/services/%postname%/` | | 2 | `service_area` | service | yes | Tertiary (geographic) | `/area/%postname%/` | | 3 | `service_attribute` | service | no | Secondary attributes | `/attribute/%postname%/` | | 4 | `portfolio_category` | portfolio | yes | — | `/portfolio/%postname%/` | | 5 | `portfolio_tag` | portfolio | no | — | `/tag/%postname%/` | | 6 | `faq_category` | faq | yes | Cluster assignment | `/faq/%postname%/` | | 7 | `doc_category` | documentation | yes | — | `/docs/%postname%/` | | 8 | `cluster` | post, page, service, faq, product | no | Core cluster assignment | `/topic/%postname%/` | | 9 | `topic_tag` | post, service, faq, documentation | no | Granular tagging | `/topic/%postname%/` | **Term Landing Page Templates (7-section structure):** Every taxonomy term archive renders as a rich landing page: 1. **Term Hero** — H1 (term name), description (from `_igny8_term_content` if active), breadcrumbs, post count 2. **Key Subtopics** — grid of child term cards (if hierarchical + children exist) 3. **Content Grid** — posts/services/products in term, filterable, paginated, layout options (grid 2/3/4 col, list) 4. **Related Terms** — sibling terms or `_igny8_term_related_terms` 5. **Cluster Cross-Links** — related clusters sharing dimensional axes (if IGNY8 connected) 6. **FAQ Section** — accordion from `_igny8_term_faq` or matching faq_category posts 7. **CTA** — configurable per term or global default **Cluster Hub Template (`taxonomy-cluster.html`):** 1. Cluster hero (H1, description, dimensional breadcrumb, content count) 2. Hub content (pillar article from `_igny8_term_content`) 3. Supporting content grid (posts/services/products grouped by type) 4. Attribute navigation (browse intersecting attributes) 5. Related clusters (cross-linking via SAG data) 6. FAQ (cluster-specific) 7. CTA **6 Interlinking Display Components (template parts):** 1. `parts/related-content.html` — after post content, reads `_igny8_related_links`, fallback to category match, 3-4 cards 2. `parts/cluster-navigation.html` — reads `igny8()->linking->get_cluster_navigation()`, fallback to same cluster term 3. `parts/attribute-browse.html` — term archive sidebar, pills/tags of browsable attribute values 4. `parts/breadcrumbs.html` — reads `igny8()->seo->get_breadcrumbs()` or theme fallback, SAG-aware dimensional path 5. `parts/term-quick-links.html` — single post sidebar/footer, all terms assigned to post grouped by taxonomy 6. `parts/child-term-grid.html` — term archive, card grid with term image/name/description/post count **Landing Page System (15 section types):** 1. `hero` — headline, subheadline, CTA, background image/video/gradient 2. `features-grid` — columns 2/3/4, items: icon/title/description 3. `how-it-works` — numbered steps: title/description/icon 4. `social-proof` — testimonials: grid/slider/single layout 5. `pricing` — billing toggle monthly/annual, plans: features/price/CTA 6. `faq` — Q&A items, schema_enabled option for FAQPage JSON-LD 7. `cta-band` — headline, subheadline, CTA, background colors 8. `content-block` — title, WYSIWYG editor, image left/right, background 9. `stats-counter` — stats: number/suffix/label, animated counters 10. `team` — from team_member CPT or manual entries 11. `portfolio-grid` — from portfolio CPT 12. `contact-form` — form shortcode, optional map, address block 13. `video-embed` — URL, poster image, autoplay, full-width options 14. `comparison-table` — columns, rows, highlight column option 15. `logo-bar` — logo images, grid or horizontal scroll Section template files in `inc/landing-pages/sections/`: one `.php` per section type. **8 Landing Page Presets:** 1. SaaS Product: hero → logo-bar → features → how-it-works → social-proof → pricing → faq → cta 2. Service Business: hero → features → content → stats → social-proof → team → contact-form → cta 3. Product Launch: hero → content → features → video → social-proof → pricing → faq → cta 4. Lead Generation: hero → features → social-proof → cta 5. Portfolio/Agency: hero → portfolio → how-it-works → social-proof → stats → contact-form 6. Event/Webinar: hero → content → features → social-proof → faq → cta 7. Cluster Hub: hero → content → features → faq → cta 8. Term Landing: hero → content → features → social-proof → faq → cta **50+ Block Patterns (by category):** - Heroes (4): hero-centered, hero-split, hero-video-bg, hero-slider - Content (4): features-3col, features-alternating, how-it-works, benefits-icons - Social Proof (4): testimonials-grid, testimonials-slider, logo-bar, stats-row - Conversion (4): cta-simple, cta-with-form, pricing-section, newsletter-signup - Services (3): service-cards, service-list, service-with-sidebar - Portfolio (3): portfolio-grid, portfolio-masonry, case-study-layout - Footers (3): footer-4col, footer-centered, footer-minimal - 13+ custom block patterns: pricing-table, feature-grid, testimonial-slider, stats-counter, team-grid, faq-accordion, cta-banner, logo-carousel, comparison-table, icon-box, service-grid, portfolio-showcase, doc-sidebar **13 Custom Gutenberg Blocks (in `inc/blocks/`):** 1. pricing-table, 2. feature-grid, 3. testimonial-slider, 4. stats-counter, 5. team-grid, 6. faq-accordion, 7. cta-banner, 8. logo-carousel, 9. comparison-table, 10. icon-box, 11. service-grid (CPT-powered), 12. portfolio-showcase (CPT-powered), 13. doc-sidebar (documentation nav) **5 Site-Type Starter Templates (with demo content):** 1. **Blog** — front-page, single.html, archive.html 2. **SaaS** — front-page, page-features.html, page-pricing.html, page-docs.html 3. **Corporate** — front-page, page-about.html, page-services.html, page-contact.html 4. **eCommerce** — front-page, archive-product.html, single-product.html 5. **Portfolio** — front-page, archive-portfolio.html, single-portfolio.html Each includes full template files, sample CPT entries, sample taxonomy terms, demo images. **3. Theme Architecture:** FSE block theme structure: ``` igny8-theme/ ├── style.css, theme.json, functions.php ├── assets/ (css/, js/, fonts/, images/) ├── inc/ │ ├── setup.php -- theme supports, menus, sidebars, image sizes │ ├── cleanup.php -- remove WP bloat (emojis, embeds, etc.) │ ├── enqueue.php -- conditional CSS/JS loading │ ├── template-tags.php -- custom template tags │ ├── breadcrumbs.php -- theme breadcrumb fallback (when plugin not active) │ ├── walkers.php -- custom nav walkers │ ├── customizer.php -- logo, colors, fonts, layout, social URLs, footer text │ ├── theme-bridge.php -- communication layer with IGNY8 plugin │ ├── cpt/ -- register.php + 7 per-CPT files │ ├── taxonomies/ -- register.php + 9 per-taxonomy files │ ├── meta-fields/ -- class-meta-box-base.php + per-CPT meta handlers │ ├── landing-pages/ -- register-cpt.php, meta-boxes.php, presets.php, render.php, sections/ │ ├── interlinking/ -- 6 component files (related-content, cluster-nav, etc.) │ ├── blocks/ -- 13 custom block registrations │ └── patterns/ -- register.php + category folders ├── templates/ -- FSE templates (20+ template files) │ ├── index.html, home.html, single.html, page.html, archive.html │ ├── single-service.html, single-portfolio.html, single-landing_page.html, single-documentation.html │ ├── archive-service.html, archive-portfolio.html, archive-faq.html, archive-documentation.html │ ├── taxonomy-service_category.html, taxonomy-service_area.html, taxonomy-service_attribute.html │ ├── taxonomy-cluster.html, taxonomy-faq_category.html │ ├── taxonomy-product_cat.html, taxonomy-product_tag.html (WooCommerce) │ ├── search.html, 404.html │ └── starters/ (5 starter template sets) ├── parts/ -- FSE template parts (20+ parts) │ ├── header.html, header-transparent.html, header-minimal.html │ ├── footer.html, footer-minimal.html │ ├── sidebar.html, sidebar-docs.html │ ├── post-meta.html, author-box.html, comments.html, pagination.html │ ├── related-content.html, cluster-navigation.html, attribute-browse.html │ ├── breadcrumbs.html, term-quick-links.html, child-term-grid.html │ ├── term-hero.html, term-content.html, term-faq.html │ └── (additional parts) └── woocommerce/ -- WooCommerce template overrides ├── archive-product.php, single-product.php ├── taxonomy-product_cat.php ├── content-product.php ├── cart/, checkout/, myaccount/ overrides ``` **Design System (theme.json):** - Colors: Primary palette (primary, primary-light, primary-dark, primary-accent), Neutral (background, surface, text, text-secondary, border), Semantic (success, warning, error, info) - Typography: Heading + body font pairings from curated list, sizes: xs, sm, base, lg, xl, 2xl, 3xl, 4xl - Spacing scale: xs (0.25rem), sm (0.5rem), base (1rem), lg (1.5rem), xl (2rem), 2xl (3rem), 3xl (4rem) - Border radius: none, sm, base, lg, full - Custom tokens for term pages and interlinking components - CSS approach: BEM naming `.tn-block__element--modifier`, <35KB gzipped total - JS: ES6+, vanilla (no jQuery on frontend), <15KB gzipped Performance targets: FCP <1.0s, LCP <1.5s, TBT <50ms, CLS <0.05, PageSpeed Insights 95+ mobile **4. Plugin Integration (graceful degradation):** - Theme checks `function_exists('igny8')` before calling any plugin API - Without plugin: theme breadcrumbs, basic related content by category, no SAG features - With plugin standalone: SEO breadcrumbs, schema, link suggestions, share buttons - With plugin connected: full SAG term pages, cluster navigation, blueprint visualization, rich term content **5. WooCommerce Integration (when active):** - Product cluster taxonomy support (register `cluster` for `product` post type) - Rich category pages following term landing structure - Product attribute support in templates - Integration with IGNY8 schema (Product schema type) - Template overrides: archive-product, single-product, taxonomy-product_cat, content-product **Cross-references:** 03A (plugin API: `igny8()` singleton), 03B (connected mode: term meta, blueprint data), 01A (SAGCluster → cluster taxonomy), 01B (SAGAttribute → service_category/service_attribute/service_area mapping) --- ## DOC 03D: toolkit-plugin.md **File:** `V2-Execution-Docs/03D-toolkit-plugin.md` **Scope:** Separate utility plugin with 5 infrastructure modules. Independent from main IGNY8 plugin but complements the companion theme. **Depends On:** 03C (companion theme is the primary consumer) ### Source Material: - temp/IGNY8-Project-Files/IGNY8-Plugin-Build-Plan.md (Toolkit section) - temp/IGNY8-Project-Files/DocC-WordPress-Ecosystem-Dev-Guide.md ### What to Cover: **1. Current State:** - No toolkit plugin exists - Users rely on multiple plugins: WP Super Cache, Contact Form 7, Wordfence, WP Mail SMTP, etc. - Goal: reduce plugin count with a single, lightweight toolkit **2. What to Build — 5 Modules:** **Module 1: Performance** - Page cache (file-based, auto-purge on post update via `save_post` hook) - HTML minification (remove whitespace, comments) - Asset optimizer (combine/minify CSS+JS with exclusion rules) - Image optimizer (WebP conversion via GD/Imagick, lazy loading, responsive srcset) - Critical CSS generation (extract above-fold CSS) - Browser cache headers (expires, cache-control via `.htaccess` or `send_headers`) - Preload/prefetch for key resources (`<link rel="preload">`) - Gzip compression check - Database optimizer (clean transients, revisions, spam comments) Classes: `Toolkit_Performance_Module`, `Toolkit_Page_Cache`, `Toolkit_Asset_Optimizer`, `Toolkit_Image_Optimizer`, `Toolkit_Critical_CSS`, `Toolkit_HTML_Minifier`, `Toolkit_Browser_Cache`, `Toolkit_Preload`, `Toolkit_Database_Optimizer` Free: page cache (basic), HTML minification Premium: full asset optimizer, image optimization + WebP, critical CSS, browser cache, preload, DB optimizer Database table: ```sql {prefix}igny8_toolkit_cache_stats id BIGINT AUTO_INCREMENT PRIMARY KEY hits INT DEFAULT 0 misses INT DEFAULT 0 purges INT DEFAULT 0 last_purge DATETIME NULL ``` **Module 2: Forms** - Drag-and-drop form builder (admin only, not Gutenberg block — simpler) - Field types: text, email, textarea, select, checkbox, radio, file upload, hidden, number, date - Submissions handler: store in DB + email notification - Anti-spam: honeypot field + basic token validation (no external service) - Entries admin page: view, export CSV, delete - Conditional logic (premium): show/hide fields based on other field values - Multi-step forms (premium) - Shortcode `[igny8_form id="X"]` + block for embedding Classes: `Toolkit_Forms_Module`, `Toolkit_Form_Builder`, `Toolkit_Form_Renderer`, `Toolkit_Form_Processor`, `Toolkit_Form_Notifications`, `Toolkit_Form_Entries`, `Toolkit_Form_AntiSpam` Free: basic builder (5 field types: text, email, textarea, select, checkbox), simple rendering Premium: all field types, conditional logic, multi-step, submissions dashboard Database table: ```sql {prefix}igny8_toolkit_submissions id BIGINT AUTO_INCREMENT PRIMARY KEY form_id INT NOT NULL data LONGTEXT NOT NULL -- JSON form field values ip_hash VARCHAR(64) NULL user_agent VARCHAR(500) NULL created_at DATETIME NOT NULL INDEX idx_form (form_id) ``` **Module 3: Security** - Login protection: limit login attempts (default 5), lockout duration (default 15min), whitelist IPs - Basic firewall: block known bad user agents, block PHP execution in uploads dir - WordPress hardening: disable XML-RPC, disable file editor (`DISALLOW_FILE_EDIT`), hide WP version, security headers (X-Frame-Options, X-Content-Type-Options, Referrer-Policy, Permissions-Policy) - Audit log: track login attempts, settings changes, plugin activations, user role changes - 2FA via email code (premium) - IP allowlist/blocklist (premium) Classes: `Toolkit_Security_Module`, `Toolkit_Login_Protection`, `Toolkit_Firewall`, `Toolkit_Hardening`, `Toolkit_Headers`, `Toolkit_Audit_Log` Free: basic login protection, file editor disable, security headers Premium: advanced firewall, 2FA, full audit logging, IP management Database table: ```sql {prefix}igny8_toolkit_audit_log id BIGINT AUTO_INCREMENT PRIMARY KEY event_type VARCHAR(50) NOT NULL -- login_success, login_failed, settings_change, plugin_activated, etc. user_id BIGINT NULL object_type VARCHAR(50) NULL -- post, user, plugin, option object_id BIGINT NULL details LONGTEXT NULL -- JSON extra data ip VARCHAR(45) NULL created_at DATETIME NOT NULL INDEX idx_event (event_type, created_at) ``` **Module 4: SMTP** - For sites NOT using the IGNY8 plugin (if both installed, this module defers to IGNY8's SMTP) - SMTP mail override: host, port, username, password, encryption (SSL/TLS) - Email delivery log with status tracking - Test email sender - From name + from email override Classes: `Toolkit_SMTP_Module`, `Toolkit_SMTP_Mailer`, `Toolkit_Email_Log`, `Toolkit_Email_Test` Free: basic SMTP override, mail sending Premium: email delivery log, templates, resend failed, analytics Database table: ```sql {prefix}igny8_toolkit_email_log id BIGINT AUTO_INCREMENT PRIMARY KEY to_email VARCHAR(320) NOT NULL subject VARCHAR(500) NOT NULL status VARCHAR(20) NOT NULL -- sent, failed error_message TEXT NULL sent_at DATETIME NOT NULL ``` **Module 5: WooCommerce Enhancements** - Quick view modal on shop/archive pages - Wishlist (cookie-based for guests, user meta for logged in) - AJAX add-to-cart on archive pages - Product filters (price range, attributes, categories) with AJAX - Gallery enhancement (zoom, lightbox, thumbnails) Classes: `Toolkit_WooCommerce_Module`, `Toolkit_Quick_View`, `Toolkit_Wishlist`, `Toolkit_AJAX_Cart`, `Toolkit_Product_Filters`, `Toolkit_Product_Gallery` Entirely premium — WooCommerce enhancements only available in paid version. **3. Architecture:** ``` igny8-toolkit/ ├── igny8-toolkit.php # Plugin header, module loader ├── readme.txt ├── includes/ │ ├── class-toolkit.php # Main singleton class │ ├── class-module-manager.php # Module toggle (same pattern as main plugin) │ ├── modules/ │ │ ├── performance/ # Module 1 (9 class files) │ │ ├── forms/ # Module 2 (7 class files) │ │ ├── security/ # Module 3 (6 class files) │ │ ├── smtp/ # Module 4 (4 class files) │ │ └── woocommerce/ # Module 5 (6 class files) │ └── admin/ │ ├── class-dashboard.php │ └── views/ (dashboard template) ├── admin/ (CSS, JS for admin) ├── frontend/ (CSS, JS for frontend) └── languages/ (i18n) ``` Each module: independent toggle, zero impact when disabled. Module manager same pattern as main IGNY8 plugin (`register()`, `activate()`, `deactivate()`, `is_active()`, `boot()`). 4 database tables total: 1. `{prefix}igny8_toolkit_submissions` — form submissions 2. `{prefix}igny8_toolkit_email_log` — SMTP email log 3. `{prefix}igny8_toolkit_audit_log` — security audit log 4. `{prefix}igny8_toolkit_cache_stats` — performance cache stats **Cross-references:** 03C (companion theme is the primary consumer), 03A (if both plugins installed, SMTP module defers to main plugin's SMTP) --- ## BUILD SEQUENCE Claude Code builds these docs in order: ``` Phase 3 Doc Build Order ═══════════════════════ 1. 03A — WP Plugin Standalone (10 modules) Foundation: standalone plugin is the base everything else extends/consumes 2. 03B — WP Plugin Connected (2 modules) Extends 03A with IGNY8 SaaS integration 3. 03C — Companion Theme Depends on plugin API from 03A/03B 4. 03D — Toolkit Plugin Independent but complements theme, built last ``` For each doc: 1. Read this plan's section for that doc 2. Read the source files listed in "Source Material" 3. Read the relevant existing V2 docs referenced in "Cross-references" 4. Write the doc following the DOC STRUCTURE STANDARD 5. Verify all IDs from IGNY8 backend are integers (BigAutoField, not UUIDs) 6. Verify all IGNY8 model references use PLURAL names (Clusters, Keywords, Tasks, etc.) 7. Verify all frontend references use .tsx + Zustand 8. Verify all WP-side code follows WordPress coding standards 9. Save to `V2-Execution-Docs/03X-filename.md` --- ## SOURCE FILES TO READ Before writing ANY Phase 3 doc, read these source files: ``` temp/IGNY8-Project-Files/IGNY8-Plugin-Build-Plan.md temp/IGNY8-Project-Files/Theme-Build-Plan.md temp/IGNY8-Project-Files/DocC-WordPress-Ecosystem-Dev-Guide.md ``` Also read the master baseline: ``` V2-Execution-Docs/00-MASTER-EXECUTION-PLAN.md ``` And the relevant Phase 1/2 docs for cross-references: ``` V2-Execution-Docs/01A-sag-data-foundation.md (SAG models) V2-Execution-Docs/01D-setup-wizard-case2-new-site.md (wizard triggers blueprint sync) V2-Execution-Docs/01G-sag-health-monitoring.md (health scoring context) V2-Execution-Docs/02D-linker-internal.md (linking logic feeds plugin) V2-Execution-Docs/02G-rich-schema-serp.md (schema generation feeds plugin) ``` --- ## OUTPUT LOCATION Write all 4 docs to: ``` V2-Execution-Docs/ ```