A platform that turns news into ranked content before competitors notice the story.
A multi-tenant SaaS that monitors industry news in real time, detects events relevant to each client, and generates SEO-optimised content — with mandatory human approval before anything publishes.
Why this exists
Most businesses know they should be publishing content about industry news. They don't — because by the time they read the news, write a post, and get it approved, the SEO window has closed.
The platform compresses that window from days to hours. Every piece of architecture below exists to win the race against time and against competitors.
How it all fits together
Four worker services, one approval service, Redis streams between them, Postgres for state. Click any component to learn what it does.
Event flow · Redis streams
news.filtered
→
ingestion-worker → intelligence-worker
content.drafts
→
after Gate 4 generation → approval-service notified
content.approved
→
after human approval → publisher-worker
content.published
→
after successful publish → analytics
news.failed
→
dead letter · ingestion errors
content.failed
→
dead letter · generation / publishing errors
The 4-gate cost funnel
The most important architectural decision in the platform. AI calls are expensive. Every article passes 4 gates. Each gate is cheaper than the next, and drops most of what enters.
| stage | volume | cost / call | monthly |
|---|---|---|---|
| Gate 1 — rules | 30,000 | $0.00 | $0.00 |
| Gate 2 — Haiku | 3,000 | $0.0001 | $0.30 |
| Gate 4 — Sonnet | 150 | $0.015 | $2.25 |
| total AI cost | ~$2.55 | ||
At $99/month per client, AI cost is 2.6% of revenue. Without the funnel: ~$450/client/month. Catastrophic.
Source spread × Google Trends
Gate 3 computes two independent signals before deciding to generate. One comes from our own data, one from outside. Drag the controls to see how they combine.
combined = spread × 0.6 + trends × 0.4
Counts how many distinct sources covered the same topic in the last 2 hours.
PostgreSQL full-text search on news_items.title. No external API.
Queries Google Trends search interest for matched keywords, geo-filtered to client location
(e.g. geo="AU"). Cached in Redis for 1 hour. Fails open if unavailable.
- Score 0-100 based on last 24h of search interest
- Same keyword pair = one API call per hour
- If unavailable → defaults to 50, pipeline continues
A story covered by 5 outlets and trending on Google = high ROI. You're writing about what people are actively searching for, before the SEO competition has published.
Urgency override: breaking news always scores ≥ 70, regardless of these signals.
The 8 angles · how we differentiate
Competitors rewrite news. We generate opinionated content with a carefully selected angle. Claude is given the full list and picks the best fit for each article + client combination. Click each card to see how it sounds in production.
intelligence.angles in values.yaml, git push, ArgoCD syncs.
No Docker rebuild required.
Competitor gap analysis
Before each Sonnet generation call, we check what competitors have already published on this topic. Three cases, three different prompts to Claude.
Angle inference · zero AI cost
We detect competitor angles from title patterns alone. No LLM call. The detected angles are injected straight into the Gate 4 prompt as "avoid these".
"What X means for Y"
→
local_impact
"N things to do after X"
→
action_list
"Why X might be wrong"
→
contrarian
"Everything you need to know about X"
→
faq_explainer
Multi-tenancy & data isolation
Row-level isolation. Every table with client data has client_id UUID.
client_id is never trusted from the request body — it comes from the signed JWT only.
One bug cannot leak another tenant's data.
Three tiers of secrets
How we ship
Two paths. kind for local development, ArgoCD + GHCR for production. Same Helm chart, different values file.
kind create cluster --name content-intelligence
kubectl cluster-info --context kind-content-intelligence
docker build -t ci/ingestion-worker:dev -f services/ingestion-worker/Dockerfile .
docker build -t ci/intelligence-worker:dev -f services/intelligence-worker/Dockerfile .
docker build -t ci/approval-service:dev -f services/approval-service/Dockerfile .
docker build -t ci/publisher-worker:dev -f services/publisher-worker/Dockerfile .
kind load docker-image ci/ingestion-worker:dev --name content-intelligence
# repeat for the other three
kubectl create namespace content-intelligence
bash scripts/create-secret.sh
helm upgrade --install ci ./helm/content-intelligence \
-f helm/content-intelligence/values.yaml \
-f helm/content-intelligence/values-prod.yaml \
--namespace content-intelligence
kubectl get pods -n content-intelligence -w
kubectl port-forward -n content-intelligence svc/ci-approval-service 8000:8000
# then open:
# http://localhost:8000/register
# http://localhost:8000/admin
Changing config without code
Where we are · where we're going
goal: one paying client. prove the value proposition.
- multi-tenant DB schema · 12 migrations
- 4-gate cost funnel · all gates operational
- competitor intelligence · RSS, gap analysis, angle avoidance
- 8-angle selection · stored in
selected_anglefor analytics - admin dashboard · audit log, source quarantine, email bypass
- WordPress + Dev.to publishers
- multi-provider AI · Anthropic, OpenAI, Google, DeepSeek
- source health · auto-quarantine, exponential backoff, 3-tier replacement discovery
- ArgoCD GitOps · GHCR · CSI-synced secrets from Parameter Store
first paying client — in progress via Tomatotree Technologies partnership.
three things that matter more than any feature.
onboard one pilot client. real data changes everything. one live client > any feature on the roadmap.
approval rate · publishing speed · ranking improvements · CTR uplift. these four numbers become the sales pitch.
resist the urge to add features until approval rate > 70%. low approval = content quality issue, not a feature gap.
goal: 5-10 paying clients across 2 verticals.
- LinkedIn · Facebook Pages · Medium publishers
- Slack approval channel (alongside email)
- Google Search Console integration per client
- Client self-service · connect WordPress, add sources from dashboard
- Stripe billing · email verification flow
- KEDA autoscaling on intelligence-worker (Redis queue depth)
- Content memory · pgvector dedup before generation (threshold ~0.85)
goal: measurable SEO uplift. differentiation visible.
- angle performance analytics · which angles rank best per industry
- semantic deduplication at scale · topic family clustering
- SEO scoring engine · per-article suggestions
- FAQ schema markup · structured data for Google
- content cluster suggestions · pillar + supporting articles
- Instagram + Ghost publishers · Reddit + Google News sources
goal: white-label · enterprise contracts · trend prediction.
- Twitter/X publisher · when API cost is justified
- RBAC · admin / editor / viewer roles per client
- vector search on content history · prevent near-duplicate angles
- white-label option
- competitor keyword gap detection
- trend prediction · content opportunities before they break
- API access for enterprise clients
That's the platform. Every decision — the 4 gates, the 8 angles, competitor inference, tiered secrets, GitOps deploy — exists to compress days into hours while keeping AI cost at 2.6% of revenue.
Questions? ping #content-intel on Slack.