Client work

Tatycan

A pet-grooming salon in Galapagar, Madrid. We built both halves of its software: the public site where customers book, and the phone-first CRM where the day is run — the agenda, every pet’s history and photos, the money, and Spain’s digital invoicing rules, all in the groomer’s pocket.

The Tatycan salon website home page: services navigation and a prominent online-booking button over a photo of a freshly groomed dog.

The ask

A real business with real customers, and software that finally fits how the work is done.

Tatycan grooms dogs and cats in Galapagar, on the edge of Madrid. The salon wanted what off-the-shelf tools wouldn’t give it: booking that understands breeds and sizes, records organized around pets rather than invoices, reminders that reach customers where they actually read them, and invoicing that satisfies Spain’s new digital-invoicing rules. So they asked for software of their own.

We built it as two small systems instead of one big one — and that separation is most of the story.

What we built

A public half that stores nothing, and a private half that runs the whole salon.

tatycan.com is the public half: fast server-rendered pages in Spanish — services, prices, gallery — and a booking form that validates the breed, size, and service combination and computes the price on the server, so the quote a customer sees is the salon’s real price list, not a guess. A finished booking doesn’t write to a database; it sends the salon a Telegram message. For a one-person salon a booking is the start of a conversation, not a transaction — so the public site holds no accounts and no customer data, and has nothing to breach.

crm.tatycan.com is the private half: the salon’s operating system, built for a phone held in one hand between dogs. Pets are the primary record — owners hang off pets, not the other way around. The agenda blocks double-bookings, every visit carries photos and notes, the finance view knows the day’s takings against categorized expenses, and a completed visit can become a fiscal record the Spanish tax agency can verify. Only names and phone numbers are stored: nothing more is needed, so nothing more is kept.

The Tatycan site on a phone: the salon brand over a groomed dog, with the online-booking button front and centre.
tatycan.com on the device customers actually book from

How it works

Two systems, deliberately separate — they meet in the groomer’s pocket.

Customers browse, pick a service, book tatycan.com the public site — fast pages, no accounts Site pages services · prices · gallery Booking form breed, size & service validated, price computed on the server a Telegram message The groomer’s phone bookings arrive here signs in, runs the day crm.tatycan.com its own system · sign-in only Agenda blocks double-bookings Pets & visits photos & full history Money & tax cash view · fiscal tickets Background engine every 5 min: reminders, confirmations, nightly tax records
Two systems that never talk to each other, and one phone. A booking is a Telegram message, not a database row; the CRM is its own system, and the groomer signs into it from the same phone the bookings arrive on.

Keeping the halves apart is the design, not an accident. The public site cannot lose customer data because it never holds any; the CRM never has to trust input from the open internet. Behind the CRM, one background engine wakes every five minutes during salon hours and does three jobs: WhatsApp appointment reminders, booking confirmations, and the nightly tax paperwork. Each job claims its work atomically — the database itself guarantees a reminder can only be claimed once — so an overlapping or retried run can never message a customer twice.

Inside the CRM

Real product, replaced data: these screens run against a seeded demo dataset — never real customers.

The CRM agenda on a phone: the day's appointments with times, prices, completion status, a blacklist warning tag, and a lapsed-clients list below.
The agenda — with a behaviour warning and the clients who haven't been back
A pet profile in the CRM: temperament tags, client-since and visit-frequency stats, average and total spend, the owner's phone numbers, and the visit history.
A pet's profile — the record the whole CRM is organized around

The hard part: invoices a tax agency can verify

Spain’s VeriFactu rules turn invoicing software into a cryptography problem. We shipped it for a one-person salon.

Under VeriFactu (Royal Decree 1007/2023), invoicing software must produce tamper-evident records: every fiscal record carries a SHA-256 fingerprint of the record before it, forming a chain that cannot be edited without breaking. The CRM issues the day’s simplified invoices nightly, renders each record to the agency’s XML format, and submits it over a mutual-TLS connection. Once a visit is invoiced, its billing fields lock.

Visit completed the groomer charges it Record nº 41 sealed · immutable fingerprint of nº 40 SHA-256 Record nº 42 sealed · immutable fingerprint of nº 41 New record nº 43 hash-chained to nº 42, numbered, then sealed the head is re-checked inside the write — two invoices at once cannot fork the chain Spain’s tax agency (AEAT) XML over mutual TLS · nightly
Every record carries the fingerprint of the one before it, so history cannot be edited without breaking the chain. The hash implementation is pinned to the tax agency’s published test vectors in the test suite — “it matches the spec” is a passing test, not an opinion.

Two details we would defend anywhere: the chain re-checks its head inside the database write itself, so two invoices issued at the same moment cannot fork the chain; and the hash implementation is pinned to the tax agency’s published test vectors in the test suite, so conformance is a passing test rather than an opinion.

Decisions worth noting

  • A booking is a message, not a system. The public site notifies the salon over Telegram instead of writing to a database — no accounts to manage, no data to breach, right-sized for a one-person salon.
  • Dates that cannot lie. Instants are stored as UTC; the Madrid calendar date is computed once, in shared code, and stored beside them — so the agenda and the finance view group by plain dates and stay correct from any device in any timezone. Money is integer cents everywhere.
  • The URL is the state. The active tab, the selected day, the list filters all live in the address bar — every screen survives browser-back and can be shared as a link, and nothing snaps back unexpectedly.
  • Inert until configured. WhatsApp messaging and VeriFactu both ship feature-flagged: empty configuration means off, so no test or preview environment can ever message a real customer or emit a real fiscal record.
  • Photos handled like they matter. Compressed in the browser before upload, location metadata stripped, and served only through the authenticated API — the photo storage is never public.

Built with

  • Cloudflare Workers
  • Hono
  • React
  • D1
  • R2

The same care, on your infrastructure

Cloud, network, and security engagements with a fixed scope and a fixed price — delivered as code you own.