Skip to content

Repository files navigation

🐾 PetPass β€” A Digital Medical Passport for Pets

One central health record for your pet, shared with any vet as a secure, read-only, AI-summarized snapshot.

Live app: https://pet-pass-xi.vercel.app/ Β Β·Β  Stack: React 19 Β· Vite Β· Tailwind Β· Supabase Β· Anthropic Claude Β· Vercel

PetPass β€” owner Overview dashboard


Overview

PetPass lets a pet owner keep their pet's complete health history in one place β€” profile, vaccinations, medications, allergies, chronic conditions, lab results, treatments, and personal observations. With one click the owner generates an AI-written professional summary and shares it with a vet through a secure link or QR code β€” read-only, time-limited, and revocable at any time.


The Problem

When a pet needs care at a new or emergency clinic, the vet has no access to prior history. This causes real harm:

  • πŸ” Repeated, unnecessary diagnostic tests
  • ⚠️ Missed drug allergies and interactions
  • ⏱️ Slower, less-informed treatment decisions
  • πŸ’Έ Higher insurance payouts from avoidable exams

Today owners cope by digging through paper folders, re-requesting records from old clinics, or trying to recall history from memory during a stressful emergency. PetPass removes that friction by giving the vet an instant, organized, AI-summarized snapshot of the pet.


Target Audience

Who When they use it What they do
Pet owners Ongoing β€” building the record over time Add pets, upload documents by category, log observations, generate a summary, share a link
Vets (no account needed) At the point of care / emergency Open a shared link or scan a QR code β†’ view a read-only summary + documents

The vet never creates an account and can never edit anything β€” access is gated entirely by a secure token.


Competitors & Differentiation

Anything the owner uses today to carry health history counts as a competitor:

Existing approach Why it falls short
Paper folder / re-faxing records between clinics Slow, easily lost, nothing to hand a vet in an emergency
Owner's memory + WhatsApp / email to the vet Unstructured, incomplete, error-prone under stress
Clinic-locked EMRs (e.g. ezVet, Provet Cloud) Data lives with one clinic β€” it doesn't travel with the pet or the owner
Generic cloud storage (Google Drive, Photos) Just a pile of files β€” no structure, no summary, no safe sharing

How PetPass is different:

  • 🧭 Owner-owned single source of truth β€” the record follows the pet, not the clinic.
  • πŸ€– AI-summarized, not raw dumps β€” the vet reads a professional summary, not 20 PDFs.
  • πŸ”’ Secure, revocable sharing β€” links expire and can be revoked; the vet gets no permanent copy.
  • ⚑ Zero-friction vet access β€” QR code or link, no login, built for the emergency handoff.

πŸš€ Live Demo

Live app: https://pet-pass-xi.vercel.app/

Demo credentials:

Email:    georgy1230@gmail.com
Password: Aa12345678

Try the core flow in ~2 minutes: Log in β†’ Overview β†’ Records (see/upload documents) β†’ Notes (owner observations) β†’ Share β†’ Generate Summary β†’ copy the share link / QR β†’ open it in a private window to see the read-only vet view.


πŸ“Έ Screenshots

AI summary & secure sharing (owner)

The owner reviews the AI-generated vet summary, key health cards, and shares it with a time-limited link or QR code β€” revocable at any time.

Vet summary and share panel with QR code

What the vet sees β€” read-only, no login

Opening the share link lands the vet on a read-only view: pet profile, AI medical summary, key health overview, owner notes, and downloadable documents. No account, no editing.

Vet shared read-only view

Contact phone numbers in these screenshots are intentionally masked.


Core User Flow

Owner

  1. Sign up / log in (email + password).
  2. Create a pet profile (type, breed, birth date, sex, sterilization, identifiers).
  3. Upload medical documents and categorize them (vaccination, lab result, prescription, treatment, surgery, general).
  4. Add structured owner notes (appetite, vomiting, stool, behavior, free text).
  5. Click Generate Summary β€” the AI produces a professional vet-facing summary.
  6. Create a share link, optionally set an expiry, share the link/QR, and revoke whenever needed.

Vet

  1. Open the shared link or scan the QR code β†’ land on /vet/:token (no login).
  2. Read a read-only summary: pet details, AI summary, key health cards, documents.
  3. Download allowed documents via short-lived signed URLs. No account, no editing.

Screens

Screen Route Auth Purpose
Landing / Public Marketing page + login/register CTAs
Login /login Public Email/password sign-in
Sign up /signup Public Account + first pet creation
Overview /overview Owner Health summary cards (allergies, meds, vaccines, treatments, notes)
Medical Records /records Owner Upload / categorize / preview documents
Notes /notes Owner Add & list structured observations
Share / Vet Summary /share Owner Generate AI summary + manage share link, QR, expiry, revoke
Vet Shared View /vet/:token Token-gated Read-only vet view

Tech Stack

Layer Technology
Frontend React 19, Vite, Tailwind CSS 3
Routing React Router 7
UI lucide-react (icons), react-qr-code
Testing Vitest + jsdom
Auth / DB / Storage Supabase (Postgres 17 + Auth + Storage)
Server logic Supabase Edge Functions (Deno)
AI Anthropic Claude
Hosting Vercel (frontend SPA)

Backend Flow

PetPass has no traditional backend server. The browser talks to Supabase directly using the public anon key (protected by Row Level Security), and anything that needs a secret key or must be trusted runs inside Supabase Edge Functions.

1. Authentication

  • Sign-up / login via supabase.auth (email + password). A database trigger creates the matching owner_profile row on sign-up.
  • The browser only ever holds VITE_SUPABASE_ANON_KEY. Row Level Security scopes every row to auth.uid(), so users can only read/write their own data.

2. Data & files (client β†’ RLS)

  • React context providers (petContext, healthRecordsContext, notesContext) read and write through the anon Supabase client.
  • Documents are uploaded to the private medical-documents bucket, path {owner_id}/{pet_id}/{uuid}-{filename}, and served to the browser via 1-hour signed URLs (src/lib/storageService.js). Files are never public.

3. AI summary generation β€” generate-summary Edge Function (verify_jwt = true)

  1. Owner clicks Generate Summary; the function verifies the caller owns the pet.
  2. It claims a per-pet lock (advisory lock via RPC) so only one generation runs at a time.
  3. It summarizes each document, then the notes, then writes a final overall summary using Claude β€” caching each result by a content hash to skip redundant work.
  4. Results are written to document_summaries, notes_summaries, and ai_summaries; the frontend polls the status until it's complete.
  5. The AI key (AI_API_KEY) lives only inside the Edge Function β€” it never reaches the browser.

4. Vet share β€” vet-overview + vet-documents Edge Functions (verify_jwt = false)

  • The share token is validated server-side: the link must exist, be not revoked (revoked_at IS NULL), and not expired (expires_at > now()).
  • vet-overview returns a read-only bundle (pet + AI summary + health cards); vet-documents returns short-lived signed URLs for the shared documents. Token validation never happens in client-side React.

πŸ—ΊοΈ Database ERD

Data model from the live Supabase project (public schema). The two hubs are owner_profile (its id = the Supabase auth user) and pet.

erDiagram
    owner_profile ||--o{ pet : owns
    owner_profile ||--o{ medical_records : owns
    owner_profile ||--o{ owner_note : owns
    owner_profile ||--o{ vet_share_link : owns
    owner_profile ||--o{ ai_summaries : owns
    owner_profile ||--o{ document_summaries : owns
    owner_profile ||--o{ notes_summaries : owns
    owner_profile ||--o{ vet_summary : owns

    pet_type ||--o{ pet_breed : has
    pet_type ||--o{ pet : classifies
    pet_breed ||--o{ pet : classifies

    pet ||--o{ medical_records : has
    pet ||--o{ owner_note : has
    pet ||--o{ vet_share_link : shared_via
    pet ||--o{ document_summaries : has
    pet ||--o| ai_summaries : has
    pet ||--o| notes_summaries : has
    pet ||--o{ vet_summary : has

    medical_record_category ||--o{ medical_records : categorizes
    medical_records ||--o| document_summaries : summarized_as

    ai_status_types ||--o{ ai_summaries : status
    ai_status_types ||--o{ document_summaries : status
    ai_status_types ||--o{ notes_summaries : status

    owner_profile {
        uuid id PK
        text first_name
        text last_name
        text email
        text phone
        text avatar_url
    }
    pet {
        bigint id PK
        uuid owner_id FK
        bigint pet_type_id FK
        bigint breed_id FK
        text name
        timestamp birth_date
        text sex
        boolean is_sterilized
        jsonb identifiers
        jsonb type_attributes
        boolean is_active
    }
    pet_type {
        bigint id PK
        text name
        text display_name
        jsonb default_fields
        boolean is_active
    }
    pet_breed {
        bigint id PK
        bigint pet_type_id FK
        text name
        text display_name
        boolean is_active
    }
    medical_record_category {
        bigint id PK
        text name UK
        text display_name
        boolean supports_expiry_date
        boolean is_active
    }
    medical_records {
        bigint id PK
        bigint pet_id FK
        uuid owner_id FK
        bigint category_id FK
        text title
        text description
        timestamptz record_date
        timestamptz expiry_date
        text storage_path
        text mime_type
        text file_hash
        boolean is_ai_summary_supported
        boolean is_active
    }
    owner_note {
        bigint id PK
        bigint pet_id FK
        uuid owner_id FK
        text title
        text free_text
        text appetite
        boolean vomiting
        text stool
        text behavior
        timestamptz observed_at
        boolean is_active
    }
    vet_share_link {
        bigint id PK
        bigint pet_id FK
        uuid owner_id FK
        text token
        timestamptz expires_at
        timestamptz revoked_at
    }
    ai_summaries {
        bigint id PK
        bigint pet_id FK "unique"
        uuid owner_id FK
        smallint status_id FK
        text summary_text
        text source_hash
        timestamptz generated_at
    }
    document_summaries {
        bigint id PK
        bigint medical_record_id FK "unique"
        bigint pet_id FK
        uuid owner_id FK
        smallint status_id FK
        text summary_text
        text source_hash
        timestamptz generated_at
    }
    notes_summaries {
        bigint id PK
        bigint pet_id FK "unique"
        uuid owner_id FK
        smallint status_id FK
        text summary_text
        text source_hash
        timestamptz generated_at
    }
    ai_status_types {
        smallint id PK
        text name UK
    }
    ai_prompts {
        bigint id PK
        text key UK
        text prompt_text
        text description
    }
    vet_summary {
        bigint id PK
        bigint pet_id FK
        uuid owner_id FK
        text summary_text
        timestamptz generated_at
    }
Loading

Note: vet_summary is a legacy table kept for reference; the active AI pipeline uses ai_summaries (final summary) together with document_summaries and notes_summaries (per-source caches). ai_prompts stores editable prompt templates and ai_status_types is a status lookup (generating / complete / error).


πŸ”Œ External Services & Integrations

Service Type Role in the product
Supabase Auth Authentication Email/password sign-up & login; session / JWT management
Supabase Postgres + RLS Database Stores all app data; Row Level Security scopes every row to its owner
Supabase Storage File storage Private medical-documents bucket + pet avatars, served via signed URLs
Supabase Edge Functions (Deno) Serverless / server logic generate-summary, vet-overview, vet-documents β€” hides keys, validates share tokens server-side
Anthropic Claude AI API Summarizes documents, notes, and produces the overall vet summary (server-side only)
Vercel Hosting / deployment Builds and serves the React single-page app

πŸ” Environment Variables

Client-side (safe to expose β€” used by the browser):

Variable Description
VITE_SUPABASE_URL Supabase project URL
VITE_SUPABASE_ANON_KEY Supabase public anon key (limited by RLS)

Server-side only (Edge Function / Vercel secrets β€” never in src/ or any VITE_ variable):

Variable Description
SUPABASE_SERVICE_ROLE_KEY Bypasses RLS; used only inside Edge Functions
AI_API_KEY Anthropic Claude API key
AI_MODEL Claude model id used for summaries

🚫 The service role key and AI key must never appear in client-side code or in a VITE_-prefixed variable. The only Supabase credential safe for the browser is the anon key.


πŸ› οΈ Run Locally

# 1. Install dependencies
npm install

# 2. Create .env.local with your Supabase project values
#    VITE_SUPABASE_URL=https://<your-project-ref>.supabase.co
#    VITE_SUPABASE_ANON_KEY=<your-anon-key>

# 3. Start the dev server β†’ http://localhost:5173
npm run dev

# Other commands
npm run build     # Production build β†’ dist/
npm run preview   # Preview the production build
npm run lint      # ESLint

The three Edge Functions run on Supabase (supabase/functions/) and require the server-side secrets above to be set in the Supabase project.


πŸ“ Project Structure

src/
  components/     # Reusable UI (shell, cards, forms, share, vet)
  pages/          # One file per route/screen
  lib/            # Supabase client, contexts, storage & helpers
  hooks/          # Custom data-fetching hooks
supabase/
  functions/      # Edge Functions: generate-summary, vet-overview, vet-documents
  migrations/     # Timestamped SQL schema migrations
docs/             # Product, UI, backend & deployment specs

About

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages