diet-guard/docs/flutter-rules-language.md
Krzysztof kuhy Rudnicki 17a2c62f26 Automate CLAUDE.md's structural rules, then cut it to 189 lines
CLAUDE.md was 1101 lines and loaded into every session in this repo. Three
passes, in order: automate what a gate can check, rewrite what is left as
instructions rather than rationale, extract what still does not fit.

Automated. Five prohibitions were enforced by nothing but a paragraph asking a
future reader not to do something; they are now repo_invariants_test.dart:

  - no app/linux/ (a GTK embedder target manages ~20fps at 4K)
  - dart:io only in *_io.dart seams and lib/desktop/ -- this one is why the
    test exists at all, since dart:io does not fail a web *compile*. It throws
    at runtime, so a bad import is a blank white window that the widget tests
    happily pass through.
  - no meal builder / repeat-last-meal / reward prompt
  - no image_picker, no CAMERA permission
  - wrapper port 8732 and the diet-guard-desktop Chrome profile, both pinned
    because IndexedDB is keyed by origin and moving either hides the whole
    local food log

Each guard was canary-tested by breaking the invariant and confirming the
suite goes red -- a guard that cannot fail is decoration.

Rules whose behaviour was already covered (budget epoch seeding, sync merge,
food bank) shrink to a pointer at the test that owns them.

Where a rule's entire value was its rationale ("the removal is the feature"),
the why moved into the name and reason string of the gate that now enforces
it, so it lives somewhere executable instead of somewhere quotable.

Extracted. The vendored flutter/flutter rules were 789 of the 1101 lines --
72% of the file, none of it about this repo. Split into five docs/ topic files
under the cap and linked. Verified content-complete: 664 non-blank lines in,
664 out, zero missing.

Python 692 tests / 100% coverage unchanged; Flutter 548 -> 555 (+7 new).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MK3HCZrM75sRHL1gL8usve
2026-08-15 16:39:57 +02:00

7.3 KiB

Language, style and architecture

Vendored Flutter/Dart AI rules. See CLAUDE.md.

Interaction Guidelines

  • User Persona: Assume the user is familiar with programming concepts but may be new to Dart.
  • Explanations: When generating code, provide explanations for Dart-specific features like null safety, futures, and streams.
  • Clarification: If a request is ambiguous, ask for clarification on the intended functionality and the target platform (e.g., command-line, web, server).
  • Dependencies: When suggesting new dependencies from pub.dev, explain their benefits.
  • Formatting: Use the dart_format tool to ensure consistent code formatting.
  • Fixes: Use the dart_fix tool to automatically fix many common errors, and to help code conform to configured analysis options.
  • Linting: Use the Dart linter with a recommended set of rules to catch common issues. Use the analyze_files tool to run the linter.

Project Structure

  • Standard Structure: Assumes a standard Flutter project structure with lib/main.dart as the primary application entry point.

Flutter style guide

  • SOLID Principles: Apply SOLID principles throughout the codebase.
  • Concise and Declarative: Write concise, modern, technical Dart code. Prefer functional and declarative patterns.
  • Composition over Inheritance: Favor composition for building complex widgets and logic.
  • Immutability: Prefer immutable data structures. Widgets (especially StatelessWidget) should be immutable.
  • State Management: Separate ephemeral state and app state. Use a state management solution for app state to handle the separation of concerns.
  • Widgets are for UI: Everything in Flutter's UI is a widget. Compose complex UIs from smaller, reusable widgets.
  • Navigation: Use a modern routing package like auto_route or go_router. For more guidelines around navigation, see the section on routing.

Package Management

  • Pub Tool: To manage packages, use the pub tool, if available.
  • External Packages: If a new feature requires an external package, use the pub_dev_search tool, if it is available. Otherwise, identify the most suitable and stable package from pub.dev.
  • Adding Dependencies: To add a regular dependency, use the pub tool, if it is available. Otherwise, run flutter pub add <package_name>.
  • Adding Dev Dependencies: To add a development dependency, use the pub tool, if it is available, with dev:<package name>. Otherwise, run flutter pub add dev:<package_name>.
  • Dependency Overrides: To add a dependency override, use the pub tool, if it is available, with override:<package name>:1.0.0. Otherwise, run flutter pub add override:<package_name>:1.0.0.
  • Removing Dependencies: To remove a dependency, use the pub tool, if it is available. Otherwise, run dart pub remove <package_name>.

Code Quality

  • Code structure: Adhere to maintainable code structure and separation of concerns (e.g., UI logic separate from business logic).
  • Naming conventions: Avoid abbreviations and use meaningful, consistent, descriptive names for variables, functions, and classes.
  • Conciseness: Write code that is as short as it can be while remaining clear.
  • Simplicity: Write straightforward code. Code that is clever or obscure is difficult to maintain.
  • Error Handling: Anticipate and handle potential errors. Don't let your code fail silently.
  • Styling:
    • Line length: Lines should be 80 characters or fewer.
    • Use PascalCase for classes, camelCase for members/variables/functions/enums, and snake_case for files.
  • Functions:
    • Keep functions short and with a single purpose. Strive for less than 20 lines.
  • Testing: Write code with testing in mind. Use the file, process, and platform packages, if appropriate, so you can inject in-memory and fake versions of the objects.
  • Logging: Use the logging package instead of print.

Dart Best Practices

  • Effective Dart: Follow the official Effective Dart guidelines (https://dart.dev/effective-dart)
  • Class Organization: Define related classes within the same library file. For large libraries, export smaller, private libraries from a single top-level library.
  • Library Organization: Group related libraries in the same folder.
  • API Documentation: Add documentation comments to all public APIs, including classes, constructors, methods, and top-level functions.
  • Comments: Write clear comments for complex or non-obvious code. Avoid over-commenting.
  • Trailing Comments: Don't add trailing comments.
  • Async/Await: Ensure proper use of async/await for asynchronous operations with robust error handling.
    • Use Futures, async, and await for asynchronous operations.
    • Use Streams for sequences of asynchronous events.
  • Null Safety: Write code that is soundly null-safe. Leverage Dart's null safety features. Avoid ! unless the value is guaranteed to be non-null.
  • Pattern Matching: Use pattern matching features where they simplify the code.
  • Records: Use records to return multiple types in situations where defining an entire class is cumbersome.
  • Switch Statements: Prefer using exhaustive switch statements or expressions, which don't require break statements.
  • Exception Handling: Use try-catch blocks for handling exceptions, and use exceptions appropriate for the type of exception. Use custom exceptions for situations specific to your code.
  • Arrow Functions: Use arrow syntax for simple one-line functions.

Flutter Best Practices

  • Immutability: Widgets (especially StatelessWidget) are immutable; when the UI needs to change, Flutter rebuilds the widget tree.
  • Composition: Prefer composing smaller widgets over extending existing ones. Use this to avoid deep widget nesting.
  • Private Widgets: Use small, private Widget classes instead of private helper methods that return a Widget.
  • Build Methods: Break down large build() methods into smaller, reusable private Widget classes.
  • List Performance: Use ListView.builder or SliverList for long lists to create lazy-loaded lists for performance.
  • Isolates: Use compute() to run expensive calculations in a separate isolate to avoid blocking the UI thread, such as JSON parsing.
  • Const Constructors: Use const constructors for widgets and in build() methods whenever possible to reduce rebuilds.
  • Build Method Performance: Avoid performing expensive operations, like network calls or complex computations, directly within build() methods.

API Design Principles

When building reusable APIs, such as a library, follow these principles.

  • Consider the User: Design APIs from the perspective of the person who will be using them. The API should be intuitive and easy to use correctly.
  • Documentation is Essential: Good documentation is a part of good API design. It should be clear, concise, and provide examples.