A personal URL shortener built on Cloudflare Workers using React, Hono, and Tailwind CSS.
- Shorten URLs with custom aliases
- Store shortened URLs in Cloudflare KV
- React-based frontend for easy interaction
- API endpoints for programmatic access
- Bearer token authentication for API
- Node.js (version 18 or higher)
- npm or yarn
- Cloudflare account with Workers and KV enabled
-
Clone the repository:
git clone <repository-url> cd vapurl
-
Install dependencies:
npm install
-
Create a Cloudflare KV namespace and note its ID.
-
Set up environment variables:
VAPURL_KV_ID: Your KV namespace IDVAPURL_API_KEY: A secret API key for authentication
wrangler.toml is auto-generated from the template (wrangler.template.toml). Set the required environment variables before running any commands.
export VAPURL_KV_ID="your-kv-namespace-id"
export VAPURL_API_KEY="your-api-key"
wrangler.tomlis listed in.gitignoreand will not be committed to the repository.
Start the development server:
npm run devThis will start Vite's development server with Hono integration.
Build the project for production:
npm run buildSet the environment variables and run:
export VAPURL_KV_ID="your-kv-namespace-id"
export VAPURL_API_KEY="your-api-key"
npm run deployThis uses envsubst to generate wrangler.toml from wrangler.template.toml, then builds and deploys.
Pushes to the main branch trigger an automatic deployment.
Add the following secrets in your GitHub repository under Settings → Secrets and variables → Actions:
| Secret | Description |
|---|---|
VAPURL_KV_ID |
Cloudflare KV Namespace ID |
VAPURL_API_KEY |
API authentication key |
CLOUDFLARE_API_TOKEN |
Cloudflare API token |
CLOUDFLARE_ACCOUNT_ID |
Cloudflare account ID |
curl -X POST https://your-worker-url/shorten \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com", "alias": "example"}'Visit https://your-worker-url/example to redirect to the original URL.
To generate/synchronize types based on your Worker configuration:
npm run cf-typegenThen use CloudflareBindings as generics when instantiating Hono:
const app = new Hono<{ Bindings: CloudflareBindings }>()This project is open source and available under the MIT License.