Build and Production
This document describes how to build each part of the Qprint project, what options to pass (including --dart-define and environment variables), and the difference between debug, profile, and release builds.
Build types (Flutter apps)
Flutter supports three build modes:
| Mode | Command | Use case | Optimizations | Assertions |
|---|---|---|---|---|
| Debug | flutter run (default) or flutter run --debug | Development, hot reload | None | Enabled |
| Profile | flutter run --profile or flutter build apk --profile | Performance profiling | Yes (no debug symbols) | Disabled |
| Release | flutter run --release or flutter build apk / flutter build windows | Production, distribution | Full (minified, tree-shaken) | Disabled |
- Debug: Slower, larger binary; assertions and
kDebugMode == true; certificate pinning is disabled in the apps for easier dev. - Profile: Like release but with profiling tools; use for measuring performance.
- Release: Smallest, fastest; certificate pinning enabled; use for production and store builds.
Backend (Go API)
Location: backend/
How to run (development)
cd backend
go run cmd/api/main.go
How to build (production)
cd backend
go build -o bin/api ./cmd/api
./bin/api
Configuration
The backend has no --dart-define. All configuration is via environment variables, typically from a .env file or host (e.g. Render).
| Variable | Required | Description |
|---|---|---|
PORT | Yes (production) | Server port (e.g. 8080 local, 10000 on Render) |
DATABASE_URL | Yes | PostgreSQL connection string |
JWT_SECRET | Yes | At least 32 characters |
ALLOWED_ORIGINS | Yes (production) | Comma-separated CORS origins |
ENVIRONMENT | Recommended | development or production |
USE_LOCAL_STORAGE | Optional | true for local uploads dir |
AWS_S3_BUCKET, AWS_REGION, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY | Optional | S3 file storage |
RAZORPAY_*, RESEND_API_KEY, etc. | Optional | See Environment Variables |
See Environment Variables and Deployment for full lists.
Frontend (Next.js)
Location: frontend/
How to run (development)
cd frontend
npm run dev
How to build (production)
cd frontend
npm run build
npm run start # optional: serve built app
Configuration
The frontend uses build-time env vars. Values are baked in at next build.
| Variable | Required | Description |
|---|---|---|
NEXT_PUBLIC_API_URL | Yes (production) | Backend API base URL (e.g. https://qprint-72wr.onrender.com) |
Where to set:
- Local:
frontend/.env.localNEXT_PUBLIC_API_URL=http://localhost:8080 - Production (e.g. Vercel): Project settings → Environment Variables → add
NEXT_PUBLIC_API_URLfor Production.
Note: Only variables prefixed with NEXT_PUBLIC_ are available in the browser. The app uses process.env.NEXT_PUBLIC_API_URL (see frontend/lib/api.ts); default fallback is http://localhost:8080.
Shopkeeper app (Flutter – Windows)
Location: shopkeeper_app/
How to run (development)
cd shopkeeper_app
flutter pub get
flutter run -d windows
With a specific API URL:
flutter run -d windows --dart-define=BASE_URL=http://localhost:8080
How to build (production / release)
Option 1 – Use the provided script (recommended for Windows):
cd shopkeeper_app
.\build_windows.bat
This script:
- Ensures SumatraPDF (and optionally LibreOffice) is in
windows/runner/bin/ - Runs
flutter cleanandflutter pub get - Runs
flutter run -d windows --release --dart-define=BASE_URL=https://qprint-72wr.onrender.com
Option 2 – Manual build:
cd shopkeeper_app
flutter clean
flutter pub get
flutter build windows --dart-define=BASE_URL=https://qprint-72wr.onrender.com
Output: build/windows/x64/runner/Release/ (e.g. shopkeeper_app.exe).
Dart-defines and config
| Define | Required | Description |
|---|---|---|
BASE_URL | Yes (production) | Backend API base URL (e.g. https://qprint-72wr.onrender.com) |
Default: If BASE_URL is not passed, the app uses https://qprint-72wr.onrender.com (see shopkeeper_app/lib/config/app_config.dart).
Examples:
# Production (or use build_windows.bat which already passes this)
flutter run -d windows --release --dart-define=BASE_URL=https://qprint-72wr.onrender.com
flutter build windows --dart-define=BASE_URL=https://qprint-72wr.onrender.com
# Local backend
flutter run -d windows --dart-define=BASE_URL=http://localhost:8080
Customer app (Flutter – Android)
Location: customer_app/
How to run (development)
cd customer_app
flutter pub get
flutter run -d android
With API URL and optional Maps key:
flutter run -d android --dart-define=BASE_URL=http://10.0.2.2:8080 --dart-define=MAPS_API_KEY=your_key
(Use 10.0.2.2 for Android emulator to reach host localhost.)
How to build (production / release)
APK (installable file):
cd customer_app
flutter build apk --dart-define=BASE_URL=https://qprint-72wr.onrender.com --dart-define=MAPS_API_KEY=your_key
App Bundle (for Play Store):
flutter build appbundle --dart-define=BASE_URL=https://qprint-72wr.onrender.com --dart-define=MAPS_API_KEY=your_key
Output: build/app/outputs/ (e.g. app-release.apk or app-release.aab).
Dart-defines and config
| Define | Required | Description |
|---|---|---|
BASE_URL | Yes (production) | Backend API base URL |
MAPS_API_KEY | Optional | Google Maps API key (can also be set in android/local.properties as MAPS_API_KEY=...) |
CERT_PINS | Optional | Comma-separated SHA-256 certificate fingerprints for leaf pinning; if unset, app uses intermediate CA pinning |
Defaults: If BASE_URL is not set, the app uses https://qprint-72wr.onrender.com. See customer_app/lib/config/app_config.dart.
Examples:
# Production
flutter build apk --dart-define=BASE_URL=https://qprint-72wr.onrender.com --dart-define=MAPS_API_KEY=your_key
# Optional: certificate pinning (leaf fingerprints)
flutter build apk --dart-define=BASE_URL=https://... --dart-define=CERT_PINS="AA:BB:CC:..."
# Emulator (local backend)
flutter run -d android --dart-define=BASE_URL=http://10.0.2.2:8080
Android-specific: MAPS_API_KEY can be set in customer_app/android/local.properties instead of --dart-define; the build injects it into the manifest (see customer_app/android/app/build.gradle.kts).
Summary: options by target
| Target | Build / run | Key options |
|---|---|---|
| Backend | go run cmd/api/main.go or go build -o bin/api ./cmd/api | Env only (.env): PORT, DATABASE_URL, JWT_SECRET, ALLOWED_ORIGINS, ENVIRONMENT |
| Frontend | npm run build (or npm run dev) | NEXT_PUBLIC_API_URL in .env.local or Vercel env |
| Shopkeeper (Windows) | .\build_windows.bat or flutter build windows | --dart-define=BASE_URL=https://qprint-72wr.onrender.com |
| Customer (Android) | flutter build apk or flutter build appbundle | --dart-define=BASE_URL=... and optionally --dart-define=MAPS_API_KEY=..., --dart-define=CERT_PINS=... |
Scripts reference
| Script | Purpose |
|---|---|
shopkeeper_app/build_windows.bat | One-shot: SumatraPDF/LibreOffice setup, flutter clean, flutter pub get, then flutter run -d windows --release --dart-define=BASE_URL=https://qprint-72wr.onrender.com |
run_shopkeeper_release.bat (repo root) | Starts already-built shopkeeper exe: shopkeeper_app\build\windows\x64\runner\Release\shopkeeper_app.exe (run build_windows.bat or flutter build windows first) |
buildscript.bat (repo root) | Sets BACKEND_URL and FRONTEND_URL, updates frontend/.env.local and (legacy) shopkeeper api_service.dart, then offers to build Frontend / Windows app / Android. Note: Shopkeeper app now uses AppConfig.baseUrl from --dart-define=BASE_URL, not a hardcoded value in api_service.dart. |
buildscript.sh (repo root) | Linux/macOS equivalent of buildscript.bat; updates frontend env and (legacy) shopkeeper file, then builds Frontend / Linux app / Android. |
startlocal.bat | Starts backend and frontend; can patch backend copy of customer app API URL (see script). |
Production checklist
- Backend:
ENVIRONMENT=production,JWT_SECRET32+ chars,ALLOWED_ORIGINSset to your frontend URL(s), noTEST_MODE=true. - Frontend:
NEXT_PUBLIC_API_URLset to your production backend URL (e.g.https://qprint-72wr.onrender.com). - Shopkeeper Windows: Build with
--dart-define=BASE_URL=https://qprint-72wr.onrender.com(or your API URL); usebuild_windows.bator equivalent. - Customer Android: Build with
--dart-define=BASE_URL=https://qprint-72wr.onrender.com(andMAPS_API_KEYif using maps); use release signing for Play Store.
For full deployment steps, see Deployment and Environment Variables.