# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Project Overview This is a Flutter application for phone number-based authentication. The app demonstrates a complete phone login flow with Firebase authentication, including phone number input, SMS verification, and authenticated user interfaces. ## Architecture & Structure The application follows a layered architecture with the following key components: - **Authentication**: Managed through Firebase Authentication with `firebase_auth` package. The `AuthState` class handles authentication state using Provider pattern. - **Navigation**: Implemented with `go_router` for declarative routing with authentication-aware redirects. - **State Management**: Uses `provider` package with `ChangeNotifierProvider` for global state management. - **UI Components**: Built with Flutter's Material Design widgets and enhanced with specialized packages: - `intl_phone_field` for international phone number input - `pinput` for PIN input fields on SMS verification ## Directory Structure ``` lib/ ├── main.dart # App entry point ├── app.dart # MaterialApp setup, theme, and routing ├── auth/ # Authentication-related screens and logic │ ├── auth_state.dart # Manages authentication state │ ├── phone_input_screen.dart │ └── sms_verification_screen.dart ├── home/ # Home screen │ └── home_screen.dart ├── profile/ # User profile screen │ └── profile_screen.dart ``` ## Key Dependencies - `firebase_core`: 4.3.0 - `firebase_auth`: 6.1.3 - `go_router`: ^17.0.1 - `provider`: ^6.1.5+1 - `intl_phone_field`: ^3.2.0 - `pinput`: ^6.0.1 ## Common Development Commands ```bash # Install dependencies flutter pub get # Run the application flutter run # Run tests flutter test # Analyze code flutter analyze # Format code flutter format lib/ # Run linter flutter analyze # Build for Android flutter build apk # Build for iOS flutter build ios ``` ## Flutter Development Best Practices (Based on rules.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. ### Code Style & Architecture - **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 `go_router`. See the navigation guide for a detailed example using `go_router`. ### Code Quality Standards - **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:** Functions should be short and with a single purpose (strive for less than 20 lines). ### Dart Best Practices - **Effective Dart:** Follow the official Effective Dart guidelines (https://dart.dev/effective-dart) - **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. - **Async/Await:** Ensure proper use of `async`/`await` for asynchronous operations with robust error handling. - Use `Future`s, `async`, and `await` for asynchronous operations. - Use `Stream`s for sequences of asynchronous events. - **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. ### Application Architecture - **Separation of Concerns:** Aim for separation of concerns similar to MVC/MVVM, with defined Model, View, and ViewModel/Controller roles. - **Logical Layers:** Organize the project into logical layers: - Presentation (widgets, screens) - Domain (business logic classes) - Data (model classes, API clients) - Core (shared classes, utilities, and extension types) - **Feature-based Organization:** For larger projects, organize code by feature, where each feature has its own presentation, domain, and data subfolders. This improves navigability and scalability. ### State Management - **Built-in Solutions:** Prefer Flutter's built-in state management solutions. Do not use a third-party package unless explicitly requested. - **Streams:** Use `Streams` and `StreamBuilder` for handling a sequence of asynchronous events. - **Futures:** Use `Futures` and `FutureBuilder` for handling a single asynchronous operation that will complete in the future. - **ValueNotifier:** Use `ValueNotifier` with `ValueListenableBuilder` for simple, local state that involves a single value. - **ChangeNotifier:** For state that is more complex or shared across multiple widgets, use `ChangeNotifier`. - **ListenableBuilder:** Use `ListenableBuilder` to listen to changes from a `ChangeNotifier` or other `Listenable`. - **MVVM:** When a more robust solution is needed, structure the app using the Model-View-ViewModel (MVVM) pattern. - **Dependency Injection:** Use simple manual constructor dependency injection to make a class's dependencies explicit in its API, and to manage dependencies between different layers of the application. - **Provider:** If a dependency injection solution beyond manual constructor injection is explicitly requested, `provider` can be used to make services, repositories, or complex state objects available to the UI layer without tight coupling. ### Lint Rules Include the package in the `analysis_options.yaml` file. Use the following analysis_options.yaml file as a starting point: ```yaml include: package:flutter_lints/flutter.yaml linter: rules: # Add additional lint rules here: # avoid_print: false # prefer_single_quotes: true ``` ### Testing - **Running Tests:** To run tests, use the `run_tests` tool if it is available, otherwise use `flutter test`. - **Unit Tests:** Use `package:test` for unit tests. - **Widget Tests:** Use `package:flutter_test` for widget tests. - **Integration Tests:** Use `package:integration_test` for integration tests. - **Assertions:** Prefer using `package:checks` for more expressive and readable assertions over the default `matchers`. #### Testing Best practices - **Convention:** Follow the Arrange-Act-Assert (or Given-When-Then) pattern. - **Unit Tests:** Write unit tests for domain logic, data layer, and state management. - **Widget Tests:** Write widget tests for UI components. - **Integration Tests:** For broader application validation, use integration tests to verify end-to-end user flows. - **integration_test package:** Use the `integration_test` package from the Flutter SDK for integration tests. Add it as a `dev_dependency` in `pubspec.yaml` by specifying `sdk: flutter`. - **Mocks:** Prefer fakes or stubs over mocks. If mocks are absolutely necessary, use `mockito` or `mocktail` to create mocks for dependencies. While code generation is common for state management (e.g., with `freezed`), try to avoid it for mocks. - **Coverage:** Aim for high test coverage. ### Visual Design & Theming - **UI Design:** Build beautiful and intuitive user interfaces that follow modern design guidelines. - **Responsiveness:** Ensure the app is mobile responsive and adapts to different screen sizes, working perfectly on mobile and web. - **Navigation:** If there are multiple pages for the user to interact with, provide an intuitive and easy navigation bar or controls. - **Typography:** Stress and emphasize font sizes to ease understanding, e.g., hero text, section headlines, list headlines, keywords in paragraphs. - **Theming:** Implement support for both light and dark themes, ideal for a user-facing theme toggle (`ThemeMode.light`, `ThemeMode.dark`, `ThemeMode.system`). ### Code Generation - **Build Runner:** If the project uses code generation, ensure that `build_runner` is listed as a dev dependency in `pubspec.yaml`. - **Code Generation Tasks:** Use `build_runner` for all code generation tasks, such as for `json_serializable`. - **Running Build Runner:** After modifying files that require code generation, run the build command: ```shell dart run build_runner build --delete-conflicting-outputs ``` ## Important Notes - Authentication flow is implemented using Firebase phone authentication - The router includes redirect logic based on authentication state - UI adapts based on login status (logged in/out views) - Phone input includes international country codes - SMS verification screen accepts 6-digit PIN codes