# ShipStatic > Static hosting on a global edge network. Deploy instantly — free, no account required. Claim to keep permanently. ## How It Works The platform has two primitives: - **Deployments** are immutable snapshots of static files. Each gets a unique ID (e.g. `happy-cat-abc1234`) and an instant preview URL at `https://{id}.shipstatic.com`. To update content, create a new deployment. - **Domains** are pointers to deployments. Repoint a domain to any deployment instantly — that's how rollbacks work. Domains can be platform (`my-app.shipstatic.com`) or custom (`www.example.com`). Key URLs: - Package: `@shipstatic/ship` (both CLI and SDK — same npm package) - MCP (one URL, no install): `https://mcp.shipstatic.com` — drop into any MCP client - MCP (local, full toolset): `@shipstatic/mcp` - API: `https://api.shipstatic.com` - Dashboard: `https://my.shipstatic.com` - Docs: `https://docs.shipstatic.com` - Agent Resources: `https://www.shipstatic.com/agents/` ## Anonymous Deploy (free, no account needed) Deploying works without credentials. The CLI, SDK, MCP server, GitHub Action, and Web Console all support this. ```bash # CLI — zero install, deploy in one line npx -y @shipstatic/ship ./dist # → live URL + claim URL (expires in 3 days unless claimed) ``` ```javascript // SDK — same zero-config experience import Ship from '@shipstatic/ship'; const ship = new Ship({}); const deployment = await ship.deploy('./dist'); // deployment.claim → URL the user visits to keep it permanently ``` ```text # MCP — one URL, free, no install, no API key # Drop into any MCP client (Claude, Cursor, Antigravity, Windsurf, VS Code, n8n): https://mcp.shipstatic.com # Agent calls deployments_upload → response includes url + claim ``` ```bash # MCP (local) — full toolset incl. custom domains, listing, account-tied ops npx -y @shipstatic/mcp ``` Without credentials, deployments go to the public account and expire in 3 days. The response includes a `claim` URL — the user visits it (signed in at `my.shipstatic.com`) to transfer ownership and keep the site permanently. With an API key, deployments go to your account and never expire. Anyone holding the claim URL can take ownership — treat it like a one-time token. Once claimed, it stops working. ## Authentication (optional) For permanent deployments and management operations. **API key** — persistent, full account access, one per account. - Format: `ship-{64 hex characters}` - Find it: dashboard → Settings → API key - Environment variable: `SHIP_API_KEY` - Config file: `.shiprc` (created by `ship config`) - HTTP header: `Authorization: Bearer ship-...` **Deploy token** — deploy-only, optional TTL, revocable. - Format: `token-{64 hex characters}` - Full secret returned only on create — copy it immediately, never retrievable again - Create via CLI: `ship tokens create --ttl 3600` (TTL in seconds) - HTTP header: `Authorization: Bearer token-...` - Consumed on first successful deploy - IP-locked optionally (auto-captured from first request) When both are present, the deploy token takes precedence. ## Quickstart ```bash # Install once, deploy many times npm install -g @shipstatic/ship # Deploy publicly (no setup) — share the URL, claim later if you want to keep it ship ./dist # Add an API key for permanent deploys ship config # Reserve and link a domain ship domains set my-app # platform domain ship domains set my-app happy-cat-abc1234 # link to a deployment ship domains set www.example.com # custom domain (paid plan) ``` --- ## Deployments ### Properties | Property | Description | |----------|-------------| | `deployment` | Unique identifier (e.g. `happy-cat-abc1234`) | | `url` | Preview URL (`https://{id}.shipstatic.com`) | | `files` | Number of files | | `size` | Total size in bytes | | `status` | `pending` → `success`/`failed`, then optionally `deleting` | | `labels` | Mutable tags (3–63 chars, lowercase alphanumeric with `.`/`-`/`_`, max 10) | | `password` | `true` if password-protected | | `via` | Origin tag — see [Origin tags](#origin-tags) | | `created` | Creation timestamp | | `claim` | Claim URL — present only on response of public (anonymous) deploys | | `expires` | Expiration timestamp for unclaimed public deploys (3 days from creation; absent for owned deploys) | ### Origin tags The `via` field records which interface created the deployment. | Value | Origin | |-------|--------| | `web` | Web Console (drag-drop or upload) | | `cli` | CLI | | `sdk` | SDK used directly | | `mcp` | MCP server (AI agents) | | `git` | GitHub Action | | `n8n` | n8n community node | | `gpt` | GPT Action (custom GPT integration) | | `vsc` | VS Code extension | ### Behaviors - **Immutable.** Only labels can be modified after creation. - **Path optimization.** Common root directories are flattened — `dist/index.html` → `index.html`. - **SPA detection.** Detects React Router, Vue Router, etc. and configures client-side routing fallbacks automatically. ### Password Protection Deployments can be locked behind a password set at upload time. Visitors see an unlock page until they enter the correct value. The plaintext is hashed with SHA-256 before storage — only the hash is kept. - Length: 6 to 128 characters - Set on upload via CLI flag, SDK option, or API field - No edit-in-place — to change or remove, redeploy ```bash ship ./dist --password 'hunter2!' # or via env var: SHIP_PASSWORD='hunter2!' ship ./dist ``` ```javascript await ship.deploy('./dist', { password: 'hunter2!' }); ``` --- ## Domains ### Properties | Property | Description | |----------|-------------| | `domain` | Fully qualified domain name | | `deployment` | Linked deployment ID, or `null` if reserved | | `status` | DNS verification state: `pending`, `partial`, `success`, or `paused` | | `labels` | Mutable tags for organization | | `verified` | When DNS was last verified | | `created` | Creation timestamp | ### Platform domains Subdomains of `shipstatic.com` (e.g. `my-app.shipstatic.com`). - Instant — no DNS, no verification - Name must be at least 6 characters - Available on all plans ### Custom domains Your own domain (e.g. `www.example.com`, `blog.example.com`). - Requires DNS records pointing to the platform - Subdomain only — apex domains (`example.com`) are not hosted directly - SSL provisioned automatically after verification - Available on paid plans ### DNS verification Platform domains are verified instantly. Custom domains require DNS verification: | Status | Meaning | |--------|---------| | `pending` | No DNS records verified yet | | `partial` | Some records found (e.g. CNAME but not A) | | `success` | All records verified — domain is live | | `paused` | Plan no longer entitles this domain (e.g. paid plan downgraded). DNS preserved; resumes on re-upgrade | **DNS records for `www` subdomains:** | Type | Name | Purpose | |------|------|---------| | CNAME | `www` | Serves the site | | A | `@` | Redirects apex to `www` (infrastructure only) | **DNS records for other subdomains** (e.g. `blog`): | Type | Name | Purpose | |------|------|---------| | CNAME | `blog` | Serves the site | **Wildcard CNAME fallback.** Pointing `*.example.com → cname.shipstatic.com` lets any subdomain you create on the platform under `example.com` resolve through the wildcard without per-subdomain records. ### Sharing DNS setup Each domain has a shareable hash (`domains.share()` SDK method, `share` CLI command, `GET /domains/:name/share` API). The hash resolves to a public page on `my.shipstatic.com/connect/...` showing the required DNS records — the recipient doesn't need an API key. Useful when handing DNS setup off to whoever owns the domain. ### DNS provider lookup `domains.dns()` identifies the domain's DNS provider (Cloudflare, Namecheap, GoDaddy, etc.) so users can be guided to the right place to configure records. ### Domain lifecycle 1. **Reserve** — `domains set ` (no deployment linked) 2. **Link** — `domains set ` 3. **Switch** — `domains set ` (instant rollback) 4. **Delete** — `domains remove ` --- ## ship.json Optional configuration file in your project root. Most sites work without one. Password protection is set on the deploy request itself, not in `ship.json`. Putting `"password"` in `ship.json` does nothing. ### Clean URLs ```json { "cleanUrls": true } ``` `/about.html` is served at `/about`. Visiting `/about.html` redirects to `/about`. ### Trailing Slash | Value | Behavior | |-------|----------| | `false` | `/about/` redirects to `/about` | | `true` | `/about` redirects to `/about/` | | not set | Both forms work | ### Redirects ```json { "redirects": [ { "source": "/pricing", "destination": "/plans", "permanent": true }, { "source": "/blog/:slug", "destination": "/posts/:slug" } ] } ``` Pattern syntax: `:param` matches one segment, `:path*` matches everything after. Default: `permanent: true` (308). ### Rewrites Serve content from a different path without changing the URL. Files on disk take priority. ```json { "rewrites": [ { "source": "/feed", "destination": "/feed.xml" } ] } ``` ### Headers ```json { "headers": [ { "source": "/assets/(.*)", "headers": [ { "key": "Cache-Control", "value": "public, max-age=31536000, immutable" } ] } ] } ``` ### SPA Fallback The platform automatically detects single-page apps and configures client-side routing fallbacks. Most SPAs work without any configuration. Use a manual rewrite only if auto-detection doesn't cover your setup: ```json { "rewrites": [ { "source": "/(.*)", "destination": "/index.html" } ] } ``` ### Processing Order 1. Static files (served if they exist) 2. Headers (all matching rules apply) 3. Redirects (checked before rewrites) 4. Rewrites (fallback when nothing else matched) Within redirects and rewrites, rules are processed in array order. Put catch-all patterns last. --- ## Important Constraints - **No apex domains.** `example.com` cannot be hosted — always use a subdomain like `www.example.com`. - **No unlinking.** Once a domain is linked to a deployment, it cannot be set back to empty. Switch to a different deployment or delete the domain. - **Platform domain minimum.** Names must be at least 6 characters. - **Deploy tokens.** Scoped to deploys, optional TTL, revocable. The full secret is returned only at create time — store it immediately. - **Anonymous deploys expire in 3 days.** Until claimed. - **Password length.** 6–128 characters. - **Labels format.** 3–63 lowercase alphanumeric characters with `.`, `-`, or `_` separators. Maximum 10 per resource. - **Domain names are normalized.** Case-insensitive, Unicode-aware. `Example.COM` → `example.com`. --- ## CLI ```bash # Zero install (recommended for one-offs and CI) npx -y @shipstatic/ship ./dist # Or install once for repeated use npm install -g @shipstatic/ship ship ./dist ``` ### Deploy ```bash ship # deploy a directory ship --label production --label v1.0 # with labels ship --password 'hunter2!' # password-protect ship --no-spa-detect --no-path-detect # disable auto-detection ship --json # machine-readable output ship -q # quiet — print only the deployment ID (for piping) ``` ### Deployments ```bash ship deployments upload ship deployments list ship deployments get ship deployments set --label production ship deployments remove ``` ### Domains ```bash ship domains set # reserve ship domains set # link or switch ship domains set --label prod # update labels ship domains list ship domains get ship domains validate # pre-flight check ship domains verify # trigger DNS verification ship domains records # required DNS records ship domains dns # DNS provider lookup ship domains share # shareable DNS setup link ship domains remove ``` ### Tokens ```bash ship tokens create --ttl 3600 --label ci # TTL in seconds; full secret printed only here ship tokens list ship tokens remove ``` ### Account ```bash ship whoami # current account ship account get # same as whoami ship ping # API connectivity ``` ### Setup ```bash ship config # interactive .shiprc setup ship completion install # install shell completions (bash, zsh, fish) ship completion uninstall # remove shell completions ``` ### Global Flags Apply to every command. | Flag | Description | |------|-------------| | `--api-key ` | API key | | `--deploy-token ` | Single-use deploy token | | `--api-url ` | API URL (for development) | | `--config ` | Custom config file path | | `--json` | JSON output | | `-q, --quiet` | Output only the resource identifier (compose with pipes) | | `--no-color` | Disable colored output | | `--help` | Show help | | `--version` | Show version | ### Deploy Flags Apply to `ship ` and `ship deployments upload`. | Flag | Description | |------|-------------| | `--label