# ShipStatic > Static hosting on a global edge network. Deploy static sites in seconds, point a domain, go live. ## How It Works The platform has two primitives: - **Deployments** are immutable snapshots of static files. Each gets a unique ID (e.g. `pink-elephant-4ruf23f`) and an instant preview URL at `https://{id}.shipstatic.dev`. 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 internal (`my-app.shipstatic.dev`) or custom (`www.example.com`). Key URLs: - Package: `@shipstatic/ship` (both CLI and SDK — same npm package) - API: `https://api.shipstatic.com` - Dashboard: `https://my.shipstatic.com` - Docs: `https://docs.shipstatic.com` ## Authentication All interfaces use the same credentials. Configure once, use everywhere. **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** — single-use, deploy-only, expires with optional TTL. - Format: `token-{64 hex characters}` - Create via CLI: `ship tokens create --ttl 3600` - HTTP header: `Authorization: Bearer token-...` - Consumed on first deploy, then invalid When both are present, the deploy token takes precedence. ## Quickstart ```bash npm install -g @shipstatic/ship ship config # enter API key once ship ./dist # deploy — site is live ship domains set my-app # reserve internal domain ship domains set my-app # link domain to deployment ``` --- ## Deployments ### Properties | Property | Description | |----------|-------------| | `deployment` | Unique identifier (e.g. `pink-elephant-4ruf23f`) | | `url` | Preview URL (`https://{id}.shipstatic.dev`) | | `files` | Number of files | | `size` | Total size in bytes | | `status` | `pending` → `success` or `failed`; then optionally `deleting` | | `labels` | Mutable tags (3–63 chars, lowercase alphanumeric with `.`/`-`/`_`, max 10) | | `via` | Creation method: `cli`, `sdk`, `web` | | `created` | Creation timestamp | | `expires` | Expiration timestamp (free-tier only) | ### 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. --- ## Domains ### Properties | Property | Description | |----------|-------------| | `domain` | Fully qualified domain name | | `deployment` | Linked deployment ID, or `null` if reserved | | `status` | DNS verification state: `pending`, `partial`, or `success` | | `labels` | Mutable tags for organization | | `verified` | When DNS was last verified | | `created` | Creation timestamp | ### Internal domains Subdomains of `shipstatic.dev` (e.g. `my-app.shipstatic.dev`). - 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 - SSL provisioned automatically after verification - Available on paid plans ### DNS verification Internal 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 | **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 | ### 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. ### 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. - **Internal domain minimum.** Names must be at least 6 characters. - **Deploy tokens are single-use.** Each token is consumed on its first deploy and becomes invalid. - **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 npm install -g @shipstatic/ship ``` ### Deploy ```bash ship # deploy a directory ship --label production --label v1.0 # with labels ship --no-spa-detect --no-path-detect # disable auto-detection ship --json # machine-readable output ``` ### 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 remove ``` ### Tokens ```bash ship tokens create --ttl 3600 --label ci ship tokens list ship tokens remove ``` ### Account ```bash ship whoami # current account ship account get # same as whoami ship ping # API connectivity ship config # setup wizard ship completion install # shell completions ``` ### Global Flags | Flag | Description | |------|-------------| | `--api-key ` | Override API key | | `--deploy-token ` | Use a single-use deploy token | | `--config ` | Custom config file path | | `--label