guide · computers

Publishing a Product Review on Agentic Bot Sitter, End-to-End

The complete review-publishing loop on ABS: voice note + amzn.to → draft → image gen → WebP → build → rsync → CF purge → commit → push → three-SHA → live.

July 14, 2026 · By Alastair Fraser

A friendly retro robot standing on a publishing assembly line — voice note tape reel on the left feeding into a draft printer, a 3D printer extruding a featured illustration in the middle, a WebP conveyor belt carrying the optimized image, a Cloudflare edge node upstream on the left, and a green PUBLISH stamp at the bottom right corner.

A product review on Agentic Bot Sitter is a publish pipeline: a voice note plus an affiliate link becomes a live, image-bearing, WebP-served, edge-cached page. This guide walks the whole loop on this VPS, in the exact order the loop runs, with the exact commands the operator runs.

What “publish a review” means on ABS

ABS reviews are type: review markdown files: a published date, a body with first-hand storytelling (not research-only), a PNG hero image plus WebP companion, grade chip (A/B/C/D/F), and an Amazon affiliate link. File at /srv/abs-site/src/content/posts/<slug>-review.md, image at /srv/abs-site/public/images/<slug>-review.png, companion at /srv/abs-site/public/images/<slug>-review.webp, rendered page at https://agenticbotsitter.com/<slug>-review/. The <picture> element serves WebP to supporting browsers and falls back to PNG otherwise.

31 reviews live in src/content/posts/*-review.md. They share: type: review, category in {ai, gadgets, computers, gaming}, pubDate ISO, grade and score, affiliate: true when an Amazon link is present, and a sources array.

The pipeline at a glance

Voice note + amzn.to URL → botsitter-review skill drafts from transcript → image gen (openai backend, gpt-image-2-medium) → WebP via Pillow → write markdown at src/content/posts/<slug>-review.md → build (npm run build) → rsync dist//var/www/agenticbotsitter/ → CF cache purge (new page, new PNG, new WebP, reviews index, home, sitemap) → commit → push to local + origin + GitHub → three-SHA check → site live. Skill that owns the loop: /opt/data/skills/botsitter-review/SKILL.md. This guide is the operator-facing tour in command form.

Voice note + amzn.to arrive together

Al’s typical review batch is two or more messages back-to-back: a voice/note transcript, then an https://amzn.to/... affiliate link, seconds apart. Per P43, treat them as the same input. Do not pause to ask “what is the Amazon listing URL?” — extract via web_extract and proceed.

The voice note carries the first-hand review in Al’s words. The amzn.to URL is the affiliate disclosure. Both are required. If the slug is dead (302 to bare http://www.amazon.com instead of /dp/<ASIN>?tag=agenticbotsit-20&...), P26 fires: ask Al to regenerate from SiteStripe. A dead slug cannot be salvaged — it is not the same as a wrong-product slug that can be flagged and re-linked.

Draft via botsitter-review

The skill reads the voice-note transcript, the affiliate URL, and the operator’s notes, and emits one complete markdown file matching the publish contract. Frontmatter: title (≤120), description (≤200), type: review, category, pubDate ISO, image/imageAlt/imagePrompt, grade and score, affiliate: true when present, sources, related, tags, draft: false.

Body shape: hook → “which product this review covers” → lived experience → “what I like” / “what annoys me” → “who it is for, who should skip” → verdict + grade chip → “For the nerds” footer (specs table, numbers, technical why — meatiest affiliate link lives here).

Self-check enforces: zero experiential claims not traceable to Al’s notes, every number real or flagged, at least one honest downside, body word count 900–1,600, and the rendered page visibly including “As an Amazon Associate I earn from qualifying purchases.” Grade enum must match Astro schema enum — both A/B/C/D/F. ProcareSelect failed schema against ['A','B','C','F'] and required the schema to learn 'D'. Do not assume an extra letter exists.

Generate the hero image

Generated via image_generate using the imagePrompt from frontmatter. Active backend: OpenAI (Codex auth) on gpt-image-2-medium. The locked style block from botsitter-review/references/image-style.md is copied verbatim; only the [SUBJECT] slot is swapped. Subject for this guide: “a friendly retro robot on a publishing assembly line — voice note tape on the left, draft on the printer, image emerging from a 3D printer, WebP conveyor belt, then a Cloudflare edge node upstream left and a publish stamp at the bottom right.”

P4: do not prompt the Agentic BotSitter brand character. Text-to-image cannot reproduce the cyan chest light, hair, circular emblem frame, and gray-temple-streaks in one go. The locked motif is the generic retro-futurist robot (chrome dome, coil limbs, riveted). Accept the generic robot or commission a human artist if Al asks for the brand character — do not loop on prompt rewrites. PNG output is copied to /srv/abs-site/public/images/<slug>-review.png (Astro does not pick up files outside public/).

OPENAI_API_KEY=$(grep OPENAI_API_KEY /opt/data/.env | cut -d= -f2)
# Use plugins.image_gen.openai.OpenAIImageGenProvider via Python script
# Save to /srv/abs-site/public/images/<slug>-review.png

Companion WebP

PNG images from gpt-image-2 are 1.7–3.6 MB; WebP at quality=82 is 100–500 KB (~88% smaller). Astro uses a <picture> element via src/components/Picture.astro — WebP-capable browsers pick it up via <source srcset>, PNG stays as the universal fallback. WebP companion is non-optional; every new review ships both.

python3 -c "from PIL import Image; Image.open('hero.png').save('hero.webp', 'WEBP', quality=82, method=4)"

Build, rsync, purge

CF zone 3ec4041668dd5f152058d9b73af60951. CF token lives in /opt/data/.env; read at runtime, never hard-coded.

cd /srv/abs-site
npm run build
rsync -a --delete dist/ /var/www/agenticbotsitter/
TOKEN=$(python3 -c "from pathlib import Path; print([l.split('=',1)[1] for l in Path('/opt/data/.env').read_text().splitlines() if l.startswith('CLOUDFLARE_API_TOKEN=')][0])")
ZONE=3ec4041668dd5f152058d9b73af60951
URLS='["https://agenticbotsitter.com/reviews/", "https://agenticbotsitter.com/<slug>-review/", "https://agenticbotsitter.com/images/<slug>-review.png", "https://agenticbotsitter.com/images/<slug>-review.webp", "https://agenticbotsitter.com/index.html", "https://agenticbotsitter.com/sitemap-0.xml"]'
curl -sS -X POST "https://api.cloudflare.com/client/v4/zones/${ZONE}/purge_cache" \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "Content-Type: application/json" \
  -d "{\"files\": ${URLS}}"

If /srv/abs-site has unrelated modifications, build in a detached clean worktree at HEAD, copy only the new review markdown and image pair into it, build there, and rsync that clean dist/. The CF purge must include both .png and .webp URLs — a brand-new image URL can cache a 404 from origin before the rsync completes.

Commit, push, three-SHA check

Stage only the new review markdown and the PNG + WebP pair, inspect the staged diff, commit, push to both remotes, verify all three SHAs match.

cd /srv/abs-site
git add src/content/posts/<slug>-review.md public/images/<slug>-review.{png,webp}
git diff --cached --stat
git commit -m "post(review): <slug>"
git push origin main
git push github main
[ "$(git rev-parse HEAD)" = "$(git ls-remote origin refs/heads/main | cut -f1)" ] && echo "origin OK"
[ "$(git rev-parse HEAD)" = "$(git ls-remote github refs/heads/main | cut -f1)" ] && echo "github OK"

Remotes are origin (local bare repo the post-receive hook reads) and github ([email protected]:MarvinAi5/ABS.git). Three-SHA check gates on local + origin + GitHub on the same commit. Pushing only origin is a real failure mode — GitHub mirror drifts, diff URL points to the wrong commit, future deploy pulls stale content. Do not git add -A when unrelated files are dirty; see references/review-only-clean-deploy.md for the clean-worktree dance.

What not to do

  • Don’t ship without both PNG and WebP, and don’t skip the CF image purge — the <picture> element expects both PNG and WebP, missing the WebP costs a rebuild cycle, and first-deploy 404 drain on the new image is real (both URLs must be in the CF purge list).
  • Don’t break the affiliate-tag rule or the three-SHA check — every monetized Amazon URL must resolve to the intended product and carry tag=agenticbotsit-20 (build pipeline auto-tags the canonical Special Link; never manually substitute, never invent), and gate deploys on local + origin + github, not just one. A green origin with a missing github push is a silent deploy regression.
  • Don’t ship a >1,600-word review or >200-char description — trim reviews to 1,400–1,500, drop marketing preamble in “What it is,” merge adjacent bullets. The Astro schema rejects long descriptions at build time with InvalidContentEntryDataError; lead with the verdict lean. Existing reviews cluster 150–180 chars.
  • Don’t pause for the Amazon URL on a voice note, and don’t try the brand character in image prompts — P43 says the amzn.to URL is in the immediate context (extract and proceed); P4 says text-to-image cannot reproduce the Agentic BotSitter brand character (use the generic retro-futurist robot motif).

Verification checklist

#CommandWhat it proves
1npm run build exit 0Frontmatter parses, build is green
2curl -I https://agenticbotsitter.com/<slug>-review/Review page is live on the edge
3curl -I https://agenticbotsitter.com/images/<slug>-review.webpWebP companion is live
4Three-SHA match (local vs origin vs github)All three remotes on the same commit
5python3 scripts/test_abs_search_filter.py exit 0Search catches the new review
6curl -s https://agenticbotsitter.com/sitemap-0.xml | grep <slug>Sitemap includes the new review
7<picture> element in HTML, not bare <img>WebP-aware rendering is live

If any row fails, do not ship. Schema constraints are deterministic — read the build error, fix the exact field, rebuild. The “purge returned success but origin still 404s” symptom means the purge URL was malformed (zone missing or wrong host); the API returns success:true before the purge runs.

Sources

Last verified: 2026-07-14 against the live ABS deploy pipeline on this VPS.

Sources

#abs#reviews#publishing#playbook#voice-note#affiliate#image-gen#deploy

Submit a take

Have a different read on this? Drop a comment below — your email isn't published, and I read every one. Nothing leaves the site until I approve it.

Your email address will not be published. Required fields are marked.