Files
igny8/docs/plans/implemented/phase3-content-template-redesign.md
IGNY8 VPS (Salman) 75e5b148f5 reorg
2026-01-11 16:58:57 +00:00

30 KiB
Raw Blame History

## 🎨 DESIGN ANALYSIS & PLAN ### Current State Analysis WordPress Single Post Template: - Uses emojis (📅, 📝, ✍️, 📁, 🏷️) in header metadata - Shows all metadata including internal/debug data (Content ID, Task ID, Sector ID, Cluster ID, etc.) - SEO section shows Meta Title & Meta Description in header (should be hidden from users) - "Section Spotlight" label is hardcoded - Images not optimally distributed - one per section sequentially - Container max-width: 1200px App ContentViewTemplate: - Uses icons properly via component imports - Similar "Section Spotlight" label issue - Better image handling with aspect ratio detection - Shows extensive metadata in header (Meta Title, Meta Description, Primary/Secondary Keywords) - Container max-width: 1440px

📐 DESIGN PLAN

1. CSS Container Width Update

.igny8-content-container {
  max-width: 1280px;           /* Default for screens <= 1600px */
}

@media (min-width: 1600px) {
  .igny8-content-container {
    max-width: 1530px;         /* For screens > 1600px */
  }
}

2. WordPress Header Redesign

USER-FACING FIELDS (Keep in Header):

Field Display Icon Notes
Title H1 - Post title
Status Badge Published/Draft/etc - Post status
Posted Date Formatted date Calendar SVG Publication date
Word Count Formatted number Document SVG Content word count
Author Author name User SVG Post author
Topic Cluster name (clickable) Compass SVG Display cluster_name as "Topic"
Categories Badge list (Parent > Child clicakble) Folder SVG WP Categories
Tags Badge list (clickable) Tag SVG WP Tags

NON-USER FIELDS (Move to Metadata Section - Editor+ only):

  • Content ID, Task ID
  • Content Type, Structure
  • Cluster ID (keep cluster_name as Topic in header)
  • Sector ID, Sector Name
  • Primary Keyword, Secondary Keywords
  • Meta Title, Meta Description
  • Source, Last Synced

3. Section Label Redesign

Current: "Section Spotlight" (generic text)

New Approach - Keyword/Tag Matching Algorithm:

  1. Source Data:

    • Get all WordPress tags assigned to the post
    • Get all WordPress categories assigned to the post
    • Get primary keyword from post meta
    • Get secondary keywords from post meta (if available)
  2. Matching Logic:

    • For each section heading (H2), perform case-insensitive partial matching
    • Check if any tag name appears in the heading text
    • Check if any category name appears in the heading text
    • Check if primary/secondary keywords appear in the heading text
    • Prioritize: Primary Keyword > Tags > Categories > Secondary Keywords
  3. Display Rules:

    • If matches found: Display up to 2 matched keywords/tags as badges
    • If no matches: Display topic (cluster_name) or leave section without label badges
    • Never display generic "Section Spotlight" text
  4. Badge Styling:

    [Primary Match] [Secondary Match]  ← styled badges replacing "Section Spotlight"
    

Colors:

  • Primary badge: theme-color @ 15% opacity background, theme-color text
  • Secondary badge: theme-color @ 8% opacity background, theme-color @ 80% text

Implementation Function (Pseudo-code):

function igny8_get_section_badges($heading, $post_id) {
    $badges = [];
    $heading_lower = strtolower($heading);
    
    // Get post taxonomies and keywords
    $tags = get_the_tags($post_id);
    $categories = get_the_category($post_id);
    $primary_kw = get_post_meta($post_id, '_igny8_primary_keyword', true);
    $secondary_kws = get_post_meta($post_id, '_igny8_secondary_keywords', true);
    
    // Priority 1: Primary keyword
    if ($primary_kw && stripos($heading_lower, strtolower($primary_kw)) !== false) {
        $badges[] = ['text' => $primary_kw, 'type' => 'primary'];
    }
    
    // Priority 2: Tags
    if ($tags && count($badges) < 2) {
        foreach ($tags as $tag) {
            if (stripos($heading_lower, strtolower($tag->name)) !== false) {
                $badges[] = ['text' => $tag->name, 'type' => 'tag'];
                if (count($badges) >= 2) break;
            }
        }
    }
    
    // Priority 3: Categories
    if ($categories && count($badges) < 2) {
        foreach ($categories as $cat) {
            if (stripos($heading_lower, strtolower($cat->name)) !== false) {
                $badges[] = ['text' => $cat->name, 'type' => 'category'];
                if (count($badges) >= 2) break;
            }
        }
    }
    
    // Priority 4: Secondary keywords
    if ($secondary_kws && count($badges) < 2) {
        $kw_array = is_array($secondary_kws) ? $secondary_kws : explode(',', $secondary_kws);
        foreach ($kw_array as $kw) {
            $kw = trim($kw);
            if (stripos($heading_lower, strtolower($kw)) !== false) {
                $badges[] = ['text' => $kw, 'type' => 'keyword'];
                if (count($badges) >= 2) break;
            }
        }
    }
    
    return $badges;
}

4. Image Distribution Strategy

Available Images (4 total):

  • Position 0: Square (1024×1024)
  • Position 1: Landscape (1536×1024 or 1920×1080)
  • Position 2: Square (1024×1024)
  • Position 3: Landscape (1536×1024 or 1920×1080)

Distribution Plan - First 4 Sections (with descriptions):

Section Image Position Type Width Alignment Description
Featured Position 1 Landscape 100% max 1024px Center Show prompt on first use
Section 1 Position 0 Square 50% Right With description + widget placeholder below
Section 2 Position 3 Landscape 100% max 1024px Full width With description
Section 3 Position 2 Square 50% Left With description + widget placeholder below
Section 4 Position 1 (reuse) Landscape 100% max 1024px Full width With description

Distribution Plan - Sections 5-7+ (reuse without descriptions):

Section Reuse Image Type Width Alignment Description
Section 5 Featured (pos 1) Landscape 100% max 1024px Full width NO description
Section 6 Position 0 Square 50% Right NO description + widget placeholder
Section 7 Position 3 Landscape 100% max 1024px Full width NO description
Section 8+ Cycle through all 4 Based on type Based on type Based on type NO description

Special Case - Tables:

  • When section contains <table> element, always place full-width landscape image BEFORE table
  • Use next available landscape image (Position 1 or 3)
  • Max width: 1024px, centered
  • Spacing: margin-bottom: 2rem before table
  • Override normal section pattern when table detected

Image Reuse Rules:

  • Images 1-4 used in first 4 sections WITH descriptions/prompts
  • Sections 5+ reuse same images WITHOUT descriptions/prompts
  • Use CSS classes: .igny8-image-first-use vs .igny8-image-reuse
  • Maintain same layout pattern (square = 50%, landscape = 100%)

Widget Placeholders:

  • Show only below square images (left/right aligned)
  • Empty div with class .igny8-widget-placeholder
  • Space reserved for future widget insertion
  • Controlled via plugin settings (future implementation)

Implementation Notes:

// Check for table in section content
function igny8_section_has_table($section_html) {
    return (stripos($section_html, '<table') !== false);
}

// Get image aspect ratio from position
function igny8_get_image_aspect($position) {
    // Even positions (0, 2) = square
    // Odd positions (1, 3) = landscape
    return ($position % 2 === 0) ? 'square' : 'landscape';
}

// Determine if image should show description
function igny8_show_image_description($section_index) {
    // First 4 sections (0-3) show descriptions
    return ($section_index < 4);
}

5. Image Alignment with Tables

When section contains a <table>:

  • Place landscape image ABOVE the table
  • Full width (max 800px)
  • Proper spacing: margin-bottom: 2rem
  • Table should not wrap around image

6. Responsive Image Width Rules

/* Landscape images */
.igny8-image-landscape {
  max-width: 1024px;  /* Updated from 800px */
  width: 100%;
  margin: 0 auto;
  display: block;
}

.igny8-image-landscape.igny8-image-reuse {
  /* No description shown on reuse */
}

/* Single square image - Right aligned */
.igny8-image-square-right {
  max-width: 50%;
  margin-left: auto;
  float: right;
  margin-left: 2rem;
  margin-bottom: 2rem;
}

/* Single square image - Left aligned */
.igny8-image-square-left {
  max-width: 50%;
  margin-right: auto;
  float: left;
  margin-right: 2rem;
  margin-bottom: 2rem;
}

/* Widget placeholder below square images */
.igny8-widget-placeholder {
  clear: both;
  min-height: 200px;
  padding: 1.5rem;
  margin-top: 1rem;
  background: rgba(0, 0, 0, 0.02);
  border: 1px dashed rgba(0, 0, 0, 0.1);
  border-radius: 12px;
  display: none; /* Hidden by default, shown when widgets enabled */
}

.igny8-widget-placeholder.igny8-widgets-enabled {
  display: block;
}

/* Table-specific image positioning */
.igny8-image-before-table {
  max-width: 1024px;
  width: 100%;
  margin: 0 auto 2rem;
  display: block;
}

7. Role-Based Visibility

Metadata Section (Bottom):

<?php if (current_user_can('edit_posts')): ?>
<div class="igny8-metadata-footer igny8-editor-only">
  <!-- All internal metadata here -->
</div>
<?php endif; ?>

Visible only to:

  • Editor
  • Administrator
  • Author (for their own posts)

8. Header Icon Set (Replace Emojis)

Create inline SVG icons matching theme color:

// Calendar Icon
<svg class="igny8-icon" viewBox="0 0 20 20" fill="currentColor">
  <path fill-rule="evenodd" d="M6 2a1 1 0 00-1 1v1H4a2 2 0 00-2 2v10a2 2 0 002 2h12a2 2 0 002-2V6a2 2 0 00-2-2h-1V3a1 1 0 10-2 0v1H7V3a1 1 0 00-1-1zm0 5a1 1 0 000 2h8a1 1 0 100-2H6z"/>
</svg>

// Document Icon (Word Count)
<svg class="igny8-icon" viewBox="0 0 20 20" fill="currentColor">
  <path fill-rule="evenodd" d="M4 4a2 2 0 012-2h4.586A2 2 0 0112 2.586L15.414 6A2 2 0 0116 7.414V16a2 2 0 01-2 2H6a2 2 0 01-2-2V4zm2 6a1 1 0 011-1h6a1 1 0 110 2H7a1 1 0 01-1-1zm1 3a1 1 0 100 2h6a1 1 0 100-2H7z"/>
</svg>

// User Icon (Author)
<svg class="igny8-icon" viewBox="0 0 20 20" fill="currentColor">
  <path fill-rule="evenodd" d="M10 9a3 3 0 100-6 3 3 0 000 6zm-7 9a7 7 0 1114 0H3z"/>
</svg>

// Compass Icon (Topic/Cluster)
<svg class="igny8-icon" viewBox="0 0 20 20" fill="currentColor">
  <path fill-rule="evenodd" d="M5.05 4.05a7 7 0 119.9 9.9L10 18.9l-4.95-4.95a7 7 0 010-9.9zM10 11a2 2 0 100-4 2 2 0 000 4z"/>
</svg>

// Folder Icon (Categories)
<svg class="igny8-icon" viewBox="0 0 20 20" fill="currentColor">
  <path d="M2 6a2 2 0 012-2h5l2 2h5a2 2 0 012 2v6a2 2 0 01-2 2H4a2 2 0 01-2-2V6z"/>
</svg>

// Tag Icon (Tags)
<svg class="igny8-icon" viewBox="0 0 20 20" fill="currentColor">
  <path fill-rule="evenodd" d="M17.707 9.293a1 1 0 010 1.414l-7 7a1 1 0 01-1.414 0l-7-7A.997.997 0 012 10V5a3 3 0 013-3h5c.256 0 .512.098.707.293l7 7zM5 6a1 1 0 100-2 1 1 0 000 2z"/>
</svg>

Icon styling:

.igny8-icon {
  width: 1rem;
  height: 1rem;
  color: var(--igny8-theme-color, currentColor);
  opacity: 0.8;
  display: inline-block;
  vertical-align: middle;
}

9. Table of Contents

Position: Below featured image, before intro section

Content: List all H2 headings from content

Features:

  • Clickable links with smooth scroll to sections
  • Collapsible/expandable (optional)
  • Numbered list matching section numbers
  • Sticky positioning option (future setting)

Implementation:

function igny8_generate_table_of_contents($content) {
    $toc_items = [];
    
    // Parse content for H2 headings
    preg_match_all('/<h2[^>]*>(.*?)<\/h2>/i', $content, $matches);
    
    if (!empty($matches[1])) {
        foreach ($matches[1] as $index => $heading) {
            $heading_text = strip_tags($heading);
            $slug = sanitize_title($heading_text);
            $toc_items[] = [
                'number' => $index + 1,
                'text' => $heading_text,
                'id' => $slug
            ];
        }
    }
    
    return $toc_items;
}

HTML Structure:

<nav class="igny8-table-of-contents">
    <div class="igny8-toc-header">
        <span class="igny8-toc-icon">📑</span>
        <h3>Table of Contents</h3>
    </div>
    <ol class="igny8-toc-list">
        <?php foreach ($toc_items as $item): ?>
        <li class="igny8-toc-item">
            <a href="#<?php echo esc_attr($item['id']); ?>" class="igny8-toc-link">
                <span class="igny8-toc-number"><?php echo $item['number']; ?>.</span>
                <span class="igny8-toc-text"><?php echo esc_html($item['text']); ?></span>
            </a>
        </li>
        <?php endforeach; ?>
    </ol>
</nav>

CSS:

.igny8-table-of-contents {
    background: var(--wp--preset--color--base, #ffffff);
    border: 2px solid rgba(0, 0, 0, 0.12);
    border-radius: 16px;
    padding: 1.5rem 2rem;
    margin-bottom: 2rem;
    box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
}

.igny8-toc-header {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    margin-bottom: 1rem;
    padding-bottom: 1rem;
    border-bottom: 1px solid rgba(0, 0, 0, 0.08);
}

.igny8-toc-header h3 {
    margin: 0;
    font-size: 1.125rem;
    font-weight: 600;
}

.igny8-toc-list {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
}

.igny8-toc-link {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.5rem 0.75rem;
    text-decoration: none;
    color: inherit;
    border-radius: 8px;
    transition: background-color 0.2s ease;
}

.igny8-toc-link:hover {
    background: rgba(0, 0, 0, 0.04);
}

.igny8-toc-number {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.5rem;
    height: 1.5rem;
    background: rgba(59, 130, 246, 0.1);
    color: rgba(59, 130, 246, 1);
    border-radius: 50%;
    font-size: 0.75rem;
    font-weight: 600;
    flex-shrink: 0;
}

.igny8-toc-text {
    flex: 1;
    font-size: 0.9375rem;
}

Settings (Future Implementation):

// Plugin settings for TOC
$igny8_toc_settings = [
    'enabled' => true,
    'show_numbers' => true,
    'collapsible' => false,
    'sticky' => false,
    'min_headings' => 3, // Only show if 3+ H2 headings
];

10. Widget System

Widget Placeholders:

Widgets appear below square images (left/right aligned) where there's natural space.

Placeholder Function:

function igny8_render_widget_placeholder($position, $section_index) {
    // Check if widgets are enabled in settings
    $widgets_enabled = get_option('igny8_widgets_enabled', false);
    
    if (!$widgets_enabled) {
        return '';
    }
    
    $placeholder_class = 'igny8-widget-placeholder igny8-widgets-enabled';
    $placeholder_class .= ' igny8-widget-' . $position; // left or right
    $placeholder_class .= ' igny8-widget-section-' . $section_index;
    
    ?>
    <div class="<?php echo esc_attr($placeholder_class); ?>" 
         data-widget-position="<?php echo esc_attr($position); ?>"
         data-section-index="<?php echo esc_attr($section_index); ?>">
        <!-- Widget content will be inserted here via settings -->
        <?php do_action('igny8_widget_placeholder', $position, $section_index); ?>
    </div>
    <?php
}

Widget Settings (Future Implementation):

// Plugin settings for widgets
$igny8_widget_settings = [
    'enabled' => false,
    'sections' => [
        'section_1' => [
            'position' => 'right',
            'widget_type' => 'related_posts', // or 'custom_html', 'ad_unit', etc.
            'content' => '',
        ],
        'section_3' => [
            'position' => 'left',
            'widget_type' => 'newsletter_signup',
            'content' => '',
        ],
    ],
];

Widget Types (Future):

  • Related Posts
  • Newsletter Signup
  • Ad Units
  • Custom HTML
  • Social Share Buttons
  • Author Bio
  • Call-to-Action Boxes

11. Updated Structure Overview

WordPress Single Post:

┌─────────────────────────────────────────────┐
│ HEADER                                       │
│  ← Back to Posts                            │
│                                             │
│  [H1 Title]              [Status Badge]     │
│                                             │
│  📅 Posted: Date  📄 Words  👤 Author       │
│  🧭 Topic: Cluster Name                     │
│  📁 [Category Badges]  🏷️ [Tag Badges]      │
└─────────────────────────────────────────────┘

┌─────────────────────────────────────────────┐
│ FEATURED IMAGE (Landscape, max 1024px)      │
│                                             │
│  [Image Prompt - first use only]            │
└─────────────────────────────────────────────┘

┌─────────────────────────────────────────────┐
│ TABLE OF CONTENTS                           │
│  📑 Table of Contents                       │
│    1. Section Heading One                   │
│    2. Section Heading Two                   │
│    3. Section Heading Three                 │
│    ... (clickable, smooth scroll)           │
└─────────────────────────────────────────────┘

┌─────────────────────────────────────────────┐
│ INTRO SECTION                               │
│  Opening Narrative                          │
│  [Content...]                               │
└─────────────────────────────────────────────┘

┌─────────────────────────────────────────────┐
│ SECTION 1                                   │
│  [Keyword Badge] [Tag Badge]                │
│  1  [H2 Heading]                            │
│                                             │
│  ┌──────────────┐ ┌──────────────────────┐ │
│  │              │ │                      │ │
│  │   Content    │ │  Square Image (50%)  │ │
│  │              │ │    Right Aligned     │ │
│  │              │ │  [Image Description] │ │
│  └──────────────┘ └──────────────────────┘ │
│                    [Widget Placeholder]     │
└─────────────────────────────────────────────┘

┌─────────────────────────────────────────────┐
│ SECTION 2                                   │
│  [Keyword Badge]                            │
│  2  [H2 Heading]                            │
│                                             │
│  ┌───────────────────────────────────────┐ │
│  │   Landscape Image (100% max 1024px)   │ │
│  │        [Image Description]            │ │
│  └───────────────────────────────────────┘ │
│                                             │
│  [Content...]                               │
└─────────────────────────────────────────────┘

┌─────────────────────────────────────────────┐
│ SECTION 3                                   │
│  [Keyword Badge] [Tag Badge]                │
│  3  [H2 Heading]                            │
│                                             │
│  ┌──────────────────────┐ ┌──────────────┐ │
│  │                      │ │              │ │
│  │  Square Image (50%)  │ │   Content    │ │
│  │    Left Aligned      │ │              │ │
│  │  [Image Description] │ │              │ │
│  └──────────────────────┘ └──────────────┘ │
│  [Widget Placeholder]                       │
└─────────────────────────────────────────────┘

┌─────────────────────────────────────────────┐
│ SECTION 4 (with table example)             │
│  [Keyword Badge]                            │
│  4  [H2 Heading]                            │
│                                             │
│  ┌───────────────────────────────────────┐ │
│  │   Landscape Image (100% max 1024px)   │ │
│  │        [Image Description]            │ │
│  └───────────────────────────────────────┘ │
│                                             │
│  [Content before table...]                  │
│                                             │
│  ┌───────────────────────────────────────┐ │
│  │        TABLE                          │ │
│  │  [Data rows and columns]              │ │
│  └───────────────────────────────────────┘ │
└─────────────────────────────────────────────┘

┌─────────────────────────────────────────────┐
│ SECTION 5 (reuse - no description)          │
│  [Keyword Badge]                            │
│  5  [H2 Heading]                            │
│                                             │
│  ┌───────────────────────────────────────┐ │
│  │ Featured Image REUSED (no caption)    │ │
│  └───────────────────────────────────────┘ │
│                                             │
│  [Content...]                               │
└─────────────────────────────────────────────┘

┌─────────────────────────────────────────────┐
│ SECTION 6 (reuse - no description)          │
│  [Tag Badge]                                │
│  6  [H2 Heading]                            │
│                                             │
│  ┌──────────────┐ ┌──────────────────────┐ │
│  │   Content    │ │  Square Image REUSED │ │
│  │              │ │    (no caption)      │ │
│  └──────────────┘ └──────────────────────┘ │
│                    [Widget Placeholder]     │
└─────────────────────────────────────────────┘

┌─────────────────────────────────────────────┐
│ METADATA FOOTER (Editor+ only)              │
│  ▸ View IGNY8 Metadata                      │
│    - Content ID: 123                        │
│    - Task ID: 456                           │
│    - Meta Title: ...                        │
│    - Meta Description: ...                  │
│    - Primary Keyword: ...                   │
│    - Secondary Keywords: [list]             │
│    - Cluster ID: 789                        │
│    - Sector: Industry Name                  │
│    - Source: AI Generated                   │
│    - Last Synced: Date/Time                 │
└─────────────────────────────────────────────┘

12. App ContentViewTemplate Updates

Changes to body section only (not header):

  1. Remove "Section Spotlight" label - Replace with keyword badge matching system
  2. Add Table of Contents below featured image (matching WordPress implementation)
  3. Match image layout rules from WordPress template:
    • Section 1: Square right-aligned 50% (with description)
    • Section 2: Landscape full width max 1024px (with description)
    • Section 3: Square left-aligned 50% (with description)
    • Section 4: Landscape full width max 1024px (with description)
    • Sections 5+: Reuse images without descriptions
  4. Featured image max 1024px centered
  5. Widget placeholders below square images (empty for now)
  6. Table detection - full-width image before tables

Implementation Priority:

  • Phase 1: Update image sizing (1024px max)
  • Phase 2: Implement keyword badge matching
  • Phase 3: Add table of contents component
  • Phase 4: Add widget placeholder divs

Summary of Files to Update

File Changes Priority
igny8-content-template.css Container width breakpoints, image sizing classes, TOC styles, widget placeholder styles 🔴 High
igny8-header.php Remove emojis, add SVG icons, add Topic field, remove SEO/internal metadata 🔴 High
igny8-metadata.php Add role check (current_user_can('edit_posts')), include all moved metadata fields 🔴 High
igny8-content-sections.php Keyword badge matching logic, smart image distribution (Section 1-4 pattern), widget placeholders 🔴 High
igny8-featured-image.php Max 1024px, landscape priority 🟡 Medium
includes/template-functions.php Add helper functions: igny8_get_section_badges(), igny8_section_has_table(), igny8_show_image_description(), igny8_generate_table_of_contents() 🔴 High
ContentViewTemplate.tsx Match section labels, image layouts, add TOC component, widget placeholders 🟡 Medium
New File: parts/igny8-table-of-contents.php Table of contents component 🟡 Medium
New File: admin/settings-page.php Widget settings, TOC settings (future) 🟢 Low

Configuration Settings (Future Implementation)

// Plugin settings structure
$igny8_plugin_settings = [
    'table_of_contents' => [
        'enabled' => true,
        'show_numbers' => true,
        'collapsible' => false,
        'sticky' => false,
        'min_headings' => 3,
        'position' => 'after_featured_image', // or 'before_content', 'floating'
    ],
    'widgets' => [
        'enabled' => false,
        'sections' => [
            'section_1' => [
                'position' => 'right',
                'widget_type' => 'none', // 'related_posts', 'custom_html', 'ad_unit', etc.
                'content' => '',
            ],
            'section_3' => [
                'position' => 'left',
                'widget_type' => 'none',
                'content' => '',
            ],
        ],
    ],
    'images' => [
        'featured_max_width' => 1024,
        'landscape_max_width' => 1024,
        'square_width_percentage' => 50,
        'show_descriptions_sections' => 4, // Show descriptions in first N sections
    ],
    'badges' => [
        'show_section_badges' => true,
        'max_badges_per_section' => 2,
        'badge_sources' => ['primary_keyword', 'tags', 'categories', 'secondary_keywords'], // Priority order
    ],
];

Implementation Phases

Phase 1: Core Template Updates (Week 1)

  • Update CSS container widths and image sizing
  • Replace emojis with SVG icons in header
  • Add Topic field to header
  • Move metadata to bottom with role check
  • Implement keyword badge matching logic

Phase 2: Advanced Features (Week 2)

  • Table of contents component
  • Table detection and image positioning
  • Image reuse logic (sections 5+)

Phase 3: App Sync (Week 3)

  • Update ContentViewTemplate.tsx to match WordPress
  • Add TOC component to React app
  • Sync image layouts and sizing

Phase 4: Settings & Configuration (Week 4)

  • Plugin settings page
  • TOC configuration options
  • Widget management interface
  • Badge display preferences

Last Updated: January 10, 2026
Document Version: 2.0
Status: Design Complete - Ready for Implementation