Vetly banner

Vetly

Veterinary Clinic Management System

Vetly additional image 1 Vetly additional image 2 Vetly additional image 3

Vetly is a full-stack veterinary clinic management system for small practices. It covers the staff side - appointments, records, prescriptions, inventory - and a patient portal for pet owners to track their pet’s care.

Stack

Layer Technology Why
Backend Spring Boot + Kotlin Strong type system, concise syntax, solid Spring ecosystem
Database PostgreSQL Highly normalized data model; benefits from joins and constraints
Auth Firebase Authentication Handles credential management and social logins via JWT, integrated into Spring Security
Storage Firebase Storage Media scoped behind Firebase auth rules
Frontend React + TypeScript + Expo Single codebase for web and native mobile
Deployment Docker Consistent environments; backend containerized, frontend served separately due to Expo limitations

Features

Appointment Management Schedule, reschedule, and cancel appointments; view upcoming appointments and patient history
Patient Records Medical history, vaccinations, treatments, with photo and document attachments
Prescription Management Create and manage prescriptions with medication details and dosage instructions
Inventory Management Track stock levels and manage suppliers
Patient Portal Pet owners can view medical history, upcoming appointments, and vaccination reminders
Clinic Details Manage address, contact information, and operating hours

Architecture

The backend follows a layered structure - controller, service, repository - with role-based access control at the service layer separating clinic staff from pet owners. It exposes a RESTful API consumed by the frontend.

Authentication flows through Firebase, with JWT tokens validated by Spring Security before reaching any endpoint. Media access is gated by Firebase Storage rules tied to the same auth context.

The frontend uses Expo’s file-based routing with deep linking support. Shared UI components (buttons, inputs, cards) are extracted into a component library used across both web and native targets.

Challenges

Domain modeling was harder than expected. The relationships between patients, owners, clinics, appointments, and inventory involve a lot of overlapping concerns. Getting the schema right required multiple iterations - including conversations with working veterinary staff about their actual workflows, which surfaced requirements that weren’t obvious upfront.

UI/UX for two distinct user types - clinic staff need density and efficiency; pet owners need simplicity and clarity. Balancing those in a shared codebase with a consistent design system required deliberate component-level decisions rather than a one-size-fits-all approach.

What I’d Do Differently

PostgreSQL for everything was a mistake. Inventory metadata and media references are non-relational by nature - a document store like MongoDB would have been a better fit there and would have simplified several awkward schema decisions.

Microservices for notifications and media. Both are good candidates for isolation - they have independent scaling needs, clear boundaries, and are the most likely integration points for third-party services (push notifications, payment processing). Keeping them in the monolith made those integrations messier than they needed to be.

More upfront domain modeling. Several refactors mid-project traced back to schema decisions made early under time pressure. Spending a week on a proper ERD and talking to domain experts before writing any code would have paid for itself.

AI species identification and a drug interaction API were both scoped out due to time constraints. Both would add real clinical value - species ID from photos for intake, and interaction checking at prescription time - and are worth revisiting.

Tags

  • spring boot
  • kotlin
  • docker
  • postgresql
  • firebase
  • react
  • typescript