Build a carbon footprint tracker in FlutterFlow by logging daily activities, calculating CO2 emissions using emission factors stored in Firestore (not hardcoded), displaying a PieChart breakdown by category and a LineChart monthly trend, comparing against a national average, and offering monthly reduction goals with contextual eco tips.
Why Emission Factors Belong in Firestore, Not Code
A carbon footprint app is only as accurate as its emission data. Emission factors — the kg of CO2 produced per unit of activity — vary significantly by country, change every year as energy grids get cleaner, and differ between scientific bodies and government datasets. If you hardcode these values into your app's Custom Functions, every factor update requires a new app release and re-review. Storing them in Firestore means you can update any factor in seconds without touching your app. This tutorial builds a full carbon tracking app around that core principle: the data is always live, always updatable, and organized by country so international users get accurate numbers.
Prerequisites
- A FlutterFlow project connected to Firebase with Firestore enabled
- Basic familiarity with FlutterFlow chart widgets (PieChart, LineChart)
- A Firestore collection called emission_factors pre-populated with initial data
- Understanding of FlutterFlow Custom Functions for calculation logic
Step-by-step guide
Populate the emission_factors Firestore collection
Populate the emission_factors Firestore collection
Before building the UI, seed your emission_factors collection with data. Each document should represent one activity type. The document ID can be a readable slug like 'car-petrol-km'. Fields: category (String: Transport / Home Energy / Food / Shopping / Flights), activityName (String), unit (String: km / kWh / kg / item / flight), co2PerUnit (Number, kg CO2 per unit), country (String: US / UK / EU / Global), source (String: citation), lastUpdated (Timestamp). Create at least 25-30 entries covering: car travel (petrol and electric per km), bus and train per km, short-haul and long-haul flights per km, home electricity by country, natural gas per kWh, beef and chicken per kg, and clothing purchases. This collection becomes the living database your app queries at runtime instead of relying on compiled constants.
Expected result: Your Firestore emission_factors collection has 25-30 documents visible in the Firebase console, each with category, unit, co2PerUnit, country, and source fields.
Build the activity logging screen
Build the activity logging screen
Create an AddActivityPage. Add a Dropdown bound to a list of distinct categories fetched from emission_factors (or hardcoded: Transport, Home Energy, Food, Shopping, Flights). When a category is selected, load a second Dropdown with all activityName values for that category from Firestore using a conditional query. Add a TextField for the quantity (with the unit label dynamically set from the selected activity's unit field). Add a DatePicker defaulting to today. Add a notes TextField (optional). When the user taps 'Log Activity', run a Custom Function to calculate CO2: multiply quantity by the co2PerUnit from the selected emission factor document. Save a new document to the user_activities collection with fields: userId, activityId, activityName, category, quantity, unit, co2Kg (calculated), loggedDate, country (from user profile), and notes.
1// Custom Function: calculateCO22// Parameters: quantity (double), co2PerUnit (double)3// Returns: double4double calculateCO2(double quantity, double co2PerUnit) {5 return quantity * co2PerUnit;6}Expected result: Logging 'Car travel, 25 km' saves a user_activities document with co2Kg approximately 4.13 (using a typical petrol factor of 0.165 kg CO2/km). The calculation matches the emission factor stored in Firestore.
Build the monthly dashboard with PieChart and totals
Build the monthly dashboard with PieChart and totals
Create a DashboardPage. Add a month selector (two arrow buttons with a Text showing the current month/year, stored in Page State). Query user_activities for the current user, filtered by loggedDate within the selected month's date range. Sum co2Kg by category using a Custom Function that groups the returned list by the category field. Display a PieChart widget (available in FlutterFlow's chart section) with one slice per category — bind the slices to your grouped data. Below the PieChart, show a summary Row with the total monthly CO2, a comparison chip ('12% below national average' or 'X kg above'), and the user's monthly goal progress bar. The national average is a constant per country — store it in a Firestore document called national_averages/{countryCode} with a field monthlyKgCO2.
Expected result: The dashboard shows a PieChart with colored slices per category. Switching months updates all figures. The comparison chip shows the user's position relative to their country's average.
Add the monthly trend LineChart
Add the monthly trend LineChart
Add a LineChart widget below the PieChart on the DashboardPage. Query the user's total monthly CO2 for the last 6 months. To do this efficiently, run a Custom Action that performs 6 Firestore queries (one per month) in parallel using Future.wait, summing co2Kg for each month. Return the results as a list of monthly totals. Bind this list to the LineChart's data series. Add a second line on the chart representing the national monthly average (a flat horizontal line from the national_averages document). This two-line chart immediately shows whether the user is trending toward or away from their goal. Add a simple trendDirection Custom Function that returns 'improving', 'worsening', or 'stable' based on the last three months' slope, and display a corresponding icon and message.
Expected result: A LineChart shows the user's CO2 trend over 6 months alongside the national average line. An improving or worsening trend indicator appears below the chart.
Add monthly goals and contextual eco tips
Add monthly goals and contextual eco tips
Create a GoalsPage. Display the user's current monthly CO2 target (set by the user via a Slider, stored in their Firestore profile document). Show a progress bar comparing current month total to the target. Add a 'My Top Impact' card that calculates which category contributed the most CO2 this month. Below it, display 2-3 context-sensitive eco tips — fetch tips from a Firestore eco_tips collection where you filter by category. For example, if Transport is the top category, show tips like 'Try combining errands into one trip' or 'Consider an electric vehicle — EVs cut transport emissions by 60-70%'. Fetch 3 random tips per category from eco_tips on page load. Add a monthly achievements system: if the user beats their goal for 3 consecutive months, award a badge stored in their profile.
Expected result: The goals page shows the current target, progress bar, top impact category, and 3 relevant tips. Users who beat their goal three months in a row see an achievement badge on their profile.
Complete working example
1import 'package:cloud_firestore/cloud_firestore.dart';2import 'package:firebase_auth/firebase_auth.dart';34final _db = FirebaseFirestore.instance;56// --- Fetch emission factor from Firestore by activity and country ---7Future<double> getEmissionFactor(String activityId, String country) async {8 // Try country-specific factor first9 var snap = await _db10 .collection('emission_factors')11 .where('activityId', isEqualTo: activityId)12 .where('country', isEqualTo: country)13 .limit(1)14 .get();1516 // Fall back to Global if country not found17 if (snap.docs.isEmpty) {18 snap = await _db19 .collection('emission_factors')20 .where('activityId', isEqualTo: activityId)21 .where('country', isEqualTo: 'Global')22 .limit(1)23 .get();24 }2526 if (snap.docs.isEmpty) return 0.0;27 return (snap.docs.first.data()['co2PerUnit'] as num).toDouble();28}2930// --- Log an activity to Firestore ---31Future<void> logActivity({32 required String activityId,33 required String activityName,34 required String category,35 required double quantity,36 required String unit,37 required double co2PerUnit,38 required DateTime loggedDate,39 String? notes,40}) async {41 final uid = FirebaseAuth.instance.currentUser?.uid;42 if (uid == null) return;4344 await _db.collection('user_activities').add({45 'userId': uid,46 'activityId': activityId,47 'activityName': activityName,48 'category': category,49 'quantity': quantity,50 'unit': unit,51 'co2Kg': quantity * co2PerUnit,52 'loggedDate': Timestamp.fromDate(loggedDate),53 'notes': notes ?? '',54 'createdAt': FieldValue.serverTimestamp(),55 });56}5758// --- Get monthly totals by category for PieChart ---59Future<Map<String, double>> getMonthlyCategoryTotals(60 int year,61 int month,62) async {63 final uid = FirebaseAuth.instance.currentUser?.uid;64 if (uid == null) return {};6566 final start = DateTime(year, month, 1);67 final end = DateTime(year, month + 1, 1);6869 final snap = await _db70 .collection('user_activities')71 .where('userId', isEqualTo: uid)72 .where('loggedDate', isGreaterThanOrEqualTo: Timestamp.fromDate(start))73 .where('loggedDate', isLessThan: Timestamp.fromDate(end))74 .get();7576 final totals = <String, double>{};77 for (final doc in snap.docs) {78 final cat = doc.data()['category'] as String;79 final co2 = (doc.data()['co2Kg'] as num).toDouble();80 totals[cat] = (totals[cat] ?? 0) + co2;81 }82 return totals;83}Common mistakes when building an Environmental Impact Tracking App in FlutterFlow
Why it's a problem: Hardcoding emission factors as constants inside Custom Functions
How to avoid: Store all emission factors in a Firestore emission_factors collection with a country field and lastUpdated timestamp. Fetch the appropriate factor at calculation time. Update factors in Firestore without touching the app code.
Why it's a problem: Querying all user activities for all time to calculate the dashboard totals
How to avoid: Always filter user_activities queries by date range for the specific period being displayed. Use monthly summary documents (user_monthly_summaries/{uid}_{year}_{month}) updated by a Cloud Function to avoid re-aggregating on every dashboard load.
Why it's a problem: Using a single national average for all users regardless of their country
How to avoid: Store national averages in a national_averages Firestore collection keyed by country code. Set the user's country during onboarding and use it to fetch the correct comparison average.
Best practices
- Store all emission factors in Firestore with country, source citation, and lastUpdated fields — never hardcode them
- Add a country selector during onboarding so CO2 calculations use region-appropriate emission factors from the start
- Cache monthly totals in summary documents to avoid repeated aggregation queries on the dashboard
- Cite your data source for each emission factor — users trust apps that are transparent about where numbers come from
- Frame the comparison positively: show percentage below average when the user is doing well, not just when they are over
- Include achievable tips relevant to the user's highest-impact category rather than generic advice
- Allow manual emission factor overrides for advanced users who know their specific energy provider's mix
Still stuck?
Copy one of these prompts to get a personalized, step-by-step explanation.
I am building a carbon footprint tracking app in FlutterFlow. Design a Firestore schema for storing emission factors that vary by country and can be updated without an app release. Include fields for category, activity type, unit, CO2 per unit, country, data source citation, and last updated timestamp. Provide 10 example documents covering transport, food, and home energy.
In my FlutterFlow project, write a Custom Function called getMonthlyCategoryTotals that accepts a year and month as integers, queries the user_activities Firestore collection for the current user filtered to that month's date range, groups the co2Kg values by category field, and returns a Map<String, double> for binding to a PieChart.
Frequently asked questions
How accurate are CO2 emission calculations in a self-built app?
Accuracy depends entirely on the emission factors you use. Factors from government sources like the UK DEFRA conversion factors or the US EPA emission factors are well-validated. Clearly cite your sources in the app's About section and note that calculations are estimates, not certified measurements.
How do I handle emission factor updates without pushing a new app version?
Because you store factors in Firestore (not code), you simply update the relevant document in the Firebase console. The app fetches factors at runtime, so all users immediately benefit from the correction without downloading an update.
Can I add flight carbon calculations?
Yes. Flight emissions are typically calculated based on distance (km) between airports multiplied by an emission factor that accounts for aircraft type and a radiative forcing multiplier. Store a flight emission factor (e.g., 0.255 kg CO2 per km for short-haul economy) in your emission_factors collection under category 'Flights', and let users input origin and destination airports or direct distance.
How do I show a national average comparison if I do not know the user's country?
Ask for country during the onboarding flow — it is a single Dropdown question. If the user skips it, fall back to a 'Global' average from your national_averages collection. You can also try to infer country from device locale as a convenience prefill, but always let the user confirm or change it.
What chart type works best for showing CO2 by category in FlutterFlow?
A PieChart is the most intuitive for showing the proportion of total emissions by category. FlutterFlow has a built-in Pie Chart widget that binds directly to a list of data points. For trends over time, use the Line Chart widget. For comparing multiple months side by side, the Bar Chart widget works well.
Can I monetize this type of app?
Yes. Common monetization approaches include: a premium tier with detailed historical reports and PDF export, a business version for companies tracking team carbon footprints, sponsorship from eco-friendly brands whose tips appear in the app, or a marketplace for verified carbon offsets. Ensure any carbon offset marketplace is connected to reputable third-party certifiers.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation