A Flutter mobile application that lets university students browse the campus cafeteria menu, place food orders in advance, and skip the queue. Built with Flutter and Firebase.
This repository (
foodorder) contains the Student App. There is the admin companion app which will not be published.
This Project code changes must be reviewed by:
- Coderabbit coderabbit.ai
- Qodo ai qodo.ai
- SonarCloud sonarcloud.io
- Project Overview
- System Architecture
- Tech Stack
- Documentation
- Prerequisites
- Getting Started
- Firestore Security Rules
- App Navigation
- Key Features
- Order Lifecycle
- Environment & Secrets
- Running Tests
- Contributing
- AI Agent Usage
- Troubleshooting
- License
| Doc | Contents |
|---|---|
| ARCHITECTURE.md | System map, Cloud Functions, update system |
| DATABASE.md | Firestore schema, security model, indexes, offline |
| BUSINESS_RULES.md | Lifecycle, reliability, restrictions, excusal, disposition |
| SECURITY.md | Auth, rules model, secrets, monitoring/privacy |
| DEPLOYMENT.md | Deploy steps, release process, rollback plan |
| TROUBLESHOOTING.md | Common issues and fixes |
| ROADMAP.md | Phase history and forward-looking plans |
| PRODUCTION_CHECKLIST.md | Release gate checklist |
| DOCUMENTATION.md | Deep dives: lifecycle, reliability engine, notifications, FCM |
| PHASE_I_REPORT.md | Release evidence and recomendations |
CampusBite solves common problems at university cafeterias:
| Problem | Solution |
|---|---|
| Long queues at meal times | Students order in advance from their phone |
| No visibility into today's menu | Live menu synced from Firestore in real-time |
| Abandoned orders causing food waste | Pickup deadline engine with countdown timers |
| No accountability for no-shows | Missed pickups are marked as no-show and the student is notified |
The system consists of three components only the foodorder student app is in this directory but all two share a single Firebase project:
foodorder/ ← Student Flutter App (this repo)
┌──────────────┐ ┌──────────────┐
│ Student App │ │ Admin App │
│ (Flutter) │ │ (Flutter) │
└──────┬───────┘ └──────┬───────┘
│ │
│ Firestore Streams │ Firestore CRUD
▼ ▼
┌─────────────────────────────────────┐
│ Cloud Firestore │
│ ┌────────┐ ┌──────┐ ┌───────────┐ │
│ │ food_ │ │orders│ │ users │ │
│ │ items │ │ │ │ /cart │ │
│ └────────┘ └──┬───┘ └───────────┘ │
│ │ │
│ onDocumentUpdated │
│ ▼ │
│ ┌────────────────────────────┐ │
│ │ Cloud Functions (v2) │ │
│ │ • Pickup Deadline Engine │ │
│ │ • Cloudinary Image Delete│ │
│ └────────────────────────────┘ │
└─────────────────────────────────────┘
│
▼
┌──────────────┐ ┌──────────────┐
│ Firebase Auth│ │ Cloudinary │
│ (Email/Pass) │ │ (Food Images)│
└──────────────┘ └──────────────┘
Data flow:
- Admin creates/updates food items → Firestore
food_itemscollection - Student app streams
food_itemsin real-time → displays live menu - Student places order → writes to
orderscollection - Admin updates order status to "ready" → Cloud Function triggers
- Cloud Function computes
readyAt,pickupDeadline→ writes back to order - Student app displays countdown timer from Firestore data
- If student doesn't collect → order marked no-show and student notified
| Layer | Technology |
|---|---|
| Framework | Flutter (Dart SDK ^3.12.2) |
| State Management | Streams + setState (simple architecture) |
| Routing | go_router with auth-aware redirects |
| Authentication | Firebase Auth (Email/Password) |
| Database | Cloud Firestore (real-time sync) |
| Cloud Functions | Firebase Functions v2 (Node.js) |
| Image Hosting | Cloudinary (via admin app) |
| Image Caching | cached_network_image |
| Typography | Google Fonts (DM Sans) |
| Offline Detection | dash_no_internet_screen |
Before you begin, ensure you have the following installed:
- Flutter SDK ≥ 3.12.2 — Install Flutter
- Dart SDK — bundled with Flutter
- Android Studio or VS Code with Flutter extensions
- An Android emulator or physical device (API 21+)
- Node.js ≥ 18 — required for Cloud Functions
- Firebase CLI —
npm install -g firebase-toolsor usenpx firebase-tools - A Firebase project — Create one here
Verify your setup:
flutter doctor
firebase --version # or: npx firebase-tools --version
node --versiongit clone <repository-url>
cd foodorderThe app requires a Firebase project with Authentication, Cloud Firestore, and Cloud Functions enabled.
- Go to the Firebase Console
- Create a new project (or use an existing one)
- Enable Email/Password under Authentication → Sign-in method
# Install FlutterFire CLI
dart pub global activate flutterfire_cli
# Configure for this project (run from customerview/)
flutterfire configure --project=<your-firebase-project-id>This generates lib/firebase_options.dart and android/app/google-services.json.
- In Firebase Console → Firestore Database → Create database
- Start in production mode
- create and update security rules (see Firestore Security Rules)
create your firebase rules and deploy them
npx firebase-tools deploy --only functionscd foodorder
flutter pub getAndroid Studio: Click the ▶ Run button in the toolbar.
VS Code:
Open lib/main.dart and press F5, or:
flutter runWeb (experimental):
flutter run -d chromeRead and write your own firestore rules. follow best practices in the official documentations.
The student app uses go_router with authentication-aware redirects:
/ → WelcomeScreen (unauthenticated landing)
/register → RegisterScreen
/login → LoginScreen
/main → MainScreen (authenticated, contains bottom nav)
/terms → TermsScreen
/support → SupportScreen
/support/faq → FaqScreen
/support/contact → ContactScreen
Auth redirects:
- Logged in + on
/,/login, or/register→ redirected to/main
Bottom Navigation Bar (inside /main):
| Index | Tab | Screen |
|---|---|---|
| 0 | Home | HomeScreen — featured items, sections, food feed |
| 1 | Categories | CategoryScreen — browse by Breakfast, Lunch, etc. |
| 2 | Search | SearchBarScreen — Firestore prefix-based search |
| 3 | Orders | OrdersScreen — active orders with countdown, history |
| 4 | Account | AccountScreen — profile, settings, logout |
- Registration, Verification & Password Recovery — Email/password authentication via Firebase Auth, complete with mandatory verification of email addresses before ordering and clean self-serve password recovery options.
- Your Favourites — Personalized carousel of student's top favourite food items computed from order history.
- Reviews & Ratings — Leave reviews for completed orders, view average food ratings, and view customer feedback.
- In-App Update System — Automatic updates with resume-able downloads and SHA-256 checksum verification to guarantee authentic builds*.
- Browse Menu — Real-time Firestore stream of available food items sorted by category.
- Categories — Quick navigation to browse food items by categories (e.g. Breakfast, Lunch, Dinner, Teasers, Drinks).
- Search — Fast, prefix-based Firestore search with 300ms debounce and in-memory caching.
- Cart & Checkout — Add items, choose target cafe, and review total amount before placing orders.
- Distance-Based Pickup Window — Automatically calculates walking distance to target cafe using GPS/Geolocator and requests corresponding pickup time window at checkout (from 10 to 25 minutes) to ensure freshness.
- Orders & Countdown Timers — Track active order statuses and see real-time pickup countdown timers synced with server-enforced deadlines.
- One-Tap Reordering — Reorder entire past orders with one tap from the order history. Automatically checks current availability/stock levels for each item before loading them into the active cart.
- Meal Planning — Pre-plan customized meals for upcoming days, study breaks, or campus events. Save custom plans directly from the active cart or convert a past order into a plan, then load and purchase in one click when ready.
- Pickup Extension — One-tap "Extend pickup by 10 min" action (once per order, before the deadline) available on the order card and in the order details sheet.
- Pickup Reliability — Your pickup reliability score, status, and collection history shown in My Profile (Phases D–F). Informational only: new users and limited-history users are never shown a poor rating. Status is informational; the Phase E graduated ordering limit is derived from the same server-maintained summary and relaxes automatically as you collect orders (Phase F).
- Notification Center — In-app notification feed supporting real-time alerts for order status changes, pickup reminders, missed-pickup (no-show) alerts, and account suspension events.
- New Order Alerts — Automatic notification of incoming student orders in real time.
- Order Flow Manager — Control order stages from pending, accepted, preparing, to ready for collection.
- No-Show Tracking — Missed pickups are automatically marked
no_showand logged toaudit_logs; no strikes are issued by the customer backend. - Account Management — Reactivate a genuinely suspended student account via the backend
reactivateStudentcallable: the ACTIVE flip and the immutableaudit_logsREACTIVATE record are written server-side (audit_logs are backend-only — no client create/update/delete).
To minimize food waste from abandoned orders while keeping pickup schedules fair for students, CampusBite calculates a dynamic pickup window based on the student's walking distance to the cafeteria at the moment they checkout:
CampusBite provides students with tools to plan meals in advance and quickly repeat past orders. These features improve convenience and decrease checkout friction, especially during busy campus hours.
CampusBite keeps pickup schedules fair and prevents food waste by enforcing server-authoritative deadlines, giving students a one-time grace action, and notifying them when an order is missed.
CampusBite features a scalable, production-ready notification platform that decouples notification delivery from core business logic.
Where notifications are created: In production, notification documents are written server-side by Cloud Functions (
createNotificationinfunctions/index.js) using the Admin SDK, which bypasses Firestore client rules.NotificationService.dartis the client-side helper — it mirrors the same idempotent creation logic for parity/future use and powers all read, unread-count, and read/delete operations in the apps. The client never writes notifications directly in the current flows.
although we commited and it is safe to do that but Never commit
google-services.json,firebase_options.dartwith real keys, or.envfiles to public repos. Add them to.gitignore.
# Run all tests
flutter test
# Run a specific test file
flutter test test/search_helper_test.dart
# Run with verbose output
flutter test --reporter expanded
# Run static analysis
flutter analyze- Push access are restricted to maintainers only
# Create a feature branch
git checkout -b feature/my-new-feature
# Make your changes, commit frequently
git add .
git commit -m "Add descriptive commit message explaining what changed and why"
# When ready to merge
git checkout main
git pull origin main
git merge feature/my-new-feature- Always run
flutter pub getafter pulling changes - Write descriptive commit messages — even if they're long
- Add comments when writing new features
- Create a branch for new features to avoid merge conflicts
- Run
flutter analyzebefore committing — no warnings allowed - Run
flutter testto make sure nothing is broken - Don't break existing features — verify navigation and build after changes
- Follow the project structure:
screens/,widgets/,services/,models/,data/,navigation/ - Keep widgets focused and reusable
- Use Firestore streams (not polling) for real-time data
- Never calculate timestamps in Flutter — the backend is the source of truth for deadlines
This project includes an AGENTS.md file that defines strict rules for AI coding assistants. When using AI tools:
- Always instruct the AI to follow
AGENTS.mdrules - The file defines the current development phase, architecture constraints, and what must/must not be implemented
- AI agents must not rewrite working code, introduce unnecessary complexity, or implement features outside the active phase
| Issue | Solution |
|---|---|
firebase_core initialization fails |
Ensure google-services.json is in android/app/ and firebase_options.dart exists |
| Firestore permission denied | Check security rules match the schema above, and the user document has the correct role |
| Search returns no results | Re-save food items through the admin app to generate searchPrefixes |
| Cloud Function not triggering | Verify functions are deployed: npx firebase-tools functions:list |
| Countdown timer shows wrong time | Ensure device clock is roughly accurate; the countdown uses pickupDeadline - DateTime.now() |
Build fails after git pull |
Run flutter pub get and flutter clean |
| Emulator not connecting to Firestore | Check internet connection and Firebase project configuration |
See the Project official Documentation for more Instructions and overviews
This project is licensed under the Apache 2.0 License terms specified in the LICENSE and NOTICE files.
To all maintainers and contributors of this app. We hope this gives an idea of the working behind the Campus Bite student app.