Header background

Vetsync

VetSync is a full-stack veterinary clinic management system designed to streamline clinic operations, patient (pet) records, appointments, and veterinary workflows. It supports multiple user roles including pet owners, clinic administrators, veterinary professionals, and system administrators.

Type

Web App

Role

Full-stack Developer

Demo

View Live

Code

View Source

Tech Stack

ReactPostgreSQLJavaScriptTailwindSequelizeNode.jsExpress

Why I Built This

Most veterinary clinics still rely on fragmented tools like spreadsheets, paper records, or disconnected systems for managing appointments, patient records, and clinic operations. This creates inefficiency, data inconsistency, and poor visibility across workflows.

I built this system to centralize clinic operations into a single platform that handles appointments, electronic health records (EHR), and user management in a structured and scalable way. The goal was to simulate a real-world clinic management system with proper role separation and backend-driven business logic.


Vetsync feed page
Main feed page
System Admin Viewing Dashboard
System Admin Dashboard

How It Works

The system is structured around four core roles: pet owners, clinic administrators, veterinary professionals, and system administrators.

Pet owners register pets and book appointments using available time slots generated by the system. The backend ensures no double booking by validating availability before saving appointments.

Clinic administrators manage clinic operations, approve veterinary professionals, and assign them to appointments. Veterinary professionals handle consultations and create electronic health records after each appointment.

All actions are authenticated using JWT, and role-based access control ensures users can only access features relevant to their role. The backend acts as the source of truth for scheduling, availability, and record management.


Clinic Admin Viewing Dashboard
Clinic Admin Dashboard
Pet Owner Viewing a Clinic
Pet Owner Clinic View

Key Decisions

Backend-driven scheduling system

Appointment availability is calculated entirely on the backend instead of relying on frontend logic. The system dynamically generates available time slots based on clinic operating hours, veterinarian availability, and existing appointments. This prevents double-booking, keeps scheduling logic centralized, and ensures the frontend only displays valid appointment slots.

Role-based relational architecture

The platform was designed around a centralized users table with role-specific sub-models for pet owners, clinic administrators, veterinary professionals, and system administrators. This avoided duplicating shared user fields while still allowing each role to maintain its own domain-specific data and permissions.

  const User = sequelize.define("User", {
    id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true },
    email: { type: DataTypes.STRING, unique: true, allowNull: false },
    password_hash: { type: DataTypes.STRING, allowNull: false },
    first_name: { type: DataTypes.STRING, allowNull: false },
    last_name: { type: DataTypes.STRING, allowNull: false },
    user_type: {
      type: DataTypes.ENUM("pet_owner", "vet_professional", "clinic_admin", "system_admin"),
      allowNull: false,
    },
    phone_number: DataTypes.STRING,
    profile_image_url: { type: DataTypes.JSON, allowNull: true },
  }, {
    tableName: "users",
    timestamps: true,
  });

Service-layer architecture

Business logic was separated into service layers instead of placing everything inside controllers. This made the application significantly easier to maintain, reuse, and scale as more complex workflows like appointment assignment, EHR management, and clinic approvals were introduced.

Activity logging system

A dedicated activity logging system was implemented to track important actions such as logins, appointment creation, and clinic activity. This creates a foundation for analytics, reporting, monitoring active/inactive clinics, and future auditing features without tightly coupling reporting logic to operational tables.

  export const auditLogger = (req, res, next) => {
    if (req.method === "OPTIONS") return next();
 
    const start = Date.now();
 
    res.on("finish", async () => {
      if (res.statusCode >= 400 && res.statusCode < 500 && !req.user) return;
 
      try {
        await AuditLog.create({
          method: req.method,
          url: req.originalUrl,
          status_code: res.statusCode,
          user_id: req.user?.id || null,
          user_email: req.user?.email || null,
          user_type: req.user?.user_type || null,
          ip_address: req.ip || req.connection?.remoteAddress || null,
          response_time_ms: Date.now() - start,
        });
      } catch (err) {
        console.error("Audit log write failed:", err.message);
      }
    });
 
    next();
  };

What I Learned

This project significantly deepened my understanding of designing real-world backend systems where business rules, data consistency, and scalability matter more than simply building CRUD endpoints.

I learned how to model complex relational data structures using PostgreSQL and Sequelize, particularly around multi-role user systems, appointment scheduling, veterinary workflows, and medical records. Designing relationships between clinics, veterinarians, appointments, pets, and EHR records forced me to think carefully about normalization, ownership, and long-term maintainability.

Building the scheduling system taught me the importance of backend-first validation. Preventing double-booking, dynamically generating available time slots, and handling veterinarian availability highlighted how critical it is to centralize scheduling logic instead of relying on frontend assumptions.

I also gained a much stronger understanding of application architecture. Structuring the backend using controllers, services, middleware, and models made the system easier to reason about as complexity increased. JWT authentication, role-based access control, and permission handling also gave me hands-on experience implementing secure multi-role systems.

Beyond the technical implementation, this project improved how I approach system design decisions. Instead of only focusing on features, I learned to think more about operational workflows, scalability, user experience, and how small architectural choices can significantly impact maintainability later in development.

Let's Connect

Have a project in mind?
Let's make it happen.

Get in Touch