🌐 See how it works → https://veinsystem.github.io/post/
Every day, an AI picks a product from your Shopify catalog, writes the caption, you approve it, and it posts to Instagram & Threads — automatically.
POST! is a self-hosted engine that picks a product from your Shopify catalog every day, builds the carousel, and writes the caption — then waits. Nothing ships to Instagram or Threads until you click approve.
The local approval screen (http://localhost:8782) — real UI, shown here with demo (Sample Store) products.
Self-hosted. Single-tenant. You own your data and your tokens. No SaaS in the loop except the Anthropic API for caption writing.
Disclaimer: This is an unofficial tool not affiliated with Meta, Instagram, or Threads. Use it in compliance with the Meta Platform Policy and Instagram's Terms of Use. The author is not responsible for any account suspension or API access revocation.
Each day the tool:
- Picks a product from your Shopify catalog (rotating, so you don't repeat the same item for weeks).
- Builds a carousel from the product's images.
- Writes a caption with Claude (Anthropic).
- Runs guards (dedup, burst limits, safety checks).
- Shows you a preview at
http://localhost:8782for one-click approval. - Publishes to Instagram and/or Threads only after you approve.
- Records everything to an append-only ledger.
Nothing goes live without your explicit approval.
Shopify catalog
│
▼
select ← rotates products (cooldown so items don't repeat)
│
▼
carousel ← assembles image slides
│
▼
caption (Claude) ← writes the post text
│
▼
guard ← dedup / burst / safety checks
│
▼
preview (approval UI :8782) ← YOU approve here
│
▼
publish (IG / Threads) ← only fires after approval
│
▼
ledger ← append-only record of what posted
flowchart TD
A[Shopify catalog] --> B[select]
B --> C[carousel]
C --> D["caption (Claude)"]
D --> E[guard]
E --> F["preview / approval UI :8782"]
F -->|you approve| G["publish (IG / Threads)"]
G --> H[ledger]
git clone https://github.com/veinsystem/post.git
cd postRun the setup wizard — it writes .env and config.json for you:
node bin/init.jsIt asks for your Shopify domain + Admin token, brand name, IG handle, IG/Threads tokens, your Anthropic key, and Cloudflare R2 settings (for public image URLs). See docs/setup_meta_tokens.md for how to obtain the Meta (Instagram/Threads) tokens.
Non-interactive smoke test (CI / trying it out):
node bin/init.js --defaults --drywrites files with dummy values and skips any network calls.
# Build the image
docker compose build
# Generate today's post plan (dry-run — safe, writes nothing live)
docker compose run --rm daily
# Start the approval UI at http://localhost:8782
docker compose up -d previewOpen http://localhost:8782, review the post, and approve. The publish service
(started with docker compose up -d publish) dispatches approved posts every 15
minutes. Actual posting only happens when you run publish.js --live and have
approved a post — see the comments in docker-compose.yml.
npm ci
DRY_RUN=1 node run-daily.js --dry-run # generate a dry-run plan
node gen-preview.js # serve the approval UI (:8782)See docs/cron.example for cron entries that generate the daily plan and poll the publish queue.
Q: My tokens keep expiring. Why?
A: Instagram Graph and Threads long-lived tokens expire after 60 days. Refresh
them before they lapse with node modules/cli/token-refresh.js (Threads) — the
tool warns you when fewer than 7 days remain. Check status any time with
node modules/cli/token-check.js. See docs/setup_meta_tokens.md.
Q: What is R2 and why do I need it?
A: Instagram and Threads APIs require publicly reachable HTTPS image URLs — they
fetch your images by URL, so localhost won't work. Cloudflare R2
is object storage with a free 10 GB tier that gives you those URLs. The tool signs
uploads itself (no extra dependency). If you already run a public static server,
you can use HOSTING_MODE=local_static instead.
Q: How does the approval flow work?
A: The tool generates a plan and a preview page but never posts on its own. You open
http://localhost:8782, see exactly how the post will look, and click approve. Only
approved posts enter the publish queue, and live posting requires the --live flag.
Two gates keep you in control.
Q: How do I get a different product every day?
A: select tracks a rotation cursor and a cooldown (default 14 days in config.json),
so it advances through your catalog and won't repeat an item until the cooldown passes.
Q: Do I have to use both Instagram and Threads?
A: No. Configure at least one. config.json's media block toggles channels; the
wizard defaults to Threads on. Provide a token for whichever channel(s) you want.
Built by @masanorimutomk2 — AI秘書 (AI Chief-of-Staff): DM me on X → https://x.com/masanorimutomk2


