An MVP-app for tracking your pet's medical records.
Development environment:
npm run installnpm run start
Production environment:
npm run installnpm run preview
The basic app scaffolding and running took under 30 minutes.
-
TanStack Start to rapidly bootstrap the app without manually configuring:
- API layer
- React setup
- Routing
- 404 and global error handling
-
While still in beta, it's ideal for MVP-level experimentation and accelerates development.
- Linting: Added standard linting setup with default configurations.
- ORM: Selected Drizzle ORM for database access. While I have no experience with Drizzle, I am excited to try it out hoping it's more lightweight and simpler than Prisma (which felt too heavy for MVP scope).
- Forms: Added react-hook-form to manage form state and validation in a declarative and performant way.
- UI: Integrated Tailwind CSS for consistent design and rapid UI development.
-
Admin users can:
- View soft-deleted records (e.g., historical allergy or vaccine data that was removed)
- See full medical history for any pet, even past modifications
-
Users and admins can:
-
Add new pets, including selecting type.
-
Create new animals, allergies, and vaccines on the fly — despite the normalized structure
- This is aided by unique constraints at the DB level to prevent duplicates
- In a production app, this would require additional validation and administrative workflows
-
Normalization & Modularity:
- The schema is well-normalized:
- Animals and vaccines are decoupled, allowing fine-grained control of vaccine schedules per species.
- Pets link to users and animals, maintaining clear separation between general species-level data and individual pets.
- Vaccine records link to the
animal_vaccinestable rather than vaccines directly — enforcing correct pairings and supporting animal-specific schedules.
Auditability:
- Every table includes
createdAt, and key medical records use adeletedAttimestamp to enable soft-deletion. - This makes it possible to audit the full historical medical trail of any pet, even if records are “removed” from the user’s perspective.
Extensibility:
- By modeling vaccine applicability with the
animal_vaccinesjoin table, the schema supports future logic like showing overdue vaccinations based on species. - You could easily extend this to support vaccine frequency or schedule data (e.g., interval_days).
Data Integrity:
- All foreign keys are explicitly enforced.
- Unique constraints on names (e.g., animals, allergies, vaccines) help reduce redundancy even when user-created entries are allowed.
- More constraints can be added - see section on improvements.
UX Considerations:
- Pet owners can freely add new allergy/vaccine names, with constraints helping dedupe at the DB level — a good trade-off between MVP simplicity and data cleanliness.
Note
- All history is traceable. Nothing is permanently deleted.
- The GitHub repo includes a pre-built SQLite file with basic sample data.
- The
db/folder contains the seed script. There's alsonpm run seedif you want to re-create your local database (does require some dependencies on your machine).
The UI consists of header (medical card with company name), sidebar, main section, and footer. On smaller viewports, the sidebar and main content are stacked instead. The pages include:
-
Landing Page (unauthenticated):
- Lists all users
- Allows creation of a new user
-
Home Page (authenticated):
- Lists pets for the current user on the left sidebar
- Clicking a pet opens the detailed view
-
Details Page:
- Shows pet info, including allergies and vaccines
- Allows adding new allergies and vaccine records
API routes follow REST principles and are co-located with the front-end using TanStack Start’s file-based routing. Major endpoints include:
-
Users
GET /api/users— List all usersGET /api/users/:id— Get a specific userPOST /api/users— Create a new user
-
Pets
GET /api/pets— Admin: List all petsGET /api/pets/:id— Get a specific petDELETE,POST /api/pets/:id/allergy- Manage a pet's allergiesDELETE,POST /api/pets/:id/vaccine- Manage a pet's vaccinesPOST /api/pets— Create new pet
-
Validation
- All data mutating endpoints use Zod for schema validation
- Shared schemas between front-end and back-end ensure consistency and type safety
The following small items were accomplished to give the MVP a bit more character:
- Name. Pelican sounds like a bit like "Medical", "Can", and starts with "Pe" from pet.
- Logo. Yes, behind the scene it's all Dr. Pelican Ph.D. keeping the records.
- Documentation was assisted by ChatGPT, which helped structure and write readable summaries based on design and architectural decisions.
-
My unfamiliarity with Drizzle and TanStack Start slowed me down:
- While I know SQL well, I found Drizzle less productive for writing SQL-like logic programmatically. I’ll look for alternatives next time.
- TanStack Start provides a lot out-of-the-box — possibly more than this MVP required.
-
Clean TypeScript usage took time, especially aligning inferred and explicit types. There’s much more that could be typed, but I had to draw the line.
-
Setting up a basic query-string-based Auth took longer than expected.
-
Added proper
NotFoundand global error pages took a bit of time, but add a lot of value. -
Implemented both frontend and backend validation to ensure input sanitation and avoid malicious data insertion.
There's a number of items listed below where improvements can be made.
-
Database Schema:
- Additional constraints should be considered (an allergy is probably unique to a pet, we shouldn't be able to record two identical allergies).
- When entering a custom vaccine, if it already exists in vaccines but not in the animal-vaccine linking table, this currently is an edge case that errors out.
-
Build Optimization:
- Remove unused CSS
- Add bundle splitting and optimize image assets for production
-
UI Enhancements:
- Replace inline editing with modals for more structured workflows
- Enable deeplinking to modals to create new records (for better navigation and shareability)
- Extract repeated styles (e.g. inputs) to common components so that they can easily be reused.
-
Testing:
- Add basic UI tests for core flows (authentication, adding medical records)
- Add backend tests to validate input handling and access control logic (e.g., authorization checks)