An e-commerce bakery platform where customers can browse and order baked goods online, earn loyalty rewards, and leave product reviews. Built as a full-stack monorepo with a SvelteKit frontend and a Spring Boot backend, deployed on DigitalOcean.
- Overview
- Tech Stack
- Repository Structure
- Prerequisites
- Getting Started
- Development Workflow
- Deployment
- Environment Variables
- Useful Commands
Peelin' Good is a bakery e-commerce platform that supports:
- π Online ordering β customers browse products, place pickup or delivery orders from bakery locations
- π·οΈ Product tagging & filtering β products are organized with tags (breads, cakes, seasonal, dietary attributes, etc.)
- π€ Customer accounts β registration, login, order history, and personalized preferences
- β Reviews & ratings β customers review purchased products, moderated by employees
- π Loyalty rewards β tiered reward system (Bronze, Silver, Gold) with points earned on orders
- π¦ Inventory & batch tracking β ingredient stock per bakery, supplier management, batch production records
- π©βπ³ Employee management β employees linked to bakeries, responsible for batch preparation and content moderation
The monorepo contains two independently deployable applications:
| App | Path | Description |
|---|---|---|
| Backend | apps/backend |
REST API built with Spring Boot 3.5, Java 21, PostgreSQL, and Flyway migrations |
| Frontend | apps/frontend |
Web client built with SvelteKit 2, Svelte 5, TypeScript, and Tailwind CSS 4 |
Both apps are containerized with multi-stage Dockerfiles and deployed to DigitalOcean App Platform via GitHub Actions.
| Document | Description |
|---|---|
| Backend Guide | Setup, architecture, migrations, testing, and Docker for the Spring Boot API |
| Frontend Guide | Setup, routing, styling, components, linting, and Docker for the SvelteKit client |
| Contributing Guide | Branching strategy, PR workflow, CI/CD checks, CodeScene, and merge process |
| Database Design | Full entity/relationship breakdown and problem statement |
| ERD Diagram | Visual entity-relationship diagram |
| Postman collection | Importable requests for the current REST API surface |
- Language: Java 21
- Framework: Spring Boot 3.5.11
- Database: PostgreSQL
- Migrations: Flyway
- Security: Spring Security
- AI: Spring AI (OpenAI-compatible client; used with OpenRouter for recommendations and related features)
- Build Tool: Maven (wrapper included β no global install needed)
- Runtime Image: Distroless Java 21
- API docs: OpenAPI / Swagger UI (
/swagger-ui/index.htmlwhen the server is running)
- Language: TypeScript
- Framework: SvelteKit 2 (Svelte 5) with
adapter-node - Styling: Tailwind CSS 4 with
tw-animate-css,tailwind-variants, andtailwind-merge - UI Components: shadcn-svelte conventions (
$lib/components/ui,$lib/utils.ts) - Icons: Lucide Svelte
- Linting: ESLint 9 + Prettier
- Runtime: Node.js 22
- Hosting: DigitalOcean App Platform
- Container Registry: GitHub Container Registry (
ghcr.io) - CI/CD: GitHub Actions
- Code Analysis: CodeScene Delta Analysis (on PRs)
.
βββ .github/
β βββ workflows/
β βββ backend-build.yml # Backend CI: build, test, Docker, deploy
β βββ frontend-build.yml # Frontend CI: lint, check, build, Docker, deploy
βββ apps/
β βββ backend/ # Spring Boot API
β β βββ src/
β β β βββ main/
β β β β βββ java/com/sait/peelin/ # Application source code
β β β β βββ resources/
β β β β βββ application.yaml # Spring config
β β β β βββ db/migration/ # Flyway SQL migrations
β β β βββ test/ # Test source code
β β βββ Dockerfile
β β βββ pom.xml
β β βββ mvnw / mvnw.cmd # Maven wrapper (no install needed)
β β βββ HELP.md
β βββ frontend/ # SvelteKit web client
β βββ src/
β β βββ lib/
β β β βββ assets/ # Static assets (favicon, etc.)
β β β βββ components/ui/ # Reusable UI components
β β β βββ hooks/ # Custom Svelte hooks
β β β βββ utils.ts # Utility helpers (cn, types)
β β β βββ index.ts # Barrel exports
β β βββ routes/ # SvelteKit file-based routing
β βββ Dockerfile
β βββ package.json
β βββ svelte.config.js
β βββ vite.config.ts
β βββ tsconfig.json
β βββ eslint.config.js
βββ docs/
β βββ backend.md # Backend setup, architecture, and development guide
β βββ frontend.md # Frontend setup, routing, styling, and development guide
β βββ contributing.md # Branching, PR workflow, CI/CD, and merge process
β βββ database-design.md # Full entity/relationship breakdown
β βββ postman/ # Postman collection for the REST API
β βββ bakery_erd.pdf # Visual entity-relationship diagram
βββ infra/ # Infrastructure configuration
βββ scripts/ # Utility scripts
βββ README.md # β You are here
Make sure you have the following installed on your machine:
| Tool | Version | Notes |
|---|---|---|
| Java JDK | 21+ | Required for the backend. Temurin recommended |
| Node.js | 22+ | Required for the frontend. Use nvm or fnm to manage versions |
| npm | Comes with Node | Used for frontend dependency management |
| Docker | Latest | Needed to build/test container images locally |
| Git | Latest | Obviously |
| PostgreSQL | 15+ | For local backend development. Alternatively, run it via Docker |
Note: You do not need to install Maven globally. The project includes a Maven wrapper (
mvnw/mvnw.cmd) that will automatically download the correct version.
Use the following default passwords for seeded accounts by role:
- Customer:
Cust123! - Employee:
Emp123! - Admin:
Admin123!
git clone <repository-url>
cd <your-clone-folder> # the repository root: should contain apps/, docs/, and this READMEIf you are using the threaded course monorepo, that folder is often Workshop-7/Workshop7 relative to the parent project root.
cd apps/backend
# Build and run tests
./mvnw verify
# Run the application in development mode
./mvnw spring-boot:runWindows users: Use
mvnw.cmdinstead of./mvnw.
The API will start on http://localhost:8080.
You will need a running PostgreSQL instance. Configure the connection in apps/backend/src/main/resources/application.yaml or via environment variables (see Environment Variables).
Flyway will automatically run any pending migrations from src/main/resources/db/migration/ on startup.
cd apps/frontend
# Install dependencies
npm install
# Start the dev server
npm run devThe app will start on http://localhost:5173 (Vite default).
mainis the production branch and is protected.- Direct pushes to
mainare not allowed. - Merges require a pull request.
- PRs cannot be merged if there are merge conflicts β resolve them first.
- Direct pushes to
- Create a feature branch from
mainfor your work:git checkout -b feature/your-feature-name
- Push your branch and open a Pull Request against
main.
When you open a PR targeting main, the following happens automatically:
- GitHub Actions CI runs the relevant pipeline(s) based on which files changed:
- Changes in
apps/backend/**β Backend CI (./mvnw verify -DskipTests; on same-repo PRs a follow-up job runs a localdocker buildonlyβno preview URL comment) - Changes in
apps/frontend/**β Frontend CI (lint, type check, build, Docker image build; same-repo PRs can get a DigitalOcean preview deploy and a PR comment with the URL)
- Changes in
- CodeScene Delta Analysis analyzes your PR for code health, complexity trends, and potential risks.
- Frontend PRs from this repository (not forks) can receive a DigitalOcean PR preview; the workflow posts a comment with the live preview URL. Backend PRs build a Docker image in CI but do not publish a separate preview app or preview URL comment.
- Fork PRs: preview jobs that would use repository secrets are skipped for safety.
β οΈ PRs that break the build cannot be merged. The GitHub Actions workflows act as required status checks, so make sure your code passes all checks before requesting a review.
| Trigger | Steps |
|---|---|
PR to main |
Checkout β JDK 21 β ./mvnw verify -DskipTests β on same-repo PRs, pr-preview runs docker build in apps/backend only (no App Platform deploy or preview URL comment) |
Push to main |
Checkout β JDK 21 setup β ./mvnw verify -DskipTests β Docker build & push to GHCR β Deploy to DigitalOcean production |
| Trigger | Steps |
|---|---|
PR to main |
Checkout β Node 22 setup β npm ci β Lint (includes Prettier) β Type check β Build β Docker build β DigitalOcean PR preview deploy + comment with URL (same-repo PRs only) |
Push to main |
Checkout β Node 22 setup β npm ci β Lint β Type check β Build β Docker build & push to GHCR β Deploy to production |
Both pipelines are scoped by path β backend changes won't trigger the frontend pipeline and vice versa.
- CodeScene Delta Analysis runs on every PR to catch code health regressions, complexity hotspots, and coupling issues.
- Frontend linting is enforced in CI via:
- ESLint 9 with TypeScript and Svelte plugins
- Prettier with Svelte and Tailwind CSS plugins
- Frontend type checking runs
svelte-checkin CI. - Backend tests: run
./mvnw verifylocally for the full unit and integration test suite. The GitHub Actions workflow currently invokes./mvnw verify -DskipTestsso CI focuses on compilation and Docker packaging.
Before pushing, run these locally to catch issues early:
# Frontend
cd apps/frontend
npm run lint # Check linting + formatting
npm run format # Auto-fix formatting
npm run check # TypeScript / Svelte type checking
# Backend
cd apps/backend
./mvnw verify # Compile + run all testsThe application is deployed on DigitalOcean App Platform.
- Production deploys happen automatically when code is merged into
main. - Preview deploys apply to the frontend app on eligible pull requests (see workflow); backend PRs do not get a separate preview environment in CI.
- Docker images are pushed to GitHub Container Registry (
ghcr.io) on production deploys.
The deployment flow:
PR Merge β GitHub Actions β Build & Test β Docker Image β Push to GHCR β Deploy to DigitalOcean
The backend uses Spring Boot's configuration via application.yaml and environment variables. For a full, annotated list of keys (database, Valkey/Redis, Stripe, JWT, mail, OAuth, Spaces, OpenRouter, optional observability), copy apps/backend/.env.example to .env or .env.local and adjust valuesβnever commit real secrets.
At minimum for local development you typically need PostgreSQL (and Redis/Valkey if you use the dev profile defaults). Common variables:
| Variable | Description |
|---|---|
SPRING_DATASOURCE_URL |
JDBC connection string (e.g., jdbc:postgresql://localhost:5433/peelin; see intellij-local-postgres.txt) |
SPRING_DATASOURCE_USERNAME |
Database username |
SPRING_DATASOURCE_PASSWORD |
Database password |
SPRING_DATA_REDIS_URL |
Redis/Valkey URL when using the local cache profile |
JWT_SECRET |
Signing secret for issued tokens (required) |
STRIPE_* |
Stripe keys and webhook secret for payments (see example file) |
The frontend uses SvelteKit's environment variable conventions. Create a .env file in apps/frontend/:
cp .env.example .env # if an example file existsImportant: Never commit
.envfiles. They are git-ignored by default. Only.env.exampleand.env.testare allowed.
These are configured in the repository's GitHub Settings β Secrets:
| Secret | Purpose |
|---|---|
DIGITALOCEAN_ACCESS_TOKEN |
DigitalOcean API token for deployments (name must match your GitHub secret) |
GITHUB_TOKEN |
Automatically provided by GitHub for GHCR access |
| Command | Description |
|---|---|
./mvnw spring-boot:run |
Start the dev server |
./mvnw verify |
Build and run all tests |
./mvnw clean package -DskipTests |
Build JAR without tests |
docker build -t peelin-backend . |
Build Docker image locally |
| Command | Description |
|---|---|
npm run dev |
Start Vite dev server with HMR |
npm run build |
Production build |
npm run preview |
Preview the production build locally |
npm run lint |
Run ESLint + Prettier checks |
npm run format |
Auto-format code with Prettier |
npm run check |
Svelte/TypeScript type checking |
npm run check:watch |
Type checking in watch mode |
docker build -t peelin-frontend . |
Build Docker image locally |