This file provides context and guidelines for GitHub Copilot to generate better code suggestions for the Cambridge Beer Festival app.
This is a Flutter application for browsing drinks (beers, ciders, meads, wines, etc.) at the Cambridge Beer Festival. The app supports Android, iOS, and Web platforms.
- Framework: Flutter (requires Dart SDK >=3.2.0 <4.0.0)
- Language: Dart (SDK >=3.2.0 <4.0.0)
- State Management: Provider (
providerpackage) - Storage: SharedPreferences for local favorites and ratings
- HTTP Client:
httppackage for API calls - UI: Material Design 3 with system theme support
lib/
├── main.dart # App entry point and navigation
├── models/ # Data models (Drink, Product, Producer, Festival)
├── providers/ # State management (BeerProvider)
├── screens/ # UI screens (DrinksScreen, DrinkDetailScreen, etc.)
├── services/ # API and storage services
└── widgets/ # Reusable UI components (DrinkCard, etc.)
- Use single quotes for strings (
'text'not"text") - Prefer const constructors wherever possible
- Prefer final for local variables and fields
- Use camelCase for variable and function names
- Use PascalCase for class names
- Always use widget keys in constructors (
{super.key}) - Sort child properties last in widget trees
- Use
ChangeNotifierwithProviderfor state management - Prefer
constwidgets to improve performance - Use
context.read<T>()for one-time reads - Use
context.watch<T>()for reactive rebuilds - Always dispose of resources (HTTP clients, controllers) in
dispose()
- Screens:
*_screen.dartwith*Screenclass names - Widgets: Descriptive names like
drink_card.dart - Services:
*_service.dartwith*Serviceclass names - Providers:
*_provider.dartwith*Providerclass names - Models: Named after the entity they represent
Each directory contains a barrel file (e.g., models.dart, services.dart) that exports all files in that directory. When adding new files, update the corresponding barrel file.
- Festival: Represents a beer festival with id, name, and data URL
- Producer: Represents a brewery/cidery with location and products
- Product: Represents a beverage with ABV, style, category, dispense method, etc.
- Drink: Combines Product with Producer for display, includes favorites/ratings
Be robust when parsing JSON from the API:
- ABV can be
String,int, ordouble - Allergens can be
int,bool, ornum - Year founded can be
intorString - Handle null values gracefully with
?.and??
- Tests are in the
test/directory - Use
flutter_testfor widget and unit tests - Use
mockitofor mocking services in tests - Run tests with:
flutter test
- Test files:
*_test.dart - Test groups: Describe the class/feature being tested
- Individual tests: Describe the expected behavior
# Get dependencies
flutter pub get
# Analyze code
flutter analyze
# Run tests
flutter test
# Run app (development)
flutter run
# Build for web (GitHub Pages deployment)
flutter build web --release --base-href "/cambridge-beer-festival-app/"
# Build for web (local testing or root-path deployment)
flutter build web --release --base-href "/"
# Build for Android
flutter build apk
# Build for iOS
flutter build iosThe app uses a Cloudflare Worker proxy to access Cambridge Beer Festival data:
- Base URL:
https://data.cambeerfestival.app - Endpoints:
/{festivalId}/{category}.json(e.g.,/cbf2025/beer.json) - Categories:
beer,cider,perry,mead,wine,international-beer,low-no
Full API documentation is available in the docs/api/ directory:
- docs/api/README.md - Overview and quick reference
- docs/api/data-api-reference.md - Complete API reference
- docs/api/beer-list-schema.json - JSON Schema for beverage data
- docs/api/festival-registry-schema.json - JSON Schema for festival configuration
The repository includes JSON schemas that define the expected structure of API responses:
- Beer List Schema (
beer-list-schema.json): Validates beverage data with producers and products - Festival Registry Schema (
festival-registry-schema.json): Validates festival configuration
These schemas can be used for:
- Validating test fixtures
- Understanding the expected API structure
- CI validation of festival configuration changes
- Wrap API calls in try-catch blocks
- Store error messages in provider state
- Display user-friendly error messages in UI
- Provide retry functionality for failed operations
- Persisted in SharedPreferences
- Scoped by festival ID
- Updated via Provider methods
Available categories come from the API data:
- beer, cider, perry, mead, wine, real cider, foreign beer
- Use Material 3 design system
- Support both light and dark themes
- Use amber/copper color scheme (seed:
0xFFD97706) - Include proper loading and error states
- Use icons from Material Icons library
The project uses Playwright for end-to-end testing of the Flutter web build.
# Build the web app first (use base-href "/" for local E2E testing)
flutter build web --release --base-href "/"
# Install dependencies (first time)
npm install
npx playwright install chromium # Only needed once per machine
# Start the http-server (in one terminal)
npm run serve:web
# Run tests (in another terminal)
npm run test:e2e
# Run with UI mode for debugging
npm run test:e2e:ui- Use single quotes for strings (same as Dart)
- Use async/await for asynchronous operations
- Use
test.describe()for grouping related tests - Use
expect()from@playwright/testfor assertions - Always wait for Flutter to be ready before interacting with the app
- Use helper function
waitForFlutterReady(page)in tests
IMPORTANT: Flutter web apps don't use traditional DOM elements!
- ❌ Can't use standard DOM selectors for Flutter widgets
- ❌ Can't directly interact with Flutter UI elements via Playwright
- ✅ Can verify page loads and Flutter canvas renders
- ✅ Can check network requests (API calls)
- ✅ Can test via accessibility features (ARIA labels from Semantics)
- ✅ Can monitor console errors and performance
- ✅ Can use visual regression testing (screenshots)
For full interaction testing (clicking buttons, typing in forms), use Flutter's built-in integration tests with the integration_test package instead. See Flutter integration testing documentation for more details.
import { test, expect } from '@playwright/test';
test.describe('Feature Name', () => {
test('should do something', async ({ page }) => {
await page.goto('/');
// Your test code here
});
});- Get dependencies:
flutter pub get - Run tests:
flutter test - Analyze code:
flutter analyze --no-fatal-infos - Start app:
flutter run(ormise run devwith mise dev environment manager)
- Review similar code to understand existing patterns
- Make minimal, focused changes (follow single responsibility principle)
- Run relevant tests:
flutter test test/path/to/test.dart - Check linting:
flutter analyze - Commit with descriptive message (one logical change per commit)
- Evaluate if functionality can be implemented with existing dependencies
- Check dependency size, maintenance status, and security on pub.dev
- Add to
pubspec.yamlwith specific version constraint - Run
flutter pub get - Import in code only where needed
- Run all tests:
flutter test - Run analyzer:
flutter analyze --no-fatal-infos - Build web (if making web changes):
flutter build web --release --base-href "/cambridge-beer-festival-app/" - Run E2E tests (if making web changes): See E2E Testing section
- API URLs: Use HTTPS only for production endpoints
- User Input: All user input is currently local (search, filters) - no server submission
- Storage: SharedPreferences used for favorites/ratings - contains no sensitive data
- Dependencies: Keep Flutter and package dependencies updated
- API Keys: Never commit API keys or secrets to the repository
- External Links: Use
url_launcherpackage for safe external link handling
The app has three deployment environments:
-
Production (
cambeerfestival.app)- Deployed on version tags (e.g.,
v2025.12.0) - Cloudflare Pages, branch
release - Workflow:
.github/workflows/release-web.yml
- Deployed on version tags (e.g.,
-
Staging (
staging.cambeerfestival.app)- Deployed automatically on push to
main - Cloudflare Pages, branch
main - Workflow:
.github/workflows/build-deploy.yml
- Deployed automatically on push to
-
PR Previews
- Unique URL per pull request
- Preview URL posted as comment on PR
- Workflow:
.github/workflows/build-deploy.yml
- Push to
main→ Staging deployment - Create tag → Production deployment
- Open PR → Preview deployment
Full documentation is available in the docs/ directory:
- Development Guide - Implementation details
- Testing Flutter Web - E2E testing approach
- CI/CD - Complete workflow documentation
- URL Routing - Path-based routing
- Cloudflare Pages Setup - Deployment setup
- Accessibility - Accessibility features and testing