Files
ca-lose/README.md
T

4.8 KiB

CA-Lose

CA-Lose is a small full-stack app for collecting ticket-sale/order form entries.

Tech stack

React TypeScript Vite Tailwind CSS MUI i18next

Node.js Express MySQL

Docker Nginx

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-mysql when using Docker Compose)
  • DB_USER (e.g. root)
  • DB_PASSWORD
  • DB_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:

Note: In docker-compose.yml the frontend service is currently commented out.

Option B: Run frontend locally (Vite) + run backend & DB

  1. Start DB + backend (Docker):
docker compose up --build database backend
  1. 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/* (see frontend/nginx.conf). In that setup the frontend should use /backend/default/... instead of http://localhost:8004/....

Database setup

The schema file is in backend/scheme.sql.

  • The users table 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: dnsmasq and wireguard (wg-easy)

Start it:

docker compose -f docker-compose.prod.yml up -d --build

Notes:

  • docker-compose.prod.yml uses an external network called proxynet. 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 import syntax. Node must treat the backend as an ESM project (commonly by adding "type": "module" to backend/package.json). Without that, the backend will fail to start (including in Docker).
  • MySQL timezone mount: The compose files mount ./mysql-timezone.cnf to /etc/mysql/conf.d/timezone.cnf. Ensure mysql-timezone.cnf is a file (not a directory) with valid MySQL config, or remove/adjust the mount.

License

Licensed under the Apache License 2.0. See LICENSE.