Initial commit: YesChef family shopping list and recipe app
Backend (.NET 10 minimal API): - Vertical slice architecture with feature folders - Postgres via EF Core with initial migration - JWT auth with family invite code registration - REST endpoints for stores, shopping lists, items, recipes - SignalR hub for real-time list collaboration (per-list groups and lists-overview group for live list creation/archival/progress) - Multi-stage Dockerfile Frontend (SvelteKit + Svelte 5 runes, Tailwind v4): - Mobile-first PWA with web manifest and service worker - Bottom-nav layout, login/register, lists overview, list detail, stores management, recipes (list/create/detail with add-to-list) - SignalR client with reference-counted connection - Real-time updates on both lists overview and list detail pages Infrastructure: - docker-compose.yml with postgres, backend, frontend services and Traefik labels for path-based routing (/api, /hubs to backend) - .env.example with required config End-to-end tests (Playwright): - test-e2e.mjs: single-user flow (auth, stores, lists, items, recipes) - test-e2e-multiuser.mjs: two-user real-time sync coverage Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:17
|
||||
environment:
|
||||
POSTGRES_DB: yeschef
|
||||
POSTGRES_USER: yeschef
|
||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
|
||||
volumes:
|
||||
- yeschef-pgdata:/var/lib/postgresql/data
|
||||
expose:
|
||||
- "5432"
|
||||
restart: unless-stopped
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U yeschef"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
backend:
|
||||
build:
|
||||
context: ./src/backend/YesChef.Api
|
||||
dockerfile: Dockerfile
|
||||
environment:
|
||||
ConnectionStrings__DefaultConnection: "Host=postgres;Database=yeschef;Username=yeschef;Password=${POSTGRES_PASSWORD}"
|
||||
Jwt__Secret: ${JWT_SECRET}
|
||||
FamilyCode: ${FAMILY_CODE}
|
||||
expose:
|
||||
- "5000"
|
||||
depends_on:
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
restart: unless-stopped
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.yeschef-api.rule=Host(`${DOMAIN}`) && (PathPrefix(`/api`) || PathPrefix(`/hubs`) || Path(`/health`))"
|
||||
- "traefik.http.routers.yeschef-api.entrypoints=websecure"
|
||||
- "traefik.http.routers.yeschef-api.tls.certresolver=letsencrypt"
|
||||
- "traefik.http.services.yeschef-api.loadbalancer.server.port=5000"
|
||||
|
||||
frontend:
|
||||
build:
|
||||
context: ./src/frontend
|
||||
dockerfile: Dockerfile
|
||||
environment:
|
||||
ORIGIN: https://${DOMAIN}
|
||||
expose:
|
||||
- "3000"
|
||||
depends_on:
|
||||
- backend
|
||||
restart: unless-stopped
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.yeschef-web.rule=Host(`${DOMAIN}`)"
|
||||
- "traefik.http.routers.yeschef-web.entrypoints=websecure"
|
||||
- "traefik.http.routers.yeschef-web.tls.certresolver=letsencrypt"
|
||||
- "traefik.http.routers.yeschef-web.priority=1"
|
||||
- "traefik.http.services.yeschef-web.loadbalancer.server.port=3000"
|
||||
|
||||
volumes:
|
||||
yeschef-pgdata:
|
||||
Reference in New Issue
Block a user