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.
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.1IVPS_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.
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.
file to edit for an entire deck
client frameworks at runtime
Why no CDN.
htmx and alpine are vendored in public/vendor. A private deck renders with zero outbound fetches.
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 deployThe 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.
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:mainRight 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 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 8006Done 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 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.