One URL for all your links - An open-source alternative to Linktree. Create a beautiful profile page to share all your important links in one place.
- Google OAuth Authentication - Secure and seamless sign-in with your existing Google account
- Custom Profile Pages - Create personalized profile pages with your unique username
- Link Management - Add, edit, and reorganize your links effortlessly
- Deep Analytics - Track clicks and view detailed insights about your audience engagement
- Avatar Upload - Upload and customize your profile picture with drag-and-drop support
- Responsive Design - Your profile looks perfect on every device
- Fast & Modern - Built with Next.js 16 and React 19 for instant page loads
┌─────────────────────────────────┐ ┌─────────────────────────────────┐
│ FRONTEND (Next.js) │ │ BACKEND (Express) │
│ oneurl.live (:3000) │ ───► │ api.oneurl.live (:3001) │
└─────────────────────────────────┘ └─────────────────────────────────┘
│
▼
┌─────────────────────────────────┐
│ DATABASE (Neon) │
│ PostgreSQL Serverless │
└─────────────────────────────────┘
Key Principle: The frontend never accesses the database directly. All data operations go through the backend API.
- Framework: Next.js 16 (App Router)
- Language: TypeScript
- State Management: TanStack Query (React Query)
- Styling: Tailwind CSS
- UI Components: Base UI React
- Charts: Recharts
- Framework: Express.js
- Database: PostgreSQL with Prisma ORM + Neon Serverless
- Authentication: Better Auth (Google OAuth)
- File Upload: UploadThing
Before you begin, ensure you have:
- Node.js 20+ or Bun installed
- PostgreSQL database (Neon recommended for serverless)
- Google OAuth credentials
- UploadThing account (free tier available)
git clone https://github.com/KartikLabhshetwar/oneurl.git
cd oneurl# Frontend
bun install
# Backend
cd backend && bun install && cd ..Frontend .env (root directory):
# Backend API URL - REQUIRED for client-side code
# NEXT_PUBLIC_ prefix makes it available in the browser
NEXT_PUBLIC_BACKEND_URL=http://localhost:3001
# UploadThing (for client-side uploads)
NEXT_PUBLIC_UPLOADTHING_APP_ID=your-app-idBackend .env (backend/ directory):
# Database - Neon PostgreSQL
DATABASE_URL=postgresql://user:password@host.neon.tech/dbname?sslmode=require
# Server
PORT=3001
NODE_ENV=development
BACKEND_URL=http://localhost:3001
FRONTEND_URL=http://localhost:3000
# Better Auth
BETTER_AUTH_URL=http://localhost:3001
BETTER_AUTH_SECRET=your-secret-key-minimum-32-characters
# Google OAuth
GOOGLE_CLIENT_ID=your-google-client-id
GOOGLE_CLIENT_SECRET=your-google-client-secret
# UploadThing
UPLOADTHING_TOKEN=your-uploadthing-tokencd backend
# Generate Prisma Client
bun run prisma:generate
# Run migrations
bun run prisma:migrateOption 1: Run both services together
bun run dev:allOption 2: Run separately
# Terminal 1 - Frontend
bun run dev
# Terminal 2 - Backend
cd backend && bun run dev- Frontend: http://localhost:3000
- Backend API: http://localhost:3001
oneurl/
├── app/ # Next.js app directory
│ ├── (auth)/ # Authentication routes (login, signup)
│ ├── (dashboard)/ # Dashboard routes (protected)
│ ├── (onboarding)/ # Onboarding flow
│ ├── [username]/ # Public profile pages
│ └── api/ # API route proxies
├── backend/ # Express backend service
│ ├── src/
│ │ ├── config/ # Auth, DB, UploadThing config
│ │ ├── routes/ # API routes
│ │ ├── services/ # Business logic
│ │ ├── middleware/ # Rate limiting, validation, auth
│ │ └── server.ts # Express app entry
│ └── prisma/ # Database schema
├── components/ # React components
│ ├── landing/ # Landing page components
│ └── ui/ # UI component library
├── lib/ # Utility functions
│ ├── auth.ts # Server-side auth utilities
│ ├── auth-client.ts # Client-side auth
│ ├── auth-guard.ts # Route protection
│ └── utils/ # API clients
└── public/ # Static assets
| Endpoint | Description |
|---|---|
/api/auth/* |
Authentication (Better Auth + Google OAuth) |
/api/profile |
User profile management |
/api/links |
Link CRUD operations |
/api/track |
Click tracking |
/api/analytics |
Analytics data |
/api/preview |
URL metadata fetching |
/api/uploadthing |
File uploads |
Frontend:
bun run dev- Start Next.js development serverbun run build- Build for productionbun run start- Start production server
Backend:
bun run dev:backend- Start backend development serverbun run build:backend- Build backend for productionbun run start:backend- Start backend production server
Both:
bun run dev:all- Run both frontend and backend
- Go to Google Cloud Console
- Create a new project or select existing one
- Enable Google+ API
- Create OAuth 2.0 credentials
- Add authorized redirect URIs:
- Development:
http://localhost:3001/api/auth/callback/google - Production:
https://api.oneurl.live/api/auth/callback/google
- Development:
- Copy Client ID and Client Secret to backend
.env
The easiest way to self-host OneURL is using Docker. Everything is pre-configured for you.
- Clone and set up environment:
git clone https://github.com/KartikLabhshetwar/oneurl.git
cd oneurl
# Create .env file in root directory
cp .env.example .env- Configure your
.envfile:
# Database - Get a free Neon PostgreSQL at https://neon.tech
DATABASE_URL=postgresql://user:password@host.neon.tech/dbname?sslmode=require
# Authentication
BETTER_AUTH_SECRET=your-secret-key-minimum-32-characters
BETTER_AUTH_URL=http://localhost:3001
# URLs (change these for production)
# IMPORTANT: NEXT_PUBLIC_BACKEND_URL is required for client-side code
NEXT_PUBLIC_BACKEND_URL=http://localhost:3001
BACKEND_URL=http://localhost:3001
FRONTEND_URL=http://localhost:3000
# UploadThing
NEXT_PUBLIC_UPLOADTHING_APP_ID=your-app-id
UPLOADTHING_TOKEN=your-uploadthing-token
# Google OAuth - Get credentials at https://console.cloud.google.com
GOOGLE_CLIENT_ID=your-google-client-id
GOOGLE_CLIENT_SECRET=your-google-client-secret- Start with Docker Compose:
# Production mode
docker-compose up --build
# Development mode with hot reload
docker-compose -f docker-compose.dev.yml up --build- Access the app:
- Frontend: http://localhost:3000
- Backend API: http://localhost:3001
For production, update your .env:
# Frontend environment variables
NEXT_PUBLIC_BACKEND_URL=https://api.yourdomain.com
NEXT_PUBLIC_UPLOADTHING_APP_ID=your-app-id
# Backend environment variables
DATABASE_URL=postgresql://user:password@host.neon.tech/dbname?sslmode=require
BACKEND_URL=https://api.yourdomain.com
FRONTEND_URL=https://yourdomain.com
BETTER_AUTH_URL=https://api.yourdomain.com
BETTER_AUTH_SECRET=your-production-secret
GOOGLE_CLIENT_ID=your-google-client-id
GOOGLE_CLIENT_SECRET=your-google-client-secret
UPLOADTHING_TOKEN=your-uploadthing-tokenCritical: Make sure NEXT_PUBLIC_BACKEND_URL matches your backend domain. This is required for client-side authentication and API calls to work.
Then deploy using any Docker-compatible platform:
- Docker Swarm
- Kubernetes
- Railway
- Render
- Fly.io
- DigitalOcean App Platform
Contributions are welcome! Please read our Contributing Guidelines for details.
- Fork the repository
- Create your feature branch (
git checkout -b feature/AmazingFeature) - Commit your changes (
git commit -m 'Add some AmazingFeature') - Push to the branch (
git push origin feature/AmazingFeature) - Open a Pull Request
This project is licensed under the BSD 3-Clause License - see the LICENSE file for details.
Made by Kartik Labhshetwar