Getting started
Deployment checklist
Use this checklist before delivering a buyer installation or publishing a production deployment.
Backend production checklist
- Set
APP_ENV=prod. - Set a unique secure
APP_SECRET. - Configure production
DATABASE_URL, or use the browser installer at/install. - Generate production JWT keys, or let the browser installer create missing keys.
- Configure
JWT_PASSPHRASE. - Configure mail delivery in admin Notification Settings.
- Configure Stripe live or test keys in admin Payment Settings.
- Configure the Stripe webhook secret in admin Payment Settings.
- Configure Google Maps key.
- Configure Pusher credentials.
- Configure storage driver and credentials.
- New database:
php bin/console app:database:install(or the browser installer). Existing database: run the migrations, or use the update page. - Build production frontend assets.
- Clear and warm Symfony cache.
- Create the first admin user, or use the browser installer.
- Point the web server document root to
public/. - Confirm HTTPS works.
- Confirm upload directories are writable.
- Confirm logs are writable.
- Confirm admin login works.
- Confirm mobile login works.
- Confirm a test order can be created.
- Confirm a test payment can be completed.
- Confirm Stripe webhook events are received.
- Optional: set
SENTRY_DSNin.env.localfor error reports, and point an uptime monitor at/api/v1/health.
Recommended production commands
composer install --no-dev --optimize-autoloader
npm ci
npm run build
php bin/console app:database:install --if-empty
php bin/console doctrine:migrations:migrate --no-interaction
php bin/console cache:clear --env=prod
php bin/console cache:warmup --env=prod
Create an admin user if one does not exist:
php bin/console app:admin:create-user admin@example.com strong-password
Caching and performance
- Settings are read in one query and kept for 5 minutes in the app cache (
var/cache); saving a setting in the admin applies at once. If you change settings directly in the database, runphp bin/console cache:pool:clear cache.app. - The app cache is on disk, which is right for one server. When several servers run the same instance, point it at Redis so they share it (also needed for rate limits): in
config/packages/cache.yamlsetapp: cache.adapter.redisanddefault_redis_provider: '%env(REDIS_URL)%', setREDIS_URL, and add theredisPHP extension. - Catalog API responses (stores, menus, home, categories, search) carry
Cache-Control: private, max-age=15and an ETag: the apps keep them for 15 seconds, then ask again and get304 Not Modifiedwhen nothing changed. Don't let a shared proxy or CDN cache/api. - A store's menu costs the same few database queries whatever its size (about 120 ms for 500 products in prod mode on a laptop).
Mobile release checklist
- Create the client's brand with
npm run brand:new(name, bundle ID / package, URL scheme, API URL, support email), see New client instance. The Apple Pay merchant ID is derived from the bundle ID. - Replace the icon (1024×1024) and set the colours and splash in
brands/<slug>/brand.json; set the EAS project ID. - Set
EXPO_PUBLIC_STRIPE_PUBLISHABLE_KEY,EXPO_PUBLIC_GOOGLE_MAPS_API_KEY,EXPO_PUBLIC_GOOGLE_MAPS_API_KEY_ANDROID,EXPO_PUBLIC_PUSHER_KEYandEXPO_PUBLIC_PUSHER_CLUSTER. - Optional: add the client's Sentry project (crash reports) and Firebase config files (analytics, with user consent) to the brand.
- Run
npm run brand:apply -- <slug>before building. - Test login and refresh token flow.
- Test location permissions.
- Test checkout.
- Test Apple Pay on a real iOS device if enabled.
- Test Google Pay on a real Android device if enabled.
- Build release binaries with EAS or the buyer's preferred build process. Later JavaScript-only fixes can ship with
eas update.
Store submission: legal pages and account deletion
- Fill in the legal details in Settings → General (legal name, registered address, tax ID, registration number, support email). They are printed in the legal pages.
- Review the terms, privacy policy, courier terms and store terms in Legal documents with a lawyer. Until you publish your own, built-in English templates are shown at
/legal/terms,/legal/privacy,/legal/rider-termsand/legal/vendor-terms. - App Store Connect and Google Play Console: use
https://your-domain/legal/privacyas the privacy policy URL. - Google Play Console → Data deletion: use
https://your-domain/account/deleteas the account deletion URL. In-app deletion is in Settings → Delete account (Apple guideline 5.1.1(v)). - Schedule
app:account:process-deletionsdaily (see Scheduled jobs).
Security checklist
- Do not commit
.env.local. - Do not commit private JWT keys.
- Do not commit Stripe secret keys. Store backend Stripe credentials in admin Payment Settings.
- Do not commit Pusher secrets.
- Use HTTPS everywhere in production.
- Restrict Google Maps keys.
- Restrict Stripe webhook events to the events you need.
- Use strong admin passwords.
- Remove demo data from production.
- Review roles before assigning admin access.
Found a mistake? Tell us.