(434) 236-9027
← Case StudiesLocal Dog Grooming Business

A Bilingual Website, Then the App That Runs the Salon

A full page-for-page bilingual build, and 95% of appointments now arriving through online booking instead of a phone call

The Challenge

Fancy Pet Salon needed a comprehensive online presence to compete in Lynchburg, Virginia's dog grooming market. They wanted a bilingual website (English and Spanish) to serve the growing Hispanic community, with full local SEO targeting dozens of service and breed combinations. The existing web presence was minimal, just a Facebook page.

The Solution

I built an Astro SSR website covering every grooming service, dog breed, and location combination. Each page has unique content, Schema.org structured data, and proper hreflang tags for the Spanish mirror. The site is built on Astro with a custom CSS framework, no WordPress, no page builder bloat. I also built an AI chatbot (Buddy) powered by Groq/Llama 3.3 70B that answers customer questions in both English and Spanish, with guardrails to prevent off-topic responses. The site is server-rendered behind Cloudflare with a hero poster image as the LCP element for fast mobile load.

Astro 6Node SSRGroq APISchema.orgCloudflareBilingual

Beyond the Website: Systems That Keep Working

A fast website is the foundation, not the finish line. To keep Fancy Pet Salon visible in local search and easy to book, we layered two automated systems on top of it, the same playbook we run for J.M. Field and other local clients.

Automated Google Business Profile Posting

An automated poster publishes a fresh Update to her Google Business Profile every week, with no manual effort from the owner. A profile that stays active signals to Google that the business is current, which supports Map Pack visibility for high-intent searches like "dog groomers near me." It is the same posting engine that keeps our other local clients' profiles fresh week after week.

Online Appointment Booking

We stood up a self-hosted Cal.com booking system so pet owners can book a grooming appointment online instead of playing phone tag. Availability lives in one place, and the booking link drops straight into the website and the Business Profile so customers can act the moment they find her.

Then the Book Itself: Rebuilding the Salon on an App

Getting the bookings in was only half of it. Fancy Pet Salon is a one-groomer shop. The person who takes the booking is the same person with both hands on a dog for most of the working day, so anything that asks her to stop, pick up a phone, or go find a pen competes directly with the work she actually gets paid for.

So we built the book. Three surfaces sitting on one back end: a browser dashboard at admin.fancypetsalon.com, which came first, an Android app she keeps on her phone, and an iOS build now going out through TestFlight. The Android and iOS apps are not two codebases. The screens, the data layer and the business rules are one Kotlin Multiplatform module compiled for both, so a fix to the booking logic lands on her phone and on an iPhone from the same change. The app is sideloaded rather than published, and it updates itself, checking a manifest, noticing a newer build, and offering it. Underneath both is a single SQLite database on the server holding clients, dogs, appointments, takings and expenses, with the Cal.com bookings syncing straight in. Nothing here is a SaaS subscription with the salon's data locked inside someone else's product. It is her book, on her server, in a file that can be copied.

AndroidiOSKotlin MultiplatformCompose MultiplatformPHPSQLiteCal.com

What the Book Holds

Read out of the production database on 2026-08-17. These are counts, not estimates.

118

Client records in the app

138

Dogs on file

172

Appointments in the book

131

Completed with a payment recorded

25

Still upcoming

$85.87

Average ticket

12 of 172, 7%

No-shows

55

Days of takings recorded

93 of 118

Clients with an email address

5

Enrolled devices

2026-03-22 to 2026-10-01

Book spans

Online Booking Now Carries the Book

The number worth caring about is not how many appointments exist. It is how many of them appeared without the groomer doing anything.

MonthAppointmentsBooked online
2026-03310
2026-0490
2026-05 (salon closed)10
2026-06 (salon closed)00
2026-077470
2026-084341
2026-09 (forward bookings)1111
2026-10 (forward bookings)33

In July, 70 of 74 appointments came in through online booking. In August it is 41 of 43, and every appointment on the books for September and October arrived the same way. Counting from June, when online booking went live, it is 125 of 131. Those are grooms that landed in her day without a phone ringing mid-clip.

One honest note about that table. The early months are not weak trade. March and April were partial data entry while the system was new, and some of those rows arrived as a bulk import rather than as bookings. May and June are near-empty because the salon was shut: the owner was out of the country. So the only fully representative operating months are July and August, and we are not going to draw a growth curve through a closure.

The Shop Was Shut and the Book Still Filled

The owner splits her year between Lynchburg and Colombia. In May and June the salon was closed and she was out of the country. Nobody was answering a phone, and there was nobody in the shop to answer it.

During June the site took 33 bookings anyway. Thirty-one of them were for July, the month she came back. Her first weeks home were already full before the plane landed, and the calendar had closed itself for the dates she was away, so nobody could book a groom that was never going to happen.

It is happening again as this is written. She flies back on 21 September, and there are already 14 appointments on the books for that trip, every one of them booked online. That is the part worth stealing for any appointment business: the booking does not depend on somebody being free to pick up.

A Client Portal, So the Salon Is Not the Only One Holding the Record

Clients sign in at portal.fancypetsalon.com and see their own dogs: breed, size, notes, visit history. They keep their own contact details current, which means a new phone number or a change of medication reaches the groomer before the appointment instead of being discovered at the table. It runs on the same database as the salon dashboard and the app, so there is one record of a client, not three.

A signup from the portal is matched against the existing book automatically. When the match is uncertain it goes to a review queue rather than silently creating a second copy of somebody who has been coming for two years.

We Deliberately Gave Up National Traffic

Fancy Pet Salon is one groomer in Lynchburg. She cannot serve somebody in Phoenix searching "dog nail clipping", and for a while the site was ranking for exactly that kind of term: thousands of impressions a month, at position 33, converting nobody. We moved the site off national phrasing and onto its own trade area.

The result reads badly if you only look at impressions, and correctly if you look at customers:

Search Console, 28 daysBeforeAfter
Clicks from local searches4444
Local click-through rate2.19%3.36%
National impressions9,6092,240
National queries ranked for1,713458

Local clicks were identical on both sides of the change. Local click-through improved. What went away was 7,369 monthly impressions that had been producing almost nothing: national click-through was 0.27%, against 3.36% locally after the shift.

Why the average position looks worse. It moved from 24.2 to 36.2, and that is the honest consequence of this choice. The old national pages did not disappear, they sank: "dog nail clipping" went from position 33 to position 70 and still logs impressions nobody clicks. Those dead entries drag the average down. It is a metric we accepted getting worse on purpose, because the alternative was keeping traffic that never became a customer.

What Four Months of Real Use Actually Taught Us

Five features in this app work correctly and have never been used once in production:

FeatureUsed in production
Dog photos7 of 138 dogs
Grooming notes on a dog8 of 138 dogs
No-shows marked12, the feature is now in use
Rabies expiry dates0 of 138 dogs
Signed consent forms0

The split is clean enough to be a design rule. The transactional features have total adoption. The reference-data features have none. Anything attached to a moment that was going to happen anyway, an appointment arriving or money changing hands, gets used constantly. Anything that asks a busy person to stop and enter data about a dog for some later benefit sat untouched for four months.

The wrong response to that is more reminders and more empty fields with red asterisks on them. The right response is to move the capture to a moment that already exists. Ask for the rabies date when a dog turns up for its first appointment, not on a profile screen nobody opens. That is what we build next, and it is only visible because the app has been in real hands long enough to show it.

Still Shipping

Builds 37 through 41 went out across 2026-07-29 and 2026-07-30. Rabies dates now surface on the appointment instead of only on the dog's page. A warning flags when the client arriving today missed their last appointment. The price a dog was charged last time is offered back at payment. Tips are recorded separately from the groom price. And 54 drawn breed portraits fill in automatically from the breed field, so a client list without photographs is not a wall of initials.

Two of those, the rabies prompt and the no-show warning, are correct and currently inert, because no rabies date has been entered and no no-show has been marked. That is the same finding as the section above, showing up in the release notes.

The Part Nobody Planned

A book built for one salon turned out to be a book most small grooming shops need. That became PupBooker, the same codebase cut into a separate product through Android build flavours, local-first on the phone with Google Drive backup. It is in closed testing on Google Play right now, free during testing and capped at 15 clients. It is not publicly available, it is not priced, and nobody outside the test group is using it. It is here only as the honest end of the arc: build something specific enough to be genuinely useful to one person, and it tends to be useful to the next hundred.

Results

Same Local Clicks, 77% Less Noise

We moved the site off national terms and onto its own trade area. Local clicks were 44 before the shift and 44 after, while national impressions fell 77%. Local click-through went from 2.19% to 3.36%. Verified in Search Console

95% of Appointments Booked Online

125 of 131 since online booking went live in June, counted in the production database on 2026-08-17. In July it was 70 of 74, in August 41 of 43

$85.87 Average Ticket, 7% No-Shows

Across 131 paid appointments. Page one for "dog groomers Lynchburg VA" and "dog grooming Lynchburg VA", the searches that actually convert

One Book, Four Surfaces

Web dashboard, self-updating Android app, iOS build in TestFlight, and a client portal, all on one SQLite database running 118 client records and 138 dogs

216 Pages

Full coverage of services, breeds, and locations in both languages

Bilingual

Complete EN/ES mirror with hreflang tags and localized SEO

AI Chatbot

Custom Buddy chatbot handling customer inquiries 24/7 in both languages

Automated GBP Posts

Weekly Google Business Profile Updates published automatically to keep the Maps listing active for local search

Want Similar Results?

Let's discuss your project. Free consultation, no strings attached.

Get in Touch
Mr. Botsworth

Mr. Botsworth

Hey! I'm Mr. Botsworth, Greg's search bot. Ask me about his projects, skills, or services.