devsnack
Documentation

Crately documentation

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

$29 on CodeCanyon
  • Version v1.0.0
  • Updated
  • Platform Flutter
  • Stack Flutter · Postgres
On this page
01

Overview

AI-powered B2B food supplier SaaS — three apps, one source. Customer Flutter app · Driver Flutter app · Next.js admin + web + API.

A complete operating system for a wholesale food supplier serving 10–500 restaurant customers.

Crately is a 3-in-1 bundle: a Next.js 16 codebase (admin panel + customer web + marketing + REST API), a customer Flutter app, and a driver Flutter app. The positioning is deliberately single-supplier-many-customers (one food wholesaler, many restaurant accounts) — not a multi-vendor marketplace.

Every B2B-specific concept is wired: account-level pricing, credit terms (NET-15/30/COD/prepaid), delivery cutoff times, standing orders, multi-location restaurant chains, owner-approval workflow, quality credits applied to invoices, FIFO/FEFO inventory batches. Eight AI features ship enabled out of the box, talking to OpenAI or Google Gemini through a server-only wrapper so the keys never leave your infrastructure.

Architecture is serverless-first: Vercel functions + a managed Postgres (Neon free tier handles thousands of orders/day) + Inngest cron. No Kubernetes, no Docker, no separate worker hosts.

Live demo: https://crately.devsnack.dev — sign in with admin@demo.com / demopassword.

02

What’s included

  • Full source for all three apps (crately_web/, crately_app/, crately_driver/).
  • Drizzle ORM schema covering 40+ tables, with migrations 0000–0004 ready to apply on a fresh Postgres.
  • Industrial Harvest design system — Tailwind v4 config + tokens, Flutter ThemeData, brand color tokens, typography (Sora + JetBrains Mono).
  • Email templates — 7 React Email templates (order confirmation, invoice issued, quality credit, password reset, abandoned cart, pre-cutoff, standing-order pre-submit).
  • PDF templates — invoice + statement via React-PDF.
  • Branding pipeline — single SVG source under branding/ → one command generates favicon, PWA icons, Flutter launcher icons for iOS + Android (color + inverted variants).
  • Documentation — this guide, README.md (overview + setup), DEPLOY.md (production), plus inline comments on every non-obvious helper.
  • 6 months of Item Support (per the Envato Item Support Policy) · free future updates.
03

Features

Customer Flutter app (crately_app/)

  • JWT login (HS256, 30-day TTL) against POST /api/v1/auth/login
  • Catalog browse — categories, product grid, product detail with account-scoped pricing, search
  • Cart with multi-line management; multi-location switcher for chain restaurants
  • Checkout with delivery-date picker, customer notes, owner-approval gate above threshold
  • Orders list (Active / Past) with status pills; detail with items + status timeline
  • Realtime delivery tracking — Google Map with driver pin, polls every 8s, Pusher private channel for sub-second updates
  • Invoices list + detail + PDF download (token-signed URL for external browser)
  • Stripe Pay Online on open invoices with deep-link return (crately://)
  • AI Order Predictor — one-tap to populate the cart from history
  • AI Recipe → Order — chef pastes a recipe, AI returns priced ingredients
  • Standing orders — create / view / edit / pause / resume; per-line notes
  • Profile + sign-out · FCM push notifications · brand mark in login + header

Driver Flutter app (crately_driver/)

  • JWT login (driver role enforced)
  • Today’s route — stops grouped, sorted by AI route optimization when available
  • Job detail with line items; start-delivery transition
  • Deliver flow — photo capture (camera), customer signature pad, optional receiver name
  • AI Quality Audit auto-fires on delivery upload — flagged audits surface in /admin/credits for one-click credit
  • Vehicle check — 6-item pre-route checklist with fuel + odometer + notes
  • Earnings — week / month / all-time, daily breakdown
  • Issues reporting — 7 categories (customer not available, wrong address, damaged goods, vehicle breakdown, etc.), optional order linkage
  • GPS streaming every 15s while on shift (paired with the customer-side tracker)

Admin panel (crately_web/admin)

  • Real KPI dashboard — today’s orders + revenue, 7-day chart, AR aging buckets, AI alerts (replenishment / credit risk / demand insights), top accounts this month, recent activity feed
  • Catalog — categories + products CRUD, AI Description Generator on product create
  • Customer accounts — list, onboarding queue, account detail, pricing tiers
  • Orders — list with filters, detail with status transitions, driver assignment, picking, AI substitution
  • Inventory — stock, expiry, wastage
  • Invoices + AR aging + payments + quality credits (with AI-flagged audit review)
  • Suppliers + purchase orders — auto-receive triggers inventory batch on “Mark received”
  • Sales reps + drivers + routes + delivery zones
  • Promotions · Communications (template editor) · Pages (marketing CMS) · Reports (sales, top products, AR aging — all with CSV export) · Settings (business profile, branding, integrations status)
  • AI screens — Insights (Sunday digest), Smart Replenishment (nightly plan), Credit Risk (daily refresh), Demand Insights weekly

Backend — Next.js API routes + Inngest crons

REST API surface lives under /api/v1/. Both web (cookie session) and mobile (JWT) auth paths are supported through the requireCustomer / requireDriver helpers in src/lib/api/.

13 Inngest functions handle cron + event-triggered work:

order-prediction-nightly
02:00 UTC daily
replenishment-nightly
02:00 UTC daily
credit-risk-daily
06:00 UTC daily
route-optimization-nightly
20:00 UTC daily
ar-aging-collection
07:00 UTC daily
statement-monthly
1st of each month, 01:00 UTC
demand-insights-weekly
Sunday 02:00 UTC
standing-order-auto-submit
hourly
pre-submission-reminder
hourly
pre-cutoff-reminder
hourly
abandoned-cart-recovery
hourly
reset-rate-limits
00:00 UTC daily
quality-audit-on-upload
event-triggered
04

Architecture

crately/
crately/
  crately_web/      Next.js 16 + Drizzle + JWT auth + Inngest
  crately_app/      Flutter customer app (Riverpod 3 + GoRouter + Dio)
  crately_driver/   Flutter driver app (same stack)
  branding/         SVG logo source of truth + raster pipeline
  docs/             Buyer documentation + this CodeCanyon bundle

Tech stack

Web framework
Next.js 16 (App Router) · React 19
Database
Postgres (Neon, Supabase, RDS — any work)
ORM
Drizzle
Web auth
In-house HS256 JWT session (jose), email + password
Mobile auth
HS256 JWT signed by the server, 30-day TTL
Background jobs
Inngest (Vercel-compatible)
Mobile
Flutter 3.x · Riverpod 3.x · GoRouter · Dio
AI
OpenAI + Google Gemini via src/lib/ai/client.ts
Payments
Stripe Checkout + webhook
Realtime
Pusher Channels (sub-second) + polling fallback
Push
Firebase Cloud Messaging (server SDK)
Email
Resend + React Email
File storage
UploadThing (with local-disk fallback)
Rate limiting
Upstash Redis (with in-memory fallback)
Maps
Google Maps SDK (iOS + Android + JS)
Charts
Recharts
PDF
React-PDF

Folder convention

Every app uses a feature-first layout. Backend: src/app/api/v1/<feature>/ + src/server/services/<feature>.ts. Flutter: lib/features/<feature>/. AI calls live exclusively under src/lib/ai/ and src/app/api/v1/ai/.

05

Quick setup

Follow the steps below to get running locally. For production deploy guidance see DEPLOY.md at the repo root.

  1. 01
    Extract zip, cd crately_web && pnpm install
  2. 02
    Create crately_web/.env.local with DATABASE_URL, AUTH_SECRET, NEXT_PUBLIC_APP_URL
  3. 03
    pnpm db:migrate && pnpm dev http://localhost:3000
  4. 04
    Register your first owner at /register, then use the admin panel to create products, accounts, pricing tiers, and delivery zones.
  5. 05

    In separate terminals, run each Flutter app with:

    terminal
    flutter run --dart-define=API_BASE=http://localhost:3000
06

Database

Any Postgres works. Neon free tier handles a small wholesaler comfortably. Pick a region near your Vercel function region — by default vercel.json pins sin1 (Singapore); if you change either, change both.

terminal
# Provision Postgres (Neon)
# Copy the connection string, then:
echo 'DATABASE_URL=postgres://...' >> crately_web/.env.local
echo 'AUTH_SECRET='"$(openssl rand -base64 32)" >> crately_web/.env.local
echo 'NEXT_PUBLIC_APP_URL=http://localhost:3000' >> crately_web/.env.local

cd crately_web
pnpm db:migrate          # applies 0000–0004

The database starts empty after migration. Register your first admin user at /register, then create products, accounts, pricing tiers, and delivery zones via the admin panel. The hosted demo at crately.devsnack.dev/admin (login admin@demo.com / demopassword) shows what a populated deployment looks like.

Useful Drizzle commands:

  • pnpm db:studio — Drizzle GUI
  • pnpm db:generate — generate a new migration after schema edits
  • pnpm db:push — push schema directly (dev only, skips migration files)
07

Optional integrations

Every integration gracefully no-ops when its env vars are missing. The codebase ships a has*() probe pattern — see src/lib/{stripe,fcm,pusher,email}.ts — so you can run a fully working demo without provisioning any third-party services.

IntegrationWhat it unlocksRequired env vars
Stripe
Pay-online on customer invoices + Flutter deep-link return
STRIPE_SECRET_KEY, STRIPE_WEBHOOK_SECRET
Pusher Channels
Sub-second driver-location updates on the customer map
PUSHER_APP_ID, PUSHER_KEY, PUSHER_SECRET, PUSHER_CLUSTER, plus the NEXT_PUBLIC_* mirror pair
Firebase Admin (FCM)
Push notifications for order status + payments
FIREBASE_SERVICE_ACCOUNT_JSON (the whole JSON as one var)
Resend
Transactional email (orders, invoices, credits, reminders)
RESEND_API_KEY, RESEND_FROM_ADDRESS
Twilio
SMS (env wired, not surfaced in app — roadmap)
TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN, TWILIO_FROM_NUMBER
UploadThing
Production storage for driver delivery photos
UPLOADTHING_TOKEN (falls back to public/uploads/)
Upstash Redis
Distributed AI rate limiting (production)
UPSTASH_REDIS_REST_URL, UPSTASH_REDIS_REST_TOKEN (falls back to in-memory)
Google Maps
Realtime tracking map + admin maps
GOOGLE_MAPS_API_KEY, NEXT_PUBLIC_GOOGLE_MAPS_API_KEY + iOS xcconfig + Android local.properties
Note
Pattern. The same probe-and-no-op idea applies if you fork. Add a new integration? Mirror the shape of src/lib/stripe.ts — lazy init, has*() probe, warn-on-failure in calling code.
08

AI providers

Two server-side providers, dual-keyed. Pick whichever fits your budget — bring at least one key.

crately_web/.env.local
# crately_web/.env.local
OPENAI_API_KEY=sk-...
# OR
GEMINI_API_KEY=AIza...

AI_DEFAULT_PROVIDER=openai      # or gemini

Per-day rate limits per account, defaults in src/lib/env.ts:

FeatureDefault per dayEnv var
Order Predictor
5
AI_RATE_LIMIT_ORDER_PREDICT_PER_DAY
Recipe Converter
10
AI_RATE_LIMIT_RECIPE_CONVERT_PER_DAY
Substitution Engine
20
AI_RATE_LIMIT_SUBSTITUTION_PER_DAY
Quality Audit
200
AI_RATE_LIMIT_QUALITY_AUDIT_PER_DAY
Description Generator
50
AI_RATE_LIMIT_DESCRIPTION_PER_DAY
Route Optimization
20
AI_RATE_LIMIT_ROUTE_OPT_PER_DAY
Demand Insights
5
AI_RATE_LIMIT_DEMAND_INSIGHTS_PER_DAY
Note
AI keys never reach the client. Every AI call lives in a Next.js route handler that calls src/lib/ai/client.ts. The Flutter apps only ever talk to /api/v1/ai/* — they never see your OpenAI key.
09

Payments (Stripe)

  1. 01
    Create a Stripe account at stripe.com, grab STRIPE_SECRET_KEY.
  2. 02

    Stripe Dashboard → Developers → Webhooks → Add endpoint:

    • URL: https://<your-domain>/api/webhooks/stripe
    • Events: checkout.session.completed

    Reveal the signing secret → copy as STRIPE_WEBHOOK_SECRET.

  3. 03

    Local dev:

    terminal
    stripe listen --forward-to localhost:3000/api/webhooks/stripe

    The CLI prints the dev signing secret to use in .env.local.

  4. 04
    On the customer Flutter app, the “Pay $X online” button opens Checkout in the system browser and returns into the app via the crately://invoices/{id}?paid=1 deep link. The order detail provider auto-invalidates so the PAID status appears within a second of Stripe’s webhook firing.
Note
PayPal. PAYPAL_CLIENT_ID + PAYPAL_CLIENT_SECRET are reserved in .env.example but the PayPal flow is not yet implemented. Roadmap.
10

Push notifications (FCM)

Push triggers fire from src/lib/push/order-notifications.ts on order status transitions + Stripe payment success.

  1. 01
    Create a Firebase project, enable Cloud Messaging.
  2. 02
    Project Settings → Service accounts → Generate new private key. Paste the entire JSON into one env var: FIREBASE_SERVICE_ACCOUNT_JSON.
  3. 03

    In crately_app/: dart pub global activate flutterfire_cli, then flutterfire configure --project=<your-id>. This overwrites the committed placeholders at android/app/google-services.json and ios/Runner/GoogleService-Info.plist with your real values. Then guard those two files from accidental commits:

    terminal
    git update-index --skip-worktree android/app/google-services.json
    git update-index --skip-worktree ios/Runner/GoogleService-Info.plist
  4. 04
    iOS only: Xcode → Runner target → Signing & Capabilities → add Push Notifications + Background Modes (Remote notifications).
  5. 05
    Same as step 3 in crately_driver/ if you want push for drivers.

Notification taps deep-link back into the app via the existing crately:// URL scheme — same plumbing as Stripe return.

Note
The placeholders. Both Flutter apps ship a placeholder google-services.json and GoogleService-Info.plist with REPLACE_WITH_PROJECT_ID markers — that’s why a fresh clone builds on both Android and iOS without you having configured Firebase yet. The Gradle hasFirebase guard reads the file and skips the Google Services plugin when the marker is present. iOS keeps the file as a bundle resource so Xcode’s “Copy Bundle Resources” step succeeds; at runtime Firebase.initializeApp() throws and main.dart catches it. Push features simply no-op until you complete this section.
11

Realtime delivery tracking (Pusher)

  1. 01
    At dashboard.pusher.com/channels/apps create a Channels app (not Beams). Pick a cluster close to your Vercel region — ap1 for Singapore.
  2. 02

    Copy keys into the env:

    crately_web/.env.local
    # Server-side
    PUSHER_APP_ID=...
    PUSHER_KEY=...
    PUSHER_SECRET=...
    PUSHER_CLUSTER=ap1
    
    # Client-side (Flutter reads these via /api/v1/config)
    NEXT_PUBLIC_PUSHER_KEY=...
    NEXT_PUBLIC_PUSHER_CLUSTER=ap1
  3. 03
    The driver app streams location every 15s while signed in (features/tracking/location_reporter.dart). On every fix the server triggers private-order-{id} events. The customer app subscribes via features/tracking/pusher_subscriber.dart when viewing an order with status OUT_FOR_DELIVERY.
  4. 04
    If you don’t configure Pusher, the customer app falls back to polling every 8s — still works, just less snappy.
12

Google Maps

Required for the realtime tracking map. Enable these APIs in Google Cloud Console:

  • Maps SDK for iOS
  • Maps SDK for Android
  • Maps JavaScript API

Use one key per platform with appropriate restrictions:

iOS
crately_app/ios/Flutter/Secrets.xcconfig (copied from the .example; gitignored)
Android
crately_app/android/local.properties (already gitignored)
Web / server
GOOGLE_MAPS_API_KEY + NEXT_PUBLIC_GOOGLE_MAPS_API_KEY in .env.local

Restrict the iOS key to your bundle id com.devsnack.crately.restaurant; restrict the Android key to your package + signing SHA-1; restrict the web key to your domain.

13

Branding and customization

Single SVG source under branding/. One command regenerates every platform’s expected size.

terminal
# Edit branding/mark-color.svg (or mark-inverted.svg for the driver variant)
cd crately_web
pnpm icons:build         # writes web favicon + PWA + Flutter master PNGs
cd ../crately_app && dart run flutter_launcher_icons
cd ../crately_driver && dart run flutter_launcher_icons

Theme tokens

  • Web: crately_web/src/app/globals.css (CSS custom properties) + tailwind.config.ts
  • Flutter customer: crately_app/lib/core/theme/{theme,colors}.dart
  • Flutter driver: crately_driver/lib/core/theme/{theme,colors}.dart

Brand color today: #0f5238 (Deep Forest Green). Surface: #f8faf6 (Sage Cream). The Material 3 token set is called “Industrial Harvest” — the full palette lives in crately_web/src/app/globals.css (CSS variables) and the matching Flutter colors.dart files.

App name and bundle id

Customer app uses com.devsnack.crately.restaurant, driver uses com.devsnack.crately.driver. Files to edit when you rebrand:

  • pubspec.yaml in each Flutter app (the name: line + the flutter_launcher_icons block)
  • ios/Runner/Info.plistCFBundleDisplayName
  • android/app/build.gradle.kts applicationId + namespace
  • android/app/src/main/AndroidManifest.xml android:label
  • iOS bundle id via Xcode Signing & Capabilities

Marketing copy

The landing page lives in crately_web/src/app/(marketing)/page.tsx as a single static file. Hero, features grid, pricing tiers, FAQ — all editable in one place. Two TODO markers indicate where to drop in a real screenshot of your branded admin/customer screen and where to swap in your CodeCanyon listing URL.

i18n

next-intl is wired but EN-only today. The messages/ folder is ready for AR (RTL), ID, MS, ES, FR — extract strings into messages/<locale>.json and wrap user-facing text in useTranslations(). Multi-language support is on the roadmap.

14

Signing and store distribution

How to produce a signed Android AAB for the Play Console and an archived iOS build for the App Store. Do this for the customer app and again for the driver app — they have separate bundle IDs and need separate listings.

Android — generate the upload keystore

One-time setup per app. Lose this keystore and you can’t update your app on the Play Store ever again — back it up to a password manager or secure cloud storage.

terminal
# From any directory:
keytool -genkey -v \
  -keystore ~/keystore/crately-customer-release.jks \
  -keyalg RSA -keysize 2048 -validity 10000 \
  -alias crately

# Repeat with a different filename + alias for the driver app:
keytool -genkey -v \
  -keystore ~/keystore/crately-driver-release.jks \
  -keyalg RSA -keysize 2048 -validity 10000 \
  -alias crately-driver

The tool prompts for a store password, key password, your name, organisation, etc. Remember the two passwords — you’ll paste them into the next step.

Android — wire the keystore into Gradle

The Gradle signing config already ships in both apps — build.gradle.kts reads a key.properties file and applies it to the release build automatically. You only need to create that file; no Gradle edits required. Create crately_app/android/key.properties (gitignored — never commit):

crately_app/android/key.properties
storePassword=<the store password you just set>
keyPassword=<the key password you just set>
keyAlias=crately
storeFile=/Users/<you>/keystore/crately-customer-release.jks

That’s it — the next flutter build --release detects key.properties and signs with your keystore. (When the file is absent, the release build falls back to the debug keystore so a fresh clone still builds locally; ship-ready release builds require the file.) Repeat for the driver app: create crately_driver/android/key.properties pointing at crately-driver-release.jks with keyAlias=crately-driver.

Android — build and upload

terminal
cd crately_app
flutter build appbundle --release
# Output: build/app/outputs/bundle/release/app-release.aab

# For the driver app:
cd ../crately_driver
flutter build appbundle --release
  1. 01
    Play Console → Create app → set package name to match your applicationId (com.devsnack.crately.restaurant for customer, com.devsnack.crately.driver for driver — or your rebranded equivalents).
  2. 02
    Production → Create new release → upload the .aab.
  3. 03
    Fill the Store listing (icon 512×512 + screenshots + description). Use the brand mark from branding/ regenerated at 512×512 for the Play icon.
  4. 04
    Roll out to Internal testing first → Closed testing → Production.

Android — get the SHA-1 for Firebase + Google Maps

When you upload an AAB to Play Console, Google re-signs it with their own key. Both your upload keystore and the Play Store signing certificate need to be registered with Firebase and the Google Maps key restrictions.

terminal
# Upload key SHA-1
keytool -list -v \
  -keystore ~/keystore/crately-customer-release.jks \
  -alias crately

# Play Store app-signing SHA-1: copy from
# Play Console → Setup → App integrity → App signing key certificate

Add both SHA-1 values:

  • Firebase Console → Project settings → Your apps → Android app → Add fingerprint.
  • Google Cloud Console → APIs & Services → Credentials → your Android Maps key → Application restrictions → add the package name + SHA-1.
Warning
Backup. Copy ~/keystore/*.jks + the matching key.properties into a password manager. Losing either means Play Store rejects every future update.

iOS — Apple Developer prerequisites

  • Apple Developer Program membership ($99/yr) at developer.apple.com.
  • Xcode 15+ on a Mac.
  • For push: an APNs key (create at Apple Developer → Certificates, Identifiers & Profiles → Keys) — upload it in Firebase Console → Project settings → Cloud Messaging → APNs Authentication Key.

iOS — bundle id and capabilities

  1. 01
    Open crately_app/ios/Runner.xcworkspace in Xcode.
  2. 02
    Select the Runner target → Signing & Capabilities.
  3. 03
    Check Automatically manage signing and select your Apple Developer Team. Xcode will auto-create the App ID, provisioning profile, and signing certificate.
  4. 04
    Set Bundle Identifier to whatever you want shipped on the App Store (default com.devsnack.crately.restaurant; rebrand to com.<your-org>.<app>).
  5. 05

    Click + Capability and add:

    • Push Notifications
    • Background Modes → tick Remote notifications
  6. 06
    Repeat for the driver app in crately_driver/ios/Runner.xcworkspace with its own bundle ID (e.g. com.devsnack.crately.driver).

iOS — App Store Connect app record

  1. 01
    Go to App Store Connect → My Apps → + → New App.
  2. 02
    Fill: platform iOS, name “Crately” (or your rebrand), primary language, bundle ID (must match step 4 above), SKU (any unique string).
  3. 03
    Repeat for the driver app.

iOS — build, archive, upload

terminal
cd crately_app
flutter build ipa --release
# Output: build/ios/archive/Runner.xcarchive

# Open the archive:
open build/ios/archive/Runner.xcarchive

Xcode Organizer opens. Click Distribute App App Store ConnectUpload. Wait for processing (~5–30 min) — you’ll get an email when it’s available in TestFlight.

Then in App Store Connect:

  1. 01
    TestFlight → invite internal testers → confirm the build runs on a real device.
  2. 02
    App Store → fill app metadata (description, keywords, screenshots — 6.7" iPhone screenshots are mandatory).
  3. 03
    Submit for review. Apple typically responds in 24–48 hours.

Repeat the build / upload / TestFlight / review for the driver app in crately_driver/.

iOS — common rejection reasons (preempt these)

  • Guideline 5.1.1 (data & privacy) — your NSCameraUsageDescription + NSLocationWhenInUseUsageDescription strings in Info.plist must explain the user-facing reason (“To capture proof-of-delivery photos”, “To show your driver on the live tracking map”). These are already populated in the bundle — review the wording for your brand.
  • Guideline 3.1.1 — Apple wants in-app purchases to use StoreKit, not Stripe, for digital goods consumed inside the app. Crately’s Stripe checkout pays for physical food delivery which is explicitly exempt (Guideline 3.1.5 — physical goods sold from a B2B platform). Mention this in the App Review Notes field if asked.
  • Sign-in test account — provide owner@demo.com / demopassword against your deployed backend in the App Review Information section. Without working demo creds, reviewers can’t get past the login screen and reject the app.
15

Production checklist

  1. 01
    Branding — replace branding/mark-color.svg + run pnpm icons:build then dart run flutter_launcher_icons in each Flutter dir.
  2. 02
    Theme tokens — edit crately_web/src/app/globals.css + both Flutter colors.dart files.
  3. 03
    App names + bundle IDs in the Flutter pubspecs + native config (see Branding and customization).
  4. 04
    Provision Postgres — Neon recommended; match your Vercel region.
  5. 05
    Install + migratepnpm install then pnpm db:migrate. Register your first admin at /register and build your catalog via the admin panel.
  6. 06
    Env vars — set DATABASE_URL, AUTH_SECRET, NEXT_PUBLIC_APP_URL + any optional integrations.
  7. 07
    Vercel — import the GitHub repo, set crately_web/ as the root directory, set region to match Postgres, paste env vars, deploy. The build command (pnpm db:migrate && pnpm build) is preset in crately_web/vercel.json.
  8. 08
    Stripe webhook — add the endpoint, paste signing secret into Vercel env.
  9. 09
    Pusher Channels — create the app, paste all six env vars into Vercel.
  10. 10
    Firebase — create project → enable Cloud Messaging → generate service account JSON → paste into FIREBASE_SERVICE_ACCOUNT_JSON.
  11. 11
    Flutter apps flutterfire configure --project=<id> in each. iOS Xcode: enable Push Notifications + Background Modes.
  12. 12

    Build Flutter releases:

    • iOS: flutter build ipa --release → archive in Xcode → upload via App Store Connect.
    • Android: flutter build appbundle --release → upload to Play Console.
  13. 13
    Inngest Cloud (optional, free tier covers a small wholesaler) — install the Inngest GitHub app, sign with INNGEST_SIGNING_KEY, the functions auto-register on deploy.
  14. 14
    UploadThing (optional) — production storage for driver delivery photos.
  15. 15
    Promote yourself to admin — find your user row, set role = 'ADMIN' or 'SUPER_ADMIN'.
  16. 16
    Privacy + Terms — admin panel → Pages → Seed defaults → edit copy → publish. Update the marketing footer link.
16

Changelog

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

v1.0.0
Initial release — three apps, eight AI features on OpenAI and Gemini, optional Stripe, Pusher, FCM, Resend, UploadThing, Upstash and Google Maps, admin dashboard, 13 background jobs.

Version 1.0.0

Initial release. Three apps; 8 AI features; Stripe + Pusher + FCM + Resend wired; Industrial Harvest design system; brand mark + launcher icons; admin dashboard with real data; static marketing landing; deploy guide.

17

Support and licensing

Bundled 6 months of email support per CodeCanyon standard — covers setup help, bug clarifications, and pointer questions. Custom development is hourly.

Hosting (Vercel), database (Neon / your choice), third-party accounts (Stripe, Pusher, Firebase, Resend, etc.) are the buyer’s responsibility. The bundle is source code, not a managed SaaS.

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