CJS.
Back to projects

Case Study · N8N Workflow

Social Content Bot

End-to-end Facebook automation that posts daily, ingests its own performance metrics, replies to comments, and renders the whole pipeline as a public dashboard. Topic bank in Airtable → Claude caption → Ideogram image → Supabase Storage → Facebook Graph API → daily metrics scrape → comment auto-reply every 15 minutes.

3 workflows · live public dashboardn8nClaude Sonnet 4.6Ideogram 3.0AirtableSupabaseNext.jsFacebook Graph API

The problem

SMB owners know they should be posting daily for social proof. They also know they won't. Content creation is the first thing that drops when the calendar fills up, and the moment it drops, the page dies, comments go unanswered, and the "we're active" signal disappears from a prospect's first impression.

I needed a system that could run a Facebook page end-to-end (write, design, post, ingest its own performance, and reply to comments) without the owner ever logging in. And it had to be visibly, publicly working, so an SMB prospect could see the daily proof-of-life on a real dashboard before they ever talked to me.

Architecture

Four logical stages, three n8n workflows, one public dashboard. Daily posting → metrics ingestion → comment auto-reply → public-facing Next.js dashboard with 1-hour ISR.

1

Daily Posting

Every morning at 09:00 Asia/Manila, n8n pulls the next pending topic from an Airtable bank, generates a caption with Claude, renders an on-brand image with Ideogram 3.0, uploads it to Supabase Storage, and posts to the Facebook Page via Graph API v19. The Airtable row is then stamped 'posted' so the queue advances FIFO. Three-layer error handling: node retry → fallback branch → Error Trigger workflow.

AirtableClaude Sonnet 4.6Ideogram 3.0Supabase StorageFacebook Graph API
2

Metrics Ingestion

Daily at 09:30 Asia/Manila, a second workflow scrapes /insights for every recent post plus the page itself and upserts into post_metrics, page_metrics, and posts_cache. RLS public-read is enabled on the metrics tables so the dashboard can read with the anon key without exposing writes.

Schedule TriggerFacebook /insightsSupabase PostgresRLS public-read
3

Comment Auto-Reply

Every 15 minutes, a third workflow scans posts ≤7 days old, fetches new comments, dedupes against the Airtable Comments table, classifies each with Claude (intent + tone), and replies under a 6-rule policy that decides whether to engage, deflect, or escalate. Every outcome is logged: replied, skipped, or escalated.

Schedule TriggerFacebook Graph APIAirtable dedupeClaude classify6-rule reply
4

Public Dashboard

A separate Next.js 16 app on Vercel renders the whole pipeline as a public dashboard: KPIs (posts, reach, engaged, clicks, replies), engagement and tone charts, top posts, and an activity timeline that merges post + comment events. Server-rendered with 1-hour ISR; the Airtable PAT is server-only with a smaller blast radius than n8n's PAT.

Next.js 16Server ComponentsISR 1hSupabase anonServer-only Airtable PAT

The dashboard

A separate Next.js 16 app reads Supabase + Airtable and renders the whole pipeline as a public, view-only dashboard. Server-rendered with 1-hour ISR; the activity timeline merges post and comment events into one chronological feed.

Social Content Bot public dashboard: KPIs for posts, reach, engaged, clicks, and replies, plus engagement and tone charts and an activity timeline.

Live Dashboard

Public, server-rendered, 1h ISR. No auth: open it and watch the bot work.

Open dashboard

The actual workflows

Both n8n graphs are running in production. The Main workflow handles the daily 9am post; the Comment Auto-Reply workflow runs every 15 minutes and uses a 6-rule policy to decide whether to reply, skip, or escalate.

Social Content Bot main workflow: daily Schedule trigger, Airtable topic fetch, Claude caption, Ideogram image, Supabase Storage upload, Facebook Page post.

Main · Daily Posting

9am Asia/Manila cron. Topic → Claude caption → Ideogram render → Supabase Storage → Facebook Graph → mark posted in Airtable.

Social Content Bot comment auto-reply workflow: every 15 min, scan recent posts, fetch comments, dedupe, classify with Claude, apply 6-rule reply policy, log outcome.

Comment Auto-Reply

Every 15 min. Posts ≤7d → fetch comments → dedupe → Claude classify → 6-rule reply policy → log every outcome.

Key decisions

The choices that separate this from a generic "AI posts to Facebook" demo.

Why a single linear workflow per concern

Posting, metrics, and comments each get their own n8n workflow instead of one mega-graph or a sub-workflow split. The reason is demo-readability: every flow has to fit on one screen when I open it in front of an SMB owner. Sub-workflows are deferred until a second platform (LinkedIn, X) shows up and I have real evidence of what's reusable, not before.

Why manual x-api-key on Anthropic HTTP Request

Anthropic API calls go through n8n's HTTP Request node with x-api-key supplied as a manual header from $env.ANTHROPIC_API. The httpHeaderAuth credential is intentionally NOT attached: double auth is undefined behavior and cost me a debugging session once. Locked in LESSONS.md across all three projects.

Why RLS public-read on metrics, server-only PAT for Airtable

The dashboard reads Supabase metrics with the anon key safely because RLS allows SELECT only on the metrics tables; writes are blocked. Airtable doesn't have row-level security, so the dashboard's Airtable PAT is a separate token from n8n's, scoped read-only and used server-side only. Two different threat models, two different patterns.

Precautions baked in

This runs unattended every day and replies on a real Facebook Page. The guardrails are the product.

  • Three-layer error handling: node retry → fallback branch → dedicated Error Trigger workflow per system
  • Comment dedupe against Airtable before any Claude call; the same comment never gets classified or replied twice
  • Supabase RLS public-read on metrics tables; the dashboard's anon key cannot write anything
  • Server-only Airtable PAT for the dashboard, scoped separately from n8n's PAT; smaller blast radius if leaked

Outcome

  • Live daily 9am Asia/Manila post with on-brand text-on-image, no human in the loop
  • Comments answered every 15 minutes under a 6-rule policy with full audit log
  • Public dashboard renders KPIs, charts, top posts, and a merged activity timeline
  • Sellable demo line: "Every morning at 9am your AI writes and posts. It replies. You watch the dashboard."

Watch the bot work in real time

Open the public dashboard. Every KPI, chart, and activity row is wired to the live pipeline.