Configuration Reference
All values are strings. Boolean switches use true unless noted.
What most people need
- Always: Google sign-in (
NUXT_SESSION_SECRET,NUXT_GOOGLE_CLIENT_ID,NUXT_GOOGLE_CLIENT_SECRET),NUXT_SITE_TOKENfor API access, D1 (DB), KV (KV), and their IDs - For analytics:
ANALYTICSbinding +NUXT_CF_ACCOUNT_ID+NUXT_CF_API_TOKEN— see Analytics - Everything else is optional
Where to put variables
Think of two moments:
| When | Meaning | Where to set |
|---|---|---|
| At build time | Used while Cloudflare builds/publishes the app | Workers Builds → Variables |
| At runtime | Used while the live app is running | Worker Settings → Variables and Secrets |
| Both | Needed in the built UI and at runtime (for example public UI settings) | Set the same value in Builds and Worker settings |
After changing public/build values
Trigger a new deploy so the app rebuilds. Values that are needed at both moments must match in both places.
Names starting with DEPLOY_* are only for connecting resources during deploy. They rewrite placeholders in tracked wrangler.jsonc into gitignored wrangler.deploy.jsonc — set DEPLOY_* in .env or Cloudflare build variables; do not hardcode production IDs in wrangler.jsonc. Names starting with NUXT_* configure the running app.
Cloudflare bindings
A binding connects a Cloudflare product to Sink under a fixed name.
| Binding | Required? | Description |
|---|---|---|
DB | Yes | D1 database — stores links |
KV | Yes | Fast cache for redirects (+ storage-ready flag) |
ANALYTICS | Recommended | Visit events for analytics |
R2 | Optional | File storage for backups and social images. Set DEPLOY_R2_BUCKET_NAME to attach a bucket |
AI | Optional | Workers AI suggestions |
ASSETS | Automatic | Static files — provided for you |
Analytics is optional. Without it, short links and the dashboard still work; charts stay empty. Setup: Analytics.
Required
NUXT_SITE_TOKEN
Set this yourself. It is the API password (MCP, scripts, curl with a Bearer header). At least 8 characters without whitespace; longer is better. Keep it stable. Signing in to the dashboard uses Google, not this token.
If you leave it empty, Sink may invent a random password at build time that can change on the next deploy.
| Variable | When | Where | Purpose |
|---|---|---|---|
NUXT_SITE_TOKEN | Runtime (secret) | Encrypted secret on the Worker | API password (MCP, scripts, curl) |
NUXT_SESSION_SECRET | Runtime (secret) | Encrypted secret on the Worker | Signs dashboard sessions — Google sign-in fails without it |
NUXT_GOOGLE_CLIENT_ID | Runtime | Worker variable | Google OAuth client (Web application) |
NUXT_GOOGLE_CLIENT_SECRET | Runtime (secret) | Encrypted secret on the Worker | Google OAuth client secret |
DEPLOY_D1_DATABASE_ID | Build | Workers Builds variables | D1 database ID (from the D1 detail page) |
DEPLOY_KV_NAMESPACE_ID | Build | Workers Builds variables | KV namespace ID (from the KV detail page) |
Create the OAuth client in the Google Cloud console with the authorized redirect URI https://<your-domain>/api/auth/google/callback (plus the localhost variants for development — see Getting started).
Recommended (analytics)
| Variable | When | Where | Purpose |
|---|---|---|---|
NUXT_CF_ACCOUNT_ID | Runtime | Worker variable | Your Cloudflare account ID |
NUXT_CF_API_TOKEN | Runtime (secret) | Encrypted secret | Custom Token with Account → Account Analytics → Read only |
Also bind ANALYTICS. Add R2 for backups, AI for Workers AI. Token steps: Analytics.
Public overrides (only if you change defaults)
Set the same value in Workers Builds and in the Worker runtime.
| Variable | Default | Purpose |
|---|---|---|
NUXT_PUBLIC_PREVIEW_MODE | empty | true = demo mode (links last 5 minutes) |
NUXT_PUBLIC_SLUG_DEFAULT_LENGTH | 6 | Length of auto-generated short codes |
NUXT_PUBLIC_KV_BATCH_LIMIT | 50 | Export page size; import accepts at most half per request |
NUXT_PUBLIC_MAX_URL_LENGTH | 16384 | Maximum target URL length in characters (256-24000) |
NUXT_PUBLIC_HOME_URL | empty | Non-empty URL redirects /; empty shows the Sink homepage |
NUXT_PUBLIC_LINK_PROXY_ENABLED | false | true allows links to opt into reverse proxy mode; off, stored proxy links fall back to redirects |
NUXT_PUBLIC_* values are baked into the built UI and read at runtime, so changes need a rebuild before the client picks them up.
NUXT_HOME_URL is the deprecated name of NUXT_PUBLIC_HOME_URL. It still works, but rename it when you next change your settings.
Click analytics store the target URL in Workers Analytics Engine, which limits all blobs in a data point to 16 KB in total. When the URL plus the other click fields (user agent, referer, and so on) exceeds that size, which is possible near the default 16384-character limit, the click still redirects but is missing from analytics. Lower NUXT_PUBLIC_MAX_URL_LENGTH if complete analytics matter more than long URLs.
Optional
Build-time options
| Variable | Where | When it turns on |
|---|---|---|
NUXT_API_CORS | Build variables | Exactly true allows browser apps on other sites to call /api/** (CORS). Login is still required |
DEPLOY_R2_BUCKET_NAME | Workers Builds only | Set to an existing R2 bucket name to attach R2 (bucket_name) |
DEPLOY_KV_PREVIEW_NAMESPACE_ID | Workers Builds variables | Optional Wrangler preview_id; defaults to DEPLOY_KV_NAMESPACE_ID |
DEPLOY_R2_PREVIEW_BUCKET_NAME | Workers Builds only | Optional Wrangler preview_bucket_name; defaults to DEPLOY_R2_BUCKET_NAME when R2 is enabled |
Runtime options
| Variable | Purpose |
|---|---|
NUXT_SUPER_ADMIN_EMAILS | Comma-separated emails granted the superadmin role (the instance owner) |
NUXT_AUTH_ALLOWED_EMAILS + NUXT_AUTH_ALLOWED_DOMAINS | Both empty → any Google account may sign in; set either to restrict who joins |
NUXT_SESSION_TTL_DAYS | Dashboard session lifetime in days (default 30) |
NUXT_NOT_FOUND_REDIRECT | Where to send unknown short codes (always HTTP 302) |
NUXT_CF_ACCESS_TEAM_DOMAIN + NUXT_CF_ACCESS_AUD | Both set → enable Cloudflare Access |
NUXT_SAFE_BROWSING_DOH | DNS-over-HTTPS URL used to check unsafe domains when unsafe is not set |
NUXT_WEBHOOK_URL | HTTP(S) URL for click webhooks |
NUXT_WEBHOOK_SECRET | Optional signing secret starting with whsec_ |
Safe browsing example: Cloudflare Family DNS https://family.cloudflare-dns.com/dns-query. See also Link Features.
Advanced defaults (usually leave alone)
| Variable | Default | Purpose |
|---|---|---|
NUXT_REDIRECT_STATUS_CODE | 301 | Normal redirect code (302 / 307 / 308 also work). Unknown-slug redirects stay 302 |
NUXT_LINK_CACHE_TTL | 60 | How long KV caches a link (seconds) |
NUXT_REDIRECT_WITH_QUERY | false | true appends visitor query params to the target URL |
NUXT_REDIRECT_NO_STORE | false | true asks browsers not to cache the redirect |
NUXT_CASE_SENSITIVE | false | true keeps custom short-code case (Docs ≠ docs) |
NUXT_DATASET | sink | Analytics dataset name; must match the ANALYTICS binding |
NUXT_LIST_QUERY_LIMIT | 500 | Max rows in analytics lists |
NUXT_API_KEY_RATE_LIMIT | 120 | Requests per minute allowed for a single API key; 0 disables the throttle |
NUXT_DISABLE_BOT_ACCESS_LOG | false | true drops detected bots from analytics and webhooks |
NUXT_DISABLE_AUTO_BACKUP | false | true turns off scheduled R2 backups |
NUXT_AI_MODEL | @cf/qwen/qwen3-30b-a3b-fp8 | Workers AI model |
NUXT_AI_PROMPT | built-in | Custom slug prompt must keep {slugRegex} |
NUXT_AI_OG_PROMPT | built-in | Custom social-preview prompt |
DEPLOY_D1_DATABASE_NAME | sink | Overrides d1_databases[].database_name in generated deploy config |
DEPLOY_ANALYTICS_DATASET | sink | Overrides analytics_engine_datasets[].dataset in generated deploy config; keep aligned with NUXT_DATASET |