Add e2e/ package, Playwright commands, Gitea CI pipeline, changelog route, memory storage backend, client hooks/utils folders, and correct context filenames.
6.2 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Project Overview
Luncher is a lunch management app for teams — daily restaurant menus, food ordering, pizza day events, and payment QR codes. Czech-language UI. Full-stack TypeScript monorepo.
Monorepo Structure
types/ → Shared OpenAPI-generated TypeScript types (source of truth: types/api.yml)
server/ → Express 5 backend (Node.js 22, ts-node)
client/ → React 19 frontend (Vite 7, React Bootstrap)
e2e/ → Playwright E2E tests (separate package)
Each of the four directories has its own package.json. Package manager: Yarn Classic.
Deployment files at repo root: Dockerfile, Dockerfile-Woodpecker, compose.yml, compose-traefik.yml.
Development Commands
Initial setup
cd types && yarn install && yarn openapi-ts # Generate API types first
cd ../server && yarn install
cd ../client && yarn install
cd ../e2e && yarn install
Running dev environment
# All-in-one (tmux):
./run_dev.sh
# Or manually in separate terminals:
cd server && NODE_ENV=development yarn startReload # Port 3001, nodemon watch
cd client && yarn start # Port 3000, proxies /api → 3001
Building
cd types && yarn openapi-ts # Regenerate types from api.yml
cd server && yarn build # tsc → server/dist
cd client && yarn build # tsc --noEmit + vite build → client/dist
Tests
# Server unit tests (Jest)
cd server && yarn test # All tests in server/src/tests/
cd server && yarn test dates # Run one file by name
cd server && yarn test -t "name" # Run by test name pattern
# E2E (Playwright) — requires prebuilt server
cd server && yarn build
cd e2e && yarn test # chromium + firefox, baseURL 127.0.0.1:3001
cd e2e && yarn test:ui # interactive UI mode
cd e2e && yarn report # open last HTML report
Jest setup (server/src/tests/setupEnv.ts) forces STORAGE=memory, deletes MOCK_DATA, and sets a fixed JWT_SECRET. Playwright auto-starts the prebuilt server and authenticates via the remote-user: e2e-user trusted-header path; locally uses STORAGE=json + MOCK_DATA=true, CI uses STORAGE=redis.
CI pipeline
Gitea Actions — .gitea/workflows/ci.yaml (no .github/ equivalent):
generate-types— runsyarn openapi-ts, uploads artifactserver-test— Jestserver-build+client-build— parallel tsc/vite buildse2e— Playwright inmcr.microsoft.com/playwright:v1.59.1-jammywith a Redis service container; only Firefox installed in CIdocker-build— master branch only, usesDockerfile-Woodpeckernotify— Discord + ntfy webhooks
Formatting
Prettier is installed in client/ (devDependency only, no script or config) — invoke via yarn prettier <path> with defaults.
Architecture
API Types (types/)
- OpenAPI 3.0 spec in
types/api.yml— all API endpoints and DTOs defined here api.ymlis a thin aggregator — actual endpoint specs live intypes/paths/<domain>/*.yml, shared schemas intypes/schemas/_index.ymlyarn openapi-tsgeneratestypes/gen/(client.gen.ts, sdk.gen.ts, types.gen.ts)- Both server and client import from these generated types
- When changing API contracts: update api.yml first, then regenerate
Server (server/src/)
- Entry:
index.ts— Express app + Socket.io setup - Routes:
routes/— 9 modular Express route handlers (food, pizzaDay, voting, notifications, qr, stats, easterEgg, dev, changelog) - Services: domain logic files at root level (
service.ts,pizza.ts,restaurants.ts,chefie.ts,voting.ts,stats.ts,qr.ts,notifikace.ts) - Helpers:
mock.ts(fake menu data forMOCK_DATA=true),pushReminder.ts(push notification reminders),utils.ts(shared utilities) - Auth:
auth.ts— JWT + optional trusted-header authentication - Storage:
storage/index.tsfactory selects implementation; backends:json.ts(file-based, dev),redis.ts(production),memory.ts(tests). Data keyed by date (YYYY-MM-DD). - Restaurant scrapers: Cheerio-based HTML parsing for daily menus from multiple restaurants
- Pizza Chefie integration:
chefie.tsscrapes pizzachefie.cz for Pizza day menus and salads (only active when a Pizza day is open) - WebSocket:
websocket.ts— Socket.io for real-time client updates - Mock mode:
MOCK_DATA=trueenv var returns fake menus (useful for weekend/holiday dev) - Config:
.env.development/.env.production(see.env.templatefor all options)
Client (client/src/)
- Entry:
index.tsx→App.tsx→AppRoutes.tsx;Login.tsxis the auth screen;FallingLeaves.tsxis a seasonal visual effect - Pages:
pages/(StatsPage) - Components:
components/(Header, Footer, Loader, PizzaOrderList, PizzaOrderRow, and modals incomponents/modals/) - Context providers:
context/—auth.tsx,settings.tsx,socket.js,eggs.tsx(note:socket.jsis the only non-TSX context file) - Hooks:
hooks/(usePushReminder.ts) - Utils:
utils/(parsePrice.ts) - Styling: Bootstrap 5 + React Bootstrap + custom SCSS files (co-located with components)
- API calls: use OpenAPI-generated SDK from
types/gen/ - Routing: React Router DOM v7
Data Flow
- Client calls API via generated SDK → Express routes
- Server scrapes restaurant websites or returns cached data
- Storage: Redis (production) or JSON file (development)
- Socket.io broadcasts changes to all connected clients
Environment
- Server env files:
server/.env.development,server/.env.production(seeserver/.env.template) - Key vars:
JWT_SECRET,STORAGE(json/redis/memory),MOCK_DATA,REDIS_HOST,REDIS_PORT - Docker: multi-stage Dockerfile,
compose.ymlfor app + Redis. Timezone: Europe/Prague.
Conventions
- Czech naming for domain variables and UI strings; English for infrastructure code
- TypeScript strict mode in both client and server
- Server module resolution: Node16; Client: ESNext/bundler
TODO.mdtracks open bugs and roadmap items — worth scanning before starting non-trivial work