ABZ Frontend Code Style Regulations

website·Indexed 30 days ago

https://code-style-regulations.abzdev2.com

A comprehensive set of frontend development standards covering architectural boundaries, FSD (Feature-Sliced Design) hierarchy, typing requirements, state management, and security practices. It defines mandatory (MUST), recommended (SHOULD), and forbidden rules for HTTP requests, i18n, performance metrics, and design system implementation to ensure consistency and refactoring safety.

Tokens
64K
Snippets
251
Records
386
Agent score
50%

What's inside ABZ Frontend Style Guide

  1. Apply fundamental frontend security principles

    Frontend code executes in an uncontrolled environment (the browser), meaning any data, tokens, or state on the client can be read, modified, or spoofed. To mitigate risks such as data leaks and infrastructure compromise, developers must adhere to these core principles:

    1. Zero Trust in Client Data: The client application is never a trusted party.
    2. Treat All Incoming Data as Untrusted: Regardless of the source, data must be treated as untrusted. This includes:
      • User input
      • URLs and query parameters
      • Responses from external APIs (third-party services, public endpoints)
      • Client-side storage (localStorage, sessionStorage, IndexedDB)
      • postMessage events from other windows or frames
      • Cookies that lack the HttpOnly flag
    3. Client-side Validation is for UX, Not Security: Client-side validation improves user experience but does not protect the system. Any check affecting security or data integrity must be performed on the backend.
  2. Avoid common state management anti-patterns

    Avoid the following three bad practices to maintain a clean architecture:

    1. Storing Server State in Client Managers: Do not put API entities or loading flags in Redux/Zustand.
    2. Using Store as an Event Bus (Commands vs. Facts): Do not store 'commands' (e.g., shouldRedirectToDashboard). Instead, store 'facts' (e.g., isAuthorized) and let the UI decide the resulting action.
    3. Storing Derived State: Do not store values that can be calculated from other state (e.g., storing both items and total in a cart). Use selectors instead.
    // ❌ BAD: Storing a command
    state.shouldRedirectToDashboard = true;
    
    // ✅ GOOD: Storing a fact
    state.isAuthorized = true;
    
    // ❌ BAD: Storing derived state
    const useCartStore = create(() => ({ items: [], total: 0 }));
    
    // ✅ GOOD: Calculating derived state via selector
    export const selectCartTotal = (items: CartItem[]) =>
      items.reduce((sum, i) => sum + i.price * i.qty, 0);
  3. Determine when to migrate from MVP to full error handling rules

    Simplified error handling is no longer acceptable and should be replaced by full classification and unification when the following occur: growth in the number of user scenarios, introduction of complex forms/states (multi-step forms, drafts, auto-save), team growth requiring unified approaches, user-perceived UX inconsistency, or when transitioning from a prototype to a product where technical debt slows development.
  4. Understand the Design System goals and scope

    The Design System aims to ensure a consistent UI across all products and teams, enable rapid theming and rebranding without modifying individual components, allow reuse of UI solutions between web and native platforms, and minimize 'magic' values and visual discrepancies.

    Its scope includes:

    • Design tokens (colors, typography, spacing, radii, shadows)
    • UI component library and their variations
    • Icons and SVG usage rules
    • Documentation and verifiable rules
  5. Implement general error handling principles

    Error handling must be an integral part of the interface architecture, designed during development rather than added post-release. The goal is to ensure the UI handles errors predictably without crashing or leaking technical details.

    Mandatory Requirements (MUST):

    • Prevent Application Crashes: All errors must be caught and handled at the appropriate level.
    • Define UI Patterns: Every error type must have a predefined display pattern.
    • Normalize Error Formats: The UI must interact with a unified error model.
    • Use Result Type: Functions that can fail must return a Result<T, AppError> instead of using uncontrolled throw/catch blocks to make errors explicit from the API to the UI.

    Recommended Practices (SHOULD):

    • Log errors to monitoring systems (e.g., Sentry, LogRocket).
    • Group similar errors to avoid spamming the user with duplicate messages.

    Prohibited Actions (FORBIDDEN):

    • Displaying stack traces to the user.
    • Displaying raw messages directly from the back-end API (messages must be localized and adapted).
    • Revealing technical details such as internal variable names, file paths, or library versions.
  6. Frontend performance goals and objectives

    Frontend optimization focuses on four primary goals to improve the subjective user experience:

    • Fast Loading: First meaningful content should appear without a perceived wait.
    • Smoothness: The interface must not lag, stutter, or freeze during interaction.
    • Stability: Content should not jump or shift during loading (preventing layout shift).
    • Predictability: The user should always understand the current state of the interface.
  7. Define and manage Server State

    Server State is a snapshot of data received from a server at a specific point in time. Unlike client state, server state can become stale, can be changed outside the client, and the client is not the source of truth. The Server State layer is responsible for the lifecycle of server data (fetch/refetch/retry), caching, request deduplication, data freshness control (staleTime/cacheTime), and UI synchronization.
  8. Define boundaries between Design System and Business Logic

    To maintain a clean architecture, responsibilities are split as follows:

    Design System Responsibility:

    • Visual style (colors, typography, spacing).
    • Accessibility and keyboard navigation.
    • Base states (default, hover, disabled, loading).

    Business Logic Responsibility:

    • Business logic and data handling.
    • Composition of components for specific user scenarios.
    • Integration with APIs and state management.
  9. Understand the Design Token Hierarchy

    Design tokens are atomic variables for UI parameters (colors, typography, spacing, radii, shadows). They are organized into a three-level hierarchy to ensure consistency and ease of theming:

    1. Core Tokens (Base): Raw values such as the base color palette, primitive sizes, and numeric values.
    2. Semantic Tokens: Values with business meaning that reference Core tokens (e.g., color.text.primary referencing a specific neutral gray). These are the primary tokens used in UI code.
    3. Component Tokens: Local tokens for specific components, used only when a component requires unique values not covered by semantic tokens.
    // 1. Core
    {
      "color": { "base": { "neutral": { "900": { "value": "#1b1b1b" } } } }
    }
    
    // 2. Semantic
    {
      "color": { "text": { "primary": { "value": "{color.base.neutral.900}" } } }
    }
    
    // 3. Component
    {
      "button": { "primary": { "bg": { "value": "{color.bg.brand}" } } }
    }
  10. Implement the Shared layer in FSD architecture

    The shared layer contains technical utilities, generic components, and API clients that are independent of business logic. It is the lowest layer in the hierarchy and must not depend on any other layers.

    Key Responsibilities:

    • UI-kit and atomic components
    • Generic hooks and utilities
    • API clients and CRUD operations (located in endpoints/)
    • Global configuration

    Constraints:

    • MUST: Contain only technical utilities, generic components, and CRUD operations.
    • FORBIDDEN: Business logic, domain state, and dependencies on other layers.
    // shared/api/client.ts
    import axios from 'axios';
    
    export const apiClient = axios.create({
      baseURL: process.env.NEXT_PUBLIC_API_URL,
      headers: { 'Content-Type': 'application/json' }
    });
    
    // shared/api/endpoints/article.api.ts
    import { apiClient } from '../client';
    import type { ArticleDTO } from '../dto/article.dto';
    
    export async function getArticle(slug: string): Promise<ArticleDTO> {
      const { data } = await apiClient.get<{ article: ArticleDTO }>(`/articles/${slug}`);
      return data.article;
    }
    
    // shared/ui/button/button.tsx
    export function Button({ children, variant, ...props }: Props) {
      return (
        <button className={styles[variant]} {...props}>
          {children}
        </button>
      );
    }
  11. Implement FSD Layered Architecture with Next.js

    The project follows Feature-Sliced Design (FSD) where the Next.js routing layer (at the project root) acts as the entry point, while the actual business logic and UI components are organized into layers within the src/ directory. Imports must only move downwards in the hierarchy, and every module must expose a Public API via an index.ts file.
    . 
    ├── app/ (or pages/) # Next.js routing (Project Root)
    └── src/              # FSD Layers
        ├── app/          # Layer 1: Initialization
        ├── pages/        # Layer 2: Page Components
        ├── widgets/       # Layer 3: Composition
        ├── features/     # Layer 4: Scenarios
        ├── entities/     # Layer 5: Domain
        └── shared/       # Layer 6: Infrastructure