Aller au contenu

43 questions

FAQ

FAQ source en anglais sur l'exploitation, la securisation, et la mise à jour d'une instance vanityURLs.

The FAQ inventory is currently maintained in English. French parity is planned after the questions stabilize.

Getting Started

1
What do I need before starting setup?
You need a short domain using Cloudflare DNS, a GitHub account and repository, a Cloudflare account, Git, Node.js 20 or newer, npm, and a text editor. After cloning, the normal path is npm run detach, npm install, npm run setup, npm run local-install, and npm run check.
operator high priority
Evidence
  • vanityURLs/code README.md — Quickstart lists a registered short domain, GitHub and Cloudflare accounts, Git, Node.js 20+, npm, and a text editor.
  • vanityURLs/code package.json — Project scripts include setup, local-install, check, and deploy workflows.

Architecture

7
How does vanityURLs work without a database?
vanityURLs compiles link and policy source files into static runtime JSON that the Cloudflare Worker reads from the Static Assets binding. There is no account database or mutable click store in the default runtime; Git is the system of record.
operator contributor high priority
Evidence
  • vanityURLs/code README.md — Links, schedules, destination policies, localized pages, and operator configuration live in Git.
  • vanityURLs/code scripts/build.mjs — Build writes build/v8s.json, build/v8s-blocklist.json, build/v8s-site-config.json, and build/v8s-custom-assets.json for the Worker.
Is vanityURLs a hosted URL shortener like Bitly, Short.io, or Dub?
No. vanityURLs is open-source software for running your own branded short-link instance on your Cloudflare account and domain. The public docs site is not a shared link-shortening service.
operator end-user high priority
Evidence
  • vanityURLs/code README.md — Quickstart instructs operators to clone the code, configure their own domain, and deploy their own Worker.
What is build/v8s.json?
build/v8s.json is the generated runtime link registry consumed by the Worker. Humans edit the source link registry in custom/v8s-links.txt; the build validates that source and compiles it into this runtime JSON. Treat build/v8s.json as generated output, not hand-edited source.
operator contributor high priority
Evidence
  • vanityURLs/code scripts/build.mjs — buildRedirectTargets writes the generated runtime link registry, build/v8s.json, from custom/v8s-links.txt or defaults/v8s-links.txt.
  • vanityURLs/code scripts/validate-runtime-registry.mjs — Runtime link registry schema 3.1 validates links, routing, states, and tree shape.
Why does vanityURLs use Node.js if it runs on Cloudflare Workers?
Node.js is used for local tooling: setup prompts, builds, validation, tests, and helper commands. The deployed redirector runs on the Cloudflare Workers serverless platform, which executes JavaScript at the edge. The same language family lets the project share validation and build conventions across Linux, macOS, Windows, and Cloudflare Workers without shipping a native server process.
operator contributor medium priority
Evidence
  • vanityURLs/code package.json — Project scripts run setup, build, tests, local helper install, and maintenance commands with Node.
  • vanityURLs/code wrangler.toml — The deployed runtime is a Cloudflare Worker generated from source under scripts/workers/.
Are commands like lnk and v8s-fix real CPU-specific binaries?
They are executable scripts, not compiled CPU-specific binaries. The shebang asks the operating system to launch node, then Node runs the text file. You do not need separate Apple Silicon, Intel, Linux, or Windows builds; you need a compatible Node.js runtime and the script file copied with executable permissions on Unix-like systems.
operator contributor medium priority
Evidence
  • vanityURLs/code scripts/lnk — The command starts with #!/usr/bin/env node.
  • vanityURLs/code scripts/v8s-fix — The command is an executable Node wrapper for the maintenance implementation.
  • vanityURLs/code scripts/local-install.mjs — Local install copies executable scripts into the configured user bin directory.
What does the .mjs file extension mean?
.mjs marks a JavaScript file as an ES module. ES modules use import and export syntax and match the module style used by modern Node.js tooling and Cloudflare Workers. In vanityURLs, .mjs files are still JavaScript; the extension mainly makes the module format explicit.
operator contributor medium priority
Evidence
  • vanityURLs/code package.json — The package declares type: module, and most project scripts use ES module syntax.
  • vanityURLs/code scripts/build.mjs — Build tooling imports Node modules and project helpers with ES module import syntax.
  • vanityURLs/code scripts/workers/worker.mjs — The Worker source is also an ES module.
Which HTTP methods does the Worker accept?
Public redirect and page requests use GET or HEAD; OPTIONS receives a quiet 204. Other methods return 405 Method not allowed, with POST /lookup/resolve reserved for lookup resolution and POST /_analytics/lookup reserved for the lookup-page beacon. Sandboxed custom HTML can call those two public lookup endpoints with Origin: null; protected endpoints remain locked down.
operator contributor trust-safety medium priority
Evidence
  • vanityURLs/code scripts/workers/worker.mjs — Worker accepts GET, HEAD, OPTIONS, POST /lookup/resolve, and POST /_analytics/lookup; other methods return 405.
  • vanityURLs/website content/docs/reference/runtime-security.en.md — Runtime security docs list accepted public methods.

Deployment

6
How is a vanityURLs instance deployed?
The build generates build/ and src/, then Cloudflare deploys src/worker.mjs with a Static Assets binding for build/. You can deploy manually with npx wrangler deploy --config wrangler.toml or let Cloudflare Workers & Pages run the build and deploy from Git.
operator contributor high priority
Evidence
  • vanityURLs/code wrangler.toml — Worker uses src/worker.mjs with an ASSETS binding pointed at ./build and run_worker_first rules.
  • vanityURLs/code package.json — deploy runs wrangler deploy; build runs scripts/build.mjs.
Should I run npm run update or npm run update -- --ref main?
For a normal production instance, run npm run update. It refreshes product-owned files from the latest stable vanityURLs release tag. Use npm run update -- --ref main only when you intentionally want unreleased code, usually on a test instance or while validating a fix with maintainers. If you upgrade from main, commit that choice clearly and switch back to the normal command after the next release is published. See Upgrading an instance for the full workflow.
operator contributor high priority
Evidence
  • vanityURLs/code scripts/upgrade.mjs — Default upgrades resolve the latest stable upstream release tag; --ref main opts into a mutable branch.
  • vanityURLs/website content/docs/reference/upgrading.en.md — The upgrading reference documents release-tag upgrades and the maintainer/testing use of --ref main.
Does vanityURLs use Cloudflare Pages?
The current runtime is a Cloudflare Worker using Static Assets, not a Cloudflare Pages _redirects site. Some Cloudflare dashboards still mention Workers & Pages, but the deployed application is the Worker configured in wrangler.toml.
operator contributor medium priority
Evidence
  • vanityURLs/code wrangler.toml — The runtime is a Cloudflare Worker with an [assets] binding, not a Pages _redirects deploy.
  • vanityURLs/code package.json — The 3.0.0 release keeps the Cloudflare Worker as the current runtime.
Which files are generated and should not be edited directly?
Treat build/ and generated src/ as build output. Edit source files in custom/, product files in defaults/ or scripts/ only when contributing upstream, then rebuild with npm run build or npm run check.
operator contributor high priority
Evidence
  • vanityURLs/code scripts/build.mjs — Build cleans and regenerates build/ and copies Worker source from scripts/workers/ to src/.
  • vanityURLs/website content/docs/reference/repository-layout.en.md — Repository layout docs classify build/ and src/ as generated output.
What should an instance repository commit?
Commit instance source files such as custom/, wrangler.toml, and normal repository metadata. Do not commit regenerated build/, src/, or other transient output unless the project documentation changes to require it.
operator high priority
Evidence
  • vanityURLs/code scripts/clean.mjs — Clean removes generated output.
  • vanityURLs/website content/docs/reference/repository-layout.en.md — Docs separate product-owned files, instance-owned files, and generated output.
What does npm run update or npm run upgrade replace?
The upgrade workflow refreshes product-owned files such as defaults/, scripts/, package manifests, and LICENSE. It refuses protected local paths including custom/, wrangler.toml, .dev.vars, and README.md.
operator high priority
Evidence
  • vanityURLs/code scripts/upgrade.mjs — Default upgrade paths are defaults, scripts, package.json, package-lock.json, and LICENSE; protected paths include custom, wrangler.toml, .dev.vars, and README.md.
  • vanityURLs/code package.json update is an alias for npm run upgrade.

Command Line

4
What does the lnk CLI manage?
./scripts/lnk manages local source files for links, schedules, random slug defaults, tags, and block policies. Successful write operations are designed to run checks and publish locally, so review its behavior before using it in a repository with custom Git-signing requirements.
operator contributor high priority
Evidence
  • vanityURLs/code scripts/lnk — Usage covers links, schedules, tags, random slug settings, policy lists, blocked domains, blocked keywords, and allowed domains.
  • vanityURLs/website content/docs/command-line-interface/lnk.en.md — The docs describe local link-management workflows.
What does npm run local-publish do?
npm run local-publish is a workstation convenience for validated instance changes: it runs checks, stages configured paths, chooses a commit message, commits, and pushes. Operators with required manual signing prompts should review this workflow before enabling it.
operator medium priority
Evidence
  • vanityURLs/code README.md — Local workflow says local-publish handles checks, commit selection, and push.
  • vanityURLs/code docs/schema-changelog.md — v8s-local-config.json includes local_publish paths and commit messages.

Operator Configuration

3
Why are there both defaults/ and custom/ directories?
defaults/ is the upstream product baseline; custom/ is the instance-owned overlay. Keeping local changes in custom/ lets npm run upgrade refresh product files without trampling instance links, branding, policies, or legal choices.
operator contributor high priority
Evidence
  • vanityURLs/code docs/adr/0002-keep-instance-changes-in-custom.md — ADR establishes the split between upstream defaults and instance-owned changes.
  • vanityURLs/website content/docs/reference/repository-layout.en.md — Docs explain product-owned defaults and instance-owned custom files.
Which operator fields must be real before launch?
Generated legal and trust pages require real operator values for legal identity, short domain, jurisdiction, governing law, contact emails, last updated date, analytics disclosure, and abuse response window. Placeholder values are treated as configuration issues instead of launch-ready content.
operator trust-safety high priority
Evidence
  • vanityURLs/code scripts/build.mjs — validateOperatorConfig requires legal_name, short_domain, jurisdiction, governing_law, contact, privacy, abuse, security, last_updated, analytics disclosure, and abuse window fields.
  • vanityURLs/code docs/schema-changelog.md — Schema changelog lists expanded operator fields for privacy, terms, trust, security, and security.txt output.

Privacy

3
Are clicks logged by default?
The architecture has no built-in click database. Redirect, miss, pageview, and lookup events are sent only when an optional analytics provider is configured for the Worker.
operator end-user trust-safety high priority
Evidence
  • vanityURLs/code scripts/workers/worker.mjs — Redirect events call logAnalyticsEvent with ctx.waitUntil, which is a no-op unless analytics provider variables are configured.
  • vanityURLs/website content/docs/reference/analytics.en.md — Docs state analytics runs server-side and is configured with Worker variables.
How is visitor IP handled when Umami is enabled?
UMAMI_GEO_IP_MODE controls whether the Worker forwards full, truncated, or no visitor IP information to Umami. If Umami is configured and the mode is missing or invalid, the documented default is truncated.
operator end-user trust-safety high priority
Evidence
  • vanityURLs/code scripts/build.mjs — deriveUmamiGeoIpMode uses UMAMI_GEO_IP_MODE and defaults to truncated for Umami.
  • vanityURLs/website content/docs/reference/analytics.en.md — Analytics reference documents full, truncated, and none modes for Umami IP handling.
Why does the privacy model mention GDPR Article 11?
The default architecture does not create visitor accounts or a per-click identity database, so operators can explain that the redirector is not designed to identify visitors. That architectural fact does not remove obligations created by optional analytics, Cloudflare logs, local law, or operator-added tooling.
operator trust-safety medium priority
Evidence
  • vanityURLs/website content/docs/reference/analytics.en.md — Analytics docs distinguish architectural statelessness from optional provider collection.
  • vanityURLs/code README.md — The product stores links and operator configuration in Git rather than visitor accounts.

Analytics

1
Which analytics providers does vanityURLs support?
The documented provider choices are Umami and Fathom, configured through Worker variables and secrets. Both are server-side integrations from the Worker rather than browser JavaScript trackers.
operator high priority
Evidence
  • vanityURLs/website content/docs/reference/analytics.en.md — Analytics reference documents Umami and Fathom variables and payloads.
  • vanityURLs/code scripts/workers/worker.mjs — Runtime sends pageview, redirect, miss, lookup, and bot events through provider-specific analytics functions.

Scheduling

2
How do scheduled links choose a destination?
Scheduled links evaluate rules in order using the configured timezone, weekdays, and from/to window. The first active rule wins; if none match, the link uses its normal target.
operator end-user high priority
Evidence
  • vanityURLs/code scripts/workers/worker.mjs — resolveScheduledTarget checks schedule rules in order and uses timezone-aware weekday/time windows.
  • vanityURLs/website content/docs/reference/schedules.en.md — Schedule docs state that the first active rule wins and the normal link target is used otherwise.
Which timezone does a scheduled link use?
A schedule rule uses its own timezone when present; otherwise the Worker falls back to UTC. Use an IANA timezone such as America/Toronto to avoid guessing around daylight saving time.
operator medium priority
Evidence
  • vanityURLs/code scripts/workers/worker.mjs — Schedule rules use rule.timezone or UTC and Intl.DateTimeFormat for evaluation.
  • vanityURLs/code docs/schema-changelog.md — Inline @schedule rules support timezone at schedule and rule level.
Related: schedule-cli

Destination Policies

5
What link lifecycle states exist?
A link can be permanent, ephemeral, expired, disabled, maintenance, or deactivated. The Worker resolves the effective state before redirecting, so state pages or error routes can replace a normal redirect.
operator end-user high priority
Evidence
  • vanityURLs/code scripts/lnk — VALID_STATES are permanent, ephemeral, expired, disabled, maintenance, and deactivated.
  • vanityURLs/code scripts/validate-runtime-registry.mjs — The generated runtime registry must define routing for every required state.
What happens when a link has passed expires_at?
When expires_at is a valid date in the past, the Worker treats the link as expired even if the stored state is different. The default expired route serves the expired state page instead of the destination.
operator end-user high priority
Evidence
  • vanityURLs/code scripts/workers/worker.mjs — getEffectiveState returns expired when expires_at is a valid past date.
  • vanityURLs/code scripts/validate-runtime-registry.mjs — expires_at must parse as a valid date when present.
Which HTTP statuses do state pages return?
The built-in state pages return meaningful status codes: disabled links return 403, expired links return 410, and maintenance links return 503. Deactivated links fall through to the not-found flow.
operator end-user trust-safety medium priority
Evidence
  • vanityURLs/code scripts/workers/worker.mjs — disabled returns 403, expired returns 410, and maintenance returns 503.
How does vanityURLs prevent unsafe redirect destinations?
Build-time policy and runtime sanitation focus on HTTP(S) destinations without embedded credentials, private-network targets, localhost targets, or known risky destination patterns. Operators can replace the source policy in custom/v8s-policies.json.
operator trust-safety destination-owner high priority
Evidence
  • vanityURLs/code defaults/v8s-policies.json — Default policy blocks private networks, localhost, auth-in-URL, unsafe protocols, and executable-style extensions.
  • vanityURLs/code scripts/workers/worker.mjs — sanitizeRedirectTarget only allows http(s), requires a hostname, and rejects username/password in redirect targets.
Does custom/v8s-policies.json merge with the default policy?
No. When custom/v8s-policies.json exists, it replaces the selected default policy source for the instance. This makes local policy ownership explicit and prevents removed local decisions from reappearing through an implicit merge. An empty or minimal custom policy is valid; copy defaults/v8s-policies.json into custom/ only when you want the defaults as an editable template.
operator contributor medium priority
Evidence
  • vanityURLs/code scripts/build.mjs — copyRuntimeBlocklist chooses custom/v8s-policies.json when it exists; otherwise defaults/v8s-policies.json.
  • vanityURLs/code docs/adr/0003-custom-policy-replaces-default-policy.md — ADR records replacement semantics for custom policy.

Localization

2
How does the Worker choose a localized page?
For localizable HTML assets, the Worker checks Accept-Language against the configured supported languages and serves the first available localized file. If no localized file is available, it falls back to the root asset, which is normally English.
operator end-user medium priority
Evidence
  • vanityURLs/code scripts/workers/worker.mjs — fetchLocalizedAsset checks Accept-Language against generated LOCALIZED_HTML_LANGUAGES and falls back to the root asset.
  • vanityURLs/code scripts/build.mjs — Build patches LOCALIZED_HTML_LANGUAGES from supported languages in v8s-site-config.json.
How do I customize public pages and assets?
Put instance-owned public assets and page replacements under custom/public/. During build, vanityURLs copies defaults/public/ first and then overlays custom/public/, so custom files win without editing upstream defaults. Product-owned runtime CSS and JavaScript use v8s- filenames and should normally stay in defaults/public/; copying them to custom/public/ creates a local shadow that can go stale after upgrades. Custom HTML receives a sandboxed compatibility profile that still allows same-host custom CSS, JavaScript, inline styles, inline scripts, forms, popups, downloads, and public lookup calls.
operator medium priority
Evidence
  • vanityURLs/code scripts/build.mjs — copyPublic overlays custom/public/ on top of defaults/public/ when custom public files exist and records them in build/v8s-custom-assets.json.
  • vanityURLs/website content/docs/reference/custom-overrides.en.md — Custom overrides docs explain instance-owned file overlays.

Trust And Safety

6
How does security.txt work?
The Worker redirects /security.txt to /.well-known/security.txt with a permanent redirect. The generated file depends on {{operator.short_domain}}, {{operator.security_contact}}, and {{operator.last_updated}}.
operator trust-safety high priority
Evidence
  • vanityURLs/code scripts/workers/worker.mjs /security.txt redirects to /.well-known/security.txt; the canonical path is served from assets.
  • vanityURLs/code scripts/build.mjs — Generated security.txt uses operator.short_domain, operator.security_contact, and operator.last_updated.
Which paths should Cloudflare Access protect?
The Worker treats localized stats paths such as /en/_stats/ and /fr/_stats/, and localized tests paths such as /en/_tests/ and /fr/_tests/, as protected operational paths. Configure the Cloudflare Access application for */_stats, */_stats/*, */_tests, and */_tests/* path patterns. Legacy /_stats redirects to /en/_stats/, and legacy /_tests redirects to /en/_tests/. If CF_ACCESS_TEAM_DOMAIN or CF_ACCESS_AUD is missing, protected paths fail closed with 503 instead of becoming public.
operator high priority
Evidence
  • vanityURLs/code scripts/workers/worker.mjs — Localized stats and tests paths require Cloudflare Access JWT validation; legacy /_stats redirects to /en/_stats/ and legacy /_tests redirects to /en/_tests/.
  • vanityURLs/website content/docs/customize/access-control.en.md — Access control docs describe protecting operational surfaces.
What does vanityURLs verify for Cloudflare Access?
For protected paths, the Worker checks the cf-access-jwt-assertion token against the configured Cloudflare Access team domain and audience. It validates the token algorithm, issuer, audience, time window, and RS256 signature from the Access JWKS.
operator contributor medium priority
Evidence
  • vanityURLs/code scripts/workers/worker.mjs — Access JWT verification checks RS256, issuer, audience, validity window, and JWKS signature.
Why does vanityURLs use both Worker checks and Cloudflare security settings?
The Worker keeps application behavior deterministic, while Cloudflare edge controls should reject noisy traffic before it spends Worker CPU or analytics quota. Use both layers: Cloudflare for high-volume network protection, and Worker checks for application-specific redirect safety.
operator contributor trust-safety high priority
Evidence
  • vanityURLs/code scripts/workers/worker.mjs — Worker blocks scanner probes, unsafe methods, private runtime files, and protected paths.
  • vanityURLs/website content/blog/layering-cloudflare-protection-around-a-short-link-domain.en.md — Blog explains why WAF, bot controls, Access, and analytics layers answer different operational questions.
How are scanner probes handled?
Known scanner paths are matched against the incoming request before short-link lookup. Matching probes receive a plain no-store 404 and should not become normal short-link misses.
operator trust-safety medium priority
Evidence
  • vanityURLs/code scripts/workers/worker.mjs — findScannerProbe loads v8s-blocklist.json and matches request-scoped scanner keywords before redirect lookup.
  • vanityURLs/code defaults/v8s-policies.json — Default policy includes scanner-probe keywords for common PHP, WordPress, repository, and admin paths.
How should someone report an abusive short link?
Send a report to {{operator.abuse_contact}} and include the short URL, destination if known, why it is harmful, and any supporting evidence. The default instance also publishes /abuse-report.md as a structured template.
end-user destination-owner trust-safety high priority
Evidence
  • vanityURLs/code scripts/build.mjs — Generated Trust & Safety page directs reports to {{operator.abuse_contact}} and references /abuse-report.md.
  • vanityURLs/code defaults/public/abuse-report.md — Default abuse report template is shipped as a public asset.

Terms And Liability

2
Who is responsible for a deployed vanityURLs instance?
The instance operator configured in custom/v8s-site-config.json is responsible for the domain, destinations, legal pages, abuse response, and operational choices for {{operator.short_domain}}. vanityURLs supplies code and defaults; it does not become the operator of each deployed instance.
operator end-user trust-safety high priority
Evidence
  • vanityURLs/code scripts/build.mjs — Generated terms identify {{operator.legal_name}} as the operator of {{operator.short_domain}}.
  • vanityURLs/code defaults/v8s-site-config.json — operator fields include legal name, domain, jurisdiction, contact, privacy, abuse, and security contacts.
Does publishing a short link endorse the destination?
No. Generated terms state that short links may redirect to third-party websites and that publishing a short link does not endorse the destination or its operator. Abuse reports should target the short link and, when appropriate, the destination host or registrar too.
end-user destination-owner trust-safety operator medium priority
Evidence
  • vanityURLs/code scripts/build.mjs — Generated terms say third-party destinations are not controlled, monitored, or endorsed by the operator.

Comparison

1
When is vanityURLs a better fit than a hosted shortener?
vanityURLs is a strong fit when you want links as code, Git history, self-operated Cloudflare infrastructure, and no shared hosted-service account surface. Hosted shorteners usually win when you need a managed dashboard, team permissions, built-in billing support, or a public API without running your own deployment.
operator contributor medium priority
Evidence
  • vanityURLs/code README.md — Project emphasizes branded short-link domains as code on Cloudflare Workers.
  • https://dub.co/pricing — Hosted developer shortener pricing and feature tiers are organized around accounts and plans.
  • https://bitly.com/pages/pricing — Mainstream hosted shortener pricing is plan-based.