Prompt: per-branch preview sites on IPFS
Have an agent give every branch or pull request of a static site its own
preview at https://<branch>.preview.example.ro on the ird IPFS gateway
— one IPNS name per preview, re-published on each build — then audit
what previews exist, what they cost, and tear down the ones whose
branches are merged.
Needs: ird access (MCP server or the ird CLI, logged in); the preview zone must be hosted on ird DNS; local access to the build output
Costs: hourly per MB pinned plus per MB served, per preview (credits_prices → recurring.ipfs-pin-hourly); IPNS names and gateway domains have no price-book line; DNS records ride on the zone's recurring.dns-zone-hourly rate
Group: hosting
Paste everything below the line into a fresh conversation. Fill in the
FILL IN block first.
Task
Do ACTION for the preview environment described below. Nothing is
pinned before I confirm the cost, and nothing is deleted before I
confirm the list.
FILL IN
ZONE: example.ro # zone hosted on ird DNS
PREFIX: preview # previews live at <slug>.PREFIX.ZONE
ACTION: publish # publish | audit | teardown
BRANCH: feature/login-form # publish: the branch being built
FOLDER: ./dist # publish: build output, index.html at its root
MERGED: feature/old-nav, fix/typo # teardown: branches whose previews go away
Non-negotiable rules
- One naming scheme, applied everywhere. Slug = branch lowercased,
anything but
a-z0-9 replaced by -, runs collapsed, edges trimmed,
at most 40 characters. Hostname <slug>.PREFIX.ZONE, pin name
preview:<slug>. Never create a name or pin outside this scheme.
- Cost per preview before pinning.
du -sh FOLDER, then MB ×
per_mb_hour × 730; show it next to the number of previews already
live (from the audit) and wait for a yes.
- One pin per preview. After a verified publish, unpin the previous
root of the same slug; otherwise every push adds a permanent charge.
- Teardown only from MERGED, only after confirmation.
ipns_delete
and ipfs_unpin have no undo: the name stops resolving, the
content stops being served. Show the exact list of names, pins
and domains that will go, then wait. Never touch anything whose
hostname is not under PREFIX.ZONE or whose pin name lacks the
preview: prefix.
Steps
A. Baseline. dns_list_zones must list ZONE. ipns_list (CLI:
ird ipfs ipns ls --json) and ipfs_pins(search="preview:") (page
with offset; CLI: ird ipfs pins --search preview: --all --json) —
keep both for the audit.
B. Publish — name (first build of a branch). If ipns_list has no
label <slug>.PREFIX.ZONE: ipns_create(hostname="<slug>.PREFIX.ZONE",
serve=true) (CLI: ird ipfs ipns create <slug>.PREFIX.ZONE --serve).
This creates the k51… name, attaches the hostname to the gateway and
writes the A record now and the _dnslink TXT once the name activates;
the certificate follows. Ownership of ZONE is verified server-side.
C. Publish — pin and switch. Previous root: the target_cid of the
name in ipns_list. Then ipfs_add(path=<absolute FOLDER>,
name="preview:<slug>") (CLI: ird ipfs add FOLDER --name preview:<slug>)
— blocks until pinned. Fetch the returned gateway URL and check
index.html renders and one asset path returns the real file (the
gateway answers a missing path with a fallback page, so eyeball the
content). Then ipns_publish(name="<slug>.PREFIX.ZONE", cid=<CID>)
(CLI: ird ipfs ipns publish <slug>.PREFIX.ZONE <CID>); it propagates
within minutes. Finally ipfs_unpin(pin=<previous CID>) if there was
one and it differs.
D. Audit. Build a table from step A: slug, hostname, state,
target_cid, last_published_at, pin size, monthly cost (size ×
per_mb_hour × 730). Add ipfs_domains (CLI: ird ipfs domains ls)
filtered to .PREFIX.ZONE so each preview shows name + pin + domain. If
a git checkout is available, git branch -r — flag previews whose
branch no longer exists as teardown candidates, and pins named
preview: with no matching name as orphans. Finish with ipfs_usage.
E. Teardown. For each slug in MERGED, after my confirmation
(whether ipns_delete also removes the linked gateway domain and DNS
records is undocumented — hence sub-steps 3 and 4):
ipns_delete(name="<slug>.PREFIX.ZONE") (CLI:
ird ipfs ipns rm <slug>.PREFIX.ZONE) — the k51… link stops
resolving.
ipfs_unpin(pin=<CID>) for every pin named preview:<slug> (CLI:
ird ipfs unpin <CID>) — billing stops.
ipfs_domains — if <slug>.PREFIX.ZONE is still attached,
ipfs_domain_delete(domain="<slug>.PREFIX.ZONE") (CLI:
ird ipfs domains rm <slug>.PREFIX.ZONE).
dns_get_zone(domain=ZONE) — if an A or _dnslink TXT for the
hostname survived, dns_delete_record(domain=ZONE,
name="<slug>.PREFIX.ZONE.") and the same for
_dnslink.<slug>.PREFIX.ZONE..
F. Verify. Publish: https://<slug>.PREFIX.ZONE serves the new
build (allow the DNSLink TTL on a re-publish; the first build also waits
for the certificate). Teardown: the slug appears in neither ipns_list,
ipfs_pins(search="preview:<slug>"), ipfs_domains nor the zone.
Deliverable
Publish: hostname, root CID, k51… address, previous CID unpinned
(yes/no), monthly cost of this preview and of all previews together.
Audit: the table from step D with teardown candidates marked. Teardown:
per slug, what was deleted at each of the four sub-steps, and the
monthly cost that stopped.