One Link. Endless Possibilities. — Connect your audience to everything you do with a beautiful, customizable landing page.
Live Demo • Features • Quick Start • Documentation • Contributing
- 4-Step Wizard: Intuitive multi-step form for creating your OneLink in minutes
- Custom Handles: Claim unique usernames with real-time availability validation
- Profile Customization: Upload profile images, write compelling bios, add unlimited links
- Responsive Design: Beautiful UI optimized for desktop, tablet, and mobile devices
- Dark Mode Support: Seamless theme switching with localStorage persistence
- Production-Ready: Full-stack architecture with MongoDB backend and real-time validation
- Highlights
- Overview
- Features
- Tech Stack
- Quick Start
- Documentation
- Database Schema
- Architecture
- Development
- Roadmap
- Learnings
- Contributing
- License
- Support
OneLink is a production-ready full-stack application for creating personalized link landing pages. Built with Next.js, React, and MongoDB, it streamlines how creators, entrepreneurs, and businesses connect their audience to all their content in one beautiful place.
- Next.js App Router: Modern React with server-side rendering and dynamic routing
- Multi-Step Form Pattern: Progressive disclosure for better UX and data validation
- MongoDB Collections: Scalable document storage with indexing for unique handles
- Dynamic Routes (
[handle]): Unlimited user profiles without pre-configuration - Client-Side Image Conversion: Base64 encoding for profile images stored with document data
- Real-Time Validation: Immediate feedback on handle availability and form requirements
|
|
| Layer | Technology | Version |
|---|---|---|
| Frontend Framework | Next.js | 16.1.6 |
| UI Library | React | 19.2.3 |
| Styling | Tailwind CSS | 4 |
| Database | MongoDB | 7.0.0 |
| Animations | Rive | 4.26.2 |
| Icons | Lucide React | 0.563.0 |
| Theme Management | next-themes | 0.4.6 |
| Linting | ESLint | 9 |
- Node.js 18.17+
- MongoDB (local or MongoDB Atlas)
- npm or yarn
# Clone the repository
git clone https://github.com/Muzzu8421/onelink.git
cd onelink
# Install dependencies
npm install
# Set up environment variables
echo 'MONGODB_URI=your_mongodb_connection_string' > .env.local
# Start the development server
npm run devVisit http://localhost:3000 in your browser.
Full Installation Guide
git clone https://github.com/Muzzu8421/onelink.git
cd onelinknpm installCreate .env.local in the project root:
# MongoDB Connection
MONGODB_URI=mongodb+srv://username:password@cluster.mongodb.net/onelinkMongoDB Atlas Setup:
- Create account at mongodb.com/cloud/atlas
- Create a free cluster
- Get connection string from "Connect" button
- Replace
usernameandpasswordwith your credentials - Add
/onelinkto the end for database name
npm run devnpm run build
npm startEnvironment Variables:
| Variable | Required | Description | Example |
|---|---|---|---|
MONGODB_URI |
✅ | MongoDB connection string | mongodb+srv://user:pass@cluster.mongodb.net/onelink |
- Navigate to homepage
- Enter your desired handle (e.g., "yourname")
- Click "Get Started Free"
- Step 1: Confirm your handle (
onelink.to/yourname) - Step 2: Write a short bio/description
- Step 3: Add links to social media, websites, products
- Step 4: Upload profile image
- Click "Create My OneLink"
- Share your unique URL with your audience!
Example OneLink:
- Handle: johnsmith
- URL: onelink.to/johnsmith
- Links: Instagram, Twitter, Portfolio, Shop
- Bio: Designer & entrepreneur sharing my journey
Share this link:
https://yoursite.com/johnsmith
Visitors click and see:
- Profile image
- Bio
- All your links in one place
Endpoint: POST /api/create
Request:
{
"handle": "yourname",
"desc": "Your bio here",
"links": [
{
"title": "Instagram",
"url": "https://instagram.com/yourname"
},
{
"title": "Portfolio",
"url": "https://yourportfolio.com"
}
],
"profileImage": "data:image/jpeg;base64,..."
}Response (Success - 200):
{
"Success": true,
"message": "OneLink created successfully",
"handle": "yourname"
}Response (Error - 409 - Duplicate Handle):
{
"Success": false,
"message": "Handle already exists"
}onelink/
├── src/
│ ├── app/
│ │ ├── layout.js # Root layout with navbar
│ │ ├── page.js # Homepage landing page
│ │ ├── generate/
│ │ │ └── page.js # 4-step wizard form
│ │ ├── [handle]/
│ │ │ └── page.js # Dynamic profile pages
│ │ ├── api/
│ │ │ └── create/
│ │ │ └── route.js # POST /api/create endpoint
│ │ ├── globals.css # Global styles
│ │ └── favicon.ico # Site favicon
│ ├── components/
│ │ ├── Navbar.js # Navigation bar
│ │ ├── CustomizationSection.js # Homepage features section
│ │ └── ShareSection.js # Call-to-action section
│ └── lib/
│ └── mongodb.js # MongoDB client config (if exists)
├── public/ # Static assets (images, gifs)
│ ├── test2.gif # Homepage animation
│ └── gen.avif # Generator page image
├── .env.local # Environment variables
├── next.config.mjs # Next.js configuration
├── tailwind.config.js # Tailwind CSS config
├── jsconfig.json # JavaScript config
└── package.json # Dependencies
{
_id: ObjectId,
handle: String, // Unique username (indexed)
desc: String, // Bio/description
profileImage: String, // Base64 encoded image
links: [
{
title: String, // e.g., "Instagram"
url: String // e.g., "https://instagram.com/..."
}
],
createdAt: Date, // Creation timestamp
updatedAt: Date // Last update timestamp
}Indexes:
db.onelinks.createIndex({ handle: 1 }, { unique: true })┌──────────────────────────────────────────────┐
│ User Browser │
├──────────────────────────────────────────────┤
│ Next.js Frontend (React Components) │
│ ├─ Homepage (landing page) │
│ ├─ Generator (4-step wizard) │
│ ├─ Profile (dynamic [handle] page) │
│ └─ Theme Manager (localStorage) │
├──────────────────────────────────────────────┤
│ Next.js API Routes (Backend) │
│ └─ POST /api/create (OneLink creation) │
│ └─ GET /[handle] (Profile retrieval) │
├──────────────────────────────────────────────┤
│ MongoDB Database │
│ └─ onelinks collection (User data) │
└──────────────────────────────────────────────┘
Data Flow:
- User enters handle on homepage → clicks "Get Started Free"
- Navigates to /generate with handle as query param
- Fills 4-step form with bio, links, and profile image
- Submits POST request to
/api/create - Backend validates handle uniqueness, stores in MongoDB
- Redirect to
/:handledynamic route - Visitor accesses profile → fetches from DB → displays OneLink page
npm run dev # Start dev server (http://localhost:3000)
npm run build # Production build
npm start # Run production build
npm run lint # Run ESLint| Route | Purpose | Status |
|---|---|---|
/ |
Landing page / homepage | ✅ Active |
/generate |
OneLink creation wizard | ✅ Active |
/[handle] |
User profile page | ✅ Active |
/api/create |
Create OneLink endpoint | ✅ Active |
- Multi-step form wizard
- Profile image upload
- Links management
- Dynamic profile pages
- Responsive design
- Dark mode support
- Click tracking per link
- View count statistics
- Time-series analytics dashboard
- Link performance insights
- User authentication & accounts
- Edit existing OneLinks
- Link scheduling
- QR code generation
- Custom domains (yourname.com)
- Link categories/sections
- Social media auto-population
- Rate limiting
- Caching layer (Redis)
- CDN integration
- Monitoring & alerts
- API keys for programmatic access
- Webhook support
Frontend Architecture
- Building multi-step forms with React hooks for progressive data collection
- Client-side file handling and Base64 encoding for image data
- Dynamic routing with catch-all segments (
[handle]) for URL patterns - Query parameter parsing for pre-filling form data
Backend Development
- RESTful API design with Next.js API routes and proper HTTP methods
- Request validation and error handling at the API layer
- MongoDB connection management and document operations
- Handling concurrent requests safely
Database Design
- Unique indexing strategy for preventing duplicate handles
- Storing nested arrays (links) within documents vs. separate collections
- Base64 image encoding trade-offs (storage vs. performance)
- Timestamp management for audit trails and future analytics
Full-Stack Considerations
- Environment variable management for development, staging, production
- Responsive mobile-first design with Tailwind CSS
- Theme persistence using browser localStorage
- How to structure code for feature scaling (components, API routes, database queries)
- UX patterns for form validation and user feedback
Contributions make the open source community amazing! We welcome:
- Bug Reports - Issues with features or functionality
- Feature Requests - New ideas and enhancements
- Pull Requests - Code improvements and fixes
- Documentation - README updates, guides, examples
# Fork the repo on GitHub
# Clone your fork
git clone https://github.com/YOUR_USERNAME/onelink.git
cd onelink
# Create a feature branch
git checkout -b feature/amazing-feature
# Make changes and commit
git add .
git commit -m "feat: Add amazing feature"
# Push to your fork
git push origin feature/amazing-feature
# Open Pull Request on GitHub- Use ESLint:
npm run lint - Follow React & Next.js best practices
- Write meaningful commit messages
- Add comments for complex logic
- Test your changes locally before submitting
This project is licensed under the MIT License - see the LICENSE file for details.
MIT License - You are free to use this project for personal or commercial purposes.
- 📖 Documentation - Read the full guide
- 🐛 Bug Reports - Open an issue
- 💬 Discussions - GitHub Discussions
MongoDB connection fails
- Verify
MONGODB_URIin.env.local - Check MongoDB Atlas IP whitelist (add your IP)
- Ensure database name is correct:
onelink - Test connection:
node -e "require('mongodb').MongoClient.connect(process.env.MONGODB_URI)" - Check network connectivity to MongoDB cluster
Handle already exists error
- Try a different handle - this one is already taken
- Check MongoDB for duplicate indexes:
db.onelinks.getIndexes() - If stuck, contact support or try with timestamp:
username_1234
Profile image not uploading
- Check file size (keep under 5MB)
- Ensure it's a valid image format (JPG, PNG, GIF, WebP)
- Check browser console for errors (F12 → Console tab)
- Try a different image file
- Clear browser cache and try again
Profile page not loading
- Verify the handle is correct (check URL)
- Ensure the handle exists in MongoDB
- Check if MongoDB connection is active
- Look for 404 errors in browser console
- Test API directly:
curl http://localhost:3000/yourhandle
Styling or theme not working
- Run
npm installto ensure Tailwind is installed - Restart dev server:
npm run dev - Clear browser cache (Ctrl+Shift+Delete)
- Check if
globals.cssis imported in layout.js - Verify tailwind.config.js has correct content paths