devsnack
Documentation

ChefAI documentation

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

$19 on CodeCanyon
  • Version v1.1.0
  • Updated Jul 2026
  • Platform Flutter
  • Stack Flutter · AI
On this page
01

Introduction

AI-powered recipe generator, weekly meal planner and calorie tracker built with Flutter. Complete source code for CodeCanyon buyers.

ChefAI is a full-featured Flutter mobile app that lets users generate AI-powered recipes from ingredients they already have, plan weekly meals, track calories and macros, and follow interactive step-by-step cooking mode — all powered by OpenAI or Google Gemini.

This package includes the complete Flutter source code, Firebase configuration, and all assets needed to publish on the App Store and Google Play under your own brand.

Key features

Dual AI providers
OpenAI and Google Gemini with hot-switch via Remote Config
Recipe generator
Generate recipes from pantry ingredients with dietary filters and allergy detection
Meal planner
AI-generated 7-day meal plans with calorie balancing and cuisine variety
Smart shopping list
Build a grocery list from the weekly meal plan — duplicates merged, grouped by supermarket aisle, tick-off state synced
Nutrition tracker
Daily calorie ring, macro bars, one-tap AI food logging, water tracker and weekly history
Cooking mode
Full-screen step-by-step guide, auto timers, wakelock, voice navigation
Monetization
RevenueCat IAP subscriptions + AdMob banner and interstitial ads built in
Dark mode
Full dark mode support with warm color palette, toggled from Settings
Auth
Email/Password + Google Sign-In + Sign in with Apple via Firebase Auth

Tech stack

  • Flutter 3.24
  • Dart 3.5
  • Riverpod 2
  • Firebase
  • OpenAI GPT-4o
  • Gemini 3.5 Flash
  • iOS and Android
02

Features

FeatureFree tierPremium
AI recipe generation
5 per day
Unlimited
Recipes per session
1 recipe
Up to 5 recipes
Save recipes
Up to 20
Unlimited
Meal planner
View only
AI auto-fill
Smart shopping list
Included
Included
Nutrition history
Today only
Full history
Food logging (AI nutrition lookup)
Included
Included
Cooking mode
Included
Included
Ingredient substitutions
Included
Included
Serving adjuster
Included
Included
Voice input
Included
Included
AdMob ads
Shown
Hidden
03

Requirements

Tool / serviceVersion / notesStatus
Flutter SDK
3.24.x (stable channel)
Required
Dart SDK
3.5.x
Required
Xcode
15+ (iOS builds)
Required
Android Studio
Hedgehog or newer
Required
Firebase project
Free Spark plan is fine
Required
OpenAI API key
Chat Completions access
Required
Google Gemini API key
Alternative/fallback AI
Optional
RevenueCat account
For subscription IAP
Optional
AdMob account
For ad monetization
Optional
CocoaPods
Latest stable
Required for iOS
04

Installation

  1. 01

    Extract the source code

    Unzip the downloaded package. You will find the Flutter project inside the chef-ai/ folder.
  2. 02

    Install Flutter dependencies

    Open a terminal in the project root and run:

    terminal
    flutter pub get
  3. 03

    Generate code (freezed models and Riverpod)

    This step is required whenever models change. Run:

    terminal
    flutter pub run build_runner build --delete-conflicting-outputs
  4. 04

    Install iOS pods

    Required for iOS builds only:

    terminal
    cd ios && pod install && cd ..
  5. 05

    Complete Firebase setup (see next section)

    The app will not run without Firebase configuration files.
Note
First run: after Firebase is configured, run flutter run to verify the app launches on a device or simulator.
05

Firebase setup

ChefAI uses Firebase for authentication, Firestore database, Remote Config (API keys), push notifications, and analytics.

Create a Firebase project

  1. 01

    Go to console.firebase.google.com

    Sign in with a Google account and click Add project.
  2. 02

    Register Android app

    Package name: com.devsnack.chefai (change to your own ID). Download google-services.json and place it in android/app/.
  3. 03

    Register iOS app

    Bundle ID: com.devsnack.chefai (change to your own ID). Download GoogleService-Info.plist and place it in ios/Runner/.

Enable Firebase services

In the Firebase Console, enable the following services under your project:

Authentication
Enable Email/Password, Google, and Apple sign-in providers
Cloud Firestore
Create database → Start in production mode → choose region
Remote Config
No extra setup needed — parameters are created below
Cloud Messaging (FCM)
Enabled by default with Firebase project

Apply Firestore security rules

In Firestore → Rules tab, paste the following:

firestore.rules
// Firestore Security Rules — paste in Firebase Console → Firestore → Rules
rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /users/{userId} {
      allow read, write: if request.auth.uid == userId;
    }
    match /recipes/{recipeId} {
      allow read: if request.auth != null &&
        (resource.data.userId == request.auth.uid || resource.data.userId == null);
      allow create: if request.auth != null &&
        request.resource.data.userId == request.auth.uid;
      allow update, delete: if request.auth != null &&
        resource.data.userId == request.auth.uid;
    }
    match /mealPlans/{userId}/weeks/{weekId} {
      allow read, write: if request.auth.uid == userId;
    }
    match /shoppingLists/{userId}/weeks/{weekId} {
      allow read, write: if request.auth.uid == userId;
    }
    match /nutritionLogs/{userId}/days/{date} {
      allow read, write: if request.auth.uid == userId;
    }
  }
}
Warning
Important: do not leave Firestore in test mode (open read/write). The security rules above are required for production.
06

Remote Config and API keys

All API keys and feature flags are stored in Firebase Remote Config — never hardcoded in the app. This allows you to update keys without releasing a new app version.

Add Remote Config parameters

In Firebase Console → Remote Config → Add parameter:

Parameter keyDefault valueDescription
openai_api_key
(your key)
OpenAI secret key — starts with sk-
gemini_api_key
(your key)
Google AI Studio API key
default_ai_provider
openai
Either openai or gemini
openai_model
gpt-4o
OpenAI model for recipe and meal plan generation
openai_model_fast
gpt-4o-mini
Cheaper OpenAI model for nutrition and substitutions
gemini_model
gemini-3.5-flash
Gemini model for recipe and meal plan generation
gemini_model_fast
gemini-3.5-flash-lite
Cheaper Gemini model for nutrition and substitutions
free_daily_generations
5
Max AI generations per day for free users
free_recipes_per_session
1
Recipes returned per generation for free users
free_max_saved_recipes
20
Max saved recipes for free users
nutrition_history_days_free
1
Days of nutrition history for free users
admob_banner_id
(your ad unit ID)
AdMob banner ad unit ID
admob_interstitial_id
(your ad unit ID)
AdMob interstitial ad unit ID
Warning
Security note: Remote Config values are not fully secret — they can be extracted from a rooted device. For production, proxy your AI calls through your own backend server and store the real API key server-side. This is strongly recommended before publishing on major app stores.

Getting API keys

07

RevenueCat (in-app purchases)

ChefAI uses RevenueCat to manage premium subscriptions across iOS and Android with a single integration.

  1. 01

    Create a RevenueCat account

    Go to app.revenuecat.com and create a new project named ChefAI.
  2. 02

    Add iOS and Android apps

    Add your bundle ID for iOS and package name for Android. Copy the Public API Key for each platform.
  3. 03

    Create products in App Store Connect / Google Play

    Create subscription products (e.g. chefai_premium_monthly, chefai_premium_yearly). Import them into RevenueCat.
  4. 04

    Update the app

    Open lib/data/services/revenue_cat_service.dart and replace the placeholder API keys with your RevenueCat public API keys.

    revenue_cat_service.dart
    // lib/data/services/revenue_cat_service.dart
    await Purchases.configure(
      PurchasesConfiguration('your_revenuecat_public_key')
    );
Note
Testing purchases: use RevenueCat’s sandbox environment for testing. iOS uses Sandbox testers from App Store Connect; Android uses License Testers from Google Play Console.
08

AdMob setup

  1. 01

    Create an AdMob account

    Go to admob.google.com. Create your account and add an app for both iOS and Android.
  2. 02

    Create ad units

    Create a Banner ad unit and an Interstitial ad unit. Copy the Ad Unit IDs.
  3. 03

    Add App IDs to native config

    The AdMob App ID (not ad unit ID) must be added to native files:

    Android — android/app/src/main/AndroidManifest.xml

    AndroidManifest.xml
    <meta-data
        android:name="com.google.android.gms.ads.APPLICATION_ID"
        android:value="ca-app-pub-XXXXXXXXXXXXXXXX~XXXXXXXXXX"/>

    iOS — ios/Runner/Info.plist

    Info.plist
    <key>GADApplicationIdentifier</key>
    <string>ca-app-pub-XXXXXXXXXXXXXXXX~XXXXXXXXXX</string>
  4. 04

    Set ad unit IDs in Remote Config

    Add admob_banner_id and admob_interstitial_id in Firebase Remote Config (see Remote Config section above).
Warning
Use test IDs during development: never click your own real ads. During development use AdMob’s official test ad unit IDs to avoid policy violations.
09

Branding and colors

All colors are centralized in lib/core/constants/app_colors.dart. Never hardcode colors in widgets — always use AppColors constants.

Change the primary color

The default accent is Saffron Orange (#F97316). To rebrand with a different color, update these two values in app_colors.dart:

app_colors.dart
static const primary      = Color(0xFFF97316);  // ← change this
static const primaryLight = Color(0xFFFB923C);  // ← and this (lighter shade)
static const primaryTint  = Color(0xFFFED7AA);  // ← background tint

Change app icon

Replace the icon assets:

  • Android: Replace files in android/app/src/main/res/mipmap-*/
  • iOS: Replace assets in ios/Runner/Assets.xcassets/AppIcon.appiconset/

Or use the flutter_launcher_icons package for automated generation from a single source image.

Change app name

android/app/src/main/AndroidManifest.xml
android:label="ChefAI"
ios/Runner/Info.plist
CFBundleDisplayName and CFBundleName

Change bundle / package ID

PlatformFile / locationCurrent value
Android
android/app/build.gradleapplicationId
com.devsnack.chefai
iOS
Xcode → Runner target → General → Bundle Identifier
com.devsnack.chefai
10

Typography and copy

ChefAI uses Montserrat loaded via the google_fonts package. No font files need to be bundled — they are downloaded automatically on first launch and then cached.

Typography scale

Use caseSizeWeight
Screen / display titles
30px
Bold
Section headers
22px
Bold
Card titles, meal names
18px
SemiBold
Body large, recipe names
16px
Bold / Regular
Body, descriptions
14px
Regular
Timestamps, tags
12px
Regular
Chips, nav labels
11px
SemiBold, uppercase
Nutrition numbers
24px
Bold, colored per macro
Cooking step number
40px
Bold #F97316

To change the font family, replace GoogleFonts.montserrat() with any other google_fonts font in lib/core/theme/app_theme.dart.

Strings and copy

All user-facing text is stored in lib/core/constants/app_strings.dart. To translate or rebrand the app copy, edit only this file — do not change strings directly in widgets.

The app is English only in v1. Multi-language support is planned for v2.

11

Architecture

Folder structure

lib/
lib/
├── core/
│   ├── constants/      ← colors, strings, sizes, prompts
│   ├── enums/          ← AIProvider, MealType, DietaryPreference…
│   ├── theme/          ← light & dark themes
│   ├── router/         ← GoRouter routes + auth redirect
│   └── utils/          ← NutritionCalculator, ServingScaler…

├── data/
│   ├── models/         ← freezed models (Recipe, MealPlan…)
│   ├── repositories/   ← Firestore read/write logic
│   └── services/
│       ├── ai/         ← RecipeAIService + OpenAI + Gemini + Factory
│       ├── remote_config_service.dart
│       ├── revenue_cat_service.dart
│       └── admob_service.dart

├── presentation/
│   ├── providers/      ← Riverpod providers (auth, recipe, meal plan…)
│   ├── screens/        ← one folder per feature / screen
│   └── widgets/        ← common, recipe, nutrition, meal_plan, cooking

└── main.dart

State management

ChefAI uses Riverpod 2 with code generation. All business logic lives in lib/presentation/providers/. Key providers:

authProvider
Firebase Auth state, login, logout
recipeGenerationProvider
AI generation flow, progress phases
recipeLibraryProvider
Saved recipes, favorites, search, filter
mealPlanProvider
7-day meal plan CRUD, AI auto-fill
nutritionProvider
Daily logging, calorie ring, macro bars
cookingModeProvider
Step tracking, countdown timers, wakelock
themeProvider
Light / dark mode toggle
premiumProvider
RevenueCat subscription status
Note
Rule: never use setState for business logic. Never call AI APIs directly from a screen. Always go through a Riverpod provider.

Navigation

ChefAI uses GoRouter with a shell route for the bottom navigation bar. Auth-guard redirects unauthenticated users to /login and unboarded users to /onboarding.

navigation
// Always navigate with GoRouter — never use Navigator.push
context.go('/home');           // replace stack
context.push('/recipe/123');   // push on stack
context.pop();                 // go back
12

AI services

AI calls go through an abstract interface RecipeAIService. Screens and providers never know which AI provider is active — the factory picks the right implementation based on Remote Config.

Switching AI provider

Change the default_ai_provider value in Firebase Remote Config to openai or gemini. The change takes effect on the next app fetch (within 1 hour) — no app update needed.

AI methods

MethodDescriptionModel
generateRecipes()
Generate recipes from ingredients
Standard model
generateMealPlan()
7-day meal plan generation
Standard model
lookupNutrition()
Nutrition for any logged food (powers meal logging)
Fast model
getSubstitutions()
Ingredient substitution suggestions
Fast model

Adding a new AI provider

  1. 01
    Create a new class implementing RecipeAIService
  2. 02
    Add the provider to AIProvider enum
  3. 03
    Add a case to AIServiceFactory.create()
  4. 04
    Add the API key to Remote Config
13

Data models

All models use freezed for immutability and JSON serialization. Never write models by hand.

ModelFilePurpose
Recipe
data/models/recipe.dart
Full recipe with ingredients, steps, nutrition
RecipeIngredient
data/models/recipe_ingredient.dart
Single ingredient with quantity, unit, optional flag
RecipeStep
data/models/recipe_step.dart
Cooking step with optional timer
NutritionFacts
data/models/nutrition_facts.dart
Calories, protein, carbs, fat, fiber, sodium, sugar
MealPlan
data/models/meal_plan.dart
7-day plan container
NutritionLog
data/models/nutrition_log.dart
Daily meal log with water tracker
ShoppingList
data/models/shopping_list.dart
One week’s grocery list, keyed to the meal plan week
ShoppingItem
data/models/shopping_item.dart
Single line: merged quantity, aisle, source recipes
UserProfile
data/models/user_profile.dart
User prefs, goals, subscription status

After any model change, always regenerate:

terminal
flutter pub run build_runner build --delete-conflicting-outputs
14

Free tier limits

Limits are enforced in providers, not screens. All values come from Remote Config so you can adjust them without an app update.

LimitRemote Config keyDefault
Daily recipe generations
free_daily_generations
5
Recipes per session
free_recipes_per_session
1
Max saved recipes
free_max_saved_recipes
20
Nutrition history (days)
nutrition_history_days_free
1
15

Build and release

Build commands

terminal
# Install dependencies
flutter pub get

# Regenerate code after model changes
flutter pub run build_runner build --delete-conflicting-outputs

# Format code
dart format lib/

# Static analysis (must be zero issues)
flutter analyze

# Run in debug mode
flutter run

# Build release APK
flutter build apk --release

# Build release App Bundle (Google Play)
flutter build appbundle --release

# Build release iOS (requires macOS + Xcode)
flutter build ios --release

Android release

  1. 01

    Generate a keystore

    terminal
    keytool -genkey -v -keystore ~/upload-keystore.jks -alias upload -keyalg RSA -keysize 2048 -validity 10000
  2. 02

    Configure signing

    Create android/key.properties with your keystore path, alias, and passwords. Reference it in android/app/build.gradle.
  3. 03

    Update version

    In pubspec.yaml, set version: 1.0.0+1 (name+build number).
  4. 04

    Build App Bundle

    flutter build appbundle --release → upload build/app/outputs/bundle/release/app-release.aab to Google Play.
Warning
Keep your keystore safe: never commit key.properties or your .jks keystore file to git. Add both to .gitignore. Losing the keystore means you cannot update your app.

iOS release

  1. 01

    Open in Xcode

    Open ios/Runner.xcworkspace (not .xcodeproj) in Xcode.
  2. 02

    Set team and bundle ID

    In Runner → Signing and Capabilities, select your Apple Developer Team and set the Bundle Identifier to your own ID.
  3. 03

    Add Sign in with Apple capability

    Click + Capability → add Sign In with Apple.
  4. 04

    Archive and upload

    Product → Archive → Distribute App → App Store Connect → Upload.
Note
Minimum iOS version: the deployment target is set to iOS 15.6 in both Podfile and project.pbxproj.

Pre-launch checklist

  • Change bundle ID / package name from com.devsnack.chefai to your own
  • Place google-services.json in android/app/
  • Place GoogleService-Info.plist in ios/Runner/
  • Enable Firebase Auth (Email, Google, Apple)
  • Apply Firestore security rules
  • Add all Remote Config parameters (API keys, limits, AdMob IDs)
  • Add AdMob App ID to AndroidManifest.xml and Info.plist
  • Configure RevenueCat and update API key in revenue_cat_service.dart
  • Update app name in AndroidManifest.xml and Info.plist
  • Replace app icon assets
  • Run flutter analyze — zero issues
  • Test on a real iOS device and Android device
  • Test purchase flow in sandbox / test environment
  • Test AdMob ads are loading
  • Verify dark mode on all screens
16

FAQ and troubleshooting

The app crashes on launch — what’s wrong?
Most likely Firebase is not configured. Ensure google-services.json and GoogleService-Info.plist are in the correct locations and that firebase_options.dart matches your project.
Recipes are not being generated — AI returns nothing
Check that openai_api_key (or gemini_api_key) is set in Firebase Remote Config and that the key has sufficient credits/quota.
Build runner fails with conflicts
Run flutter pub run build_runner clean then flutter pub run build_runner build --delete-conflicting-outputs.
iOS pod install fails
Try cd ios && pod deintegrate && pod install. Make sure CocoaPods is up to date: sudo gem install cocoapods.
How do I change the AI model?
No code change needed — set openai_model, openai_model_fast, gemini_model, or gemini_model_fast in Firebase Remote Config. The “fast” models are used for nutrition lookups and ingredient substitutions; the standard models are used for recipe and meal plan generation. Leaving a value blank falls back to the built-in default.Note: AI providers retire models over time. If generation suddenly starts failing, check that your configured model is still available — that is the most common cause. Also note that OpenAI’s GPT-5 family renamed max_tokens to max_completion_tokens, so switching to one of those models also requires updating the request body in _chat() in lib/data/services/ai/openai_recipe_service.dart.
Can I remove AdMob or RevenueCat?
Yes. Remove the relevant service file, remove the package from pubspec.yaml, and remove references from providers. Both are optional integrations.
17

Changelog

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

v1.1.0 · Jul 2026
Manual meal logging, AI nutrition lookup, shared AI service provider, documentation refresh.
v1.0.0 · Mar 2026
Initial release with 26 screens, dual AI providers, RevenueCat and AdMob, dark mode, cooking mode with wakelock and timers.

Version 1.2.0 · August 2026

  • Smart shopping list — build a grocery list from the weekly meal plan. Duplicate ingredients are merged across recipes, grouped by supermarket aisle, with tick-off state saved to Firestore, manual items, and plain-text sharing.
  • AI model IDs moved to Remote Config (openai_model, gemini_model, and their _fast variants) — change models without an app update when a provider retires one.
  • Default Gemini models updated to the current generation.
  • Editable profile (/profile/edit) — diet, allergies, cuisines, calorie and macro goals, household size, cooking skill, and measurement units, with a BMR/TDEE calorie calculator.
  • Paywall now loads real RevenueCat offerings and purchases the selected package.
  • Request timeouts and detailed error logging added to both AI services; token budgets now scale with the requested recipe count.
  • Fixes: cooking timer notifications now initialize and fire; recipe ratings and cook counts persist for unsaved recipes; the logging streak increments; fiber is tracked per logged meal; scaled servings carry into cooking mode.
Warning
Upgrading from v1.1: re-apply the Firestore security rules — they now include the shoppingLists collection, and the shopping list will fail with permission-denied without it. Then run flutter pub run build_runner build --delete-conflicting-outputs for the new models.

Version 1.1.0 · July 2026

  • Manual meal logging to any meal section.
  • AI nutrition lookup surfaced in the tracker.
  • Shared AI service provider used by both recipe generation and nutrition lookup.

Version 1.0.0 · March 2026

  • Initial release — all screens, dual AI providers, RevenueCat + AdMob monetization, full dark mode, step-by-step cooking mode with wakelock and timers.
18

Support and licensing

We’re happy to help with installation, configuration, and customization questions. Typical response time is within 24 hours on business days.

Note
When contacting support, please include your CodeCanyon purchase code, Flutter version (flutter --version), and a description of the issue with any error messages.

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