Pi Durable
earendil · shipped with pi 1.0 · 2026-10-01
private · tailnet only
/
01

how publishing works

From folder to URL in four moves

This deck was scaffolded, verified, committed and pushed from this machine in minutes. Each slide traces one stage of that chain with the real commands used.

The whole pipeline.

Scaffold a working app, write one MDX file, gate it with npm run verify, then git push piku HEAD:main. The instance runs what was committed; nothing is built server-side.

02

stage 1

One command makes the app

new-maha.sh copies a starter kit that already carries the runtime contract: a Procfile with a web: line, HOST=0.0.0.0, and PORT pinned in ENV.

IVPS_INSTANCE=piku bash ~/.agents/skills/create-maha-app/new-maha.sh \
  orbit 8006 orbit.komodo-everest.ts.net,orbit.aiground.io,piku,localhost,127.0.0.1

IVPS_INSTANCE

Adds the git remote named piku, so a later push needs no wiring.

Hostnames go in verbatim

They land in security.allowedDomains; a name missed now means a rebuild and redeploy later.

dist/ is committed

The deploy target runs no build, so the built output ships in the first commit.

Unique names

The folder is the app name is the piku app; two publications never share one.

03

stage 2

One file holds the whole deck

Everything you are reading lives in src/pages/index.mdx: prose and component tags together. Astro renders it server-side, MDX authors it, Alpine holds the slide index, HTMX swaps fragments.

1

file to edit for an entire deck

0

client frameworks at runtime

Why no CDN.

htmx and alpine are vendored in public/vendor. A private deck renders with zero outbound fetches.

04

stage 3

Verify is a gate, not a formality

npm run verify builds, boots the app on a scratch port, then checks what a user would see: the page answers 200, the slides exist, a form POST returns a fragment instead of a 403, and each slide index reveals exactly one visible slide.

npm run verify   # non-zero exit means do not deploy

The POST check matters because Astro discards any Host not listed in security.allowedDomains, so a missing hostname reads as a CSRF rejection even while the page itself loads fine.

05

stage 4

The push is the deploy

piku pulls the pushed tree, reuses its cached node_modules, and swaps the worker via the uwsgi emperor. No image, no registry, no build on the instance.

npm run build && git add -A && git commit -m "orbit: content"
git push piku HEAD:main

Right after a push the port answers nothing while piku reinstalls; poll until it speaks:

until curl -sf -o /dev/null --max-time 3 http://piku:8006/; do sleep 3; done
06

handoff

TLS never terminates on piku

The instance serves plain HTTP on the pinned port. Turning that port into an HTTPS URL belongs to ivps, which this machine cannot run, so it is handed over as one command.

ivps expose-service cloudai:piku orbit 8006

Done prints Service 'svc:orbit' is LIVE at https://orbit.komodo-everest.ts.net (HTTP 200). The public name uses one token, domain and port joined:

ivps expose-public-custom cloudai:piku orbit.aiground.io:8006
07

proof

A live round-trip

This deck is the app it describes: it went through every slide above before you read this one. Submit the form and watch the server answer with an HTML fragment, swapped in place.

Verify what users see.

After any publish: curl -s -o /dev/null -w '%{http_code}' http://piku:8006/ must print 200. A JS-gated page returns 200 with everything hidden, so assert the revealed state, not the markup.

jump to

keyboard

→ space
next slide
←
previous slide
home / end
first / last
o
overview grid
?
this panel
esc
close