<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Fully branded short URLs via continuous integration on vanityURLs</title><link>https://www.vanityurls.link/en/</link><description>Recent content in Fully branded short URLs via continuous integration on vanityURLs</description><generator>Hugo</generator><language>en-CA</language><atom:link href="https://www.vanityurls.link/en/index.xml" rel="self" type="application/rss+xml"/><item><title>Redirects as Code: Managing Short Links the GitOps Way</title><link>https://www.vanityurls.link/en/blog/redirects-as-code/</link><pubDate>Mon, 10 Mar 2025 00:00:00 +0000</pubDate><guid>https://www.vanityurls.link/en/blog/redirects-as-code/</guid><description>&lt;p&gt;Most URL shorteners are black boxes. You log in through a web UI, create a link, and hope the service stays running. When something breaks — a link stops working, a campaign URL points to the wrong page, someone accidentally deleted a redirect — there&amp;rsquo;s no audit trail, no rollback, no way to know who changed what and when.&lt;/p&gt;
&lt;p&gt;vanityURLs takes a different approach: your redirects live in a plain text file, in a Git repository, deployed via Cloudflare Pages. This is GitOps applied to URL management.&lt;/p&gt;</description></item><item><title>Why vanityURLs? The case for owning your short links</title><link>https://www.vanityurls.link/en/blog/why-vanityurls/</link><pubDate>Mon, 20 Jan 2025 00:00:00 +0000</pubDate><guid>https://www.vanityurls.link/en/blog/why-vanityurls/</guid><description>&lt;p&gt;URL shorteners look like a solved problem. Pick a free service, paste a long URL, get a short one. Done. For years, services like bit.ly, goo.gl, and TinyURL made this trivially easy and free.&lt;/p&gt;
&lt;p&gt;Then bit.ly slashed free accounts to 10 links per month. Google killed goo.gl. Millions of published links — in books, presentations, printed materials, email footers — started dying.&lt;/p&gt;
&lt;p&gt;The problem isn&amp;rsquo;t that these services got worse. It&amp;rsquo;s that they were always the wrong architectural choice.&lt;/p&gt;</description></item><item><title>Say Goodbye to Third-Party URL Shorteners: Introducing VanityURLs</title><link>https://www.vanityurls.link/en/blog/introducing-v8s/</link><pubDate>Fri, 16 Aug 2024 00:00:00 +0000</pubDate><guid>https://www.vanityurls.link/en/blog/introducing-v8s/</guid><description>&lt;p&gt;For years, URL shortening services like bit.ly, goo.gl, and tinyurl have been go-to tools for anyone needing to share compact links. These services were free and convenient — but the landscape is changing, and not for the better.&lt;/p&gt;
&lt;h2 id="the-problem-with-relying-on-third-party-services"&gt;The Problem with Relying on Third-Party Services&lt;/h2&gt;
&lt;p&gt;In January 2024, Bitly — the leading URL shortener since 2008 — made a significant change: accounts created after 2018 were suddenly limited to just &lt;strong&gt;10 links per month&lt;/strong&gt;. For those who had relied on the previous limit of 10,000 free links per month, this was a major blow.&lt;/p&gt;</description></item><item><title>Accessibility Statement</title><link>https://www.vanityurls.link/en/accessibility/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.vanityurls.link/en/accessibility/</guid><description>&lt;p&gt;&lt;em&gt;Last reviewed: April 2026. This statement applies only to vanityURLs.link, not to self-hosted vanityURLs deployments.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;We&amp;rsquo;re committed to making this site usable by as many people as possible, regardless of ability or assistive technology. This statement explains what we&amp;rsquo;ve implemented, what we know is imperfect, and how to test or report accessibility issues.&lt;/p&gt;
&lt;h2 id="conformance-status"&gt;Conformance status&lt;/h2&gt;
&lt;p&gt;We target &lt;strong&gt;WCAG 2.1 Level AA&lt;/strong&gt; and the site is &lt;strong&gt;partially conformant&lt;/strong&gt; — the majority of criteria are met, with a small number of known gaps documented below.&lt;/p&gt;</description></item><item><title>Admin dashboard</title><link>https://www.vanityurls.link/en/docs/admin-dashboard/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.vanityurls.link/en/docs/admin-dashboard/</guid><description>&lt;p&gt;The admin dashboard is intentionally read-only. It is an operational view over the generated registry, not a content management system.&lt;/p&gt;
&lt;p&gt;It reads:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/v8s.json
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="what-it-shows"&gt;What it shows&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Route inventory&lt;/li&gt;
&lt;li&gt;Effective state&lt;/li&gt;
&lt;li&gt;Exact vs splat routing&lt;/li&gt;
&lt;li&gt;Expiry review&lt;/li&gt;
&lt;li&gt;Metadata quality&lt;/li&gt;
&lt;li&gt;Routing-table behavior&lt;/li&gt;
&lt;li&gt;Expiring-soon and missing-metadata filters&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Analytics remain in Umami or Fathom. The dashboard is the routing and lifecycle plane; analytics tools are the measurement plane.&lt;/p&gt;
&lt;h2 id="protection"&gt;Protection&lt;/h2&gt;
&lt;p&gt;Protect &lt;code&gt;/_stats&lt;/code&gt;, &lt;code&gt;/_stats/*&lt;/code&gt;, &lt;code&gt;/_tests&lt;/code&gt;, and &lt;code&gt;/_tests/*&lt;/code&gt; with Cloudflare Access. The Worker validates the Access assertion header and fails closed when protection is incomplete.&lt;/p&gt;</description></item><item><title>bhdicaire.com</title><link>https://www.vanityurls.link/en/showcase/bhdicaire-com/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.vanityurls.link/en/showcase/bhdicaire-com/</guid><description>&lt;p&gt;bhdicaire.com is the personal vanity domain of &lt;a href="https://github.com/bhdicaire"&gt;Benoît H. Dicaire&lt;/a&gt;, founder and primary maintainer of vanityURLs. It was the first deployment that proved the concept worked, predating the project&amp;rsquo;s open-source release.&lt;/p&gt;
&lt;p&gt;All links are managed via the &lt;code&gt;lnk&lt;/code&gt; CLI script and deployed automatically through Cloudflare Pages on every push to the main branch.&lt;/p&gt;</description></item><item><title>Blocklist policy</title><link>https://www.vanityurls.link/en/docs/blocklist/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.vanityurls.link/en/docs/blocklist/</guid><description>&lt;p&gt;vanityURLs uses &lt;code&gt;defaults/v8s-blocklist.json&lt;/code&gt; as the upstream trust-and-safety policy. Instance-specific policy lives in &lt;code&gt;custom/v8s-blocklist.json&lt;/code&gt; and is merged over the defaults.&lt;/p&gt;
&lt;p&gt;The goal is to protect the reputation of a short-link domain by reducing phishing, malware, redirect chains, and risky URL forms.&lt;/p&gt;
&lt;p&gt;A redirect engine is powerful infrastructure. Do not use a vanityURLs instance to hide malicious destinations, bypass trust systems, launder another shortener chain, disguise affiliate or tracking links without disclosure, or route people to content they did not reasonably expect. A short-link domain earns trust slowly and can lose it very quickly.&lt;/p&gt;</description></item><item><title>CLI</title><link>https://www.vanityurls.link/en/docs/cli/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.vanityurls.link/en/docs/cli/</guid><description>&lt;p&gt;The repo-local CLI is &lt;code&gt;./scripts/lnk&lt;/code&gt;. It is a Node executable, so it works on macOS, Linux, Windows, and CI environments where Node and Git are available.&lt;/p&gt;
&lt;p&gt;Bash is not required for link management. The Zsh helper remains optional and separate.&lt;/p&gt;
&lt;h2 id="requirements"&gt;Requirements&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Node.js 20 or newer&lt;/li&gt;
&lt;li&gt;npm&lt;/li&gt;
&lt;li&gt;Git&lt;/li&gt;
&lt;li&gt;Wrangler for deployment commands&lt;/li&gt;
&lt;li&gt;A Cloudflare account only when deploying or managing Worker secrets&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;On Windows, run the commands from PowerShell, Windows Terminal, or a Git-aware shell. The CLI itself does not require WSL.&lt;/p&gt;</description></item><item><title>Cloudflare Workers</title><link>https://www.vanityurls.link/en/docs/cloudflare/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.vanityurls.link/en/docs/cloudflare/</guid><description>&lt;p&gt;The current vanityURLs runtime deploys as a Cloudflare Worker with static assets. The Worker is the origin for the short-link hostname, so use a Worker Custom Domain instead of the older Pages &lt;code&gt;_redirects&lt;/code&gt; or DNS &lt;code&gt;AAAA 100::&lt;/code&gt; route pattern.&lt;/p&gt;
&lt;h2 id="cloudflare-navigation-map"&gt;Cloudflare navigation map&lt;/h2&gt;
&lt;p&gt;Cloudflare splits the required vanityURLs settings across three different dashboard areas. Check the dashboard scope before changing a setting; being in the right Cloudflare product is not always enough.&lt;/p&gt;</description></item><item><title>Contribution Guide</title><link>https://www.vanityurls.link/en/contributing/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.vanityurls.link/en/contributing/</guid><description>&lt;p&gt;Contributions are welcome! vanityURLs recognizes &lt;a href="https://allcontributors.org/docs/en/emoji-key"&gt;all types of contributions&lt;/a&gt; based on the all-contributors specification.&lt;/p&gt;
&lt;h2 id="ways-to-contribute"&gt;Ways to contribute&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Bug reports&lt;/strong&gt; — open an issue in the &lt;a href="https://github.com/vanityURLs/vanityURLs/issues"&gt;GitHub repository&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Documentation&lt;/strong&gt; — improve or translate docs in the &lt;a href="https://github.com/vanityURLs/website"&gt;website repository&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Code&lt;/strong&gt; — submit a &lt;a href="https://github.com/vanityURLs/vanityURLs/pulls"&gt;pull request&lt;/a&gt; with fixes or new features&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Community&lt;/strong&gt; — help others in &lt;a href="https://github.com/orgs/vanityURLs/discussions"&gt;GitHub Discussions&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This project is released with a &lt;a href="https://github.com/vanityURLs/website/blob/main/.github/CODE_OF_CONDUCT.md"&gt;Contributor Code of Conduct&lt;/a&gt;. By participating you agree to abide by its terms.&lt;/p&gt;
&lt;h2 id="pull-request-guidelines"&gt;Pull request guidelines&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Keep PRs focused — one feature or fix per PR&lt;/li&gt;
&lt;li&gt;Update documentation for any user-facing changes&lt;/li&gt;
&lt;li&gt;Add a clear description of what the PR does and why&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="questions"&gt;Questions?&lt;/h2&gt;
&lt;p&gt;Start a discussion in &lt;a href="https://github.com/orgs/vanityURLs/discussions"&gt;GitHub Discussions&lt;/a&gt; before opening a PR for large changes.&lt;/p&gt;</description></item><item><title>Custom overrides</title><link>https://www.vanityurls.link/en/docs/custom-overrides/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.vanityurls.link/en/docs/custom-overrides/</guid><description>&lt;p&gt;Use &lt;code&gt;custom/&lt;/code&gt; for instance-owned files. This keeps v8s.link-style deployments upgradable because default pages, Worker logic, and product policy can move forward without mixing in every local brand choice.&lt;/p&gt;
&lt;h2 id="build-order"&gt;Build order&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Copy &lt;code&gt;defaults/public/&lt;/code&gt; into &lt;code&gt;build/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Overlay &lt;code&gt;custom/public/&lt;/code&gt; when it exists&lt;/li&gt;
&lt;li&gt;Copy the default &lt;code&gt;defaults/public/_stats/index.html&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Overlay &lt;code&gt;custom/public/_stats/index.html&lt;/code&gt; when it exists&lt;/li&gt;
&lt;li&gt;Build &lt;code&gt;v8s.json&lt;/code&gt; from &lt;code&gt;custom/v8s-links.txt&lt;/code&gt; when it exists, otherwise from &lt;code&gt;defaults/v8s-links.txt&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Merge &lt;code&gt;defaults/v8s-blocklist.json&lt;/code&gt;, optional &lt;code&gt;custom/v8s-blocklist.json&lt;/code&gt;, and optional generated blocklist data&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="recommended-custom-files"&gt;Recommended custom files&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;custom/v8s-links.txt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;custom/v8s-schedules.json
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;custom/v8s-blocklist.json
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;custom/public/v8s-logo.svg
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;custom/public/v8s-redirected.svg
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;custom/public/favicon.svg
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Only add HTML or CSS overrides when brand assets and content files are not enough.&lt;/p&gt;</description></item><item><title>Default links</title><link>https://www.vanityurls.link/en/docs/demo/links/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.vanityurls.link/en/docs/demo/links/</guid><description>&lt;p&gt;The default link registry is &lt;code&gt;defaults/v8s-links.txt&lt;/code&gt;. A production instance normally replaces it with &lt;code&gt;custom/v8s-links.txt&lt;/code&gt;, but the defaults are useful because they show the supported shape of a real registry.&lt;/p&gt;
&lt;h2 id="namespaced-examples"&gt;Namespaced examples&lt;/h2&gt;
&lt;p&gt;The default file groups links by human task area:&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Prefix&lt;/th&gt;
 &lt;th&gt;Examples&lt;/th&gt;
 &lt;th&gt;Purpose&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;ai/&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;ai/chat&lt;/code&gt;, &lt;code&gt;ai/claude&lt;/code&gt;, &lt;code&gt;ai/hf&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;AI tools and model resources&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;edu/&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;edu/a&lt;/code&gt;, &lt;code&gt;edu/d&lt;/code&gt;, &lt;code&gt;edu/s&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Research and academic lookup&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;g/&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;g/cal&lt;/code&gt;, &lt;code&gt;g/drive&lt;/code&gt;, &lt;code&gt;g/meet&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Google productivity surfaces&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;meet/&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;meet/g&lt;/code&gt;, &lt;code&gt;meet/t&lt;/code&gt;, &lt;code&gt;meet/z&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Meeting-room aliases&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;pkg/&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;pkg/d&lt;/code&gt;, &lt;code&gt;pkg/n&lt;/code&gt;, &lt;code&gt;pkg/p&lt;/code&gt;, &lt;code&gt;pkg/r&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Package registries&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;social/&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;social/fb&lt;/code&gt;, &lt;code&gt;social/ig&lt;/code&gt;, &lt;code&gt;social/x&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Social profiles&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;v8s/&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;v8s/code&lt;/code&gt;, &lt;code&gt;v8s/doc&lt;/code&gt;, &lt;code&gt;v8s/status&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;vanityURLs project links&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Namespacing keeps the root short-link space clean while still allowing memorable URLs such as &lt;code&gt;v8s.link/social/x&lt;/code&gt;.&lt;/p&gt;</description></item><item><title>felx.cc</title><link>https://www.vanityurls.link/en/showcase/felx-cc/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.vanityurls.link/en/showcase/felx-cc/</guid><description>&lt;p&gt;felx.cc is the personal vanity domain of &lt;a href="https://github.com/felleg"&gt;Félix Léger&lt;/a&gt;, one of the creators of vanityURLs. It was one of the first production deployments of the project and serves as the live proof of concept.&lt;/p&gt;
&lt;p&gt;All links at felx.cc are managed via a plain-text &lt;code&gt;_redirects&lt;/code&gt; file hosted on GitHub and deployed automatically to Cloudflare Pages on every push.&lt;/p&gt;</description></item><item><title>Impressum</title><link>https://www.vanityurls.link/en/impressum/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.vanityurls.link/en/impressum/</guid><description>&lt;div class="not-prose my-5 rounded-lg border border-blue-200 dark:border-blue-800 bg-blue-50 dark:bg-blue-900/20 p-4"&gt;
 &lt;div class="flex gap-3"&gt;
 &lt;svg class="w-5 h-5 text-blue-500 dark:text-blue-400 shrink-0 mt-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/&gt;
 &lt;/svg&gt;
 &lt;div class="flex-1 min-w-0"&gt;
 &lt;p class="text-sm font-semibold text-blue-800 dark:text-blue-300 mb-1"&gt;
 Last reviewed: April 2026
 &lt;/p&gt;
 &lt;div class="text-sm text-blue-700 dark:text-blue-300 [&amp;&gt;p]:m-0 [&amp;&gt;p+p]:mt-2 [&amp;&gt;code]:bg-black/10 [&amp;&gt;code]:px-1 [&amp;&gt;code]:rounded"&gt;
 
 &lt;/div&gt;
 &lt;/div&gt;
 &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;&lt;em&gt;This notice is provided in accordance with § 5 DDG (Digitale-Dienste-Gesetz, Germany), § 5 ECG (E-Commerce-Gesetz, Austria), and equivalent transparency obligations for users in German-speaking countries.&lt;/em&gt;&lt;/p&gt;</description></item><item><title>License</title><link>https://www.vanityurls.link/en/license/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.vanityurls.link/en/license/</guid><description>&lt;p&gt;vanityURLs is an open source software released under the &lt;strong&gt;MIT License&lt;/strong&gt;.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;MIT License

Copyright (c) 2024 Benoît H. Dicaire

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the &amp;#34;Software&amp;#34;), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED &amp;#34;AS IS&amp;#34;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The full license text is also available in the &lt;a href="https://github.com/vanityURLs/vanityURLs/blob/main/LICENSE" target="_blank" rel="noopener"&gt;GitHub repository&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Link format</title><link>https://www.vanityurls.link/en/docs/link-format/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.vanityurls.link/en/docs/link-format/</guid><description>&lt;p&gt;&lt;code&gt;v8s-links.txt&lt;/code&gt; is the human-authored source of truth for links. Each non-empty, non-comment row is pipe-delimited:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;slug|target|state|title|description|tags|owner|expires_at|notes
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Field&lt;/th&gt;
 &lt;th style="text-align: right"&gt;Required&lt;/th&gt;
 &lt;th&gt;Description&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;slug&lt;/code&gt;&lt;/td&gt;
 &lt;td style="text-align: right"&gt;yes&lt;/td&gt;
 &lt;td&gt;Slash-delimited alias path, without leading &lt;code&gt;/&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;target&lt;/code&gt;&lt;/td&gt;
 &lt;td style="text-align: right"&gt;yes&lt;/td&gt;
 &lt;td&gt;Absolute &lt;code&gt;http&lt;/code&gt; or &lt;code&gt;https&lt;/code&gt; URL, or a hostname normalized to &lt;code&gt;https://&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;state&lt;/code&gt;&lt;/td&gt;
 &lt;td style="text-align: right"&gt;no&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;permanent&lt;/code&gt;, &lt;code&gt;ephemeral&lt;/code&gt;, &lt;code&gt;expired&lt;/code&gt;, &lt;code&gt;disabled&lt;/code&gt;, &lt;code&gt;maintenance&lt;/code&gt;, &lt;code&gt;deactivated&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;title&lt;/code&gt;&lt;/td&gt;
 &lt;td style="text-align: right"&gt;no&lt;/td&gt;
 &lt;td&gt;Dashboard title&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;description&lt;/code&gt;&lt;/td&gt;
 &lt;td style="text-align: right"&gt;no&lt;/td&gt;
 &lt;td&gt;Human-readable purpose&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;tags&lt;/code&gt;&lt;/td&gt;
 &lt;td style="text-align: right"&gt;no&lt;/td&gt;
 &lt;td&gt;Comma-separated tags&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;owner&lt;/code&gt;&lt;/td&gt;
 &lt;td style="text-align: right"&gt;recommended&lt;/td&gt;
 &lt;td&gt;Accountability label&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;expires_at&lt;/code&gt;&lt;/td&gt;
 &lt;td style="text-align: right"&gt;no&lt;/td&gt;
 &lt;td&gt;ISO date or timestamp&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;notes&lt;/code&gt;&lt;/td&gt;
 &lt;td style="text-align: right"&gt;no&lt;/td&gt;
 &lt;td&gt;Internal notes&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="exact-links"&gt;Exact links&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;social/x|https://x.com/vanityURLs|permanent|X / Twitter|Social profile|social,x|v8s||
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The link resolves only &lt;code&gt;/social/x&lt;/code&gt;.&lt;/p&gt;</description></item><item><title>Migration guide</title><link>https://www.vanityurls.link/en/docs/migration/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.vanityurls.link/en/docs/migration/</guid><description>&lt;p&gt;Use this guide when moving from the older Cloudflare Pages &lt;code&gt;_redirects&lt;/code&gt; model to the current Worker model used by v8s.link.&lt;/p&gt;
&lt;h2 id="what-changed"&gt;What changed&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;wrangler.toml&lt;/code&gt; is the deployment source of truth&lt;/li&gt;
&lt;li&gt;Static files are served through the Worker assets binding named &lt;code&gt;ASSETS&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;The build copies &lt;code&gt;defaults/&lt;/code&gt;, overlays &lt;code&gt;custom/&lt;/code&gt;, and generates &lt;code&gt;build/v8s.json&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;custom/v8s-links.txt&lt;/code&gt; is preferred when it exists; otherwise the build uses &lt;code&gt;defaults/v8s-links.txt&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/_stats&lt;/code&gt; and &lt;code&gt;/_tests&lt;/code&gt; are protected by Cloudflare Access&lt;/li&gt;
&lt;li&gt;Server-side analytics are emitted by the Worker&lt;/li&gt;
&lt;li&gt;Scanner probes and risky destinations are blocked by &lt;code&gt;v8s-blocklist.json&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="convert-legacy-lnk-files"&gt;Convert legacy .lnk files&lt;/h2&gt;
&lt;p&gt;Legacy rows looked like this:&lt;/p&gt;</description></item><item><title>Privacy</title><link>https://www.vanityurls.link/en/privacy/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.vanityurls.link/en/privacy/</guid><description>&lt;div class="not-prose my-5 rounded-lg border border-blue-200 dark:border-blue-800 bg-blue-50 dark:bg-blue-900/20 p-4"&gt;
 &lt;div class="flex gap-3"&gt;
 &lt;svg class="w-5 h-5 text-blue-500 dark:text-blue-400 shrink-0 mt-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/&gt;
 &lt;/svg&gt;
 &lt;div class="flex-1 min-w-0"&gt;
 &lt;p class="text-sm font-semibold text-blue-800 dark:text-blue-300 mb-1"&gt;
 Last reviewed: April 2026
 &lt;/p&gt;
 &lt;div class="text-sm text-blue-700 dark:text-blue-300 [&amp;&gt;p]:m-0 [&amp;&gt;p+p]:mt-2 [&amp;&gt;code]:bg-black/10 [&amp;&gt;code]:px-1 [&amp;&gt;code]:rounded"&gt;
 This policy applies only to the current website (e.g., &lt;code&gt;vanityURLs.link&lt;/code&gt;), not to sites built with vanityURLs.
 &lt;/div&gt;
 &lt;/div&gt;
 &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;vanityURLs.link is a documentation website for an open-source project. We take your privacy seriously.&lt;/p&gt;</description></item><item><title>Quickstart</title><link>https://www.vanityurls.link/en/docs/getting-started/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.vanityurls.link/en/docs/getting-started/</guid><description>&lt;p&gt;vanityURLs is a Git-managed short-link engine for your own domain. The current runtime deploys as a Cloudflare Worker with static assets. The build starts from &lt;code&gt;defaults/&lt;/code&gt;, overlays your &lt;code&gt;custom/&lt;/code&gt; files, generates &lt;code&gt;build/v8s.json&lt;/code&gt;, and publishes the Worker with Wrangler.&lt;/p&gt;
&lt;h2 id="what-you-need"&gt;What you need&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;A GitHub repository based on &lt;code&gt;vanityURLs/vanityURLs&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;A short domain, such as the public reference domain &lt;code&gt;v8s.link&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;A Cloudflare account with the domain in Cloudflare DNS&lt;/li&gt;
&lt;li&gt;Node.js 20 or newer and npm&lt;/li&gt;
&lt;li&gt;Git&lt;/li&gt;
&lt;li&gt;Wrangler connected to the Cloudflare account that owns the Worker&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The primary CLI is &lt;code&gt;./scripts/lnk&lt;/code&gt;, a Node script that runs on macOS, Linux, Windows, and CI environments where Node and Git are available. Bash is not required for link, schedule, or blocklist management. The optional &lt;code&gt;scripts/v8s.zsh&lt;/code&gt; helper is only for Zsh users who want to open known redirects from their shell.&lt;/p&gt;</description></item><item><title>Release checklist</title><link>https://www.vanityurls.link/en/docs/release-checklist/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.vanityurls.link/en/docs/release-checklist/</guid><description>&lt;p&gt;Use this checklist before launching a new instance or promoting a major upgrade. A v8s instance is simple, but a short-link domain still attracts scanners, bots, and abuse attempts.&lt;/p&gt;
&lt;h2 id="repository"&gt;Repository&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Run &lt;code&gt;npm run clean&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Refresh upstream &lt;code&gt;defaults/&lt;/code&gt; and &lt;code&gt;scripts/&lt;/code&gt; with the upgrade workflow.&lt;/li&gt;
&lt;li&gt;Keep all instance-owned files in &lt;code&gt;custom/&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;npm run check&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Review generated registry and blocklist changes.&lt;/li&gt;
&lt;li&gt;Commit and deploy from a clean working tree.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="worker-and-assets"&gt;Worker and assets&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Confirm the Worker has an &lt;code&gt;ASSETS&lt;/code&gt; binding.&lt;/li&gt;
&lt;li&gt;Confirm the custom domain points to the Worker.&lt;/li&gt;
&lt;li&gt;Disable public &lt;code&gt;workers.dev&lt;/code&gt; and preview URLs if they are not part of the service.&lt;/li&gt;
&lt;li&gt;Protect &lt;code&gt;/_stats&lt;/code&gt; and &lt;code&gt;/_tests&lt;/code&gt; with Cloudflare Access.&lt;/li&gt;
&lt;li&gt;Keep &lt;code&gt;/_stats/*&lt;/code&gt; and &lt;code&gt;/_tests/*&lt;/code&gt; policies narrow.&lt;/li&gt;
&lt;li&gt;Confirm the Worker accepts only &lt;code&gt;GET&lt;/code&gt;, &lt;code&gt;HEAD&lt;/code&gt;, and &lt;code&gt;OPTIONS&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Confirm private implementation assets return 404.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="cloudflare-domain-configuration"&gt;Cloudflare domain configuration&lt;/h2&gt;
&lt;p&gt;In Cloudflare, the relevant settings are split across three places:&lt;/p&gt;</description></item><item><title>Reporting a Vulnerability</title><link>https://www.vanityurls.link/en/vulnerability/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.vanityurls.link/en/vulnerability/</guid><description>&lt;div class="not-prose my-5 rounded-lg border border-green-200 dark:border-green-800 bg-green-50 dark:bg-green-900/20 p-4"&gt;
 &lt;div class="flex gap-3"&gt;
 &lt;svg class="w-5 h-5 text-green-500 dark:text-green-400 shrink-0 mt-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"/&gt;
 &lt;/svg&gt;
 &lt;div class="flex-1 min-w-0"&gt;
 &lt;p class="text-sm font-semibold text-green-800 dark:text-green-300 mb-1"&gt;
 If you discover a security vulnerability in vanityURLs
 &lt;/p&gt;
 &lt;div class="text-sm text-green-700 dark:text-green-300 [&amp;&gt;p]:m-0 [&amp;&gt;p+p]:mt-2 [&amp;&gt;code]:bg-black/10 [&amp;&gt;code]:px-1 [&amp;&gt;code]:rounded"&gt;
 &lt;p&gt;Please report it responsibly with &lt;em&gt;&lt;a href="https://github.com/vanityURLs/vanityURLs/security/advisories/new"&gt;GitHub Security Advisories&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;br&gt;&lt;strong&gt;Do not open a public GitHub issue for security vulnerabilities&lt;/strong&gt;&lt;/p&gt;</description></item><item><title>Repository layout</title><link>https://www.vanityurls.link/en/docs/repository-layout/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.vanityurls.link/en/docs/repository-layout/</guid><description>&lt;p&gt;The repository separates product defaults from instance-owned changes. That separation is what makes v8s.link useful as a reference implementation and lets future instances update upstream code without losing local branding.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;defaults/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; public/ # default HTML, CSS, icons, localized pages
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; public/_stats/ # read-only stats dashboard shell
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; v8s-links.txt # demo/default link registry
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; v8s-schedules.json # optional schedule rules
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; v8s-blocklist.json # default trust-and-safety policy
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; v8s-blocklist-categories.json
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;custom/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; public/ # instance branding and page overrides
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; v8s-links.txt # instance-owned links
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; v8s-schedules.json # instance schedules
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; v8s-blocklist.json # instance allow/block policy
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;scripts/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; src/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; worker.mjs # canonical Worker runtime source
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; worker.test.mjs # Worker runtime tests
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; lnk # Node CLI for links and schedules
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; build.mjs # build defaults + custom into deploy output
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; clean.mjs # remove generated output
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; upgrade.mjs # refresh product-owned files from upstream
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;build/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; v8s.json # generated runtime registry
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; v8s-blocklist.json # generated trust-and-safety policy
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ...static assets...
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="defaults"&gt;Defaults&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;defaults/&lt;/code&gt; is the product baseline. The public v8s.link instance uses these files to show a working shortener with the search-style home page, expand page, localized status pages, default icons, the protected stats shell, and sample links.&lt;/p&gt;</description></item><item><title>Runtime registry</title><link>https://www.vanityurls.link/en/docs/runtime-registry/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.vanityurls.link/en/docs/runtime-registry/</guid><description>&lt;p&gt;The Worker does not read &lt;code&gt;v8s-links.txt&lt;/code&gt; on every request. The build creates a private runtime registry at &lt;code&gt;build/v8s.json&lt;/code&gt; and publishes it as an internal asset. Direct public requests for &lt;code&gt;v8s.json&lt;/code&gt;, &lt;code&gt;redirect-targets.json&lt;/code&gt;, and blocklist assets return 404.&lt;/p&gt;
&lt;p&gt;The registry is intentionally simple: one generated JSON file, schema version &lt;code&gt;2.2&lt;/code&gt;, validated before deploy, consumed by one Worker.&lt;/p&gt;
&lt;h2 id="build-inputs"&gt;Build inputs&lt;/h2&gt;
&lt;p&gt;The registry is generated from:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;defaults/v8s-links.txt&lt;/code&gt;, then &lt;code&gt;custom/v8s-links.txt&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;defaults/v8s-schedules.json&lt;/code&gt;, then &lt;code&gt;custom/v8s-schedules.json&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;defaults/v8s-blocklist.json&lt;/code&gt;, generated blocklist data, and &lt;code&gt;custom/v8s-blocklist.json&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;static page assets from &lt;code&gt;defaults/public/&lt;/code&gt; overlaid by &lt;code&gt;custom/public/&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Use &lt;code&gt;custom/&lt;/code&gt; for every instance-owned change. That keeps future updates simple: upstream can refresh &lt;code&gt;defaults/&lt;/code&gt; and &lt;code&gt;scripts/&lt;/code&gt; while the instance keeps its own links, policy, branding, legal pages, and generated secrets.&lt;/p&gt;</description></item><item><title>Runtime security approach</title><link>https://www.vanityurls.link/en/docs/runtime-security/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.vanityurls.link/en/docs/runtime-security/</guid><description>&lt;p&gt;The vanityURLs runtime is deliberately simple. It is not a public link-submission service, not a database-backed application, and not a general web framework. It is a Git-built redirect engine: validate the link registry, deploy static assets, read &lt;code&gt;v8s.json&lt;/code&gt;, and return one of a small set of outcomes.&lt;/p&gt;
&lt;p&gt;Simplicity is part of the security model. The Worker has fewer moving parts than a typical shortener: no public write API, no visitor accounts, no cookies, no client-side analytics, no database query layer, and no origin server behind Cloudflare.&lt;/p&gt;</description></item><item><title>Scheduled links</title><link>https://www.vanityurls.link/en/docs/schedules/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.vanityurls.link/en/docs/schedules/</guid><description>&lt;p&gt;Scheduled links let a stable slug point somewhere different during configured time windows. Keep the normal link in &lt;code&gt;v8s-links.txt&lt;/code&gt;, then add rules in &lt;code&gt;v8s-schedules.json&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Schedules currently apply to exact links. Splat links stay path-driven.&lt;/p&gt;
&lt;p&gt;For common schedule changes, use the Node CLI instead of hand-editing JSON:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;./scripts/lnk schedule add hangout https://zoom.us/j/work --label work --days mon,tue,wed,thu,fri --from 09:00 --to 17:00 --timezone America/Toronto --default https://discord.gg/personal
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;./scripts/lnk schedule list hangout
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The CLI writes &lt;code&gt;custom/v8s-schedules.json&lt;/code&gt; by default. Set &lt;code&gt;V8S_SCHEDULES_FILE&lt;/code&gt; or pass &lt;code&gt;--file&lt;/code&gt; to use another path.&lt;/p&gt;</description></item><item><title>Security Statement</title><link>https://www.vanityurls.link/en/security/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.vanityurls.link/en/security/</guid><description>&lt;div class="not-prose my-5 rounded-lg border border-blue-200 dark:border-blue-800 bg-blue-50 dark:bg-blue-900/20 p-4"&gt;
 &lt;div class="flex gap-3"&gt;
 &lt;svg class="w-5 h-5 text-blue-500 dark:text-blue-400 shrink-0 mt-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/&gt;
 &lt;/svg&gt;
 &lt;div class="flex-1 min-w-0"&gt;
 &lt;p class="text-sm font-semibold text-blue-800 dark:text-blue-300 mb-1"&gt;
 Last reviewed: April 2026
 &lt;/p&gt;
 &lt;div class="text-sm text-blue-700 dark:text-blue-300 [&amp;&gt;p]:m-0 [&amp;&gt;p+p]:mt-2 [&amp;&gt;code]:bg-black/10 [&amp;&gt;code]:px-1 [&amp;&gt;code]:rounded"&gt;
 This statement applies to vanityURLs.link. It does not apply to self-hosted instances of vanityURLs, which are the sole responsibility of their operators.
 &lt;/div&gt;
 &lt;/div&gt;
 &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;vanityURLs.link is a static documentation website for the open-source project. vanityURLs does NOT do&lt;/p&gt;</description></item><item><title>Server-side analytics</title><link>https://www.vanityurls.link/en/docs/server-side-analytics/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.vanityurls.link/en/docs/server-side-analytics/</guid><description>&lt;p&gt;vanityURLs records analytics from the Worker, not from browser JavaScript. Redirects can be measured even when the visitor never loads an HTML page, and the public pages do not need client-side tracking scripts.&lt;/p&gt;
&lt;p&gt;Analytics is non-blocking. The Worker sends events with &lt;code&gt;ctx.waitUntil()&lt;/code&gt;, so redirect latency is not tied to Umami, Fathom, or another provider being available.&lt;/p&gt;
&lt;h2 id="providers"&gt;Providers&lt;/h2&gt;
&lt;p&gt;Set one or more providers with &lt;code&gt;ANALYTICS_PROVIDER&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-toml" data-lang="toml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;vars&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;ANALYTICS_PROVIDER&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;umami&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;UMAMI_ENDPOINT&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;https://cloud.umami.is/api/send&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;UMAMI_WEBSITE_ID&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&amp;lt;umami website id&amp;gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;UMAMI_GEO_IP_MODE&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;truncated&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-toml" data-lang="toml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;vars&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;ANALYTICS_PROVIDER&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;fathom&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;FATHOM_SITE_ID&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&amp;lt;fathom site id&amp;gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;FATHOM_ENDPOINT&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;https://cdn.usefathom.com/&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;During a migration, send to both:&lt;/p&gt;</description></item><item><title>Terms of Service</title><link>https://www.vanityurls.link/en/terms/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.vanityurls.link/en/terms/</guid><description>&lt;div class="not-prose my-5 rounded-lg border border-blue-200 dark:border-blue-800 bg-blue-50 dark:bg-blue-900/20 p-4"&gt;
 &lt;div class="flex gap-3"&gt;
 &lt;svg class="w-5 h-5 text-blue-500 dark:text-blue-400 shrink-0 mt-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/&gt;
 &lt;/svg&gt;
 &lt;div class="flex-1 min-w-0"&gt;
 &lt;p class="text-sm font-semibold text-blue-800 dark:text-blue-300 mb-1"&gt;
 Last reviewed: April 2026
 &lt;/p&gt;
 &lt;div class="text-sm text-blue-700 dark:text-blue-300 [&amp;&gt;p]:m-0 [&amp;&gt;p+p]:mt-2 [&amp;&gt;code]:bg-black/10 [&amp;&gt;code]:px-1 [&amp;&gt;code]:rounded"&gt;
 
 &lt;/div&gt;
 &lt;/div&gt;
 &lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="1-the-website"&gt;1. The Website&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;https://www.vanityURLs.link&lt;/code&gt; is a documentation website provided to support the vanityURLs open-source project. It is offered for informational purposes only and may be modified or discontinued at any time without notice.&lt;/p&gt;</description></item><item><title>Trust Center</title><link>https://www.vanityurls.link/en/trust/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.vanityurls.link/en/trust/</guid><description/></item><item><title>Upgrading an instance</title><link>https://www.vanityurls.link/en/docs/upgrading/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.vanityurls.link/en/docs/upgrading/</guid><description>&lt;p&gt;Installing a vanityURLs instance is easy. Updating one safely is the part that needs a repeatable workflow, because the instance owner should keep links, branding, policy, and Cloudflare configuration while receiving new defaults, scripts, fixes, and security hardening.&lt;/p&gt;
&lt;p&gt;The rule is simple:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;instance-owned files live in &lt;code&gt;custom/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Cloudflare deployment settings live in &lt;code&gt;wrangler.toml&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;generated output is disposable&lt;/li&gt;
&lt;li&gt;upstream product files live in &lt;code&gt;defaults/&lt;/code&gt; and &lt;code&gt;scripts/&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="upgrade-command"&gt;Upgrade command&lt;/h2&gt;
&lt;p&gt;Run from a clean worktree:&lt;/p&gt;</description></item><item><title>Validation and CI</title><link>https://www.vanityurls.link/en/docs/validation-ci/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.vanityurls.link/en/docs/validation-ci/</guid><description>&lt;p&gt;Run validation before every deploy. v8s is designed so link mistakes, unsafe targets, stale generated assets, and Worker regressions fail before Cloudflare receives a new version.&lt;/p&gt;
&lt;h2 id="local-commands"&gt;Local commands&lt;/h2&gt;
&lt;p&gt;Use the combined check for normal work:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;npm run check
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It builds the runtime, runs lint checks, and executes the Worker tests. For targeted work, use:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;npm run lint
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;npm &lt;span class="nb"&gt;test&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;npm run build
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;npm run smoke:analytics
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Run &lt;code&gt;npm run clean&lt;/code&gt; before release or before comparing generated output. It removes build cruft so the repo only shows intentional source changes.&lt;/p&gt;</description></item></channel></rss>