A production-ready URL Shortener built with Node.js, Express, and SQLite. Dockerized and ready for deployment.
- Shorten URLs with validation
- Custom aliases
- Expiration dates
- Click tracking (analytics)
- Rate limiting
- SQLite database with auto-migration
- Docker support with multi-stage builds (runs tests during build)
- Node.js >= 18
- Docker & Docker Compose (optional)
-
Install Dependencies
npm install
-
Configure Environment Copy
.env.exampleto.env:cp .env.example .env # Edit .env if needed -
Run Tests
npm test -
Start Server
npm start # Or for development with nodemon: npm run dev
This will build the image (running tests inside) and start the service with a persistent SQLite volume.
docker-compose up --builddocker build -t url-shortener .POST /api/shorten
curl -X POST http://localhost:3000/api/shorten \
-H "Content-Type: application/json" \
-d '{ "longUrl": "https://www.google.com", "customAlias": "go-google", "expiresInDays": 7 }'Response:
{
"code": "go-google",
"shortUrl": "http://localhost:3000/go-google",
"longUrl": "https://www.google.com",
"expiresAt": "2023-10-27T10:00:00.000Z",
"createdAt": "2023-10-20T10:00:00.000Z"
}GET /:code
Opens the short URL in browser or redirects via curl.
curl -L -v http://localhost:3000/go-googleGET /api/info/:code
curl http://localhost:3000/api/info/go-googleResponse:
{
"longUrl": "https://www.google.com",
"createdAt": "...",
"expiresAt": "...",
"clicks": 5,
"lastAccessedAt": "..."
}GET /health
curl http://localhost:3000/healthTo deploy to AWS EC2 via GitHub Actions, configure the following GitHub Secrets:
EC2_HOST: Public IP or DNS of your EC2 instance.EC2_USERNAME: SSH username (e.g.,ubuntuorec2-user).EC2_SSH_KEY: Private SSH key content (PEM).
Workflow Overview (conceptual):
- CI: On push to
main, runnpm test. - CD:
- Log in to Docker Registry (Docker Hub or ECR).
- Build and push image:
docker build -t myuser/url-shortener . && docker push myuser/url-shortener. - SSH into EC2.
- Run
docker pull myuser/url-shortener. - Run
docker-compose up -d.
| Variable | Default | Description |
|---|---|---|
| PORT | 3000 | Server port |
| BASE_URL | http://localhost:3000 | Base URL for short links |
| DB_PATH | ./data/urls.db | Path to SQLite database file |
| APP_VERSION | dev | Application version tag |
| NODE_ENV | development | Environment (production/development) |