5.6 KiB
5.6 KiB
AGENTS.md
File structure
.
├── server.js # Express server with API endpoints
├── package.json # Dependencies (express, cors)
├── public/
│ ├── Test.html # Root HTML file (served at /)
│ ├── main.v2.js # Complete frontend client app
│ └── styles.css # UI styles
├── Docker/
│ └── Dockerfile # Node.js Alpine image
├── docker-compose.yml # Docker service definition
└── sessions/ # Data directory (bind-mounted in Docker)
├── ELT/ # Elektro department
├── HLS/ # HLS department
└── ARCH/ # Architektur department
Overview
Single-page app for tracking engineering projects across weekly sessions
("Sitzungen"). Vanilla JS/HTML/CSS frontend (public/) + Node.js/Express server
(server.js). No build step, no bundler. Data is persisted as CSV files under
sessions/.
Running
npm installthennpm start(executesnode server.js).- Or with Docker:
docker compose -f Docker/docker-compose.yml up --build. - Server runs on
PORTenv var or defaults to3003; servespublic/Test.htmlas root and API under/load-all,/save-csv,/delete-csv. - Frontend assumes the API lives at
window.location.origin, falling back tohttp://localhost:3003when opened as a local file. OpeningTest.htmldirectly without a server will load seed/demo data.
Operations
Local
npm install
npm start
Access at http://localhost:3003 (or PORT=3004 if occupied).
Docker
docker compose -f Docker/docker-compose.yml up --build
Access at http://localhost:3003 (or override with PORT=3004).
CSV format
- Delimiter: semicolon (
;) - Encoding: UTF-8 with BOM (
\ufeff) - Structure:
sessions/<DEPT>/contains department data- Week files:
<Label>.csv(e.g.,KW_30___2026.csv) - Global people:
_people.csvwith columnsNAME;Rollen;Voller Name
Data layout
- Data is split by department:
sessions/ELT/,sessions/HLS/,sessions/ARCH/. Valid departments are hard-coded inserver.js(VALID_DEPARTMENTS) andmain.v2.js(DEPARTMENTS). Unknown department values fall back toELT. - Each week is one CSV file named
<Label>.csvwith;delimiter and UTF-8 BOM. - Each department has a global people list in
_people.csvwith columnsNAME;Rollen;Voller Name. New people are added globally and copied into the current week. Historical weeks keep their own person copies so deleted global people remain visible in old sessions. - The app reads CSVs on startup via
/load-all;localStorageis used only for the last-selected department/tab UI state. Do not store data inlocalStorage. - Editing CSVs by hand is possible but risky; prefer the UI.
Architecture notes
- Frontend is in
public/(Test.html,main.v2.js,styles.css). main.v2.jsis the entire client app loaded as a classic non-module<script>; all functions are globals onwindow.- State lives in
let db = { weeks: [], currentWeek, globalPeople: {} }. - Each week object has
projects(withassign,lph,group,status,order) andpeoplewith session-local copies. save()schedulessyncAllToServer()debounced by 500 ms; this writes all weeks plus the global_people.csvto the server, not just the changed one.- Weeks are sorted by calendar week extracted from the label (
KW XX / YYYY), not alphabetically. applyAutoLock()locks every week except the chronologically last one after load/clone/new-week, so historical weeks are read-only unless explicitly unlocked.- Person IDs are derived from the person's abbreviation/name to stay stable
across reloads (
personIdForNameinmain.v2.js).
Docker
- Dockerfile uses
node:20-alpineas base image. - Copies only
package.json/package-lock.jsonfirst (npm ci --production), then server files. - Excludes
Docker/,node_modules/,.git,.gitignorevia.dockerignore. - Runs as non-root
nodeuser;/app/sessionsbind-mounted from host./sessions. - HEALTHCHECK on
/healthendpoint; service restarts on failure (unless-stopped). - Frontend must be served via HTTP (not
file://) for CORS to work.
Security / auth quirk
projectsandpeopletabs plus week deletion are gated by a password modal. The check comparesCryptoJS.SHA256(input)toPROTECTED_PASSWORD_HASHinmain.v2.js. This is client-side only and not real security. CryptoJS is loaded from a CDN (cdnjs.cloudflare.com) inTest.html, so the password gate needs internet access.- User-provided status HTML is sanitized on render (small tag/attribute whitelist) to mitigate XSS while keeping formatting options.
- Filenames sent to
/save-csvand/delete-csvare strictly validated server side to prevent path traversal.
Conventions
- UI strings, comments, and CSV content are German. Preserve German in user-facing text.
- No linter, formatter, typecheck, or test suite is configured. Verify changes by running the server and exercising the relevant tab in the browser.
- This is not a git repo. Don't assume git workflows.
- Edit
main.v2.jsfunctions in place; the file is intentionally one large script with German header comments per section. Match that style.
Testing & verification
- No automated test suite exists. Manual verification only:
- Start server (
npm startor Docker) - Open
http://localhost:3003 - Check
/healthendpoint returns{ok:true} - Exercise relevant tab in browser (Board, Projects, People)
- Verify CSV persistence in
sessions/directory
- Start server (