# cityssm/sunrise-cms architecture

> Architecture diagram of the GitHub repository cityssm/sunrise-cms, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-06-23). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/cityssm/sunrise-cms
- Repository: https://github.com/cityssm/sunrise-cms

## Overview

1. This is a server-rendered Node/TypeScript application for cemetery management. The primary user-facing domains are cemeteries, burial sites, contracts, funeral homes, work orders, reports, and an admin console. The README confirms the app is intended to run locally or on modest infrastructure, with no separate database server requirement implied by the architecture.

2. The top-level request path is: `routes/*` define URL groups, `handlers/*` contain the actual page/action logic, and `views/*` render EJS templates back to the browser. This is the main architectural boundary: routing, request handling, and presentation are separated into distinct folders per business area.

3. The code is organized by feature rather than by technical layer. Major subsystems include `burialSites`, `cemeteries`, `contracts`, `funeralHomes`, `workOrders`, `dashboard`, `reports`, `admin`, `print`, and `api`. Each of these has paired GET/POST handler folders, which suggests standard page rendering plus form-action endpoints in the same feature boundary.

4. The data layer lives in `database/*` and is very granular. Instead of a single ORM-style repository, the app exposes many task-specific functions such as add/update/delete/get/move/restore/backup/cleanup operations for each record type. That indicates a procedural persistence layer where handlers call narrowly scoped database functions directly.

5. Shared business logic is concentrated in `helpers/*`. These helpers cover authentication, permissions, configuration, caching, database utilities, reports, printing/PDF behavior, images, partial dates, Find a Grave integration, i18n, and domain-specific logic for burial sites, contracts, users, and attachments. This is the main service layer between handlers and persistence.

6. There is a substantial cache subsystem under `helpers/cache/*` for reference data such as cemeteries, burial site types, contract types, service types, settings, and work order metadata. These caches likely reduce repeated database reads for low-churn configuration tables and are important to the app’s read path.

7. The UI is classic server-side rendering with EJS templates in `views/*` and static assets in `public/*`. Client-side behavior is bundled as feature-specific scripts in `public/javascripts/*`, with matching TypeScript sources. The front end is therefore thin and page-oriented rather than a standalone SPA.

8. Admin functionality is a separate subsystem with its own views, handlers, and client scripts. It manages reference tables, user accounts, permissions, audit logs, settings, fees, database maintenance, and configuration tables. The architecture treats admin data as a distinct control plane from the operational cemetery records.

9. Work orders are a first-class workflow module, not just a note-taking add-on. The work order area includes milestones, workday views, iCal/calendar output, comments, related records, and close/reopen operations. That implies a transactional workflow flow: create work order → attach burial sites/contracts → track milestones/time → close or reopen as needed.

10. Integrations are isolated under `integrations/*`. The repo includes Consigno Cloud workflow support, Dynamics GP helpers/types, and Ntfy helpers/types. These external service boundaries are used by domain handlers and background tasks rather than being embedded throughout the codebase.

11. There are dedicated background/operational entry points in `tasks/*` and Windows service scripts at the repo root. There is also a CLI importer under `cli/findAGraveMemorialExtractorImport` and legacy import utilities in `temp/legacyImportFromCsv`. This shows the system has operational flows beyond the web UI: scheduled backups, workflow polling, service installation, and data migration/import.

12. Data and file handling is explicit. The `data/` folder contains attachments, backups, sessions, and partial configuration files; `public-internal/` holds internal images; and several feature areas support attachments and PDFs. This suggests the system’s operational state is partly file-based, with the application coordinating database records and filesystem artifacts.

13. Authentication, authorization, and permissions are centralized. There are shared authentication helpers, a `handlers/permissions.ts` module, and feature-level behavior changes for read-only vs update/admin users, which is also reflected in the Cypress test suites. Permission checks are therefore a cross-cutting concern applied before handlers execute domain actions.

14. Localization and environment-specific configuration are built in. The app has `locales/en` and `locales/de`, plus config helpers, default config, partial configs, and test-specific config files. This makes runtime behavior dependent on environment and locale, but still managed through shared config helpers rather than hardcoded feature logic.

15. Testing is layered: unit tests live in `test/`, end-to-end browser tests live in `cypress/e2e/`, and CI workflows cover linting and coverage. The test structure mirrors the feature architecture, which is useful when drawing the system diagram because it validates the same request/handler/database boundaries used in production.

Main entry points: [`database`](https://github.com/cityssm/sunrise-cms/tree/main/database) (Database), [`helpers`](https://github.com/cityssm/sunrise-cms/tree/main/helpers) (Helpers), [`handlers`](https://github.com/cityssm/sunrise-cms/tree/main/handlers) (Handlers), [`integrations`](https://github.com/cityssm/sunrise-cms/tree/main/integrations) (Integrations)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_runtime["Runtime"]
  node_app["App entry<br/>Node/TS bootstrap<br/>[app.ts]"]
  node_routes["Routes<br/>URL routing"]
  node_handlers["Handlers<br/>Request logic"]
  node_views["Views<br/>EJS templates"]
end

subgraph group_features["Features"]
  node_cemetery_features["Cemeteries<br/>Domain feature"]
  node_burial_features["Burial sites<br/>Domain feature"]
  node_contract_features["Contracts<br/>Domain workflow"]
  node_funeral_features["Funeral homes<br/>Domain feature"]
  node_workorder_features["Work orders<br/>Workflow module"]
  node_admin_features["Admin console<br/>Control plane"]
  node_reporting["Reports<br/>Reporting feature"]
  node_print["Print output<br/>Screen/PDF output"]
  node_api["API"]
end

subgraph group_platform["Platform"]
  node_helpers["Helpers<br/>Shared service layer"]
  node_database[("Database<br/>Procedural data layer")]
  node_cache["Caches<br/>Reference cache"]
  node_integrations["Integrations<br/>External services"]
  node_files["Files & assets<br/>Filesystem state"]
end

subgraph group_ops["Operations"]
  node_ops["Tasks & services<br/>Operational jobs"]
end

node_app -->|"mounts"| node_routes
node_routes -->|"dispatches to"| node_handlers
node_handlers -->|"renders"| node_views
node_handlers -->|"uses"| node_helpers
node_handlers -->|"reads/writes"| node_database
node_helpers -->|"consults"| node_cache
node_helpers -->|"supports"| node_database
node_helpers -->|"adapts"| node_integrations
node_helpers -->|"manages"| node_files
node_cemetery_features -->|"persists"| node_database
node_burial_features -->|"persists"| node_database
node_contract_features -->|"persists"| node_database
node_contract_features -->|"syncs"| node_integrations
node_workorder_features -->|"persists"| node_database
node_workorder_features -->|"exports"| node_print
node_admin_features -->|"administers"| node_database
node_admin_features -->|"refreshes"| node_cache
node_reporting -->|"queries"| node_database
node_print -->|"formats"| node_helpers
node_api -->|"uses"| node_helpers
node_ops -->|"maintains"| node_database
node_ops -->|"polls"| node_integrations

click node_app "https://github.com/cityssm/sunrise-cms/blob/main/app/app.ts"
click node_routes "https://github.com/cityssm/sunrise-cms/tree/main/routes"
click node_handlers "https://github.com/cityssm/sunrise-cms/tree/main/handlers"
click node_views "https://github.com/cityssm/sunrise-cms/tree/main/views"
click node_cemetery_features "https://github.com/cityssm/sunrise-cms/tree/main/handlers/cemeteries-get"
click node_burial_features "https://github.com/cityssm/sunrise-cms/tree/main/handlers/burialSites-get"
click node_contract_features "https://github.com/cityssm/sunrise-cms/tree/main/handlers/contracts-get"
click node_funeral_features "https://github.com/cityssm/sunrise-cms/tree/main/handlers/funeralHomes-get"
click node_workorder_features "https://github.com/cityssm/sunrise-cms/tree/main/handlers/workOrders-get"
click node_admin_features "https://github.com/cityssm/sunrise-cms/tree/main/handlers/admin-get"
click node_reporting "https://github.com/cityssm/sunrise-cms/tree/main/handlers/reports-get"
click node_print "https://github.com/cityssm/sunrise-cms/tree/main/handlers/print-get"
click node_api "https://github.com/cityssm/sunrise-cms/tree/main/handlers/api-get"
click node_helpers "https://github.com/cityssm/sunrise-cms/tree/main/helpers"
click node_database "https://github.com/cityssm/sunrise-cms/tree/main/database"
click node_cache "https://github.com/cityssm/sunrise-cms/tree/main/helpers/cache"
click node_integrations "https://github.com/cityssm/sunrise-cms/tree/main/integrations"
click node_files "https://github.com/cityssm/sunrise-cms/tree/main/data"
click node_ops "https://github.com/cityssm/sunrise-cms/tree/main/tasks"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_app,node_routes,node_handlers,node_views toneBlue
class node_cemetery_features,node_burial_features,node_contract_features,node_funeral_features,node_workorder_features,node_admin_features,node_reporting,node_print,node_api toneAmber
class node_helpers,node_database,node_cache,node_integrations,node_files toneMint
class node_ops toneRose
```

## Components

### Runtime

Application entry, routing, and server-side rendering

- [App entry](https://github.com/cityssm/sunrise-cms/blob/main/app/app.ts): Node/TS bootstrap · Starts the server process and wires the application runtime. · `app/app.ts`
- [Routes](https://github.com/cityssm/sunrise-cms/tree/main/routes): URL routing · Defines request paths and dispatches them into feature handlers. · `routes`
- [Handlers](https://github.com/cityssm/sunrise-cms/tree/main/handlers): Request logic · Feature-specific GET/POST page and action handlers. · `handlers`
- [Views](https://github.com/cityssm/sunrise-cms/tree/main/views): EJS templates · Server-rendered page templates and partials for browser responses. · `views`

### Features

Business domains exposed through routes, handlers, and views

- [Cemeteries](https://github.com/cityssm/sunrise-cms/tree/main/handlers/cemeteries-get): Domain feature · Core cemetery records and related burial-site navigation. · `handlers/cemeteries-get`
- [Burial sites](https://github.com/cityssm/sunrise-cms/tree/main/handlers/burialSites-get): Domain feature · Burial-site CRUD, search, mapping, GPS capture, and comments. · `handlers/burialSites-get`
- [Contracts](https://github.com/cityssm/sunrise-cms/tree/main/handlers/contracts-get): Domain workflow · Contract records with fees, interments, attachments, related records, and external workflow actions. · `handlers/contracts-get`
- [Funeral homes](https://github.com/cityssm/sunrise-cms/tree/main/handlers/funeralHomes-get): Domain feature · Funeral-home records and related service lookup. · `handlers/funeralHomes-get`
- [Work orders](https://github.com/cityssm/sunrise-cms/tree/main/handlers/workOrders-get): Workflow module · Work-order lifecycle, milestones, workday views, calendar output, and close/reopen actions. · `handlers/workOrders-get`
- [Admin console](https://github.com/cityssm/sunrise-cms/tree/main/handlers/admin-get): Control plane · Reference tables, users, permissions, settings, audit log, and database maintenance. · `handlers/admin-get`
- [Reports](https://github.com/cityssm/sunrise-cms/tree/main/handlers/reports-get): Reporting feature · Search and render operational reports from shared report data. · `handlers/reports-get`
- [Print output](https://github.com/cityssm/sunrise-cms/tree/main/handlers/print-get): Screen/PDF output · Printable screen and PDF renderers for records and work orders. · `handlers/print-get`
- [API](https://github.com/cityssm/sunrise-cms/tree/main/handlers/api-get): HTTP API · Small API surface for generated outputs and integrations. · `handlers/api-get`

### Platform

Shared helpers, persistence, integrations, and files

- [Helpers](https://github.com/cityssm/sunrise-cms/tree/main/helpers): Shared service layer · Cross-cutting business logic for auth, permissions, config, caching, reports, printing, and domain utilities. · `helpers`
- [Database](https://github.com/cityssm/sunrise-cms/tree/main/database): Procedural data layer · Task-specific persistence functions for CRUD, search, lifecycle transitions, maintenance, and audit logging. · `database`
- [Caches](https://github.com/cityssm/sunrise-cms/tree/main/helpers/cache): Reference cache · In-memory or shared caches for low-churn reference and settings data. · `helpers/cache`
- [Integrations](https://github.com/cityssm/sunrise-cms/tree/main/integrations): External services · Isolated adapters for Consigno Cloud, Dynamics GP, and Ntfy. · `integrations`
- [Files & assets](https://github.com/cityssm/sunrise-cms/tree/main/data): Filesystem state · Attachments, backups, sessions, partial configs, images, and static assets managed alongside the app. · `data`

### Operations

Background jobs, imports, and service management

- [Tasks & services](https://github.com/cityssm/sunrise-cms/tree/main/tasks): Operational jobs · Background tasks, import utilities, and Windows service entry points. · `tasks`

## Connections

- App entry → Routes: mounts · Application startup registers route modules.
- Routes → Handlers: dispatches to · URL groups invoke feature GET/POST handlers.
- Handlers → Views: renders · Handlers return EJS pages for browser responses.
- Handlers → Helpers: uses · Request logic depends on shared business helpers.
- Handlers → Database: reads/writes · Handlers call targeted persistence functions directly.
- Helpers → Caches: consults · Helpers use caches for reference data and settings.
- Helpers → Database: supports · Shared utilities wrap or coordinate database behavior.
- Helpers → Integrations: adapts · Shared service logic bridges external workflows and services.
- Helpers → Files & assets: manages · Helpers coordinate attachments, images, PDFs, sessions, and config artifacts.
- Cemeteries → Database: persists · Cemetery handlers create, update, delete, and search cemetery records.
- Burial sites → Database: persists · Burial-site handlers handle maps, GPS, comments, restoration, and search.
- Contracts → Database: persists · Contract handlers manage fees, interments, attachments, transactions, and related contracts.
- Contracts → Integrations: syncs · Contracts can start or inspect external workflows and documents.
- Work orders → Database: persists · Work-order handlers manage milestones, comments, closure, and workday state.
- Work orders → Print output: exports · Work orders produce calendar and printable outputs.
- Admin console → Database: administers · Admin handlers manage reference tables, users, settings, and maintenance actions.
- Admin console → Caches: refreshes · Admin changes update cached reference data.
- Reports → Database: queries · Reports are assembled from report-specific data access.
- Print output → Helpers: formats · Print output relies on PDF, print, and locale helpers.
- API → Helpers: uses · API endpoints reuse shared business and formatting logic.
- Tasks & services → Database: maintains · Background jobs and import/service scripts initialize, back up, clean up, and migrate data.
- Tasks & services → Integrations: polls · Operational tasks support external workflow polling and sync.
