LENK.CF
LENK.CF is an open-source URL shortener built for Vercel serverless deployment with MongoDB for persistence, Redis for caching, and a no-framework frontend. It ships with a custom-branded landing page, custom alias support, Redis-backed redirect acceleration, a lightweight PWA setup, and a small JSON API.
The current frontend uses a dark editorial design system with an animated intro sequence, SEO and GEO metadata, and a redesigned 404 experience.
Highlights
- Shorten long URLs with generated short IDs.
- Create custom aliases with validation for letters, numbers,
_, and-. - Cache both
url -> shortIdandshortId -> urlin Redis to reduce database lookups. - Redirect short links with permanent
301redirects. - Serve a static landing page and error page through Vercel routing.
- Expose a simple API for creation, redirects, discovery, and listing.
- Include a minimal service worker for PWA-style asset caching.
- Ship a metadata-rich homepage with Open Graph, Twitter Card, canonical, and JSON-LD schema.
Stack
Frontend
- HTML
- CSS / SCSS assets
- Vanilla JavaScript
- Service Worker
Backend
- Node.js serverless functions on Vercel
- MongoDB with Mongoose
- Redis v3 client for caching and shared utility helpers
Infrastructure
- Vercel routing via vercel.json
- MongoDB Atlas or any reachable MongoDB deployment
- Redis Cloud or any reachable Redis instance
How It Works
- The landing page at
/serves the static UI fromstatic/index.html. - A random short link is created through
GET /p/<encodedUrl>. - A custom short link is created through
POST /customwith{ url, shortId }. - Redirects are resolved through the catch-all route and served by
api/redirect.js. - MongoDB stores canonical records.
- Redis stores hot lookups to avoid repeated database reads.
Current Feature Set
URL Creation
- Random IDs are generated in
api/p.js. - Existing URLs are reused when already present in the database.
- Custom aliases are rejected if the alias already exists.
Redirect Resolution
- Cached short IDs return immediately from Redis.
- Cache misses fall back to MongoDB.
- Missing records redirect to
/404.
Frontend Experience
- Intro loading animation that visually compresses a long URL into a short link.
- Inline result section with copy-to-clipboard support.
- Domains panel for alternate domains.
- Toast notifications for success and error states.
Metadata / Discoverability
- Canonical URL
- Open Graph and Twitter metadata
- Geographic metadata
- JSON-LD for
WebApplicationandFAQPage
Project Structure
.
|-- api/
| |-- _lib/
| | |-- cache.js
| | |-- db.js
| | `-- rate-limit.js
| |-- all.js
| |-- custom.js
| |-- index.js
| |-- p.js
| `-- redirect.js
|-- models/
| `-- model.js
|-- static/
| |-- 404.html
| |-- index.html
| `-- assets/
| |-- robots.txt
| |-- script.js
| |-- styles.css
| |-- styles.scss
| `-- sw.js
|-- LICENSE
|-- README.md
|-- package.json
`-- vercel.json
Runtime Requirements
- Node.js 18+
- A MongoDB database
- A Redis instance
- Vercel CLI for local serverless development
Environment Variables
Create a .env file in the project root for local development.
DB=mongodb+srv://<user>:<password>@cluster0.xxxxx.mongodb.net/lenk-cf?retryWrites=true&w=majority
REDIS_URL=redis://default:<password>@<host>:<port>
Variable Reference
| Variable | Required | Purpose |
|---|---|---|
DB |
Yes | MongoDB connection URI used by api/_lib/db.js |
REDIS_URL |
Yes in practice | Redis connection used by cache helpers and shared Redis utilities |
Notes:
api/_lib/db.jsconnects withdbName: 'lenk-cf'.api/_lib/rate-limit.jsfalls back toredis://127.0.0.1:6379ifREDIS_URLis missing, but the app expects Redis to be available for normal operation.
Local Development
This repository does not define npm scripts. Use the Vercel CLI directly.
1. Clone the repository
git clone https://github.com/adithyapaib/lenk.cf
cd lenk.cf
2. Install dependencies
npm install
3. Add environment variables
Create .env as shown above.
4. Start local development
npx vercel dev
The app is typically available at http://localhost:3000.
Deploying to Vercel
1. Install the Vercel CLI
npm install -g vercel
2. Authenticate and link the project
vercel
3. Configure environment variables in Vercel
Add these in the Vercel project settings:
DBREDIS_URL
4. Deploy
vercel deploy
API Overview
All endpoints are served from the same Vercel deployment domain.
GET /
Returns the static homepage UI.
GET /api
Returns a JSON object with server status, route hints, domains, and credits.
Example response shape:
{
"server": "online",
"end_points": [
{"/": "index.html"},
{"/p/<url>": "Creates a new shortID for the url sent or returns an existing shortID."}
],
"source": "https://github.com/adithyapaib/lenk.cf"
}
GET /p/<encodedUrl>
Creates or reuses a short ID for a URL.
Example:
GET /p/https%3A%2F%2Fexample.com%2Fdocs%2Fintro
Success response:
"Ab3"
Behavior:
- Validates the decoded URL.
- Returns a cached short ID when available.
- Reuses an existing database record for the same URL.
- Generates a 3-character ID and falls back to 5 characters if the first candidate collides.
POST /custom
Creates a short link with a user-specified alias.
Request:
POST /custom
Content-Type: application/json
{
"url": "https://example.com",
"shortId": "myalias"
}
Success response:
"myalias"
Conflict response:
0
Validation:
urlis required and must parse withnew URL(...).shortIdis required.shortIdmust match^[a-zA-Z0-9_-]+$.
GET /custom/<encodedUrl>%3A%3A%3A69<custom_shortID>
Supports the legacy custom-link format used by the older API index.
Example:
GET /custom/https%3A%2F%2Fexample.com%3A%3A%3A69docs
Behavior:
- Decodes the URL portion before
:::69. - Uses the value after
:::69as the requested custom short ID. - Returns the same success and conflict payloads as
POST /custom.
GET /all
Returns all stored documents, prefixed with a count object.
Example response shape:
[
{ "numberOfShortURLS": 2 },
{ "_id": "...", "url": "https://example.com", "shortId": "Ab3" },
{ "_id": "...", "url": "https://example.org", "shortId": "docs" }
]
GET /<shortId>
Redirects with HTTP 301 to the original URL.
Behavior:
- Uses Redis first.
- Falls back to MongoDB.
- Redirects to
/404when no matching short ID exists. - Normalizes stored URLs by prepending
https://if a protocol is missing during redirect.
GET /404
Returns the branded not-found page.
Vercel Routing
Routing is defined in vercel.json.
Key mappings:
/->static/index.html/css->static/assets/styles.css/js->static/assets/script.js/serviceworker->static/assets/sw.js/robots.txt->static/assets/robots.txt/p/...->api/p.js/customrequests are handled byapi/custom.js/all->api/all.js/api->api/index.js- catch-all fallback route ->
api/redirect.js
Data Model
MongoDB documents are stored through the Mongoose model in models/model.js.
Schema:
{
url: String,
shortId: String
}
There are no explicit schema indexes or uniqueness constraints at the model level right now. Uniqueness is enforced in route logic.
Cache Strategy
Redis is used by api/_lib/cache.js and shared by the route handlers.
| Cache Key | Value | TTL | Used By |
|---|---|---|---|
url:<longUrl> |
shortId |
7 days | api/p.js, api/custom.js |
shortid:<shortId> |
destination URL | 30 days | api/p.js, api/custom.js, api/redirect.js |
all |
serialized JSON array | 30 seconds | api/all.js |
Security Headers
Current handlers set a small set of response headers:
api/p.js:X-Content-Type-Options,X-Frame-Options,X-XSS-Protectionapi/custom.js:X-Content-Type-Options,X-Frame-Optionsapi/redirect.js:X-Content-Type-Options,Referrer-Policy
Rate Limiting
api/_lib/rate-limit.js exposes a Redis-backed helper:
getRedisClient()checkRateLimit(ip, limit = 100, windowSec = 3600)
At the moment, the helper exists but is not wired into the public route handlers. That means the repository includes rate-limit infrastructure, but requests are not currently being blocked by it.
PWA Notes
The service worker in static/assets/sw.js is intentionally minimal.
Current behavior:
- Caches
./and/cssduring install. - Claims clients on activation.
- Does not currently implement runtime fetch handling.
Frontend Notes
The current homepage includes:
- Intro overlay animation
- Copy-to-clipboard result state
- Alternate domain panel
- Toast-based status feedback
- SEO, GEO, and social metadata
- JSON-LD structured data
Alternate Domains
The UI currently advertises these domains:
https://lenk.cfhttps://nani.cfhttps://4543.mlhttps://urml.ml
Availability depends on DNS, hosting status, and whether those domains are still pointed at the deployed project.
Limitations and Implementation Notes
- No npm scripts are defined in
package.json. - The API is intentionally simple and does not include authentication.
/allexposes all stored records and should be treated carefully in public deployments.- Alias uniqueness is handled in application logic rather than database constraints.
- The rate-limit helper is present but not enforced.
- The service worker is partial rather than a full offline strategy.
Example cURL Requests
Create a random short link
curl "http://localhost:3000/p/https%3A%2F%2Fexample.com%2Fguide"
Create a custom short link
curl -X POST "http://localhost:3000/custom" \
-H "Content-Type: application/json" \
-d '{"url":"https://example.com","shortId":"docs"}'
Inspect the API index
curl "http://localhost:3000/api"
List all stored links
curl "http://localhost:3000/all"
License
This project is licensed under the MIT License. See LICENSE.
Credits
- Project: Adithya Pai
- Site: https://adithyapai.com
- Source: https://github.com/adithyapaib/lenk.cf
β€οΈ lenk.cf
A fast, open-source URL shortener built with Node.js, MongoDB, and Vercel serverless functions. Features Redis caching for near-instant redirects, a custom alias system, a Progressive Web App (PWA) frontend, and a simple REST API.
Tech Stack
Client: HTML, SCSS, Vanilla JS, PWA (Service Worker)
Server: Node.js, MongoDB (Mongoose), Redis, Vercel Serverless Functions
π¦ Screenshots
.png)
π» Requirements
- Node.js 18+
- MongoDB Atlas cluster
- Redis instance (e.g. Redis Cloud)
- Vercel CLI
π Deployment
1. Install Vercel CLI
npm i -g vercel
2. Set up MongoDB Atlas
Go to MongoDB Atlas, create a cluster, and copy the Node.js connection URI.
3. Set up Redis
Create a free Redis instance at Redis Cloud and copy the connection URL.
4. Clone and install
git clone https://github.com/adithyapaib/lenk.cf
cd lenk.cf
npm i
5. Create .env
DB=mongodb+srv://<user>:<password>@cluster0.xxxxx.mongodb.net/lenk-cf?retryWrites=true&w=majority
REDIS_URL=redis://default:<password>@<host>:<port>
6. Run locally
vercel dev
App runs at http://localhost:3000.
7. Deploy to Vercel
vercel deploy
Add DB and REDIS_URL as Environment Variables in your Vercel project settings.
π’ API Reference
All endpoints are available at http://localhost:3000 locally or your Vercel domain in production.
GET /api β API info
Returns server status and a list of all endpoints.
GET /<shortId> β Redirect
Resolves a short ID and redirects to the original URL (301). Results are cached in Redis for 30 days.
GET /p/<encodedUrl> β Create short link (random alias)
GET /p/https%3A%2F%2Fexample.com%2Fsome%2Flong%2Fpath
| Parameter | Description |
|---|---|
encodedUrl |
Required. The long URL, encodeURIComponent-encoded. |
Returns the generated shortId as a JSON string. Cached for 7 days.
POST /custom β Create short link (custom alias)
POST /custom
Content-Type: application/json
{ "url": "https://example.com", "shortId": "myalias" }
| Field | Description |
|---|---|
url |
Required. The long URL to shorten. |
shortId |
Required. Your custom alias (letters, numbers, hyphens, underscores). |
Returns the shortId string on success, or 0 if the alias is already taken. Cached for 30 days.
GET /all β List all short links
Returns all documents in the database, prefixed with a count. Cached for 30 seconds.
GET /404 β Not found page
Shown when a short ID doesn't exist in the database.
π° Environment Variables
| Variable | Description |
|---|---|
DB |
MongoDB connection URI |
REDIS_URL |
Redis connection URL |
π¦ Caching
| Cache key | TTL | Used in |
|---|---|---|
shortid:<id> β URL |
30 days | redirect.js, p.js, custom.js |
url:<url> β shortId |
7 days | p.js, custom.js |
all β JSON list |
30 seconds | all.js |
π Domains
π¦ Acknowledgements
- ππΌββοΈ Follow me on GitHub and star β this repo!
π License