Files
CLProject/PROJECT_FILES_GUIDE.md
T
2026-04-19 21:14:16 +02:00

20 KiB

Project Files Guide

This document explains the role of the main files in this project in a way that should be easy to follow for a junior developer.

The project is split into a few clear parts:

  • server code in src/app.js and the rest of src
  • browser frontend files in public
  • database structure and example data in sql
  • environment and local development helpers in the root folder and scripts

How The Application Works At A High Level

The project has two big sides:

  • the backend, which provides templates, lookups, configuration, report storage, and audit logging through REST API endpoints
  • the frontend, which runs in the browser, stores drafts locally, and uses the backend for centrally managed configuration and report submission

In simple terms:

  1. Express starts the server.
  2. The server exposes API endpoints under /api/v1/....
  3. The server also serves the frontend files from the public folder.
  4. The browser loads the frontend entry point public/app.js which imports modules from public/js/.
  5. The frontend downloads templates and config from the API using a single batch request.
  6. The frontend stores reports and images locally in IndexedDB.
  7. Reports can be submitted to the server via POST /api/v1/reports.

Root Files

package.json

Role: Defines the Node.js project itself.

What it contains:

  • project name and version
  • npm scripts such as start, dev, and test:environment
  • dependency list such as express, mariadb, and dotenv

Why it matters: When you run npm install or npm start, Node uses this file to know how the project should behave.

README.md

Role: Main entry document for developers.

What it contains:

  • project purpose
  • setup steps
  • available endpoints
  • development notes

Why it matters: This is the first file a new developer should read before touching the code.

docker-compose.yml

Role: Starts the full local development environment.

What it contains:

  • the application container
  • the MariaDB container
  • the phpMyAdmin container
  • port mappings and volume configuration

Why it matters: Instead of installing and configuring everything manually, you can start the full stack with one command.

.env.example

Role: Example environment configuration.

What it contains:

  • default port values
  • database host, name, user, and password placeholders

Why it matters: It shows which environment variables the application expects.

.env

Role: Real environment file used on the current machine.

What it contains:

  • actual local values for ports and database credentials

Why it matters: The backend reads this file during startup through dotenv.

Public Folder

The public folder contains files that are sent directly to the browser.

public/user.html

Role: Operator workspace HTML shell.

What it contains:

  • shared sidebar with template selector, sync button, report list, and search/filter
  • report editor main area with hero, summary cards, form, inspector panel
  • report list item <template> for runtime rendering

When you edit it:

  • when you need to change the report editing layout
  • when adding new user-facing controls or sections

public/admin.html

Role: Administrator workspace HTML shell.

What it contains:

  • simplified sidebar with template selector and sync button (no report list)
  • admin main area with image policy editor form and admin summary panel

When you edit it:

  • when adding new admin configuration panels
  • when changing the image policy form fields

public/index.html

Role: Legacy combined app shell (no longer served by routes).

Note: This file has been superseded by user.html and admin.html. It remains in the repository for reference but is not routed to by the Express server.

public/portal.html

Role: Simple chooser page that lets the user open either the user area or the admin area.

What it contains:

  • a short explanation of the two entry points
  • a link to /user
  • a link to /admin

What it does: It is the landing page served at /. It does not contain complex logic. Its job is only to separate the entry points.

public/app.js

Role: Thin orchestrator entry point for the frontend.

What it contains:

  • imports from all ES modules under public/js/
  • startup flow (init(), cacheElements(), bindEvents())
  • report CRUD operations (create, open, delete, submit)
  • sync logic with the API using batch template fetch
  • dirty-flag autosave loop
  • admin image-policy save
  • event delegation for the report list
  • search/filter event wiring
  • null guards for page-specific elements (user vs admin)

What changed: This file was originally a monolithic ~1700-line file. It has been split into modules (A1) and now acts as a controller. It is shared between user.html and admin.html — it detects which DOM elements exist and only binds behavior for the current page.

public/styles.css

Role: Main styling file for the frontend.

What it contains:

  • color variables
  • layout rules
  • sidebar and panel styles
  • form field styles
  • admin and user page styles
  • responsive behavior for smaller screens

What it does: It controls how the application looks on desktop and mobile.

When you edit it:

  • when spacing or sizing is wrong
  • when a section needs a new visual style
  • when mobile layout needs improvement

public/sw.js

Role: Service worker for offline behavior.

What it contains:

  • cache name
  • app shell file list (including all new JS modules)
  • install, activate, and fetch event handlers
  • LRU cache trimming for dynamic entries (P5)

What it does: It tells the browser how to cache frontend files and API responses.

Important behavior:

  • static files use cache-first strategy
  • API calls use network-first strategy
  • dynamic cache is bounded to prevent unbounded storage growth

public/icon.svg

Role: SVG icon used by the PWA manifest (F5).

Frontend ES Modules (public/js/)

These modules were extracted from the original monolithic app.js (A1). All render functions include null guards so the shared app.js can safely run on both user.html (operator workspace) and admin.html (administrator workspace).

public/js/constants.js

Role: Shared constants used across frontend modules.

What it contains:

  • IndexedDB name, version, and store names
  • API base path (/api/v1)
  • autosave interval, render debounce timing, cache limits

public/js/state.js

Role: Centralized state management for the frontend.

What it contains:

  • state object with all application state (including dirty flag, search query, filter)
  • elements object for cached DOM references
  • getCurrentReport() and getTemplateRecord() helpers
  • stateHelpers bundle used by other modules to avoid circular imports

public/js/i18n.js

Role: Internationalization locale extraction (F7).

What it contains:

  • English locale with ~80 UI string keys
  • t(key, ...params) translation function with placeholder replacement
  • setLocale() for future language support

public/js/utils.js

Role: Pure utility and formatting functions.

What it contains:

  • prettifyStatus(), formatDateTime(), formatTime(), formatRelativeTime(), formatFileSize()
  • sanitizeForFilename(), generateReportNumber(), buildGeneratedFilename()
  • makeTemplateKey(), deriveTemplateCatalog()
  • debounce() helper for rate-limiting function calls (P2)

public/js/db.js

Role: IndexedDB operations with multi-store transaction support.

What it contains:

  • openDatabase() with schema version 2
  • CRUD helpers: dbGetAll(), dbGet(), dbPut(), dbDelete(), dbGetAllByIndex()
  • dbTransaction() for atomic multi-store operations (A5)
  • saveSetting() and loadSetting() for UI preferences

public/js/api.js

Role: API communication layer with versioned base path (A3).

What it contains:

  • fetchJson(path, options) that prepends the API base path automatically
  • registerServiceWorker()

public/js/validation.js

Role: Shared validation logic for reports and admin forms (A7).

What it contains:

  • validateReport() — checks required fields, number ranges, attachment counts
  • validateImageRulesPayload() — validates image policy form submissions
  • evaluateRequiredWhen() — conditional field requirement logic
  • isBlankValue() — blank check by field type

public/js/images.js

Role: Image optimization with Web Worker support (P1).

What it contains:

  • optimizeImage(file, imageRules) — automatically detects Web Worker support
  • Worker path: delegates to image-worker.js via OffscreenCanvas
  • Falls back to main-thread canvas when OffscreenCanvas is unavailable

public/js/image-worker.js

Role: Web Worker for background image processing (P1).

What it contains:

  • self.onmessage handler using createImageBitmap and OffscreenCanvas
  • Sends optimized blob back to main thread with matching message ID

public/js/forms.js

Role: Dynamic form field creation from template JSON.

What it contains:

  • createFieldNode(field, report, callbacks) — renders fields with callback pattern
  • createAttachmentFieldNode() with IntersectionObserver for lazy-loading thumbnails (P3)
  • escapeHtml() for XSS prevention

public/js/renderer.js

Role: All DOM render functions with search and filter support (F4).

What it contains:

  • render() orchestrator — conditionally calls user or admin renders
  • renderReportList() — filters by search query and status
  • renderCurrentReport(fieldCallbacks) — accepts callbacks for field changes
  • renderTemplateSelector(), renderTemplateSummary()
  • renderSyncSummary(), renderImagePolicy(), renderAdminImageRules()
  • updateConnectionBadge(), updateSaveBadge()
  • Uses t() for all user-visible strings
  • Null guards on all page-specific functions for safe user/admin coexistence

public/js/export.js

Role: Report data export functionality (F2).

What it contains:

  • exportReportCSV() — generates CSV from template fields and report answers
  • exportReportAttachments() — triggers download for each attachment blob
  • csvEscape() and downloadBlob() helper functions

public/manifest.webmanifest

Role: Basic PWA metadata file.

What it contains:

  • app name
  • short name
  • theme color
  • start URL

What it does: Helps the browser treat the app more like an installable web application.

Source Folder

The src folder contains backend code.

src/server.js

Role: Real server startup file.

What it contains:

  • startup function
  • database connection check
  • Express app startup
  • graceful shutdown logic

What it does: This is the file Node runs when the backend starts.

Simple mental model:

  • load the Express app
  • make sure MariaDB is reachable
  • start listening on a port
  • close cleanly when the process is stopped

src/app.js

Role: Express application configuration file.

What it contains:

  • middleware registration
  • API v1 route registration under /api/v1/ prefix (A3)
  • static file serving
  • frontend entry page routes
  • global error handling

Important routes:

  • /api/v1/... for versioned backend endpoints
  • / for the chooser page
  • /user and /admin for the frontend app shell

Source Subfolders

src/config/env.js

Role: Loads and validates environment variables.

What it contains:

  • dotenv setup
  • required environment key checks
  • normalized env object export

What it does: It reads raw values from .env and converts them into a safer object the rest of the code can use.

Why this is useful: Instead of reading process.env everywhere, the app reads from one clean place.

src/db/pool.js

Role: Creates and manages the MariaDB connection pool.

What it contains:

  • one shared database pool
  • query() helper
  • closePool() helper

What it does: It gives the service layer a standard way to run SQL queries.

Why it matters: Without this file, each route or service would have to manage its own connections, which would be messy and error-prone.

src/middleware/errorHandler.js

Role: Handles not-found routes and server errors.

What it contains:

  • notFoundHandler
  • errorHandler

What it does: When a route does not exist, or when code throws an error, this file creates a JSON response instead of letting the app fail in an uncontrolled way.

src/middleware/validateParams.js

Role: URL parameter validation middleware (A7).

What it contains:

  • validateParam(name) — checks route params against safe patterns (code or UUID)
  • validateNumericParam(name) — validates numeric route parameters

What it does: It rejects malformed URL parameters at the middleware level before they reach route handlers.

src/routes/healthRoutes.js

Role: Defines the health-check endpoint.

What it contains:

  • GET /api/health

What it does: Checks whether the server and database are working.

Why it matters: This endpoint is used by tests and is also useful when debugging container problems.

src/routes/templateRoutes.js

Role: Defines template-related API endpoints.

What it contains:

  • list endpoint for active templates
  • batch endpoint with ?include=definitions for single-request sync (A2)
  • endpoint for one active template
  • endpoint for a specific template version
  • version listing for a template (F3)
  • version publishing endpoint (F3)
  • parameter validation middleware
  • LRU cache integration (P4)

src/routes/lookupRoutes.js

Role: Defines lookup-related API endpoints.

What it contains:

  • list endpoint for lookup sets
  • endpoint for one lookup set
  • parameter validation and LRU cache integration

src/routes/configRoutes.js

Role: Defines configuration-related API endpoints.

What it contains:

  • image rule read and update endpoints
  • export profile endpoint
  • general app config endpoint
  • LRU cache read-through and invalidation (P4)
  • audit trail logging on image rules update (F6)

src/routes/reportRoutes.js

Role: Defines report submission API endpoints (F1).

What it contains:

  • GET / — list submitted reports with filters (status, templateCode, limit, offset)
  • GET /:reportId — single report by UUID
  • POST / — submit or update a report (UPSERT by UUID, audit-logged)

src/services/templateService.js

Role: Handles template-related database queries.

What it contains:

  • SQL for active template list
  • getAllActiveTemplates() — batch query returning all templates with definitions (A2)
  • listTemplateVersions() — all versions of a given template (F3)
  • publishTemplateVersion() — retire current active, activate specified version (F3)
  • template row mapping logic

src/services/lookupService.js

Role: Handles lookup-related database queries.

src/services/configService.js

Role: Handles configuration-related database queries.

src/services/reportService.js

Role: Handles report submission and retrieval (F1).

What it contains:

  • submitReport(report) — UPSERT by report UUID
  • getReport(uuid) — fetch single report
  • listReports({ status, templateCode, limit, offset }) — filtered listing

src/services/auditService.js

Role: Audit trail logging for admin mutations (F6).

What it contains:

  • logAuditEvent({ entityType, entityCode, action, oldValue, newValue }) — writes to audit_log table
  • getAuditLog() — reads audit entries with optional filters

src/services/cacheService.js

Role: In-memory LRU cache with TTL for server-side data (P4).

What it contains:

  • createCache({ maxEntries, ttlMs }) factory function
  • Pre-configured singletons: templateCache, lookupCache, configCache
  • Each cache instance has get(), set(), delete(), and clear() methods

src/utils/asyncHandler.js

Role: Small helper for async Express routes.

What it contains:

  • asyncHandler() wrapper

What it does: It catches rejected async route errors and forwards them to Express error middleware.

Why it matters: Without it, every async route would need repetitive try/catch blocks.

src/utils/json.js

Role: Small helper for parsing JSON values coming from MariaDB.

What it contains:

  • parseJsonColumn()

What it does: It safely converts JSON strings into objects and arrays.

Why it matters: Several database columns store JSON text, and this helper prevents the same parsing logic from being repeated in multiple files.

SQL Folder

sql/schema.sql

Role: Creates the database structure.

What it contains:

  • database creation
  • table definitions
  • keys and foreign keys

What it does: It defines how templates, lookups, image rules, export profiles, and app config are stored.

sql/seed.sql

Role: Inserts example data.

What it contains:

  • one example checklist template
  • lookup values
  • one image policy
  • one export profile
  • app config values

What it does: It gives the frontend and API something real to work with immediately after startup.

Scripts Folder

scripts/test-environment.js

Role: Simple smoke test for the local environment.

What it contains:

  • API health checks
  • template endpoint checks
  • direct database checks
  • phpMyAdmin checks

What it does: It verifies that the main development services are working together.

When to use it:

  • after starting Docker containers
  • after changing infrastructure-related code
  • after big refactors when you want a quick confidence check

If you are new to this project, a good reading order is:

  1. README.md
  2. PROJECT_FILES_GUIDE.md
  3. src/server.js
  4. src/app.js
  5. src/routes/templateRoutes.js
  6. src/services/templateService.js
  7. public/js/constants.js and public/js/state.js
  8. public/app.js — the thin orchestrator that wires everything together
  9. public/js/renderer.js and public/js/forms.js
  10. public/index.html
  11. public/app.js
  12. sql/schema.sql
  13. sql/seed.sql

That order helps because it moves from the high-level entry points into the deeper details.

Practical Rule Of Thumb

When you are trying to change something, use this shortcut:

This simple rule is often enough to help you find the right file quickly.