4.8 KiB
CA-Lose
CA-Lose is a small full-stack app for collecting ticket-sale/order form entries.
Tech stack
Architecture
- Frontend: React + TypeScript + Vite (UI uses MUI + Tailwind, i18n via i18next)
- Backend: Node.js + Express (also renders a minimal EJS page at
/) - Database: MySQL 8
In production, the frontend is served by Nginx and proxies /backend/* to the backend container.
Repos & folders
backend/ # Express API + EJS views
frontend/ # React app (Vite) + Nginx container
docker-compose.yml
docker-compose.prod.yml
API overview
The backend router is mounted at /default:
GET /default/users→ returns{ users: string[] }GET /default/confirm-user?username=<name>→ validates user and returns metadata (e.g. next id)POST /default/new-entry?username=<name>→ stores a new entry in MySQL
Configuration
Backend environment variables
The backend reads configuration from environment variables (and can also load a backend/.env file via dotenv).
PORT(e.g.8004)DB_HOST(e.g.ca-lose-mysqlwhen using Docker Compose)DB_USER(e.g.root)DB_PASSWORDDB_NAME(e.g.ca_lose)
Docker Compose environment
Both compose files expect DB_PASSWORD to be present in your shell environment or a root .env file.
Create a root .env (not committed) like:
DB_PASSWORD=change-me
Local development
Option A: Docker Compose (backend + database)
This is the quickest way to get the API + MySQL running.
docker compose up --build
What you get:
- Backend: http://localhost:8004
- MySQL: localhost:3311 (container port 3306)
Note: In docker-compose.yml the frontend service is currently commented out.
Option B: Run frontend locally (Vite) + run backend & DB
- Start DB + backend (Docker):
docker compose up --build database backend
- Start frontend (local Node):
cd frontend
npm ci
npm run dev
Open the Vite dev server URL (usually http://localhost:5173).
Important:
- During local development (Vite), the frontend currently calls the backend via a hard-coded URL (
http://localhost:8004). - When the frontend is served by the Nginx container, requests are expected to go through the Nginx proxy at
/backend/*(seefrontend/nginx.conf). In that setup the frontend should use/backend/default/...instead ofhttp://localhost:8004/....
Database setup
The schema file is in backend/scheme.sql.
- The
userstable is required for the user dropdown. - The backend creates an entry table dynamically per user and date when calling
GET /default/confirm-user.
Example (inside MySQL):
INSERT INTO users (username, first_name, last_name)
VALUES ('demo', 'Demo', 'User');
Production / Deployment
The production compose file builds and runs:
frontend(Nginx)backend(Express)database(MySQL)- optional infrastructure:
dnsmasqandwireguard(wg-easy)
Start it:
docker compose -f docker-compose.prod.yml up -d --build
Notes:
-
docker-compose.prod.ymluses an external network calledproxynet. Create it if it does not exist:docker network create proxynet -
The production file assigns static IPs; adjust the subnets/IPs if they conflict with your environment.
Lint / build
Frontend:
cd frontend
npm run lint
npm run build
Troubleshooting
- Backend does not start / ESM imports: The backend code uses ESM
importsyntax. Node must treat the backend as an ESM project (commonly by adding"type": "module"tobackend/package.json). Without that, the backend will fail to start (including in Docker). - MySQL timezone mount: The compose files mount
./mysql-timezone.cnfto/etc/mysql/conf.d/timezone.cnf. Ensuremysql-timezone.cnfis a file (not a directory) with valid MySQL config, or remove/adjust the mount.
License
Licensed under the Apache License 2.0. See LICENSE.