# Component Architecture
This document defines the strict separation of concerns for all UI code in the website layer.
## The Three Layers
```
apps/website/
├── app/ ← App Layer (Pages & Layouts)
├── components/ ← Component Layer (App Components)
├── ui/ ← UI Layer (Pure Elements)
└── hooks/ ← Shared Logic
```
---
## 1. App Layer (`app/`)
**Purpose**: Pages, layouts, and routing configuration.
**Characteristics**:
- ✅ Only page.tsx, layout.tsx, route.tsx files
- ✅ Can import from `components/`, `ui/`, `hooks/`
- ✅ Can use Next.js features (redirect, cookies, headers)
- ✅ Can use Server Components
- ❌ **NO raw HTML with styling**
- ❌ **NO business logic**
- ❌ **NO state management**
**Allowed**:
```typescript
// app/dashboard/page.tsx
export default function DashboardPage() {
return (
);
}
```
**Forbidden**:
```typescript
// ❌ WRONG - Raw HTML in app/
export default function DashboardPage() {
return (
{/* ❌ No raw HTML with styling */}
Dashboard
{/* ❌ No inline handlers */}
);
}
```
---
## 2. Component Layer (`components/`)
**Purpose**: App-level components that may contain state and business logic.
**Characteristics**:
- ✅ Can be stateful (useState, useReducer)
- ✅ Can have side effects (useEffect)
- ✅ Can use hooks
- ✅ Can contain business logic
- ✅ Can import from `ui/`, `hooks/`
- ❌ **NO Next.js imports** (navigation, routing)
- ❌ **NO raw HTML with styling** (use ui/ elements)
**Allowed**:
```typescript
// components/DashboardHeader.tsx
export function DashboardHeader() {
const [isOpen, setIsOpen] = useState(false);
return (
{isOpen && }
);
}
```
**Forbidden**:
```typescript
// ❌ WRONG - Next.js imports in components/
import { useRouter } from 'next/navigation'; // ❌
export function DashboardHeader() {
const router = useRouter(); // ❌
// ...
}
```
---
## 3. UI Layer (`ui/`)
**Purpose**: Pure, reusable, stateless UI elements.
**Characteristics**:
- ✅ Stateless (no useState, useReducer)
- ✅ No side effects (no useEffect)
- ✅ Pure functions based on props
- ✅ Maximum reusability
- ✅ Framework-agnostic
- ❌ **NO state management**
- ❌ **NO Next.js imports**
- ❌ **NO business logic**
**Allowed**:
```typescript
// ui/Button.tsx
export function Button({ children, onClick, variant = 'primary' }) {
const className = variant === 'primary'
? 'bg-blue-500 text-white'
: 'bg-gray-200 text-black';
return (
);
}
// ui/Card.tsx
export function Card({ children, className = '' }) {
return (
{children}
);
}
```
**Forbidden**:
```typescript
// ❌ WRONG - State in UI element
export function Button({ children }) {
const [isLoading, setIsLoading] = useState(false); // ❌
return ;
}
// ❌ WRONG - Next.js imports
import { useRouter } from 'next/navigation'; // ❌
export function Link({ href, children }) {
const router = useRouter(); // ❌
// ...
}
```
---
## 4. Hooks Layer (`hooks/`)
**Purpose**: Shared stateful logic.
**Characteristics**:
- ✅ Can use all hooks
- ✅ Can contain business logic
- ✅ Can be used by components and pages
- ❌ **NO JSX**
- ❌ **NO UI rendering**
**Allowed**:
```typescript
// hooks/useDropdown.ts
export function useDropdown() {
const [isOpen, setIsOpen] = useState(false);
return {
isOpen,
open: () => setIsOpen(true),
close: () => setIsOpen(false),
toggle: () => setIsOpen(!isOpen),
};
}
```
---
## ESLint Enforcement
### 1. **No Raw HTML in `app/`**
```json
{
"files": ["app/**/*.tsx", "app/**/*.ts"],
"rules": {
"gridpilot-rules/no-raw-html-in-app": "error"
}
}
```
**Catches**:
- `