If something doesn't seem to work out and you get stuck in some sort of loop doing it over and over again, ponder for a while and suggest changes to AGENT.md
Remember to double check the compatible dependencies before suggesting a change
This section outlines the established coding conventions and practices to maintain consistency and quality across the project.
- NativeWind: The project uses NativeWind for styling. This allows using Tailwind CSS utility classes directly on components via the
classNameprop. - Utility-First Approach: We follow a utility-first approach. Instead of writing custom CSS, we build complex components from a constrained set of primitive utilities.
- No
StyleSheet.create: We avoid usingStyleSheet.create. All styling should be done usingclassName. - Merging and Conditional Classes:
clsxandtailwind-mergeare available for conditionally applying and merging class names.class-variance-authoritycan be used for creating variants of components.
- ESLint: The project uses a comprehensive ESLint setup to enforce code quality and consistency. The configuration (
.eslintrc.js) extends fromeslint:recommended,plugin:react/recommended, andplugin:@typescript-eslint/recommended. - Plugins: It utilizes plugins for React (
react), React Hooks (react-hooks), React Native (react-native), and TypeScript (@typescript-eslint). - Key Rules:
react-hooks/rules-of-hooks: Enforces the rules of hooks (error).react-hooks/exhaustive-deps: Warns about missing dependencies inuseEffectanduseCallback(warn).react-native/no-inline-styles: Discourages inline styles (warn).@typescript-eslint/no-unused-vars: Warns about unused variables (warn).
- Prettier: Prettier is used for automated code formatting to ensure a consistent code style across the entire codebase. The project includes a Prettier configuration file to define specific formatting rules.
- React Context: The project utilizes React Context for managing global state, specifically for authentication through
AuthContext(src/context/AuthContext.tsx). AuthContext: This context is the single source of truth for authentication and user data. It handles:- User State: Storing the current user object and
isSignedInstatus. - Session Management: Providing
signIn,signUp, andsignOutmethods. - Token Persistence: Automatically storing and retrieving the authentication token using
expo-secure-storeon native andlocalStorageon web. - Data Fetching: Initializing the user's session by fetching the user object from the API if a valid token is found.
- User State: Storing the current user object and
- Component-Level State: For component-specific state, React Hooks (
useState) are used.
- Expo Router: The project uses Expo Router for file-system based routing. This allows for creating new routes by simply adding files to the
src/appdirectory. - Stack Navigator: The root layout (
src/app/_layout.tsx) uses aStacknavigator fromexpo-routerto manage the navigation hierarchy. - Protected Routes: Authentication-aware routing is implemented using
Stack.Protectedto separate routes accessible only to authenticated or unauthenticated users.
- Centralized API Client: A centralized
ApiClientclass (src/lib/api/client.ts) is used for all API communication. This client handles requests, headers, and errors. It's instantiated with a base URL from@/lib/config. - Modular API Structure: The API is organized into modules. The main example is the
authApimodule (src/lib/api/auth.ts).authApiModule: This module encapsulates all authentication-related endpoints:login(username, password): Authenticates a user usingapplication/x-www-form-urlencoded.register(newUser): Creates a new user.logout(token): Logs out the user, requires anAuthorizationheader.getCurrentUser(token): Fetches the current user's data, requires anAuthorizationheader.
- Zod Validation: The client and API modules use
zodfor request and response schema validation (e.g.,AuthResponseSchema,UserSchema). This ensures type safety. If validation fails, anApiErroris thrown. - Error Handling: The
ApiClientincludes robust error handling:- Distinguishes between network errors and HTTP error responses.
- Parses various error formats from the server, including FastAPI validation errors.
- Throws a custom
ApiErrorwith a user-friendly message and anApiErrorCode.
- Authorization: For protected endpoints, the API modules are responsible for adding the
Authorization: Bearer ${token}header to requests. - Convenience Methods: The base
apiClientprovides convenience methods (get,post, etc.) that are used by the API modules.
- Frameworks: The project uses Jest as the test runner and
@testing-library/react-nativefor rendering components and hooks in a test environment. - Test Structure: Test files are located in the
src/__tests__directory, with a folder structure that mirrors thesrcdirectory. Test files use*.tsxextensions. - Mocking: Dependencies such as API services (
@/lib/api/auth) and native modules (expo-secure-store) are mocked usingjest.mockto isolate tests and control their behavior. - Hook and Context Testing: Hooks and Contexts are tested using the
renderHookutility from@testing-library/react-native, often in conjunction with a wrapper component (likeAuthProvider). - Component Testing: Components are tested using
renderto mount them andfireEventto simulate user interactions. Assertions are made about the component's output usingwaitForto handle asynchronous updates. - Asynchronous Code: Asynchronous operations are tested using
async/await, and thewaitForandactutilities are used to manage state updates and side effects.
By adhering to these practices, we can ensure a high-quality, consistent, and maintainable codebase. Please suggest changes to these practices, if they change in the codebase or new practices are made.