# Hook Conventions

Patterns and conventions for building hooks in the `officerdev` workspace. These complement the root `CLAUDE.md` and `APP_CONVENTIONS.md`.

## File Ordering

Within a hook file, order sections as:

1. Imports (types → external → workspace → relative)
2. Constants
3. Main export (the hook)
4. `export type UseXType = ReturnType<typeof useX>`
5. Types (params types, internal types)
6. Helper functions

```ts
import type { ChatMessage } from '../apps/Chat/types';
import { useState, useRef } from 'react';
import { useClient } from 'hooks/useClient';

const DEBOUNCE_MS = 1000;

export function useChat(sessionId?: string, model?: string | null) {
  // ...
  return { messages, sendPrompt, stopGeneration };
}

export type UseChatType = ReturnType<typeof useChat>;

// ── Types ──

type InternalMessage = {
  id: string;
  timestamp: number;
};

// ── Helpers ──

const formatMessage = (msg: InternalMessage) => { /* ... */ };
```

## Simple Hooks — Single File

Hooks that are self-contained (one function, a few types, maybe some helpers) stay as a single file in `src/hooks/`.

```
hooks/
├── useFilesAPI.ts
├── useChat.ts
└── index.ts
```

The file is named after the hook: `useFilesAPI.ts` exports `useFilesAPI`.

## Complex Hooks — Directory

When a hook accumulates supporting code (constants, components, config), promote it to a directory:

```
hooks/
├── useFileViewerPanels/
│   ├── index.ts                    # Barrel re-export
│   ├── useFileViewerPanels.tsx     # The hook
│   ├── layouts.ts                  # Static data / constants
│   └── Providers.tsx               # Helper components
└── index.ts
```

Rules:
- `index.ts` is a barrel — only re-exports the hook and its `ReturnType`
- The hook file is named `useX.ts(x)` matching the directory name
- Supporting files are named by what they contain: `layouts.ts`, `Providers.tsx`
- Component files are **PascalCased** (e.g. `Providers.tsx`), everything else is **kebab-case** or **camelCase**
- The parent `hooks/index.ts` barrel doesn't change when promoting — `export * from './useFileViewerPanels'` resolves to the directory's `index.ts`

## When to Promote

Promote a single-file hook to a directory when:
- It has **3+ non-trivial constants** that deserve their own file (layouts, configs, mappings)
- It contains **React components** used as helpers (providers, wrappers)
- The file exceeds **~200 lines** and has clear separable concerns

Don't promote for:
- A couple of small types or helper functions — keep them in the same file
- Hooks that are just API wrappers (like `useFilesAPI`)

## Return Type Export

Always export a `ReturnType` alias immediately after the hook. This lets consumers type props without importing the hook itself:

```ts
export function useFilesAPI(root: string = 'home') {
  // ...
}

export type UseFilesAPIType = ReturnType<typeof useFilesAPI>;
```

```tsx
// Consumer uses the type without calling the hook
import type { UseFilesAPIType } from 'officerdev';

type ToolbarProps = {
  files: UseFilesAPIType;
};
```

## Barrel Exports

The root `hooks/index.ts` re-exports everything. Each entry is a single `export *` line:

```ts
export * from './appRegistry';
export * from './useFilesAPI';
export * from './useFileViewerPanels';
export * from './useChat';
```

When adding a new hook, add one line here. Order alphabetically.
