Clone the repo, configure environment files, run frontend and backend in two terminals, and use the shared formatters before you commit.
Also useful
- Product overview:
docs/project-overview.md - CI/CD, deploy targets, GitHub secrets:
docs/ci-cd-pipelines.md - Docker log paths and rotation:
docs/logging-docker.md - Backend API keys and OAuth details:
backend/README.md
| Path | Role |
|---|---|
frontend/ |
React + TypeScript + Vite |
backend/ |
Java 23 + Spring Boot (Docker Compose for local API) |
scripts/terminal/ |
Frontend dev splash (print.mjs, ascii-art.txt) |
backend/scripts/ |
start.ps1 / start.sh Docker helpers |
.githooks/ |
Pre-commit formatting |
scripts/setup-git-hooks.sh |
One-time hook install |
docs/ |
Architecture, CI/CD, logging |
.github/workflows/ |
GitHub Actions |
| Tool | Version |
|---|---|
| Node.js | 22+ |
| npm | bundled with Node |
| Java | 23+ |
| Docker Desktop | recommended (Postgres + backend container) |
| Git | clone and hooks |
Maven globally is optional — use backend/mvnw (or mvnw.cmd on Windows).
Terminal 1 — backend (Spring Boot in Docker; custom banner on startup):
cd backend
npm ci # only if you use backend/package.json scripts
npm run devTerminal 2 — frontend (terminal splash, then Vite):
cd frontend
npm ci
npm run dev| Service | URL |
|---|---|
| Frontend | http://localhost:5173 |
| Backend API | http://localhost:8080 |
| Health | http://localhost:8080/actuator/health |
Stop backend stack: cd backend && npm run stop or docker compose down.
git clone https://github.com/misterdrac/UniVoyage
cd UniVoyageGit Bash / WSL:
./scripts/setup-git-hooks.shPowerShell:
git config core.hooksPath .githooksThe pre-commit hook runs the backend Maven formatter and frontend Prettier, then re-stages only files already in the index (git diff --cached --name-only). Stage only what belongs in that commit.
cd backend
cp env.example .envPowerShell: Copy-Item env.example .env
Minimum for local Docker:
DB_PASSWORD=your_db_password
POSTGRES_PASSWORD=your_db_password
JWT_SECRET=your-long-random-secretGenerate a strong JWT secret: openssl rand -base64 32
See backend/env.example for OAuth, email (Resend/Postmark), trip APIs, cookies, and POSTGRES_HOST_PORT (often 5433 on Windows if 5432 is taken).
OAuth (browser testing) — set client ID/secret in backend/.env and register the same redirect in each provider console:
http://localhost:5173/auth/google/callback
http://localhost:5173/auth/github/callback
http://localhost:5173/auth/linkedin/callback
OAuth and AI keys live in backend/.env, not in Vite env vars.
Email OTP / password reset / verify — configure EMAIL_PROVIDER, RESEND_API_KEY (or another provider from env.example), plus APP_FRONTEND_RESET_URL and APP_FRONTEND_VERIFY_URL pointing at localhost routes.
cd frontend
npm ciFor most daily dev, npm run dev without .env is enough — Vite proxies /api to http://127.0.0.1:8080.
Optional explicit API base (copy from frontend/env.example):
VITE_API_URL=http://localhost:8080/apiLocal API runs in Docker (univoyage_backend), not as a bare java -jar on the host.
| Command | What it does |
|---|---|
npm run dev |
docker compose up --build — follow logs; Spring banner on container start |
npm start |
Detached up, then logs -f backend |
npm run start:detached |
docker compose up --build -d only |
npm run logs |
Tail backend logs (banner only after restart/rebuild) |
npm run stop |
docker compose down |
npm run ps |
docker compose ps |
Shell wrappers (same stack, no npm):
cd backend
.\scripts\start.ps1 -Detachedcd backend
./scripts/start.sh -dPlain Compose:
cd backend
docker compose up --build -d
docker compose psAfter changing banner.txt, rebuild: npm run dev or docker compose up --build.
Custom startup art replaces the default Spring logo:
- File:
backend/src/main/resources/banner.txt - Enabled in:
application.yml,application-docker.yml(SPRING_PROFILES_ACTIVE=docker),application-prod.yml(prod) - Prints UniVoyage ASCII, then API version, Spring Boot, Java, and active profile
Keep frontend terminal art in sync: scripts/terminal/ascii-art.txt (lines starting with # are comments and skipped by the frontend splash).
Point backend/.env at your Postgres host/port, then:
cd backend
npm run run:localWindows: npm run run:local:win or .\mvnw.cmd spring-boot:run
Same banner.txt appears in the IDE Run console if you start UniVoyageApplication from your editor.
cd frontend
npm run devRuns scripts/terminal/print.mjs (frontend profile — cyan panel with URLs and proxy hint), then Vite.
- App: http://localhost:5173
- API calls use
/api→ Vite dev proxy → backend:8080
Edit ASCII in scripts/terminal/ascii-art.txt; edit backend startup art in banner.txt.
- API base path:
/api(seefrontend/src/config/apiConfig.ts) - CORS:
backend/src/main/java/com/univoyage/config/CorsFilterConfig.java - Local origins typically include
http://localhost:5173andhttp://127.0.0.1:5173
OAuth uses a full-page redirect (no popup); callback routes live under /auth/{provider}/callback.
After hooks are installed, every commit runs:
- Backend:
./mvnw formatter:formatinbackend/ - Frontend:
npx prettier --write "src/**/*.{js,jsx,ts,tsx,css,scss,md,json}"infrontend/
Backend
cd backend
./mvnw formatter:format
./mvnw formatter:validateWindows: .\mvnw.cmd instead of ./mvnw.
Frontend
cd frontend
npx prettier --write "src/**/*.{js,jsx,ts,tsx,css,scss,md,json}"
npm run lint| Check | Expected |
|---|---|
| Frontend home | http://localhost:5173 loads |
| Backend health | http://localhost:8080/actuator/health → "status":"UP" |
| Network tab | /api/... without CORS errors |
| Login | http://localhost:5173/?login=1 |
If health fails: docker compose ps in backend/, verify .env passwords match Postgres, and port POSTGRES_HOST_PORT (5433 vs 5432).
Frontend (cd frontend):
npm run test:run # all Vitest tests
npm run test:auth-matrix # OAuth / reset / verify / OTP matrix
npm run test:e2e # OAuth callback E2E smoke
npm run build # production build (run before push)Backend:
cd backend
./mvnw clean test
./mvnw -q test "-Dtest=AuthIdentitiesControllerIntegrationTest"Auth QA checklist: frontend/docs/AUTH_REGRESSION_CHECKLIST.md
| URL | Purpose |
|---|---|
| http://localhost:5173 | Frontend |
| http://localhost:5173/?login=1 | Open sign-in |
| http://localhost:5173/profile | Profile / sign-in methods |
| http://localhost:5173/admin | Admin login + 2FA |
| http://localhost:5173/auth/reset-password | Password reset |
| http://localhost:5173/auth/verify-email | Email verification |
| http://localhost:8080/actuator/health | Backend health |
| Problem | Fix |
|---|---|
ECONNREFUSED 127.0.0.1:8080 |
Backend not up — cd backend && docker compose ps; container must be Up |
| Backend Restarting, Flyway checksum mismatch | Stale DB vs migrations — dev reset: docker compose down -v && docker compose up --build |
OAuth redirect_uri_mismatch |
Provider console URI must match http://localhost:5173/auth/{provider}/callback exactly |
| OTP / reset email missing | Set EMAIL_* in backend/.env; check docker compose logs backend |
| Postgres connection refused | Start Compose; check POSTGRES_HOST_PORT in .env |
| Pre-commit fails on deleted file | git add -u for removals; hook only re-stages cached paths |
Vitest user-event missing |
cd frontend && npm ci |
- Default branch:
master - Feature-branch pushes run fast feedback workflows; PRs add stricter checks
- Full master pipeline and release/deploy:
docs/ci-cd-pipelines.md - Deploy: backend Railway (
SPRING_PROFILES_ACTIVE=prod), frontend Vercel
# Frontend
cd frontend && npm run dev && npm run build && npm run lint && npm run test:run
# Backend (Docker)
cd backend && npm run dev && npm run logs && npm run stop
# Backend (format / test)
cd backend && ./mvnw formatter:format && ./mvnw clean test