Skip to content
The-SensoriumPublic

About

Sensorium is a social platform that places you into a group of exactly eight people, called a cluster.

Resources

Code of conduct

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

351 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Sensorium logo

Sensorium

Eight people. One cluster.

About · Features · Getting Started · Scripts · Testing · Documentation · Contributing · License

License: GPL-3.0

About

Sensorium is an open-source social platform that places you into a group of exactly eight people, called a cluster, matched by birth date, location, or Open Mix (no filter). Once matched, the room opens immediately at formation, and you get tools built for long-term friendship: realtime chat with reactions and read receipts, a cluster-scoped posts feed, audio/video calls, availability check-ins, Signals (requests for help), and community governance through votes. Answering the five introduction questions is an optional in-cluster checklist that never blocks access. It ships as a web app and an Android app that share one Supabase backend, plus moderator/admin workspaces and a transactional email + push pipeline.

Platforms

  • Web app (src/): the full product - chat, posts, discovery, moderation, and admin surfaces - served on Vercel.
  • Android app (mobile/): an Expo/React Native companion for members, sharing the same Supabase backend and accounts, with push notifications via Expo. Admin and moderation stay web-only. See mobile/README.md.

Features

  • Matching: enter up to six queues (exact birth date, birth year and month, generation 5-year cohort, birth year, local radius, or Open Mix). A cluster forms when a mode reaches eight ready people.
  • Cluster chat: realtime messaging with edits, reply threads, @-mentions, emoji reactions, image sharing, and a GIF picker (KLIPY).
  • Read receipts: per-message "seen by" detail with the time each member first read it, updated automatically as members scroll.
  • Cluster calls: start or join audio/video calls from the room on web and Android, with ringing state and membership gating powered by LiveKit.
  • Introduction checklist: a five-question shared intro stays answerable at any time as an optional in-cluster checklist (progress nudge, never a gate, no deadline).
  • Posts: a cluster-scoped feed of text, images, and GIFs - optional titles, heart likes, and threaded comments and replies, visible only to the cluster.
  • Clusters directory: browse matching modes and preview a mode's non-archived clusters (name, status, member count, formation date).
  • Signals: raise a request for help, reply in threads, and track open, in-progress, and resolved states.
  • Governance: votes for cluster renames and member replacement, invitation flows, and cooldowns.
  • Notifications & push: a per-cluster notification center with per-type preferences, plus Android push notifications delivered through an Expo outbox pipeline.
  • Moderation, roles & appeals: member reporting, a moderation queue with moderator/admin workspaces, warnings, temporary suspensions and permanent bans, and an in-app appeal flow with email notifications.
  • Safety: per-user muting, a "My Reports" self-status view, and self-service account deletion that departs your clusters and anonymizes moderation records.

Tech Stack

Layer Choice
Web frontend React 19, TypeScript, Vite
Routing React Router v8
Styling Tailwind CSS v4, tokens from docs/DESIGN.md
Server state TanStack Query + Supabase Realtime
Mobile app React Native via Expo (mobile/), expo-router, expo-notifications, EAS
Calls LiveKit: @livekit/components-react (web), @livekit/react-native (mobile), tokens minted by the create-call-token Edge Function
GIFs KLIPY, queried directly from the client with VITE_KLIPY_APP_KEY
Backend Supabase (Postgres, Auth, Storage, Realtime)
Edge Functions Supabase Edge Functions (Deno): send-emails (Resend), send-push (Expo), create-call-token (LiveKit)
Email Resend, drained by the send-emails Edge Function
Push notifications Expo Push, drained by the send-push Edge Function
Scheduled jobs pg_cron over database functions
Testing and lint oxlint, TypeScript, Vitest, Playwright

See docs/TECHNICAL.md for the full, versioned stack.

Getting Started

Prerequisites

  • Node.js 20+ and npm
  • Supabase CLI
  • Docker (for the local Supabase stack)

Run the app locally

# 1. Install dependencies
npm install

# 2. Start the local Supabase stack (Postgres, Auth, Storage, Realtime, Studio)
supabase start

# 3. Point the app at your local project
cp .env.example .env
#     VITE_SUPABASE_URL=http://127.0.0.1:54321
#     VITE_SUPABASE_ANON_KEY=<from `supabase status`>

# 4. Run the app in dev mode
npm run dev

Rebuild the backend from scratch against any fresh stack:

supabase db reset

Seed the demo golden-path user and cluster (used by local dev and E2E):

npm run seed:demo

Local realtime note: if chat or presence does not flow after changing realtime migrations, run supabase stop && supabase start so the realtime server reconnects.

Mobile app (Android)

The Android app lives in mobile/ and shares the web app's Supabase backend and accounts.

cd mobile
cp .env.example .env          # EXPO_PUBLIC_SUPABASE_URL + publishable key (staging first)
npm install
npm run sync:db-types         # refresh synced db types + shared lib/feature modules from web (realtime.ts stays pinned)
npx expo start                # scan with Expo Go or run on a device

Android builds with push enabled require mobile/google-services.json and EAS credentials; see mobile/README.md for the full setup.

Environment variables

Variable Required Description
VITE_SUPABASE_URL yes Supabase project URL
VITE_SUPABASE_ANON_KEY yes Public anon (publishable) key
VITE_KLIPY_APP_KEY no KLIPY app key that enables the chat/post GIF picker
VITE_KLIPY_ENDPOINT no KLIPY API base URL (defaults to https://api.klipy.com/api/v1)
VITE_GEOCODING_ENDPOINT no Geocoding endpoint override used by Local mode
VITE_TURNSTILE_SITE_KEY no Cloudflare Turnstile site key for auth bot protection; empty means the widget is hidden (local dev only)

Only the anon key is used in the browser. All privileged operations run through Postgres RPC functions guarded by Row Level Security. See docs/TECHNICAL.md for how the environments, deployments, and CI secrets fit together.

Scripts

Command Description
npm run dev Start the Vite dev server
npm run build Type-check (tsc -b) and build (vite build)
npm run preview Locally preview the production build
npm run lint Run oxlint
npm test Run the Vitest and React Testing Library suite once
npm run test:coverage Run the unit suite and enforce the v8 coverage gate
npm run test:integration Run the integration suite against the local Supabase stack
npm run test:watch Run Vitest in watch mode
npm run test:e2e Run the Playwright E2E suite (chromium + mobile-chromium projects)
npm run check:release Dry-run the develop → main release merge before opening the release PR
npm run seed:demo Idempotently seed the running local stack with demo data
npm run sync:legal Refresh the legal content pages

Testing

Sensorium has three test layers. npm test, npm run test:coverage, npm run test:integration, and npm run test:e2e run them; see CONTRIBUTING.md for the full matrix and what each layer requires.

  • Unit and component (npm test): Vitest and React Testing Library run against pure logic (modes, availability, utils, onboarding validation) and components.
  • Coverage gate (npm run test:coverage): the unit suite measures src/** with v8 and enforces minimum thresholds so CI fails if coverage regresses. The gate is an enforced floor, not a target.
  • Integration (npm run test:integration): exercises the Supabase stack end-to-end (RPC functions, RLS, and security definer behavior) with fixtures created via service role and assertions through per-user anonymous clients. Requires a running local stack.
  • E2E (npm run test:e2e): Playwright specs under e2e/ walk the golden path, cluster room, posts, notifications, safety, seen-by, and settings. They run on two projects (desktop chromium and a mobile viewport) and expect a seeded local Supabase stack and the two demo accounts.
  • Mobile: mobile/ is linted with oxlint, typechecked with TypeScript, and has its own Vitest runner (currently a small suite covering shared helpers; most behavior is validated on web and in the integration suite).

Mobile scripts live in mobile/package.json: npm start / npm run android / npm run ios (Expo), npm run lint, npm test, and npm run sync:db-types.

Environments

Environment Branch Vercel deployment Database
Production main Production Production Supabase project
Preview develop Preview Staging Supabase project
Feature preview feature/* Preview (per branch) Staging Supabase project

Sensorium uses a staging-driven Git workflow. All work starts from develop; main is reserved for production releases. Migrations are applied to staging when a PR merges into develop, and to production when develop merges into main. See docs/TECHNICAL.md and CONTRIBUTING.md for details.

The Android app is built through the EAS/CI release workflows and shares the same production and staging Supabase projects as the web app.

Security

  • Every table has Row Level Security enabled. The frontend never writes tables directly except through RPC functions or RLS-permitted inserts.
  • Chat media, post images, and profile photos are stored in private buckets (chat-images, posts-images, avatars) and served through short-lived signed URLs.
  • Push notifications route through a database outbox drained by the cron-woken send-push Edge Function (Expo); transactional emails route through send-emails (Resend). Both are guarded by secrets and are never reachable from the browser.
  • No secrets ship in the client. Use VITE_ variables for public values only.

If you find a vulnerability, please open a private issue or reach out before publishing details.

Documentation

Read the docs in this order when you are new to the project. Each document states its audience up front; the index at docs/README.md shows how they relate.

  1. Start here. docs/ARCHITECTURE.md gives the high-level mental model: how the frontend, Supabase, and the database fit together. About 10-15 minutes.
  2. What the product is. docs/PRD.md describes the product requirements, screens, and user flows.
  3. What it looks like. docs/DESIGN.md documents the visual design system and design tokens.
  4. How it is built. docs/TECHNICAL.md is the deeper technical reference: stack, schema, migrations, storage, realtime, and deployment. Read it when you start working in the code.
  5. How to contribute. CONTRIBUTING.md covers the Git workflow, code conventions, and testing requirements.

For the mobile app specifically, see mobile/README.md.

Design records for features that already shipped (implementation plans) live in docs/archive/. You do not need them to get started; reach for one only when you want the why behind a specific feature.

Contributing

Contributions are welcome. Please read CONTRIBUTING.md before starting. It covers the development workflow, code style, database and migration rules, and testing requirements.

By participating in this project you agree to abide by the Code of Conduct.

License

Released under the GNU General Public License, Version 3 (GPL-3.0).

About

Sensorium is a social platform that places you into a group of exactly eight people, called a cluster.

Resources

Code of conduct

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages