Docs For AI
Architecture

Architecture Overview

Frontend architecture patterns - component design, design patterns, micro-frontends, and monorepos

Frontend Architecture

Good architecture enables teams to build scalable, maintainable applications. This section covers patterns and practices for structuring frontend projects.

Core Topics

Architecture Principles

Separation of Concerns

Application Layers
├── Presentation Layer
│   ├── UI Components
│   ├── Styling
│   └── User Interactions
├── Business Logic Layer
│   ├── State Management
│   ├── Data Transformation
│   └── Validation
└── Data Layer
    ├── API Communication
    ├── Caching
    └── Persistence

Key Principles

PrincipleDescription
Single ResponsibilityEach module/component has one job
Open/ClosedOpen for extension, closed for modification
Dependency InversionDepend on abstractions, not implementations
DRYDon't Repeat Yourself (but don't over-abstract)
KISSKeep It Simple, Stupid
YAGNIYou Aren't Gonna Need It

Project Structure

src/
├── features/
│   ├── auth/
│   │   ├── components/
│   │   ├── hooks/
│   │   ├── api/
│   │   ├── store/
│   │   ├── types/
│   │   └── index.ts
│   ├── dashboard/
│   └── settings/
├── shared/
│   ├── components/
│   ├── hooks/
│   ├── utils/
│   └── types/
├── lib/
│   ├── api-client.ts
│   └── storage.ts
├── app/
│   ├── routes.tsx
│   ├── providers.tsx
│   └── App.tsx
└── main.tsx

Layer-Based Structure

src/
├── components/
│   ├── common/
│   ├── forms/
│   └── layout/
├── pages/
├── hooks/
├── services/
├── store/
├── utils/
├── types/
└── main.tsx

Dependency Management

Import Rules

// Good - explicit imports, clear dependencies
import { Button } from '@/shared/components';
import { useAuth } from '@/features/auth';
import { formatDate } from '@/shared/utils';

// Feature module index.ts - explicit exports
export { LoginForm } from './components/LoginForm';
export { useAuth } from './hooks/useAuth';
export type { User } from './types';

// Avoid circular dependencies
// features/auth should not import from features/dashboard
// if dashboard imports from auth

Dependency Direction

Allowed Dependencies:
├── Pages → Features → Shared
├── Features → Shared
├── Features → Lib
└── Shared → Lib

Forbidden:
├── Shared → Features
├── Features → Pages
└── Lib → anything above

State Architecture

State Categorization

TypeScopeExamplesSolution
UI StateComponentOpen/close, focususeState, useReducer
Feature StateFeatureForm data, filtersFeature store
Global StateApp-wideUser, themeGlobal store
Server StateRemoteAPI dataReact Query, SWR
URL StateNavigationPage, paramsRouter

State Colocation

// Start with local state
function SearchBox() {
  const [query, setQuery] = useState('');
  return <input value={query} onChange={e => setQuery(e.target.value)} />;
}

// Lift when needed by siblings
function SearchFeature() {
  const [query, setQuery] = useState('');
  return (
    <>
      <SearchBox query={query} onQueryChange={setQuery} />
      <SearchResults query={query} />
    </>
  );
}

// Use global store only when truly global
// (accessed by unrelated features)

Communication Patterns

Component Communication

// Props (parent → child)
<Child data={data} onAction={handleAction} />

// Callback (child → parent)
onAction={(result) => setParentState(result)}

// Context (ancestor → descendants)
<ThemeContext.Provider value={theme}>
  <DeepChild /> {/* Can access theme */}
</ThemeContext.Provider>

// Events (siblings, unrelated)
const eventBus = new EventEmitter();
eventBus.emit('notification', { message: 'Hello' });
eventBus.on('notification', handleNotification);

Error Boundaries

// Error boundary for graceful degradation
class ErrorBoundary extends Component<Props, State> {
  state = { hasError: false, error: null };

  static getDerivedStateFromError(error: Error) {
    return { hasError: true, error };
  }

  componentDidCatch(error: Error, info: ErrorInfo) {
    logErrorToService(error, info);
  }

  render() {
    if (this.state.hasError) {
      return <this.props.fallback error={this.state.error} />;
    }
    return this.props.children;
  }
}

// Usage
<ErrorBoundary fallback={ErrorPage}>
  <FeatureComponent />
</ErrorBoundary>

Architecture Decision Records

Document architectural decisions for team alignment.

# ADR-001: State Management Solution

## Status
Accepted

## Context
Need to manage complex state across the application.

## Decision
Use Zustand for global state and React Query for server state.

## Consequences
### Positive
- Simple API, small bundle size
- Clear separation of client/server state

### Negative
- Less structure than Redux
- Team needs to learn new library

Best Practices

Architecture Guidelines

  1. Start simple, evolve as needed
  2. Colocate code that changes together
  3. Define clear module boundaries
  4. Establish dependency rules early
  5. Document architectural decisions
  6. Review architecture in code reviews
  7. Refactor continuously, not in big bangs

On this page