Skip to content
Daily Post Automation

AI Automation assessment · n8n · Task 1

PlacidWay content, turned into a safe daily Facebook post, automatically.

An n8n workflow reads PlacidWay's public treatment packages, clinic profiles, blog articles and patient Q&A. It writes a short Facebook post with Gemini, generates an on-brand image when the page has none, and checks the post twice against the source page. It then publishes to a test Page, or holds it for a reviewer. Every run is logged, every failure raises an alert, and this dashboard shows each step as it happens.

Next scheduled post

—

Loading…

Published
–
URLs used
–
Runs
–

Latest run

No runs yet

1 / day
Scheduled post at 09:00 Asia/Manila, plus on-demand test runs
0 repeats
A URL is never published twice, enforced in the workflow and in the database
4 types
Blog articles, treatment packages, clinic profiles and patient Q&A, rotated through the week
2 checks
Rule-based guardrail plus a second LLM fact check before anything goes live

Goal & scenario

One fresh, on-brand Facebook post every day, with no copy-and-paste.

The brief: a production-minded first version of the system PlacidWay's marketing team would actually run, with sound decisions and clear trade-offs over polish.

Context

PlacidWay is a medical tourism marketplace. It publishes treatment packages, clinic profiles, blog articles and patient Q&A across thousands of pages.

The daily problem

Keeping the Facebook Page fresh means someone picks a page, rewrites it into a post, checks it doesn't over-promise, and publishes it, every single day.

What this workflow does

This workflow is version one of that system. It does the picking, writing, checking and publishing. A human only steps in when approval mode is on, or when an alert asks for attention.

Ground rules this build follows

  • Only public PlacidWay pages; robots.txt respected, including its 10-second crawl delay (stricter than the brief's 1 request per second).
  • Posts go to a test Facebook Page or stay in draft/dry-run mode. Never to a PlacidWay Page.
  • Healthcare content: no medical claims, no promised outcomes, no invented prices or facts.

Requirements

Every functional requirement, and exactly how it's met

Each card links to the pipeline stage that implements it, where you can inspect the n8n nodes.

R1

Trigger

Runs once a day on a schedule. Also supports a manual run for testing.

  • A Schedule Trigger fires daily at 09:00, using the workflow's own timezone (Asia/Manila).
  • A header-secured webhook starts a manual run. The admin panel here calls it, with optional mode, content-type and dry-run overrides.
Evidence: Run history shows trigger = schedule or manual for every run.See nodes
R2

Extract

Collect content: title, URL, summary or body, and featured image if available. Justify the method.

  • All four PlacidWay content types, each from its own public sitemap: blog articles (≈5,100), treatment packages (≈3,900), clinic profiles (≈1,350) and patient Q&A (≈4,500). One request returns every URL with its last-modified date.
  • Then a single HTML fetch of the chosen page. Open Graph meta gives title, summary and a 1200×630 image. JSON-LD gives structured Article, Product and FAQ data. Paragraphs inside <main> give the body.
  • No headless browser: pages are server-rendered, so a browser would only add cost and load on PlacidWay.
Evidence: Each post links to a content_items row with its title, summary, body excerpt and image.See nodes
R3

Select

Pick one item per run and never post the same URL twice. Keep a simple store of what was posted.

  • Postgres is the store. The workflow excludes every URL that is published, publishing or awaiting approval.
  • A partial unique index on posts(source_url) rejects a duplicate even if two runs race.
  • Dry runs, rejections and failures don't consume a URL, so a bad draft doesn't burn good content.
Evidence: The URLs-used counter, and the unique index in db/migrations.See nodes
R4

Generate

LLM-written post: a hook, 2–4 lines of value, a CTA, the link and 3–5 hashtags, under 500 characters before the link.

  • Gemini returns structured JSON (hook, lines[2–4], cta, hashtags[3–5]) against a response schema, so the shape can't drift.
  • The prompt gives the model only the extracted page as facts, plus a PlacidWay brand brief researched from their public site, press and social channels: calm, warm, no hard sell, soft CTAs like "Request a free quote", and #PlacidWay #MedicalTourism plus topic tags.
  • The workflow assembles copy, then the link, then the hashtags, and enforces under 500 characters before the link.
Evidence: Each post card shows its character count before the link.See nodes
R4a

Guardrails

No medical claims, no outcome promises, no invented prices, no facts that aren't on the source page. Add a check and explain it.

  • Rule check (deterministic): blocks claim words such as cure, guarantee, 100%, risk-free, painless, permanent and "will fix". Every number and currency amount must appear in the source text. Also checks structure, length and hashtag count.
  • LLM fact check (second pass, temperature 0): a reviewer prompt lists unsupported claims, prices or outcomes. If its output can't be parsed, the post fails.
  • Both checks must pass. One rewrite is allowed, with the violations fed back. After that the post is blocked and an alert is raised. Nothing unchecked is published.
Evidence: The guardrail report is stored on every post and shown in the live console.See nodes
R5

Publish

Post to a test Facebook Page, or schedule. Include the image when one exists.

  • Two publishing methods, switchable in Workflow settings. Posting agent (default): the run ends Ready to post, and a posting agent with its own browser, logged into Facebook once, posts the caption and image. It declines Facebook's upsell pop-ups and reports success only after it finds the post live on the Page.
  • Graph API: /{page-id}/photos with the image and caption, or /{page-id}/feed with the link, using a Page token stored as an n8n credential (never in the workflow or git).
  • A manual fallback is always on the Ready card: Copy caption, Open image, Open Page, then Mark as posted with the link.
Evidence: Published posts link to the real Facebook post; three are live on the test Page.See nodes
R6

Review option

A config flag switches between auto-publish and approval mode, where a reviewer approves the draft first.

  • config.default_mode = auto | approval. Manual runs can override it per run.
  • In approval mode the run pauses on an n8n Wait node. The draft appears in this dashboard's approval queue, and Approve or Reject resumes the run. Drafts expire after 24 h.
Evidence: Approval queue in the admin panel; runs show status waiting while paused.See nodes
R7

Logging & errors

Log each run (item, post text, Facebook post ID, status). Retry sensibly and alert on failure; never fail silently.

  • Every run writes a runs row first, then posts and content rows, so even a crash leaves a trace.
  • Every external call retries: sitemap and page 3× at 3 s; Gemini 3× at 5 s; Graph API 3× at 5 s.
  • A dedicated Error Handler workflow classifies failures (SITE_UNREACHABLE, LLM_ERROR, FB_TOKEN_EXPIRED, …), marks the run failed and raises an alert that this dashboard shows as a banner.
Evidence: Run history plus the alert feed.See nodes

How it works

The pipeline, node by node

Every tile is a real node in the n8n workflow. Switch between the horizontal flow and the stacked view. Nodes light up as the latest run passes through them. Click any node for its purpose, inputs, outputs and failure behaviour.

Legendrunningsuccesswaitingerrornot reachedbranch path
8 stages · 49 nodes · scroll sideways →
1

Trigger

R1

A daily schedule fires the run automatically. A secured webhook lets a person start a test run from this dashboard.

↳ Nothing to post

2

Extract

R2

Discover fresh content through PlacidWay's public sitemap, then read the single chosen page politely. A snapshot source covers the case where the site blocks the server.

↳ Snapshot source

3

Select

R3

Pick exactly one item per run and never the same URL twice, enforced in two places.

↳ Nothing to post

↳ Snapshot source

4

Generate

R4

Gemini writes a hook, 2–4 lines of value, a CTA and 3–5 hashtags, under 500 characters before the link.

↳ Retry path

5

Guardrails

R4a

Two independent checks: deterministic rules, then a second LLM pass that verifies every claim against the source.

↳ Retry path

↳ Blocked

6

Image

R5 · stretch

Use the page's featured image, or generate an on-brand image with Gemini when there's none, it's a generic placeholder or a clinic logo.

7

Review & publish

R5 · R6

A config flag decides between auto-publish and approval mode. Dry runs stop here.

↳ Approval mode

↳ Manual handoff

8

Log

R7

Every run ends with a status, the chosen item, the post text and the Facebook post ID.

Companion workflow

PW · Error Handler

An n8n Error Trigger workflow attached to the main workflow. It turns any unhandled failure into a classified alert (SITE_UNREACHABLE, LLM_ERROR, FB_TOKEN_EXPIRED, FB_PUBLISH_FAILED, EXTRACTION_FAILED, DATABASE_ERROR), marks the run failed, and releases any post stuck in publishing.

Companion workflow

PW · Engagement Sync

Every 6 hours, reads reactions, comments and shares for posts from the last 14 days via the Graph API and stores them next to each post.

Live run

Watch the workflow run in real time

This console follows the latest execution of the n8n workflow, whether the schedule fired it or someone pressed Run. Each node reports as it finishes.

Reconnecting…
  1. Trigger
  2. Extract
  3. Select
  4. Generate
  5. Guardrails
  6. Image
  7. Review & publish
  8. Log

Selected content

Picked once the sitemap has been ranked and filtered.

Execution log
  1. Waiting for the next run…

PlacidWay Demo (test Page)

Just now ·

The generated post appears here once the run reaches the guardrails.
LikeCommentShare
Guardrail verdicts appear here: the rule check first, then the LLM fact check.

Outputs

What the workflow has produced

Every post here was written from a real PlacidWay page and passed or failed the guardrails on its own. Each one links to its source and, once published, to the live Facebook post.

Loading posts…

Decisions & trade-offs

Why it's built this way

The brief values sound decisions over polish. These are the calls that shaped the workflow, and what each one costs.

01

Sitemap + single page fetch, not crawling or a headless browser

The sitemap is PlacidWay's own index of what's new. Ranking by last-modified surfaces fresh content in one request, and pages are server-rendered, so plain HTTP is enough. A live run makes just 2 requests to placidway.com, 11 seconds apart, to honour the Crawl-delay: 10 in robots.txt.

Trade-off: If PlacidWay changes its markup, extraction fails loudly with an alert rather than posting something wrong.

02

Belt and braces guardrails

Word lists are cheap and predictable but miss paraphrase. An LLM judge catches paraphrase but can be fooled. Running both, and requiring both to pass, gives fast deterministic coverage plus semantic coverage.

Trade-off: Costs one extra Gemini call per post (well under a cent) and occasionally blocks a borderline-but-fine post. For healthcare content that is the right way to fail.

03

Postgres as the store, not a spreadsheet

It runs on the same VPS network as n8n. Uniqueness is enforced by an index, not by hope. The same tables feed this dashboard.

Trade-off: Slightly more setup than Google Sheets, but no API quotas and real constraints.

04

Approval inside the workflow (Wait node), not a second workflow

The paused execution keeps all its context, so approving resumes exactly where it stopped. The run's whole story stays in one place.

Trade-off: Executions can wait at most 24 h by design. Expired drafts free their URL for a later run.

05

A snapshot source instead of working around the site's protection

PlacidWay's Cloudflare blocks datacenter IPs. Rather than proxies or disguised requests, the workflow can read real pages captured once from a normal connection. A single config switch moves it back to live fetching when the IP is allowlisted.

Trade-off: Snapshot content is only as fresh as its capture date, and the pool is small (10 per type). It's a demo bridge, not the production mode.

06

Publishing through an agent-owned browser when there's no API token

The Graph API needs a Meta developer app and Page token. For the assessment, the workflow hands posts to a posting agent with its own server-side browser, logged into Facebook once by a person. It's deterministic, verifies each post is live, and stops on any security check instead of working around it. The Graph API path stays built in, one setting away.

Trade-off: UI automation depends on Facebook's markup and isn't the officially supported route. For production, switch to the Graph API with a Page token.

07

Live view from n8n's own execution data

The dashboard follows n8n's per-node progress. The workflow doesn't need extra logging nodes for the live view, and scheduled runs show up just like manual ones.

Trade-off: Polling roughly every second while a run is active. Negligible on one workflow.

Where it runs

Self-hosted on one VPS, next to n8n

The workflow, its database and this dashboard share a private Docker network on a Hostinger VPS. Only Traefik faces the internet. The workflow only ever calls three outside services.

pf-vps · Docker network n8n_default

Traefik

TLS · Let's Encrypt · :443

n8n

3 workflows · schedule · webhooks

pw-dashboard

Next.js · this page

pw-postgres

Postgres 17 · internal only

HTTPS

External services

placidway.com

sitemap + 1 page · 11 s apart

Gemini API

writer + fact-check judge

Facebook Graph API

test Page · engagement

Content source today: PlacidWay's Cloudflare rejects requests from datacenter IPs, including this VPS (HTTP 403), even though robots.txt allows the paths. Until the IP is allowlisted, runs read a snapshot of real public pages captured once from a normal connection (10 newest per content type, robots-allowed paths, 11 s apart per its Crawl-delay). Everything after extraction is identical. Switching back is one config value: source_mode = live.

Hostinger KVM 2 · 2 vCPU · 8 GB · Ubuntu (srv1866850). n8n reaches Postgres by container name; the dashboard reads n8n through its API and resumes approvals server-side.

Configuration

All secrets live in .env on the server. The workflow only sees them as n8n credentials.

N8N_API_URL / N8N_API_KEY
Dashboard reads execution progress; deploy script upserts workflows
N8N_WEBHOOK_SECRET
Header secret for the manual-run webhook
GEMINI_API_KEY / GEMINI_MODEL / GEMINI_IMAGE_MODEL
Text and image models. The key is stored as an n8n credential at deploy time
FB_PAGE_ID / FB_PAGE_TOKEN / FB_GRAPH_VERSION
Test Page. Token stored as an n8n credential
DATABASE_URL / POSTGRES_*
Postgres for n8n and the dashboard
ADMIN_PASSCODE / SESSION_SECRET
Unlock the admin panel; sign its cookie
SCHEDULE_TZ / SCHEDULE_HOUR
Daily trigger time
POSTER_SECRET
Shared secret between the posting agent and the dashboard
BROWSER_HOST / BROWSER_USER / BROWSER_PASSWORD
Agent browser web view address and its login

Deliverables

What's handed over

Outputs and documentation. The workflow itself runs here, so a reviewer can watch it, trigger it and inspect every node.

ready

README

Setup, environment variables, how to run, and architecture. Lives in the repository root.

live

Sample output

At least 3 posts generated from real PlacidWay pages, each with its source URL. Shown live under Outputs and kept in docs/sample-outputs.md.

View sample posts →
ready

Overview (PDF)

A short read: the assessment, what was built, how the workflow works end to end, key decisions and links.

Download overview
ready

Full documentation (PDF)

Everything in detail: setup, settings, every node, operating scenarios, guardrails, errors and alerts, hosting, data model and runbook.

Download PDF
recording

Screen recording

5–10 minute narrated walkthrough: a live run from extraction to the AI post, then the result on the test Facebook Page.

Stretch goals

  • Variety rules

    Weekly rotation across all four content types: articles, packages, clinic profiles and patient Q&A. Overridable per run and in config.

  • Image handling

    Uses the page's 1200×630 Open Graph image when it's good. Otherwise generates an on-brand 16:9 image with Gemini (no text, faces or medical imagery) and serves it from the dashboard.

  • Dashboard of scheduled and published posts

    This page: run history, post gallery, approval queue and live pipeline.

  • Engagement read-back

    Every 6 h, reactions, comments and shares are read from the Graph API and stored next to each post.

  • Brand overlay next

    Stamping a logo or frame onto images (n8n Edit Image node) is a next step.

  • Cross-posting to Instagram / LinkedIn next

    The post is platform-neutral. Instagram needs a Business account linked to the Page. Out of scope for v1.

Admin panel

Actions here run the real workflow on n8n.

Publishing mode

Approval pauses the run until a reviewer decides in the Approvals tab.

Content type

The weekday rule rotates through all four content types.

Image

Featured first uses the page's image and only generates one when it's missing, generic or a logo.

Content source

Live fetches placidway.com, which currently blocks this server's IP. Snapshot uses real pages captured once from a normal connection.

Admin access

The proposal is public. Triggering runs and approving drafts needs the admin passcode.