Deploy static sites to Cloudflare R2 with subdomain routing
npm install @just-be/deployDeploy static sites and setup routing for the wildcard subdomain service.
- Bun runtime
- A Cloudflare Workers wildcard subdomain service with R2 and KV configured
The script will automatically run wrangler login if you're not authenticated with Cloudflare. This will open a browser window for OAuth authentication.
Alternatively, you can set the CLOUDFLARE_API_TOKEN environment variable:
``bash`
export CLOUDFLARE_API_TOKEN="your-api-token"
The deploy script requires access to:
- KV namespace for routing rules
- R2 bucket for static file storage
To use different resources, set these environment variables:
`bash`
export KV_NAMESPACE_ID="your-kv-namespace-id"
export R2_BUCKET_NAME="your-bucket-name"
bunx @just-be/deploy
You can find your KV namespace ID and R2 buckets by running:
`bash`
wrangler kv namespace list
wrangler r2 bucket list
No installation needed! Run directly with bunx:
`bash`
bunx @just-be/deploy
Or install globally:
`bash`
bun install -g @just-be/deploy
Create a deploy.json file in your project:
`json`
{
"rules": [
{
"subdomain": "myapp",
"type": "static",
"path": "apps/myapp",
"dir": "./dist",
"spa": true
},
{
"subdomain": "old-site",
"type": "redirect",
"url": "https://new-site.com",
"permanent": true
}
]
}
Then run:
`bash`
bunx @just-be/deploy
`bash`
bunx @just-be/deploy path/to/config.json
Deploy static files to R2 and serve them via a subdomain.
`json`
{
"subdomain": "myapp",
"type": "static",
"path": "apps/myapp",
"dir": "./dist",
"spa": true
}
Options:
- subdomain (required): Subdomain name (e.g., "myapp" for myapp.just-be.dev)type
- (required): Must be "static"path
- (required): R2 path prefix where files will be storeddir
- (required): Local directory containing files to uploadspa
- (optional): Enable SPA mode - all routes serve index.htmlfallback
- (optional): Custom 404 file (cannot be used with spa)
Configure an HTTP redirect from a subdomain to another URL.
`json`
{
"subdomain": "old-site",
"type": "redirect",
"url": "https://new-site.com",
"permanent": true
}
Options:
- subdomain (required): Subdomain nametype
- (required): Must be "redirect"url
- (required): Target URL (must be http/https)permanent
- (optional): Use 301 (permanent) redirect instead of 302 (temporary)
Proxy requests from a subdomain to another URL.
`json`
{
"subdomain": "api",
"type": "rewrite",
"url": "https://api.example.com",
"allowedMethods": ["GET", "POST", "PUT", "DELETE"]
}
Options:
- subdomain (required): Subdomain nametype
- (required): Must be "rewrite"url
- (required): Target URL to proxy to (must be http/https)allowedMethods
- (optional): HTTP methods allowed (default: ["GET", "HEAD", "OPTIONS"])
`json`
{
"rules": [
{
"subdomain": "portfolio",
"type": "static",
"path": "sites/portfolio",
"dir": "./build",
"fallback": "404.html"
},
{
"subdomain": "docs",
"type": "static",
"path": "sites/docs",
"dir": "./out",
"spa": true
},
{
"subdomain": "blog",
"type": "static",
"path": "sites/blog",
"dir": "./dist"
}
]
}
`json`
{
"rules": [
{
"subdomain": "app",
"type": "static",
"path": "apps/main",
"dir": "./dist",
"spa": true
},
{
"subdomain": "legacy",
"type": "redirect",
"url": "https://app.just-be.dev",
"permanent": true
},
{
"subdomain": "api",
"type": "rewrite",
"url": "https://backend.example.com",
"allowedMethods": ["GET", "POST", "PUT", "DELETE", "PATCH"]
}
]
}
The package includes a JSON Schema (deploy.schema.json) for editor validation and autocomplete. Many editors will automatically provide validation and suggestions for deploy.json files.
1. Parses configuration from deploy.json@just-be/wildcard
2. Validates all rules using Zod schemas from content-bucket/{path}/{relative-path}
3. For static sites:
- Scans the local directory for all files
- Uploads each file to R2 at
- Creates a KV entry with routing configuration
4. For redirects/rewrites:
- Creates a KV entry with the routing configuration
5. Configures the wildcard service to route requests for each subdomain
The script works with any wildcard service that has:
- R2 Bucket: For storing static files (default: content-bucket)6118ae3b937c4883b3c582dfef8a0c05
- KV Namespace: For routing rules (default: )
No local wrangler.toml file is required - the script accesses Cloudflare resources directly via the Wrangler CLI.
Configuration is validated using Zod schemas to ensure:
- Valid subdomain format (alphanumeric with hyphens, 1-63 characters)
- SPA mode and fallback file are not used together
- Required fields are present for each rule type
- URLs are safe (http/https only)
- @just-be/wildcard` - Shared Zod schemas and routing handlers for wildcard subdomain configuration
MIT