Apna Contacts private contact vault dashboard

ProjectsCase StudySaaS Product2026

Case Study

Apna Contacts

A security-first multi-tenant contact vault for families and small businesses—owner CRUD, view-only members, and passworded guest share links.

A security-first, multi-tenant contact vault where families and small businesses share numbers without giving away edit access.

Apna Contacts is a private shared phone book built on Next.js and Supabase. Owners manage one or more vaults; invited members stay view-only; guests open a passworded share link—no account required—to search, call, and WhatsApp.

Industry
Consumer SaaS · Family & small business tooling
Category
Multi-tenant SaaS · Contact vault
Role
Full Stack Product Engineer — product, architecture, security, and UI end to end
Timeline
2025 — 2026
Status
Production-ready product build
Stack
Next.js · React · TypeScript · Tailwind · Supabase · Postgres RLS · Server Actions · Zod

Executive Overview

Apna Contacts solves a simple, painful problem: important numbers live in one person’s phone, while family and staff keep asking for the electrician, the doctor, or the shop supplier in group chats.

The product is a private vault—not a public social directory. Owners create named workspaces (home, shop, family), invite members as view-only, and issue guest share links with optional passwords and expiry.

The engineering story is defense in depth: Server Actions enforce roles, Postgres RLS isolates tenants, and guests never touch tables through the Data API—only SECURITY DEFINER RPCs after a signed session cookie.

The build evolved from a single-owner family book into a multi-tenant SaaS with Google OAuth, CSV import (including Google Contacts), CSP nonces, and privacy-aware SEO that keeps private routes out of indexes.

Business Problem

Existing workflow

Households and shops store numbers in personal phones or shared Google accounts, then forward screenshots, CSVs, or full account access whenever someone needs a lookup.

Pain points

  • Family chats constantly ask “who has the electrician’s number?”
  • Home and shop contacts mix in one phone with no clean separation.
  • Sharing a Google account or full CSV exposes edit rights and private data.
  • Relatives who only need read access should not need full logins or owner privileges.
  • Guest access without proper session design either leaks data or becomes unusable.

Why it matters

Contact books hold trusted personal and business relationships. The product only works if sharing is easy for guests and impossible to abuse—view-only by default, tenant isolation by design.

Solution

Apna Contacts keeps one source of truth for numbers and three clear access modes:

  • Owner vaults

    Full CRUD on contacts, categories, favorites, CSV import, invites, guest links, and workspace settings across multiple named vaults.

  • Invited members

    Authenticated view-only access to a single vault—search and open contacts without create, edit, or delete rights.

  • Guest share links

    Password-optional, expiring links at /g/{token}. Guests get a signed cookie session and a mobile-first read-only contact UI—no signup.

  • Search-first mobile UX

    All / Favorites / Recent tabs, multi-phone contacts, call / WhatsApp / copy actions, and category badges inspired by familiar phone contact apps.

  • Security as product

    Dual authorization (app roles + RLS), HMAC guest cookies, rate-limited share attempts, CSP with nonces, and noindex on private routes.

Families and shops keep one trusted book, share lookup access without edit rights, and separate home vs work vaults—while guests never become members and never gain table-level API access.

Core Features

Contact vault

Contacts CRUD

Create, edit, delete, favorite, and browse contacts with multi-phone JSON fields.

NeedOwners need one reliable book, not scattered notes.

ValueSingle source of truth for important numbers.

Search & tabs

Search by name, phone, or category; filter All / Favorites / Recent.

NeedLookups happen on mobile, under time pressure.

ValueFaster find → call / WhatsApp.

CSV import

Import standard and Google Contacts CSV with preview and validation.

NeedExisting phone books should not be retyped.

ValueLow-friction migration into the vault.

Multi-tenant workspaces

Named vaults

Multiple workspaces per account (e.g. Home, Shop) with active-workspace context.

NeedHome and business contacts should not mix.

ValueClean separation without multiple apps.

Invitations

Email invite tokens, join flow, revoke, and member remove—members stay view-only.

NeedTrusted family needs access without owner powers.

ValueShared access without shared passwords for members.

Owner dashboard

Totals, favorites, weekly adds, category breakdown, and recent updates.

NeedOwners need a quick health check of the vault.

ValueClear overview before diving into contacts.

Guest sharing

Share links

Create, list, and revoke guest links with optional password and expiry.

NeedRelatives should not need accounts for a quick lookup.

ValueFrictionless read access under owner control.

Signed guest sessions

HMAC-signed HTTP-only cookie after RPC session create; middleware validates signature then DB session.

NeedAnonymous access must still be authenticatable and short-lived.

ValueGuest UX without opening the Data API to anon.

Guest contact UI

Read-only list and detail under /{slug}/guest/contacts with call / WhatsApp / copy.

NeedGuests need the same lookup actions as members.

ValueUseful sharing, not a dead view-only dump.

Auth & account

Email + Google OAuth

Supabase Auth with signup bootstrap that creates a personal workspace via DB trigger.

NeedOwners need a fast, familiar sign-in path.

ValueLower setup friction for the person who owns the vault.

Account controls

Profile, password change, and delete-account confirmation.

NeedPersonal data products need clear exit and security hygiene.

ValueOwner trust and compliance-minded UX.

User Journey

Owner → Vault ready

  1. 01

    Signs up or signs in (email / Google)

  2. 02

    Personal workspace bootstrapped automatically

  3. 03

    Adds contacts or imports CSV

  4. 04

    Optionally creates a second vault (e.g. Shop)

  5. 05

    Invites family members as view-only

  6. 06

    Creates a guest share link for relatives

Member → Lookup

  1. 01

    Accepts invite and signs in

  2. 02

    Opens the assigned vault contacts

  3. 03

    Searches or browses Favorites / Recent

  4. 04

    Calls, WhatsApps, or copies a number

  5. 05

    Cannot create, edit, or delete contacts

Guest → Share link

  1. 01

    Opens /g/{token}

  2. 02

    Enters optional share password

  3. 03

    Receives signed guest session cookie

  4. 04

    Browses read-only contacts for that vault

  5. 05

    Calls or WhatsApps without creating an account

Technical Highlights

Dual-layer authorization

App roles (owner / member / guest) gate Server Actions; Postgres RLS isolates rows by workspace and restricts writes to owners.

Business valueA bug in the UI cannot casually bypass tenant or write rules.

Guests via RPCs only

Anonymous clients never get table grants. Guest list/get flows run through SECURITY DEFINER RPCs with narrow return columns.

Business valueShare links stay useful without exposing the workspace schema.

HMAC guest cookies

Guest sessions are signed with GUEST_SESSION_SECRET, validated in middleware, then checked against DB session validity.

Business valueShort-lived, tamper-resistant guest access without full auth accounts.

Multi-tenant evolution

Migrations document the path from single-owner share password to workspaces, invites, member view-only, and authz hardening waves.

Business valueShows production discipline: ship, secure, then scale the tenancy model.

CSP + privacy SEO

Per-request CSP nonces, strict security headers, robots/noindex on private routes, and llms.txt guidance for crawlers.

Business valuePrivate contact data stays out of indexes and training scrapes by default.

Google Contacts import

CSV parser handles header aliases, multi-phone rows, system labels, and starred → favorite mapping with preview before insert.

Business valueOwners migrate real phone books without manual cleanup first.

Challenges & Solutions

ChallengeSolution
Family needed easy lookup access without giving everyone edit rights or a full Google account.Three-tier access: owner CRUD, authenticated view-only members, and passworded guest share links.
Anonymous guest access is a classic leak surface if guests can query tables directly.No anon table grants—session RPCs plus HMAC cookies and rate-limited password attempts.
Home and shop contacts mixed when everything lived in one personal phone book.Named multi-tenant workspaces with RLS isolation and an active-workspace switcher.
Early single-owner share-password design did not scale to invites and multiple vaults.Incremental migrations to workspaces, invitations, guest_share_links, and repeated security hardening.
Private product routes must not become public SEO or AI-crawler fodder.noindex on app routes, robots disallow for contacts/guest/invite paths, and privacy-aware llms.txt.

Tech Stack

Frontend
Next.js App Router, React 19, TypeScript, Tailwind CSS v4, shadcn/ui, Lucide, Sonner
Forms & validation
React Hook Form, Zod, Server Actions
Backend
Next.js Server Actions — no separate API server
Database
Supabase Postgres with Row Level Security
Authentication
Supabase Auth — email/password + Google OAuth; HMAC guest sessions
Guest security
SECURITY DEFINER RPCs, pgcrypto password hashes, signed HTTP-only cookies
Theming
next-themes, light/dark product UI
Ops
Supabase Edge Function keep-alive + pg_cron for free-tier pause prevention
Deployment
Vercel-oriented Next.js deploy with security headers

Project Gallery

Recommended capture order for the case-study gallery.

  1. 01Landing — private vault positioning
  2. 02Owner dashboard — metrics & categories
  3. 03Contacts list — search & tabs
  4. 04Contact detail — call / WhatsApp / copy
  5. 05New contact / multi-phone form
  6. 06CSV import preview
  7. 07Workspace switcher — Home vs Shop
  8. 08Settings — members & invites
  9. 09Share — guest link management
  10. 10Guest entry — password gate
  11. 11Guest contacts — read-only mobile UI
  12. 12Dark mode — dashboard & contacts

Key Learnings

Product

For personal data products, the access model is the product—owners, members, and guests need different journeys, not one shared login.

Engineering

App-layer checks and Postgres RLS should say the same thing; either alone is not enough for multi-tenant contact data.

Architecture

Guest flows stay safer when anonymous users never get table grants and only call narrowly scoped RPCs.

Security

Iterative hardening migrations (token secrecy, invite email binding, rate keys) are part of shipping—not a one-time checklist.

Future Improvements

PriorityImprovementBusiness value
HighInvite email delivery (Resend) so owners do not rely only on copyable linksFaster member onboarding with less manual sharing.
HighFine-grained roles and selective contact sharing beyond owner vs view-onlyBetter fit for shops where some staff need limited edits.
MediumWorkspace switcher and settings UX polish for multi-vault ownersClearer day-to-day vault management.
MediumContact activity / recent-call hints for guests and membersFaster repeat lookups for frequently used numbers.
LowOptional WhatsApp deep-link templates and label presets per categorySlightly faster outreach from the detail screen.

Need a multi-tenant product with real access control?

Apna Contacts is a full-stack case study in private data sharing—workspaces, RLS, guest sessions, and a mobile-first vault UX. If you are building something where permissions are the product, let’s talk.

Start a conversation
Optional technical notes

Notes on how guest access, tenancy, and authorization stay aligned across the Next.js app and Supabase.

Access modes, not one role

Owner, member, and guest are different products in one codebase. Write paths require owner; members and guests only read. That rule is enforced in role helpers and again in RLS policies.

Guest share passwords protect the link—not the workspace membership model. Guests never become members through a share URL.

Tenant isolation

Every contact, category, invite, and share link is scoped by workspace_id. Signup bootstraps a personal workspace via a database trigger so owners land in a usable vault immediately.

The workspace slug in guest URLs is branding only—the active guest workspace always comes from the validated session, never from a client-trusted path segment alone.

Security migrations as narrative

The SQL history is part of the product story: initial contacts schema, production owner RLS, guest sessions, multi-tenant workspaces, member view-only, then waves that hide share tokens, bind invites to auth emails, and harden rate limiting.

That arc is deliberate—ship a useful vault, then harden the surfaces that appear once real sharing begins.

Role

Full Stack Product Engineer

Client

Personal product / SaaS build

Date

2026

Collaborators

Solo build

Next Project

GitSearch AI

View next
Ask AI about Zohaib