Fiesta Fitnes
Fitness studioPančevo, Serbia
Trial requests land in a sheet with real statuses, and the studio confirms every one by phone.
Status
Services
- Website · Booking & orders · Lead pipeline & CRM · Automations
Year
2026
Results
Not measured yet.

The problem
The old site's main button asked visitors to book a trial training, but behind it sat only a contact form, with no pipeline. One contact page showed raw shortcodes instead of content. The trust counters rendered as zero without JavaScript.
What we built
- A static site with 21 page templates and 29 blog posts moved over from WordPress.
- A 4-step trial request: program, preferred day and part of day, contact, review.
- Gift voucher and contact forms on the same backend.
- A Google Sheet CRM with separate tabs for trial requests, messages and vouchers.
- Statuses NEW → CONTACTED → CONFIRMED, then COMPLETED or REJECTED. Rows recolour by status.
- A studio email with Call and Reply buttons, and a confirmation with a request code for the visitor.
- A Config tab for recipients, rate limits and a pause switch. No developer needed.
- A 301 map for every changed WordPress URL, so existing links keep working.
How it works
The flow end to end, as the system is built to run. Sheet and status names are the client's own.
09 steps · 1 sheet
- Program
- Day and part of day
- Contact and consent
- Review and send
- Checks and rate limits
- Sheet row · NEW
- Studio and visitor emails
- Studio calls back
- CONFIRMED
Under the hood
The details a developer checks first. Most of them exist so an inquiry is never lost or sent twice.
- Idempotent writes. The same request ID returns the same result, and the same phone, date and part of day count as a duplicate, even from a new tab.
- Rate limits per phone and across the whole form, each with its own message.
- A spam quarantine that can't lock out a real person whose password manager fills the hidden field.
- The response carries the real email outcome, and the sheet records it on every row.
- A timeout means unknown outcome and a status check, not a blind resend.
- Server validation rejects impossible dates like 31 February.
- A pause switch in the Config tab stops new requests without touching code.
- The build refuses to ship pointing at localhost, and tests refuse to touch the real sheet.
Stack
What it runs on.
- Astro · TypeScript · Google Apps Script · Google Sheets · MailApp · Playwright · Netlify
Build QA
From our own test runs before launch. These are build numbers, not business results.
- astro check on 46 files: 0 errors, 0 warnings, 0 hints.
- Interaction audit: 96 page and viewport runs, 132 buttons, 0 problems.
- Responsive audit of every page at 7 widths: no findings.
- Backend health check on 22 September 2026: live and connected to the sheet.
What we didn't build, on purpose
Scope is a decision. Every line here was decided, not forgotten.
- Not a booking system. Visitors request a day and part of day, and the studio confirms the exact time by phone.
- No slots, no capacity, no slot-taken errors. The first version had them. We removed them.
- No Calendly or Cal.com. The right tool for high volume, the wrong one for a handful of trial requests.
- No voucher sales. Vouchers are requested, never purchased, and never marked as issued.
- No ratings in the structured data. Tests check that none sneak in.
The build
Captured from our local pre-launch build. Phone numbers, email addresses, prices and photos of people from the client's site are blurred wherever they appear.



