Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions commis/.firebaserc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"projects": {
"default": "YOUR_PROJECT_ID"
}
}
66 changes: 66 additions & 0 deletions commis/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# Commis Catering Assistant

An AI-powered catering assistant showcasing how to build interactive, stateful **Generative UI (GenUI)** utilizing Flutter, Cloud Firestore, and Dart Cloud Functions.

This repository is organized as a monorepo containing both the mobile/tablet client application and the serverless backend triggers.

```mermaid
graph TD
A[Flutter App] -->|Reads / Writes| B[(Cloud Firestore)]
A -->|Direct Conversation| C[GenUI Core/Renderer]
C -->|Interactive State| A
D[Dart Cloud Functions] <-->|onDocumentWritten trigger| B
D -->|Generates UI JSON| B
```

---

## Project Structure

This project is divided into two primary workspaces:

1. **[Flutter Application (app/)](file:///Users/redbrogdon/source/commis/app/README.md)**: The Flutter frontend application displaying upcoming catering jobs, menus, ingredient listings, and hosting the interactive AI Culinary Assistant chat interface.
2. **[Cloud Functions (functions/)](file:///Users/redbrogdon/source/commis/functions/README.md)**: The serverless backend codebase written in Dart. This includes Firestore triggers that monitor job updates to automatically generate and cache recommended UI cards using Gemini.

Refer to the individual `README.md` files linked above for specific setup and configuration details for each component.

---

## Quick Start (Local Development)

To run the full stack locally using the Firebase Emulator Suite, perform the following steps:

### 1. Prerequisites
- [Flutter SDK](https://docs.flutter.dev/get-started/install)
- [Firebase CLI](https://firebase.google.com/docs/cli) (v15.15.0 or higher is required for Dart support)
- [FlutterFire CLI](https://firebase.google.com/docs/flutter/setup)

### 2. Enable Dart Functions support
```bash
firebase experiments:enable dartfunctions
```

### 3. Start the Emulators
From the root of the workspace, start the Firebase emulator:
```bash
firebase emulators:start
```

### 4. Seed the Database
While the emulator is running, open a new terminal window to seed Firestore with the mock catering dataset:
```bash
export FIRESTORE_EMULATOR_HOST=localhost:8080
cd functions
dart run bin/seed_ingredients.dart
dart run bin/seed_recipes.dart
dart run bin/seed_jobs.dart
```

### 5. Run the Flutter App
From the `app/` directory, configure your local Firebase app and run:
```bash
cd app
flutterfire configure
flutter run
```
*(In debug mode, the app automatically detects and routes traffic to the local Firestore and Functions emulators).*
49 changes: 49 additions & 0 deletions commis/app/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Miscellaneous
*.class
*.log
*.pyc
*.swp
.DS_Store
.atom/
.build/
.buildlog/
.history
.svn/
.swiftpm/
migrate_working_dir/

# IntelliJ related
*.iml
*.ipr
*.iws
.idea/

# The .vscode folder contains launch configuration and tasks you configure in
# VS Code which you may wish to be included in version control, so this line
# is commented out by default.
#.vscode/

# Flutter/Dart/Pub related
**/doc/api/
**/ios/Flutter/.last_build_id
.dart_tool/
.flutter-plugins-dependencies
.pub-cache/
.pub/
/build/
/coverage/

# Symbolication related
app.*.symbols

# Obfuscation related
app.*.map.json

# Android Studio will place build artifacts here
/android/app/debug
/android/app/profile
/android/app/release

# Firebase configuration files (generated by FlutterFire CLI)
google-services.json
GoogleService-Info.plist
45 changes: 45 additions & 0 deletions commis/app/.metadata
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled and should not be manually edited.

version:
revision: "e1fd963c6f6922bd32afde2e9698a363cd0406d2"
channel: "stable"

project_type: app

# Tracks metadata for the flutter migrate command
migration:
platforms:
- platform: root
create_revision: e1fd963c6f6922bd32afde2e9698a363cd0406d2
base_revision: e1fd963c6f6922bd32afde2e9698a363cd0406d2
- platform: android
create_revision: e1fd963c6f6922bd32afde2e9698a363cd0406d2
base_revision: e1fd963c6f6922bd32afde2e9698a363cd0406d2
- platform: ios
create_revision: e1fd963c6f6922bd32afde2e9698a363cd0406d2
base_revision: e1fd963c6f6922bd32afde2e9698a363cd0406d2
- platform: linux
create_revision: e1fd963c6f6922bd32afde2e9698a363cd0406d2
base_revision: e1fd963c6f6922bd32afde2e9698a363cd0406d2
- platform: macos
create_revision: e1fd963c6f6922bd32afde2e9698a363cd0406d2
base_revision: e1fd963c6f6922bd32afde2e9698a363cd0406d2
- platform: web
create_revision: e1fd963c6f6922bd32afde2e9698a363cd0406d2
base_revision: e1fd963c6f6922bd32afde2e9698a363cd0406d2
- platform: windows
create_revision: e1fd963c6f6922bd32afde2e9698a363cd0406d2
base_revision: e1fd963c6f6922bd32afde2e9698a363cd0406d2

# User provided section

# List of Local paths (relative to this file) that should be
# ignored by the migrate tool.
#
# Files that are not part of the templates will be ignored by default.
unmanaged_files:
- 'lib/main.dart'
- 'ios/Runner.xcodeproj/project.pbxproj'
54 changes: 54 additions & 0 deletions commis/app/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# Commis Catering Assistant - Flutter Application

This directory contains the Flutter frontend mobile/tablet client application.

## Features
- **GenUI Integration**: Instantly renders stateful widgets from AI-generated A2UI JSON payloads.
- **AI Culinary Assistant Workspace**: Interactive chat interface for planning menus, managing shopping checklists, and requesting ingredient estimations.
- **Catering Job Pipeline**: Interactive dashboards tracking the statuses of upcoming jobs, with inline warning cards and quick action triggers.

---

## Getting Started

### Prerequisites
- [Flutter SDK](https://docs.flutter.dev/get-started/install)
- [FlutterFire CLI](https://firebase.google.com/docs/flutter/setup)

### Firebase Config Setup
Before running the application, you must link it to your own Firebase project.
1. Run the FlutterFire CLI from this directory to generate your platform configuration files:
```bash
flutterfire configure
```
This generates a local [firebase_options.dart](file:///Users/redbrogdon/source/commis/app/lib/firebase_options.dart) file, as well as the platform-specific configuration files (`google-services.json` and `GoogleService-Info.plist`) which are gitignored.

### Running the App
- **Local Emulator Mode (Default)**: In debug mode, the app automatically routing requests to `localhost:8080` (Firestore) and `localhost:5001` (Functions). Simply start your Firebase Emulator Suite in the root directory and run:
```bash
flutter run
```
- **Production Mode**: To override emulator routing and connect directly to your live production Firebase services, run:
```bash
flutter run --dart-define=USE_EMULATORS=false
```

---

## Generating the Catalog Prompt

The application uses a test script to compile the widget catalog specifications into a system prompt format for Gemini. Because this imports Flutter UI dependencies, it must be run within the Flutter test runner environment.

To regenerate the `catalog_prompt.txt` file, run:
```bash
flutter test test/generate_prompt_test.dart
```
This parses the catalog defined in [catalog.dart](file:///Users/redbrogdon/source/commis/app/lib/ui/catalog/catalog.dart) and saves the output to `catalog_prompt.txt`.

---

## Verification & Testing
To run the project's test suite, execute:
```bash
flutter test
```
9 changes: 9 additions & 0 deletions commis/app/analysis_options.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
include: package:flutter_lints/flutter.yaml

analyzer:
exclude:
- build/**

linter:
rules:
directives_ordering: true
14 changes: 14 additions & 0 deletions commis/app/android/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
gradle-wrapper.jar
/.gradle
/captures/
/gradlew
/gradlew.bat
/local.properties
GeneratedPluginRegistrant.java
.cxx/

# Remember to never publicly share your keystore.
# See https://flutter.dev/to/reference-keystore
key.properties
**/*.keystore
**/*.jks
48 changes: 48 additions & 0 deletions commis/app/android/app/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
plugins {
id("com.android.application")
// START: FlutterFire Configuration
id("com.google.gms.google-services")
// END: FlutterFire Configuration
// The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
id("dev.flutter.flutter-gradle-plugin")
}

android {
namespace = "com.example.commis"
compileSdk = flutter.compileSdkVersion
ndkVersion = flutter.ndkVersion

compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}

defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId = "com.example.commis"
// You can update the following values to match your application needs.
// For more information, see: https://flutter.dev/to/review-gradle-config.
minSdk = flutter.minSdkVersion
targetSdk = flutter.targetSdkVersion
versionCode = flutter.versionCode
versionName = flutter.versionName
}

buildTypes {
release {
// TODO: Add your own signing config for the release build.
// Signing with the debug keys for now, so `flutter run --release` works.
signingConfig = signingConfigs.getByName("debug")
}
}
}

kotlin {
compilerOptions {
jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17
}
}

flutter {
source = "../.."
}
7 changes: 7 additions & 0 deletions commis/app/android/app/src/debug/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<!-- The INTERNET permission is required for development. Specifically,
the Flutter tool needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>
45 changes: 45 additions & 0 deletions commis/app/android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application
android:label="commis"
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher">
<activity
android:name=".MainActivity"
android:exported="true"
android:launchMode="singleTop"
android:taskAffinity=""
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<!-- Specifies an Android theme to apply to this Activity as soon as
the Android process has started. This theme is visible to the user
while the Flutter UI initializes. After that, this theme continues
to determine the Window background behind the Flutter UI. -->
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme"
/>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data
android:name="flutterEmbedding"
android:value="2" />
</application>
<!-- Required to query activities that can process text, see:
https://developer.android.com/training/package-visibility and
https://developer.android.com/reference/android/content/Intent#ACTION_PROCESS_TEXT.

In particular, this is used by the Flutter engine in io.flutter.plugin.text.ProcessTextPlugin. -->
<queries>
<intent>
<action android:name="android.intent.action.PROCESS_TEXT"/>
<data android:mimeType="text/plain"/>
</intent>
</queries>
</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.example.commis

import io.flutter.embedding.android.FlutterActivity

class MainActivity : FlutterActivity()
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="?android:colorBackground" />

<!-- You can insert your own image assets here -->
<!-- <item>
<bitmap
android:gravity="center"
android:src="@mipmap/launch_image" />
</item> -->
</layer-list>
12 changes: 12 additions & 0 deletions commis/app/android/app/src/main/res/drawable/launch_background.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@android:color/white" />

<!-- You can insert your own image assets here -->
<!-- <item>
<bitmap
android:gravity="center"
android:src="@mipmap/launch_image" />
</item> -->
</layer-list>
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading