Metaviz AI
SaaS Case Study

AI Field-Service SaaS App

Leads, quotes, jobs, invoicing, payments, dispatch, and an AI Butler — one platform for trade businesses.

A full-stack AI-powered field-service SaaS built mobile-first for Swiss tradespeople — electricians, plumbers, HVAC specialists, carpenters, painters, and contractors. The platform replaces the patchwork of paper notebooks, spreadsheets, and WhatsApp threads small trade businesses run on today. Leads, quotes, jobs, invoices, payments, scheduling, and dispatch all live in one app — across a Flutter mobile app (iOS + Android, offline-first), a React admin panel for the office, and a built-in AI Butler that drafts quotes from voice or photo. Fully live in production with Swiss QR-Rechnung invoicing, Stripe Terminal Tap-to-Pay, TWINT, and English / Deutsch / Français / Italiano.

AI Field-Service SaaS App
Project
AI Field-Service SaaS (Handyman Platform)
Industry
Field Service Management / Trades & Home Services / B2B SaaS
Duration
MVP to Production (Live)
Client
Swiss Trades Market
Overview

Project at a glance

A production-grade, AI-powered field-service SaaS for Swiss trade businesses. The platform unifies the full six-stage business workflow — Lead → Quote → Job → Invoice → Payment → Review — across three surfaces: a Flutter mobile app (iOS + Android, offline-first with SQLite), a React + Vite admin SPA for the office, and an OpenAI / Anthropic / Groq multi-model AI Butler that drafts quotes from voice or photo. Built for the Swiss market with QR-Rechnung invoicing, CHE-UID validation, Swiss VAT (8.1% / 2.6% / 0%), Stripe Terminal Tap-to-Pay, TWINT, and four-language UI (EN / DE / FR / IT).

The Problem

Trade Businesses Are Still Running on WhatsApp, Spreadsheets, and Paper

high pain
  • No single system for the full workflow — electricians, plumbers, and contractors juggled WhatsApp for contact, spreadsheets for quotes, paper for jobs, and separate accounting software for invoices, losing hours every day to admin.
  • Quoting on-site was slow and error-prone — no way to generate a professional, accurate quote at the customer's kitchen table, so jobs were lost to faster competitors.
  • No offline mobile solution — field workers in basements, rooftops, and rural areas had no reliable tool; apps that needed a live connection were useless on real job sites.
  • Swiss compliance was a manual nightmare — QR-Rechnung invoices, correct VAT rates (8.1% / 2.6% / 0%), and CHE-UID validation were done by hand, slowly and with frequent errors that delayed payment.
  • Getting paid on-site was impossible — businesses chased bank transfers for days or carried bulky card terminals; there was no lightweight phone-based payment option.
  • Dispatch was a whiteboard problem — scheduling field workers used physical whiteboards or shared calendars with no live availability, causing double-bookings and missed appointments.
  • Multi-language markets were underserved — Swiss tradespeople work across German, French, Italian, and English cantons, and no tool served all four languages from a single app.
The Solution

How We Built One App to Replace the Entire Trade Business Stack

Metaviz AI built a tri-surface, AI-powered field-service platform — Flutter mobile app, React admin SPA, and AI Butler — all powered by a single FastAPI backend. Every pain point was directly addressed.

1Butler AI — Voice-to-Quote in Seconds: describe a job by voice, text, or photo and Butler drafts the quote instantly. Photo analysis reads faulty appliances, leaking pipes, and broken tiles. Voice runs fully on-device via Sherpa-ONNX so no audio leaves the phone.
2Six-Stage Workflow in One App: capture a lead in the morning, send a quote from the customer's kitchen, complete the job in the afternoon, collect payment before leaving the driveway, and request a review on the way home.
3Offline-First That Actually Works: the Flutter app keeps working with zero signal — jobs, customers, quotes, photos, signatures, and notes stored locally in SQLite, with prioritised background sync on reconnect.
4Swiss QR-Rechnung Invoicing: compliant QR-Bill invoices that scan and pay in every Swiss banking app (PostFinance, UBS, Raiffeisen, ZKB) with per-line VAT, CHE-UID validation, and branded PDF — fully automated.
5Stripe Terminal Tap-to-Pay: take card payments on-site — chip, contactless, and mobile wallet — with no extra hardware; the customer signs on the device and payment reconciles automatically.
6Real-Time Drag-and-Drop Dispatch: office staff drag job cards across team members on a live dispatch board with availability awareness — no double-bookings, no whiteboard, no guesswork.
Before

WhatsApp threads for customer contact; spreadsheet quotes emailed the next day; paper job sheets on clipboards; manual, error-prone QR-Bill creation; cash only or chasing bank transfers; a physical whiteboard for dispatch.

After

One app from lead capture to review; AI Butler drafts quotes in seconds on-site; digital jobs with photos and signatures; automatic Swiss QR-Rechnung generation; Stripe Tap-to-Pay + TWINT on the phone; a real-time drag-and-drop dispatch board.

Ecosystem

The Platform Modules — Six Stages, Three Surfaces, One Backend

Butler AI

Multi-model AI (OpenAI GPT-4o, Anthropic Claude, Groq) that drafts quotes from voice, text, or photo. On-device speech via Sherpa-ONNX — no audio leaves the phone. pgvector semantic search over past quotes and jobs.

OpenAIAnthropicGroqPydanticAIpgvectorSherpa-ONNX

Leads & CRM

Full lead pipeline with source tracking, status management, and one-tap conversion to quote. Replaces the WhatsApp contact flow.

FastAPIPostgreSQLFirebase Cloud Messaging

Quotes Module

On-site quote builder with Swiss VAT line items (8.1% / 2.6% / 0%), deposit %, validity period, branded PDF, and voice-to-quote via Butler AI.

ReportLabPydanticAIFastAPISwiss VAT engine

Jobs & Field Work

End-to-end job management: before/during/after photos, on-device signatures, recurring jobs, templates — all working offline in SQLite.

sqfliteconnectivity_plusimage_pickersignature

Swiss QR-Rechnung

Automated compliant QR-Bill invoice PDF with per-line VAT, CHE-UID validation, cantonal address fields, and postal code validation.

reportlabqrcodeFastAPIasyncpg

Payments

Stripe Terminal Tap-to-Pay, TWINT, Stripe Checkout (subscriptions), manual bank transfer with auto-reconcile, Stripe Connect payouts.

Stripe SDKmek_stripe_terminal@stripe/terminal-js

Dispatch Board

Real-time drag-and-drop scheduling with live availability matrix (available / booked / unavailable / on leave). WebSocket fan-out.

dnd-kitFastAPI WebSocketrole-scoped RBAC

Schedule & Maps

Day/week calendar with OpenStreetMap job pins, service-area radius, address autocomplete and reverse geocoding.

flutter_mapOpenStreetMapLeafletlatlong2

Auth & Security

Passkeys (FIDO2/WebAuthn), Face ID / Touch ID, magic link, Google/Apple sign-in, 2FA. GDPR export and full audit logging.

webauthnlocal_authpython-joseArgon2flutter_secure_storage

Multi-Tenant RBAC

Four roles: Field Worker / Dispatcher / Manager / Admin with calibrated access to quoting, billing, dispatch, and analytics.

FastAPI RBAC middlewarerole-scoped JWT

Multi-Language

EN / DE / FR / IT with one-tap switch. Locale-aware formatting, per-region legal pages (Impressum, Datenschutz, AGB).

flutter_localizationsARB filesi18nextreact-i18next

Subscription Billing

Pro / Business / Enterprise tiers via Stripe Subscriptions — trial-to-paid, seat pricing, Stripe Connect onboarding, usage metering.

Stripe SDKStripe ConnectCelery + Redis
User Experience

Designed for every screen

Web

  • Full leads, quotes, jobs, invoices, and orders management from a desktop browser
  • Real-time drag-and-drop dispatch board with live team availability awareness
  • Stripe Terminal Tap-to-Pay via @stripe/terminal-js for front-desk payments
  • Leaflet + react-leaflet map with job pin clustering and service-area visualization
  • Subscription and billing management dashboard
  • Analytics and reporting with PDF / Excel export
  • Role-based views — Admin / Manager / Dispatcher / Field Worker
  • Full multilingual UI via i18next (EN / DE / FR / IT)
Voice-to-Quote: Open Butler AI → Describe job by voice → Sherpa-ONNX transcribes on-device → GPT-4o drafts quote → Review and send to customerJob Completion: Open job → Before photos (offline) → Complete work → After photos + signature (offline) → Sync on reconnect → QR-Rechnung invoice → Tap-to-Pay → Request reviewOffline Flow: Enter no-signal area → App works fully via SQLite → Cache-age indicator shown → Reconnect → Prioritised background sync runs automatically

Mobile

Platforms: iOS & Android (Flutter), offline-first

  • Offline-first dashboard — all data accessible with zero signal via SQLite local store
  • Lead pipeline: capture, track, and convert leads to quotes from the field
  • On-site quote builder with voice input (Sherpa-ONNX on-device), Swiss VAT line items, deposit %, and branded PDF
  • Butler AI chat — describe a job by voice, text, or photo and receive a drafted quote instantly
  • Job management: before/during/after photo capture, on-device signature, completion notes, recurring jobs
  • Swiss QR-Rechnung invoice generation — one tap, compliant PDF ready to send
  • Stripe Terminal Tap-to-Pay — on-site card payments from the phone, no hardware needed
  • TWINT and manual bank transfer payment options
  • Day/week schedule with OpenStreetMap job pins and service-area radius overlay
  • Push notifications via Firebase Cloud Messaging — new jobs, quote accepted, payment received
  • Passkeys, Face ID / Touch ID biometric login — one-handed in a van
  • One-tap language switch: EN / DE / FR / IT — no app restart
  • Cache-age indicators when offline (e.g. 'viewing cached data from 2h ago')
  • Prioritised background sync on reconnect — status updates first, then signatures, invoices, photos
Admin Dashboard

Full control, behind the scenes

  • Real-time drag-and-drop dispatch board — drag job cards across team members; live availability matrix (available / fully booked / unavailable / on leave); WebSocket fan-out for instant updates
  • Full CRUD on leads, quotes, jobs, invoices, customers, and products/services
  • Swiss QR-Rechnung invoice management — generate, preview, send, and track payment status
  • Revenue dashboard — Stripe subscriptions, Tap-to-Pay, TWINT, bank transfer — all reconciled
  • Team management — invite members, assign roles, set working hours, service areas, exception dates
  • Analytics — job completion rates, revenue per tradesperson, quote conversion rate, average job value
  • Celery background job monitoring via Flower — AI embeddings, notification queues, CSV imports
  • GDPR data export and full audit log on sensitive operations
  • Customer CRM with booking history, communication log, and review management
Roles
AdminManagerDispatcherField Worker
Permissions
Admin — Full access: billing, team management, settings, all data, RBAC managementManager — Quotes, jobs, invoices, analytics, dispatch — no billing or RBACDispatcher — Dispatch board, schedule, job status updates — no billing or quotingField Worker — Own jobs and schedule only — no customer financial data or team views
AI Assistant

Butler AI

An embedded in-app AI assistant (Flutter mobile + React admin SPA) that drafts quotes from voice, text, or photo. Model-routed via PydanticAI — OpenAI GPT-4o for vision, Anthropic Claude for reasoning, Groq for speed. On-device speech via Sherpa-ONNX (no audio leaves the phone) and pgvector RAG over past quotes and jobs so every draft gets smarter over time.

Embedded widget
Voice-to-quote: describe a job out loud, receive a fully drafted, VAT-accurate quote
Photo analysis: photograph a faulty appliance, broken tile, or leaking pipe — Butler identifies and drafts the job
Multi-turn conversation with full message history across sessions
Semantic search across past quotes and jobs via pgvector RAG
Fully on-device speech recognition (Sherpa-ONNX) — no audio sent to any server
Multi-model routing: Groq for speed, GPT-4o for vision, Anthropic Claude for reasoning
Example queries
I need a quote for replacing a 40L electric water heater in Zurich — include parts and 3 hours labour at CHF 95/h
This pipe is leaking behind the wall — what should I charge? (+ photo of the leak)
Draft a quote for repainting a 4-room apartment, 120m², two coats
What was the last quote I did for Müller GmbH?
Show me all jobs with incomplete signatures this week
Architecture

System design

System architecture
Frontend
Flutter (Dart) · Riverpod · GetIt · sqflite · React 19 · TypeScript · Vite · Tailwind CSS · Radix UI · TanStack React Query · dnd-kit · Leaflet + react-leaflet · i18next
Backend
Python 3.11 · FastAPI · uvicorn + gunicorn · SQLAlchemy (async) · asyncpg · Alembic · Pydantic v2 · PydanticAI · Celery + Redis · Celery Beat · reportlab + qrcode · python-jose (JWT) · passlib + Argon2 · webauthn · Stripe SDK
Infrastructure
Coolify (managed Docker Compose) on DigitalOcean · Python 3.11-slim + Node 20-alpine containers · Docker multi-stage builds · nginx reverse proxy · PostgreSQL + pgvector · Redis 7 · Cloudflare + Let's Encrypt TLS · Sentry · structlog (JSON) · Flower
Flutter Mobile App (iOS + Android) — Riverpod + GetIt for state/DI; sqflite (SQLite) offline-first local store; prioritised sync queue with conflict resolution; Sherpa-ONNX on-device speech; mek_stripe_terminal Tap-to-Pay; firebase_messaging push; flutter_map + OpenStreetMap; local_auth + passkeysReact + Vite Admin SPA — React 19 + TypeScript; TanStack React Query; react-hook-form + Zod; Tailwind CSS + Radix UI; dnd-kit dispatch board; Leaflet maps; @stripe/terminal-js; i18next; Firebase Cloud MessagingFastAPI Backend (Python 3.11) — Async FastAPI with uvicorn/gunicorn multi-worker; SQLAlchemy (async) + asyncpg; Alembic migrations; Pydantic v2 + PydanticAI; Celery + Redis (4-worker pool + Beat); FastAPI WebSocket for real-time dispatchMulti-Model AI Layer — OpenAI GPT-4o (vision), Anthropic Claude (long-context), Groq (low-latency); routed via PydanticAI; pgvector for RAG; optional Cohere rerankingSwiss Document Engine — reportlab + qrcode for QR-Rechnung PDF; Swiss VAT engine (8.1/2.6/0%); CHE-UID validation; cantonal address and postal code validation
Business Logic

The rules that run the product

Rules
  • Every entity follows the six-stage lifecycle: Lead → Quote → Job → Invoice → Payment → Review. Stage transitions trigger automated status fan-out via WebSocket and push notification.
  • Quotes carry per-line Swiss VAT rates (8.1% / 2.6% / 0%) and can include deposit percentage and validity period. Accepted quotes auto-convert to Jobs.
  • Swiss QR-Rechnung invoices are generated only after a Job is marked complete and require a valid CHE-UID and IBAN. PDF is generated server-side via reportlab + qrcode.
  • Butler AI is model-routed by task: Groq for low-latency drafts, GPT-4o for vision/photo analysis, Anthropic Claude for complex reasoning. PydanticAI validates all structured outputs.
  • Offline sync follows a strict priority queue: job status updates → signatures → payment records → invoices → photos. Conflict resolution uses server-wins with a local audit trail.
  • Dispatch board respects per-member working hours, service areas, and exception dates. Availability matrix broadcast in real time via FastAPI WebSocket.
  • RBAC enforced at API middleware (FastAPI role-scoped JWT) and UI level. Field Workers can only access their own jobs and schedule.
  • Stripe subscriptions determine feature access tiers. Stripe Connect requires vendor onboarding before Tap-to-Pay or payouts are enabled.
Workflows
  • Voice-to-Quote: Field worker opens Butler → speaks job description → Sherpa-ONNX transcribes on-device → PydanticAI routes to Groq or GPT-4o → structured quote draft returned → worker reviews and sends PDF
  • Job Completion: Job opened → before photos (offline) → work completed → after photos + signature (offline) → sync on reconnect → QR-Rechnung invoice auto-generated → Tap-to-Pay or TWINT → review request sent
  • Dispatch Flow: Manager opens dispatch board → new job card appears → drag to available team member → WebSocket fans out → field worker receives push notification
Automations
  • Celery Beat sends quote follow-up reminders at configurable intervals after sending
  • Firebase Cloud Messaging push sent on quote accepted, job assigned, payment received, and review submitted
  • pgvector embeddings computed asynchronously via Celery whenever a new quote or job is saved
  • Alembic migrations run automatically on deployment via Coolify container startup hooks
  • Stripe webhook handler auto-reconciles payments and updates invoice status within seconds
Features

Everything inside

Butler AI (Voice, Text & Photo)

  • Voice-to-quote: describe a job out loud, receive a fully drafted, VAT-accurate quote
  • Photo analysis: photograph a fault — Butler identifies and drafts the job
  • Multi-turn conversation with full message history across sessions
  • Semantic search across past quotes and jobs via pgvector RAG
  • Fully on-device speech (Sherpa-ONNX) — no audio sent externally
  • Multi-model routing: Groq for speed, GPT-4o for vision, Claude for reasoning

Leads & CRM

  • Lead capture with source tracking (web form, phone, referral, walk-in)
  • Lead status pipeline with one-tap conversion to quote
  • Customer profile with full job and communication history
  • Direct contact shortcuts: phone, WhatsApp, email

Quotes

  • On-site quote builder with Swiss VAT line items (8.1% / 2.6% / 0%)
  • Deposit percentage, payment terms, and validity period
  • Automated follow-up reminders after sending
  • Branded PDF sent via email in one tap
  • One-tap accept — automatic job creation

Jobs & Field Work

  • Full job detail: customer, address, photos, notes, assigned team member
  • Before / during / after photo capture — works offline
  • On-device customer signature — works offline
  • Recurring job scheduling and job templates
  • Real-time job status push to office

Swiss QR-Rechnung Invoicing

  • Compliant QR-Bill PDF generation — one tap after job completion
  • Per-line VAT rates (8.1% / 2.6% / 0%) with CHE-UID validation
  • Cantonal address fields and Swiss postal code validation
  • Compatible with PostFinance, UBS, Raiffeisen, ZKB, and all Swiss banking apps

Payments

  • Stripe Terminal Tap-to-Pay — on-site card, contactless, Apple/Google Pay — phone only
  • TWINT Swiss instant payment
  • Manual bank transfer with automatic reconciliation
  • Stripe Connect onboarding for contractor payouts
  • Pro / Business / Enterprise subscription billing via Stripe Subscriptions

Dispatch Board

  • Real-time drag-and-drop job scheduling (dnd-kit + WebSocket)
  • Live availability matrix per team member
  • Per-member working hours, service areas, exception dates
  • Instant fan-out to office devices and field worker push notifications

Offline-First Mobile

  • Full app functionality with zero signal via SQLite local store
  • Cache-age indicators showing data freshness
  • Prioritised background sync queue on reconnect
  • Works in basements, rooftops, rural areas — wherever the job takes you

Auth & Security

  • Passkeys (FIDO2/WebAuthn) — phishing-resistant, device-native
  • Face ID / Touch ID / fingerprint biometric login
  • Magic link and Google / Apple sign-in
  • 2FA via Twilio Verify (SMS OTP)
  • Argon2 password hashing, iOS Keychain / Android Keystore token storage
  • GDPR data export and full audit logging on sensitive operations

Multi-Language (EN / DE / FR / IT)

  • One-tap language switch — no restart required
  • Compile-time-safe Flutter ARB files for mobile
  • i18next with browser language detection for web admin
  • Locale-aware number, date, and currency formatting
  • Per-region legal pages: Impressum, Datenschutz, AGB Handwerker
Tech Stack

Built on a modern stack

Frontend
Flutter (Dart)RiverpodGetItSherpa-ONNX (on-device speech)mek_stripe_terminalqr_flutterflutter_map + OpenStreetMapfirebase_messaginglocal_authpasskeys (FIDO2)React 19TypeScriptViteTailwind CSSRadix UITanStack React Queryreact-hook-form + Zoddnd-kitLeaflet + react-leaflet@stripe/terminal-jsi18next + react-i18next
Backend
Python 3.11FastAPIuvicorn + gunicornSQLAlchemy (async)asyncpgAlembicPydantic v2PydanticAIOpenAI GPT-4oAnthropic ClaudeGroqCelery + Redis + Celery Beatreportlab + qrcodepython-jose (JWT)passlib + Argon2webauthnStripe SDK
Database
PostgreSQL + pgvector (primary + vector search)Redis 7 (Celery broker + app cache)SQLite via sqflite (mobile offline store)
DevOps
Coolify (managed Docker Compose)DigitalOceanPython 3.11-slim + Node 20-alpine containersDocker multi-stage buildsnginx reverse proxyCloudflare + Let's Encrypt TLSSentrystructlog (JSON)Flower (Celery monitoring)
Tools
Stripe Switzerland · Stripe Connect · Stripe Terminal · Stripe Checkout · Stripe Subscriptions · TWINTFirebase Cloud Messaging · Firebase Realtime Database · SendGrid · Twilio VerifyPydanticAI (model routing) · Cohere (optional reranking) · Sherpa-ONNXCloudinary (vendor media CDN) · image_picker + file_picker · WebP optimizationOpenStreetMap + Nominatim · latlong2 · geolocator · geocoding
Results

Outcomes that move the business

~40%
Feature-development time cut
4 (EN / DE / FR / IT)
Languages supported
3
Client surfaces from one backend
3
AI model providers routed
  • Shipped a tri-surface SaaS (Flutter mobile + React admin + AI Butler) from a single FastAPI backend — cutting feature-development time by ~40% with zero API drift across clients
  • Integrated three AI model providers (OpenAI, Anthropic, Groq) through a single PydanticAI routing layer — giving Butler the right model for every task
  • Built fully on-device speech recognition via Sherpa-ONNX — voice input works offline, no audio ever leaves the phone, solving both privacy and connectivity
  • Generated compliant Swiss QR-Rechnung invoices automatically via reportlab + qrcode — eliminated manual QR-Bill creation
  • Implemented passkey (FIDO2/WebAuthn) authentication on Flutter and web — phishing-resistant, biometric-first login for field workers
  • Delivered four-language support (EN / DE / FR / IT) with one-tap switching, locale-aware formatting, and per-region legal pages

Customer-day compression: capture a lead in the morning, send a quote from the customer's kitchen, complete the job in the afternoon, and collect payment before leaving the driveway — all from one app. Eliminated the WhatsApp + spreadsheet + paper + separate-accounting stack. Offline-first SQLite keeps field workers productive in basements, rooftops, and rural job sites with automatic prioritised sync on reconnect. Stripe Terminal Tap-to-Pay turns every phone into a card reader — no terminal, no invoice chasing.