The project is live here: Tether
This case study is still a work in progress. It will get moved to my portfolio once it is finished.
up next
- bug fixes and backlog features
- search for interactions and facts
- conversational interface
- dashboard
- calendar view
case study
Context
Most people rely on memory to maintain relationships—and memory can be unreliable.
Existing tools don’t solve this well. CRMs optimize for transactions and pipeline, notes apps store information passively, and messaging history is fragmented and hard to revisit.
I wanted to create a system that actively supports remembering what’s important about, and to, people: who someone is, how we know each other, and what to remember before the next conversation.
Tether is a personal relationship management system designed around that idea.
Problem
Relationship data is fundamentally difficult to model:
- Fragmented: spread across texts, notes, and memory
- Longitudinal: evolves over months and years
- Sensitive: requires strong privacy and user control
There isn’t a clear pattern for balancing:
- structure vs flexibility
- capture vs recall
- usefulness vs trust
Audience
People who:
- care about maintaining relationships but struggle to recall details over time
- already use notes, reminders, or mental checklists to keep track of others’ needs and preferences
- want to show up more thoughtfully in conversations without relying on memory alone
Features
- Relationship warmth (cold / warm / hot): Like a relationship strength score, but more human. This is calculated based on length of relationship history and time since last interaction. I am planning on factoring in frequency of interaction at some point, too.
- Quick log: One action logs a minimal “Quick Log” interaction so warmth and “last touched” stay honest on days you don’t want to write.
- Briefs before you see someone: The app can build a relationship summary and a shorter “before we meet” note from their profile, saved facts, and recent logs using AI (don’t worry, personal information is never sent through the API). This allows you to refresh your memory before you see someone again, especially if you haven’t caught up in a long time.
- AI you still own: It pulls fact and follow up candidates out of notes; you can fix them, keep them, or delete them.
- One event, many people; two timelines: Log a hangout once, link everyone who was there; it shows on each person’s history. There’s also a single feed of recent activity across everyone so you can skim what happened lately.
Approach
I approached Tether as both a product and systems design problem.
Schema-first foundation
Before building UI, I defined user stories (Gherkin-style) and designed the data model around:
- People
- Interactions
- Facts
- Follow-ups
This allowed me to handle:
- shared interactions across multiple people
- timeline reconstruction
- future extensibility
Starting with structure reduced rework later when edge cases appeared (e.g. overlapping events, timezone boundaries).
Core loop
Instead of building around features, I focused on a tight loop:
- Capture: log interactions quickly
- Timeline: organize events across people
- Recall: surface relevant context before future interactions
AI as an assistive layer (not the product)
AI sits on top of structured data, not in place of it.
Use cases:
- Extraction: candidate facts from interactions
- Summarization: relationship briefs
- Suggestions: follow-ups or reminders
Example:
After logging a few interactions, the system may suggest:
- “Recently moved to Boston”
- “Prefers early morning workouts”
These are:
- tied to specific interactions
- editable or discardable
- never treated as ground truth
Trust and control
Because this data is personal, I treated trust as a product requirement:
- AI outputs are framed as candidates, not facts
- Users can review, edit, or discard all suggestions
- Model responses are grounded in logged data for traceability
- Personally identifying information is excluded or abstracted before sending data to the model
Stack
- Frontend: Next.js, React, TypeScript, Tailwind
- Backend: Supabase, Postgres
- AI: OpenAI API
- Infra: Upstash for rate limiting
Schema changes are managed via migrations to keep local and deployed environments aligned.
Key features & decisions
- Database design: Keep Postgres and row-level security in mind from day one.
- Timeline and multi-person interactions: I centered the model around interactions rather than static profiles, since relationships evolve through events over time.
- Traceable AI outputs: Users should always understand where information comes from.
- Privacy-first AI design: Personal information should never be shared with the AI.
- Fast capture: Reduced friction (e.g. keyboard shortcuts, voice-to-text, quick log) to improve input quality and product stickiness, which directly impacts AI usefulness.
Outcome
Tether evolved from a roadmap into a working application with:
- authentication and user-scoped data
- person profiles (categories, relationship warmth, contact methods)
- interaction logging with multi-person support
- global and per-person interaction timelines
- filtering, sorting, and multiple view modes
- AI-assisted features:
- structured fact extraction
- relationship summaries
- follow-up suggestions
Additional improvements (rate limiting, schema migrations, lint/build discipline) pushed it beyond a prototype toward something usable day-to-day.
Takeaways
- AI positioning is a design decision: Present model output as editable suggestions, not authoritative answers. That preserves trust and keeps the product usable in practice.
- Structure before intelligence: A coherent data model makes AI output more dependable; dependable data also depends on capture staying quick and low-friction.
- Relational memory is an interaction problem, not a storage problem: Saving information was straightforward. The harder work was surfacing the right context at the right time without overwhelming the person view.