A full-stack URL shortener application built with Next.js, TypeScript, Node.js, and MongoDB. Features include custom domains, analytics, QR codes, and more.
- URL Shortening: Create short, memorable links from long URLs
- Custom Domains: Use your own branded domains for short links
- QR Code Generation: Automatic QR code generation for every link
- Link Analytics: Detailed analytics with charts and insights
- Bulk Link Creation: Create multiple links at once
- Link Management: Edit, delete, and organize your links
- Custom Slugs: Create personalized short URLs
- Link Expiration: Set expiration dates for temporary links
- Password Protection: Secure links with passwords
- Tag System: Organize links with custom tags
- Real-time Analytics: Live click tracking and statistics
- Export Data: Download analytics data as CSV
- Responsive Design: Works perfectly on all devices
- Dark/Light Mode: Toggle between themes
- Real-time Updates: Live data updates using modern state management
- SEO Optimized: Built with SEO best practices
- Performance Optimized: Fast loading and smooth interactions
- Next.js 14 - React framework with App Router
- TypeScript - Type-safe development
- Tailwind CSS - Utility-first CSS framework
- Recoil - State management
- Framer Motion - Smooth animations
- Recharts - Beautiful charts and analytics
- Radix UI - Accessible UI components
- Lucide React - Beautiful icons
- Node.js - JavaScript runtime
- Express.js - Web framework
- TypeScript - Type-safe backend development
- MongoDB - NoSQL database
- Mongoose - MongoDB object modeling
- JWT - Authentication
- bcryptjs - Password hashing
- QRCode - QR code generation
``` url-shortener/ βββ frontend/ # Next.js frontend application β βββ app/ # App Router pages β β βββ dashboard/ # Dashboard pages β β βββ login/ # Authentication pages β β βββ register/ β βββ components/ # Reusable components β β βββ auth/ # Authentication components β β βββ dashboard/ # Dashboard components β β βββ landing/ # Landing page components β β βββ providers/ # Context providers β β βββ ui/ # UI components β βββ store/ # Recoil state management β β βββ atoms/ # State atoms β β βββ selectors/ # State selectors β βββ lib/ # Utility functions βββ backend/ # Node.js backend application β βββ src/ β β βββ controllers/ # Route controllers β β βββ middleware/ # Custom middleware β β βββ models/ # Database models β β βββ routes/ # API routes β β βββ types/ # TypeScript types β βββ dist/ # Compiled JavaScript βββ README.md ```
- Node.js 18+
- MongoDB database
- npm or yarn package manager
-
Clone the repository ```bash git clone https://github.com/yourusername/url-shortener.git cd url-shortener ```
-
Install backend dependencies ```bash cd backend npm install ```
-
Install frontend dependencies ```bash cd ../frontend npm install ```
-
Set up environment variables
Backend (.env) ```env
PORT=5000 NODE_ENV=development
MONGODB_URI=mongodb://localhost:27017/linkly
JWT_SECRET=your-super-secret-jwt-key JWT_EXPIRES_IN=7d
DEFAULT_DOMAIN=somn.in FRONTEND_URL=http://localhost:3000 ```
Frontend (.env.local) ```env NEXT_PUBLIC_API_URL=http://localhost:5000/api ```
-
Start the development servers
Backend: ```bash cd backend npm run dev ```
Frontend: ```bash cd frontend npm run dev ```
-
Access the application
- Frontend: http://localhost:3000
- Backend API: http://localhost:5000
The application supports custom domains for branded short links. Here's how it works:
- Set
DEFAULT_DOMAIN=somn.in
in your backend environment - This domain is used for all links by default
- Go to Dashboard β Domains
- Click "Add Domain"
- Enter your domain name (e.g.,
yourbrand.com
) - Add the DNS TXT record provided
- Click "Verify Domain"
Add this TXT record to your domain's DNS: ``` Type: TXT Name: @ Value: linkly-verify=your-verification-token ```
- Verification: Automatic DNS verification
- Default Domain: Set any verified domain as default
- Branded Links: All new links use your custom domain
- SSL Support: Automatic HTTPS for all domains
The app uses JWT-based authentication with persistent login:
- User creates account with email/password
- Password is hashed using bcryptjs
- JWT token is generated and returned
- User provides credentials
- Server validates and returns JWT token
- Token is stored in localStorage
- Automatic redirect to dashboard
- Token is checked on app initialization
/api/auth/getme
endpoint validates token- User state is restored automatically
- Invalid tokens are cleared
- Middleware protects dashboard routes
- Automatic redirect to login if unauthenticated
- Token validation on every request
- Real-time: Clicks are tracked immediately
- Geolocation: Country-based analytics
- Device Detection: Mobile, desktop, tablet tracking
- Browser Analytics: Browser and OS information
- Referrer Tracking: Source of traffic
- Overview Cards: Total clicks, links, click rate
- Interactive Charts: Line charts, pie charts, bar charts
- Time-based Filtering: 7 days, 30 days, 90 days
- Export Functionality: Download data as CSV
- Top Performers: Most clicked links
```typescript interface ClickAnalytics { totalClicks: number totalLinks: number clickRate: number topCountries: Array<{ country: string; clicks: number }> topDevices: Array<{ device: string; clicks: number }> topBrowsers: Array<{ browser: string; clicks: number }> clicksByDate: Array<{ date: string; clicks: number }> topLinks: Array<{ id: string; title: string; clicks: number }> } ```
POST /api/auth/register
- User registrationPOST /api/auth/login
- User loginGET /api/auth/getme
- Get current userPOST /api/auth/logout
- User logout
GET /api/links
- Get user's links (with pagination)POST /api/links
- Create new linkGET /api/links/:id
- Get specific linkPUT /api/links/:id
- Update linkDELETE /api/links/:id
- Delete linkPOST /api/links/bulk
- Create multiple linksGET /api/links/tags
- Get all tags
GET /api/domains
- Get user's domainsPOST /api/domains
- Add new domainPOST /api/domains/:id/verify
- Verify domainPOST /api/domains/:id/default
- Set default domainDELETE /api/domains/:id
- Delete domain
GET /api/analytics/overview
- Overall analyticsGET /api/analytics/links/:id
- Link-specific analyticsGET /api/analytics/dashboard
- Dashboard analytics
GET /:slug
- Redirect to original URL (tracks click)
The application uses a comprehensive design system:
- Cards: Information containers with hover effects
- Buttons: Multiple variants (primary, secondary, outline, ghost)
- Forms: Inputs, textareas, selects with validation
- Navigation: Sidebar, breadcrumbs, tabs
- Modals: Dialogs, alerts, confirmations
- Analytics Charts: Line, bar, pie charts with Recharts
- Data Tables: Sortable, filterable tables
- Link Cards: Rich link display with actions
- Stats Cards: Metric displays with trends
- Forms: Link creation, domain management
- Mobile-first: Optimized for mobile devices
- Breakpoints: sm, md, lg, xl responsive breakpoints
- Touch-friendly: Large touch targets
- Adaptive Layout: Components adapt to screen size
- Password Hashing: bcryptjs with salt rounds
- JWT Tokens: Secure token-based authentication
- Token Expiration: Configurable token lifetime
- Secure Headers: CORS, security headers
- Input Validation: Server-side validation
- SQL Injection Prevention: Mongoose ODM protection
- XSS Prevention: Input sanitization
- Rate Limiting: API rate limiting (can be added)
- DNS Verification: Verify domain ownership
- HTTPS Enforcement: Secure connections only
- Domain Validation: Prevent malicious domains
- Connect your GitHub repository to Vercel
- Set environment variables in Vercel dashboard
- Deploy automatically on push to main branch
- Create new project on Railway or Heroku
- Connect GitHub repository
- Set environment variables
- Deploy with automatic builds
- Create MongoDB Atlas cluster
- Get connection string
- Update MONGODB_URI in environment variables
- Configure network access and database users
```env
NODE_ENV=production MONGODB_URI=mongodb+srv://username:password@cluster.mongodb.net/linkly JWT_SECRET=your-production-jwt-secret DEFAULT_DOMAIN=yourdomain.com FRONTEND_URL=https://yourdomain.com
NEXT_PUBLIC_API_URL=https://your-api-domain.com/api ```
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature
) - Commit your changes (
git commit -m 'Add amazing feature'
) - Push to the branch (
git push origin feature/amazing-feature
) - Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
- Next.js - React framework
- Tailwind CSS - CSS framework
- Radix UI - UI components
- Recharts - Chart library
- Lucide - Icon library
- Framer Motion - Animation library
If you have any questions or need help, please:
- Check the Issues page
- Create a new issue if your problem isn't already reported
- Provide detailed information about your setup and the issue
Built with β€οΈ by [Your Name]