Skip to content
<Hyun/>
All projects

Animalysis

Team project · Prototype dashboard

A pet’s records, with context.

Read the activity chart beside the records that ground an answer, with my prototype work and team contributions clearly separated.

Interactive explanation · not the live service

Loading interactive explanation…

Explore the architectureSystem diagrams, design decisions and detailed flows

System overview

  1. React SPAVite, shadcn/ui, Recharts
    Step 1, records
    NEXT.JS BACK ENDNext.js API routesusers, pets, records
    PostgreSQLSupabase, Drizzle
  2. Next.js API routes
    Step 2, activity
    Sample daily logsactivity prototype
  3. React SPA
    Step 3, chat
    NEXT.JS BACK ENDChat routegrounded GPT-4.1
    stream
    OpenAI APIstreamed replies

Other connections

  • React SPAtoClerksign in
A Vite/React SPA signs users in with Clerk and calls Next.js route handlers: (1) users, pets and records go to Postgres, (2) the activity charts read sample daily logs, and (3) the chat route streams the assistant's replies from OpenAI.
View the diagram as text

Parts

  • React SPA (Vite, shadcn/ui, Recharts): Client / UI
  • Clerk (sign-in, sign-up): External service
  • Next.js API routes (users, pets, records): Owned service
  • Chat route (grounded GPT-4.1): Owned service
  • PostgreSQL (Supabase, Drizzle): Data store / broker
  • Sample daily logs (activity prototype): Data store / broker
  • OpenAI API (streamed replies): External service

Connections

  • Step 1: React SPA → Next.js API routes: records
  • Next.js API routes → PostgreSQL
  • Step 2: Next.js API routes → Sample daily logs: activity
  • Step 3: React SPA → Chat route: chat
  • Chat route → OpenAI API: stream
  • React SPA → Clerk: sign in

From sign-in to a pet's health timeline

  1. Sign in

    Clerk handles sign-in and sign-up, and the app's pages render only for signed-in users.

  2. Link the account

    The dashboard sends the Clerk user id to the API, which creates a matching user row if none exists, then loads that user's pets.

  3. Load health records

    The health records page fetches all records, upcoming ones (scheduled for today or later) and recent ones (completed or ongoing in the last 30 days) in parallel.

  4. Add a record

    A new record is validated with a zod schema and inserted in a database transaction, then the lists refresh.

  5. Chart activity

    The activity endpoint groups a pet's daily logs by day, week or month and derives calories and heart rate; React Query refetches every minute and Recharts draws the lines.

The project & my contribution

Problem
Pet owners need one place for each pet's health records and activity trends.
Solution
A web app for health records and activity charts, plus a GPT-4.1 assistant grounded in the owner's own records.
Result
A team prototype; the activity data and the chat were still prototypes at the last commit.

My part

  • Built the GPT-4.1 assistant route: it checks requests with zod and grounds the prompt in the owner's animals and 60 days of records
  • Built the activity metrics endpoint (day, week or month) and the Recharts activity chart that reads it
  • Built the chat widget and a streaming chat hook in the React front end
  • My teammate built sign-in with Clerk, the Drizzle database and the health-record pages

How it's built

  • Vite + React + TypeScript SPA with shadcn/ui, React Query, Recharts and Clerk sign-in
  • Next.js route handlers over PostgreSQL with Drizzle

Highlights

  • Health records are validated with zod and written in a transaction
  • Activity charts by day, week or month with calorie and heart-rate estimates
  • GPT-4.1 assistant grounded in the owner's own pet records
  • The activity data and the chat were still prototypes at the last commit