User Manual · 02 · The Content Engine
WholeReach — Automated Marketing System

The Content Engine

How real posts are written from real data — four content families, deterministic templates, and the honesty guard that never guesses.

Want to change the content?This page explains how the engine writes posts. For the exact steps to edit wording, add a new post type, or refresh the feed, see Playbooks 6–8.

Four content families

Every post belongs to one of four families. Each is fed by a real, independent data source.

FamilyWhat it postsFed by
Site featureSpotlights a site in the network with its real description and link.the network site list (~177 sites)
AI-marketing tipA genuine marketing principle drawn from our skills library, with a link to more.the marketing-skills library (47 skills)
Milestone / winAnnounces a real improvement in a site's quality score ("up 30 this week").weekly quality-score snapshots
New-site spotlightIntroduces a site newly added to the network.score snapshots (new entries)

Posting rotates across families so a feed never turns into all-promo or all-tips.

The honesty guard

This is the single most important design decision, and the thing that makes the system safe to run for clients. Every template declares the exact facts it needs. Before a post is written, the engine checks those facts are present in the source data.

  • All facts present → the post is written.
  • A fact missing → the post is held and flagged, never filled with a guess.
Why this matters to a clientA price, a square-footage, a "now selling" status — the system will only ever state what the source verifies. You can put this in front of a builder and it will not embarrass you by inventing a number.

Deterministic templates (and why they cost nothing)

Posts are produced by fixed templates that slot verified facts into proven sentence patterns — not by calling a paid AI model every time. That has two big consequences:

  • Zero per-post AI cost. Generating 1,000 posts costs the same as generating one: nothing.
  • Predictable, on-brand output. You always know what a post will read like before it goes out.

Each family has multiple template variants for variety. Editing or adding one is a small, safe code change.

Where the templates live

/opt/portal/portal_templates.py       # builder-listing templates (demo)
/opt/portal/portal_templates_wt.py    # network self-promo templates

The feed generator

gen-social-feed.py on the main droplet is where real data becomes publishable items. It:

  • reads the site list, decodes and cleans each description, drops anything truncated;
  • pulls a genuine principle from each marketing skill (preferring the skill's stated goal);
  • compares this week's quality scores against last week's and keeps only meaningful gains (+5 or more, score 60+);
  • writes the combined feed and copies it to the hub.

It runs nightly at 05:00 UTC, just before the hub builds the day's posts. See Data Sources for exactly what it reads.

Rotation & variety

Two rules keep the feed fresh:

  • Least-recently-used first — the content combination that hasn't been posted in the longest time is chosen next, so the system works through the whole network before repeating.
  • Family cap per batch — no single family can dominate a batch, so tips, features, and wins stay mixed.

Adding or changing content

Common changes, in order of how often you'll make them:

You want to…Where
Reword posts / add a template variantportal_templates_wt.py
Change what data becomes postsgen-social-feed.py (main droplet)
Change how often a tenant postsclients.json → cadence
Add a whole new content familynew template block + a feed section that emits its items