PitchStation Apps Apps home Markdown for agents
PitchStation Apps · Overview

Put a running prototype in front of people

Some deliverables are software, not documents. PitchStation Apps takes a project with a docker-compose.yml (or a Vite + React or Next.js app), builds it on a host the platform manages, and gives it a live HTTPS address under its host's base domain, such as demo-crm.apps-ap.pitchstation.ai, or your own domain. Public or password-gated, with an expiry if you want one, release history, rollback and proof that the address really serves your app. New here? Start with the user manual.

What you getHow a deploy worksFive ways inBefore you startStatus in this releaseLimitsWhere next

§01What you get

A live address with TLS

Every app gets an address under its host's base domain: SLUG.apps-ap.pitchstation.ai on Singapore's hosts, SLUG.apps.pitchstation.ai on Oregon's, and the host's own label in between (SLUG.hN.…) on an isolated host without per-app DNS. Each name gets its own Let's Encrypt certificate, renewed automatically. Custom domains and aliases are added with a DNS ownership proof.

Releases and rollback

Each upload is a numbered release, and data on named volumes survives every release. A rollback runs an earlier release's Compose file again; it brings back that release's code when each release tags its images differently. A failed health check leaves the new release serving, so the fix is usually a redeploy. Details.

Access you control

Public, or gated by a password you choose, with an optional expiry that is enforced on every request — even if PitchStation itself is unreachable.

Secrets stored encrypted

Environment variables are stored encrypted and written to the release at deploy time. The API only ever returns key names.

Operations you can resume

Deploys, rollbacks and address changes run as durable operations with an ID. Closing your laptop does not cancel them; retrying with the same key never deploys twice.

Readiness evidence

A readiness check proves each address answers over TLS with the right access policy, serves this app's identity marker and its critical assets — not just "HTTP 200 from something".

§02How a deploy works

How a deploy worksA content deploy: the client packages your directory into a tar.gz, leaving out .env files, .git, node_modules, keys and local databases. The API accepts it as a durable operation: a dry run first returns a redacted plan, and the apply returns an operation ID. The worker builds it on the app host over SSH, runs the migration, starts it on a loopback port and checks that the health path answers 200. Then the managed route serves it with nginx, a certificate and an access policy checked on each request, and readiness proves TLS, identity, assets and access. Changing an address or the access policy never rebuilds or restarts the app; two publishers never write to one host at the same time; an uncertain remote outcome stops for inspection; database migrations are never rolled back automatically. 1 · Package2 · Accept3 · Build on the host4 · Route and prove your directory → tar.gz.env, .git, node_modules,keys and local DBs excluded(client, MCP or your own tar) POST /api/apps/:id/deploydry run first: redacted planapply: operation ID (HTTP 202)source kept until done SSH to the app hostcompose build → migrate →up on 127.0.0.1:<hostPort>health check must answer 200 nginx vhost + certificatepolicy check on each requestreadiness: TLS, identity,assets, access policy What never happens Changing an address or the access policy never rebuilds or restarts the app. Two publishers never write to one host at the same time (a per-host lease with a fence). An uncertain remote outcome is never guessed: it stops for inspection. A database migration is never rolled back automatically: make migrations idempotent and forward-compatible. How a deploy worksA content deploy: the client packages your directory into a tar.gz, leaving out .env files, .git, node_modules, keys and local databases. The API accepts it as a durable operation: a dry run first returns a redacted plan, and the apply returns an operation ID. The worker builds it on the app host over SSH, runs the migration, starts it on a loopback port and checks that the health path answers 200. Then the managed route serves it with nginx, a certificate and an access policy checked on each request, and readiness proves TLS, identity, assets and access. Changing an address or the access policy never rebuilds or restarts the app; two publishers never write to one host at the same time; an uncertain remote outcome stops for inspection; database migrations are never rolled back automatically. 1 · Package your directory → tar.gz.env, .git, node_modules, keys andlocal databases left out(client, MCP or your own tar) 2 · Accept POST /api/apps/:id/deploydry run first: a redacted planapply: an operation ID (HTTP 202)source kept until done 3 · Build on the host SSH to the app hostcompose build → migrate → upon a loopback host portthe health check must answer 200 4 · Route and prove nginx vhost and certificatepolicy check on each requestreadiness: TLS, identity, assetsand access policy What never happens Changing an address or the access policynever rebuilds or restarts the app. Twopublishers never write to one host at thesame time. An uncertain remote outcome isnever guessed: it stops for inspection.Migrations are never rolled backautomatically.
A content deploy: the client packages your directory, the API accepts it as a durable operation, the worker builds and health-checks it on the app host, then the managed route serves it with TLS and the access policy.

Content and configuration are separate on purpose. A deploy changes the code that runs. A domains or policy change edits the address or who may reach it, without touching the running containers. An env change updates secrets and restarts the current release. Each is its own operation, planned first and applied explicitly.

§03Five ways in

All five speak the same REST API, so anything one can do the API can do. Pick by where you are working. Stopping and deleting an app are REST calls only; the client and the web page have neither. The user manual has the full task-by-channel table.

ChannelBest forCreate appDeployDomains · accessEnv · rollbackStop · deleteStatus · readiness
Web · /apps.htmlOwners changing addresses and access by hand——yes——yes
AI skill · create-pitchstation-appAsking Claude Code, Codex or another agent to make a project deployable and ship ityesyesyesyesby RESTyes
MCP · 6 pitchstation_app_* toolsAssistants without a shell (Claude Desktop, Cline, Cursor)—yesa password, on deployoperation retry/cancel—yes
Apps client · pitchstation-apps.cjsTerminals and CI: one dependency-free Node fileyesyesyesyes—yes
REST API · /api/appsYour own tooling; the complete surfaceyesyesyesyesyesyes
Why MCP stops at deploy and status. Domain, access and environment changes are reviewed plans guarded by a configuration version (an ETag): the change you approve is exactly the change applied. That review is a conversation with the user, not a single tool call, so those steps stay in the client, the skill (which walks the review) and the web page.

§04Before you start

The app.deploy capability

Running your own prototypes and running someone else's code are different trust levels, so hosting is never on by default. An administrator grants app.deploy to your account. Without it every call answers 403 CAPABILITY_REQUIRED.

A personal access token

Create one with the Apps preset at /tokens.html (it starts with pst_). Tools read it from PITCHSTATION_APPS_TOKEN (the MCP server from PITCHSTATION_MCP_TOKEN), or the shared PITCHSTATION_TOKEN; never paste it into a command line or a chat.

A host your account may use

Either a host registered to your account, or a shared host the platform offers to teammates. GET /api/apps/targets (client targets, or pitchstation_app_list) lists both with free slots, budget headroom, architecture and region, plus your quota on shared hosts (3 apps unless an admin changes it). Leave the host out when you create an app and the platform places it for you and says why.

Choose public or private up front

Say at creation whether the app is private (with a password you keep) or public. A public app also declares that it restricts nobody itself (application policy none) — at creation or later — or readiness will not certify it. Why.

§05Status in this release

AreaStateNotes
App hostsliveSingapore (*.apps-ap.pitchstation.ai, ARM64) is the shared host for teammates: Compose rules and per-app budgets are enforced there. Oregon (*.apps.pitchstation.ai, x86) is the platform account's own host. It was resized on 30 September and stays out of the pool until four of its apps stop publishing ports on every interface; there the rules and budgets warn. On Singapore every image and binary must be available for ARM64. A host an admin has not approved answers HOST_NOT_APPROVED to an apply; dry runs work everywhere.
Shared hosts, placement and quotaliveTeammates with app.deploy can create apps on shared hosts without a host of their own; 3 apps each by default. Admins approve hosts (host check, onboarding, live and pool flags) on the admin page, with no restart.
Status, logs, failed-step outputliveContainers, health, restarts, out-of-memory kills and usage against the budget; redacted logs; a failed step shows the redacted tail of its output.
Resolving an uncertain deployliveWhen only your containers were involved (a migration, up, health), you inspect and confirm it yourself; routing and host-level cases go to an admin.
Managed route (per-host TLS + access policy)liveNew apps use it from their first deploy (first production app on 27 September 2026, after a fix to how the policy is linked on the host).
Apps deployed before 18 Septemberlegacy routeSix earlier apps keep serving on their original routes. They were inventoried; their first domains or policy change moves them onto the managed route after checking the existing route has not changed.
Custom domainsfirst use pendingImplemented with per-host _pitchstation.HOSTNAME TXT proofs; not yet exercised on a production custom domain.
AI skill · Apps client · MCP toolsliveThe client is a single download (with targets, status, logs, resources, reconcile, releases and private-first --password-file); it prints each error's fields and details. MCP has six app tools, and its deploy takes a readiness marker. See the user manual and the deploy guide.
Sign-in page and access linksliveA private app shows people a sign-in page (a 12-hour session; API clients keep HTTP Basic) and passes their own Authorization header to the app once they are in. Per-recipient access links open it for one person each, revocable on their own.
Backups and restoreliveDeclare how the data is backed up. A deploy of an app that already has a release then backs it up first (before its first pre-deploy hook, else its migration, else its start), as well as on demand and daily if asked. Copies leave the host with the platform backups. Restore is previewed and confirmed.
Moving between hostsliveThe release is copied, all source services stop, then a final volume backup is taken; the destination builds the release (or loads its image archive), restores the data and takes over the routing. Stateful moves require volume backups. The old copy is kept 7 days; admins can evacuate a whole host.
Image archives and the build ceilingliveBuild elsewhere (your machine, CI, a Devbox) and deploy the images: archive, then deploy --image-archive; the host loads them and builds nothing. Builds that do run on a host run inside its build ceiling, installed by each host's next onboarding.
Deploy settings and packagingliveA migration service and pre/post-deploy hooks; a Compose file in a subdirectory; .pitchstationignore; env templates kept; local databases left out; Next.js (standalone) scaffolding for npm and pnpm workspaces. Build-time env keys say when a change needs a redeploy.
Private apps: callbacks, caching, sign-in, link useliveCallback paths skip the gate (never expiry); content-hashed assets may be cached in the viewer's browser; listed PitchStation people and teams sign in with their account; each access link shows its use. Each host's policy verifier upgrades at its next routing operation; link use arrives once its reporter is updated by onboarding.
Strict hosts, egress controlsliveA Compose allowlist and no-new-privileges on strict hosts; outbound mail, the metadata service and connection floods blocked on restricted hosts. The team hosts stay standard and open unless an admin switches them. On an owner's own host an admin can grandfather a reviewed finding (audited), so the host can enforce the rules.
Isolated host per developer, spend capfirst launch pendingReserve a host of your own inside your monthly cap (shared with dev instances); an administrator launches it with the scoped AWS profile, and it runs strict, user-namespace remapped and egress-restricted from its first boot. Every host reports memory, disk and load every 5 minutes, with a growth proposal when it stays full.
Per-app DNS recordszone delegation pendingImplemented for Route 53: each app gets its own record, so apps can move between hosts under one name. Active once the app zones are delegated.
Abuse reports, takedown, termslivePublic reports at /abuse.html go to an admin queue; takedown stops an app and answers 404 until lifted. Publisher terms can be required (off for the team).
Renewal alerts by emailnot enabledCertificates renew automatically; expiry alerts need separate monitoring configuration.

§06Limits

WhatLimit
Source upload80 MiB compressed, 256 MiB expanded, 20,000 files; no links, devices, traversal or duplicate paths; files containing private keys are refused
Health checkYour healthPath must answer HTTP 200 within the poll window (60 s) after start; a redirect is a failure
Step time budgetsbuild 20 min · migrate 15 min · up 10 min · health 5 min; any single remote step 30 min
Requests to your app64 MiB request bodies · 300 s proxy read timeout · WebSockets supported
Plans and evidenceA reviewed domains/policy plan expires after 15 minutes; a readiness result is valid for 5 minutes
Preview password12–72 UTF-8 bytes, chosen and kept by the owner
Host portsOne permanent port per app in 41000–41999, loopback only
Budget per appDefault 512 MB memory, 1 CPU, 256 processes (64–16,384 MB, 0.1–16 CPUs, 32–4,096 processes). A host admits budgets up to its memory minus the host's reserve (512 MB unless an administrator changes it), times an overcommit factor: ×1.25 on owner hosts and ×1.0 on shared hosts (server settings APP_MEM_OVERCOMMIT_OWNER and APP_MEM_OVERCOMMIT_POOL)
Shared hosts3 apps per person by default; an app there must be stopped before it is deleted
LogsUp to 1,000 lines or 256 KiB per read; 10 status or log reads a minute per person per app

§07Where next

User manual

Task by task: access and setup, a first deploy, the Apps web page panel by panel, domains, access, settings, monitoring, recovery, error codes, data, limits and a FAQ.

Read the manual →
Deploy guide

The app contract, then step-by-step deploys through the skill, MCP, the client and REST; addresses, access, env, rollback and troubleshooting.

Read the guide →
API reference

Every endpoint, the dry-run / ETag / idempotency conventions, operation states and the typed error codes.

Open the reference →
Architecture & separation

How the pieces fit, what Apps borrows from the rest of PitchStation, and the staged design for running it as a separate service or platform.

See the design →
PitchStation Apps documentation · updated 2 October 2026 · Markdown version · User manual · OpenAPI: /api/openapi-apps.json · Apps home: pitchstation.ai/apps · Main site: pitchstation.ai