Minimal URL shortener with DNS validation, custom codes, click tracking, and real-time analytics (Next.js 15 + Neon PostgreSQL + Prisma)
🚀 Live Demo: https://tiny-link-harsh.vercel.app/
- Overview
- Features
- Tech Stack
- Architecture & Project Structure
- Installation & Setup
- API Overview
- Frontend Flows
- Environment Configuration
- Author
TinyLink is a production-ready URL shortener built with enterprise-grade validation, featuring:
- DNS Verification – Only accepts real, existing domains
- Custom short codes with duplicate protection
- Real-time click tracking with timestamps
- Beautiful gradient UI with toast notifications
- Instant updates without page reload
- Copy-to-clipboard functionality
- Delete functionality with confirmation
- Deployed on Vercel with Neon PostgreSQL
Demonstrates Next.js 15 App Router, Prisma ORM, DNS validation, and full-stack TypeScript patterns.
- ✅ Shorten any URL → tiny-link-harsh.vercel.app/abc123
- ✅ Auto-add https:// for user convenience (e.g., google.com → https://google.com)
- ✅ DNS verification – Rejects fake domains (e.g., codechef.co fails, codechef.com works)
- ✅ Custom codes (e.g., tiny.link/mylink)
- ✅ Duplicate protection – Rejects existing codes with clear error message
- ✅ Smart redirects with click counting
- ✅ Last clicked timestamp tracking
- 📈 Real-time stats – Total clicks + last click timestamp per link
- 🗑️ Delete links with loading state and confirmation
- 📋 List all your links with beautiful card layout
- 📋 Copy-to-clipboard with toast notification
- ⚡ Instant UI updates – No page reload needed
- 🎨 Toast notifications for all actions (success/error)
- 🔍 3-Layer validation:
- Format check (valid URL structure)
- TLD check (200+ valid domain extensions)
- DNS check (domain must actually exist)
- 🚫 Rejects invalid URLs:
- ❌ Fake TLDs (e.g., .ap, .xyz123)
- ❌ Non-existent domains (e.g., fake-site-12345.com)
- ❌ Malformed URLs
- ✅ Accepts all valid formats:
- google.com
- `https://github.com
- perplexity.ai
- vercel.app
- 🌈 Modern gradient design with animations
- 📱 Fully responsive – Mobile, tablet, desktop
- 🎯 Real-time validation feedback
- ⚡ Loading states on all buttons
- 🎉 Success animations with toast
- 🚀 Smooth transitions and hover effects
- 📊 Stats visualization with icons
- ❌ Clear error messages with context
| Layer | Technologies |
|---|---|
| Framework | Next.js 15 (App Router), TypeScript, React 19 |
| Database | Neon PostgreSQL (Serverless), Prisma ORM |
| Styling | Tailwind CSS, CSS Gradients, Animations |
| Validation | DNS Resolution (Node.js dns/promises), URL API |
| UI Library | React Hot Toast (notifications) |
| Deployment | Vercel (serverless functions + edge network) |
| Dev Tools | ESLint, Prettier, Prisma Studio, TypeScript Strict Mode |
tiny-link/ ├── app/ # Next.js 16 App Router │ ├── api/links/ # API routes (POST, GET, DELETE) │ │ └── [code]/ # Stats + delete │ ├── code/[code]/ # Stats page │ ├── page.tsx # Dashboard │ ├── healthz/ # Health check │ └── not-found.tsx ├── lib/ │ └── prisma.ts # Prisma client ├── prisma/ │ └── schema.prisma # Link model (code, url, clicks, timestamps) ├── .env # DATABASE_URL └── tailwind.config.js
- Node.js v18+ (LTS)
- Neon PostgreSQL account
- npm or yarn
git clone https://github.com/Harsh427744/tiny-link.git cd tiny-link
Copy .env.example → .env:
DATABASE_URL="postgresql://user:[email protected]/tinylink?sslmode=require" NEXTAUTH_SECRET="your-random-secret" NEXTAUTH_URL="http://localhost:3000"
npm install npx prisma generate npx prisma db push # or migrate deploy
npm run dev
Dashboard: http://localhost:3000
POST /api/links # { url: "https://...", code?: "custom" } GET /api/links # List user's links GET /api/links/:code # Stats for code DELETE /api/links/:code # Delete link
GET /:code # 302 redirect + increment clicks GET /healthz # { "ok": true, "version": "1.0" }
Create Link Payload:
{ "url": "https://google.com", "code": "google" // optional custom code }
- Dashboard → Form: Enter URL → Shorten
- Success → Copy
tiny.link/abc123+ view clicks - Stats
/code/abc123→ Total clicks + timestamps - Delete → Confirm → Removed from list
- Invalid URL → Inline error + shake animation
RequiredDATABASE_URL="postgresql://[email protected]/tinylink?sslmode=require"OptionalNEXTAUTH_SECRET="sk-..." # Generate with openssl rand -base64 32 NEXTAUTH_URL="http://localhost:3000"
Harsh Agarwal
- GitHub: @Harsh427744
- LinkedIn: harsh323
- Email: [email protected]
⭐ Star this repo if you find it helpful!
Built for take-home assignment • Deployed on Vercel + Neon • Production-ready
