Universal redirect runtime for fetch-compatible edge platforms (Cloudflare Workers, Vercel Edge Functions, Netlify Edge Functions). It enforces HTTPS, serves a favicon, and applies redirect or proxy rules defined in a remote redirects.json file.
Live previews:
- Primary domain: https://i0c.cc
- Vercel deployment: https://vc.i0c.cc
- Netlify deployment: https://nf.i0c.cc
After deploying:
- Set
REDIRECTS_CONFIG_URLor the repo/branch/path trio in your platform’s dashboard so the runtime can load the correctredirects.json. - Sync secrets across environments if you override other handler options (for example, cache bindings).
- Re-run
npm run buildlocally when updating the shared redirect logic, then redeploy.
- Cloudflare Workers: src/platforms/cloudflare.ts
- Vercel Edge Functions: src/platforms/vercel-edge.ts
- Netlify Edge Functions: src/platforms/netlify-edge.ts
Need a custom runtime? Import handleRedirectRequest from src/lib/handler.ts and call it with your own Request object plus optional HandlerOptions (for example, to override the config URL or provide a custom cache implementation).
ROBOTS_POLICY: Controls therobots.txtpolicy.- Set to
allow: GeneratesAllow: /and includesSitemap.xml. - Set to default or other values: Outputs
Disallow: /and omitsSitemap.xml.
- Set to
You can override the default GitHub location without touching the code. Set any of the environment variables below; the runtime will pick them up automatically on Cloudflare (Worker bindings) or Vercel (process.env).
REDIRECTS_CONFIG_URL(fallback:CONFIG_URL) — Absolute URL of theredirects.json. This short-circuits the repo/branch/path logic.REDIRECTS_CONFIG_REPO(fallback:CONFIG_REPO) — GitHub repo inowner/nameform.REDIRECTS_CONFIG_BRANCH(fallback:CONFIG_BRANCH) — Branch that hosts the data file.REDIRECTS_CONFIG_PATH(fallback:CONFIG_PATH) — Path to the JSON file inside the repo.
If repo, branch, or path are provided (with or without a direct URL), the handler automatically constructs the raw GitHub URL. With no environment overrides, the defaults remain IGCyukira/i0c.cc, branch data, file redirects.json.
You can also deploy the WebUI panel to edit redirects.json online.
Provide a Slots (or slots / SLOT) object in redirects.json to define all routing rules. The table below lists the available fields for each route:
| Field | Type | Default | Description |
|---|---|---|---|
type |
string | prefix |
Route mode: prefix for prefix redirects, exact for exact matches, proxy for reverse proxying |
target |
string | "" |
Destination URL (use exactly one of target / to / url) |
to / url |
string | "" |
Alias fields (use exactly one of target / to / url) |
appendPath |
boolean | true |
Whether to append the remaining path when using prefix / proxy mode (not applicable to exact) |
status |
number | 302 |
HTTP status code for non-proxy responses (do not set for proxy) |
priority |
number | by order | Determines rule precedence for the same path; smaller numbers are matched first |
- Keys must start with
/and can use colon parameters (such as:id) or the*wildcard; captures can be referenced in the target with$1,:id, and so on. - The
proxytype forwards the request to the destination and returns the upstream response; other types respond with aLocationredirect. - To configure multiple rules for the same path, provide an array. Array order controls the default priority, or you can specify
priorityexplicitly. Smaller numbers match earlier.
Tip: add the schema reference below to unlock autocomplete and validation in supporting editors (the schema lives on main, so it still applies if the JSON sits in a data branch):
{
"Slots": {
// Fallback: send any unmatched path to the site homepage
"/": "https://example.com",
// Multiple rules for one path, with priority controlling the order
"/docs/:page": [
{
"type": "exact",
"target": "https://kb.example.com/:page",
"status": 302,
"priority": 1
},
{
"type": "prefix",
"target": "https://docs.example.com/:page",
"appendPath": false,
"status": 301,
"priority": 5
}
],
// Simple redirect: campaign landing page
"/promo": {
"target": "https://example.com/campaign",
"status": 308
},
// API example:
// 1. /api matches the health check exactly and returns 200
// 2. Other requests go to the primary API
// 3. Failover to the backup API if the primary fails
"/api": [
{
"type": "exact",
"target": "https://status.example.com/healthz",
"status": 200,
"priority": 1
},
{
"type": "proxy",
"target": "https://api.example.com",
"appendPath": true,
"priority": 10
},
{
"type": "proxy",
"target": "https://backup-api.example.com",
"appendPath": true,
"priority": 20
}
],
// Wildcard: proxy /media/* to the CDN and keep the remainder of the path
"/media/*": {
"type": "proxy",
"target": "https://cdn.example.com/$1"
},
// Prefix redirect: admin console entry, keeping the original path
"/admin": {
"type": "prefix",
"target": "https://console.example.com",
"appendPath": true,
"status": 307
}
}
}
For the Chinese version, see README.zh-CN.md.

{ "$schema": "https://raw.githubusercontent.com/IGCyukira/i0c.cc/main/redirects.schema.json", "Slots": { // ... } }