Skip to content
2025 – 2026AI ProductPrivacy by DesignSafety

Serenify

An AI wellness product where the hard problems are trust ones: what the model is allowed to see, and what it must do when a conversation turns to crisis.

database-enforced isolation on every user-owned table
Per userdatabase-enforced isolation on every user-owned table
user controls over which personal data the assistant may read
Granularuser controls over which personal data the assistant may read
cached insight generation per user, cutting redundant model calls
1 per daycached insight generation per user, cutting redundant model calls

Wellness is a domain where a plausible AI response is not good enough. I built Serenify as a product that takes that seriously: per-user data isolation enforced at the database, granular controls over what the assistant can read, retrieval over documents the user chose to share, and explicit crisis-resource surfacing rather than leaving a distressed user to the model's judgment.

The problem

An empathetic chat interface is straightforward to build and the wrong place to stop. The real questions are structural: how do you guarantee one user's journal can never reach another's session, how does a user grant the assistant access to some of their history but not all of it, and what happens when someone describes self-harm to a chatbot. Those are architecture and safety decisions, not prompt decisions.

Constraints

  • The data is health-adjacent and personal, so isolation has to be enforced by the datastore rather than by application code remembering to filter.
  • Users must be able to withhold context from the AI without losing the rest of the product.
  • Crisis signals can appear in any conversation, so detection cannot live in a single flow.
  • Repeated model calls over personal history are expensive, so caching had to respect per-user boundaries.

Decisions

What I chose, why, and what I turned down to get there.

Row-level isolation tied to the authenticated user

Every user-owned table enforces access against the authenticated identity at the database layer, so a query cannot return another user's rows even if application code is wrong. In a product holding journals and mood history, isolation belongs where it cannot be forgotten rather than in every query that touches it.

Considered and rejected

  • Filtering by user in application queries — correct until one query forgets, and that one query is a data breach

Explicit user control over what the assistant can see

Granular toggles decide which categories of personal data the AI may read. Personalization and privacy genuinely trade off here, so the resolution is to let the user set the balance rather than to pick a default and hide it. A wellness product that quietly reads everything has broken something more important than a feature.

Retrieval scoped to documents the user uploaded

Embeddings over user-provided health documents let the assistant ground its responses in that person's actual context, stored in the same per-user isolated store. Retrieval is what makes the responses specific rather than generic, and scoping it per user is what makes it safe to do at all.

Detect crisis language and surface real resources

When a conversation indicates crisis, the product surfaces helpline and emergency resources directly instead of relying on the model to respond well. A model's answer to someone in danger is a probability distribution; a helpline number is not. This is the decision I would defend hardest in the whole product.

Cache derived insights per user per day

Generated insights are computed once and reused within the day rather than regenerated on every view, which cuts model calls substantially and keeps what the user sees stable rather than shifting each time they open the app.

A known limitation, stated plainly

In the current open-source build the model is called from the client, which means the API key is exposed to the browser — acceptable for a self-hosted personal deployment, not for a hosted multi-user product. The documented fix is to proxy model calls through a server-side function so the key never reaches the client. It is written down in the repository rather than left for someone to discover, because an unstated known weakness is worse than the weakness.

What the product actually does

Empathetic chat, mood tracking across several dimensions, journaling with AI-assisted reflection, guided sessions, and a dashboard of trends over time — with the privacy controls and crisis flows threaded through all of it rather than bolted on at the end.

Stack

  • React
  • TypeScript
  • Supabase
  • PostgreSQL
  • pgvector
  • Gemini
  • Vite
  • Vercel

What was mine

Designed and built solo as an open-source product — data model, privacy and isolation design, AI workflows, retrieval, and the full interface.