devsnack
Documentation

ServeAI documentation

Run it, point it at your own accounts, ship it under your own brand. Written against version 0.1.0 of the download you get on CodeCanyon.

$19 on CodeCanyon
  • Version v0.1.0
  • Updated
  • Platform Flutter
  • Stack Flutter · Next.js
On this page
01

Overview

A complete 3-in-1 package: Next.js backend + admin panel, plus two Flutter apps — one for customers, one for providers. Book, track, pay, chat, review. Built for home services, handyman, beauty, tutoring, or any location-based on-demand marketplace.

Live demo: serveai.devsnack.dev · Quick start: quick-start.html

ServeAI is a complete on-demand services platform sold as a single purchase. Inside the ZIP you get three tightly-integrated applications:

  • Customer app (Flutter 3 · Riverpod 3) — Browse categorized services, get an AI-powered price estimate, pick packages and add-ons, attach any documents the service requires, book with a card / wallet / cash, watch the provider arrive in real time, chat, pay, review.
  • Provider app (Flutter 3 · Riverpod 3) — Onboarding + document upload, real-time job feed, accept / decline, status transitions, live location broadcast, chat, request extra charges, track earnings, request payouts. Agency owners also invite workers and dispatch jobs.
  • Admin panel + backend (Next.js 16 · Drizzle ORM) — Everything you need to run the platform: services / categories CRUD, bookings oversight, customer document review, provider approvals, agencies, coupons, earnings, payouts, feature flags, maintenance mode, audit log, admin notifications. All on the same Next.js server that powers the mobile API.

Use cases. The code is domain-agnostic — we ship it seeded with home services, but the same engine works for handyman, beauty & wellness, car detailing, tutoring, pet care, moving help, any location-based on-demand marketplace.

Two verticals, one codebase. Alongside the physical on-demand model, ServeAI supports digital service / cyber cafe businesses — passport and ID applications, tax registration, banking paperwork, online form filling. Turn on the documents_enabled flag and services can require customers to attach documents at booking time, which an admin then reviews. Same backend, same apps, different default content.

02

Architecture

One Next.js server handles both the admin panel and the mobile API, with Socket.IO attached for real-time updates. Postgres lives on Neon (serverless). Stripe handles payments behind an abstraction so you can add other providers later. Cloudflare R2 stores photos, provider credentials, and customer booking documents — always via short-lived presigned upload URLs, with a per-namespace role policy so a provider can’t write into customer document storage.

architecture
                         ┌──────────────────────────┐
                         │      Neon Postgres       │
                         │   (Drizzle ORM schema)   │
                         └────────────┬─────────────┘

   ┌───────────────────┐    ┌─────────┴──────────┐    ┌──────────────────┐
   │   Customer App    │◄──►│   Next.js server   │◄──►│  Admin Panel     │
   │   (Flutter)       │    │   /api/* + /admin  │    │  (Next.js UI)    │
   └───────┬───────────┘    │   + Socket.IO      │    └──────────────────┘
           │                └──────┬────┬────────┘
           │                       │    │
   ┌───────┴───────────┐           │    │         ┌──────────────────┐
   │   Provider App    │◄──────────┘    ├────────►│  Stripe Connect  │
   │   (Flutter)       │                │         │  (webhooks)      │
   └───────────────────┘                │         └──────────────────┘

                           ┌────────────┼────────────┐
                           │            │            │
                  ┌────────▼──────┐ ┌───▼────┐ ┌────▼──────────┐
                  │  Firebase     │ │   R2   │ │  AI provider  │
                  │  Auth + FCM   │ │ bucket │ │  (OpenAI /    │
                  └───────────────┘ └────────┘ │   Gemini)     │
                                               └───────────────┘
Note

Why not next dev?

Socket.IO is attached to a custom HTTP server (web/server.ts), which is why the dev command is npx tsx server.ts, not next dev. If you start the app with Next’s built-in dev server you’ll get HTTP routes but no real-time.

03

Customer app features

Catalog & discovery

  • Browse service categories
  • Service detail with packages + add-ons
  • Featured services carousel
  • AI-powered price estimation (when AI enabled)

Booking wizard

  • Package → schedule → address → review → confirm
  • A documents step appears only for services that require one
  • Coupon apply with live preview
  • Pay by card (Stripe sheet), wallet, or cash
  • Before/after photo uploads

Document upload

  • Attach images or PDFs — ID proof, address proof, photo, signature, forms
  • Mandatory documents block the wizard; optional ones don’t
  • Review status per document, with the admin’s note when something’s wrong
  • Re-upload in place when an admin requests a replacement
  • Approved documents are frozen — they can’t be silently swapped out

Real-time tracking

  • Provider location on a map while en route
  • Status transitions push-notified
  • In-booking chat with the provider
  • Reschedule or cancel with refund

Account

  • Wallet with top-up (Stripe) and transactions
  • Referral codes
  • Saved addresses
  • Booking history + reviews
04

Provider app features

Onboarding

  • Multi-step signup wizard
  • ID + certification document upload to R2
  • Service selection with custom pricing
  • Weekly availability editor
  • Status gated — PENDINGAPPROVED by admin

Job flow

  • Live job feed with push notifications
  • Accept / decline from lock screen
  • State machine: ACCEPTEDEN_ROUTE ARRIVEDIN_PROGRESSCOMPLETED
  • Live location broadcast while en route
  • Request extra charges (customer approves)
  • Read-only view of the customer’s approved documents

Earnings

  • Per-booking earnings with commission + agency cut breakdown
  • Wallet balance + history
  • Payout requests (Stripe Connect transfer)

Agency mode

  • Owners create an agency and invite workers by phone
  • Dispatch incoming jobs to any approved worker
  • Configurable owner-cut percentage
  • Workers still accept/decline via the same job flow
05

Admin panel features

Catalog & pricing

  • Categories (hierarchical)
  • Services with R2 photo uploads
  • Packages & add-ons editor
  • Per-service required-documents editor (type, label, required/optional)
  • Coupons (flat or percentage, usage limits, expiry)

Operations

  • Bookings list + detail with full audit trail
  • Document review — approve, reject, or request a re-upload with a note
  • Outstanding-documents banner so you can chase what’s missing
  • Providers directory + approve / suspend
  • Agencies directory + owner-cut override
  • Customers directory with wallet + booking history

Money

  • Transactions ledger (bookings, refunds, commissions, payouts)
  • Payout requests queue with approve / reject
  • Earnings + revenue charts
  • Configurable commission rate

Platform

  • Feature flags (AI, chat, cash, wallet, documents) — instant toggle
  • Maintenance mode with banner shown in both apps
  • AI provider switch (OpenAI ↔ Gemini)
  • Broadcast push notifications
  • Reviews moderation with admin replies
  • Email composer via Resend
06

Tech stack

LayerTechnologyVersion
Backend framework
Next.js (App Router)
16.x
Database
PostgreSQL on Neon (serverless)
ORM
Drizzle ORM + drizzle-kit
0.45 / 0.31
Real-time
Socket.IO on a custom Next server
4.8
Admin auth
NextAuth v5 with Drizzle adapter
5.0 beta
Mobile auth
Firebase Admin SDK → platform JWT
14.x
Payments
Stripe Connect (pluggable PaymentProvider)
22.x
AI
Vercel AI SDK — OpenAI or Gemini
7.x
Object storage
Cloudflare R2 (S3-compatible)
Email
Resend
6.x
Admin UI
React 19 + Radix UI + Tailwind v4
Mobile framework
Flutter (Dart SDK ≥ 3.12)
3.x
Mobile state
Riverpod (hand-written models, no codegen)
3.4
Mobile routing
GoRouter
17.x
Mobile HTTP
Dio
5.11
Mobile push
firebase_messaging + flutter_local_notifications
16.x / 22.x
Mobile maps
google_maps_flutter
2.18
Mobile payments
flutter_stripe
14.x
Testing
Vitest (backend) + flutter_test + mocktail + http_mock_adapter
07

Database schema

All tables live in web/lib/db/schema.ts as Drizzle definitions. Migrations are generated with drizzle-kit generate and applied with drizzle-kit migrate (automatically on Railway boot via the start:migrate script).

Core entities

admins
Admin-panel operators with roles (SUPER_ADMIN, MANAGER)
users
Customers — email, phone, wallet, referral code
providers
Service providers — status, rating, wallet, payment account, optional agency
provider_documents
Uploaded IDs and certifications per provider
agencies
Provider collectives with an owner and configurable owner commission rate

Catalog

categories
Hierarchical service categories (parent_id supports subcategories)
services
Individual services with base price, unit, featured flag
service_photos
Gallery images per service
service_packages
Tiers (Basic / Standard / Premium) with price + duration
service_addons
Optional extras a customer can toggle during booking
service_required_documents
What a customer must attach to book this service — document type, label, required/optional
provider_services
Join table — which services each provider offers, with optional custom pricing
availability
Provider weekly schedule (day of week + start/end time)
addresses
Customer saved addresses with lat/lng
coupons
Discount codes — flat or percentage, with limits and expiry

Bookings & money

bookings
Core booking record — status, schedule, price breakdown, payment status, optional coupon, extra-charge fields, live provider location
booking_addons
Add-ons picked at booking creation (snapshot of price)
booking_photos
Before/after images attached by the provider
booking_documents
Customer-uploaded documents with review status (PENDING / APPROVED / REJECTED / REUPLOAD_REQUESTED), the admin’s note, and who reviewed it
reviews
Customer review per completed booking
transactions
All money movements — payments, refunds, commissions, agency cuts, payouts
earnings
Per-booking provider earnings with commission + agency cut + net
payout_requests
Provider withdrawal requests, approved/transferred by admin

Messaging & platform

chat_messages
In-booking chat between customer and provider
notifications
In-app notification inbox
fcm_tokens
Registered device tokens (scoped to user or provider)
refresh_tokens
Mobile refresh tokens for JWT rotation
settings
Key/value runtime configuration (feature flags, commission rate, AI provider, mock flags)
08

Feature flags

Runtime flags live in the settings table and are exposed to the mobile apps via GET /api/config. The admin panel’s Settings page edits them live — no redeploy, no rebuild of the mobile apps. Server routes also enforce disabled flags (they return 400) so the apps can’t slip past with stale cached values.

KeyDefaultEffect when disabled
ai_features_enabled
true
AI price-estimate UI hidden; server rejects AI calls
chat_enabled
true
Chat tab hidden; POST /chat returns 400
cash_payment_enabled
true
Cash option hidden in the wizard; booking with CASH returns 400
wallet_enabled
true
Wallet option hidden; booking with WALLET returns 400
documents_enabled
false
Document step, cards and admin review hidden; the documents routes return 400. This is the one flag that defaults off — it’s the digital-services vertical, so a home-services install never sees it unless you switch it on.
maintenance_mode
false
When true, both apps show a banner; existing flows stay available
maintenance_message
(empty)
Text rendered in the maintenance banner
commission_rate
0.15
Platform commission applied to each booking’s subtotal
ai_provider
openai
Switches between OpenAI and Gemini at request time
mock_purchase
true in dev
Short-circuits Stripe calls to a fake success path
mock_subscribe
true in dev
Reserved for future subscription flows
09

Backend setup

Full setup is documented in README.md at the repo root. The highlights below cover what’s unique to each surface; follow the README for the exact commands in order.

terminal
cd web
npm install
cp ../.env.example ../.env.local   # edit — see §Setup — env vars below
npx drizzle-kit migrate
npm run db:seed                    # demo data: admin, providers, customer, bookings
npx tsx server.ts                  # dev server on :3000 (NOT "next dev")

Admin panel: http://localhost:3000/admin. Seeded admin: admin@serveai.dev / password123.

Neon Postgres

  1. 01
    Create a Neon project at neon.tech.
  2. 02
    Copy the pooled connection string from the dashboard.
  3. 03
    Paste into DATABASE_URL in .env.local — make sure it ends with ?sslmode=require.
10

Firebase setup

  1. 01
    Create a Firebase project (or one per app — customer and provider can share).
  2. 02
    Enable Authentication (Email/Password) and Cloud Messaging.
  3. 03
    For each Flutter app, run flutterfire configure — this writes firebase_options.dart, drops google-services.json on Android, and GoogleService-Info.plist on iOS.
  4. 04
    Download a service account JSON (Project Settings → Service accounts → Generate new private key).
  5. 05

    In .env.local, fill:

    .env.local
    FIREBASE_PROJECT_ID=your-project-id
    FIREBASE_CLIENT_EMAIL=firebase-adminsdk-...@your-project.iam.gserviceaccount.com
    FIREBASE_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n"
  6. 06
    Flip MOCK_AUTH=false once the keys are in.
11

Payments (Stripe)

  1. 01
    Create a Stripe account and enable Connect (Express accounts).
  2. 02
    In .env.local, set STRIPE_SECRET_KEY, STRIPE_PUBLISHABLE_KEY, STRIPE_WEBHOOK_SECRET.
  3. 03
    Flip MOCK_PURCHASE=false.
  4. 04
    Add a webhook in the Stripe Dashboard pointing at https://<your-domain>/api/payments/webhook.
  5. 05
    For the Flutter customer app, pass the publishable key at build time: --dart-define=STRIPE_PUBLISHABLE_KEY=pk_live_...
Note

PaymentProvider abstraction

All Stripe code is confined to web/lib/payments/stripe.ts. Everything else (routes, services, UI) goes through the PaymentProvider interface in provider.ts. To add PayPal, Razorpay, or local wallets later, implement the interface in a new file and register it in the factory in index.ts — no call-site changes.

12

AI providers

  1. 01
    Grab an API key from OpenAI or Google AI Studio (or both).
  2. 02
    Set OPENAI_API_KEY and/or GEMINI_API_KEY in .env.local.
  3. 03
    In admin panel → Settings, pick which provider to route AI calls to. No redeploy.
13

Storage (R2)

  1. 01
    Create a Cloudflare R2 bucket from the Cloudflare dashboard.
  2. 02
    Create an API token with object read/write on that bucket.
  3. 03
    Expose the bucket on a custom domain or use the r2.dev preview URL.
  4. 04

    Fill the R2 block in .env.local:

    .env.local
    R2_ACCOUNT_ID=...
    R2_ACCESS_KEY_ID=...
    R2_SECRET_ACCESS_KEY=...
    R2_BUCKET=...
    R2_PUBLIC_URL=https://cdn.your-domain.com
14

Google Maps key (no-commit workflow)

The key never needs to touch git. Pick one path per platform.

Android — three options, in order of preference

  1. 01

    User-global gradle properties

    Edit ~/.gradle/gradle.properties (Windows: %USERPROFILE%\.gradle\gradle.properties) and add one line:

    gradle.properties
    MAPS_API_KEY=AIzaSy...

    Every Flutter project on this machine, every build, picks it up. This is the recommended path — it works outside the repo entirely.

  2. 02

    Environment variable

    Good for CI/CD:

    terminal
    export MAPS_API_KEY=AIzaSy...
    flutter build appbundle --release
  3. 03

    Per-project local.properties

    In customer_app/android/local.properties (and the provider equivalent) add:

    local.properties
    maps.api.key=AIzaSy...

    local.properties is gitignored by Flutter defaults.

iOS

Each app ships a tracked template. Copy it once and fill in your key:

terminal
cp customer_app/ios/Flutter/Secrets.xcconfig.example customer_app/ios/Flutter/Secrets.xcconfig
cp provider_app/ios/Flutter/Secrets.xcconfig.example provider_app/ios/Flutter/Secrets.xcconfig
# edit each file → MAPS_API_KEY = AIzaSy...

The real Secrets.xcconfig is gitignored. Debug.xcconfig and Release.xcconfig optional-include it, Info.plist reads $(MAPS_API_KEY) into the GMSApiKey entry, and AppDelegate.swift passes it to GMSServices.provideAPIKey.

15

Android release signing

By default, release builds fall back to debug keys so flutter run --release works without extra setup. Play Store rejects debug-signed AABs, so for your own submission you’ll generate an upload keystore and wire it via a gitignored key.properties file.

Note

Upload key vs. app signing key

Since August 2021 Google enrolls every new app in Play App Signing — Google holds the actual app signing key and re-signs the APKs delivered to devices. Your keystore is the upload key: Play verifies your uploads with it but isn’t the same key users install with. Practical effect: if you lose your upload key you can reset it via a Google support ticket, but you still need to keep it safe.

1. Generate the upload keystore

One keystore per app. Run from each app’s android/ directory:

terminal
cd customer_app/android
keytool -genkey -v -keystore upload.jks \
  -keyalg RSA -keysize 2048 -validity 10000 \
  -alias upload

Keytool will ask for a store password, key password, and your name/org. Use strong passwords and save them somewhere durable (a password manager, not a Post-it).

Warning

Back up the keystore before building anything with it

If you lose the upload.jks file you can recover via Google’s reset flow (a few days’ turnaround). If you lose the passwords you may still recover. But the safer habit: back up the .jks and the passwords to an offline location — losing both means you publish updates under a new upload identity, which is extra friction you don’t want.

2. Create key.properties

In customer_app/android/key.properties (gitignored — the .gitignore already covers it):

customer_app/android/key.properties
storeFile=upload.jks
storePassword=your-store-password
keyAlias=upload
keyPassword=your-key-password

Repeat for provider_app/android/ — a separate keystore, a separate key.properties. They’re different apps, so Play treats them as different listings.

3. Build the AAB

terminal
flutter build appbundle --release -PMAPS_API_KEY=AIzaSy...

Once key.properties exists, android/app/build.gradle.kts picks it up automatically via the release signingConfig. Output: build/app/outputs/bundle/release/app-release.aab.

4. First Play Console upload

  1. 01
    Create a Google Play developer account ($25 one-time) at play.google.com/console.
  2. 02
    Create a new app. Use the exact applicationId from build.gradle.kts (com.devsnack.serveai.customer / .provider, or whatever you renamed them to).
  3. 03
    Fill out the store listing (title, short/full description, icon, feature graphic, screenshots, privacy policy URL).
  4. 04
    Complete the content rating questionnaire and data-safety declaration.
  5. 05
    Release → Production (or Internal testing for a quick test track) → Create new release → upload the .aab.
  6. 06
    Play enrolls the app in Play App Signing on first upload. Confirm the dialog.
  7. 07
    Submit for review. First review is 1–7 days.

5. Subsequent releases

Bump version in pubspec.yaml (e.g. 0.1.1+2), rebuild the AAB, upload to the same release track. Play handles the upgrade migration automatically.

16

iOS code signing

iOS signing needs one up-front Apple Developer Program enrollment, then mostly lives inside Xcode. The Flutter build system takes care of the rest — you’ll only touch signing manually if you set up CI/CD later.

1. Apple Developer Program

  1. 01
    Enroll at developer.apple.com/programs ($99/year). Individual or organization account — organization needs a D-U-N-S number and takes a few days.
  2. 02
    Once active, you get access to Certificates, Identifiers & Profiles, and to App Store Connect.

2. Register bundle IDs

Register each app’s bundle ID under Certificates, Identifiers & Profiles → Identifiers → App IDs:

  • com.devsnack.serveai.customer (or your rename)
  • com.devsnack.serveai.provider (or your rename)

Enable the Push Notifications capability on both — FCM delivers iOS pushes through APNs.

3. Signing inside Xcode (automatic — recommended)

For each app:

  1. 01
    Open the Xcode workspace (not the .xcodeproj directly): open ios/Runner.xcworkspace.
  2. 02
    Select the Runner target → Signing & Capabilities tab.
  3. 03
    Tick Automatically manage signing.
  4. 04
    Pick your Team from the dropdown. Xcode creates (or picks up) a development certificate and provisioning profile for that team + bundle ID.
  5. 05
    Confirm Bundle Identifier matches the ID you registered in Apple Developer.
  6. 06
    Add the Push Notifications capability from the “+ Capability” button.

Repeat for the provider app (separate Xcode workspace, separate bundle ID).

4. APNs auth key for FCM pushes

FCM needs to talk to APNs on your behalf. A single APNs auth key covers all your apps across both development and production, so you only do this once per Apple developer account.

  1. 01
    Apple Developer → Certificates, Identifiers & Profiles → Keys+.
  2. 02
    Name it “ServeAI APNs”, tick Apple Push Notifications service (APNs), Continue, Register.
  3. 03
    Download the generated .p8 file. You can only download it once — save it somewhere durable.
  4. 04
    Note the Key ID shown on screen and your Team ID (top-right of the developer dashboard).
  5. 05
    Firebase Console → Project settings → Cloud Messaging tab → under the iOS section, upload the .p8 file and paste the Key ID + Team ID.

5. Build and archive

From the Flutter project root:

terminal
cd customer_app
flutter build ipa --release \
  --dart-define=API_BASE_URL=https://your-backend.up.railway.app \
  --dart-define=STRIPE_PUBLISHABLE_KEY=pk_live_...

Output: build/ios/ipa/customer.ipa. For submission, open the generated archive in Xcode:

terminal
open build/ios/archive/Runner.xcarchive

Xcode’s Organizer opens. Click Distribute App App Store ConnectUpload. Xcode validates, signs for distribution using your team’s distribution certificate, and uploads to App Store Connect.

6. TestFlight & App Store

  1. 01
  2. 02
    My Apps → + → create a new app using the bundle ID you registered.
  3. 03
    Once the upload finishes processing (10–30 min), it appears under TestFlight. Add internal testers immediately; external testers need a quick Beta App Review.
  4. 04
    For a production release: App Store tab → fill metadata, screenshots (required sizes: 6.9", 6.5", 5.5" for iPhone; 13" for iPad), submit for App Review. First review is 1–3 days.

7. Subsequent releases

Bump the version in pubspec.yaml, rebuild the IPA, upload — App Store Connect keeps the history per version.

Note

Manual signing / CI-CD

Automatic signing works for one developer on one Mac. If you set up CI (fastlane, Codemagic, Xcode Cloud), switch to manual signing and export your distribution certificate as a .p12 plus the matching provisioning profile. Load both into the CI environment as secrets, and point Xcode at them via CODE_SIGN_IDENTITY and PROVISIONING_PROFILE_SPECIFIER build settings.

17

Run the mobile apps

terminal
# Customer app
cd customer_app
flutter pub get
flutter run \
  --dart-define=API_BASE_URL=http://10.0.2.2:3000 \
  --dart-define=STRIPE_PUBLISHABLE_KEY=pk_test_xxx

# Provider app (same flags, separate emulator/device)
cd ../provider_app
flutter pub get
flutter run --dart-define=API_BASE_URL=http://10.0.2.2:3000

On Android emulator, 10.0.2.2 is the host. On iOS simulator, use localhost or your LAN IP.

18

Deployment

Full step-by-step Railway recipe is in section 6. Deploy to Railway of the project README.md — TL;DR: push to GitHub, point Railway at the repo, paste env vars, done. Drizzle migrations run automatically on boot via the start:migrate script.

19

Customization

Branding

Primary / secondary / surface colors
customer_app/lib/core/theme/*, provider_app/lib/core/theme/*, web/app/globals.css
Logo (SVG + PNG)
assets/brand/ in each Flutter app, web/public/brand/
Launcher icon
assets/icon/ in each Flutter app (regenerate with dart run flutter_launcher_icons)
Splash screen
flutter_native_splash section in pubspec.yaml (regenerate with dart run flutter_native_splash:create)
App display name
android:label in each AndroidManifest.xml, CFBundleDisplayName in each Info.plist
Bundle / package ID
applicationId in android/app/build.gradle.kts, PRODUCT_BUNDLE_IDENTIFIER in Xcode

Platform behavior

  • Commission rate — admin panel → Settings. Falls back to PLATFORM_COMMISSION_RATE env var (default 0.15).
  • Agency owner cut — per-agency in the admin panel; default 0.1 (10%).
  • Service minimum order — per-coupon min_order_value column.
  • Feature flags — admin panel → Settings (see Feature flags table above).

Adding a payment provider

  1. 01
    Create web/lib/payments/<name>.ts exporting a class that implements the PaymentProvider interface in provider.ts.
  2. 02
    Register it in web/lib/payments/index.ts (the factory returns the active provider based on a setting).
  3. 03
    Add the provider key to the admin panel’s Settings page.
  4. 04
    No call-site changes — every route and service imports from lib/payments/index.ts, never directly from Stripe.

Adding a language

English ships. The stack is wired for i18n from day one:

  • Web — add an ARB equivalent under web/messages/, register in next-intl config.
  • Customer app — add an ARB file under customer_app/lib/l10n/, regenerate with flutter gen-l10n.
  • Provider app — same pattern under provider_app/lib/l10n/.
20

Production checklist

Before flipping your live site from demo to production:

#ActionWhere
1
Flip MOCK_AUTH, MOCK_PURCHASE, MOCK_SUBSCRIBE to false
Railway env vars
2
Fill real Firebase service account
FIREBASE_* in Railway env
3
Fill real Stripe live keys + production webhook secret
STRIPE_* in Railway env
4
Configure your own Google Maps key (see Google Maps key)
~/.gradle/gradle.properties + ios/Flutter/Secrets.xcconfig
5
Generate upload keystores for both Android apps
{customer,provider}_app/android/key.properties
6
Register bundle IDs on Play Console + App Store Connect
Google Play / Apple developer dashboards
7
Register Stripe Connect webhook at /api/payments/webhook
Stripe Dashboard
8
Populate settings defaults via admin panel
Admin → Settings
9
Seed service categories, services, packages, add-ons
Admin → Categories / Services
10
Approve initial providers so the catalog isn’t empty
Admin → Providers
Warning

Rotate the demo Maps key

If you used the seller’s demo Google Maps key while evaluating, rotate your own at console.cloud.google.com before shipping — shared keys get throttled or banned.

21

Changelog

Every version published so far. Updates are free for the life of the item.

v0.1.0
Initial release — Next.js 16 backend on Neon, customer and provider Flutter apps, 20-page admin panel, Stripe Connect with mock mode, realtime tracking and chat, FCM push, AI price estimation, 270+ automated tests.

v0.2.0 — Customer documents & dependency refresh

  • Customer document upload. Services can require documents (ID proof, address proof, photo, signature, form, other); customers attach them during booking; admins approve, reject, or request a re-upload with a note. Off by default behind documents_enabled.
  • New booking_documents and service_required_documents tables, plus a customer-only booking-documents R2 namespace.
  • Providers see approved documents read-only; approved documents can’t be superseded.
  • The booking wizard’s step list is now derived from the service instead of a fixed five steps.
  • Dependencies brought up to date across all three apps — Riverpod 3, GoRouter 17, Firebase 4/6/16, flutter_stripe 14, flutter_local_notifications 22, flutter_secure_storage 11, ESLint 10, AI SDK 7, TanStack Table 9, firebase-admin 14.
  • Removed an unused code-generation stack (Freezed, json_serializable, Retrofit, build_runner) — models were already hand-written.
  • Android compileSdk raised to 37; Dart SDK floor is now 3.12.

v0.1.0 — Initial release

  • Next.js 16 backend + Drizzle ORM on Neon
  • Customer + Provider Flutter apps (Riverpod 2)
  • Admin panel with 20 pages (catalog, operations, money, platform)
  • Stripe Connect payments with mock mode for dev
  • Real-time tracking, chat, and status updates over Socket.IO
  • FCM push notifications + notification inbox
  • AI price estimation with OpenAI / Gemini switch
  • Agency feature — owner invites workers, configurable commission split
  • Wallet + coupon + referral systems
  • Runtime feature flags + maintenance mode banner
  • 270+ automated tests (backend + both mobile apps)
22

Support and licensing

Every purchase includes 6 months of support for setup questions and bug fixes. Custom feature work quoted separately.

What support covers

  • Six months of support from purchase, extendable at checkout
  • Support covers bugs in the template and questions about how it is put together
  • It does not cover custom feature work, third-party API changes or store review outcomes
  • The Regular licence covers one free end product. Charging users for the app itself needs the Extended licence