Library management system built with Spring Boot, Next.js, and PostgreSQL.
bookstudio/
βββ apps/
β βββ api/ REST API β Spring Boot 4, Java 17, Maven
β βββ web/ Frontend β Next.js 16, TypeScript, Tailwind CSS, pnpm
βββ database/ SQL scripts (schema, functions, triggers, data)
βββ package.json Root orchestration (concurrently)
βββ docker-compose.yml Base services (postgres + api)
βββ docker-compose.override.yml Dev β web with next dev + hot reload (auto-loaded)
βββ docker-compose.prod.yml Prod β web with next build
| Layer | Technology |
|---|---|
| API | Spring Boot 4, Java 17, Spring Data JPA, Maven |
| Database | PostgreSQL 18 |
| Frontend | Next.js 16.1, TypeScript, Tailwind CSS v4, shadcn/ui |
| File storage | Configured in system as needed |
- Docker Compose v2 to run everything together
- For local dev without Docker: Java 17 JDK, Maven or
./mvnw, Node.js 20+, pnpm
# 1. Clone the repository
git clone <repo-url> bookstudio && cd bookstudio
# 2. Create the environment file
cp .env.example .env
# Edit .env β at minimum: DB_PASSWORD
# 3. Start all services
pnpm docker:up # dev mode β web runs with next dev + hot reload (default)
pnpm docker:up:prod # prod mode β web built with next build| Service | URL |
|---|---|
| PostgreSQL | localhost:5432 |
| API | http://localhost:8080 |
| Web | http://localhost:3000 |
| Swagger UI | http://localhost:8080/swagger-ui.html |
Ports are configurable in .env via DB_PORT, API_PORT, WEB_PORT.
Note: Scripts in
database/run automatically the first time the PostgreSQL volume is created. To reset the database from scratch:pnpm docker:down -- -v && pnpm docker:up.Port conflicts: If any default port is already in use, override it in
.envβ e.g.DB_PORT=5433,API_PORT=8081,WEB_PORT=3001. Internal container communication is unaffected.
psql -U postgres -c "CREATE DATABASE bookstudio;"
psql -U postgres -d bookstudio -f database/01-schema.sql
psql -U postgres -d bookstudio -f database/02-functions.sql
psql -U postgres -d bookstudio -f database/03-triggers.sql
psql -U postgres -d bookstudio -f database/04-data.sqlpnpm install # first time only β installs concurrently
pnpm dev # starts API + Web in parallelOr run each one separately:
pnpm dev:api # only API (Spring Boot)
pnpm dev:web # only Web (Next.js)Tip: If you use the Spring Boot extension in VS Code, the API starts automatically from the editor. In that case, just run
pnpm dev:web.
| Script | Description |
|---|---|
pnpm dev |
Start API + Web in parallel |
pnpm dev:api |
Start API only |
pnpm dev:web |
Start Web only |
pnpm web:build |
Production build (Next.js) |
pnpm web:lint |
Run ESLint |
pnpm web:lint:fix |
Run ESLint with auto-fix |
pnpm web:format |
Format with Prettier |
pnpm docker:up |
Start all services β dev mode (next dev, hot reload) |
pnpm docker:down |
Stop dev Docker services |
pnpm docker:up:prod |
Start all services β prod mode (next build) |
pnpm docker:down:prod |
Stop prod Docker services |
cd apps/api
# Set up local properties
cp src/main/resources/application-local.properties.example \
src/main/resources/application-local.properties
# Fill in your DB credentials, etc.
./mvnw spring-boot:run
# API available at http://localhost:8080
# Swagger UI at http://localhost:8080/swagger-ui.htmlcd apps/web
pnpm install
cp .env.example .env.local
# Edit .env.local
pnpm dev
# App available at http://localhost:3000Configuration depends on how you run the project:
| Approach | Config file |
|---|---|
| Docker Compose | .env (copy from .env.example) |
| Web standalone | apps/web/.env.local (copy from apps/web/.env.example) |
| API standalone | apps/api/src/main/resources/application-local.properties (copy from .example) |
The root .env.example is only for Docker Compose β if you deploy each service independently (e.g. via Coolify using the individual Dockerfiles), use the per-service config files instead.
| Variable | Service | Description |
|---|---|---|
DB_USERNAME |
postgres, api | Database user |
DB_PASSWORD |
postgres, api | Database password |
DB_PORT |
postgres | Host port for the DB container (default 5432) |
API_PORT |
api | Host port for the API container (default 8080) |
WEB_PORT |
web | Host port for the Web container (default 3000) |
