# opalescentt/haven architecture

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

- Interactive diagram: https://gitdiagram.com/opalescentt/haven
- Repository: https://github.com/opalescentt/haven

## Overview

1. **Overall shape**
   - This is a **Next.js App Router** application with both UI pages and server API routes in the same repo.
   - The architecture is centered on a **MongoDB-backed application server**, with Next.js handling rendering, routing, and API access.

2. **Primary product areas**
   - The UI is organized around a few user-facing modules: **child profile**, **staff directory**, **resources map**, **partner organizations**, and **support groups**.
   - These correspond to the repository’s main care-coordination concepts: children, staff, events, registrations, and community resources.

3. **Frontend boundary**
   - Pages live under `app/*/page.js`, so the main presentation layer is route-based rather than component-library driven.
   - Shared UI is kept in `components/`, including the **Navbar** and a small set of reusable widgets like the calendar dropdown and support-group icons.
   - `app/layout.js`, `app/providers.js`, and `app/globals.css` provide the global shell, app-wide providers, and styling baseline.

4. **Server/API boundary**
   - The operational backend is implemented as **Next.js route handlers** under `app/api/*/route.js`.
   - Key API domains are:
     - `auth` for login/session handling
     - `user` for user profile data
     - `children` for child records, including an individual-child subroute
     - `events` for event retrieval and management
     - `registrations` for signups or attendance records
     - `staff` and `staff-directory` for staff-facing data
   - This keeps the public UI thin and pushes business logic into server routes.

5. **Authentication and request gating**
   - Authentication is built around **NextAuth** via `app/api/auth/[...nextauth]/route.js`.
   - `middleware.js` likely protects selected routes and enforces session-aware access control.
   - The architecture suggests a split between public informational pages and protected or role-aware workflows for sensitive child-related data.

6. **Data model layer**
   - MongoDB integration is encapsulated in `lib/mongodb.js`.
   - The domain models are defined in `models/`:
     - `User`
     - `Child`
     - `Event`
     - `Registration`
   - This implies a classic app-server pattern: route handler → model → database, with the models acting as the schema and validation boundary.

7. **Sensitive child data handling**
   - `lib/childEncryption.js` indicates that child records contain **sensitive fields encrypted at the application layer** rather than stored fully in plain text.
   - That is an important architectural boundary: child data is not just stored; it is intentionally protected before persistence and likely decrypted only where needed by trusted server-side code.

8. **Event and community workflows**
   - Events are first-class domain data, with constants in `lib/constants/events.js` and a seeding script in `scripts/seed-events.js`.
   - The `registrations` API and `models/Registration.js` show a flow where users can discover events and register for them.
   - `lib/utils/calendar.js` and the calendar dropdown component suggest the UI includes date-based browsing or filtering of events.

9. **Resource discovery and directory data**
   - `staff-directory`, `partner-organizations`, and `resources-map` pages indicate the app is also a **resource navigation layer**, not just a case-management tool.
   - Static reference data appears to be centralized in `lib/constants/partners.js` and `lib/constants/features.js`, which likely drive what is shown in these directory-style views.

10. **Support-group ingestion pipeline**
   - The `app/support-groups/` folder includes parser scripts such as `alliancecares_parser.cjs` and `amara_parser.cjs`.
   - That suggests support-group content is partially **ingested from external sources** and normalized into app-friendly data rather than manually authored only.
   - The support groups page likely consumes this parsed output to show organizations and contact/resource details.

11. **Auxiliary classification tooling**
   - The `classifier/` directory contains Python code for `classifier.py`, `classifier-test.py`, and `sensitive_info_detector.py`.
   - This looks like an offline or batch-oriented analysis tool, likely used to classify text and detect sensitive information in imported content.
   - It is separate from the main Next.js request path, which makes it an auxiliary processing subsystem rather than a runtime dependency of the UI.

12. **Operational scripts and automation**
   - `scripts/fetch-places.js` suggests external data enrichment, likely pulling place or location data for the resources map.
   - `.github/workflows/weekly-scrape.yml` shows the repo has **scheduled automation**, probably to refresh community/support data on a cadence.
   - These scripts form an ingestion/maintenance layer around the core app.

13. **Data flow summary**
   - The main flow is: **user visits a Next.js page → authenticated session is checked → page calls an API route → route reads/writes MongoDB models → response drives the UI**.
   - For sensitive child data, the flow includes an extra **encryption/decryption step** in the server layer.
   - For support resources and directory content, there is an additional **external-source scrape/parse step** before data lands in the app.

14. **Diagram boundaries to show**
   - A good architecture diagram should separate:
     - **Client/UI pages**
     - **Next.js server routes**
     - **Authentication/session layer**
     - **MongoDB persistence**
     - **Sensitive-data encryption**
     - **External ingestion jobs and parsers**
     - **Python classification utilities**
   - Those are the meaningful boundaries in this repository; everything else is supporting implementation detail.

Main entry points: [`lib/mongodb.js`](https://github.com/opalescentt/haven/blob/main/lib/mongodb.js) (MongoDB), [`app/api/children/[id]/route.js`](https://github.com/opalescentt/haven/blob/main/app/api/children/[id]/route.js) (Child API), [`app/api/children/route.js`](https://github.com/opalescentt/haven/blob/main/app/api/children/route.js) (Children API), [`app/api/events/route.js`](https://github.com/opalescentt/haven/blob/main/app/api/events/route.js) (Events API)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_frontend["UI layer"]
  node_app_page["Home<br/>route page<br/>[page.js]"]
  node_child_profile_page["Child profile<br/>route page<br/>[page.js]"]
  node_staff_directory_page["Staff directory<br/>route page<br/>[page.js]"]
  node_resources_map_page["Resources map<br/>route page<br/>[page.js]"]
  node_partner_orgs_page["Partners<br/>route page<br/>[page.js]"]
  node_support_groups_page["Support groups<br/>route page<br/>[page.js]"]
  node_layout_shell["App shell<br/>next layout<br/>[layout.js]"]
  node_providers["Providers<br/>app context<br/>[providers.js]"]
  node_navbar["Navbar<br/>shared UI<br/>[Navbar.js]"]
  node_calendar_dropdown["Calendar picker<br/>shared UI"]
end

subgraph group_api["Server API"]
  node_auth_route["Auth<br/>[route.js]"]
  node_children_api["Children API<br/>route handler<br/>[route.js]"]
  node_child_api["Child API<br/>route handler<br/>[route.js]"]
  node_events_api["Events API<br/>route handler<br/>[route.js]"]
  node_registrations_api["Regs API<br/>route handler<br/>[route.js]"]
  node_staff_api["Staff API<br/>route handler<br/>[route.js]"]
  node_staff_directory_api["Directory API<br/>route handler<br/>[route.js]"]
  node_user_api["User API<br/>route handler<br/>[route.js]"]
end

subgraph group_data["Data layer"]
  node_mongodb[("MongoDB<br/>database connector<br/>[mongodb.js]")]
  node_child_encryption{{"Child crypto<br/>security util<br/>[childEncryption.js]"}}
  node_child_model["Child model<br/>mongoose model<br/>[Child.js]"]
  node_event_model["Event model<br/>mongoose model<br/>[Event.js]"]
  node_registration_model["Registration model<br/>mongoose model<br/>[Registration.js]"]
  node_user_model["User model<br/>mongoose model<br/>[User.js]"]
end

subgraph group_ingestion["Ingestion"]
  node_support_parsers["Support parsers<br/>import parsers"]
  node_fetch_places["Place fetcher<br/>enrichment script<br/>[fetch-places.js]"]
  node_seed_events["Event seeder<br/>seed script<br/>[seed-events.js]"]
  node_weekly_scrape["Weekly scrape<br/>workflow<br/>[weekly-scrape.yml]"]
end

subgraph group_analysis["Analysis tools"]
  node_classifier_py["Classifier<br/>python tool<br/>[classifier.py]"]
  node_sensitive_detector{{"Sensitive detector<br/>python tool"}}
end

node_middleware["Middleware<br/>route gate<br/>[middleware.js]"]

node_layout_shell -->|"renders"| node_navbar
node_layout_shell -->|"wraps"| node_providers
node_app_page -->|"uses"| node_navbar
node_child_profile_page -->|"loads"| node_children_api
node_staff_directory_page -->|"loads"| node_staff_directory_api
node_resources_map_page -->|"shows data from"| node_fetch_places
node_partner_orgs_page -->|"loads"| node_user_api
node_support_groups_page -->|"consumes"| node_support_parsers
node_support_groups_page -.->|"refreshed by"| node_weekly_scrape
node_calendar_dropdown -->|"filters"| node_events_api
node_auth_route -->|"authenticates"| node_user_model
node_middleware -.->|"guards"| node_auth_route
node_children_api -->|"queries"| node_mongodb
node_child_api -->|"queries"| node_mongodb
node_events_api -->|"queries"| node_mongodb
node_registrations_api -->|"queries"| node_mongodb
node_staff_api -->|"queries"| node_mongodb
node_staff_directory_api -->|"queries"| node_mongodb
node_user_api -->|"queries"| node_mongodb
node_children_api -->|"uses"| node_child_model
node_child_api -->|"uses"| node_child_model
node_child_api -->|"protects"| node_child_encryption
node_events_api -->|"uses"| node_event_model
node_registrations_api -->|"uses"| node_registration_model
node_user_api -->|"uses"| node_user_model
node_seed_events -->|"seeds"| node_event_model
node_fetch_places -.->|"enriches"| node_resources_map_page
node_classifier_py -->|"uses"| node_sensitive_detector
node_classifier_py -.->|"analyzes"| node_support_parsers

click node_app_page "https://github.com/opalescentt/haven/blob/main/app/page.js"
click node_child_profile_page "https://github.com/opalescentt/haven/blob/main/app/child-profile/page.js"
click node_staff_directory_page "https://github.com/opalescentt/haven/blob/main/app/staff-directory/page.js"
click node_resources_map_page "https://github.com/opalescentt/haven/blob/main/app/resources-map/page.js"
click node_partner_orgs_page "https://github.com/opalescentt/haven/blob/main/app/partner-organizations/page.js"
click node_support_groups_page "https://github.com/opalescentt/haven/blob/main/app/support-groups/page.js"
click node_layout_shell "https://github.com/opalescentt/haven/blob/main/app/layout.js"
click node_providers "https://github.com/opalescentt/haven/blob/main/app/providers.js"
click node_navbar "https://github.com/opalescentt/haven/blob/main/components/Navbar.js"
click node_calendar_dropdown "https://github.com/opalescentt/haven/blob/main/components/ui/calendar_dropdown.js"
click node_auth_route "https://github.com/opalescentt/haven/blob/main/app/api/auth/[...nextauth]/route.js"
click node_children_api "https://github.com/opalescentt/haven/blob/main/app/api/children/route.js"
click node_child_api "https://github.com/opalescentt/haven/blob/main/app/api/children/[id]/route.js"
click node_events_api "https://github.com/opalescentt/haven/blob/main/app/api/events/route.js"
click node_registrations_api "https://github.com/opalescentt/haven/blob/main/app/api/registrations/route.js"
click node_staff_api "https://github.com/opalescentt/haven/blob/main/app/api/staff/route.js"
click node_staff_directory_api "https://github.com/opalescentt/haven/blob/main/app/api/staff-directory/route.js"
click node_user_api "https://github.com/opalescentt/haven/blob/main/app/api/user/route.js"
click node_mongodb "https://github.com/opalescentt/haven/blob/main/lib/mongodb.js"
click node_child_encryption "https://github.com/opalescentt/haven/blob/main/lib/childEncryption.js"
click node_child_model "https://github.com/opalescentt/haven/blob/main/models/Child.js"
click node_event_model "https://github.com/opalescentt/haven/blob/main/models/Event.js"
click node_registration_model "https://github.com/opalescentt/haven/blob/main/models/Registration.js"
click node_user_model "https://github.com/opalescentt/haven/blob/main/models/User.js"
click node_support_parsers "https://github.com/opalescentt/haven/blob/main/app/support-groups/alliancecares_parser.cjs"
click node_fetch_places "https://github.com/opalescentt/haven/blob/main/scripts/fetch-places.js"
click node_seed_events "https://github.com/opalescentt/haven/blob/main/scripts/seed-events.js"
click node_weekly_scrape "https://github.com/opalescentt/haven/blob/main/.github/workflows/weekly-scrape.yml"
click node_classifier_py "https://github.com/opalescentt/haven/blob/main/classifier/classifier.py"
click node_sensitive_detector "https://github.com/opalescentt/haven/blob/main/classifier/sensitive_info_detector.py"
click node_middleware "https://github.com/opalescentt/haven/blob/main/middleware.js"

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_page,node_child_profile_page,node_staff_directory_page,node_resources_map_page,node_partner_orgs_page,node_support_groups_page,node_layout_shell,node_providers,node_navbar,node_calendar_dropdown toneBlue
class node_auth_route,node_children_api,node_child_api,node_events_api,node_registrations_api,node_staff_api,node_staff_directory_api,node_user_api toneAmber
class node_mongodb,node_child_encryption,node_child_model,node_event_model,node_registration_model,node_user_model toneMint
class node_support_parsers,node_fetch_places,node_seed_events,node_weekly_scrape toneRose
class node_classifier_py,node_sensitive_detector toneIndigo
class node_middleware toneNeutral
```

## Components

### UI layer

Next.js pages and shared presentation shell

- [Home](https://github.com/opalescentt/haven/blob/main/app/page.js): route page · Landing page for the app · `app/page.js`
- [Child profile](https://github.com/opalescentt/haven/blob/main/app/child-profile/page.js): route page · Child-facing profile and details view · `app/child-profile/page.js`
- [Staff directory](https://github.com/opalescentt/haven/blob/main/app/staff-directory/page.js): route page · Directory view for staff records · `app/staff-directory/page.js`
- [Resources map](https://github.com/opalescentt/haven/blob/main/app/resources-map/page.js): route page · Map-based resource discovery view · `app/resources-map/page.js`
- [Partners](https://github.com/opalescentt/haven/blob/main/app/partner-organizations/page.js): route page · Partner organizations listing · `app/partner-organizations/page.js`
- [Support groups](https://github.com/opalescentt/haven/blob/main/app/support-groups/page.js): route page · Support-group browsing and imported content · `app/support-groups/page.js`
- [App shell](https://github.com/opalescentt/haven/blob/main/app/layout.js): next layout · Global layout for pages · `app/layout.js`
- [Providers](https://github.com/opalescentt/haven/blob/main/app/providers.js): app context · Application-wide client providers · `app/providers.js`
- [Navbar](https://github.com/opalescentt/haven/blob/main/components/Navbar.js): shared UI · Primary navigation component · `components/Navbar.js`
- [Calendar picker](https://github.com/opalescentt/haven/blob/main/components/ui/calendar_dropdown.js): shared UI · Event date selection control · `components/ui/calendar_dropdown.js`

### Server API

Route handlers that expose the application domain

- [Auth](https://github.com/opalescentt/haven/blob/main/app/api/auth/[...nextauth]/route.js): nextauth route · Session and login handling · `app/api/auth/[...nextauth]/route.js`
- [Children API](https://github.com/opalescentt/haven/blob/main/app/api/children/route.js): route handler · Collection endpoint for child records · `app/api/children/route.js`
- [Child API](https://github.com/opalescentt/haven/blob/main/app/api/children/[id]/route.js): route handler · Single-child endpoint · `app/api/children/[id]/route.js`
- [Events API](https://github.com/opalescentt/haven/blob/main/app/api/events/route.js): route handler · Event retrieval and management · `app/api/events/route.js`
- [Regs API](https://github.com/opalescentt/haven/blob/main/app/api/registrations/route.js): route handler · Registration and attendance records · `app/api/registrations/route.js`
- [Staff API](https://github.com/opalescentt/haven/blob/main/app/api/staff/route.js): route handler · Staff-facing records · `app/api/staff/route.js`
- [Directory API](https://github.com/opalescentt/haven/blob/main/app/api/staff-directory/route.js): route handler · Staff directory data endpoint · `app/api/staff-directory/route.js`
- [User API](https://github.com/opalescentt/haven/blob/main/app/api/user/route.js): route handler · User profile data endpoint · `app/api/user/route.js`

### Data layer

MongoDB models and server-side protection

- [MongoDB](https://github.com/opalescentt/haven/blob/main/lib/mongodb.js): database connector · Database connection layer · `lib/mongodb.js`
- [Child crypto](https://github.com/opalescentt/haven/blob/main/lib/childEncryption.js): security util · Application-layer encryption for child data · `lib/childEncryption.js`
- [Child model](https://github.com/opalescentt/haven/blob/main/models/Child.js): mongoose model · Child record schema · `models/Child.js`
- [Event model](https://github.com/opalescentt/haven/blob/main/models/Event.js): mongoose model · Event record schema · `models/Event.js`
- [Registration model](https://github.com/opalescentt/haven/blob/main/models/Registration.js): mongoose model · Registration schema · `models/Registration.js`
- [User model](https://github.com/opalescentt/haven/blob/main/models/User.js): mongoose model · User schema · `models/User.js`

### Ingestion

External import, scraping, and scheduled refresh jobs

- [Support parsers](https://github.com/opalescentt/haven/blob/main/app/support-groups/alliancecares_parser.cjs): import parsers · External support-group content normalization · `app/support-groups/alliancecares_parser.cjs`
- [Place fetcher](https://github.com/opalescentt/haven/blob/main/scripts/fetch-places.js): enrichment script · External location data enrichment · `scripts/fetch-places.js`
- [Event seeder](https://github.com/opalescentt/haven/blob/main/scripts/seed-events.js): seed script · Populates event data · `scripts/seed-events.js`
- [Weekly scrape](https://github.com/opalescentt/haven/blob/main/.github/workflows/weekly-scrape.yml): workflow · Scheduled content refresh automation · `.github/workflows/weekly-scrape.yml`

### Analysis tools

Offline Python classification and sensitive-info detection

- [Classifier](https://github.com/opalescentt/haven/blob/main/classifier/classifier.py): python tool · Offline text classification utility · `classifier/classifier.py`
- [Sensitive detector](https://github.com/opalescentt/haven/blob/main/classifier/sensitive_info_detector.py): python tool · Sensitive information detection utility · `classifier/sensitive_info_detector.py`

### Other components

- [Middleware](https://github.com/opalescentt/haven/blob/main/middleware.js): route gate · Route protection and session-aware access control · `middleware.js`

## Connections

- App shell → Navbar: renders
- App shell → Providers: wraps
- Home → Navbar: uses
- Child profile → Children API: loads
- Staff directory → Directory API: loads
- Resources map → Place fetcher: shows data from
- Partners → User API: loads
- Support groups → Support parsers: consumes
- Support groups → Weekly scrape: refreshed by
- Calendar picker → Events API: filters
- Auth → User model: authenticates
- Middleware → Auth: guards
- Children API → MongoDB: queries
- Child API → MongoDB: queries
- Events API → MongoDB: queries
- Regs API → MongoDB: queries
- Staff API → MongoDB: queries
- Directory API → MongoDB: queries
- User API → MongoDB: queries
- Children API → Child model: uses
- Child API → Child model: uses
- Child API → Child crypto: protects
- Events API → Event model: uses
- Regs API → Registration model: uses
- User API → User model: uses
- Event seeder → Event model: seeds
- Place fetcher → Resources map: enriches
- Classifier → Sensitive detector: uses
- Classifier → Support parsers: analyzes
