CareConnect - Architecture Overview
Tech Stack
- Framework: Next.js 15 (App Router)
- Language: TypeScript
- Styling: Tailwind CSS v4 + Radix UI
- Database: Supabase (PostgreSQL + Vector)
- Internationalization:
next-intl(Support for EN, FR, AR, ZH-Hans, ES, PT, PA) - Testing: Playwright (E2E), Vitest (Unit)
Directory Structure
app/: Next.js App Router pages and API routes.[locale]/: Localized routes.api/v1/: RESTful API endpoints. (See OpenAPI Spec)[locale]/offline/: PWA offline page (Workbox navigation fallback targets/offline).worker.ts: Semantic search Web Worker.components/: UI components.ui/: Standardized primitives (Button, etc.).hooks/: Custom React hooks (useSearch,useServices).lib/: Utility functions (API helpers, search logic).types/: TypeScript definitions.messages/: Localization dictionaries (EN, FR, AR, ZH-Hans, ES, PT, PA).docs/: Project documentation.
Core Concepts
Search Architecture
The search system uses a hybrid approach:
graph TD
A[User Query] --> B{Keyword Search}
B -- Results Found --> C[Re-rank based on Relevance]
B -- Low/No Results --> D[Fuzzy Search Suggestion]
C --> E[Lazy Semantic Search Worker]
E --> F[Neural Re-ranking]
F --> G[Final Results Display]
A --> H[Search API POST - v16.0 Hybrid]
H --> I[Server-side Hybrid Scoring]
I --> G - Instant Keyword Search: Filters results locally/via basic db queries for immediate feedback.
- Fuzzy Search ("Did you mean?"): If results are low, the Levenshtein algorithm suggests alternative queries based on service names and tags.
- Lazy Semantic Search: Loads the optional browser embedding worker in the background and upgrades local search with vector similarity only after the model initializes successfully. If worker initialization or embedding generation fails, the app fails closed to keyword-only search instead of emitting synthetic vectors.
- Search API (v16.0 Enhancements): A server-side alternative (
POST /api/v1/search/services) that implements complex ranking factors including authority tiers, data completeness boosts, intent targeting, and continuous proximity decay. It uses a hybrid strategy: fetching the full filtered candidate set from the DB and scoring it in-memory using the same TypeScript pipeline as local mode so synthetic-query and intent-only matches are preserved. The shared request contract now carriescategory,location, andopenNowfilters in both modes, including empty-query "open now" browsing. - Governance Freshness Enforcement: Both local and server search exclude records that fall outside the 180-day public-visibility window so stale listings do not keep ranking with only a soft penalty.
- Result Explainability: Public result cards and linked detail pages can surface normalized match reasons so users can inspect why a service ranked for their query.
Search Modes
The application supports two search modes, controlled by NEXT_PUBLIC_SEARCH_MODE:
- Local (Default): Downloads a compressed JSON bundle of all services. Search logic runs entirely in the browser. Best for offline support and zero-latency typing.
- Server: Sends
POSTrequests to the Librarian API. The server executes the query and returns results. Best for large datasets (>1000 items) and devices with limited RAM. (Note: Server mode does not load the JSON bundle, saving bandwidth).
AI Assistant Architecture
- Engine:
@mlc-ai/web-llm(WebGPU) running in a Web Worker for UI responsiveness. - Strategy: "LLM-as-Search" (query rewrite/expansion) + deterministic rendering of search results.
- Privacy:
- Local-Only: Inference runs entirely in the user's browser.
- No Data Egress: Queries never leave the device.
- Zero-Knowledge: Server knows that a user is chatting, but not what they are saying.
- Zero-Logging Search (v13.0): When using Server Search, queries are sent as
POST(no URL logs). Query-, location-, and open-now-driven responses areCache-Control: no-store; only anonymous category-only browse responses may use short public caching. The databaseservices_publicview enforces a strict data boundary. - Share Target Handoff:
POST /api/v1/sharestores shared search text in a short-lived first-party cookie and redirects without?q=so sensitive share text does not land in URLs, history, or referrers. - Lifecycle:
- Opt-In: Model download only triggered by explicit user action.
- Idle Cleanup: VRAM released after 5 minutes of inactivity.
Privacy-Preserving Personalization
- Client-Side Profile: User demographics (Age, Identities) stored in
localStorage(careconnect_user_context). - Zero PII: No user accounts, login, or cookies required for basic personalization.
- Local Eligibility: "Likely Qualify" checks run locally by parsing cached service data against the local profile.
- Identity Boosting: Search ranking adjustments happen on the client-side
WebWorker.
Data Pipelines
- Source of Truth: Manually curated service records remain authoritative. In development they live in
data/services.json; in production the app reads from Supabase when configured, with local JSON fallback when the database is unavailable. - DB-Authoritative Runtime Reads: When Supabase is available, runtime search/detail loading now reads directly from the database contract instead of overlaying live search metadata from local JSON snapshots. Curated JSON remains the no-DB/offline fallback and the import source for backfills. Existing environments must run the rollout-safe curated backfill once after the contract change so blank DB runtime fields are populated without overwriting live values.
sequenceDiagram
participant Curators as Curators + Research Inputs
participant Import as Validation + Import Scripts
participant DB as Verified Database
participant Embed as Embedding Generator
Curators->>Import: Verified JSON / CSV / seed files
Import->>Import: Normalize & validate schema
Import->>DB: Upsert curated records
DB->>Embed: Pull Verified Listings
Embed->>DB: Store Vector Embeddings
DB->>Client: JSON/API Delivery - Ingestion:
- Human-reviewed JSON, CSV, and municipal/provider seed files are validated before import.
scripts/import/geojson-import.ts: Generic utility for ingesting municipal (City of Kingston) and specialized (Indigenous/Faith) seed files.generate-embeddings.ts: Generates logical-semantic embeddings at build time.- Versioning:
generate-changelog.tstracks diffs between syncs. - Offline Export Contract:
/api/v1/services/exportsanitizes the public payload, derives a stable SHA-256 fingerprint for bothversionandETag, and offline sync clears the in-memory service cache after a successful refresh so newly synced data is visible immediately.
User Feedback & Impact Loop (v14.0)
- Architecture: Privacy-preserving feedback system.
- Pipeline: Client (
FeedbackWidget) -> API (/api/v1/feedback) -> Supabase (feedbacktable). - Aggregations: Database materialized views (
feedback_aggregations,unmet_needs_summary) provide performant metrics for the/impactpage and Partner Dashboard. - Privacy: No PII, cookies, or persistent IDs are stored. Rate limiting is handled in-memory.
Equity-First Access (v14.0)
- Localization Parity: Full UI translation coverage for all 7 supported locales. Mandatory EN/FR parity for all service data.
- Simplified Views: Optional plain-language summaries (Grade 6-8 reading level) for high-impact services, stored in
plain_language_summaries. - Low-Bandwidth Outputs: Printable "Resource Cards" optimized for physical distribution and accessibility.
- Printable Card Privacy: Printable cards escape interpolated service content and render QR codes locally as inline data URLs instead of calling third-party QR hosts.
Visible Verification & Trust Signals (v14.0)
- Provenance:
TrustPaneldisplayslast_verifieddates, verification methods, and source provenance to build user confidence. - Verification Levels:
L1: Basic verification.L2: Manual verification by CareConnect team.L3: Partner-claimed and verified.L4: Governance-level policy concept for future partner/audit workflows; not currently represented in runtime types or search scoring.- Partner Update Workflow: Structured request-approval loop via
service_update_requestsensures data integrity while engaging service providers.
Push Notifications
- Technology: Web Push API + Service Worker (
public/sw.js, pluspublic/custom-sw.jsfor app-specific hooks). - Flow: User Opt-In -> Service Worker Subscribes -> Endpoint stored in
push_subscriptions-> Server-side trigger via VAPID keys. - Privacy: No PII linked to subscriptions. User can revoked at any time via browser settings.
Automated Maintenance Bots
- URL Health Bot: Monthly check of all service URLs (
scripts/health-check-urls.ts). When a provider's public page is bot-hostile from CI, the checker can fall back to a small allowlist of official provider override probes without changing the curated public URL stored in service data. - Phone Validator: Connectivity checks using Twilio Lookup API (
scripts/validate-phones.ts). - Automation: GitHub Actions maintain quiet-by-default governance issues and prefer job summaries over routine PR comments.
- Finding Workflows: Health and staleness workflows reuse one bot issue per lane, update it while action is needed, and close it automatically after the condition clears. The monthly URL health workflow also writes a readable summary of broken and inconclusive checks into the Actions run.
- Reminder Workflows: Monthly/quarterly verification reminders reuse one issue per lane, reopen it for the new cycle, and keep a compact recent-cycle history instead of opening a new issue every run.
Database Security & Row Level Security (RLS)
- Security Model: Supabase PostgreSQL with Row Level Security ensures data isolation and privacy.
- Public Views:
services_publicview created withsecurity_invoker = trueto use invoker's permissions (not definer's). - Hardened Policies: All INSERT policies validate foreign keys (e.g.,
service_id IN (SELECT id FROM services_public)) to prevent spam and invalid data. - Performance Optimizations: Auth function calls wrapped in scalar subqueries
(SELECT auth.uid())to avoid per-row re-evaluation. - Policy Consolidation: Separate policies for SELECT/INSERT/UPDATE/DELETE to avoid "Multiple Permissive Policies" performance warnings.
- Public Transparency: Aggregated metrics are exposed via Standard Views (
feedback_aggregations,unmet_needs_summary) that wrap underlying Materialized Views (mat_*). These wrappers enforcesecurity_invoker = trueto ensure the query runs with the user's permissions, satisfying security audits while maintaining API compatibility. - Documentation: See Database Security Guide for complete RLS policy documentation.
- Testing: RLS policies verified via
tests/integration/rls-policies.test.ts.
Partner Dashboard & RBAC
- Access Control: Role-Based Access Control (RBAC) implemented via
organization_memberstable. - Roles:
owner,admin,editor,viewer. - Functions: CRUD operations for listings, member invites (invite/accept flow), and analytics viewing.
- Multi-Lingual Content: Self-service editing for English and French fields (local services are EN/FR only).
- Mutation Guardrails: Partner-facing write APIs use an explicit allowlist for editable fields.
ownerandadmincan mutate any service in their organization,editoris limited to compatible ownership signals on services they created, andvieweris denied. Direct partnerPUT/PATCHwrites now persistaccess_scriptandaccess_script_frthrough the typed service storage contract while still rejecting privileged/unknown fields.
Data Flow
- Services: Fetched via
/api/v1/services. Cached using SWR-like strategies in hooks. - Analytics: Aggregate-only search events (
locale+resultCount) are posted to/api/v1/analytics/searchasynchronously. Raw query text, category, and location are not stored.
v22 Phase 0 Pilot Instrumentation (Internal)
- Purpose: Capture pilot-only connection outcome signals before Phase 1 feature rollout.
- Internal Endpoints:
POST /api/v1/pilot/events/contact-attemptPOST /api/v1/pilot/events/connectionPOST /api/v1/pilot/events/referralPOST /api/v1/pilot/events/service-statusPOST /api/v1/pilot/events/data-decay-auditPOST /api/v1/pilot/events/preference-fitPATCH /api/v1/pilot/events/referral/{id}POST /api/v1/pilot/scope/servicesPOST /api/v1/pilot/metrics/recomputePOST /api/v1/pilot/integration-feasibilityGET /api/v1/pilot/metrics/scorecard- Security Model:
- Authenticated session required for all pilot endpoints.
- Organization-scoped authorization enforced for event writes and scorecard reads.
- Admin authorization required for integration feasibility decision writes.
- Privacy Constraints:
- Request payload validation rejects disallowed keys (
query,query_text,message,user_text,notes). - Raw query text is never accepted into pilot event contracts.
- Repeat-failure attribution uses opaque
entity_key_hashvalues rather than raw identifiers. - Resilience:
- Pilot DB operations use circuit-breaker-wrapped storage access.
- If pilot tables are not present, endpoints fail with explicit
501responses to prevent silent data loss. - Metric recompute writes canonical snapshots to
pilot_metric_snapshots; scorecard reads stay snapshot-based. - Readiness Reporting:
pilot_service_scopeis the canonical scoped-service source for bounded pilot readiness audits.npm run audit:pilot-readiness -- --pilot-cycle-id <id> [--org-id <uuid>]exports scoped JSON, Markdown, and CSV artifacts without mutating curated service data.docs/implementation/v22-pilot-readiness/contains the scope-file-first handoff bundle, including the runbook andscope.template.jsonfor cases where a committed pilot cycle does not yet exist.
Routing & Discovery
- Public Routes:
/service/[id]: Rich detail page./submit-service: Public crowdsourcing form./dashboard: Partner portal./about: Project mission and impact metrics. Includes Katarokwi Land Acknowledgment./about/partners: Data source transparency and verification process.- Provincial Services Discovery:
is_provincialflag allows services to be promoted in search results globally.- Provincial services display a "Province-Wide" badge for clarity.
- Language Selection:
LanguageSelectorcomponent inHeaderprovides 7-locale switching.- Arabic triggers RTL (Right-to-Left) direction in root layout.
- Internal Links:
ServiceCardnow links to internal detail pages instead of external URLs.
Partner Claim Workflow
- Claim Logic: Unclaimed services can be claimed by authenticated organizations.
- Verification: Claiming a service automatically elevates its status to
L1. - Atomic Operations:
lib/services.tshandles the claim logic with database consistency checks.
Hooks Architecture
We use a modular hook system to separate concerns:
- Search Hooks:
useSearchcoordindates state,useServiceshandles logic, anduseSemanticSearchmanages the worker. - Utility Hooks: Generic hooks for
localStorageandGeolocationensure SSR safety and consistency.
Logging & Monitoring
- Logger Utility: Located in
lib/logger.ts. Use instead ofconsole.log. - Error IDs: The Error Boundary generates unique IDs (e.g.,
ERR-K9X2J1) for cross-referencing logs with user reports. - Health Visibility: In production,
/api/v1/healthexposes only basic public status and has no SLO side effects. Detailed public-probe execution lives at/api/v1/health/probe, which requiresAuthorization: Bearer ${HEALTH_PROBE_TOKEN}and is the only path that records uptime samples and evaluates SLO alerts.
User Interface & Accessibility
- High Contrast Mode: Global state managed via
useHighContrasthook, applying.high-contrastclass and CSS variable overrides. - Print Optimization: Specific
@media printstyles inglobals.cssandPrintButtoncomponent for physical delivery of information. - Data Freshness:
FreshnessBadgeprovides visual cues on the reliability of data based onlast_verified/provenance.verified_at, including an explicit expired state once a record crosses the 180-day governance limit. - Offline Safety Surfaces:
OfflineSnapshotStatusreads IndexedDB sync metadata (lastSync) and shows snapshot age plus stale-data warnings on offline surfaces when cached data may be outdated. - External Maps: Service-detail pages keep Google Maps loading opt-in. Directions remain available, but third-party map previews do not load until the user explicitly requests them.
- Search Explainability Surfaces:
ServiceMatchReasonsshows deduplicated match reasons on result cards and on detail pages when the user follows a search result with ranking context attached.
Development
npm run dev: Start local server.npm run test: Run the default Vitest suite.npm run test:db: Run real DB-backed retrieval and policy tests.npm run test:e2e:local: Run partial E2E tests (CI handles full suite).AGENTS.md: Contributor and local workflow guidance.docs/development/testing-guidelines.md: Detailed testing guidance.