Frontend Engineering Conventions (Next.js App Router)
1. General Principles
-
MUST USE TYPESCRIPT!
-
NEVER DUPLICATE CODE! Always check if there is already a solution to the problem before writing your own code. If you find a solution, use it instead of reinventing the wheel. You MUST use existing code whenever possible.
-
SINGLE RESPONSIBILITY PRINCIPLE: Each module or function MUST have a single responsibility. This makes the code easier to understand, test, and maintain.
-
FOLLOW THE PROJECT ARCHITECTURE. You MUST make sure to split code into logical modules or features (e.g., domain-driven design concepts) and follow the layered architecture pattern as currently defined in the project.
-
MODULAR CODE. Code MUST be modular and decoupled to achieve better maintainability and reusability.
2. Best practices
- Use ONLY FUNCTIONAL COMPONENTS for React!
- PRIMARILY Use SERVER COMPONENTS.
- Using client components is penalized and must be considered only when absolutely necessary. If the implementation can be done with server components, do it with server components.
- Split React components into PRESENTATIONAL and CONTAINER components.
- Container components should be used for data fetching and business logic.
- Presentational components MUST NOT CONTAIN ANY STATE! Any component that has JSX is considered a PRESENTATIONAL component. This is extra important!! PRESENTATIONAL COMPONENTS MUST NOT CONTAIN ANY STATE!
- Maximally reuse PRESENTATIONAL components. If you need to use a component more than once, extract it into a PRESENTATIONAL component.
- Use variants for PRESENTATIONAL components. Variants are used to change the look and feel of a component based on different states or conditions.
- Use LAYOUT components for things that determine positioning and structure of the page. These are special components that are used to wrap PRESENTATIONAL components. They are also used to wrap other LAYOUT components. They can only contain positioning and no other visual elements.
- You MUST COMOPLY WITH THESE RULES!!!
2.1 Server-First Architecture Requirements
- DO NOT OVERUSE CLIENT COMPONENTS! Client components should only be used for absolute necessity (debounced search, form submissions, user interactions).
- USE URL PARAMETERS FOR ALL STATE MANAGEMENT instead of client-side state.
- Server components must handle all data fetching and URL parameter parsing.
- All filters, search, pagination, and sorting MUST use URL parameters.
- URLs must be bookmarkable and shareable.
- Back/forward navigation must work correctly.
- NO client-side state for data management - everything goes through URL params.
2.2 Presentational Component Strict Rules
- Each presentational component MUST be in its own separate file.
- Presentational components must have ZERO STATE WHATSOEVER.
- No event handlers in presentational components - they only display data.
- No props drilling - components receive only the data they need to display.
- Components must be pure functions of their props.
2.3 Code Reuse Philosophy
- MAXIMIZE CODE REUSE! Always look for existing patterns before creating new ones.
- If there are similar behaviors, extract them into shared components.
- Create shared components that can be used across different data types (invoices, transactions, etc.).
- Extract common UI patterns into reusable components.
- Components must look and feel the same across the application.
2.4 Design System Consistency
- Maintain visual consistency across all features.
- Use a streamlined design system approach.
- Components must have consistent styling, spacing, and behavior.
- Extract styling patterns into reusable component variants.
3. Next.js Best Practices
- You MUST comply with Next.js best practices. You MUST use Server Components, Server Actions, and Server Side Rendering (SSR) and Static Site Generation (SSG)
- You MUST make sure that the code is optimized for performance.
- Refer to Next.js documentation for more information.
3.1 URL-Driven Architecture
- Use URL search parameters for all application state (filters, search, pagination, sorting).
- Server components should read and parse URL parameters using
searchParams. - Use Next.js
Linkcomponents androuter.push()to update URL parameters. - Ensure all navigation preserves existing URL parameters when appropriate.
3.2 Data Fetching Patterns
- Server components should fetch data directly using services/repositories.
- Pass parsed URL parameters to service layer for filtering/sorting.
- Avoid unnecessary data fetching - only fetch what's needed.
- Use proper error boundaries and loading states.
3.3 Performance Optimization
- Minimize client-side JavaScript by maximizing server component usage.
- Use proper caching strategies for data fetching.
- Implement pagination to avoid loading large datasets.
- Use debounced search to prevent excessive API calls.