18 KiB
Item 5: WordPress Content Template Improvements and Redesign
Priority: High
Target: Production Launch
Last Updated: December 11, 2025
Overview
Redesign WordPress content templates to optimize image placement, content structure, and cluster hub landing pages. Implement adaptive templates for different article lengths (500, 1000, 1500 words) with intelligent image reuse logic and proper HTML formatting.
Current Implementation Analysis
Content Template System
Location: backend/igny8_core/modules/publisher/ and content generation
Current State:
- Content generated as HTML in
Content.content_htmlfield - Images generated separately with prompts
- No formal template system for WordPress publishing
- Image placement done during content generation, not during publishing
Issues:
- No consistent image placement strategy
- No adaptation for article length
- Image reuse logic not implemented
- Cluster hub pages not differentiated from regular content
Content HTML Structure
Generated by: backend/igny8_core/ai/functions/generate_content.py
Current Format:
<p><em>Hook text...</em></p>
<p>Introduction paragraph 1...</p>
<p>Introduction paragraph 2...</p>
<h2>Section Heading 1</h2>
<p>Section content...</p>
<ul>
<li>List item 1</li>
<li>List item 2</li>
</ul>
<h2>Section Heading 2</h2>
<p>Section content...</p>
<table>
<tr><th>Column 1</th><th>Column 2</th></tr>
<tr><td>Data 1</td><td>Data 2</td></tr>
</table>
<!-- More sections... -->
Issues:
- No image tags in HTML (images added separately)
- No placeholder markers for image insertion
- Section lengths not adaptive to total word count
- Table structures sometimes inconsistent
Image System
Models:
ContentImage- Stores image URL, prompt, type (featured/in-article), position- Linked to
Contentvia foreign key
Current Image Generation:
- Content generated with HTML
- Image prompts extracted from content
- Images generated from prompts
- Images stored in
ContentImagetable - Publishing combines content HTML + image URLs
Issues:
- No clear insertion points in HTML
- Image position field not always used correctly
- Featured image vs in-article distinction unclear
- No reuse logic when fewer images than placeholders
Image Placement Strategy
Placement Rules by Article Length
500-Word Article
Structure: Intro + 2 sections + Conclusion
Image Placement:
- Position 1: After introduction (before first H2)
- Position 2: Mid-article (before second H2 or within)
- Position 3: Before conclusion (optional, if 3 images available)
Total Images: 2-3
1000-Word Article
Structure: Intro + 4-5 sections + Conclusion
Image Placement:
- Position 1: After introduction
- Position 2: After section 2
- Position 3: After section 3 or 4 (mid-article)
- Position 4: Before conclusion
- Position 5: Within longest section (optional)
Total Images: 3-5
1500-Word Article
Structure: Intro + 6-8 sections + Conclusion
Image Placement:
- Position 1: After introduction
- Position 2: After section 2
- Position 3: Mid-article (after section 4)
- Position 4: After section 5 or 6
- Position 5: Before conclusion
- Position 6-7: Within longer sections (optional)
Total Images: 4-7
Image Reuse Logic
Scenario: Not enough images for all placement positions
| Available Images | Reuse Strategy |
|---|---|
| 1 image | Use 3 times: after intro, mid-article, before conclusion |
| 2 images | Alternate: Image 1 → Image 2 → Image 1 → Image 2 (repeat pattern) |
| 3 images | Use each twice: distribute evenly across positions |
| 4+ images | Use each once until exhausted, then reuse starting from first |
Implementation Logic:
def get_image_for_position(position: int, available_images: list) -> Image:
"""
Get image for a specific position using reuse logic.
Args:
position: 0-indexed position (0 = after intro, 1 = mid-article, etc.)
available_images: List of ContentImage objects
Returns:
ContentImage object to use at this position
"""
if not available_images:
return None
num_images = len(available_images)
if num_images == 1:
# Reuse single image everywhere
return available_images[0]
elif num_images == 2:
# Alternate between images
return available_images[position % 2]
elif num_images == 3:
# Use each twice (0,1,2,0,1,2)
return available_images[position % 3]
else:
# Use each once, then repeat
return available_images[position % num_images]
Template System Design
Template Structure
Create: backend/igny8_core/modules/publisher/templates.py (NEW)
Purpose: Format content + images for WordPress publishing
Base Content Template
Class: ContentTemplate
Methods:
| Method | Purpose | Returns |
|---|---|---|
prepare_content(content, images) |
Main entry point | Formatted HTML |
insert_images(html, images, word_count) |
Insert images at positions | HTML with images |
get_image_positions(word_count) |
Calculate insertion points | List of positions |
format_image_html(image, alt_text) |
Format single image tag | HTML string |
add_featured_image_meta(content, image) |
Set WordPress featured image | Meta dict |
500-Word Template
Class: ShortFormTemplate(ContentTemplate)
Structure:
<div class="content-wrapper">
<!-- Introduction -->
<p><em>Hook...</em></p>
<p>Intro paragraph 1...</p>
<p>Intro paragraph 2...</p>
<!-- Image 1: After introduction -->
<figure class="wp-block-image">
<img src="..." alt="..." />
<figcaption>Image caption (optional)</figcaption>
</figure>
<!-- Section 1 -->
<h2>Section Heading 1</h2>
<p>Section content...</p>
<!-- Image 2: Mid-article -->
<figure class="wp-block-image">
<img src="..." alt="..." />
</figure>
<!-- Section 2 -->
<h2>Section Heading 2</h2>
<p>Section content...</p>
<!-- Conclusion -->
<p>Conclusion...</p>
</div>
Characteristics:
- 2-3 images total
- Shorter sections (80-100 words each)
- Minimal subsections
- Concise lists and tables
1000-Word Template
Class: StandardTemplate(ContentTemplate)
Structure:
<div class="content-wrapper">
<!-- Introduction -->
<p><em>Hook...</em></p>
<p>Intro paragraphs...</p>
<!-- Image 1 -->
<figure>...</figure>
<!-- Section 1 -->
<h2>Section Heading 1</h2>
<p>Paragraphs...</p>
<h3>Subsection 1.1</h3>
<p>Content...</p>
<!-- Section 2 -->
<h2>Section Heading 2</h2>
<p>Content...</p>
<!-- Image 2 -->
<figure>...</figure>
<!-- Section 3 -->
<h2>Section Heading 3</h2>
<ul>...</ul>
<!-- Image 3 -->
<figure>...</figure>
<!-- Section 4 -->
<h2>Section Heading 4</h2>
<table>...</table>
<!-- Image 4 -->
<figure>...</figure>
<!-- Conclusion -->
<h2>Conclusion</h2>
<p>Summary and CTA...</p>
</div>
Characteristics:
- 3-5 images
- Standard sections (140-160 words each)
- 2-3 subsections per section
- Mix of content types (paragraphs, lists, tables)
1500-Word Template
Class: LongFormTemplate(ContentTemplate)
Structure:
<div class="content-wrapper">
<!-- Introduction (180 words) -->
<p><em>Hook (45 words)...</em></p>
<p>Intro paragraph 1 (70 words)...</p>
<p>Intro paragraph 2 (65 words)...</p>
<!-- Image 1 -->
<figure>...</figure>
<!-- Section 1 (180 words) -->
<h2>Section Heading 1</h2>
<p>Opening paragraph (80 words)...</p>
<h3>Subsection 1.1</h3>
<p>Content (50 words)...</p>
<h3>Subsection 1.2</h3>
<p>Content (50 words)...</p>
<!-- Section 2 -->
<h2>Section Heading 2</h2>
<p>Content...</p>
<!-- Image 2 -->
<figure>...</figure>
<!-- ... More sections with strategic image placement ... -->
<!-- Section 7 -->
<h2>Section Heading 7</h2>
<p>Final content section...</p>
<!-- Image 5 -->
<figure>...</figure>
<!-- Conclusion (60 words) -->
<h2>Conclusion</h2>
<p>Summary paragraph...</p>
<p>Call to action...</p>
</div>
Characteristics:
- 4-7 images
- Longer sections (180-200 words each)
- 3-4 subsections per section
- Deeper content with more examples
- Optional info boxes or callouts
Cluster Hub Landing Page Template
Purpose: Comprehensive resource page for topic clusters
Class: ClusterHubTemplate(ContentTemplate)
Structure
<div class="cluster-hub">
<!-- Hero Section -->
<section class="hero">
<h1>{Cluster Name}</h1>
<p class="subtitle">{Cluster Description}</p>
<figure class="hero-image">
<img src="..." alt="..." />
</figure>
</section>
<!-- Overview Block -->
<section class="overview">
<h2>What is {Cluster Name}?</h2>
<p>Comprehensive introduction to the topic...</p>
<p>Why it matters and what you'll learn...</p>
</section>
<!-- Key Concepts Grid -->
<section class="key-concepts">
<h2>Key Concepts</h2>
<div class="concept-grid">
<div class="concept-card">
<h3>Concept 1</h3>
<p>Brief explanation...</p>
</div>
<!-- More concept cards -->
</div>
</section>
<!-- Featured Image -->
<figure>...</figure>
<!-- Subcluster Cards (if hierarchical) -->
<section class="subclusters">
<h2>Explore Related Topics</h2>
<div class="subcluster-grid">
<div class="subcluster-card">
<h3>Subcluster Name</h3>
<p>Description...</p>
<a href="...">Learn more →</a>
</div>
<!-- More subclusters -->
</div>
</section>
<!-- Latest Articles -->
<section class="latest-articles">
<h2>Latest Articles</h2>
<div class="article-list">
<!-- Auto-populated from content in this cluster -->
<article class="article-preview">
<img src="..." alt="..." />
<h3>Article Title</h3>
<p>Excerpt...</p>
<a href="...">Read more →</a>
</article>
<!-- More articles -->
</div>
</section>
<!-- Popular Articles -->
<section class="popular-articles">
<h2>Most Popular</h2>
<div class="article-list">
<!-- Sorted by views or engagement -->
</div>
</section>
<!-- CTA Block -->
<section class="cta">
<h2>Stay Updated</h2>
<p>Get the latest insights on {Cluster Name}...</p>
<form>
<input type="email" placeholder="Enter your email" />
<button>Subscribe</button>
</form>
</section>
<!-- Footer Navigation -->
<section class="footer-nav">
<h3>Related Topics</h3>
<ul>
<li><a href="...">Related Cluster 1</a></li>
<li><a href="...">Related Cluster 2</a></li>
<!-- More links -->
</ul>
</section>
</div>
Cluster Hub Features
| Feature | Implementation | Purpose |
|---|---|---|
| Hero Image | Full-width banner | Visual impact, brand identity |
| Concept Cards | 3-6 key concepts | Quick overview, scannable |
| Subcluster Grid | Links to child clusters | Hierarchy navigation |
| Latest Articles | Auto-query by cluster_id | Fresh content |
| Popular Articles | Sorted by view_count | Engagement driver |
| CTA Block | Email signup or action | Lead generation |
| Footer Nav | Related cluster links | Internal linking |
Conditional Variants
Category Archive (WordPress Taxonomy)
Differences from Cluster Hub:
- Shows WordPress category tree
- Includes post count per category
- Pagination for article list
- Filter by date, popularity
Tag Archive
Differences:
- Shows related tags as cloud
- Simpler layout (no hero, no concepts)
- Focus on article list
- Sorted by relevance
Attribute Archive (Product/Service)
Differences:
- Shows attribute filter options
- Product/service grid instead of article list
- Comparison table
- Filter by attribute values
Implementation Plan
Phase 1: Template System Foundation (Week 1)
Tasks:
- ✅ Create
ContentTemplatebase class - ✅ Implement image position calculator
- ✅ Implement image reuse logic
- ✅ Create image HTML formatter with figure tags
- ✅ Add WordPress meta integration (featured image)
File: backend/igny8_core/modules/publisher/templates.py (NEW)
Phase 2: Article Length Templates (Week 1-2)
Tasks:
- ✅ Implement
ShortFormTemplate(500 words) - ✅ Implement
StandardTemplate(1000 words) - ✅ Implement
LongFormTemplate(1500 words) - ✅ Test image insertion for each template
- ✅ Validate HTML output
Testing:
- Generate 10 articles per template
- Verify word counts
- Check image placement
- Validate HTML structure
Phase 3: Cluster Hub Template (Week 2)
Tasks:
- ✅ Implement
ClusterHubTemplate - ✅ Create hero section builder
- ✅ Create concept card generator
- ✅ Implement article list query
- ✅ Add related cluster links
- ✅ Test with real clusters
File: Same as Phase 1
Phase 4: Publishing Integration (Week 2-3)
Tasks:
- ✅ Update WordPress publisher to use templates
- ✅ Pass content + images to template
- ✅ Generate final HTML
- ✅ Send to WordPress with featured image meta
- ✅ Test full publishing workflow
File: backend/igny8_core/modules/publisher/views.py
Method: publish_to_wordpress()
Changes:
def publish_to_wordpress(content_id):
content = Content.objects.get(id=content_id)
images = ContentImage.objects.filter(content=content).order_by('position')
# Select template based on word count
if content.word_count <= 600:
template = ShortFormTemplate()
elif content.word_count <= 1200:
template = StandardTemplate()
else:
template = LongFormTemplate()
# Prepare content with images
final_html = template.prepare_content(content, images)
# Get featured image
featured_image = images.filter(type='featured').first()
# Publish to WordPress
wp_client.create_post(
title=content.title,
content=final_html,
featured_image_url=featured_image.image_url if featured_image else None,
# ... other meta
)
Phase 5: Taxonomy Templates (Week 3)
Tasks:
- ✅ Implement category archive variant
- ✅ Implement tag archive variant
- ✅ Implement attribute archive variant
- ✅ Add conditional rendering logic
- ✅ Test all taxonomy types
HTML Quality Standards
Image Tags
Format:
<figure class="wp-block-image size-large">
<img
src="{image_url}"
alt="{descriptive_alt_text}"
class="wp-image-{id}"
/>
<figcaption>{optional_caption}</figcaption>
</figure>
Alt Text Generation:
- Extract from image prompt
- Include relevant keywords
- Descriptive, not generic ("Person using laptop" → "Digital marketer analyzing SEO metrics on laptop")
Responsive Images (Future)
Enhancement:
<img
src="{image_url}"
srcset="{image_url_600} 600w, {image_url_1200} 1200w, {image_url_1920} 1920w"
sizes="(max-width: 600px) 100vw, (max-width: 1200px) 50vw, 33vw"
alt="{alt_text}"
/>
Requires: Image resizing service or WordPress handling
Content Wrapper
Purpose: Consistent styling and layout
<div class="content-wrapper entry-content">
<!-- Article content -->
</div>
WordPress Classes:
entry-content- Standard WordPress content classwp-block-*- Gutenberg block classes for proper styling
Testing Requirements
Template Output Tests
| Test Case | Expected Result |
|---|---|
| 500-word article with 1 image | Image reused 3 times at strategic positions |
| 1000-word article with 3 images | Each image used once, evenly distributed |
| 1500-word article with 5 images | Images at intro, mid-points, and conclusion |
| Article with 0 images | No image tags, content flows normally |
| Cluster hub page | All sections rendered, related content populated |
HTML Validation
- ✅ All HTML valid (W3C validator)
- ✅ All image tags have alt text
- ✅ Heading hierarchy correct (H1 → H2 → H3)
- ✅ No broken image links
- ✅ Figure tags properly closed
- ✅ WordPress classes applied correctly
WordPress Integration Tests
- ✅ Featured image set correctly
- ✅ Images appear in correct positions
- ✅ Content renders properly in WordPress editor
- ✅ Mobile responsive (WordPress theme handles)
- ✅ Image captions display correctly
- ✅ Internal links work
Success Metrics
- ✅ 100% of articles have images placed correctly
- ✅ Image reuse logic works for all scenarios
- ✅ Article lengths match templates (±5% tolerance)
- ✅ HTML validates 100%
- ✅ Cluster hubs render all sections
- ✅ WordPress publishing succeeds 100%
- ✅ User feedback: content looks professional
- ✅ No manual image placement needed
Related Files Reference
Backend (NEW)
backend/igny8_core/modules/publisher/templates.py- Template systembackend/igny8_core/modules/publisher/image_manager.py- Image reuse logic
Backend (Update)
backend/igny8_core/modules/publisher/views.py- Publishing integrationbackend/igny8_core/ai/functions/generate_content.py- Content structure
Models
backend/igny8_core/business/content/models.py- Content, ContentImage models
Notes
- Templates should be flexible enough for custom themes
- Image captions optional (can extract from prompt or leave empty)
- Cluster hub template can be used for category/tag pages
- Consider adding shortcode support for advanced layouts
- Future: Allow custom template selection per content piece
- Future: Visual template editor for admins