Create Custom Hook
SkillDev toolsCreate a reusable React hook (useX). Triggers "create hook", "new hook", "custom hook", a useX-style name, or extracting logic out of a component.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the Create Custom Hook skill
What this skill tells your AI
The instructions your AI receives, as published by darkroomengineering/cc-settings in skills/hook/SKILL.md and read by ahel’s review.
Create a custom React hook following Darkroom conventions. The hook itself is stack-agnostic — what differs between satus and novus is the path alias.
Step 1 — Detect stack
Read package.json:
dependencies.next→ satus / Next.js (path alias@/, hooks require a'use client'boundary)dependencies["react-router"]→ novus / React Router (path alias~/, components isomorphic)
Step 2 — Choose location
| Stack | Hook path |
|---|---|
| satus | lib/hooks/<name>.ts |
| novus | hooks/<name>.ts (novus puts hooks/ at the project root) |
Confirm by checking the existing lib/hooks/ or hooks/ directory structure if either pattern is unclear from package.json alone.
Step 3 — Emit template
satus / Next.js
// lib/hooks/<name>.ts
'use client'
// Client Components can prerender on the server. Read browser APIs in effects
// or event handlers, with the same initial state on the server and browser.
import { useState, useEffect } from 'react'
interface Use<Name>Options {
// Hook configuration options
}
interface Use<Name>Return {
// Return type definition
}
export function use<Name>(options?: Use<Name>Options): Use<Name>Return {
// Implementation
return {
// Return values
}
}
novus / React Router
// hooks/<name>.ts
// No 'use client' — RR components are isomorphic; the hook runs wherever
// it's called from. Read browser APIs in effects or event handlers, with the
// same initial state on the server and browser.
import { useState, useEffect } from 'react'
interface Use<Name>Options {
// Hook configuration options
}
interface Use<Name>Return {
// Return type definition
}
export function use<Name>(options?: Use<Name>Options): Use<Name>Return {
// Implementation
return {
// Return values
}
}
Conventions (both stacks)
- Type everything — options interface, return interface.
- Named export —
export function useX, not default. - Prefix with
use— React hook naming convention. - No memoization — React Compiler handles it automatically.
- Hydration-safe state — both stacks can render on the server. Use a
deterministic initial value for the server render and first browser render;
'use client'does not disable prerendering. Atypeof windowbranch in a lazy state initializer can still produce different markup and a hydration mismatch. ReadlocalStoragein an effect, and finish that read before enabling an effect that persists state, so initial defaults cannot overwrite stored values.
Stack-specific
| satus | novus | |
|---|---|---|
| Directive | 'use client' (hooks live in client boundary) | None (isomorphic) |
| Browser APIs | SSR-safe initial state; effects or event handlers | SSR-safe initial state; effects or event handlers |
| Path alias | @/ | ~/ |
Before you start
If this hook uses an external library, fetch docs first:
- Use Context7 MCP (
mcp__context7__resolve-library-id→get-library-docs) in Claude or when the user configured it in standalone Codex. Otherwise use official docs through native browsing or inspect the pinned local package. cc-settings does not auto-run unpinned registry MCP packages in Codex. - Run
bun info <package>to check the latest version.
Consider Using Hamo
For common use cases, prefer hamo hooks (fetch hamo docs via Context7 first):
import { useWindowSize, useRect, useIntersectionObserver } from 'hamo'
Only create custom hooks when hamo doesn't cover the use case.
Example
User: "create a useLocalStorage hook" (in satus repo)
→ Creates lib/hooks/use-local-storage.ts with 'use client', deterministic initial state, effect-based storage read before writes
User: "create a useLocalStorage hook" (in novus repo)
→ Creates hooks/use-local-storage.ts, no directive, deterministic initial state, effect-based storage read before writes
Arguments
$ARGUMENTS— Hook name (e.g., "useAuth", "useLocalStorage")
Signals
- GitHub stars
- 45
- Forks
- 3
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
hook- Source
- github.com/darkroomengineering/cc-settings