A modern URL shortening service with user accounts, custom categories, and analytics. Built with Deno, React, and PostgreSQL.
- Frontend: url-shortner-self-mu.vercel.app
- Backend API: url-shortner-1-pzxs.onrender.com
- Health Check: url-shortner-1-pzxs.onrender.com/health
- 🔐 User Accounts - Sign up and manage your own URLs
- 📊 Analytics - See how many times your links get clicked
- 🏷️ Categories - Group your URLs however you want
- 🎨 Clean Interface - Dark mode support, works on mobile
- ⚡ Actually Fast - Deno backend + Neon PostgreSQL
- 🔒 Security Built-in - JWT auth, CORS, password hashing
graph TB
subgraph "Frontend - Vercel"
A[React + Vite]
B[TailwindCSS]
A --> B
end
subgraph "Backend - Render"
C[Deno Server]
D[JWT Auth]
E[CORS Handler]
C --> D
C --> E
end
subgraph "Database - Neon"
F[(PostgreSQL)]
G[Users Table]
H[URLs Table]
I[Categories Table]
F --> G
F --> H
F --> I
end
A -->|HTTPS| C
C -->|SQL Queries| F
style A fill:#61dafb
style C fill:#000
style F fill:#336791
How it works:
- You visit the site and create an account
- Frontend sends your request to the Deno backend on Render
- Backend validates everything and saves to PostgreSQL on Neon
- You get a short link like
url-shortner-1-pzxs.onrender.com/abc123 - Anyone who clicks that link gets redirected to your original URL
- We count every click so you can see your stats
- Deno - The backend runtime
- Node.js - For frontend build tools
- Neon account - Free PostgreSQL database
# Get the code
git clone https://github.com/Voodels/URL-Shortner.git
cd URL-Shortner
# Create your env file
cp .env.example .envNow edit .env with your database info:
PORT=8000
JWT_SECRET=your_secret_here # openssl rand -base64 32
ALLOWED_ORIGINS=http://localhost:5173
DB_TYPE=postgres
DB_HOST=your-project.neon.tech # from neon.tech dashboard
DB_PORT=5432
DB_USER=neondb_owner
DB_PASSWORD=your_password
DB_NAME=neondb
DB_TLS=trueSetup the database:
PGPASSWORD='your_password' psql \
-h your-project.neon.tech \
-U neondb_owner \
-d neondb \
-f database/schema_postgres.sqlInstall frontend stuff:
cd frontend
npm install
cd ..Start everything:
./dev.shOr manually:
# Terminal 1
cd backend
deno run --allow-net --allow-env --allow-read server.ts
# Terminal 2
cd frontend
npm run devOpen http://localhost:5173 and you're good to go!
.
├── backend/ # Deno backend API
│ ├── server.ts # Main server entry point
│ ├── routes.ts # API route handlers
│ ├── database.ts # Database configuration
│ ├── postgres-store.ts # PostgreSQL repository
│ ├── auth-service.ts # Authentication logic
│ └── types.ts # TypeScript type definitions
│
├── frontend/ # React frontend
│ ├── src/
│ │ ├── App.tsx # Main app component
│ │ ├── components/ # React components
│ │ └── api.ts # API client
│ └── package.json
│
├── database/ # Database schemas
│ ├── schema_postgres.sql # PostgreSQL schema
│ └── schema.sql # Original MySQL schema
│
├── .env # Environment variables (not in git)
├── .env.example # Environment template
├── dev.sh # Development startup script
└── README.md # This file
POST /auth/register- Register new userPOST /auth/login- Login userGET /me- Get current user info
POST /shorten- Create short URLGET /shorten/:shortCode- Get URL detailsPUT /shorten/:shortCode- Update URLDELETE /shorten/:shortCode- Delete URLGET /urls- Get user's URLsGET /shorten/:shortCode/stats- Get URL statisticsGET /:shortCode- Redirect to original URL
GET /categories- Get user's categoriesPOST /categories- Create categoryPUT /categories/:id- Update categoryDELETE /categories/:id- Delete categoryPOST /shorten/:shortCode/categories- Add categories to URLDELETE /shorten/:shortCode/categories- Remove categories from URL
Backend
- Deno - Modern JavaScript/TypeScript runtime
- PostgreSQL - Database (hosted on Neon)
- JWT + bcrypt - Authentication
Frontend
- React 18 - UI framework
- Vite - Build tool (crazy fast)
- TailwindCSS + DaisyUI - Styling
Hosting
- Render - Backend deployment
- Vercel - Frontend deployment
- Neon - PostgreSQL database
- Fork this repo
- Create account on Render
- New Web Service → Connect your fork
- Settings:
- Environment: Docker
- Dockerfile Path:
docker/Dockerfile.backend - Docker Context:
./
- Add environment variables from your
.env - Deploy!
Test it: curl https://your-app.onrender.com/health
- Create account on Vercel
- Import your fork
- Settings:
- Framework: Vite
- Root Directory:
frontend - Build Command:
npm run build - Output Directory:
dist
- Add env var:
VITE_API_URL=https://your-backend.onrender.com - Deploy!
Important: Update ALLOWED_ORIGINS on Render to include your Vercel URL:
ALLOWED_ORIGINS=https://your-backend.onrender.com,https://your-frontend.vercel.app
| Variable | Description | Example |
|---|---|---|
PORT |
Backend server port | 8000 |
JWT_SECRET |
Secret for JWT token signing | Generate with openssl rand -base64 32 |
ALLOWED_ORIGINS |
CORS allowed origins (comma-separated) | http://localhost:5173,https://yourdomain.com |
LOG_REQUESTS |
Enable request logging | true or false |
DB_TYPE |
Database type | postgres, mysql, or memory |
DB_HOST |
Database hostname | your-project.neon.tech |
DB_PORT |
Database port | 5432 |
DB_USER |
Database username | your_username |
DB_PASSWORD |
Database password | your_password |
DB_NAME |
Database name | neondb |
DB_TLS |
Enable TLS connection | true (recommended for Neon) |
- Generate a random
JWT_SECRET(don't use the example!) - Never commit
.envfiles - Always use HTTPS in production
- Set
ALLOWED_ORIGINSto your actual domains only - Database uses TLS encryption
Found a bug? Have an idea? PRs are welcome!
- Fork it
- Create your branch (
git checkout -b cool-feature) - Commit changes (
git commit -m 'Added something cool') - Push (
git push origin cool-feature) - Open a Pull Request
MIT License - do whatever you want with it
Made by @Voodels
Questions? Open an issue or check out the live demo!