ContentEngine — Technical Addendum #2
Content Type Templates, Schema Library, Refresh System & Validation Architecture
| Field | Value |
|---|---|
| Author | Alton Wells |
| Date | March 2026 |
| Status | Draft for Review |
| Parent Spec | ContentEngine Technical Specification v3 |
| Depends On | Addendum #1 (LangExtract Implementation) |
| Scope | Content type definitions, structural templates, JSON-LD schema library, author entity specs, refresh queue system, SEO validation engine v2 |
1. Purpose & Scope
This addendum defines the complete content production framework for ContentEngine: what content types the system produces, how each type is structurally templated, what schema markup each type carries, how content freshness is managed, and how the SEO validation engine enforces quality at the deployment gate.
1.1 What This Addendum Covers
- Eight content type definitions with structural templates, required elements, and SEO rules
- Complete JSON-LD schema library mapped per content type
- Author entity specifications for three authors (Alton, Stan, Auctor)
- Organization entity specification for Consul
- Refresh queue system: scoring model, tiers, calendar integration, 90-day evaluation cycle
- SEO Validation Engine v2: BLOCKING/WARNING/INFO severity tiers with 16 checks
- Content depth validation check (brief-to-draft structural coverage)
- Historical validation score tracking schema
1.2 What This Addendum Does Not Cover
- Topic cluster definitions (deferred until competitive analysis is complete)
- Image generation pipeline (manual placement for MVP; pipeline is a future addendum)
- Agent prompt engineering (separate addendum)
- Filesystem-as-context architecture (deferred per parent spec)
1.3 Industry Context
Consul is a B2B SaaS AI executive assistant targeting CEOs and founders at a $200/month price point. Content must build trust with high-ticket decision-makers. The vertical is "AI productivity / executive operations" — not YMYL, but E-E-A-T signals are critical because the buyer is sophisticated and skeptical. Schema strategy reflects this: we optimize for commercial intent SERPs, AI Overview citations, and authority signals.
2. Content Type Registry
ContentEngine produces eight content types. Each type has a distinct structural template, schema mapping, internal linking profile, image density rule, and refresh cadence.
2.1 Type Overview
| Type ID | Type Name | Build Pattern | Typical Length | Primary Schema | Refresh Cadence |
|---|---|---|---|---|---|
blog_post | Blog Post | Recurring production | 1,500–2,500 words | BlogPosting | 90-day evaluation |
listicle | Listicle | Recurring production | 1,500–3,000 words | Article + ItemList | 90-day evaluation |
guide | Comprehensive Guide | Recurring production | 3,000–5,000 words | Article (long-form) | 90-day evaluation |
how_to | How-To / Tutorial | Recurring production | 2,000–4,000 words | HowTo | 90-day evaluation |
comparison | Comparison | Recurring production | 2,000–4,000 words | Article + ItemList or Product | 90-day evaluation |
case_study | Case Study | Irregular, customer-driven | 1,500–2,500 words | Article + Review | Annual |
pillar | Pillar / Hub Page | One-time per cluster | 2,500–4,000 words | CollectionPage | Quarterly |
glossary | Glossary / Definition | One-time batch | 500–1,200 words | DefinedTerm + FAQPage | Only when definitions evolve |
2.2 Comparison Sub-Variants
The comparison type covers two structural variants. The Brief Agent specifies which variant applies based on the target keyword.
| Variant | Trigger Keywords | Structure | Schema |
|---|---|---|---|
| Head-to-Head ("vs") | "X vs Y", "X alternative", "X compared to Y" | Two-option deep comparison with criteria matrix | Article with embedded Product entities using isSimilarTo |
| Roundup | "Best X tools", "Top X for Y", "X options for Y" | Multi-option ranked list with per-option sections | Article + ItemList with ListItem entries |
3. Content Type Template Specifications
Each content type has a required structural scaffold. The Writer Agent must follow this scaffold exactly. The SEO Validation Engine checks structural compliance.
3.1 Blog Post (blog_post)
Purpose: Topical authority pieces targeting informational and commercial-informational keywords. The workhorse content type.
Target length: 1,500–2,500 words
Required structural scaffold:
1# [H1: Title containing primary keyword]
2
3[TL;DR Box: 3-5 bullet point key takeaways in a styled callout.
4 Maps to `speakable` schema. First bullet answers the core question directly.
5 Total length: 80-120 words.]
6
7[Hero image: AI-generated, contextually relevant to topic]
8
9[Opening paragraph: 2-3 sentences. Primary keyword in first sentence.
10 Establishes the problem or question. Hooks the reader.]
11
12## [H2: Section 1 — secondary keyword or subtopic]
13
14[2-4 paragraphs, 200-400 words per section]
15[IMAGE marker if section exceeds 400 words]
16[Internal link within contextual sentence]
17
18## [H2: Section 2]
19...
20
21## [H2: Section N — typically 4-6 H2 sections total]
22
23### [H3 subsections as needed — no H3 without parent H2]
24
25## Frequently Asked Questions
26
27[Minimum 3 Q&A pairs. Questions sourced from PAA extraction data
28 in the content brief. Each answer: 2-4 sentences, concise,
29 citation-ready for AI engines.]
30
31### [Q1: Question text as H3]
32[Answer paragraph]
33
34### [Q2]
35...
36
37## [Closing section: Summary, next steps, or CTA]
38
39[Final paragraph with internal link to related pillar or guide content]SEO rules specific to blog posts:
- Internal links: minimum 1 per 400 words, minimum 4 total
- External links: minimum 1 authoritative source
- Image density: minimum 3 images (hero + 2 body), 1 per 800 words
- FAQ: required, minimum 3 Q&A pairs
- ToC: required if word count exceeds 1,500 words
- Primary keyword density: 0.8%–2.0%
3.2 Listicle (listicle)
Purpose: High-shareability content targeting "best of," "top N," and curated list queries. Strong for backlink acquisition and social distribution.
Target length: 1,500–3,000 words (scales with list size)
Required structural scaffold:
1# [H1: "N [Noun] for [Audience/Use Case]" or "Top N [Things]"]
2
3[TL;DR Box: Numbered quick-pick list (top 3-5 from the full list)
4 with one-sentence reason per pick. Maps to `speakable`.]
5
6[Hero image]
7
8[Opening paragraph: Why this list matters. What criteria were used.
9 Primary keyword in first sentence.]
10
11## [Table of Contents — auto-generated, anchor-linked]
12
13## [H2: 1. List Item Name]
14
15[Overview paragraph: what it is, why it's on the list]
16[Key details: 2-3 supporting points]
17[Pros/cons or key features if applicable]
18[IMAGE: screenshot, product image, or relevant visual]
19[Internal link if we have related content]
20
21## [H2: 2. List Item Name]
22...
23
24## [H2: N. List Item Name]
25
26## How We Evaluated [Topic]
27
28[Methodology paragraph: explains selection criteria.
29 Builds E-E-A-T credibility. 150-250 words.]
30
31## Frequently Asked Questions
32
33[Minimum 3 Q&A pairs, sourced from PAA data]
34
35### [Q1]
36[Answer]
37
38## Final Thoughts
39
40[Summary with recommendation tiers:
41 "Best overall," "Best for budget," "Best for [use case]"]
42[Internal link to related guide or pillar]SEO rules specific to listicles:
- Internal links: minimum 1 per 500 words, minimum 3 total
- External links: minimum 1 per list item (to the thing being listed, if external)
- Image density: 1 per list item (minimum), hero image required
- FAQ: optional but recommended (minimum 3 if included)
- ToC: required (always exceeds 1,500 words with 5+ items)
- Primary keyword density: 0.5%–1.5%
- Each list item H2 must be numbered and descriptively named
3.3 Comprehensive Guide (guide)
Purpose: Pillar-supporting deep-dive content targeting high-volume informational keywords. The authority builder. Designed for AI Overview citation eligibility.
Target length: 3,000–5,000 words
Required structural scaffold:
1# [H1: "The Complete Guide to [Topic]" or "[Topic]: Everything You Need to Know"]
2
3[TL;DR Box: 5-7 bullet point key takeaways. First bullet is a
4 one-sentence definition or core answer. Maps to `speakable`.
5 Total length: 100-150 words.]
6
7[Hero image]
8
9[Opening paragraph: Defines the topic. States why it matters now.
10 Primary keyword in first sentence. Author credibility signal
11 ("Based on our experience building Consul..." or similar).]
12
13## Table of Contents
14[Auto-generated, anchor-linked, levels H2 and H3]
15
16## What Is [Topic]?
17
18[Definition section: 2-3 paragraphs. First paragraph is a
19 citation-ready definition (2-3 sentences, under 60 words,
20 designed to be extractable by AI engines and featured snippets).
21 Remaining paragraphs expand with context.]
22[IMAGE: explanatory diagram or visual]
23
24## Why [Topic] Matters [for Audience]
25
26[Problem/opportunity framing. 200-400 words.
27 Statistics and citations from brief's external resources.]
28
29## [H2: Core Concept Section 1]
30
31### [H3: Subtopic A]
32[200-300 words per H3]
33[Internal link]
34
35### [H3: Subtopic B]
36[IMAGE if section exceeds 600 words without one]
37
38## [H2: Core Concept Section 2]
39...
40
41## [H2: Core Concept Section N — typically 5-8 H2 sections]
42
43## How to Get Started with [Topic]
44
45[Actionable next steps. 3-5 numbered steps.
46 Internal links to how-to content or product.]
47
48## Frequently Asked Questions
49
50[Minimum 5 Q&A pairs for guides. Sourced from PAA data.
51 Answers are concise and citation-ready.]
52
53### [Q1: Question]
54[Answer: 2-4 sentences]
55...
56
57## Conclusion
58
59[Summary paragraph. Internal link to pillar page.
60 CTA: "Learn more about how Consul handles [topic]" or similar.]SEO rules specific to guides:
- Internal links: minimum 1 per 300 words, minimum 8 total
- External links: minimum 3 authoritative sources with citations
- Image density: minimum 5 images, 1 per 700 words
- FAQ: required, minimum 5 Q&A pairs
- ToC: required (always exceeds 1,500 words)
- Primary keyword density: 0.5%–1.5%
- Must contain at least one citation-ready definition block (under 60 words, standalone paragraph)
- H3 sections required under at least 3 H2 sections
3.4 How-To / Tutorial (how_to)
Purpose: Step-by-step instructional content targeting "how to" queries. Highest schema richness (HowTo markup). Strong featured snippet and AI Overview candidate.
Target length: 2,000–4,000 words
Required structural scaffold:
1# [H1: "How to [Action] [with/for Context]"]
2
3[TL;DR Box: Numbered quick-step summary (abbreviated version
4 of the full steps, 1 sentence each). Maps to `speakable`.
5 Total length: 80-120 words.]
6
7[Hero image: shows the end result or the process overview]
8
9[Opening paragraph: What you'll learn. What you'll need.
10 Expected time/difficulty. Primary keyword in first sentence.]
11
12## What You'll Need (Prerequisites)
13
14[Bulleted list of requirements, tools, or knowledge needed.
15 Keep concise — each item 1 sentence max.]
16
17## Table of Contents
18
19## [H2: Step 1 — Action Verb + Description]
20
21[Detailed instructions for this step. 200-400 words.
22 Sub-steps as H3 if this step has multiple parts.]
23[IMAGE: screenshot or visual showing this step]
24[Pro tip or common mistake callout if applicable]
25
26## [H2: Step 2 — Action Verb + Description]
27...
28
29## [H2: Step N]
30
31## Troubleshooting Common Issues
32
33[3-5 common problems with solutions.
34 Each as H3 under this section.
35 Targets "why isn't [thing] working" PAA queries.]
36
37### [Problem 1]
38[Solution: 2-3 sentences]
39
40## Frequently Asked Questions
41
42[Minimum 3 Q&A pairs sourced from PAA data]
43
44## What's Next?
45
46[Next steps after completing the tutorial.
47 Internal links to advanced content or related guides.
48 CTA to Consul if applicable.]SEO rules specific to how-tos:
- Internal links: minimum 1 per 400 words, minimum 5 total
- External links: minimum 1 (tool or resource referenced in steps)
- Image density: minimum 1 per step, minimum 4 total (hero + step images)
- FAQ: required, minimum 3 Q&A pairs
- Troubleshooting section: required
- ToC: required
- Primary keyword density: 0.8%–2.0%
- Every step H2 must begin with an action verb
HowToschema: every step must map to aHowToStepwithname,text, andimage
3.5 Comparison (comparison)
Purpose: Decision-stage content targeting commercial and transactional keywords. Two sub-variants: head-to-head (vs) and roundup. Critical for bottom-funnel capture.
Target length: 2,000–4,000 words
3.5.1 Head-to-Head Variant
Required structural scaffold:
1# [H1: "[Product A] vs [Product B]: [Differentiator or Audience Context]"]
2
3[TL;DR Box: Quick verdict (3-4 sentences).
4 "Choose [A] if you need X. Choose [B] if you need Y."
5 Maps to `speakable`.]
6
7[Hero image: side-by-side visual or comparison graphic]
8
9[Opening paragraph: Why this comparison matters.
10 Who should read this. Primary keyword in first sentence.]
11
12## Quick Comparison Table
13
14[Feature comparison table with rows for key criteria
15 and columns for Product A, Product B, and "Winner" or "Best For".
16 This table maps to structured data and is a featured snippet target.]
17
18## Table of Contents
19
20## [H2: Product A] Overview
21
22[200-300 word overview. What it is, who it's for, key strengths.]
23[IMAGE: product screenshot or logo]
24
25## [H2: Product B] Overview
26
27[Same structure as Product A]
28
29## [H2: Comparison Criterion 1 — e.g., "Ease of Use"]
30
31[Head-to-head analysis for this criterion.
32 Specific examples, not vague claims.
33 Verdict sentence at end of section.]
34
35## [H2: Comparison Criterion 2]
36...
37
38## [H2: Comparison Criterion N — typically 4-6 criteria]
39
40## Pricing Comparison
41
42[Side-by-side pricing with plan details.
43 Value-for-money analysis, not just numbers.]
44
45## Our Verdict
46
47[3-4 paragraphs. Recommendation segmented by use case.
48 "For [use case A], choose [Product]. For [use case B], choose [other]."
49 Internal link to Consul if we're one of the compared products.]
50
51## Frequently Asked Questions
52
53[Minimum 3 Q&A pairs. Target "is [A] better than [B]" style queries.]3.5.2 Roundup Variant
Uses the same scaffold as the Listicle type (Section 3.2) but with comparison-specific language: criteria matrix at top, per-option deep dives, and a verdict section instead of "Final Thoughts." Schema uses ItemList with ListItem entries.
SEO rules specific to comparisons:
- Internal links: minimum 1 per 400 words, minimum 4 total
- External links: minimum 1 per product compared (to their homepage or pricing page)
- Image density: minimum 1 per product compared, plus hero and comparison table
- FAQ: required, minimum 3 Q&A pairs
- Comparison table: required (featured snippet target)
- ToC: required
- Primary keyword density: 0.5%–1.5%
- Products must be described with specific, verifiable details (no vague claims)
3.6 Case Study (case_study)
Purpose: Social proof and trust-building content. Demonstrates real results from Consul users. Lower SEO volume value but critical for conversion and E-E-A-T.
Target length: 1,500–2,500 words
Required structural scaffold:
1# [H1: "How [Customer/Company] [Achieved Outcome] with Consul"]
2
3[Results Box: 3 key metrics in a styled callout.
4 e.g., "50% reduction in email time | 3 hours saved daily | 2x meeting efficiency"
5 Maps to `speakable`.]
6
7[Hero image: customer headshot or company logo with context]
8
9[Opening paragraph: One-sentence hook with the key result.
10 Customer context (industry, size, role). Primary keyword.]
11
12## The Challenge
13
14[What problem was the customer facing?
15 Specific pain points. Quantify where possible.
16 200-300 words.]
17
18## Why They Chose Consul
19
20[Decision process. What alternatives were considered.
21 What made Consul the choice. 150-250 words.]
22
23## The Solution
24
25[How Consul was implemented. Specific features used.
26 Timeline. 200-400 words.]
27[IMAGE: workflow diagram or product screenshot in context]
28
29## The Results
30
31[Quantified outcomes. Before/after comparisons.
32 Each result as a sub-section or bold callout.
33 300-500 words.]
34
35### [Result 1: Metric + Context]
36### [Result 2]
37### [Result 3]
38
39## [Customer Name]'s Perspective
40
41[Direct quote from the customer. 2-4 sentences.
42 This maps to `Review` schema.]
43
44## Key Takeaways
45
46[3-5 bullet points summarizing lessons.
47 Generalizable insights, not just product promotion.]
48
49[CTA: "See how Consul can help your team" + internal link]SEO rules specific to case studies:
- Internal links: minimum 3 (to product, related guide, and pillar)
- External links: link to customer's website (with their permission)
- Image density: minimum 3 (hero, solution diagram, results chart)
- FAQ: not required
- ToC: optional (most case studies are under 2,500 words)
- Primary keyword density: 0.3%–1.0% (lower — these are narrative, not keyword-driven)
- Must contain at least one direct customer quote
- Must contain at least 2 quantified results
3.7 Pillar / Hub Page (pillar)
Purpose: Cluster parent page that links to all child content within a topic pillar. The topical authority anchor. Optimized for broad, high-volume keywords.
Target length: 2,500–4,000 words
Build pattern: One-time build per topic cluster. Updated quarterly or when new child content is published (add link to new child page).
Required structural scaffold:
1# [H1: "[Topic]: The Complete Resource"]
2
3[TL;DR Box: 5-7 bullet takeaways covering the full topic scope.
4 Maps to `speakable`. 100-150 words.]
5
6[Hero image]
7
8[Opening paragraph: Broad topic definition. Why it matters.
9 Audience framing. Primary keyword in first sentence.
10 Author credibility signal.]
11
12## Table of Contents
13[Anchor-linked, H2 and H3 levels]
14
15## What Is [Topic]?
16
17[Foundational definition section. 300-500 words.
18 Citation-ready definition in first paragraph.
19 IMAGE: concept diagram or overview visual]
20
21## [H2: Subtopic Cluster 1 — e.g., "Email Management"]
22
23[Overview paragraph: 150-250 words. Covers the subtopic broadly.
24 Does NOT go deep — that's what child content does.]
25
26**Key resources:**
27[Internal links to 3-5 child content pieces in this subtopic.
28 Each link has a one-sentence description.
29 These are the cluster links that build topical authority.]
30
31### [H3: Key concept within this subtopic — brief coverage]
32
33## [H2: Subtopic Cluster 2]
34...
35
36## [H2: Subtopic Cluster N — typically 4-7 clusters]
37
38## How to Get Started
39
40[Practical entry point. 200-300 words.
41 Links to beginner-level child content.]
42
43## Frequently Asked Questions
44
45[Minimum 5 Q&A pairs covering the broad topic.
46 These are GLOBAL FAQs about the topic, not piece-specific.]
47
48## Related Resources
49
50[Curated list of 5-10 most important child pages
51 organized by audience need or experience level.]SEO rules specific to pillar pages:
- Internal links: minimum 15 (this is the linking hub — every child page must be linked)
- External links: minimum 3 authoritative sources
- Image density: minimum 4 (hero, concept diagram, 2+ section images)
- FAQ: required, minimum 5 Q&A pairs (global/topic-level FAQs)
- ToC: required
- Primary keyword density: 0.5%–1.0%
- Every H2 subtopic section must contain at least 2 internal links to child content
- Page must be updated when new child content is published in the cluster
CollectionPageschema withhasPartreferencing all child pages
3.8 Glossary / Definition Page (glossary)
Purpose: Targets "what is [term]" queries. Designed for featured snippet capture, AI Overview citation, and voice search. Builds topical authority at the concept level.
Target length: 500–1,200 words
Build pattern: Batch build (20-40 terms initially), then add terms as new concepts emerge. Refresh only when definitions evolve.
Required structural scaffold:
1# [H1: "What Is [Term]? Definition, Examples & Guide"]
2
3[Definition Box: 1-2 sentence definition in a styled callout.
4 Under 50 words. Optimized for featured snippet extraction
5 and AI Overview citation. Maps to `speakable`.]
6
7[Hero image: conceptual visual for the term]
8
9[Opening paragraph: Expanded definition. 3-4 sentences.
10 Primary keyword in first sentence.
11 "In the context of [domain]..." framing.]
12
13## How [Term] Works
14
15[Explanation section. 200-400 words.
16 Practical, concrete explanation.
17 Example or analogy included.]
18[IMAGE: diagram or visual explanation]
19
20## Why [Term] Matters
21
22[Business value / relevance. 150-250 words.
23 Connects to the reader's context.]
24
25## [Term] Examples
26
27[2-3 concrete examples with brief descriptions.
28 100-200 words total.]
29
30## [Term] vs [Related Term]
31
32[If a commonly confused related term exists.
33 Brief comparison. 100-200 words.
34 Internal link to the related term's glossary page.]
35
36## Frequently Asked Questions
37
38[Minimum 3 Q&A pairs. Target PAA queries.
39 "Is [term] the same as [other term]?"
40 "Who uses [term]?" etc.]
41
42## Related Terms
43
44[List of 3-5 related glossary terms as internal links.
45 Builds the glossary cross-linking mesh.]
46
47## Learn More
48
49[Internal link to the relevant guide or pillar page.]SEO rules specific to glossary pages:
- Internal links: minimum 5 (related terms + parent guide/pillar)
- External links: minimum 1 authoritative definition source
- Image density: minimum 2 (hero + explanatory diagram)
- FAQ: required, minimum 3 Q&A pairs
- ToC: not required (pages are short)
- Primary keyword density: 1.0%–2.5%
- Must contain a citation-ready definition block (under 50 words, standalone paragraph in callout)
DefinedTermschema is requiredspeakablemust point to the definition box
4. JSON-LD Schema Library
Every page published by ContentEngine carries structured JSON-LD markup in the <head>. Schema is generated programmatically from content metadata and template structure — not manually authored. The CMS (Next.js + Supabase) injects schema at render time.
4.1 Schema Architecture
Each page carries a @graph array containing multiple schema entities. This is the Google-recommended approach for complex pages.
Base graph (present on every page):
1{
2 "@context": "https://schema.org",
3 "@graph": [
4 { "@type": "Organization", ... },
5 { "@type": "WebSite", ... },
6 { "@type": "WebPage", ... },
7 { "@type": "[ContentTypeSchema]", ... },
8 { "@type": "Person", ... },
9 { "@type": "BreadcrumbList", ... }
10 ]
11}4.2 Organization Entity (Global — Every Page)
This entity is configured once in system settings and injected on every page via the publisher property.
1{
2 "@type": "Organization",
3 "@id": "https://consul.ai/#organization",
4 "name": "[PLACEHOLDER: Legal entity name]",
5 "alternateName": "Consul",
6 "url": "https://consul.ai",
7 "logo": {
8 "@type": "ImageObject",
9 "@id": "https://consul.ai/#logo",
10 "url": "https://consul.ai/images/logo.png",
11 "contentUrl": "https://consul.ai/images/logo.png",
12 "width": "[PLACEHOLDER]",
13 "height": "[PLACEHOLDER]",
14 "caption": "Consul - AI Executive Assistant"
15 },
16 "image": { "@id": "https://consul.ai/#logo" },
17 "description": "Consul is a trust-first AI executive assistant that closes coordination loops across email, calendar, and messaging.",
18 "foundingDate": "[PLACEHOLDER: YYYY]",
19 "numberOfEmployees": {
20 "@type": "QuantitativeValue",
21 "value": "[PLACEHOLDER]"
22 },
23 "sameAs": [
24 "[PLACEHOLDER: LinkedIn URL]",
25 "[PLACEHOLDER: Twitter/X URL]",
26 "[PLACEHOLDER: YouTube URL if applicable]"
27 ],
28 "contactPoint": {
29 "@type": "ContactPoint",
30 "contactType": "customer support",
31 "email": "[PLACEHOLDER: support email]"
32 }
33}Action item: Fill in all PLACEHOLDER values before first publication. Store these in a site_config table in Supabase, not hardcoded.
4.3 WebSite Entity (Global — Every Page)
1{
2 "@type": "WebSite",
3 "@id": "https://consul.ai/#website",
4 "url": "https://consul.ai",
5 "name": "Consul",
6 "description": "AI Executive Assistant for CEOs and Founders",
7 "publisher": { "@id": "https://consul.ai/#organization" },
8 "inLanguage": "en-US"
9}4.4 Author Entities
Three author entities are defined. Each maps to a dedicated author profile page on the site.
4.4.1 Alton Wells
1{
2 "@type": "Person",
3 "@id": "https://consul.ai/authors/alton-wells/#person",
4 "name": "Alton Wells",
5 "url": "https://consul.ai/authors/alton-wells/",
6 "image": {
7 "@type": "ImageObject",
8 "url": "https://consul.ai/images/authors/alton-wells.jpg",
9 "caption": "Alton Wells"
10 },
11 "jobTitle": "[PLACEHOLDER: Title]",
12 "worksFor": { "@id": "https://consul.ai/#organization" },
13 "knowsAbout": [
14 "AI executive assistants",
15 "email automation",
16 "calendar management",
17 "AI delegation",
18 "productivity systems",
19 "SaaS product development"
20 ],
21 "sameAs": [
22 "[PLACEHOLDER: LinkedIn URL]",
23 "[PLACEHOLDER: Twitter/X URL]",
24 "[PLACEHOLDER: Personal site URL if applicable]"
25 ],
26 "description": "[PLACEHOLDER: 1-2 sentence bio for schema]"
27}4.4.2 Stan [Last Name]
Same structure as Alton. All PLACEHOLDER fields must be filled per individual.
1{
2 "@type": "Person",
3 "@id": "https://consul.ai/authors/stan//#person",
4 "name": "Stan [PLACEHOLDER: Last Name]",
5 "url": "https://consul.ai/authors/stan/",
6 "image": { ... },
7 "jobTitle": "[PLACEHOLDER]",
8 "worksFor": { "@id": "https://consul.ai/#organization" },
9 "knowsAbout": [ ... ],
10 "sameAs": [ ... ],
11 "description": "[PLACEHOLDER]"
12}4.4.3 Auctor (AI Editorial Author)
Auctor is presented transparently as an AI editorial assistant. The profile and schema reflect this.
1{
2 "@type": "Person",
3 "@id": "https://consul.ai/authors/auctor/#person",
4 "name": "Auctor",
5 "url": "https://consul.ai/authors/auctor/",
6 "image": {
7 "@type": "ImageObject",
8 "url": "https://consul.ai/images/authors/auctor.jpg",
9 "caption": "Auctor - Consul Editorial AI"
10 },
11 "jobTitle": "AI Editorial Assistant",
12 "worksFor": { "@id": "https://consul.ai/#organization" },
13 "knowsAbout": [
14 "AI productivity tools",
15 "email management",
16 "scheduling automation",
17 "executive workflows",
18 "content research"
19 ],
20 "description": "Auctor is Consul's AI editorial assistant. Articles by Auctor are researched and drafted using AI, then reviewed, enriched with original insights, and approved by Alton Wells or Stan before publication."
21}4.5 Author Profile Page Specification
Each of the three authors has a dedicated page at /authors/[slug]/. These pages are critical for E-E-A-T signals.
Required content blocks per author profile page:
- Hero section: Headshot (or avatar for Auctor), full name, title, one-line tagline
- Bio section: 2-3 paragraphs covering credentials, expertise areas, and connection to Consul. For Auctor, this section transparently describes the human-AI editorial process: "Articles by Auctor are researched and drafted using AI, then reviewed and enriched by [Alton/Stan] before publication. Every piece undergoes human editorial review, fact-checking, and the addition of original experience and insights."
- Expertise tags: Visual display of
knowsAbouttopics as clickable tags linking to relevant pillar pages - Social links: All
sameAsURLs displayed as icons - Recent articles: Dynamic feed of the 10 most recent articles by this author, pulled from
our_pagestable filtered byauthor_id - Article count and topic breakdown: "X articles published across [topics]"
Schema on author profile page:
1{
2 "@context": "https://schema.org",
3 "@graph": [
4 { "@type": "ProfilePage", ... },
5 { "@type": "Person", ... (full entity from above) },
6 { "@type": "Organization", ... },
7 { "@type": "BreadcrumbList", ... }
8 ]
9}4.6 Content Type Schema Mapping
4.6.1 Blog Post Schema
1{
2 "@type": "BlogPosting",
3 "@id": "https://consul.ai/blog/[slug]/#article",
4 "headline": "[meta title]",
5 "name": "[H1 title]",
6 "description": "[meta description]",
7 "datePublished": "[ISO 8601]",
8 "dateModified": "[ISO 8601]",
9 "author": { "@id": "https://consul.ai/authors/[author-slug]/#person" },
10 "publisher": { "@id": "https://consul.ai/#organization" },
11 "mainEntityOfPage": { "@id": "https://consul.ai/blog/[slug]/" },
12 "image": {
13 "@type": "ImageObject",
14 "url": "[hero image URL]",
15 "width": "[width]",
16 "height": "[height]"
17 },
18 "wordCount": "[actual word count]",
19 "articleSection": "[topic cluster name]",
20 "keywords": "[primary keyword, secondary keyword 1, secondary keyword 2]",
21 "inLanguage": "en-US",
22 "isPartOf": { "@id": "https://consul.ai/#website" },
23 "about": [
24 {
25 "@type": "Thing",
26 "name": "[primary topic]",
27 "sameAs": "[Wikipedia URL if applicable]"
28 }
29 ],
30 "speakable": {
31 "@type": "SpeakableSpecification",
32 "cssSelector": [".tldr-box", ".article-headline"]
33 }
34}Additional schema when FAQ section is present:
1{
2 "@type": "FAQPage",
3 "@id": "https://consul.ai/blog/[slug]/#faq",
4 "mainEntity": [
5 {
6 "@type": "Question",
7 "name": "[Question text]",
8 "acceptedAnswer": {
9 "@type": "Answer",
10 "text": "[Answer text]"
11 }
12 }
13 ]
14}4.6.2 Guide Schema
Uses Article (not BlogPosting) with articleBody scope and richer hasPart for section structure:
1{
2 "@type": "Article",
3 "@id": "https://consul.ai/guides/[slug]/#article",
4 "headline": "...",
5 "datePublished": "...",
6 "dateModified": "...",
7 "author": { "@id": "..." },
8 "publisher": { "@id": "..." },
9 "wordCount": "...",
10 "speakable": {
11 "@type": "SpeakableSpecification",
12 "cssSelector": [".tldr-box", ".definition-box", ".article-headline"]
13 },
14 "hasPart": [
15 {
16 "@type": "WebPageElement",
17 "name": "[H2 section title]",
18 "cssSelector": "#[section-anchor-id]"
19 }
20 ]
21}Guides always carry FAQPage schema (minimum 5 Q&A pairs).
4.6.3 How-To Schema
This is the richest single-page schema. Every step maps to a HowToStep.
1{
2 "@type": "HowTo",
3 "@id": "https://consul.ai/tutorials/[slug]/#howto",
4 "name": "[H1 title]",
5 "description": "[meta description]",
6 "datePublished": "...",
7 "dateModified": "...",
8 "author": { "@id": "..." },
9 "publisher": { "@id": "..." },
10 "totalTime": "PT[estimated minutes]M",
11 "estimatedCost": {
12 "@type": "MonetaryAmount",
13 "currency": "USD",
14 "value": "0"
15 },
16 "supply": [],
17 "tool": [
18 {
19 "@type": "HowToTool",
20 "name": "[tool from prerequisites section]"
21 }
22 ],
23 "step": [
24 {
25 "@type": "HowToStep",
26 "name": "[Step H2 title]",
27 "text": "[Step content — first paragraph only for schema]",
28 "url": "https://consul.ai/tutorials/[slug]/#step-1",
29 "image": {
30 "@type": "ImageObject",
31 "url": "[step image URL]"
32 }
33 }
34 ],
35 "speakable": {
36 "@type": "SpeakableSpecification",
37 "cssSelector": [".tldr-box", ".article-headline"]
38 }
39}How-Tos always carry FAQPage schema (minimum 3 Q&A pairs).
4.6.4 Listicle Schema
1{
2 "@type": "Article",
3 "@id": "https://consul.ai/blog/[slug]/#article",
4 "headline": "...",
5 "author": { "@id": "..." },
6 "publisher": { "@id": "..." },
7 "datePublished": "...",
8 "dateModified": "...",
9 "speakable": { ... }
10}Plus ItemList for the ranked items:
1{
2 "@type": "ItemList",
3 "@id": "https://consul.ai/blog/[slug]/#list",
4 "name": "[H1 title]",
5 "numberOfItems": "[count]",
6 "itemListOrder": "https://schema.org/ItemListOrderDescending",
7 "itemListElement": [
8 {
9 "@type": "ListItem",
10 "position": 1,
11 "name": "[Item name]",
12 "url": "[external URL to the item, or anchor link to section]"
13 }
14 ]
15}4.6.5 Comparison Schema (Head-to-Head)
Uses Article as the base, with embedded Product entities connected via isSimilarTo:
1{
2 "@type": "Article",
3 "headline": "...",
4 "author": { "@id": "..." },
5 "mentions": [
6 {
7 "@type": "SoftwareApplication",
8 "@id": "#product-a",
9 "name": "[Product A]",
10 "applicationCategory": "BusinessApplication",
11 "operatingSystem": "[platforms]",
12 "url": "[product URL]",
13 "isSimilarTo": { "@id": "#product-b" }
14 },
15 {
16 "@type": "SoftwareApplication",
17 "@id": "#product-b",
18 "name": "[Product B]",
19 "applicationCategory": "BusinessApplication",
20 "url": "[product URL]",
21 "isSimilarTo": { "@id": "#product-a" }
22 }
23 ]
24}When Consul is one of the compared products, add offers and aggregateRating (when available from third-party platforms):
1{
2 "@type": "SoftwareApplication",
3 "name": "Consul",
4 "applicationCategory": "BusinessApplication",
5 "operatingSystem": "Web, iOS",
6 "offers": {
7 "@type": "Offer",
8 "price": "200.00",
9 "priceCurrency": "USD",
10 "priceValidUntil": "[YYYY-MM-DD]",
11 "availability": "https://schema.org/OnlineOnly"
12 }
13}Note: aggregateRating is deferred until third-party review platforms (G2, Capterra) are set up. The schema hook is defined here; the data will be populated when available. On-site testimonials use individual Review schema (see Case Study below), not aggregateRating.
4.6.6 Comparison Schema (Roundup)
Same as Listicle (Article + ItemList) with itemListElement entries linking to each reviewed product.
4.6.7 Case Study Schema
1{
2 "@type": "Article",
3 "@id": "https://consul.ai/case-studies/[slug]/#article",
4 "headline": "...",
5 "author": { "@id": "..." },
6 "publisher": { "@id": "..." },
7 "datePublished": "...",
8 "dateModified": "...",
9 "about": {
10 "@type": "SoftwareApplication",
11 "name": "Consul",
12 "@id": "https://consul.ai/#software"
13 },
14 "speakable": {
15 "@type": "SpeakableSpecification",
16 "cssSelector": [".results-box", ".article-headline"]
17 }
18}Plus Review schema from the customer quote:
1{
2 "@type": "Review",
3 "@id": "https://consul.ai/case-studies/[slug]/#review",
4 "author": {
5 "@type": "Person",
6 "name": "[Customer name]",
7 "jobTitle": "[Customer title]",
8 "worksFor": {
9 "@type": "Organization",
10 "name": "[Customer company]"
11 }
12 },
13 "reviewBody": "[Customer quote text]",
14 "itemReviewed": {
15 "@type": "SoftwareApplication",
16 "name": "Consul",
17 "@id": "https://consul.ai/#software"
18 }
19}4.6.8 Pillar Page Schema
1{
2 "@type": "CollectionPage",
3 "@id": "https://consul.ai/topics/[slug]/#page",
4 "name": "[H1 title]",
5 "description": "[meta description]",
6 "author": { "@id": "..." },
7 "publisher": { "@id": "..." },
8 "datePublished": "...",
9 "dateModified": "...",
10 "mainEntity": {
11 "@type": "Thing",
12 "name": "[Topic name]",
13 "description": "[Topic definition]"
14 },
15 "hasPart": [
16 {
17 "@type": "WebPage",
18 "name": "[Child page title]",
19 "url": "[Child page URL]"
20 }
21 ],
22 "speakable": {
23 "@type": "SpeakableSpecification",
24 "cssSelector": [".tldr-box", ".article-headline"]
25 }
26}hasPart is dynamically populated from the content relationship graph — all pages with a child_of edge pointing to this pillar's topic cluster are included.
4.6.9 Glossary Page Schema
1{
2 "@type": "DefinedTerm",
3 "@id": "https://consul.ai/glossary/[slug]/#term",
4 "name": "[Term]",
5 "description": "[Definition from definition box — under 50 words]",
6 "inDefinedTermSet": {
7 "@type": "DefinedTermSet",
8 "name": "Consul Glossary",
9 "url": "https://consul.ai/glossary/"
10 }
11}Plus FAQPage schema for the FAQ section, and Article as the base content type.
speakable points to the definition box CSS selector.
4.7 BreadcrumbList Schema (Global — Every Page)
Generated dynamically from the URL path. Present on every page.
1{
2 "@type": "BreadcrumbList",
3 "@id": "https://consul.ai/[path]/#breadcrumb",
4 "itemListElement": [
5 {
6 "@type": "ListItem",
7 "position": 1,
8 "name": "Home",
9 "item": "https://consul.ai/"
10 },
11 {
12 "@type": "ListItem",
13 "position": 2,
14 "name": "[Section]",
15 "item": "https://consul.ai/[section]/"
16 },
17 {
18 "@type": "ListItem",
19 "position": 3,
20 "name": "[Page Title]",
21 "item": "https://consul.ai/[section]/[slug]/"
22 }
23 ]
24}4.8 SoftwareApplication Schema (Consul Product Entity)
This entity represents the Consul product itself. Referenced by case studies, comparisons, and product-adjacent content.
1{
2 "@type": "SoftwareApplication",
3 "@id": "https://consul.ai/#software",
4 "name": "Consul",
5 "description": "AI executive assistant that manages email, calendar, and scheduling for CEOs and founders.",
6 "applicationCategory": "BusinessApplication",
7 "operatingSystem": "Web, iOS",
8 "url": "https://consul.ai",
9 "offers": {
10 "@type": "AggregateOffer",
11 "lowPrice": "50.00",
12 "highPrice": "200.00",
13 "priceCurrency": "USD",
14 "offerCount": 2,
15 "offers": [
16 {
17 "@type": "Offer",
18 "name": "Founding Member",
19 "price": "50.00",
20 "priceCurrency": "USD",
21 "availability": "https://schema.org/LimitedAvailability",
22 "description": "Lifetime founding member discount"
23 },
24 {
25 "@type": "Offer",
26 "name": "Standard",
27 "price": "200.00",
28 "priceCurrency": "USD",
29 "availability": "https://schema.org/OnlineOnly"
30 }
31 ]
32 },
33 "creator": { "@id": "https://consul.ai/#organization" },
34 "featureList": [
35 "Automated email triage and drafting",
36 "AI-powered scheduling and calendar management",
37 "Daily briefings via email and iMessage",
38 "Multi-interface access (Web, Email, iMessage)",
39 "24/7 automated workflows"
40 ]
41}4.9 Speakable Implementation
The speakable property identifies content sections most relevant for text-to-speech and AI extraction. It is not visually rendered — it is encoded in schema only.
CSS selectors referenced by speakable must exist in the page markup:
| Selector | Maps To | Present On |
|---|---|---|
.tldr-box | TL;DR / Key Takeaways callout box | Blog, listicle, guide, how-to, pillar |
.definition-box | Definition callout (under 50/60 words) | Guide, glossary |
.results-box | Key metrics callout | Case study |
.article-headline | H1 element | All content types |
.comparison-table | Quick comparison table | Comparison (head-to-head) |
The Writer Agent outputs these as markdown callout blocks. The CMS renderer maps them to the correct HTML elements with the specified CSS classes.
5. Refresh Queue System
5.1 Design Principles
Every piece of content is re-evaluated on a maximum 90-day cycle. Re-evaluation does NOT mean automatic refresh — it means the system scores refresh urgency and only pieces crossing a threshold enter the active refresh queue. High-performing content gets its next evaluation pushed out (up to 150 days). The goal is ensuring every published page is either performing well or actively being improved.
5.2 Refresh Urgency Score
Each page receives a composite urgency score calculated from five weighted signals. Score range: 0-100.
| Signal | Weight | Data Source | Scoring Logic |
|---|---|---|---|
| Position Decay | 30% | GSC our_page_performance | Score = (position drop over trailing 30 days / 10) × 100, capped at 100. A 5-position drop = 50. No drop = 0. |
| Traffic Decline | 25% | GSC our_page_performance | Score = (% impression decline, trailing 30d vs prior 30d) × 100, capped at 100. 40% decline = 40. Growth = 0. |
| Content Age | 20% | our_pages.last_updated / dateModified | Score = (days since last update / 90) × 100, capped at 100. 90+ days = 100. Just updated = 0. |
| Competitive Displacement | 15% | Graph outperforms edges, competitor_changes | Score = count of new/worsened outperforms edges for this page's target keyword × 25, capped at 100. |
| Factual Staleness | 10% | our_page_extractions (claim entities with dated statistics) | Score = (count of claims referencing years older than current year / total claims) × 100. |
Composite urgency score = weighted sum of all five signals.
5.3 Refresh Thresholds and Evaluation Scheduling
| Urgency Score | Action | Next Evaluation |
|---|---|---|
| 0–25 | No action. Content is performing well. | Push to 150 days from now |
| 26–50 | Flag for monitoring. Surface in dashboard as "watch list." | Re-evaluate in 60 days |
| 51–70 | Queue for light refresh. | After refresh completes |
| 71–85 | Queue for moderate refresh. | After refresh completes |
| 86–100 | Queue for heavy refresh. Prioritize immediately. | After refresh completes |
5.4 Refresh Tiers
| Tier | Scope | Brief Required? | Writer Agent Instructions | Estimated Human Review Time |
|---|---|---|---|---|
| Light | Update statistics, fix broken links, update dateModified, refresh any outdated claims. No structural changes. | No brief. Agent receives the page + extraction data showing stale claims. | "Update the following factual claims with current data. Fix any broken links. Do not change structure, tone, or headings." | 5 minutes |
| Moderate | Restructure sections, add new content informed by competitive changes, update schema, add/improve FAQ with current PAA data. | Abbreviated brief (outline changes only, not full brief). | "Apply the following structural changes to the existing content. Add the following new sections. Update FAQ with these questions." | 15 minutes |
| Heavy | Near-complete rewrite triggered by major rank collapse, topic shift, or competitive leapfrog. | Full brief (same as new content). | Same as new content creation — full Writer Agent pass. | 20-30 minutes (same as new content) |
5.5 Calendar Integration
Refreshes are mixed into the content calendar at a 70/30 ratio (new content / refreshes). The Strategy Agent manages this allocation.
Rules:
- The Strategy Agent sees the refresh queue as a prioritized list alongside new content opportunities.
- When planning a production cycle, the agent allocates approximately 70% of capacity slots to new content and 30% to refreshes.
- Refresh items are sorted by urgency score (highest first).
- Light refreshes consume 0.25 capacity units (minimal human review). Moderate refreshes consume 0.5 units. Heavy refreshes consume 1.0 units (same as new content).
- As the content library grows, the ratio naturally shifts — more pages means more refresh candidates. The 70/30 is a starting target; the Strategy Agent can adjust based on queue depth.
- If the refresh queue is empty or all scores are below threshold, 100% of capacity goes to new content.
5.6 Refresh Tracking Schema
1CREATE TABLE refresh_evaluations (
2 id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
3 page_id UUID NOT NULL REFERENCES our_pages(id),
4 evaluated_at TIMESTAMP DEFAULT now(),
5 urgency_score FLOAT NOT NULL,
6 position_decay_score FLOAT NOT NULL,
7 traffic_decline_score FLOAT NOT NULL,
8 content_age_score FLOAT NOT NULL,
9 competitive_displacement_score FLOAT NOT NULL,
10 factual_staleness_score FLOAT NOT NULL,
11 action_taken VARCHAR(20) NOT NULL, -- 'none', 'watch', 'light', 'moderate', 'heavy'
12 next_evaluation_date DATE NOT NULL,
13 refresh_plan_item_id UUID REFERENCES content_plan_items(id), -- links to the refresh work item if queued
14 notes TEXT
15);
16
17CREATE INDEX idx_refresh_page ON refresh_evaluations(page_id);
18CREATE INDEX idx_refresh_next ON refresh_evaluations(next_evaluation_date);When a refresh is queued, a content_plan_items row is created with a new status enum value:
1ALTER TYPE content_plan_item_status ADD VALUE 'refresh_light';
2ALTER TYPE content_plan_item_status ADD VALUE 'refresh_moderate';
3ALTER TYPE content_plan_item_status ADD VALUE 'refresh_heavy';This integrates refreshes into the existing calendar UI and workflow pipeline.
5.7 Refresh-Specific SEO Rules
When a page is refreshed, the following SEO requirements apply:
dateModifiedin schema MUST be updated to the refresh publication date.datePublishedMUST remain the original publication date (never change).- The URL/slug MUST NOT change. If a slug change is absolutely necessary (rare), a 301 redirect from old to new URL must be created and the validation engine must verify the redirect is in place.
- The canonical URL must remain the same page URL.
- All existing internal links pointing TO this page from other pages must be verified (the Publishing Agent checks inbound
links_tograph edges). - If the refresh adds new sections, the Publishing Agent must run the
should_link_toanalysis to identify existing pages that should link to the refreshed page's new content. - After refresh publication, the same post-publish pipeline fires: LangExtract re-extraction, summary regeneration, graph edge rebuild.
6. SEO Validation Engine v2
6.1 Architecture Overview
The validation engine runs as deterministic code — no LLM involved. It operates like a CI/CD deployment gate: every content piece must pass all BLOCKING checks before publication. WARNING and INFO checks are logged, tracked, and surfaced in the dashboard but do not block publication.
6.2 Severity Tiers
| Tier | Behavior | Analogy |
|---|---|---|
| BLOCKING | Publication halted. Auto-fix attempted (max 3 cycles). If still failing, escalate to human with specific failure report. | Failing test in CI — merge blocked. |
| WARNING | Logged in validation report. Surfaced in dashboard. Tracked historically. Does not block publication but contributes to content health score. | Linting warning — merge allowed, tech debt tracked. |
| INFO | Logged for analytics. Never blocks. Used for trending analysis and optimization over time. | Code coverage metrics — informational only. |
6.3 Complete Check Registry
BLOCKING Checks (Must Pass)
Check B1: Meta Title
- Length: 50-60 characters
- Contains primary keyword
- Unique across all
our_pages(checked againstour_page_seo.meta_title) - Will not truncate in SERPs (validated via pixel-width estimation, max 580px)
- Auto-fixable: Yes (truncation adjustment, keyword insertion)
Check B2: Meta Description
- Length: 150-160 characters
- Contains primary keyword
- Contains value proposition or call-to-action language
- Unique across all
our_pages - Auto-fixable: Yes
Check B3: Heading Hierarchy
- Exactly one H1
- H1 contains primary keyword
- No skipped heading levels (H1 → H3 without H2)
- Logical nesting throughout
- H2s use secondary keywords from brief where natural
- Auto-fixable: Partial (can fix skipped levels, cannot fix missing keyword)
Check B4: Primary Keyword Presence
- Primary keyword appears in: meta title, H1, first 100 words, at least one H2, meta description
- All five placements are required
- Auto-fixable: Partial
Check B5: Keyword Density
- Primary keyword density: within range specified per content type (see Section 3)
- No keyword stuffing patterns (3+ identical keyword phrases within 200 words)
- Auto-fixable: No (requires content rewriting)
Check B6: Internal Linking Minimum
- Meets minimum link count for content type (varies — see Section 3)
- All internal links resolve to published pages (verified against
our_pagestable) - Anchor text is descriptive (no "click here", "read more", "this article")
- Anchor text is diversified (no more than 30% exact-match keyword anchors)
- Links are contextually placed (not in a footer dump section)
- Auto-fixable: Partial (can verify resolution, cannot add missing links)
Check B7: Schema Validity
- JSON-LD present and parseable
- Schema type matches content type mapping (Section 4.6)
- All required properties for the schema type are present and non-empty
authorreferences a valid author entitypublisherreferences the Organization entitydatePublishedis present and valid ISO 8601dateModifiedis present and >=datePublishedspeakableselector references exist in page markup- For
HowTo: every step H2 maps to aHowToStep - For
FAQPage: every FAQ Q&A pair maps to aQuestion/Answer - For
CollectionPage:hasPartcontains all child pages from graph - Auto-fixable: Yes (schema is generated programmatically — fix is regeneration)
Check B8: URL & Slug
- URL-friendly (lowercase, hyphens, no special characters, no spaces)
- Contains primary keyword or close variant
- Under 75 characters (path portion only)
- No duplicate slug in
our_pagestable - For refreshes: URL matches original (no slug changes without redirect)
- Auto-fixable: Partial (can suggest slug, cannot auto-change)
Check B9: Date Integrity
datePublishedpresent in schema and matches visible publish datedateModifiedpresent in schema- For new content:
dateModifiedequalsdatePublished - For refreshed content:
dateModifiedis the refresh date,datePublishedis the original date - Visible "last updated" date on page matches schema
dateModified - Auto-fixable: Yes
Check B10: Content Type Structural Compliance
- Content matches the required structural scaffold for its content type (Section 3)
- Required sections are present (e.g., FAQ section on types that require it)
- Required elements exist (e.g., comparison table on comparison pages, prerequisites on how-tos, customer quote on case studies)
- TL;DR box present on types that require it
- ToC present when required (word count threshold or type requirement)
- Auto-fixable: No (structural issues require content rework)
WARNING Checks (Logged, Not Blocking)
Check W1: Image Density
- Meets minimum image count for content type
- Meets minimum density (1 per 800 words)
- No 2 consecutive H2 sections without an image
- Hero image present
- All images have alt text (human-written)
- All images have explicit width and height attributes
Check W2: External Linking
- Meets minimum external link count for content type
- No links to competitor domains (checked against
competitorstable) - External links have
rel="noopener"on new-tab links - External links point to authoritative domains (heuristic: domain authority check if available)
Check W3: Readability Score
- Flesch-Kincaid readability within configured range (target: grade 8-12 depending on content type)
- No paragraph exceeds 300 words
- Sentence length variety present (standard deviation of sentence lengths > 5 words)
Check W4: Content Depth Coverage
- Draft covers all H2 sections specified in the approved brief
- Each H2 section meets its target word count (within ±20%)
- No brief-specified subtopic is missing entirely
- This is a structural check, not a quality judgment
Check W5: FAQ Section Quality
- FAQ section meets minimum Q&A count for content type
- Questions are actual questions (end with "?")
- Answers are 2-4 sentences each (citation-ready length)
- Questions are unique (no near-duplicates within the same page)
Check W6: Mobile & Performance
- All images have explicit width/height (prevents CLS)
- Images use
loading="lazy"except hero image (above-the-fold) - No inline styles that break mobile viewport
- Tables have responsive handling (horizontal scroll wrapper)
- No excessively large embedded content (>500KB individual assets)
INFO Checks (Analytics Only)
Check I1: Word Count Delta
- Actual word count vs. brief target word count
- Logged as percentage delta (e.g., "+12%", "-8%")
Check I2: Keyword Density Exact
- Primary keyword density as exact percentage
- Secondary keyword presence (count and density)
Check I3: Schema Richness Score
- Count of schema properties populated beyond minimum required
- Scored 0-100 based on optional property coverage
- Tracks how "complete" the schema is vs. maximum possible
Check I4: Internal Link Density Ratio
- Internal links per 1,000 words
- Compared to site-wide average for the same content type
Check I5: Estimated Reading Time
- Calculated from word count (avg 250 wpm)
- Logged for analytics and potential on-page display
Check I6: Citation-Ready Block Count
- Number of standalone paragraphs under 60 words that contain factual claims or definitions
- These are the blocks most likely to be extracted by AI engines
- Higher count = higher AI citation eligibility
6.4 Validation Output Schema
1interface SeoValidationResult {
2 pageId: string;
3 contentType: ContentType;
4 validatedAt: Date;
5 validationVersion: string; // schema version of the check suite
6
7 // Gate decision
8 passed: boolean; // true if all BLOCKING checks pass
9
10 // Summary scores
11 blockingScore: string; // "10/10", "8/10"
12 warningScore: string; // "5/6", "4/6"
13 infoMetrics: Record<string, string | number>;
14
15 // Individual checks
16 checks: Array<{
17 id: string; // "B1", "W3", "I2"
18 name: string;
19 tier: "BLOCKING" | "WARNING" | "INFO";
20 passed: boolean;
21 value?: string | number; // actual measured value
22 target?: string | number; // expected value or range
23 details: string;
24 failureReason?: string;
25 autoFixable: boolean;
26 autoFixApplied?: boolean;
27 }>;
28}6.5 Historical Validation Tracking
Every validation run is stored for trend analysis and refresh signal generation.
1CREATE TABLE validation_history (
2 id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
3 page_id UUID NOT NULL REFERENCES our_pages(id),
4 validated_at TIMESTAMP DEFAULT now(),
5 validation_trigger VARCHAR(20) NOT NULL, -- 'pre_publish', 'refresh_eval', 'scheduled_audit', 'manual'
6 passed BOOLEAN NOT NULL,
7 blocking_score VARCHAR(10) NOT NULL,
8 warning_score VARCHAR(10) NOT NULL,
9 check_results JSONB NOT NULL, -- full check array
10 info_metrics JSONB NOT NULL,
11 content_hash VARCHAR(64) NOT NULL, -- detect if content changed between validations
12 validation_version VARCHAR(20) NOT NULL
13);
14
15CREATE INDEX idx_val_page ON validation_history(page_id);
16CREATE INDEX idx_val_date ON validation_history(validated_at);
17CREATE INDEX idx_val_trigger ON validation_history(validation_trigger);Usage: The refresh evaluation system (Section 5) can query validation_history to detect score decay. If a page's warning score drops between validation runs (e.g., a link target was unpublished, breaking an internal link), this contributes to refresh urgency.
Scheduled audit: A weekly Trigger.dev job runs the full validation suite against all published pages. This catches degradation from external changes (broken links, updated competitor content, expired schema data).
6.6 Auto-Fix Pipeline
When a BLOCKING check fails, the auto-fix pipeline attempts resolution before escalating to human review.
Pipeline:
- Validation runs. If any BLOCKING check fails, collect all failures.
- For each failure marked
autoFixable: true, the Final Cleanup Agent applies the fix. - Validation re-runs on the fixed content.
- Maximum 3 fix-revalidate cycles.
- If all BLOCKING checks pass after auto-fix, proceed to publication.
- If any BLOCKING check still fails after 3 cycles, escalate to human with a report listing all remaining failures, fix attempts made, and specific guidance on what needs manual correction.
Auto-fixable checks and their fix strategies:
| Check | Fix Strategy |
|---|---|
| B1: Meta Title | Truncate to 60 chars at word boundary. Insert primary keyword if missing (prepend). |
| B2: Meta Description | Truncate to 160 chars at sentence boundary. Insert primary keyword if missing. |
| B3: Heading Hierarchy (partial) | Insert missing H2 parent for orphaned H3s. Cannot fix missing keyword in H1. |
| B7: Schema Validity | Regenerate schema from content metadata. This always works since schema is programmatic. |
| B9: Date Integrity | Set dates from content metadata in Supabase. |
7. Content Depth Validation — Detailed Design (Check W4)
This check closes the loop between the Brief Agent's competitive gap analysis and the Writer Agent's actual output. It ensures the draft covers what the brief specified.
7.1 How It Works
The check compares the approved brief's outline against the draft's actual heading structure and section content.
Input:
- Approved brief outline (from
content_briefs.outlineJSONB field) - Draft content (markdown with heading structure)
Validation logic:
1For each H2 in brief.outline:
2 1. Find matching H2 in draft (fuzzy string match, >70% similarity threshold)
3 2. If no match found: FAIL — "Brief section '[heading]' missing from draft"
4 3. If match found:
5 a. Count words in draft section
6 b. Compare to brief's suggestedWordCount for that section
7 c. If actual < (suggested × 0.8): WARNING — "Section '[heading]' is
8 [X]% below target word count"
9 4. Check that H3 subsections specified in brief exist under this H2
10
11Report:
12 - sections_covered: [count] / [total brief sections]
13 - sections_missing: [list]
14 - sections_underweight: [list with actual vs target]
15 - coverage_percentage: sections_covered / total × 100Threshold: Coverage percentage must be >= 85% to pass. Below 85% triggers a WARNING.
7.2 Why This Is a WARNING, Not BLOCKING
Content depth is a quality signal, not a binary pass/fail. A writer may deliberately merge two brief sections or cover a topic differently than outlined if they discover better framing during writing. Blocking publication for structural deviation would create false negatives. The WARNING surfaces the gap for human review without halting the pipeline.
8. Image Placement Rules
8.1 Writer Agent Image Markers
The Writer Agent outputs image placement markers in the following format:
1[IMAGE: {description of what should go here} | alt: {suggested alt text basis}]The description tells the human image placer what type of image fits. The alt field gives a starting point for alt text (human refines this).
8.2 Placement Rules
| Rule | Specification |
|---|---|
| Hero image | Required on every content type. Placed immediately after the TL;DR/Results box, before the first body paragraph. |
| Density floor | Minimum 1 image per 800 words of body content. |
| Section gap | No more than 2 consecutive H2 sections without an image between them. |
| Minimum per type | Blog: 3, Listicle: 1 per item + hero, Guide: 5, How-to: 1 per step + hero, Comparison: 1 per product + hero, Case study: 3, Pillar: 4, Glossary: 2 |
| Image type | AI-generated images relevant to the page content. |
| Format requirements | WebP preferred (with JPEG fallback). Max 500KB per image. Explicit width and height in HTML attributes. loading="lazy" on all images except hero. |
| Alt text | Written by human during image placement. Must be descriptive and include relevant keywords naturally. 10-125 characters. Must not start with "Image of" or "Picture of." |
8.3 Schema for Images
Every image maps to an ImageObject in the page schema. The hero image is referenced by the content type schema's image property. Step images in how-tos are referenced by their corresponding HowToStep.image.
9. Open Questions for Review
| # | Question | Impact | Recommended Default |
|---|---|---|---|
| 1 | Should the speakable CSS selectors be validated against actual deployed HTML, or only against the markdown template spec? Deployed HTML validation requires a post-render check. | Speakable schema accuracy | Validate against template spec at build time. Add deployed HTML validation as a Phase 2 enhancement. |
| 2 | The comparison type allows Consul as one of the compared products. Should there be a review flag for comparisons that mention Consul directly, to ensure objectivity? | Brand credibility | Yes. Any comparison mentioning Consul should have a requires_objectivity_review: true flag on the content plan item. |
| 3 | For the glossary batch build (20-40 terms), should terms be identified by the Strategy Agent from SERP extraction data, or manually curated? | Glossary relevance | Hybrid. Strategy Agent proposes terms from PAA and SERP data. Human curates final list. |
| 4 | Should validation history be retained indefinitely, or pruned after a retention period? | Storage | Retain indefinitely. Validation records are small (JSONB per check, ~2-5KB per run). Annual storage for 500 pages × 52 weekly audits = ~130MB. Negligible. |
| 5 | The auto-fix pipeline for meta title/description involves prepending keywords. Should there be a "preferred format" template per content type (e.g., "[Keyword]: [Benefit] | Consul")? | Meta tag consistency and brand |
End of Addendum #2
Next addendum: Hierarchical Summary Generation — defining how LangExtract extraction outputs are aggregated into navigable Level 0-3 summaries for agent consumption.