---
description: Fullstack Architecture
alwaysApply: false
---

# Fullstack Architecture

Architectural patterns for full-stack applications.

## Architectural Layers

```
Presentation → Application → Domain ← Infrastructure
```

- **Presentation**: Components, pages, state management, routing
- **Application**: Route handlers, request validation, auth, response formatting
- **Domain**: Business rules, models, use cases — pure functions, no external deps
- **Infrastructure**: Database, external APIs, file storage, caching

Dependencies point inward — domain has zero dependencies on outer layers.

## Server vs Client Components

```tsx
// Server Component (default) — direct DB access, no interactivity
export default async function UsersPage() {
  const users = await db.user.findMany();
  return <ul>{users.map(u => <li key={u.id}>{u.name}</li>)}</ul>;
}

// Client Component — interactivity, hooks, browser APIs
'use client';
export function UserForm({ onSubmit }: Props) {
  const [name, setName] = useState('');
  return <form onSubmit={...}><input value={name} onChange={e => setName(e.target.value)} /></form>;
}
```

**Composition**: Server component fetches data, passes to client component for interactivity.

## Server Actions

```tsx
'use server';
export async function createUser(formData: FormData) {
  await db.user.create({ data: { name: formData.get('name') as string } });
  revalidatePath('/users');
}
// Usage: <form action={createUser}>...</form>
```

## State Synchronization

- **Optimistic updates**: `useOptimistic` to update UI before server confirms
- **Cache invalidation**: `revalidatePath` / `revalidateTag` after mutations

## Error Handling Across Stack

```tsx
// Server: structured errors with status codes
if (!user) {
  return NextResponse.json(
    { error: { code: 'NOT_FOUND', message: 'User not found' } },
    { status: 404 }
  );
}
// Client: handle loading, error, and success states
const { data, error, isLoading } = useQuery(['user', id], fetchUser);
if (isLoading) return <Skeleton />;
if (error) return <ErrorMessage error={error} />;
return <UserCard user={data} />;
```

## Anti-Patterns

- Putting business logic in route handlers instead of the domain layer
- Using client components when server components suffice (unnecessary JS shipped)
- Mutating server state without cache invalidation
