Oktapod Docs

Deploy the web surfaces

What ships as public web, what stays private, and how to check each surface before a deploy. For maintainers.

Oktapod has two public web surfaces and one private operator surface.

SurfaceSourceAudienceShips as
Landingapps/landingPublicStatic Vite site, including /update/, /security/, and the branded 404. /docs/ redirects to docs.oktapod.ai.
Docsdocs-sitePublicStatic pages at docs.oktapod.ai, built by apps/landing/docs-build.
Control UIapps/uiPrivateBuilt into dist/control-ui and served by each Oktapod.

There is no public API site. apps/gateway is the authenticated private gateway/control-plane boundary. It serves runtime endpoints and the access-key-gated Control UI bundle; it is not a marketing or docs site. Keep app.oktapod.ai, api.oktapod.ai, and any public route to apps/gateway or apps/ui parked.

Build and preview

Use Node 24.

pnpm build:sites

This builds the landing, the docs site, and the Control UI, and validates the docs. Preview them locally:

pnpm build:landing
pnpm build:ui

Serve apps/landing/dist or apps/ui/dist with any static server to check layout. A static preview only proves layout and assets; check real access and live activity through an actual Oktapod address, such as http://127.0.0.1:8788/ or your Tailscale address.

Checks before a public deploy

pnpm sites:check
pnpm public-sites:browser-check --screenshot-dir=.oktapod/reports/public-sites

sites:check runs pnpm build:sites and pnpm docs:check. The browser check renders the public sites at phone, tablet, and desktop widths. Save screenshots for review instead of opening new visible browser windows.

A page passes at 360, 390, 820, and 1440 pixels wide when it has no horizontal overflow, mobile navigation opens and closes, primary buttons stay visible and tappable, and the first screen hints at the next section.

The full web gate

Before calling the web work deploy-ready, run the single gate with the private Control UI address:

pnpm web:deploy-check --control-ui-url=https://<your-tailnet-host>/ --screenshot-dir=.oktapod/reports/web-deploy/full-gate

It checks the public build, metadata, icons, and social preview, runs the Control UI tests and browser e2e, confirms the live Control UI serves the same hashed bundle as the local build, and captures phone, tablet, and desktop screenshots. The auth evidence includes control-ui-auth/control-ui-locked-recovery-phone-390.png and control-ui-auth/control-ui-reconnect-banner-phone-390.png, so raw 401 unauthorized states cannot be missed during review. It writes index.html and summary.json in the screenshot folder for one-page review. Use --skip-live-control-ui only for public or local-only evidence.

To check just the live Control UI:

pnpm control-ui:live-check --url=https://<your-tailnet-host>/
pnpm control-ui:live-browser-check --url=https://<your-tailnet-host>/ --screenshot-dir=.oktapod/reports/web-deploy/control-ui

Deploy

Public binary downloads are open to everyone. Publish only the explicit runtime and setup binary allowlist under /downloads/<tag>/, with SHA-256 checksums. The binary delivery tree excludes source archives, transfer bundles, private release feeds, runtime credentials, and operator data.

Repository publication is a separate step. The planned open-source release uses Apache-2.0 and must first pass the dependency-notice and source/history review. The repository is currently private; do not infer publication from open binary downloads. Source publication does not authorize disclosure of operator data or private operational artifacts.

Public deploy:

  1. landing: sync apps/landing/dist to the public host, then make directories 0755 and files 0644 so nginx can read them;
  2. docs: pnpm build:landing also renders docs-site into apps/landing/dist-docs (navigation from docs-site/docs.json); sync that folder to the docs host with the same permissions. The docs host must return its 404.html for unknown paths and must not fall back to index.html.

The public nginx site serves /install.sh and /install.ps1 as plain text from the verified release commit. It serves the branded 404.html for unknown paths and /site.webmanifest as application/manifest+json, and must not fall back to index.html.

Private Oktapod deploy:

  1. private gateway/control-plane boundary
  2. Control UI bundle served by Oktapod
  3. local service and connectors

After a private deploy, rebuild the Control UI with the same Node 24 the service uses, restart Oktapod, and rerun the two live Control UI checks above.

Do not claim public API-site readiness. Claim private gateway/control-plane readiness only after gateway health, access-key auth, and Control UI checks pass through the actual Oktapod service.