A simple URL shortening application that lets users create short links from long URLs.
This is a Link Shortener app that allows registered users to:
- Sign in using their Google, Microsoft, or Facebook accounts
- Create shortened versions of long URLs
- Share their short links easily
- Track basic statistics on their shortened links
- Manage their URLs through a personal dashboard
Implemented or largely implemented:
- OAuth login flow with Google
- User URL management (create/list/update/delete)
- Redirect flow and backend API contract generation
- Development and production build/deploy tooling
Still pending for MVP completion:
- Microsoft OAuth login integration
- Facebook OAuth login integration
- Permanent storage for invalidated JWT blacklist entries
- Basic statistical tracking for shortened URLs
This project is developed using GitHub Copilot. A key objective of this project is to gain valuable experience with heavily using GitHub Copilot as an AI coding assistant, exploring its capabilities for accelerating development workflows and improving code quality.
make buildThis runs go generate ./... first (regenerating the SQL scripts in sql/) and then compiles the server binary to bin/server.
To regenerate SQL scripts without building:
make generateUse this workflow whenever backend endpoint request/response schemas change.
- Update backend handlers, viewmodels, and Huma route registrations.
- Regenerate the OpenAPI spec from backend routes:
make generate-spec
- Regenerate the typed frontend API client from the OpenAPI file:
cd frontend && npm run generate:api
- Validate that the generated client compiles with the frontend:
cd frontend && npm run build
The generated client is written into frontend/src/lib/api/ and should be committed together with backend API changes.
The project runs as a split local environment:
- PostgreSQL is hosted in Docker via
docker compose. - Backend runs with live reload using Air.
- Frontend runs with Vite dev server.
Useful commands from the Makefile:
- Start only PostgreSQL in Docker:
make run-pg-dev - Start backend only:
make run-backend-dev - Start frontend only:
make run-frontend-dev - Start full local environment:
make run-dev - Stop full local environment:
make stop-dev - Stop services individually:
make stop-pg-dev,make stop-backend-dev,make stop-frontend-dev
For production deployment, the repository builds and ships these artifacts:
- Backend executable:
bin/server- Built by
make build-backend-prod(linux/amd64, with stripped symbols).
- Built by
- Frontend static bundle:
frontend/dist/- Built by
make build-frontend-prod APP_BASE_URL=https://yourdomain.com.
- Built by
- Full production bundle: both of the above via
make build-prod APP_BASE_URL=https://yourdomain.com. - Database migration SQL scripts in
sql/- Regenerated by
make build(viamake generate) and used for production schema rollout.
- Regenerated by
The make deploy target builds production artifacts, syncs bin/server and frontend/dist/ to the server, and restarts the systemd service.
This project uses Semantic Versioning (MAJOR.MINOR.PATCH) stored in the root version file.
- Policy:
MAJOR: breaking changesMINOR: backward-compatible feature additionsPATCH: backward-compatible fixes
- Mechanism:
- The current version is embedded into backend builds via Go linker flags.
- Release tags are created as
vX.Y.Z.
- Command:
make bump BUMP=patch(orminor,major)
make bump updates the version file, creates a commit, and creates the corresponding git tag.
In dev mode (LINKSHORTENER_ENV=dev) the server applies any pending migrations automatically on startup. No manual action is required during day-to-day development.
In prod mode (LINKSHORTENER_ENV=prod) the server never modifies the database schema automatically. Ready-to-run SQL scripts are generated into the sql/ directory as part of every build.
Two types of script are generated:
| File | Purpose |
|---|---|
sql/schema.sql |
All migrations in order — use to initialise a brand-new database |
sql/<name>.sql |
Individual migration — apply only the incremental change |
Recommended workflow for a schema change:
- Add a new migration file in
backend/infrastructure/pg/migrations/. - Run
make build(ormake generate) — the updated SQL scripts are written tosql/. - Review the generated
sql/<new_migration>.sqlto confirm the DDL. - Apply the script against the production database before deploying the new server binary:
psql "$DATABASE_URL" -f sql/<new_migration>.sql
- Deploy and start the new server binary.
To initialise a brand-new production database from scratch:
psql "$DATABASE_URL" -f sql/schema.sqlSecurity note:
sql/contains no secrets. The scripts are safe to commit to version control and review in pull requests.
See Deploy.md for the full step-by-step guide covering one-time server setup and repeatable deployments.
MIT License - See LICENSE file for details