RememberME is a memory layer for AI-assisted citizen services. It gives authenticated assistants durable, consent-aware context—so residents are not asked the same eligibility questions, ID details, and case facts on every new chat session.
The product pairs a Vite + React marketing and dashboard experience with a Next.js (App Router) API backed by Supabase (Auth, Postgres, Storage). Optional context resolution APIs format profile and document metadata for safe injection into LLM prompts.
Public portals and chatbots often behave like amnesia: each visit starts cold. RememberME is designed so the same resident, once verified, can carry forward structured context (name, contact, address, credential fields, document references) to the next conversation—reducing repetition, tokens, and time-to-resolution.
| Mode | What residents experience |
|---|---|
| Without memory | The assistant asks again for information the agency already holds or the resident already provided. Threads are longer; friction and drop-off increase. |
| With memory | After sign-in, resolved context can be supplied to the model (with masking rules). The assistant acknowledges prior facts and moves the task forward. |
| Without persistent memory | With memory layer |
|---|---|
![]() |
![]() |
High-level flow from resident touchpoint to assistant response:
flowchart LR
subgraph Resident
R[Resident]
end
subgraph Client["RememberME frontend (Vite)"]
H[Marketing + demos]
D[Dashboard / credential UI]
end
subgraph API["Next.js API"]
A[Auth: signup / login]
P[Profile + PATCH]
C[Context resolve]
G[Geocode proxy]
end
subgraph Data["Supabase"]
Auth[(Auth)]
DB[(Postgres profiles)]
St[(Storage: documents / portrait)]
end
subgraph Assistant["AI channel"]
L[LLM / chat UI]
end
R --> H
R --> D
H --> A
D --> A
D --> P
D --> G
A --> Auth
P --> DB
P --> St
D --> P
L --> C
C --> P
C --> DB
P --> Auth
Credential dashboard flow (document-style UI, field map, address map):
flowchart TB
subgraph SignIn["1. Access"]
SI[Sign in via Auth modal]
end
subgraph Dash["2. Dashboard"]
PH[Portrait upload]
ED[Edit / save profile + license fields]
FM[Field map: inline fill + sync]
MAP[Address → geocode → map + OSM link]
ID[Smart document import placeholder]
end
subgraph Persist["3. Persistence"]
API[PATCH /api/profile]
Photo[POST /api/profile/photo]
Doc[POST /api/profile/id-document]
end
SI --> PH
SI --> ED
ED --> FM
FM --> MAP
ED --> API
PH --> Photo
ID --> Doc
| Path | Role |
|---|---|
frontend/ |
Vite + React SPA: marketing site, auth modals, credential dashboard, Leaflet address map. |
backend/ |
Next.js App Router: REST-style API routes, Supabase server client, OpenAPI/Swagger. |
backend/sql/ |
Postgres migrations and schema notes (run in Supabase SQL editor). |
- Node.js 20+
- npm
- Supabase project (URL + anon/publishable key for client-side flows; backend uses server env)
cd backend
npm installcp .env.local.example .env.localConfigure (example—use your project values, never commit secrets):
NEXT_PUBLIC_SUPABASE_URL=https://YOUR_PROJECT.supabase.co
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY=your_publishable_key
FRONTEND_ORIGIN=http://localhost:5173npm run devAPI base: http://localhost:3000
| Method | Path | Purpose |
|---|---|---|
| GET | /api/health |
Liveness |
| POST | /api/signup |
Register via Supabase Auth |
| POST | /api/login |
Session via Supabase Auth |
| GET | /api/profile |
Authenticated profile + license + signed URLs |
| PATCH | /api/profile |
Update display names, phone, address, license fields |
| POST | /api/profile/photo |
Portrait upload (Storage + profile_photo_path) |
| POST | /api/profile/id-document |
ID scan upload (smart-import narrative) |
| GET | /api/geocode |
?q= — server-side geocode proxy (Nominatim) |
| POST | /api/demo-requests |
Contact / inquiry rows (demo_requests table) |
| GET | /api/context/parameters |
Discoverable context keys |
| POST | /api/context/resolve |
Resolve allowlisted parameters for prompts |
| GET | /api/openapi |
OpenAPI 3.1 JSON |
| GET | /api/docs |
Swagger UI |
Context route examples and response shapes are unchanged from the detailed curls in the Context API section below.
backend/sql/001_profiles_and_id_storage.sql— profiles, storage-related columns, demo_requests, RLS patterns.backend/sql/002_profile_photo_display_names.sql— optional portrait + display name columns (also folded into section 4 of001for greenfield installs).
Schema documentation for AI-assisted changes: backend/sql/SUPABASE_SCHEMA_REFERENCE.md.
cd frontend
npm installDefault dev setup proxies /api to http://localhost:3000 (see frontend/vite.config.js).
VITE_API_BASE_URL=http://localhost:3000
# Match GitHub Pages project-site path when testing production build locally:
# VITE_BASE_PATH=/RememberME/npm run devApp: http://localhost:5173 — use the Without memory / With memory control to compare the two demo videos.
npm run buildThe UI is static after vite build; GitHub Pages hosts frontend/dist. The Next.js API is not on Pages—host the backend separately (Vercel, Railway, Fly.io, etc.) and point the SPA at it.
- Pages: Repository Settings → Pages → Build and deployment
- Source: GitHub Actions (not “Deploy from a branch”).
- First deploy: Merge the workflow (
.github/workflows/deploy-github-pages.yml) tomain, or run Actions → Deploy frontend to GitHub Pages → Run workflow. - Site URL:
https://<owner>.github.io/<repository>/
Example:https://octocat.github.io/RememberME/
Add a repository secret (Settings → Secrets and variables → Actions → New repository secret):
| Name | Value |
|---|---|
VITE_API_BASE_URL |
Public base URL of your deployed API, no trailing slash (e.g. https://rememberme-api.vercel.app) |
Rebuild/redeploy after changing this secret. The workflow passes it into Vite at build time.
Set FRONTEND_ORIGIN (or your backend’s equivalent allowlist) to your Pages origin, e.g.:
FRONTEND_ORIGIN=https://octocat.github.ioIf your corsHeaders compares exact origins, you may need to allow the full Pages URL including path—adjust backend/lib/http.js if necessary so preflight from the static site succeeds.
By default the workflow sets base to /<repository>/. For a user site at the domain root (https://username.github.io/ with a repo named username.github.io), set a repository variable:
| Name | Value |
|---|---|
VITE_PAGES_BASE |
/ |
(Trailing slash is normalized in the workflow.)
cd frontend
VITE_BASE_PATH=/RememberME/ npm run build
npx vite preview --base /RememberME/Open the printed URL so asset paths match GitHub Pages.
Terminal 1 — API
cd backend && npm run devTerminal 2 — UI
cd frontend && npm run devOpen http://localhost:5173, sign in, and open Dashboard (#dashboard) for the credential experience.
Discover parameters:
curl -X GET http://localhost:3000/api/context/parameters \
-H "Authorization: Bearer <SUPABASE_ACCESS_TOKEN>"Resolve (default masking of high-sensitivity fields):
curl -X POST http://localhost:3000/api/context/resolve \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <SUPABASE_ACCESS_TOKEN>" \
-d '{
"parameters": [
"first_name",
"drivers_license.license_number",
"documents.id_document_path"
]
}'Example response shape:
{
"requested_parameters": ["first_name", "drivers_license.license_number"],
"resolved": {
"first_name": "Taylor",
"drivers_license.license_number": "[REDACTED]"
},
"context_text": "first_name: Taylor\ndrivers_license.license_number: [REDACTED]",
"context_tokens_estimate": 16,
"masked_fields": ["drivers_license.license_number"],
"resolvedNested": {
"first_name": "Taylor",
"drivers_license": {
"license_number": "[REDACTED]"
}
},
"missing": []
}- Treat publishable keys as public; keep service role keys server-only.
POST /api/context/resolvesupports explicit opt-in for sensitive fields (include_sensitive); default behavior masks high-risk values.- ID and portrait assets use signed URLs with short TTLs; align Storage RLS with your threat model.
This repository is maintained for the RememberME pilot. For contribution guidelines and licensing, add a CONTRIBUTING.md and LICENSE as your organization requires.

