UGC Reactions from Real Creators
Real creator library videos at $11 and images at $8. Custom production from $25/video with a $250 minimum. Commercial licensing included.
翻訳待ち
No updates detected yet. GitHub releases will appear here.
Snip: a URL shortener with click analytics, QR codes and a Chart.js dashboard (Node.js, Express, SQLite)
翻訳待ち
Loading the full README.
Read the full README ↗Snip is a full-stack URL shortener like Bitly. It turns long links into short ones with optional custom aliases, generates a QR code for each, and tracks every click with a clean analytics dashboard: clicks over time, unique visitors, referrers, browsers, operating systems and devices.
Backend: Node.js, Express, Postgres (Neon) in production and SQLite (built-in node:sqlite) locally, qrcode
Frontend: vanilla JavaScript + Chart.js
Tests: 16 integration tests with node:test, with the API tests run on both SQLite and Postgres (via PGlite)
Hosting: Vercel (serverless) + Neon Postgres
🔗 Live demo: https://link-shortener-alpha-orpin.vercel.app/
https:// added automatically and validation (blocks javascript: and private or localhost addresses)/my-portfolio), with reserved words and duplicates rejectedRequires Node.js 22.13 or newer.
git clone https://github.com/akrambgh1/link-shortener.git
cd link-shortener
npm install
npm start # http://localhost:4100
npm test
All /api/links routes need an X-Owner-Key header (any random 16–64 character string).
| Method | Endpoint | Description |
|---|---|---|
| POST | /api/links | { url, alias? } → create a short link |
| GET | /api/links | Your links with click counts |
| GET | /api/links/:code/stats?days=30 | Totals, timeline, referrers, browsers, OS, devices, recent clicks |
| GET | /api/links/:code/qr.svg | QR code image |
| DELETE | /api/links/:code | Delete a link and its clicks |
| GET | /:code | 302 redirect to the original URL (and records the click) |
curl -X POST http://localhost:4100/api/links \
-H "Content-Type: application/json" -H "X-Owner-Key: my-secret-owner-key-123" \
-d '{"url":"github.com/akrambgh1","alias":"me"}'
# → { "link": { "code": "me", "shortUrl": "http://localhost:4100/me", ... } }
links (id, code UNIQUE, url, owner, created_at)
clicks (id, link_id → links ON DELETE CASCADE, clicked_at, referrer, browser, os, device, visitor)
Stats are calculated with SQL GROUP BY queries, and days with no clicks are filled in, so the chart never has gaps.
DATABASE_URL.VISITOR_SALT environment variable (any random string), then Redeploy.vercel.json sends /api/* and short codes like /my-link to the serverless function. Everything else (the dashboard) is served as static files.
src/db.js exposes a tiny all() / get() interface with ? placeholders, converted to $1, $2… for Postgres. Case-insensitive aliases use a lower(code) unique index that works in both. The API tests run on SQLite and on real Postgres via PGlite.
link-shortener/
├── server.js # Local server
├── api/index.js # Vercel serverless entry
├── vercel.json # Rewrites for /api/* and short codes
├── src/
│ ├── app.js # Routes, validation, redirect + click tracking, stats
│ ├── db.js # SQLite / Postgres adapter + schema
│ └── ua.js # User-agent & referrer parsing
├── public/ # Dashboard (HTML, CSS, JS + Chart.js), 404 page
└── test/api.test.js
Cache-Control: no-store matters for click countingMIT. Free to use and modify.