Ting Blueprint · 002

Build an SEO Automation System

A practical technical reference for discovering search opportunities, grounding bilingual content in approved evidence, validating every revision, publishing safely and monitoring performance.

Difficulty
Advanced
Estimated build time
5–10 days
Architecture type
Guardrailed workflow orchestration
Updated
July 2026
Language
English
On this page
Reference boundary

What this educational system demonstrates

This Blueprint describes a reusable pattern for evidence-grounded bilingual content operations. Scheduled jobs discover demand, compare existing pages, gather verifiable sources, draft both locales, enforce independent policy gates, publish automatically only when every signal passes, and keep measuring each page. The records and identifiers are fictional examples, and the design is not a description of Ting’s private systems.

Included

  • Demand discovery with existing-content deduplication
  • Evidence records linked to every factual clause
  • Paired English and Arabic revisions
  • Automatic publication, verification, monitoring and lifecycle actions

Not included

  • Ting’s production architecture or provider choices
  • Private prompts, scoring rules or internal thresholds
  • Real customer, analytics or credential data
  • A guarantee of rankings, traffic or revenue
Reference design

Resumable architecture and state machine

A small state machine defines legal transitions, while a scheduler advances one bounded step per invocation. Durable storage holds leases, evidence, decisions and retries so interrupted work resumes safely. This is one educational pattern; teams should adapt the states and limits to their own risk, volume and platform.

Reference workflow from search opportunity discovery through content and evidence checks, bilingual drafts, automatic quality gates, publishing and monitoring.
Swipe horizontally to explore the full workflow.A simplified, signal-gated SEO reference workflow; the state diagrams and contracts below define the educational implementation behavior.
MermaidResumable architecture and state machine
01Opportunity
02Existing Content
03Evidence
04Bilingual Draft
05Quality Gates
06Policy Decision
07Publication
08Monitoring
View Mermaid source
flowchart LR
    T["Scheduled Trigger"] --> A["Discovery & Eligibility"]
    A --> B["Evidence Research"]
    B --> C["Bilingual Brief & Drafts"]
    C --> D["Claim, Quality & SEO Gates"]
    D --> E["Publish & Verify"]
    E --> F["Monitor & Lifecycle"]
    F -- "refresh / merge / noindex" --> B
MermaidJob state transitions
01Discovered
02Eligible
03Researched
04Drafted
05Validated
06Ready to Publish
07Published
08Monitoring
View Mermaid source
stateDiagram-v2
    [*] --> DISCOVERED
    DISCOVERED --> ELIGIBILITY_CHECK
    ELIGIBILITY_CHECK --> CLUSTERING
    CLUSTERING --> RESEARCHING
    RESEARCHING --> EVIDENCE_READY
    EVIDENCE_READY --> BRIEF_GENERATING
    BRIEF_GENERATING --> DRAFTING
    DRAFTING --> CLAIM_VALIDATION
    CLAIM_VALIDATION --> QUALITY_VALIDATION
    QUALITY_VALIDATION --> SEO_VALIDATION
    SEO_VALIDATION --> READY_TO_PUBLISH
    READY_TO_PUBLISH --> PUBLISHING
    PUBLISHING --> PUBLISHED
    PUBLISHED --> MONITORING
    CLAIM_VALIDATION --> REPAIRING: unsupported claim
    SEO_VALIDATION --> REPAIRING: gate failed
    REPAIRING --> DRAFTING: bounded retries
    MONITORING --> REFRESH_REQUIRED: decay detected
    REFRESH_REQUIRED --> RESEARCHING: refresh cycle
    DRAFTING --> FAILED_RETRYABLE: provider error
    FAILED_RETRYABLE --> DRAFTING: backoff resume
Educational choices

Named reference stack

The example uses GitHub for version control, Postgres for workflow and evidence state, OpenRouter as a server-side model gateway, and a Web Hoster / Cloud Infrastructure for the application and schedules. These are educational reference choices, not claims about Ting’s production stack.

GitHub

Reference version control and CI for code, policy fixtures and deployment history.

Official documentation

Web Hoster / Cloud Infrastructure

Application runtime, scheduled triggers, secret injection, health checks and rollback.

Official documentation

Postgres

Illustrative durable store for topics, evidence, immutable revisions, decisions and lifecycle signals.

Official documentation

OpenRouter

An educational server-side model gateway choice with schema-constrained output, timeouts and fallback policy.

Official documentation

Scheduled Jobs + Application Functions

The reference runs discovery and worker schedules at configurable cadences; each tick performs one bounded step and reserves time to persist safely.

Portable layout

Reference repository, schedules and setup

The example keeps web routes and the content worker in one repository so contracts and tests evolve together. Discovery and worker schedules are illustrative: choose a cadence and runtime budget that match your own demand, provider limits and recovery objectives.

Project treeTEXT
reference-seo-system/
  app/api/cron/content/
    discovery/route.js      # scheduled opportunity discovery
    worker/route.js         # advance one due workflow step
  app/blog/[slug]/page.js   # render published articles
  src/seo/
    orchestrator.js         # lease a workflow and run one bounded step
    state-machine.js        # legal transitions for the reference flow
    repository.js           # leases, budgets and circuit breakers
    discovery.js            # demand discovery, scoring and deduplication
    research.js             # evidence retrieval and verification
    structured-output.js    # schema-constrained model calls
    policy.js               # automatic publication and lifecycle gates
    monitoring.js           # outcome checks and lifecycle signals
    search-console.js       # indexing and performance measurements
    *.test.js               # regression suites beside the modules
  hosting-config.example    # runtime schedules and resource limits
Install packagesSHELL
# Educational reference dependencies. Choose versions that match
# your application and review their official documentation.
npm install next react react-dom pg

# pg       -> reference Postgres repository
# Hosting  -> deploy to a Web Hoster / Cloud Infrastructure
.env.exampleENV
# .env.example — placeholder values only; never commit real secrets
DATABASE_URL=postgres://user:password@host:5432/database
MODEL_GATEWAY_API_KEY=replace_with_server_side_secret
CONTENT_CRON_SECRET=replace_with_random_bearer_token
CONTENT_DAILY_NEW_PAGE_LIMIT=replace_with_integer
CONTENT_MAX_MODEL_CALLS_PER_WORKFLOW=replace_with_integer
CONTENT_POLICY_VERSION=replace_with_version_identifier
Durable contracts

Topics, workflows, evidence and results

Reference tables persist each topic, source, validation result, transition and lifecycle signal. Nothing depends on a chat transcript. Use immutable revision records, idempotency keys and an audit trail so an automatic action can be explained, retried or rolled back.

Topic and workflow tablesSQL
-- Illustrative reference schema; adapt names to your system.
create table content_topics (
  id uuid primary key,
  query text not null,
  locale text check (locale in ('en','ar')),
  intent text,
  canonical_topic text,
  priority_score numeric
);

create table content_workflows (
  id uuid primary key,
  topic_id uuid references content_topics(id),
  current_state text not null,
  intended_action text,
  retry_count int default 0,
  failure_category text,
  idempotency_key text unique,
  locked_at timestamptz,
  next_review_at timestamptz
);
Evidence and validation tablesSQL
create table content_evidence_sources (
  id uuid primary key,
  workflow_id uuid references content_workflows(id),
  url text not null,
  publisher text,
  retrieved_at timestamptz,
  excerpt text,
  verification_status text      -- verified | retired
);

create table content_validation_results (
  workflow_id uuid,
  stage text,                   -- CLAIM | QUALITY | SEO | PUBLICATION
  decision text,                -- pass | repair | reject
  details jsonb
);

-- Every factual clause must map to retrieved evidence.
-- Unsupported clauses route to REPAIRING, never to publication.
state-machine.jsJAVASCRIPT
// src/seo/state-machine.js — educational reference example
export const WORKFLOW_STATES = Object.freeze([
  "DISCOVERED", "ELIGIBILITY_CHECK", "CLUSTERING",
  "EXISTING_CONTENT_CHECK", "RESEARCHING", "EVIDENCE_READY",
  "BRIEF_GENERATING", "BRIEF_READY", "DRAFTING", "DRAFTED",
  "CLAIM_VALIDATION", "QUALITY_VALIDATION", "SEO_VALIDATION",
  "REPAIRING", "READY_TO_PUBLISH", "PUBLISHING", "PUBLISHED",
  "MONITORING", "REFRESH_REQUIRED", "MERGE_REQUIRED",
  "REDIRECT_REQUIRED", "NOINDEX_REQUIRED", "REJECTED",
  "FAILED_RETRYABLE", "FAILED_FINAL"
]);

assertTransition("DRAFTED", "CLAIM_VALIDATION"); // allowed
assertTransition("DRAFTED", "PUBLISHED");        // throws
Worker loopJAVASCRIPT
// A scheduler on your Web Hoster / Cloud Infrastructure invokes
// this worker. One lease, one bounded step, then release.
export async function runContentWorker() {
  const workflow = await claimNextDueWorkflow();
  if (!workflow) return { ok: true, idle: true };

  try {
    await advanceOneStep(workflow);
  } catch (error) {
    await recordFailure(workflow, error); // backoff + circuit breaker
  }
  return { ok: true, workflowId: workflow.id };
}
Prevent cannibalization

Clustering and existing-content checks

Before drafting, compare locale, search intent, canonical topic, query overlap and content similarity against every eligible page. The deterministic outcome is create, refresh, merge or reject. A new URL is allowed only when it serves a distinct intent that an existing page cannot satisfy.

create

No strong page covers the same locale and intent.

refresh

One relevant page exists but coverage is partial or stale.

merge

Several pages compete for the same intent.

reject

Existing content is strong or the opportunity is ineligible.

Deterministic decisionJAVASCRIPT
// Compare locale, intent, canonical cluster and similarity
// before drafting. This function is deterministic and testable.
export function decideIntendedAction({ topic, livePages }) {
  const sameCluster = livePages.filter((page) =>
    page.locale === topic.locale &&
    page.canonicalTopic === topic.canonicalTopic
  );

  if (sameCluster.some((p) => p.coverage === "strong")) return "REJECT_TOPIC";
  if (sameCluster.some((p) => p.coverage === "partial")) return "REFRESH_EXISTING";
  if (sameCluster.length > 1) return "MERGE_INTO_EXISTING";
  return "CREATE_NEW";
}
Evidence before prose

Research and exact-claim grounding

Store retrieved sources before writing. The writer may use only supported excerpts, and a separate verifier maps every factual clause back to exact evidence. Missing, stale or contradictory support sends the revision to repair or rejection; model labels cannot bypass the ledger.

Claim validationJAVASCRIPT
// Re-extract every factual clause and verify the exact text
// against stored evidence instead of relying on model memory.
export async function validateClaims(workflowId, draft) {
  const evidence = await getVerifiedEvidence(workflowId);

  return extractClaims(draft).map((claim) => ({
    ...claim,
    status: evidence.some((row) =>
      claim.evidenceIds.includes(row.id) &&
      supportsExactClause(row.excerpt, claim.text)
    ) ? "supported" : "unsupported"
  }));
}
  • Allow official and primary sources according to policy.
  • Persist source title, retrieval time and excerpt.
  • Distinguish an unavailable source from an unsupported claim.
  • Never allow the model to invent a URL or evidence ID.
Localize meaning

Bilingual brief and drafting

One evidence-backed brief produces native English and Arabic revisions in the same translation group. Arabic is written naturally for Saudi readers while preserving the same supported facts, intent boundaries, internal-link purpose, canonical relationship and hreflang pairing.

01

Shared brief

Intent, audience, evidence, boundaries and required links.

02

Two native drafts

Each locale is written for its readers under the same claim boundaries.

03

Locale pairing

Each version carries correct canonical and hreflang relationships.

04

Drift review

Compare claims, numbers and promises across both locales.

Automatic, never unchecked

Signal-gated validation and publication

Deterministic checks and role-separated model reviews evaluate evidence coverage, quality, duplication, metadata, links, structured data and locale parity. Publication proceeds automatically only when every required signal passes. A disagreement blocks, repairs or rejects the revision; no manual queue is part of the publishing path.

Gate result contractJSON
{
  "workflow_id": "wf_reference_topic_en",
  "current_state": "SEO_VALIDATION",
  "intended_action": "CREATE_NEW",
  "locales": ["en", "ar"],
  "gates": {
    "claims": "pass",
    "quality": "pass",
    "seo": "pending",
    "publication_policy": "pending"
  },
  "retry_count": 0,
  "failure_category": null,
  "publishable": false
}
Every claim is supported
No duplicate intent
Valid title and description
Reachable internal links
Correct canonical and hreflang
Compatible structured data
Automated policy decision recorded
Public URL verified
Content has a lifecycle

Automatic monitoring, refresh, merge and noindex

Fresh Search Console and indexation measurements drive recurring lifecycle checks. Decay, overlap or loss of independent value can queue a refresh, merge, redirect or noindex action automatically, but only after minimum sample, confidence, destination-health and rollback gates pass. The system never defaults to the older URL.

keep

Content remains useful, accurate and distinct.

refresh

Evidence, coverage or performance needs an update.

merge

Multiple pages compete and should be consolidated.

noindex

The page no longer provides independent value.

Transparent failure

Scheduled endpoints and failure behavior

Protect scheduled routes with a server-side secret and return structured results. Classify retryable failures, use bounded backoff and circuit breakers, reserve time for persistence, and cap daily work. A timeout or provider outage must stop safely without publishing a partial revision or consuming an unrelated retry budget.

GET /api/cron/content/workerJAVASCRIPT
// app/api/cron/content/worker/route.js — simplified reference
export async function GET(request) {
  const token = request.headers.get("authorization");
  if (token !== "Bearer " + process.env.CONTENT_CRON_SECRET) {
    return Response.json({ error: "unauthorized" }, { status: 401 });
  }

  const result = await runContentWorker();
  return Response.json(result);
  // A revision is published automatically only after every policy signal
  // passes and the public URL is verified. Otherwise it repairs or stops.
}
Regression before scale

Tests beside the reference modules

Test legal transitions, evidence coverage, demand filtering, bilingual parity, publication rollback and lifecycle thresholds. Evaluation fixtures should include unsupported claims, prompt injection, DNS changes, stale measurements, duplicate intent, partial bilingual writes and failed public verification.

Critical regression casesJAVASCRIPT
// Illustrative regression cases for the reference implementation.
const cases = [
  ["illegal state transition", "throws"],
  ["unsupported factual clause", "REPAIRING"],
  ["duplicate intent detected", "MERGE_REQUIRED"],
  ["provider fails repeatedly", "circuit_breaker_open"],
  ["all publication signals pass", "PUBLISHED"],
  ["public URL verification fails", "automatic_rollback"],
  ["overlap exceeds merge threshold", "automatic_merge_queued"],
  ["lifecycle evidence is incomplete", "action_blocked"]
];

test.each(cases)("%s -> %s", async (scenario, expected) => {
  expect(await runFixture(scenario)).toEqual(expected);
});
Decision accuracy

Create, refresh, merge or reject matches the expected fixture.

Claim coverage

Share of factual clauses linked to valid evidence.

Locale parity

No changed numbers, promises or meaning between versions.

Publication safety

Zero publications before all policy gates and public verification pass.

Operational readiness

Web hosting, persistence and rollback

Run the application on a Web Hoster / Cloud Infrastructure with injected secrets, health checks, rate limits and monitored schedules. Keep durable state outside process memory, deploy immutable revisions, retain the last healthy version, and rehearse automatic rollback before enabling unattended publishing.

Durable state

Persist jobs, transitions, evidence and policy decisions outside process memory.

Bounded retries

Use idempotency keys, backoff and a dead-letter queue instead of open retries.

Observability

Track stage latency, cost, gate failures and job age.

Rollback

Keep the prior version, document rollback and reverify the public URL.

Operational ownership

Assign policy, publishing and incident owners without making routine publication wait on a manual queue.

Reference boundary

Security and intentional exclusions

Treat source pages as untrusted input, pin outbound evidence requests to validated HTTPS destinations, keep model and database credentials server-side, redact logs, and separate retrieval, publishing and lifecycle permissions. This Blueprint intentionally excludes Ting’s prompts, private integrations, production thresholds and security implementation details.

Least privilege

Separate source-reading permissions from publishing and lifecycle actions.

Untrusted input

Sanitize HTML and source instructions before model use.

Server secrets

Never expose keys or traces to the browser.

Request boundaries

Limit job rate, size and duration.

Safe logs

Redact secrets, personal data and private content.

Guardrailed autonomy

Do not refresh, merge or noindex until signal thresholds and rollback checks pass.