A No-Database Link Shortener on Cloudflare Workers
A short, memorable URL is handy for sharing links, and a Cloudflare Worker is a cheap way to run one. There’s no database involved: redirects live in a single file that you edit and push. Here’s the full setup.
Set up the worker directory
To get started, use Cloudflare’s create-cloudflare CLI to create your project:
npm create cloudflare@latest -- link-shortener
Answer the prompts:
What would you like to start with?
● Hello World example
Which template would you like to use?
● Worker only
Which language do you want to use?
● TypeScript
Do you want to add an AGENTS.md file to help AI coding tools understand Cloudflare APIs?
● No
Do you want to use git for version control?
● Yes
Do you want to deploy your application?
● No
This will create the scaffolding needed for your worker, including wrangler, which we’ll use to deploy.
Set up the redirects file
Create a file at src/redirects.ts:
const redirects: Record<string, string> = {
e: 'https://example.com',
a: 'https://another.example',
};
export default redirects;
Within that Record you set up all your redirects: the key is the short URL slug, the value is the target URL.
The actual redirect
Clear out the existing src/index.ts and replace it with the following:
// Import the redirects
import redirects from './redirects';
export default {
async fetch(request: Request): Promise<Response> {
// Get the slug from the request URL
const slug = new URL(request.url).pathname.slice(1).replace(/\/$/, '');
// If no slug has been provided, redirect somewhere by default, e.g. to a personal profile
if (!slug) {
return Response.redirect('https://example.com/', 302);
}
// Look up the target in the `redirects` `Record` and redirect there.
// `Object.hasOwn` makes sure slugs like `constructor` or `toString` don't match inherited properties.
if (Object.hasOwn(redirects, slug)) {
return Response.redirect(redirects[slug], 302);
}
// If an invalid slug has been provided, return a `404`
return new Response('Not Found', { status: 404 });
},
} satisfies ExportedHandler<Env>;
Set up your route
Now we need to tell Cloudflare which domain to use for our URL shortener. There are a few ways of doing this. You could use a path prefix and redirect anything from https://example.com/g/{foo}. In that case you’ll need to adjust the .slice(1) in the code above (e.g. to .slice(3)), and use a regular route rather than a custom domain.
As I want a short URL, I’m using a short domain without a path prefix: the whole domain is used for shortening.
The best way to define this is using the routes key in the wrangler.jsonc file. You can find the full details of the various options for defining routes in the Wrangler documentation.
To define a domain-based route, add the following routes key to the existing wrangler.jsonc file:
{
"routes": [
{ "pattern": "go.thms.uk", "custom_domain": true }
]
}
Create a deploy action for automatic deployment
To have your link shortener deployed automatically every time you push a change, we’ll use Forgejo Actions.
Within the repo, create a file at .forgejo/workflows/deploy.yml and paste the following:
name: Deploy
on:
workflow_dispatch:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
- name: Install
run: npm ci
- name: Deploy to Cloudflare Workers
run: npm run deploy
env:
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
(If you are using GitHub, place this at .github/workflows/deploy.yml instead.)
Set up the Cloudflare API token
To authenticate the deployment, we need to create a Cloudflare API token.
Go to Manage Account > Account API Tokens and create a token. You need to add two policies:
- A policy scoped to your domain, with the following permissions:
- Developer Platform > Workers Routes: Read & Edit
- DNS & Zones > Zone: Read & Edit
- A policy scoped to your account, with the following permissions:
- Developer Platform > Workers Scripts: Read & Edit
- Account & Billing > Account Settings: Read
Complete the setup process, and you’ll be given your Account ID and your API token. Make a note of both.
Provide your secrets to Forgejo
Create your repository if you haven’t yet, then go to your repository settings and find Actions > Secrets in the left column. Add two secrets: CLOUDFLARE_ACCOUNT_ID and CLOUDFLARE_API_TOKEN. It should look like this:

(If you are using GitHub, this lives at Settings > Secrets and variables > Actions > Repository secrets.)
Deploy and test
Push your code, and it should automatically be deployed to Cloudflare Workers. Visit one of your short URLs to test.
Any time you want to add a short URL or adjust an existing one, just update redirects.ts and push to Forgejo/GitHub.
That’s all there is to it: no database, no admin UI, just a single file under version control, which also gives you a full history of every link you’ve ever created. The trade-off is that every change needs a push and a deploy, but for a personal link shortener that’s a price I’m happy to pay.