ship.json
An optional ship.json file in the root of your project configures how the platform serves your deployment. Most sites work perfectly without one — add it only when you need redirects, rewrites, headers, or URL formatting.
Clean URLs
Remove .html extensions from URLs. When enabled, /about.html is served at /about. Visiting /about.html redirects to /about.
{
"cleanUrls": true
}
Trailing Slash
Control trailing slash behavior for all URLs.
| Value | Behavior |
|---|---|
false |
/about/ redirects to /about |
true |
/about redirects to /about/ |
| not set | Both forms serve content without redirecting |
{
"trailingSlash": false
}
Redirects
Send visitors from one URL to another. The browser URL changes.
{
"redirects": [
{ "source": "/pricing", "destination": "/plans", "permanent": true },
{ "source": "/blog/:slug", "destination": "/posts/:slug", "permanent": true }
]
}
| Property | Type | Required | Description |
|---|---|---|---|
source |
string | Yes | Pattern to match |
destination |
string | Yes | Target URL or path |
permanent |
boolean | No | true = 308, false = 307. Default: true |
Pattern syntax
Named parameters match a single path segment:
{ "source": "/blog/:slug", "destination": "/posts/:slug" }
Wildcards match everything after:
{ "source": "/docs/:path*", "destination": "/help/:path*" }
Rewrites
Serve content from a different path without changing the browser URL. Files on disk are checked first — rewrites only apply when no file matches.
{
"rewrites": [
{ "source": "/feed", "destination": "/feed.xml" }
]
}
| Property | Type | Required | Description |
|---|---|---|---|
source |
string | Yes | Pattern to match |
destination |
string | Yes | Target path or URL |
The same pattern syntax as redirects applies (:param, :path*).
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:
{
"rewrites": [
{ "source": "/(.*)", "destination": "/index.html" }
]
}
Headers
Add custom HTTP response headers. Unlike redirects and rewrites, multiple header rules can match the same request.
{
"headers": [
{
"source": "/assets/(.*)",
"headers": [
{ "key": "Cache-Control", "value": "public, max-age=31536000, immutable" }
]
}
]
}
| Property | Type | Required | Description |
|---|---|---|---|
source |
string | Yes | Pattern to match |
headers |
array | Yes | Key-value pairs to set |
Processing Order
Rules are evaluated in this order:
- Static files — served first if they exist on disk
- Headers — all matching rules apply
- Redirects — checked before rewrites
- Rewrites — only when no file or redirect matched
Within redirects and rewrites, rules are processed in array order. Put catch-all patterns last.