A fullstack web interface and API for shortening links, redirecting users, and monitoring access. A fullstack project focused on simplicity, modern design, and performance.
👉 Live demo: https://ns.grdev.app.br
| Feature | Description |
|---|---|
| 🔗 URL Shortening | Generates random codes or accepts custom slugs |
| ↪️ Redirection | Instantly forwards users to the original link |
| 📊 Click Counter | Tracks how many times each link has been accessed |
| 🎨 Modern UI | Responsive interface with Glassmorphism effect (EJS + CSS) |
| 🛡️ Security | URL validation and special character blocking via Regex |
| 📋 Quick Copy | Copies the generated link to clipboard with visual feedback |
| 🚦 Rate Limiting | Protection against spam and API abuse |
| Layer | Technology | Purpose |
|---|---|---|
| Backend | Node.js + Express |
Server and routing |
| Language | TypeScript |
Static typing and compile-time safety |
| Frontend | EJS |
View engine / templates |
| Database | MongoDB + Mongoose |
Data persistence |
| Validation | Zod |
Schema and input validation |
| Security | Express Rate Limit |
Spam and abuse protection |
| Infra | Docker + Docker Compose |
Application containerization |
| CI/CD | GitHub Actions |
Automated build and deploy pipeline |
| Code Quality | ESLint + Prettier + EditorConfig |
Consistent formatting across the codebase |
NODEShort/
├── .github/
│ └── workflows/
│ └── deploy.yml # GitHub Actions CI/CD pipeline
├── public/ # Static assets (CSS, images, JS)
├── views/
│ └── index.ejs # Main EJS template
├── src/
│ ├── controllers/ # Route handler logic
│ ├── middleware/ # Rate limiting and request guards
│ ├── models/ # Mongoose schema definitions
│ ├── routes/ # Express route declarations
│ └── server.ts # Application entry point
├── dist/ # Compiled TypeScript output (generated by build)
├── .env.example # Environment variable reference template
├── .editorconfig # Editor formatting rules (indent, charset, EOL)
├── eslint.config.js # ESLint rules and parser config (with typescript-eslint)
├── .prettierrc # Prettier formatting preferences
├── tsconfig.json # TypeScript compiler configuration
├── docker-compose.yml # Multi-container orchestration config
├── Dockerfile # Production image build instructions
└── package.json
The system accepts an optional customUrl parameter:
- Without custom URL — the server generates a unique random ID (e.g.
abc123) - With custom URL — checks availability in the database; if free, the link adopts that slug
- Auto-cleanup — the backend strips whitespace and Zod validates the format to ensure compatibility
{
originalUrl: string, // Destination link (long URL)
shortId: string, // Random code or custom slug
clicks: number, // Access counter (default: 0)
createdAt: Date // Auto-generated creation timestamp
}The schema is defined with Mongoose and the corresponding TypeScript type is automatically inferred via InferSchemaType, keeping a single source of truth between the database schema and the application's typings.
The project uses GitHub Actions to automate build and deploy on every push to master.
Push to master
│
▼
TypeScript build (tsc) + Docker image build
│
▼
Push to Docker Hub
│
▼
SSH into VPS → pull new image → recreate container
| Secret | Description |
|---|---|
DOCKERHUB_USERNAME |
Docker Hub username |
DOCKERHUB_TOKEN |
Docker Hub access token |
SSH_HOST |
VPS public IP |
SSH_USER |
SSH user |
SSH_KEY |
Full private SSH key |
Add them under Settings → Secrets and variables → Actions.
git clone https://github.com/Geovanni-dev/gr-nodeshort
cd encurtador-urlEdit .env.example and fill in your MongoDB DATABASE_URL.
docker compose up -d --buildnpm install
npm run build
npm startFor development with automatic reload:
npm run devHosted on a Linux VPS with fully automated deploys via GitHub Actions. Every push to master compiles the TypeScript source, rebuilds the image, pushes it to Docker Hub, and updates the running container on the server with zero manual steps.
- ✅ End-to-end static typing with TypeScript
- ✅ Containerized infrastructure with Docker
- ✅ CI/CD pipeline with GitHub Actions
- ✅ Custom domain and subdomain (
ns.grdev.app.br)
MIT © Geovani Rodrigues
