Create short links with custom slugs, QR codes, and simple analytics. Built with Next.js App Router, Prisma (SQLite), and a clean dark UI.
- Shorten any URL with generated or custom slugs
- Expiring links (optional)
- Click analytics: total clicks, last access, recent events (IP, user‑agent)
- Stats page for each link at
/s/<slug> - Built‑in QR code rendering (no external image calls)
- Basic IP rate limiting on the create API
- GitHub‑inspired dark theme with responsive layout
- Next.js 15 (App Router, TypeScript)
- React 19
- Prisma ORM + SQLite
- nanoid (slug generation)
- qrcode (client‑side QR canvas)
- Install deps and generate Prisma client
pnpm install ; pnpm prisma generate
# or
npm install ; npx prisma generate
# or
bun install ; bunx prisma generate- Create and migrate the database
pnpm prisma migrate dev
# seed (optional)
pnpm run seed- Run the dev server
pnpm dev
# Open http://localhost:3000Environment variable:
DATABASE_URL(defaults tofile:./dev.dbvia Prisma)NEXT_PUBLIC_BASE_URL(optional; base used when returningshortUrl)
dev— start Next.js in dev modebuild— production build (Turbopack)start— start production servermigrate— run Prisma migrations in devseed— seed example data
POST /api/shorten
Request
{
"url": "https://example.com",
"slug": "optional-custom",
"expiresAt": "2025-12-31T23:59:59.000Z"
}Response
{ "slug": "abc1234", "shortUrl": "http://localhost:3000/abc1234" }GET /api/stats/:slug
Returns link metadata and the last 25 click events.
/— Landing + shortener form/[slug]— Redirects to the long URL, logs a click/s/[slug]— Stats page with metrics, QR, and recent eventsapp/not-found.tsx— Custom 404 with image and helpful actions
- Prisma client is created via a singleton in
lib/prisma.tsto avoid hot‑reload issues. - Rate limiting lives in
lib/ratelimit.ts(simple token bucket). Replace with a durable store for production. - QR codes render locally in
app/components/Qr.tsxusing a canvas to avoid remote blockers.
For personal and educational use. Replace branding and review dependencies before production use.