Work / Paw Clinic

Paw Clinic

Practice software for veterinary dental clinics, with a real dental chart

The problem

Veterinary dental clinics run on software built for groomers and general practices. Their booking tools treat a dog's dental cleaning like a haircut appointment, and none of them can record what actually happened in the mouth, tooth by tooth. So clinics keep a paper chart next to the computer and type reports for owners by hand.

What I built

Paw Clinic is practice software made for veterinary dentistry:

  • Staff get a calendar, bookings, clients and pets, services, products, memberships, payments and insights.

  • At the heart of it is a visit report with a real dental chart.

  • Pet owners book online and see their pet's reports in their own portal.

  • Clinic staff have a native mobile app for the day's appointments.

  • A marketing site sells it all.

I built the product end to end: the web app, the backend, the mobile app and the marketing site. I work with the client as a partner rather than a contractor, so the product decisions are shared too, from what the chart should record to how plans are priced.

The bookings list for the day with status and price

The day's bookings, by status, with the price and the vet on each.

A dental chart that knows teeth

The visit report has a full dental chart using veterinary tooth numbering, with 42 teeth for dogs and 30 for cats. Each tooth outline was traced from anatomical renders, so the chart looks like a mouth rather than a grid of boxes. Vets click a tooth to mark findings such as tartar, gingivitis or extraction, add the general exam and behaviour, attach before and after photos, and send the report to the owner. The same chart runs in the web app, the mobile app and on the marketing site.

The dental chart with marked teeth

The dental chart in a visit report, with findings marked on two teeth.

Four products in one app

One Next.js app serves the staff dashboard, the pet-owner portal, public online booking and a platform admin, separated by domain at the edge. Staff sign in with a password; pet owners sign in with a code sent by email, so they never need one.

The clinic calendar by vet

The calendar, one column per vet.

A mobile app that never loses a check-in

The staff app is native, not a website in a wrapper. It talks to a versioned mobile API whose contract is generated from the server's validation schemas, so the app and the server cannot drift apart. Every write carries an idempotency key, so a request retried on a bad connection is applied exactly once. When an old version of the app calls the API, the server asks it to update instead of failing in strange ways. Screens the app does not have open the web dashboard already signed in.

Four screens of the Paw Clinic staff app: today, a booking, the calendar and clients

The staff app: the day's progress, a booking's timeline, the calendar by vet and the client list.

The dental chart, visit report and a client profile in the staff app

The same dental chart on the phone: tap a tooth, mark a finding, and the report fills itself in.

The web app also has an offline mode. A clinic can turn it on to keep today's schedule available and queue check-ins when the internet drops, then sync them when it returns.

Payments, plans and reminders

Clinics take deposits, appointment payments, fees and membership payments through Stripe, and pay for their own plan by subscription. Every payment is fulfilled exactly once, however many times the payment provider sends the same event, and each plan's features are switched on and off in one place. Reminders go out by email and SMS 24 hours and 2 hours before each visit, along with recall messages when a pet is due back.

The insights page with revenue and top services

Insights: revenue, appointments by status and top services.

Built to be trusted

Images go to private cloud storage and are served through short-lived signed links. The seed scripts refuse to run against the production database. The interface works in English and in a right-to-left language, and the type system makes sure every English string has a translation.

See it at paw.clinic.