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:
- Express starts the server.
- The server exposes API endpoints under
/api/v1/.... - The server also serves the frontend files from the public folder.
- The browser loads the frontend entry point public/app.js which imports modules from public/js/.
- The frontend downloads templates and config from the API using a single batch request.
- The frontend stores reports and images locally in IndexedDB.
- 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, andtest:environment - dependency list such as
express,mariadb, anddotenv
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:
stateobject with all application state (including dirty flag, search query, filter)elementsobject for cached DOM referencesgetCurrentReport()andgetTemplateRecord()helpersstateHelpersbundle 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 replacementsetLocale()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()andloadSetting()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 automaticallyregisterServiceWorker()
public/js/validation.js
Role: Shared validation logic for reports and admin forms (A7).
What it contains:
validateReport()— checks required fields, number ranges, attachment countsvalidateImageRulesPayload()— validates image policy form submissionsevaluateRequiredWhen()— conditional field requirement logicisBlankValue()— 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.jsviaOffscreenCanvas - 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.onmessagehandler usingcreateImageBitmapandOffscreenCanvas- 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 patterncreateAttachmentFieldNode()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 rendersrenderReportList()— filters by search query and statusrenderCurrentReport(fieldCallbacks)— accepts callbacks for field changesrenderTemplateSelector(),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 answersexportReportAttachments()— triggers download for each attachment blobcsvEscape()anddownloadBlob()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/userand/adminfor the frontend app shell
Source Subfolders
src/config/env.js
Role: Loads and validates environment variables.
What it contains:
dotenvsetup- required environment key checks
- normalized
envobject 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()helperclosePool()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:
notFoundHandlererrorHandler
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=definitionsfor 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 UUIDPOST /— 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 UUIDgetReport(uuid)— fetch single reportlistReports({ 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 tablegetAuditLog()— 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(), andclear()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
Recommended Reading Order For A Junior Developer
If you are new to this project, a good reading order is:
- README.md
- PROJECT_FILES_GUIDE.md
- src/server.js
- src/app.js
- src/routes/templateRoutes.js
- src/services/templateService.js
- public/js/constants.js and public/js/state.js
- public/app.js — the thin orchestrator that wires everything together
- public/js/renderer.js and public/js/forms.js
- public/index.html
- public/app.js
- sql/schema.sql
- 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:
- if the browser layout looks wrong, check public/index.html and public/styles.css
- if browser behavior is wrong, check public/app.js
- if an API endpoint is wrong, check src/routes first and then src/services
- if database data is wrong, check sql/schema.sql, sql/seed.sql, and the service file that runs the query
- if the app does not start, check src/server.js, src/config/env.js, and docker-compose.yml
This simple rule is often enough to help you find the right file quickly.