Skip to content

Deploy to PandaStack button

The Deploy to PandaStack button lets anyone deploy your repository to their own PandaStack account with one click. You paste a badge into your README; a visitor clicks it, lands on a pre-filled deploy screen, fills in any required environment variables, and confirms. It mirrors Vercel’s “Deploy” / /new/clone shape, so a repo’s Vercel button URL works on PandaStack with just a domain swap.

Paste this Markdown into your README (swap owner/repo for your repository):

[![Deploy to PandaStack](https://dashboard.pandastack.io/deploy-button.svg)](https://dashboard.pandastack.io/deploy?repo=owner/repo)

The HTML equivalent:

<a href="https://dashboard.pandastack.io/deploy?repo=owner/repo">
<img src="https://dashboard.pandastack.io/deploy-button.svg" alt="Deploy to PandaStack" />
</a>

The badge asset (deploy-button.svg) is a self-contained 200×36 rounded pill served from the dashboard’s public directory, with an inline panda mark and “Deploy to PandaStack” text.

The badge links to https://dashboard.pandastack.io/deploy with query parameters that seed the deploy form:

ParamRequiredDefaultPurpose
repoYesowner/repo. Without it, the page shows a help card.
typeNostatic or container
branchNomainGit branch to deploy
buildCmdNonpm run build (static)Build command
outputDirNodist (static)Static build output directory
langNoauto (container)Container language: auto, nodejs, python, go, docker
nameNoBase project name
root-directory or rootDirNo./Monorepo subdirectory (stored as ./{dir}). root-directory is the Vercel name.
envNoComma-separated required env var names, e.g. env=OPENAI_API_KEY,DATABASE_URL
envDescriptionNoA URL rendered as a “What are these? ↗” help link next to the env prompts

Minimal:

https://dashboard.pandastack.io/deploy?repo=owner/repo

With env prefill and a monorepo root (Vercel-parity):

https://dashboard.pandastack.io/deploy?repo=owner/repo&type=container&root-directory=apps/web&env=OPENAI_API_KEY,DATABASE_URL&envDescription=https://github.com/owner/repo#env

Static site with an explicit build:

https://dashboard.pandastack.io/deploy?repo=owner/repo&type=static&branch=main&buildCmd=npm%20run%20build&outputDir=dist

For richer, self-documenting deploys, commit a pandastack.json file to the root of your repository. The /deploy page fetches it from the public GitHub contents API — https://api.github.com/repos/{owner}/{repo}/contents/pandastack.json?ref={branch}, with no auth — base64-decodes the content, and its values win over / merge onto the query-param seeds (for example, the env array in the file merges over the env= query list, adding descriptions and default values).

FieldTypeMaps to
type'static' | 'container'Project type
namestringProject name (sanitized to RFC-1123, base capped at 54 chars)
language'auto' | 'nodejs' | 'python' | 'go' | 'docker'Container runtime
buildCommandstringBuild command
outputDirstringStatic build directory
startCommandstringContainer start command
healthCheckPathstringContainer health check path
dockerfilePathstringDockerfile path
rootDirstringbaseDir (monorepo subdirectory)
env(string | { key | name, description, value? })[]Required env prompted on /deploy

The env array is what makes the deploy screen prompt for variables (Vercel parity) instead of the app booting with missing configuration. Declare each variable either as a bare string or as an object with a description and optional default:

{
"type": "container",
"name": "my-app",
"language": "auto",
"env": [
{ "key": "OPENAI_API_KEY", "description": "Your OpenAI key" },
"DATABASE_URL"
]
}

All declared env must be filled before the Deploy button is enabled.

  • Container language defaults to auto (Railpack zero-config detection, so a one-click deploy needs no commands).
  • Static defaults: buildCommand npm run build, outputDir dist.
  • baseDir defaults to ./.
  1. A visitor clicks the deploy-button.svg badge in your README.
  2. Their browser opens https://dashboard.pandastack.io/deploy?repo=owner/repo(&…).
  3. The dashboard’s AppShell requires authentication — an unauthenticated visitor is bounced to /login and returned to /deploy after signing in.
  4. The page fetches and parses pandastack.json (if present) and prefills the editable form; pandastack.json values win over the query-param seeds.
  5. The visitor fills any required env and confirms.
  6. On submit, the page builds a create-project request (with isPublic: true, autoDeploy: false, prPreview: false, enableAnalytics: false) and calls POST /v1/projects.
  7. On success, the dashboard routes to /projects/{name}.

Because a project name is its public *.pandastack.app subdomain and names are globally unique, two people clicking the same badge would otherwise collide. To prevent that, the submitted project name is {base}-{randomSuffix} — an 8-character lowercase-alphanumeric suffix (generated with crypto.getRandomValues, stable for the session). The visible base is validated against RFC-1123 (/^[a-z0-9]([-a-z0-9]*[a-z0-9])?$/, ≤ 54 characters).