Skip to content
SaaSLive2025

Petzara

Full-stack SaaS for pet shop management — appointments, finances, team, and Stripe subscriptions

React 19Vite 6Tailwind CSS v4Node.js 22Express 5
Runs onWebPWA (phone and computer)Desktop (Electron)
petzara.app
steps to book: pet, service, and date
3
color palettes switched live
4
roles — admin and team member — in the same pet shop
2
installable on phone and computer
PWA

01

Overview

Petzara is a SaaS built from scratch across two separate repositories: a React 19/Vite front end and a Node.js/Express/MongoDB back end. The system is multi-tenant — each pet shop has its own isolated data and can add team members who share the same context in real time via Socket.io. It features JWT authentication with automatic refresh through an httpOnly cookie, a complete subscription system with Stripe (monthly and annual plans, trial, webhooks, and access blocking on expiration), cron jobs that automatically update appointment statuses, and transactional emails sent via Resend.

My role

Solo full-stack developer — architecture, Node.js/Express/MongoDB back end, React 19/Vite front end, Socket.io, complete Stripe integration, Railway deployment, and production maintenance.


Category

SaaS

Year

2025

Status

Live

Platforms

WebPWA (phone and computer)Desktop (Electron)

Two repositories, one product: the React front end talks only to the API, and the API is what knows about tenants, subscriptions, and status. Stripe, Resend, and Socket.io orbit the server — the browser never sees a secret.

React 19 App

Vite · PWA · Railway

Tailwind v4React Router 7Socket.io clientRecharts

Express 5 API

Node 22 · Railway

JWT + refresh httpOnlySocket.ionode-cronStripe webhook

Data and services

MongoDB + integrations

MongooseStripeResendSentry

Sync: Every resource carries the owner's ObjectId; team members inherit the owner and join the same Socket.io room — the same schedule changes for everyone at the same time.


02

The Problem

Pet shops grow by word of mouth but get stuck on operations: the schedule lives in a notebook, client history gets lost in WhatsApp, the team has no view of the day, and finances sit in spreadsheets. As the business grows, this manual process becomes a bottleneck that limits operational capacity.

03 — The Solution

A multi-tenant SaaS with a React PWA front end and a Node.js/MongoDB back end: an appointment schedule with automatic status updates, client/pet/service records, integrated finances, team management with permissions, and Stripe subscriptions with a trial — accessible as an installable app on your phone.


04

Inside the product

The system in action, recorded from the real application with a demo store — no screen is a mockup.

01

Schedule

An appointment in three steps — and the team sees it instantly

Client and pet come from the records, the base service adds the extras to the price, the date comes from a calendar, and the time from a clock. On save, the row enters the list highlighted, the status changes from the table's own menu, and a cron moves the appointment to “In progress” when the time arrives.

  • Price calculated on the spot: base service + selected extras
  • Status Pending → In progress → Completed with automatic cron transition
  • List, month, week, and day over the same data, with filters and search
Schedule
02

Public link

The client picks a time and confirms via WhatsApp

Each pet shop gets its own URL (petzara.app/agendar/name). The public page reads the time grid, the breaks, and the number of simultaneous appointments configured in the dashboard, shows only the open slots for morning and afternoon, and opens the shop's WhatsApp with the message ready — no sign-up, no password.

  • Grid, breaks, and capacity come from the pet shop's Settings
  • Taken slots disappear on their own as the schedule fills up
  • The link can be turned off with a toggle, without deleting anything
Public link
03

Customization

Four palettes, one live switch

Terracotta & Sage, Deep Forest, Muted Ocean, and Earthy Ochre. The choice belongs to the user and becomes two CSS custom properties on the root — sidebar, buttons, charts, and even the logo change without reloading the page.

  • Tailwind v4 tokens pointing to --brand-primary and --brand-secondary
  • SVG logo with one version per palette
  • Preference saved to the account: applies on any device
Customization
04

Finance

From completed appointment to accounts receivable

Each completed appointment generates revenue; the Accounts Receivable tab lists what is still pending and confirms payment with the chosen method. Expenses are entered by category, the cash flow and the expenses pie chart are calculated on the server, and the appointment data can be exported to CSV or Excel by period.

  • Balance, revenue, and expenses for the period with Recharts charts
  • Payment confirmation with Pix, card, or cash
  • XLSX/CSV export generated in the browser from the API
Finance
05

Team

Email invitation and permissions by area

The admin invites by email, sets the department, and checks what the team member can see. The invitation goes out through Resend with an acceptance link; whoever joins gets the same owner, lands in the same Socket.io room, and sees the day's schedule — without seeing the finances unless access is granted.

  • Invitation with an expiration date and acceptance with the person's own password
  • Permissions per module, changeable later
  • Internal notifications by category: schedule, billing, and team
Team
06

First access

Wizard, guided tour, and checklist up to the first appointment

Whoever just created an account sets up the name, business days and hours, and the public link in three screens. Then a tour highlights, item by item, the path to the first appointment — and a checklist on the home screen tracks progress while the trial runs.

  • Trial with an email notice before it expires and a soft block when it ends
  • Tour driven by data-tour: opens and closes the sidebar by itself on mobile
  • Four-step checklist with progress on the home screen
First access
07

Mobile

Built for the counter: drawer menu and bottom-sheet forms

On mobile, the sidebar becomes a drawer, schedule cards replace the table, and the new appointment form slides up as a sheet. The PWA installs on the home screen, and the public link was designed first for the client's phone.

  • One layout, two contexts: full admin and team member focused on the day
  • Chunk error boundary reloads on its own after a deploy
  • Installable as an app, with automatic updates
Mobile

05

8 video walkthroughs

Each video shows a complete task, end to end. Click to watch with controls.


06

Key Features

01

Real-Time Schedule

Appointments with automatic status transitions (confirmed → in progress → completed) via cron job, with instant updates for the whole team through Socket.io.

02

Client and Pet Management

Complete records of owners and pets with service history, notes, and care preferences.

03

Financial Control

Dashboard of revenue, transactions, and business metrics, with data export by period.

04

Team Management

Team records with tiered permissions — team members access only what they need for daily service.

05

Stripe Subscription

Monthly and annual plans with Stripe checkout, a free trial, a payment webhook, and automatic access blocking when the subscription expires.

06

PWA + Public Booking Link

Installable as a phone app via PWA. A public link lets clients book a time without creating an account in the system.


07

Product screens

Real screenshots of the product, organized by module. Click any screen to enlarge it.

Overview: appointments this month, revenue by service, and today's schedule
Appointment statuses and the month mini-calendar
Notification center by category
List with pet, owner, services, price, and per-row actions
Month view
Week with appointments by hour
Day by day, hour by hour
Step 1: client and pet
Step 2: base service and extras
Step 3: calendar and clock
Details with owner, person in charge, notes, and complete
Sort, period, and status filters

08

On mobile

The pet shop owner checks the counter's schedule and the owner books by phone — both screens were designed mobile-first and installed as a PWA.

Home
Menu
Schedule
Calendar
New appointment
Finance
Clients
Notifications
Public link
Confirm
Login

09

Technologies

Front-end

React 19Vite 6Tailwind CSS v4

Back-end

Node.js 22Express 5

Database

MongoDBMongoose

Deployment

Railway

Integrations

StripeSocket.ioResendGoogle OAuthSentry

Libraries

React Hook FormRechartsReact Router 7node-cronvite-plugin-pwa

10

Design Decisions

Four color themes switchable at runtime via CSS custom properties (terracotta, forest, ocean, ochre). The interface is split into two contexts: admin with full management and team member with a view focused on the day's appointments. A guided tour built in through GuidedTourContext onboards new users.

11

Technical Challenges

Stripe's webhook requires the raw body (Buffer) to validate the signature against the secret, but express.json() consumes the body first. Solution: mount the webhook route before any body-parsing middleware. The second challenge: the inline refresh token in authMiddleware that regenerates the access token without rejecting the request — the new token is returned in the X-Access-Token header and captured transparently by the front end's axios interceptor.


12

Results

  • SaaS in production with active appointments and Stripe subscriptions
  • Working multi-tenancy: admin and team members share data in real time via Socket.io
  • Installable PWA on mobile with a public booking link for clients without an account

13

Learnings

  • Two-layer JWT: 15-minute access token + 30-day refresh token in an httpOnly cookie, renewed automatically through an axios interceptor without redirecting the user
  • Multi-tenancy in MongoDB: isolating resources by owner ObjectId, with team members inheriting the admin's context through an owner field
  • Complete Stripe integration: the webhook route must be mounted before express.json() to receive the raw body and validate the signature — a detail that breaks the integration if ignored
  • Socket.io with per-owner rooms: every event (appointments, clients, pets, finances) triggers real-time updates for the admin and team members simultaneously
  • Cron jobs in production: automatic appointment status updates, alerts for trials expiring in 3 days, and automatic expiration of overdue trials