// INFT-3101 · Mobile Development · Durham College

RECIPE
BUDDY

Role Developer + UI/UX Designer
Student Divyansh Kumar · 100912841
Platform Flutter · Android / iOS
Course INFT-3101
Scroll to explore
01

PROJECT
OVERVIEW

What it is
Recipe App
A full-stack Flutter application for creating, viewing, and managing personal recipes — with cloud sync and real-time data.
Core Tech
Firebase
Google Authentication, Firestore for data persistence, and Firebase Storage for image hosting — a complete BaaS integration.
Screens Built
4 Screens
Login, Home Grid, Add Recipe, and Recipe Details — all designed and developed from scratch by me.
Key Challenge
Firebase Perms
Debugging Firebase Storage permission rules during image uploads required deep dive into security rules and async error handling.
02

THE
STORY

The brief was simple: build a mobile app for a final project. The vision I had was more ambitious — a production-quality recipe manager that felt as polished as apps on the App Store, not a prototype slapped together overnight.

I designed and developed every screen from scratch — the login flow with Google OAuth persistence, the home screen with its responsive 3-column recipe grid, a camera-integrated add-recipe flow, and a detail screen with a curved image header that took serious time to get right.

On the backend, I wired up three Firebase services: Authentication for secure login, Firestore for structured recipe data, and Firebase Storage for user images. Getting all three to talk to each other reliably — with proper permission rules and async flows — was the real engineering challenge.

The result is an app that handles the full lifecycle of a recipe: capture an image with your phone's camera, fill in the details, and it's live in the cloud instantly — accessible from any device, any session.

📱
Add your hero / overview screenshot here
// app overview · add your image
03

ARCHITECTURE

Frontend
Flutter framework with Dart — single codebase targeting Android & iOS
Widget-based component architecture, state managed locally per screen
Custom curved image header on Recipe Details using ClipPath
Responsive 3-column GridView layout with CrossAxisSpacing and padding
Auth
Google Sign-In via firebase_auth — OAuth 2.0 token flow
Persistent session state — user stays logged in across app restarts
StreamBuilder listening to authStateChanges() for reactive UI routing
Manual sign-out triggers session clear and redirect to login screen
Database
Cloud Firestore — NoSQL document-oriented database via Firebase SDK
Recipes stored as documents: name, ingredients (array), steps (array), imageUrl (string)
Real-time snapshots via .snapshots() stream — home grid updates live
User-scoped collections for per-user recipe isolation
Storage
Firebase Storage for binary image data — JPEG captured from device camera
image_picker package bridges native camera API → Flutter file object
Upload returns a download URL that is saved alongside recipe document in Firestore
Security rules scoped to authenticated users — debugged permission errors manually
04

TECH
STACK

🦋
Flutter
UI Framework
🎯
Dart
Language
🔥
Firebase Auth
Authentication
🗃️
Firestore
NoSQL Database
🖼️
Firebase Storage
Image Hosting
📷
image_picker
Camera Bridge
🔐
Google Sign-In
OAuth 2.0
☁️
Cloud Functions
Backend Logic
05

DATA
MODEL

Recipe Firestore Doc
String id
String name
List<String> ingredients
List<String> steps
String? imageUrl
Timestamp createdAt
toFirestore() → Map
fromFirestore(doc) → Recipe
AuthService Singleton
FirebaseAuth _auth
User? currentUser
Stream<User?> authState
signInWithGoogle() → Future
signOut() → Future<void>
listenAuthState() → Stream
RecipeService Repository
FirebaseFirestore _db
FirebaseStorage _storage
CollectionRef _collection
addRecipe(Recipe) → Future
getRecipesStream() → Stream
uploadImage(File) → String
deleteRecipe(id) → Future
HomeScreen StatefulWidget
Stream<List> recipesStream
bool isLoading
GridView.builder(3 columns)
FloatingActionButton → AddScreen
StreamBuilder → RecipeCard
AppBar with logout action
06

BUILD
TIMELINE

// PHASE 01 · Project Setup
Environment & Firebase Init
Set up Flutter project, configured Firebase project on Google Console, integrated firebase_core, firebase_auth, cloud_firestore, and firebase_storage packages. Established project folder structure.
flutter create pubspec.yaml google-services.json
// PHASE 02 · Authentication
Google Sign-In Flow
Implemented Google OAuth via firebase_auth. Built the login screen UI, handled credential flow, and configured persistent session so users stay authenticated across cold restarts.
OAuth 2.0 authStateChanges StreamBuilder
// PHASE 03 · Home Screen
Dynamic Recipe Grid
Built the home screen with a 3-column responsive GridView pulling live data from Firestore via a Stream. Designed RecipeCard widget with image loading and title overlay. Added FloatingActionButton routing.
GridView.builder Firestore Stream CachedNetworkImage
// PHASE 04 · Add Recipe
Camera + Cloud Upload
Integrated image_picker to capture photos from device camera. Handled file upload to Firebase Storage with proper async/await chains. Resolved Storage security rule permission errors after extensive debugging.
image_picker Firebase Storage Security Rules
// PHASE 05 · Recipe Details
Curved Header Design
Designed the details screen with a curved image header using ClipPath widget. Displayed ingredients and steps in styled list views. Focused on visual polish and smooth scroll behavior.
ClipPath CustomClipper ListView
// PHASE 06 · Polish & Testing
QA & Final Report
Final testing across emulator and physical device. Fixed edge cases around image loading on weak network. Wrote documentation, compiled screenshots, and submitted final report.
Device Testing Error Handling Documentation
07

APP
SCREENS

01
Login Screen
Add your screenshot
// login · google sign-in
02
Home Screen
Add your screenshot
// home · recipe grid
03
Add Recipe
Add your screenshot
// add · camera + form
04
Recipe Detail
Add your screenshot
// detail · curved header

→ To add screenshots: replace each slot with <img> tags pointing to your image files, or drop them into the dashed placeholders above.

08

CHALLENGES
OVERCOME

01
Firebase Storage Permissions
Image upload silently failed in production due to restrictive default security rules. Error messages from Firebase were ambiguous — required reading through rules documentation and iterative testing to identify the exact scope issue.
Scoped rules to authenticated user UID, re-deployed and verified uploads
02
Session Persistence Edge Cases
Ensuring the user stays logged in across app kills — not just backgrounding — required correctly using authStateChanges() stream and handling the null User case on cold start without flashing the login screen.
Used StreamBuilder at the root level to route based on auth state reactively
03
Curved Image Header (ClipPath)
The Recipe Details screen needed a visually distinctive curved header image. Flutter's ClipPath requires a custom CustomClipper subclass — getting the curve to feel natural rather than mechanical took several iterations.
Tuned quadraticBezierTo control points until the curve felt designed, not computed
04
Slow Image Loading on Weak Network
Grid images loaded inconsistently on slow connections — no placeholder meant jarring layout shifts. The Firebase Storage CDN also added latency on first load. Known issue documented with a clear improvement path.
Identified; CachedNetworkImage with shimmer placeholder flagged for next iteration
09

REFLECTION

This project was my first time integrating three Firebase services simultaneously in a production-grade mobile app. Going in, I understood Firebase conceptually — coming out, I understand it operationally: the difference between Authentication's user object and Firestore's document structure, the async lifecycle of a Storage upload, and what security rules actually do at the HTTP layer.

The debugging process for the Storage permissions issue taught me more than any tutorial could. It forced me to read raw Firebase documentation, understand how IAM policies intersect with client-side SDK calls, and think about security as an architectural concern rather than a config checkbox.

On the frontend side, building the curved header on the Recipe Details screen pushed me to understand Flutter's rendering pipeline more deeply — why ClipPath works at the canvas level, and why getting visual polish in Flutter requires thinking in terms of paint operations, not just widget trees.

If I were to rebuild this, I'd add offline caching via Hive or local SQLite to make the app fully functional without a network — and I'd abstract the Firebase service calls into a proper repository pattern from day one rather than refactoring it in later.

// Skills Gained
Flutter / Dart
Firebase Authentication
Cloud Firestore
Firebase Storage
Security Rules Design
Async / Await Patterns
Custom ClipPath UI
Camera API Integration
State Management
Responsive Grid Layout