{"id":27867911,"url":"https://github.com/jjteoh-thewebdev/url-shortener","last_synced_at":"2026-01-21T09:02:40.590Z","repository":{"id":284075689,"uuid":"953741941","full_name":"jjteoh-thewebdev/url-shortener","owner":"jjteoh-thewebdev","description":"A URL shortener. Next.js for frontend, Express \u0026 Fastify for backend","archived":false,"fork":false,"pushed_at":"2025-03-28T09:51:14.000Z","size":687,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-05-04T22:55:26.695Z","etag":null,"topics":["devcontainer","docker","expressjs","fastify","mikroorm","nextjs","playwright","postgresql","prisma","redis","tailwindcss"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jjteoh-thewebdev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-03-24T02:10:09.000Z","updated_at":"2025-04-03T15:49:43.000Z","dependencies_parsed_at":"2025-03-24T03:23:05.358Z","dependency_job_id":"8dd5b9c9-233a-4769-b9c5-600886478e17","html_url":"https://github.com/jjteoh-thewebdev/url-shortener","commit_stats":null,"previous_names":["jjteoh-thewebdev/url-shortener"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/jjteoh-thewebdev/url-shortener","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jjteoh-thewebdev%2Furl-shortener","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jjteoh-thewebdev%2Furl-shortener/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jjteoh-thewebdev%2Furl-shortener/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jjteoh-thewebdev%2Furl-shortener/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jjteoh-thewebdev","download_url":"https://codeload.github.com/jjteoh-thewebdev/url-shortener/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jjteoh-thewebdev%2Furl-shortener/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28630938,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-21T04:47:28.174Z","status":"ssl_error","status_checked_at":"2026-01-21T04:47:22.943Z","response_time":86,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["devcontainer","docker","expressjs","fastify","mikroorm","nextjs","playwright","postgresql","prisma","redis","tailwindcss"],"created_at":"2025-05-04T22:55:25.981Z","updated_at":"2026-01-21T09:02:40.580Z","avatar_url":"https://github.com/jjteoh-thewebdev.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# URL Shortener\r\n\r\n\u003cdiv align=\"center\"\u003e\r\n    \u003cimg src=\"media/landing-page-1.png\" /\u003e\r\n\u003c/div\u003e\r\n\r\nA modern, scalable URL shortener application built with:\r\n- Frontend app: Next.js + TailwindCSS + Playwright \r\n- Backend management: Express.js + Prisma(Postgres)\r\n- Backend redirector: Fastify.js + MikroORM\r\n\r\n**Normally you will not need to have 2 different techstacks for the backend services. I did this because I want to explore different tech stack.**\r\n\r\nAll services are built with Typescript. This project implements a microservices architecture with separate services for URL management, redirection, and frontend.\r\n\r\n\r\n\r\n## Project Background\r\n\r\nThis is a POC for implementing URL shortener application that is designed to provide a robust and scalable solution for shortening URLs with features like password protection, custom aliases(urls), and little analytics capability. For detailed information about the project's architecture, design decisions, and technical specifications, please refer to [PROJECT.md](PROJECT.md).\r\n\r\n## Features\r\n\r\n- 🔗 URL shortening with custom aliases\r\n- 🔒 Password protection for URLs\r\n- 📊 URL analytics and statistics\r\n- 🚀 High-performance redirection with Redis caching\r\n- 🧪 Comprehensive test coverage\r\n- 🐳 Docker support\r\n- 🔄 URL expiration management\r\n\r\n## Folder Organization\r\n\r\n### backend-management\r\nThe management service handles URL creation and management. It provides RESTful APIs for:\r\n- Creating shortened URLs\r\n\r\n[View backend-management README](backend-management/README.md)\r\n\r\n### backend-redirector\r\nThe redirection service handles the actual URL redirection with Redis caching for high performance. It provides:\r\n- Fast URL redirection\r\n- Password verification\r\n- Redis caching\r\n- Analytics tracking\r\n\r\n[View backend-redirector README](backend-redirector/README.md)\r\n\r\n### frontend\r\nA modern Next.js application that provides the user interface for the URL shortener. Features include:\r\n- Modern UI with Tailwind CSS, shadcn/ui, Lucide Icons\r\n- Responsive design\r\n- Password protection UI\r\n- Playwright test framework\r\n\r\n[View frontend README](frontend/README.md)\r\n\r\n## Setup Database\r\n\r\n1. Create PostgreSQL database for backend services:\r\n   ```sql\r\n   CREATE DATABASE url_shortener;\r\n   ```\r\n\r\n2. Create `.env` file in `backend-management`:\r\n   ```bash\r\n   # backend-management/.env\r\n   DATABASE_URL=\"postgresql://user:password@localhost:5432/url_shortener\r\n   ```\r\n\r\n3. Run migrations:\r\n\r\n   **Note: for ease of maitenance, only do migration in backend-management with Prisma. Do not run migrations with MikroORM in backend-redirector**\r\n   ```bash\r\n   # In backend-management directory\r\n   npm run migrate:dev\r\n   ```\r\n\r\n## Running with Docker Compose\r\n\r\n1. Create a `.docker.env` file in the each project root:\r\n   ```bash\r\n   cp sample.env .docker.env\r\n   ```\r\n\r\n2. Start all services:\r\n   ```bash\r\n   docker-compose up -d\r\n   ```\r\n\r\n3. Access the services:\r\n   - Frontend: http://localhost:3000\r\n   - Management API: http://localhost:3001\r\n   - Redirector API: http://localhost:3002\r\n\r\n4. Stop all services:\r\n   ```bash\r\n   docker-compose down\r\n   ```\r\n\r\n## Project Gallery\r\n\r\n### Landing Page Design\r\n![URL Shortening Interface](media/landing-page-1.png)\r\n\r\n### Validation with ZOD\r\n![Validation with ZOD](media/landing-page-2.png)\r\n\r\n### Result Page\r\n![Result Page](media/result-page-1.png)\r\n\r\n### E2E Testing with Playwright\r\n![E2E Testing with Playwright](media/playwright-report.png)\r\n\r\n\r\n## Development\r\n\r\n### Prerequisites\r\n- Node.js 20.x or later\r\n- PostgreSQL\r\n- Redis\r\n- Docker and Docker Compose\r\n- npm\r\n\r\n### Local Development\r\n\r\n1. Clone the repository:\r\n   ```bash\r\n   git clone https://github.com/yourusername/url-shortener.git\r\n   cd url-shortener\r\n   ```\r\n\r\n2. Set up environment variables in `frontend`, `backend-management` and `backend-redirector`:\r\n   ```bash\r\n   cp sample.env .env\r\n   ```\r\n\r\n3. Install dependencies:\r\n   ```bash\r\n   # Install dependencies for all services\r\n   npm install\r\n   cd frontend \u0026\u0026 npm install\r\n   cd ../backend-management \u0026\u0026 npm install\r\n   cd ../backend-redirector \u0026\u0026 npm install\r\n   ```\r\n\r\n4. Start the development servers:\r\n   ```bash\r\n   # Start frontend\r\n   cd frontend \u0026\u0026 npm run dev\r\n\r\n   # Start management service\r\n   cd backend-management \u0026\u0026 npm run dev\r\n\r\n   # Start redirector service\r\n   cd backend-redirector \u0026\u0026 npm run dev\r\n   ```\r\n\r\n## Roadmap\r\n\r\n1. setup observability stack\r\n2. setup everything in kubernetes\r\n\r\n\r\n\r\n## Contributing\r\n\r\n1. Fork the repository\r\n2. Create a feature branch\r\n3. Make your changes\r\n4. Run tests\r\n5. Submit a pull request\r\n\r\n## License\r\n\r\nThis project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjjteoh-thewebdev%2Furl-shortener","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjjteoh-thewebdev%2Furl-shortener","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjjteoh-thewebdev%2Furl-shortener/lists"}