Initial commit: EatMe attendance tracker

Google-SSO PWA for bistro employee clock-in/out, admin employee
management, and stats with CSV export. Express + SQLite backend,
React + Zustand frontend in the light-mono-tui design language.
Multi-stage Dockerfile, compose.yaml for image-based deploys, nginx
reverse-proxy template, and an OKF documentation bundle in docs/.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Michal Pemcak
2026-08-12 11:57:55 +02:00
commit fffcb73ea4
90 changed files with 3411 additions and 0 deletions

42
Dockerfile Normal file
View File

@@ -0,0 +1,42 @@
# syntax=docker/dockerfile:1
# ---- frontend build: React/Vite PWA -> static dist/ ----
FROM node:22-slim AS frontend-build
WORKDIR /app/frontend
COPY frontend/package.json frontend/package-lock.json ./
RUN npm ci
COPY frontend/ .
# Vite inlines VITE_* env vars at build time, so the Google client id has to
# be supplied as a build arg: docker build --build-arg VITE_GOOGLE_CLIENT_ID=...
ARG VITE_GOOGLE_CLIENT_ID
ENV VITE_GOOGLE_CLIENT_ID=$VITE_GOOGLE_CLIENT_ID
RUN npm run build
# ---- backend build: TypeScript -> single esbuild bundle ----
FROM node:22-slim AS backend-build
WORKDIR /app/backend
COPY backend/package.json backend/package-lock.json ./
RUN npm ci
COPY backend/ .
RUN npm run build
# ---- runtime: only prod deps + the two build outputs ----
FROM node:22-slim AS runtime
ENV NODE_ENV=production
WORKDIR /app
# better-sqlite3 has a native binding, so it's installed for real here rather
# than copied from another stage — same base image as backend-build, so the
# compiled binary always matches what it runs on.
COPY backend/package.json backend/package-lock.json ./
RUN npm ci --omit=dev && npm cache clean --force
COPY --from=backend-build /app/backend/dist ./dist
COPY --from=frontend-build /app/frontend/dist ./dist/public
ENV PORT=4000
ENV DB_PATH=/app/data/eatme.db
EXPOSE 4000
VOLUME ["/app/data"]
CMD ["node", "dist/index.js"]