Skip to main content

Configuration Settings

Define your short links, analytics trackers, and worker settings through a single JSON configuration file managed by the CLI.

Config File Location

The CLI resolves config.json by checking these locations in order:

  1. Current working directory
  2. Project root (detected by package.json)
  3. user config directory (~/.config/branded-short-links/)

If no config file exists, the CLI copies config.sample.json into the user config directory as a starting point.

Structure

The config file has three top-level sections:

{
  "settings": { ... },
  "links": { ... },
  "trackers": [ ... ]
}

Settings

Controls worker identity and debug behavior.

FieldTypeRequiredDescription
worker_namestringYesName of the Cloudflare Worker deployment.
base_domainstringYesCustom domain for short links (e.g., example.com).
show_response_outputbooleanYesShow masked config on the landing and 404 pages for debugging.
{
  "settings": {
    "worker_name": "branded-short-links",
    "base_domain": "example.com",
    "show_response_output": false
  }
}

Defines the shortcode-to-URL mappings and an optional fallback.

FieldTypeRequiredDescription
fallback_urlstringNoDefault redirect for unmatched shortcodes. Must be a valid URL.
itemsarrayYesArray of link items (see below).

Each item maps a shortcode path to a destination URL with a specific redirect status.

FieldTypeRequiredDescription
shortcodestringYesPath segment starting with / (e.g., /github). Min 2 chars.
http_responsenumberYesHTTP redirect status: 301, 302, 303, 307, or 308.
redirect_urlstringYesDestination URL. Must be a valid URL.
{
  "links": {
    "fallback_url": "https://example.com",
    "items": [
      {
        "shortcode": "/github",
        "http_response": 301,
        "redirect_url": "https://github.com/yourname"
      },
      {
        "shortcode": "/linkedin",
        "http_response": 302,
        "redirect_url": "https://linkedin.com/in/yourname"
      }
    ]
  }
}

Redirect Status Codes

CodeNameUse Case
301Moved PermanentlyPermanent redirect. Search engines transfer link equity.
302FoundTemporary redirect. Original URL retains SEO value.
303See OtherRedirect after POST. Forces GET on the destination.
307Temporary RedirectTemporary redirect. Preserves the original HTTP method.
308Permanent RedirectPermanent redirect. Preserves the original HTTP method.

Shortcode Matching

The worker strips trailing slashes before matching. Query strings and hash fragments are not used for matching and are not forwarded to the redirect destination for matched shortcodes — the redirect always goes to the exact redirect_url from your config. This differs from fallback redirects, which do preserve the original path, query, and hash (see below).

RequestMatched ShortcodeRedirect Destination
https://example.com/github/githubhttps://github.com/yourname
https://example.com/github?ref=twitter/githubhttps://github.com/yourname
https://example.com/github//githubhttps://github.com/yourname
https://example.com/unknown(none)Fallback URL or 404 page

Fallback URL Behavior

When a request doesn't match any shortcode and a fallback_url is configured, the redirect behavior depends on the request path:

  • Root path (/) — Redirects to the fallback URL's origin only (e.g., https://example.com). The original path, query string, and hash are not forwarded.
  • Any other path — Redirects to the fallback URL's origin with the original pathname, query string, and hash fragment preserved (e.g., /about?ref=home#section appended to the fallback origin).

Fallback redirects always use HTTP status 301 (Moved Permanently). This is not configurable — only shortcode redirects use the per-link http_response setting.

When no fallback_url is configured, the root path serves the landing page and all other unmatched paths serve a 404 page.

Trackers

An array of analytics integrations. Each tracker has a type field that determines which additional fields are required. All trackers fire in parallel on every matched shortcode redirect.

See Trackers for the full reference on each tracker type.

Quick Reference

TypeRequired Fields
ga4name, measurement_id, api_secret
facebookname, pixel_id
ntfyname, server, topic, token
ntfy-reverse-proxyname, url; optional: token
posthogname, host, api_key
plain-textname, url; optional: token

Sample Config

The full sample configuration file:

{
  "settings": {
    "worker_name": "branded-short-links",
    "base_domain": "example.com",
    "show_response_output": false
  },
  "links": {
    "fallback_url": "https://example.com",
    "items": [
      {
        "shortcode": "/example",
        "http_response": 301,
        "redirect_url": "https://example.com/destination"
      }
    ]
  },
  "trackers": [
    {
      "name": "my-ga4",
      "type": "ga4",
      "measurement_id": "",
      "api_secret": ""
    }
  ]
}

Validation

Run the validate command to check your config against the schema:

bsl validate

Validation checks:

  • All required fields are present and correctly typed.
  • URLs are valid format.
  • Shortcodes start with / and are at least 2 characters.
  • HTTP response codes are one of the allowed values.
  • No duplicate shortcodes exist.
  • No duplicate tracker names exist.
  • Tracker-specific fields match the declared type (extra fields are rejected).

Environment Variables

The CLI resolves .env by checking these locations in order (same as config resolution):

  1. Current working directory
  2. Project root (detected by package.json)
  3. user config directory (~/.config/branded-short-links/)

The first .env file found is loaded automatically. During first deploy, the CLI saves new tokens to ~/.config/branded-short-links/.env.

VariablePurpose
CLOUDFLARE_API_TOKENAPI token for Cloudflare Workers deployment.
NODE_ENVNode.js environment setting.
LOG_LEVELControls CLI log verbosity.
LOG_TIMEEnables timestamps in CLI log output.