Integrate nutritional data into FlutterFlow by calling the Nutritionix API (natural language food search) or USDA FoodData Central API via a Cloud Function. The Cloud Function returns calories, protein, carbs, and fat per serving. Display results in a search ListView, let users log meals to a Firestore meals collection, and show daily totals on a dashboard. Cache common foods in Firestore to avoid slow API responses on every search.
Build a food and nutrition tracker in FlutterFlow with real API data
A food nutrition app needs three things: a database of food items with macronutrient data, a search mechanism to find food by name or barcode, and a meal logging system to track daily intake. Two free APIs provide the nutrition database: Nutritionix (natural language parsing — 'one cup of rice' returns exact nutritional data) and USDA FoodData Central (government database of 400,000+ foods, free with API key). The meal logging is a simple Firestore write. The daily dashboard aggregates the logged meals in real time. This tutorial builds all three layers.
Prerequisites
- A Nutritionix API account (free tier at developer.nutritionix.com — App ID and App Key) OR a USDA FoodData Central API key (free at fdc.nal.usda.gov/api-guide)
- A FlutterFlow project connected to Firebase (Firestore for meal logging)
- Basic understanding of FlutterFlow's Backend Queries and Action Flows
- A logged-in user in your app (meals are stored per user)
Step-by-step guide
Set up the Nutritionix API Group in FlutterFlow
Set up the Nutritionix API Group in FlutterFlow
In FlutterFlow, go to API Manager → Add API Group. Name it Nutritionix. Set the Base URL to https://trackapi.nutritionix.com/v2. Under Headers, add: x-app-id with value [NUTRITIONIX_APP_ID] and x-app-key with value [NUTRITIONIX_APP_KEY]. Store both values in Settings → Secrets as NUTRITIONIX_APP_ID and NUTRITIONIX_APP_KEY. Add an API Call named searchFoods: POST method, path /search/instant, JSON body {"query": "[searchQuery]", "branded": true, "common": true, "detailed": true}. Add a second API Call named getNutrients: POST method, path /natural/nutrients, JSON body {"query": "[foodDescription]"}. The searchFoods call returns a list of matching food items; getNutrients takes natural language ('1 cup cooked rice') and returns exact macro data. Test both calls in the API Manager Test tab.
Expected result: Both API Calls test successfully. searchFoods returns food name, brand, thumbnail, and food_id. getNutrients returns nf_calories, nf_protein, nf_total_carbohydrate, nf_total_fat.
Build the food search screen
Build the food search screen
Create a FoodSearch page. Add a TextField named foodSearchField with a search icon and placeholder 'Search food...'. Add On Text Change trigger (with 300ms debounce via a Page State timer) that updates Page State variable searchQuery. Add a Backend Query at the page level calling the searchFoods API Call with [searchQuery] bound to the searchQuery Page State variable. Add a condition: only show the results ListView when searchQuery length > 2 to avoid empty queries. The ListView uses Generate Dynamic Children bound to the API response common and branded arrays. Each list item shows: a CircleAvatar with the food photo_url or a default food icon, the food_name text, and serving info text. On List Item Tap, navigate to the FoodDetail page passing food_name and serving_qty as parameters.
Expected result: Typing in the search field shows a scrollable list of matching foods with names and serving information, loading within 1-2 seconds.
Show nutrition detail and add to meal log
Show nutrition detail and add to meal log
Create a FoodDetail page with Page Parameters foodName (String) and servingQty (Double). On Page Load, call the getNutrients API Call with query bound to '[servingQty] [foodName]' (e.g., '1 cup rice'). Display nutrition data: a large calorie number (nf_calories), and a row of three macro chips — Protein (nf_protein g), Carbs (nf_total_carbohydrate g), Fat (nf_total_fat g). Add a serving size adjuster: a Row with minus and plus buttons that modify Page State servings variable (default 1.0), and display all nutrition values multiplied by servings using Custom Functions. Add a 'Add to Meal Log' button. On tap: create a Firestore document in meals/{userId}/entries with fields: foodName, calories (nf_calories × servings), protein, carbs, fat, servings, mealType (Breakfast/Lunch/Dinner from a ChoiceChips selector), loggedAt (server timestamp).
Expected result: The nutrition detail page shows calories and macros for the selected food, adjustable by serving size, with a working Add to Meal Log button.
Build the daily nutrition dashboard
Build the daily nutrition dashboard
Create a NutritionDashboard page. Add a DatePicker at the top defaulting to today (stored in Page State selectedDate). Add a Backend Query on the page body querying meals/{userId}/entries where loggedAt is within the selectedDate range (today 00:00 to 23:59). Show a calories summary card: a Text widget with the sum of all entries' calories (use a Custom Function sumNutrient(entries, 'calories') → entries.map(e => e.calories).reduce((a, b) => a + b, 0)), a progress bar showing calories vs a daily goal (App State dailyCalorieGoal), and three macro circles (Protein, Carbs, Fat) with grams eaten vs goal. Below the summary, show a ListView of today's meal entries grouped by mealType. Each entry row shows the food name, calories, and a delete button that calls the Delete Document action on that entry document.
Expected result: The dashboard shows today's total calories, macro breakdown, progress toward daily goals, and a list of all logged meals with delete capability.
Cache common foods in Firestore for instant search
Cache common foods in Firestore for instant search
The USDA API can take 2-5 seconds per query and Nutritionix has a rate limit on the free tier (200 calls/day). Add a Firestore cache: before calling the API, check if a matching document exists in foods_cache with the searchQuery as the document ID. If it exists and was updated less than 7 days ago, use the cached data. If not, call the API, store the result in foods_cache/{query} with a lastUpdated Timestamp, and return the result. Implement this logic in a Cloud Function cacheSearch that FlutterFlow calls instead of the API directly. Pre-populate the cache with the 100 most common foods (rice, chicken breast, eggs, banana, apple, etc.) so the first search for these common items returns instantly. This reduces API calls by 80-90% for a typical nutrition app user who logs the same foods daily.
Expected result: Common food searches return results in under 200ms from the Firestore cache instead of 1-3 seconds from the external API.
Complete working example
1// Custom Function: sumDailyNutrients2// Sums nutrition values across all logged meal entries for the day3// Parameters: entries - List<dynamic> from Firestore Backend Query result4// field - String name of the field to sum ('calories', 'protein', etc.)5// Returns: double total6double sumDailyNutrients(7 List<dynamic> entries,8 String field,9) {10 if (entries.isEmpty) return 0.0;1112 double total = 0.0;13 for (final entry in entries) {14 if (entry is Map) {15 final value = entry[field];16 if (value is num) {17 total += value.toDouble();18 }19 }20 }21 return double.parse(total.toStringAsFixed(1));22}2324// Custom Function: adjustedNutrient25// Multiplies a base nutrition value by serving count26// Used on the FoodDetail page when user adjusts portions27double adjustedNutrient(28 double baseValue,29 double servings,30) {31 if (servings <= 0) return 0.0;32 return double.parse((baseValue * servings).toStringAsFixed(1));33}3435// Custom Function: macroPercentage36// Returns what percentage of calories come from a given macro37// protein and carbs = 4 kcal/g, fat = 9 kcal/g38double macroPercentage(39 double macroGrams,40 double totalCalories,41 String macroType,42) {43 if (totalCalories <= 0) return 0.0;44 final kcalPerGram = macroType == 'fat' ? 9.0 : 4.0;45 return (macroGrams * kcalPerGram / totalCalories * 100)46 .clamp(0.0, 100.0);47}Common mistakes
Why it's a problem: Calling the USDA FoodData Central API directly on every keystroke as the user types
How to avoid: Add a debounce of at least 500ms before triggering the search — wait until the user stops typing for half a second. Use the Firestore cache for common foods (Step 5). For real-time search feel, show Nutritionix instant search results (which are faster) first, then load detailed nutritional data from USDA/Nutritionix /nutrients endpoint only when the user selects a specific food.
Why it's a problem: Storing calorie and macro totals as Firestore document fields instead of calculating them from logged entries
How to avoid: Calculate daily totals in real time from the logged entries using Custom Functions (sumDailyNutrients as shown in the complete code). Query all entries for the day and sum the values in the UI. Firestore reads for a day's entries (typically 3-20 documents) are cheap and fast — no need to maintain a pre-aggregated total.
Why it's a problem: Not handling the case where a food has no nutritional data in the API
How to avoid: Use Custom Functions that return 0.0 as a default when the nutrient value is null. In the Firestore meal entry write, store 0 for missing values rather than null. Display a '—' placeholder text when a value is unavailable rather than '0g' which would be misleading.
Best practices
- Always show calorie counts in kcal prominently — users expect the 'calories' number to be kilocalories (what food labels show), not kilojoules
- Include a serving unit selector alongside the serving size adjuster — '100g' vs '1 cup' vs '1 medium banana' represent different actual quantities
- Add barcode scanning via the mobile_scanner pub.dev package to look up packaged foods by UPC code — this is the most-requested feature in food logging apps
- Store the raw API response JSON alongside the extracted nutrients in Firestore so you can re-calculate if you add new nutrient fields later without requiring users to re-log
- Respect the FDA nutrition labeling rounding rules in your display: calories round to nearest 5 below 50 and nearest 10 above 50; fat rounds to nearest 0.5g below 5g and nearest gram above
- Add a recent foods section to the search results — most users log the same 20-30 foods repeatedly, and showing recents before search results dramatically improves the logging speed
- Cache nutritional data per food in Firestore with the food API ID as the document ID — this means the same food item is only fetched from the API once across all users of your app
Still stuck?
Copy one of these prompts to get a personalized, step-by-step explanation.
I am building a food nutrition tracking app in FlutterFlow using the Nutritionix API. Write a Node.js Firebase Cloud Function named getNutritionData that: (1) accepts a POST request with a 'query' field like '1 cup cooked brown rice', (2) calls the Nutritionix /natural/nutrients endpoint with the query, (3) checks a Firestore cache collection first and returns cached data if available and less than 7 days old, (4) returns an object with calories, protein_g, carbs_g, fat_g, serving_description. Include the Nutritionix API headers from environment variables.
Create a food search page in my FlutterFlow app. Add a TextField that calls my Nutritionix API Group's searchFoods endpoint when the user stops typing. Show results in a ListView with food name and serving info. When a food is tapped, navigate to a FoodDetail page that shows calories, protein, carbs, and fat for the selected food, with a serving size stepper and an Add to Meal Log button.
Frequently asked questions
What is the best API for food nutrition data in a FlutterFlow app?
Nutritionix is the best choice for most apps: it has natural language parsing ('1 cup of rice'), 320,000+ foods, a free tier with 200 API calls/day and no credit card required. USDA FoodData Central is better if you need the full scientific micronutrient data (vitamins, minerals) and have no usage limits concern — it is completely free with an API key. Open Food Facts is the best choice for packaged food barcode scanning — it is free, open-source, and has 3 million products worldwide.
How do I add barcode scanning to my nutrition app in FlutterFlow?
Add the mobile_scanner package (^5.1.0) via Custom Code → Pubspec Dependencies. Create a Custom Widget wrapping MobileScanner that opens a full-screen camera view when activated. The scanner fires an onDetect callback with the barcode value (e.g., '012000019628'). Pass this UPC code to the Open Food Facts API: GET https://world.openfoodfacts.org/api/v0/product/{barcode}.json — no API key required. The response contains nutrient_levels with calorie, fat, sugars, and salt data. Cache the barcode lookup in Firestore to avoid re-fetching the same product.
How do I calculate net carbs for keto diet tracking?
Net carbs = total carbohydrates minus dietary fiber. Both values are returned by the Nutritionix API (nf_total_carbohydrate and nf_dietary_fiber). Create a Custom Function: double netCarbs(double totalCarbs, double fiber) => (totalCarbs - fiber).clamp(0.0, double.infinity);. Store both total carbs and fiber in your Firestore meal entries so you can display either total carbs or net carbs based on user diet preference without re-querying the API.
Can I show a standard nutrition facts label in FlutterFlow?
Yes, using a Custom Widget that renders the FDA-style nutrition facts panel. Create a Custom Widget that takes nutrition values as parameters and builds a Column with the exact formatting: bold 'Nutrition Facts' header, serving size, large calorie display, a thick rule, and nutrient rows with %DV values. The %DV is calculated as: nutrientAmount / dailyValue * 100 (e.g., 20g fat / 78g daily value = 26%DV). Alternatively, display a simplified macro breakdown card using standard FlutterFlow widgets for a less formal but faster implementation.
How do I set up daily calorie and macro goals for each user?
Create a Firestore user_settings document per user with fields calorieGoal, proteinGoal, carbGoal, and fatGoal. Add a Goals settings page in FlutterFlow with number input fields for each goal, saved to Firestore on Submit. On the nutrition dashboard, fetch the user_settings document in a page-level Backend Query. Use Custom Functions to calculate progress: progressPercent(consumed, goal) → (consumed / goal * 100).clamp(0, 100). Bind this to a LinearProgressIndicator widget value. For personalized goal calculation, add a TDEE calculator page based on height, weight, age, and activity level using the Mifflin-St Jeor formula in a Custom Function.
Can RapidDev build a full nutrition tracking app in FlutterFlow?
Yes. A production nutrition app with barcode scanning, meal planning, weekly trends, restaurant food integration, and social sharing involves significant FlutterFlow UI design, Custom Widget development, and API integration work. RapidDev has built health and wellness apps in FlutterFlow with nutrition tracking, wearable data integration, and coaching features. Reach out with your feature list and target user base for a project estimate.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation