Last updated: 2026-03-09
Red Door is a cruise-first social platform with:
- A static web frontend (GitHub Pages-compatible)
- An optional Express + WebSocket backend for multi-user/networked behavior
- Optional PostgreSQL persistence and optional S3-compatible object storage
The active frontend product emphasis is Cruise mode. Date and Hybrid logic exists server-side and in services/tests, with frontend behavior still cruise-first.
- Frontend: React 18, TypeScript, Vite 5, MapLibre GL
- Backend: Node.js, Express, WebSocket (
ws), TypeScript (tsxruntime) - Data: In-memory + JSON persistence fallback, optional PostgreSQL (
pg) - Media: Local object storage fallback, PostgreSQL object storage, or S3-compatible object storage
- Tests: Jest + ts-jest
- Guest session creation (
/auth/guest) - Registered account flow (
/auth/register,/auth/login) - Email verification and resend flow (
/auth/verify-email,/auth/resend-verification) - 18+ age-gate verification (
/auth/verify-age) - Session resolution endpoint (
/session) - Role support with admin auto-promotion via configured admin emails
- Ban/unban enforcement (admin)
- Supported modes:
cruise,date,hybrid - Authoritative mode endpoints:
GET /modePOST /modePOST /mode/hybrid-opt-in
- Service-level enforcement for invalid transitions, anonymous restrictions, and age gate restrictions
- Self profile read/write (
GET/PUT /profile/me) - Public profile listing + single profile read
- Profile media reference mutation (
PUT /profile/media/references) - Upload initiation + completion (
/profile/media/initiate,/profile/media/complete) - Public media URL retrieval (
/media/public/:mediaId/url) - Media ownership and metadata validation via service layer
- Public postings (ads/events): list/create + event invite/response/join-request flows
- Cruising spots: list/create/check-in/check-in listing/spot actions
- Favorites: list + toggle
- Submissions (stories): list/create/view/rate
- Promoted profiles: payment start/confirm/create/list
- Chat send/list/list threads/read receipts
- Chat media initiate + URL retrieval
- Mode-aware chat policy enforcement
- Cruise-mode expiry behavior in service tests
- WebSocket gateway with auth handshake, heartbeat, payload limits, and broadcast filtering
- Call signaling endpoint (
/call/signal)
- Global block/unblock/list blocked
- Report user/message endpoints
- Admin moderation endpoints for users, cruise spots, postings, and submissions
- Admin DB health diagnostics endpoint (
/admin/db/health) - Deterministic explicit error codes mapped to HTTP statuses
- Location privacy rules enforced in presence service tests (server-side randomization expectations)
- Multi-tab app shell (
discover,threads,ads,groups,cruise,profile,settings,submissions,promoted) - Map + chat discovery views
- Travel/location preference and permission request plumbing
- API endpoint resolution via build-time constants and local/remote fallback logic
- WebSocket URL derivation logic for realtime support
- GitHub Pages static page sync support for route HTML files
The following frontend/backend behavior changes are now implemented and live in main:
- Mobile bottom bar redesigned to focused overlays:
- Inbox overlay with tabs for Chat Grid, Threads, Pinned, Cruising Spots, Groups
- Public Ads board as a dedicated right-side bottom bar action
- Top bar redesigned with:
- RED DOOR logo on left
- Profile preview action in center
- Filter and account-function overlays from top
- Travel mode improvements:
- Travel picker instruction moved to in-map overlay (no extra black space)
- Map click now asks for confirmation before temporary relocation
- Group creation flow improvements:
- Date, Start Time, End Time inputs now labeled
- Start/End rendered side-by-side and validated (
end > start, future end)
- Chat/inbox behavior upgrades:
- Location message preview now reads
Location Sent - Group-chat invite flow supports accept/decline end-to-end notifications
- Invite recipient message text uses
You’ve received a Chat Invite - Group thread title state now reflects
+1context - Unread badges now decrement correctly when messages are read
- Bottom inbox badge no longer resets on tab/screen changes
- Chat-grid unread/online visual signals refined
- Location message preview now reads
- Data persistence behavior:
- Cruising spots persist across sessions
- Groups expire at configured end time
- Ads persist and roll over with 12-hour retention behavior
- Moderation/safety visibility updates:
- Blocked users are removed from map/chat grid visibility
- Banned users are filtered from public profile and active presence endpoints
- Profile/settings cleanup:
- Duplicate Discreet/Travel messaging removed
- Internal media ID labels removed from user-facing settings UI
- Red-theme migration and mobile polish:
- Blue accents replaced with red variants
- Overflow/horizontal scroll issues reduced across overlay layouts
- Icon-only controls integrated from new asset set
- Auth flow update:
- Registered users auto-verify age after registration/login path where age is known
- Separate age-gate card is now guest/anonymous-only
- Error handling update:
- Error banners are now scoped to the active section/tab and no longer leak into unrelated screens (including Discover map)
The backend currently exposes health/config, auth, profiles/media, favorites, public postings/events, cruising spots, submissions, admin moderation/diagnostics, promoted profiles, mode/presence/matching/dating feed, chat, call signal, block list, and reporting endpoints.
Primary implementation: backend/src/server.ts
- Node.js 20+
- npm 10+
JWT_SECRETfor backend auth
- Backend/runtime:
PORTJWT_SECRETCORS_ALLOWED_ORIGINSADMIN_EMAILSREQUIRE_DATABASEDATABASE_URL/NEON_DATABASE_URLDATABASE_SSL
- Frontend build/runtime defines:
DUALMODE_API_BASE_PATHDUALMODE_WS_URLDUALMODE_DEFAULT_CENTER_LATDUALMODE_DEFAULT_CENTER_LNG
- Dev orchestration:
DUALMODE_BACKEND_ORIGINDUALMODE_BACKEND_PORTDUALMODE_FRONTEND_PORTDUALMODE_DEV_HMRDUALMODE_DEV_WATCHDUALMODE_DEV_WATCH_POLLDUALMODE_DEV_WATCH_POLL_INTERVAL_MS
- Optional integrations present in code/env:
- SMTP:
SMTP_HOST,SMTP_PORT,SMTP_SECURE,SMTP_USER,SMTP_PASS,SMTP_FROM - Twilio:
TWILIO_ACCOUNT_SID,TWILIO_AUTH_TOKEN,TWILIO_FROM_NUMBER - Google Sheets webhook:
GOOGLE_SHEETS_WEBHOOK_URL - S3-compatible:
S3_ENDPOINT,S3_REGION,S3_BUCKET,S3_ACCESS_KEY_ID,S3_SECRET_ACCESS_KEY,S3_FORCE_PATH_STYLE
- SMTP:
Use .env.example as baseline.
The early-access homepage can forward each new signup to a Google Sheet through a deployed Google Apps Script web app.
- Create a Google Sheet with a tab named
Signups. - Open
Extensions -> Apps Script. - Paste this script:
function doPost(e) {
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Signups");
const body = JSON.parse(e.postData.contents);
sheet.appendRow([
new Date(),
body.name || "",
body.email || "",
body.membershipCode || "",
body.createdAtMs || "",
body.source || "red-door"
]);
return ContentService
.createTextOutput(JSON.stringify({ ok: true }))
.setMimeType(ContentService.MimeType.JSON);
}- Deploy the script as a web app:
- Execute as:
Me - Who has access:
Anyone
- Execute as:
- Copy the deployment URL into
GOOGLE_SHEETS_WEBHOOK_URL.
New early-access signups will continue to save locally in the backend store and will also be forwarded to Google Sheets. If the Google webhook fails, signup still succeeds and the server logs the sync failure explicitly.
Install:
npm installFrontend dev (Vite custom launcher):
npm run devLegacy fallback dev mode (no HMR/watch):
npm run dev:legacyBackend + frontend together:
DUALMODE_API_BASE_PATH=/api DUALMODE_WS_URL=/ws JWT_SECRET=dev npm run dev:stackBuild:
npm run buildPages static sync flow:
npm run build:pagesThe following were run successfully on 2026-03-09:
npm test
npm run typecheck
npm run build- Test suites: 16 passed / 16 total
- Tests: 207 passed / 207 total
- Coverage summary:
- Statements: 94.33%
- Branches: 85.57%
- Functions: 96.55%
- Lines: 98.57%
- Critical services with 100% branch coverage in latest run:
matchingService.tsmodeService.tspresenceService.ts
Command run:
npm audit --audit-level=lowCurrent findings:
rollupadvisory (high) via Vite dependency chainesbuildadvisory (moderate) via Vite dependency chainfast-xml-parseradvisory (moderate) via AWS SDK XML builder chain- Total reported: 5 vulnerabilities (2 low, 2 moderate, 1 high)
Notes:
- Auto-fix path indicates potential breaking upgrade (
vite@7.x) if usingnpm audit fix --force.
Based on git log -n 30 --oneline:
b291817auth: auto-verify age after register and guest-only age gate24cc1fatravel: confirm relocation after map selectione667cb0chat: keep inbox badge driven by app-level unread sync0021fcdui: scope errors to active section and suppress discover carryover5a646e0map: overlay travel picker hint to remove bottom spacerd483314ui: add group start/end inputs and tighten ban/block visibility0c40ccechat: fix invite flow, location preview, and unread decrementd670ccaupdates1506615ui: center chat action sheet and tighten top icon controlsef41fbfchat ui: fix action sheet clipping and camera/mic integrations548f0a3ui/chat: unread-highlight grid, 12h ad retention, nav layout polish4a1d5bdchat/groups: anon labels, unread decrement, persistent spots and expiring groupsd41e9acui: remove mobile overflow and retheme remaining blue accentsd216a7cui: move session errors into active tab overlays41f2e65frontend: darken bars and make mobile discover map full-heighte32d418frontend: increase nav and overlay icon sizes21d5467frontend: enlarge ui icons and remove visible icon button chromeaec2dd0frontend: move ui icons into src assets for CI-safe imports2225f14frontend: replace nav controls with icon-only asset buttonsffa97dffrontend: redesign topbar and add expanded top-down filtersd02d4ecfrontend: retheme overlays red and remove mobile horizontal overflow77c6b43frontend: add mobile ads board overlay and third nav buttone1b3c4ffrontend: add two-button mobile nav with tabbed inbox overlayd5dae03fix: show authenticated action errors and tighten posting validation3aa7529test: stabilize auth coverage threshold in CIbc22adafix: restore posting and spot creation flows3b3fc06chore: push all pending updates36db5fcci: harden scripts and align workflow gatesf9754adAdd AI governance, architecture docs, and codex workflow files7592d90fix promoted profiles create/sync behavior
CI(.github/workflows/ci.yml)- Runs on push + pull request
- Executes:
npm ci,npm run typecheck,npm run test:coverage,npm run build,npm audit --omit=dev --audit-level=high
Quality Gates(.github/workflows/quality-gates.yml)- Runs on pull requests to
mainand manual trigger - Executes: typecheck, coverage tests, build, high-level audit
- Runs on pull requests to
Deploy GitHub Pages(.github/workflows/pages.yml)- Runs on push to
mainand manual trigger - Builds site from source (
npm run build) - Publishes
dist/via official Pages actions (configure-pages,upload-pages-artifact,deploy-pages)
- Runs on push to
- Production build:
npm run build
- Build + sync static pages artifacts:
npm run build:pages
- Preview production build locally:
npm run preview
- Pages deploy now uses workflow artifacts from source build (not committed static dist snapshots).
- If Pages deploy fails:
- Verify CI/build passed on the same commit
- Confirm
dist/generation succeeds locally withnpm run build - Re-run
Deploy GitHub Pagesvia workflow dispatch
frontend/: React app sourcebackend/: API server, services, repositories, realtime gatewaytests/: Jest service and gateway testsdocs/: product rules, acceptance criteria, threat/perf/style/test docsscripts/: build/deploy utility scripts (pages sync, obfuscation)dist/: build outputassets/+ root*.html: GitHub Pages static publish artifacts
- Product rules:
docs/product.md - Acceptance criteria:
docs/acceptance_criteria.md - Testing policy:
tests/README.md - API server entrypoint:
backend/src/server.ts - Frontend app shell:
frontend/src/app/App.tsx - Frontend router and screens:
frontend/src/app/Router.tsx - Dev server launcher:
vite.dev.mjs - Build script:
vite.build.mjs - Pages sync script:
scripts/sync-pages-static.mjs
- Product docs mark Date/Hybrid frontend scope as reserved, while backend services/routes include mode/matching/date-feed logic. Keep product-vs-implementation alignment explicit during future changes.
npm run buildcurrently warns about large chunks (MapLibre bundle) but build succeeds.- Security advisories are currently transitive dependency issues and may require dependency-major decisions to fully remediate.