Beyond Authority/ build-spec v1.0
Google Search Essentials ↗

BUILD SPECIFICATION · v1.0 · ENGINEERING HANDOFF

Beyond AuthorityA self-improving, multi-agent content authority platform.

This document is the developer-ready technical specification for an autonomous content operating system that researches, plans, writes, fact-checks, enriches, optimizes, scores, publishes, and refreshes content at programmatic scale, while remaining structurally compliant with Google's people-first and scaled-content-abuse policies. Human involvement is designed to converge to review + approve per article.

Anti-hallucination invariant

No statistical claim, study citation, expert quote, regulated-domain assertion, or numeric fact may be published unless it carries a verified source URL, an extracted snippet, and a confidence score above the publish threshold. This is enforced at the database level (publish-blocking constraint), not as an editorial preference. See §6.

§ 01

Executive architecture overview

The system is organized as a one-way pipeline with three feedback loops. A demand layer generates topic opportunities; a production layer (multi-agent) converts opportunities into publish-ready drafts; a distribution layer publishes to WordPress and packages for AI extraction; a learning layer ingests GA4, Search Console, and AI-citation signals to refresh winners and prune losers.

System diagram

End-to-end data flow

  1. A scheduled worker pulls SERP, PAA, trends, and competitor deltas → upserts topic_opportunities.
  2. Opportunities scoring above threshold are enqueued as brief_jobs.
  3. The brief generator produces a structured content_brief (intent, entities, outline, required claims, target schema types).
  4. Research agent fans out searches (Perplexity Sonar, Google CSE, domain-restricted) and persists source_documents with extracted snippets.
  5. Writer agent drafts the article section-by-section, citing source IDs inline as machine tokens ([[src:42]]).
  6. Fact-check agent extracts claims, classifies them, and rejects unsupported factual / statistical / regulated claims (publish-blocking).
  7. Authority + SEO packaging agents inject E-E-A-T signals, GEO blocks, JSON-LD, internal links.
  8. QA agent scores 0–100. <80 revise, 80–89 human review, 90+ auto-eligible for publish queue.
  9. WordPress publisher pushes draft → human one-click approval → live → IndexNow ping.
  10. Performance ingester correlates article_id ↔ GSC query ↔ GA4 session ↔ AI citation mention; winners get refresh tasks, losers get rewrite or noindex tasks.

§ 02

Module-by-module technical design

The 14 modules are listed in pipeline order. Each module has a single responsibility, a typed input contract, a typed output contract, and is independently retryable.

M1

Topic Opportunity Miner

Purpose. Continuously discover ranked topic opportunities by combining SERP data, PAA, trends, and competitor deltas.

Inputs / outputs.

// input
{ niche_id: string, run_window: "daily" | "weekly" }
// output -> topic_opportunities[]
{
  id, query, intent: "informational"|"commercial"|"transactional"|"navigational",
  serp_difficulty: 0-100, est_volume: number, paa: string[],
  competitor_gap: { competing_urls: string[], avg_word_count: number, missing_subtopics: string[] },
  opportunity_score: 0-100, source_signals: object
}

External APIs / models. DataForSEO or Ahrefs/Semrush API · Google Custom Search · Google Trends (unofficial pytrends) · Reddit/Quora scrapers via official APIs

Failure modes. Vendor rate limit → exponential backoff with jitter; partial run accepted; opportunities never overwrite, only upsert with new run_id.

Integration. Writes to topic_opportunities; M2 (Brief generator) consumes top-N by opportunity_score.

M2

Brief Generator

Purpose. Convert a selected opportunity into a structured, machine-actionable brief.

Inputs / outputs.

// output -> content_briefs
{
  id, opportunity_id, primary_keyword, secondary_keywords[],
  search_intent, target_persona, angle, outline: [{h2, h3s[], required_entities[], required_claims[]}],
  schema_types: ("Article"|"FAQPage"|"HowTo"|"QAPage")[],
  word_count_target: number, internal_link_targets[], readability_target: "grade-8"
}

External APIs / models. Lovable AI Gateway with google/gemini-3-flash-preview by default; google/gemini-2.5-pro for high-stakes briefs.

Failure modes. If model returns invalid JSON, retry with structured output (tool calling, see §5 prompts-as-contracts). Hard fail → flag for human.

Integration. M3 research agent reads required_claims to seed search queries.

M3

Research Agent

Purpose. Gather authoritative source material per required claim, persist with provenance.

Inputs / outputs.

// output -> source_documents
{ id, brief_id, url, domain, domain_authority, fetched_at, snippet, full_text_hash,
  matched_claim_id, source_class: "primary"|"secondary"|"tertiary", confidence: 0-1 }

External APIs / models. Perplexity Sonar (grounded search) · Google Programmable Search · direct fetch with respect for robots.txt · arXiv / PubMed / SEC / .gov APIs for regulated domains.

Failure modes. If <2 primary sources found for a regulated claim, mark claim as ungrounded → fact-check agent will block publish.

Integration. Writes source_documents linked to claim IDs; M4 writer agent only references stored source IDs.

M4

Writer Agent

Purpose. Compose the article section-by-section using only stored sources.

Inputs / outputs.

// output -> drafts
{ id, brief_id, version, body_markdown, sections[], inline_citations: [{anchor, source_id}],
  word_count, reading_grade }

External APIs / models. google/gemini-2.5-pro or openai/gpt-5 via Lovable AI Gateway; reasoning effort 'medium'.

Failure modes. If a section references a source_id not present in source_documents → hard reject, regenerate that section only.

Integration. M5 fact-check, M6 authority injection consume the draft.

M5

Fact-Check Agent

Purpose. Extract every claim, classify, validate, block publish on failure. See §6.

Inputs / outputs.

// output -> claim_validations
{ id, draft_id, claim_text, class, supporting_source_ids[], confidence, status: "pass"|"warn"|"block" }

External APIs / models. Lovable AI for extraction; deterministic verifier scripts for numbers (regex + cross-source agreement).

Failure modes. Any 'block' status sets draft.publish_blocked = true at the DB level (CHECK constraint).

Integration. Sets gating flag read by M11 publisher.

M6

Authority Injection Agent

Purpose. Add E-E-A-T signals: author bio, methodology block, primary-experience markers, citations footer.

Inputs / outputs.

Mutates draft.body_markdown, populates draft.author_block, draft.methodology_block, draft.references[].

External APIs / models. Internal author registry; Lovable AI for experience-narrative drafting.

Failure modes. Missing author profile → fall back to editorial team author with reviewer attribution.

Integration. Outputs feed M7 SEO packaging.

M7

SEO Packaging Agent

Purpose. Generate title tag, meta description, slug, H1, excerpt, alt text, JSON-LD payloads, internal-link plan. See §7.

Inputs / outputs.

{ title_tag (≤60), meta_description (≤155), slug (kebab), h1, excerpt (≤160),
  jsonld[]: schema.org payloads, internal_links: [{anchor, target_url}], image_alts[] }

External APIs / models. Lovable AI; schema.org validator (deterministic); internal-link graph query.

Failure modes. Title >60 chars → deterministic truncator; invalid JSON-LD → reject, regenerate.

Integration. Output stored on draft; M8 GEO layer adds answer-first blocks.

M8

GEO / AI Visibility Agent

Purpose. Inject answer-first paragraph, key-takeaways, FAQ block, definitions, bottom-line. See §8.

Inputs / outputs.

Mutates body to ensure every required GEO block is present and within token-extractable lengths.

External APIs / models. Lovable AI; deterministic block-presence linter.

Failure modes. Linter failure → regenerate missing block only.

Integration. Feeds M9 QA + scoring.

M9

QA + Scoring Engine

Purpose. Compute weighted 0–100 score across 10 dimensions; route based on threshold. See §9.

Inputs / outputs.

// output -> quality_scores
{ draft_id, dimension_scores: {factuality, originality, depth, readability, eeat,
  geo_extraction, schema_validity, internal_linking, brand_voice, intent_match},
  total: 0-100, decision: "publish_ready"|"human_review"|"revise" }

External APIs / models. Mix of deterministic checks + Lovable AI rubric scoring (gpt-5-mini for cost).

Failure modes. Score 50–79 → loop back to writer with diff prompt; <50 → archive + alert.

Integration. publish_ready drafts enter publish_queue.

M10

Plagiarism + Duplicate-Topic Detector

Purpose. Block near-duplicate publication; ensure originality.

Inputs / outputs.

Returns similarity score vs internal corpus (pgvector cosine) and external (Copyscape/Originality.ai).

External APIs / models. Originality.ai or Copyscape API; pgvector embeddings (text-embedding-3-large equivalent).

Failure modes. Internal similarity >0.85 to existing slug → block, propose merge/refresh instead.

Integration. Gating check before publish_queue.

M11

WordPress Publisher

Purpose. Create draft post via REST, upload media, assign taxonomy, inject schema. See §10.

Inputs / outputs.

Inputs: approved draft. Outputs: wp_post_id, permalink, status='draft'.

External APIs / models. WordPress REST /wp/v2/posts, /wp/v2/media; Yoast or RankMath compatible meta fields.

Failure modes. WP 5xx → retry with backoff; permanent failure → put draft back in queue, alert.

Integration. Human one-click approval flips status to 'publish'.

M12

Indexing & Distribution

Purpose. Sitemap regen, IndexNow ping, social repurposing.

Inputs / outputs.

Triggers on post status=publish.

External APIs / models. IndexNow (Bing/Yandex), Google Indexing API where eligible (job postings / livestream only — otherwise rely on sitemap), buffer/zapier for social.

Failure modes. IndexNow non-200 → log; never block downstream.

Integration. Notifies Learning layer to begin tracking.

M13

Performance Ingester

Purpose. Pull GA4 + Search Console + AI-citation signals; correlate to articles.

Inputs / outputs.

Writes performance_metrics rows daily.

External APIs / models. GA4 Data API, Search Console API, custom AI citation tracker (see §11).

Failure modes. API quota → spread across hours; missing data day → mark gap, do not extrapolate.

Integration. Drives Learning layer decisions.

M14

Refresh + Expansion Agent

Purpose. Identify winners (refresh) and gap clusters (expand). Generate new opportunities or refresh tasks.

Inputs / outputs.

Outputs new topic_opportunities or refresh_jobs referencing existing article_id.

External APIs / models. Internal queries on performance_metrics + Lovable AI for cluster naming.

Failure modes. Insufficient data (<28 days) → defer.

Integration. Closes the loop back to M1/M2.

§ 03

Data model (Postgres / Supabase)

Schema is normalized; vector embeddings live in a sibling table to avoid bloating row width. All tables have created_at, updated_at, and tenant_id for multi-niche use. RLS is enabled on every table; access is mediated by a has_role() security-definer function (see Lovable's user-roles guidance).

Core tables

-- Topic discovery
topic_opportunities (
  id uuid pk, tenant_id uuid, query text, intent text,
  serp_difficulty int, est_volume int, paa jsonb,
  competitor_gap jsonb, opportunity_score numeric,
  source_signals jsonb, status text default 'new',
  created_at timestamptz, updated_at timestamptz
)
INDEX (tenant_id, opportunity_score desc), INDEX (status);

content_briefs (
  id uuid pk, opportunity_id uuid fk, primary_keyword text,
  secondary_keywords text[], search_intent text, persona text,
  outline jsonb, schema_types text[], word_count_target int,
  required_claims jsonb, status text default 'draft'
)

source_documents (
  id uuid pk, brief_id uuid fk, claim_id uuid null,
  url text, domain text, domain_authority int,
  source_class text check (source_class in ('primary','secondary','tertiary')),
  snippet text, full_text_hash text, fetched_at timestamptz,
  confidence numeric check (confidence between 0 and 1)
)
UNIQUE (brief_id, url);

drafts (
  id uuid pk, brief_id uuid fk, version int, body_markdown text,
  body_html text, word_count int, reading_grade numeric,
  author_id uuid, methodology_block text,
  seo jsonb,            -- title_tag, meta_description, slug, h1, excerpt, image_alts
  jsonld jsonb,         -- array of schema.org payloads
  internal_links jsonb,
  publish_blocked boolean default true,
  status text default 'in_progress'
)

claim_validations (
  id uuid pk, draft_id uuid fk, claim_text text,
  class text check (class in
    ('opinion','observation','common_knowledge','factual','statistical','regulated')),
  supporting_source_ids uuid[], confidence numeric,
  status text check (status in ('pass','warn','block'))
)

quality_scores (
  id uuid pk, draft_id uuid fk, dimension_scores jsonb,
  total numeric, decision text, scored_at timestamptz
)

publish_queue (
  id uuid pk, draft_id uuid fk unique, scheduled_at timestamptz,
  wp_post_id bigint null, permalink text null, state text
)

performance_metrics (
  id uuid pk, article_id uuid fk, date date,
  gsc_clicks int, gsc_impressions int, gsc_ctr numeric, gsc_position numeric,
  ga4_sessions int, ga4_engaged_sessions int, ga4_avg_engagement_sec numeric,
  ai_citations jsonb -- {chatgpt: n, perplexity: n, google_aio: n}
)
UNIQUE (article_id, date);

embeddings (
  id uuid pk, owner_table text, owner_id uuid,
  embedding vector(1536)
)
INDEX USING ivfflat (embedding vector_cosine_ops);

-- User roles per security guidance
app_role enum ('admin','editor','reviewer','viewer');
user_roles (id uuid pk, user_id uuid fk auth.users, role app_role,
  unique(user_id, role));

Publish-blocking constraint

drafts.publish_blocked defaults to true. The fact-check agent is the only writer permitted to flip it to false (enforced by an RLS policy keyed to a service role). The publish queue's check function rejects any draft with publish_blocked = true.

§ 04

Orchestration layer

Recommended primary: Temporal or Inngest over n8n / Make.com for the production pipeline. Reason: durable workflows, native retries, versioning, and idempotency keys are first-class — critical when a single article traverses 9+ stateful steps. n8n / Make remain excellent for the periphery (social repurposing, Slack alerts, Sheets exports). Keep the user's preferred tools as a documented fallback.

Queue topology

  • q.discover — daily cron → M1 miner
  • q.brief — opportunity_score > threshold → M2
  • q.research — fan-out per required_claim
  • q.writeq.factcheckq.authority q.seoq.geoq.score
  • q.publish — gated on publish_blocked = false AND score ≥ 90 OR human approval
  • q.refresh — driven by performance signals

Idempotency & retries

  • Every job carries a deterministic key: {stage}:{draft_id}:{version}.
  • Writer/agent calls store the prompt + model + temperature hash in agent_runs; identical hash returns cached result within 24h.
  • Retries: 3 attempts with jitter (1s, 8s, 60s); on permanent failure → dead-letter queue + Slack alert + dashboard surface.
  • Each external API call (OpenAI, Perplexity, WP REST) wrapped in a circuit breaker (50% error rate over 1 min trips for 5 min).

§ 05

Multi-agent design

Agents are not autonomous loops; they are typed function calls against the Lovable AI Gateway with rigid input/output JSON schemas (tool calling). The orchestration layer — not the model — decides the next step. This eliminates the unbounded token consumption and reasoning drift typical of agent frameworks.

Roles

AgentDefault modelHand-off contract
ResearchPerplexity Sonar + gemini-3-flash-previewReturns source_documents[] linked to claim IDs.
Writergpt-5 or gemini-2.5-proReturns {sections[], inline_citations[]}; every citation must be a known source_id.
Fact-checkgemini-2.5-proReturns claim_validations[]; deterministic verifier double-checks numbers.
Authority injectiongemini-3-flash-previewReturns {author_block, methodology_block, references[]}.
SEO packaginggemini-3-flash-previewReturns {seo, jsonld, internal_links} validated by deterministic linter.
QA scoringgpt-5-miniReturns dimension scores + decision.

Prompts as contracts

Each agent has a versioned prompt file plus a Zod/JSON-schema for its output, enforced via tool-calling. Example for the writer:

tools: [{
  type: "function",
  function: {
    name: "submit_section",
    parameters: {
      type: "object", required: ["heading","markdown","citations"],
      properties: {
        heading: { type: "string" },
        markdown: { type: "string", maxLength: 8000 },
        citations: {
          type: "array",
          items: { type: "object", required: ["anchor","source_id"],
            properties: {
              anchor: { type: "string" },
              source_id: { type: "string", format: "uuid" }
            }}
        }
      }
    }
  }
}],
tool_choice: { type: "function", function: { name: "submit_section" } }

Shared memory

Agents do not pass freeform context. Memory is the database. Each agent receives a query handle (brief_id / draft_id) and reads only the rows it needs. This makes runs reproducible and debuggable.

§ 06

Factual validation pipeline

Classification rules

  • Opinion — first-person stance, hedged language → no source required.
  • Observation — descriptive, non-numeric, non-controversial → no source required.
  • Common knowledge — verifiable in any general encyclopedia → no source required, but flagged for review on first occurrence per topic.
  • Factual — specific non-numeric claim → ≥1 secondary source.
  • Statistical — any number, percentage, rank, year → ≥2 independent sources, numeric agreement within tolerance, deterministic regex check.
  • Regulated (YMYL) — health, legal, financial, safety → ≥2 primary sources from a domain allowlist (e.g. nih.gov, cdc.gov, sec.gov, who.int, peer-reviewed journals).

Anti-hallucination guarantees

  1. The writer agent cannot emit a citation that isn't already in source_documents for that brief — schema rejects unknown source_ids.
  2. The fact-checker re-fetches each source URL and confirms the snippet still appears (catches hallucinated URLs and drift).
  3. For statistics, the verifier extracts the number from the cited snippet and compares it to the number in the draft. Mismatch → block.
  4. Expert quotes require a verifiable URL of the original utterance (interview, paper, press release). No fabricated experts.
  5. Database constraint: a draft cannot enter publish_queue while any claim_validations.status = 'block' exists for it.

This aligns with Google's guidance that scaled content is acceptable only when it is original, accurate, and people-first; mass-produced unverified content falls under scaled content abuse.

§ 07

SEO + AI extraction packaging

Generation rules (deterministic where possible)

FieldRule
title_tag≤60 chars, primary keyword in first 50 chars, brand suffix optional. Truncated deterministically if model overruns.
meta_description≤155 chars, includes primary keyword + value-prop verb, no clickbait. Note: Google may rewrite descriptions; this is acceptable.
slugkebab-case, ≤60 chars, stop-words removed, ASCII only.
h1Distinct from title_tag where useful; one H1 per page (enforced by linter).
excerpt≤160 chars; doubles as og:description when not overridden.
image_altsDescriptive, no keyword stuffing; required for every non-decorative image.
internal_links3–8 contextual links to existing articles in the same cluster; anchor text varied (no exact-match repetition).
canonicalSelf-referential by default; cross-canonical only on intentional duplicate variants.
author blockReal author with bio, photo, credentials, social links — supports E-E-A-T.

JSON-LD schema selection

  • Article on every post (with author, datePublished, dateModified, publisher).
  • BreadcrumbList on every post.
  • FAQPage when the article contains a FAQ block of distinct Q→A pairs that are visible on the page. Note: as of August 2023 Google restricts FAQ rich results to authoritative government and health sites; structured data remains valuable for AI extraction even when rich results are not shown (source).
  • QAPage for single-question pages.
  • Organization on the homepage / about page only (publisher reference inside Article handles the rest).
  • HowTo only where genuinely procedural; same eligibility caveat as FAQ.

Meta keywords tag — explicitly excluded

The system never emits a <meta name="keywords"> tag. Google has stated publicly that it does not use the meta keywords tag for ranking (official post), and including it leaks the keyword strategy to competitors with zero ranking benefit.

§ 08

AI visibility / GEO layer

Google AI Overviews, ChatGPT search, Perplexity, and Bing Copilot extract short, attributable spans of text. The GEO layer guarantees every article exposes those spans in a stable, predictable place. Note: exact inclusion factors for AI Overviews are not publicly documented and evolve frequently — the rules below are the empirically-supported best practices, not a guarantee of citation.

Required blocks (linter-enforced)

  1. Answer-first paragraph — 40–60 words immediately after H1, directly answering the primary query.
  2. Key takeaways — 3–5 bullets, each ≤20 words, fact-dense.
  3. Concise definition block — for any defined entity, provide a one-sentence dictionary-style definition.
  4. FAQ block — 4–8 Q&A pairs phrased exactly as users ask, mirrored in FAQPage JSON-LD.
  5. Bottom-line block — at end of article, restates the answer with the strongest supporting fact.

Entity consistency rules

  • Entity names use a canonical spelling registered in an internal entity table; the writer agent receives the canonical form.
  • Author, publisher, organization names match across JSON-LD, on-page byline, and sameAs links to Wikipedia / Wikidata / LinkedIn.
  • sameAs links are populated for the Organization and Person schema where verifiable URLs exist.

§ 09

Quality scoring engine

DimensionWeightHow measured
Factuality20% of factual/statistical/regulated claims with status='pass'.
E-E-A-T signals12Author bio + credentials + methodology + citation density.
Originality121 − max similarity (internal pgvector + Originality.ai).
Depth10Coverage of brief.required_entities & required_claims.
Intent match10Rubric scoring vs SERP intent of primary keyword.
GEO extraction readiness10Linter pass on all 5 required blocks.
Schema validity8schema.org validator + Google rich-results test (where applicable).
Internal linking63–8 contextual links, varied anchors, all 200 OK.
Readability6Flesch-Kincaid grade vs target (default grade 8).
Brand voice6Embedding-similarity to brand-voice corpus > threshold.

Total = sum (max 100). Routing: <80 → revise loop (max 3); 80–89 → human review queue; ≥90 → publish-ready.

Learning loop: performance_metrics joined to quality_scores monthly; weights re-fit via linear regression against composite outcome (clicks × engaged-session-rate × AI-citation count). Weight changes require human approval.

§ 10

WordPress integration

REST endpoints

  • POST /wp-json/wp/v2/media — upload featured + inline images (Cloudinary-hosted source, downloaded server-side then re-uploaded to host on WP for SEO ownership).
  • POST /wp-json/wp/v2/posts — create post with status: 'draft'.
  • POST /wp-json/wp/v2/categories, /tags — upsert taxonomy.

Field mapping

{
  title: draft.seo.h1,
  content: draft.body_html, // includes injected JSON-LD <script type="application/ld+json">
  excerpt: draft.seo.excerpt,
  slug: draft.seo.slug,
  status: "draft",
  author: wp_author_id,
  featured_media: wp_media_id,
  meta: {
    // Yoast
    _yoast_wpseo_title: draft.seo.title_tag,
    _yoast_wpseo_metadesc: draft.seo.meta_description,
    _yoast_wpseo_canonical: draft.seo.canonical,
    // RankMath equivalents (set both — only one will be active)
    rank_math_title: draft.seo.title_tag,
    rank_math_description: draft.seo.meta_description,
    rank_math_canonical_url: draft.seo.canonical
  }
}

One-click approval UX

Dashboard shows a side-by-side: rendered preview + diff vs last version + claim-validation summary. Single button posts {status:'publish'} to WP and emits an event into the indexing queue.

§ 11

Indexing & performance loop

  • Sitemap regenerated on publish; submitted via Search Console API.
  • IndexNow ping to Bing/Yandex on publish + on substantive update.
  • Google Indexing API only for eligible types (JobPosting, BroadcastEvent). Otherwise rely on sitemap + crawl.
  • GA4 + GSC ingested daily into performance_metrics.
  • AI citation tracker: a worker runs the article's primary query against ChatGPT (web), Perplexity, and (where accessible) Google AI Overviews via headless browser; parses cited URLs; increments counters. Caveat: this is a best-effort signal — AI surfaces are non-deterministic and detection methodology must be re-validated quarterly.
  • Winner refresh: articles with rising impressions but flat/falling CTR → meta + intro rewrite. Articles with rising AI citations → expand cluster.
  • Loser handling: <28-day data is held; after 90 days with bottom-quartile performance → rewrite or noindex (decision routed to reviewer).

§ 12

Dashboard + control panel

Screens

  1. Pipeline — kanban: Discovered → Briefed → Drafting → Fact-check → Scoring → Review → Published. Each card shows score, blockers, ETA.
  2. Topic Bank — sortable table of topic_opportunities with manual promote/demote.
  3. Draft Queue — review UI with side-by-side preview, claim-validation drawer, one-click approve.
  4. Performance — per-article: GSC clicks/impressions, GA4 engagement, AI-citation counts; cluster rollups.
  5. Controls — global throttles: max articles/day, niche on/off, agent model overrides, tone slider (informative ↔ persuasive), authority intensity (light ↔ heavy citation), emotional intensity (neutral ↔ strong stance).
  6. Audit log — every agent run, prompt hash, model, cost, decision.

§ 13

Tech stack specification

LayerRecommendedRationale / fallback
Frontend dashboardNext.js 15 (App Router) or TanStack StartSSR for auth-gated review UI. TanStack Start is the Lovable default and works well here.
Backend / agentsPython (FastAPI) for agent workers; Node.js for WP REST + dashboard APIPython ecosystem (instructor, pydantic, pgvector clients) is stronger for typed LLM I/O. Node is fine as fallback.
OrchestrationTemporal or InngestDurable workflows. n8n / Make.com retained for peripheral automations.
LLM accessLovable AI Gateway (Gemini + GPT-5 family)Single key, no direct provider integration; default google/gemini-3-flash-preview, escalate to gpt-5 / gemini-2.5-pro for writing & fact-check.
Grounded searchPerplexity Sonar APICitations included; falls back to Google Programmable Search.
DatabaseSupabase Postgres + pgvectorRLS, auth, storage, edge functions in one. User roles enforced via has_role() security definer per Lovable guidance.
CMSWordPress RESTAs specified.
MediaCloudinaryTransformations + AVIF/WebP delivery; copy to WP for canonical hosting.
AnalyticsGA4 + Search Console APIsDaily ingest into performance_metrics.
PlagiarismOriginality.ai (paid) + pgvector internalInternal-first, external on shortlist.
ObservabilitySentry + OpenTelemetry → GrafanaPer-agent traces; cost dashboards.

§ 14

Compliance + guardrails

  • People-first content: every brief must articulate a target persona and a unique angle. Self-assessment per Google's helpful-content guidance is run as a rubric inside the QA scoring agent.
  • Scaled content abuse: every article carries verified authorship, original research or original synthesis, and passes the factuality gate. Pure aggregation/summarization without added value is rejected at brief stage.
  • Mobile-first indexing: WP theme audited for mobile parity; no content hidden from mobile.
  • Plagiarism + duplicate-topic detection: internal pgvector cosine + Originality.ai; threshold 0.85 internal, 15% external match.
  • Brand-voice enforcement: voice corpus embedded; QA dimension scores semantic similarity vs corpus.
  • Disclosure: AI-assisted content is allowed by Google when it meets E-E-A-T and helpful-content criteria; we additionally surface human reviewer name on every published post.

§ 15

Phased build roadmap

Phase 1 — MVP (weeks 0–8)

  • Single niche, single tenant.
  • Modules M1 (lite), M2, M3, M4, M5, M7, M9, M11, M12.
  • No social repurposing, no AI citation tracking, no multi-agent escalation (single writer model).
  • Success: 20 publish-ready articles/week, ≥80 mean QA score, <10 min mean human review per article, zero blocked-claim escapes to publish.

Phase 2 — Authority scale (weeks 8–20)

  • Add M6 authority injection, M8 GEO layer, M10 plagiarism, M13 + M14 learning loop.
  • Competitor gap analyzer, social repurposer, local SEO expansion, AI citation tracker.
  • Multi-tenant niches; per-niche tone/authority controls.
  • Success: 60–100 articles/week, ≥85 mean QA, <5 min mean review, measurable cluster topical authority growth (impressions and average position trending up across the cluster, not single posts), AI-citation count rising month-over-month.

Phase 3 — Self-tuning (weeks 20+)

  • Weight re-fitting from performance_metrics; automated cluster expansion; experimentation framework (A/B titles, intros, schema).

§ 16

Output KPIs

KPITargetMechanism
High-quality articles / week20 (P1) → 100 (P2)Throughput governed by orchestration concurrency + agent cost budget.
Mean human review time / article<5 minSide-by-side review UI + claim-validation drawer; only ≥90-score drafts in queue.
Blocked-claim escape rate0DB-level publish-block constraint + reverifier on publish.
Topical authority growth+ cluster impressions, − avg position monthlyGSC ingest + cluster rollups in dashboard.
AI visibilityCitation count up MoM in ChatGPT + Perplexity + AIO (where measurable)AI citation tracker; quarterly methodology revalidation.
Cost / publish-ready articleTracked, decreasing trendCost dashboard from agent_runs.

Closing note for the engineering team

Build the publish-blocking constraint and the source-id citation contract first. Every other feature can be staged, but those two are what make the system structurally safe against the failure modes (hallucination, scaled-content abuse) that would otherwise compound at scale.