.claude/skills/recollect-mutation-hook-refactoring/SKILL.md
recollect-mutation-hook-refactoring
npx skillsauth add timelessco/recollect recollect-mutation-hook-refactoringInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Handles mutation hook template refactoring and file renaming after API caller migration. For API caller migration itself (getApi and postApi patterns with Zod types), use the recollect-caller-migration skill.
Migrating API callers? Use the
recollect-caller-migrationskill instead. It covers the 4-layer pattern: constant URL update, hook rewrite withgetApi/postApi+ Zod types, consumer double-unwrap removal, and dead code cleanup. This skill handles what comes AFTER — template refactoring and file renaming.
Scope: Mutation hooks, legacy helpers, legacy types, and file cleanup ONLY. No API route creation (the recollect-api-migrator agent handles that). No API caller migration (the recollect-caller-migration skill handles that).
Execute these steps in order for each route being cleaned up. Each step prevents a specific class of dead code or broken references.
Import types from the v2 route file instead of apiTypes.ts. Point postApi to the v2 URL.
// Before
import { type LegacyPayload } from "@/types/apiTypes";
postApi<LegacyResponse>("/api/old/path", payload);
// After
import {
type EntityPayload,
type EntityResponse,
} from "@/app/api/v2/domain/endpoint/route";
postApi<EntityResponse>("/api/v2/domain/endpoint", payload);
If the v2 route uses a different payload/response shape, update the hook's optimistic updater and cache structure to match.
Search for every file importing the old hook:
ast-grep --lang tsx -p 'useOldHookName' src/ # Replace useOldHookName with the actual hook name
Update each site:
Open src/async/supabaseCrudHelpers/index.ts and remove the legacy function. Remove any imports that become unused.
This prevents dead code from accumulating in the crud helpers barrel.
Open src/types/apiTypes.ts and remove the legacy payload/response type. Types now live in the v2 route's schema.ts.
This ensures a single source of truth for types.
Use trash (never rm) to remove:
trash src/pages/api/{entity}/{endpoint}.ts # Old Pages Router route
trash src/async/mutationHooks/{entity}/use{OldHook}.ts # Old mutation hook (if separate)
Run both checks — they catch different classes of issues:
pnpm lint:types # Catches broken imports, type mismatches
pnpm lint:knip # Catches orphaned exports, unused code
Fix any issues before marking the route as complete.
| User says | Load this |
| -------------------------------------------------- | ---------------------------------------------------------------------------- |
| "API caller migration" / "getApi pattern" / "postApi pattern" / "caller migration" | Use recollect-caller-migration skill |
| "update hook for [route]" / "wire up v2 [route]" | Execute workflow above |
| "mutation hook template" / "how to structure hook" | references/mutation-hook-template.ts |
| "where is [helper/type/constant]" | references/codebase-patterns.md |
| "cache structure" / "query keys" | references/codebase-patterns.md |
When updating hooks, preserve these error handling patterns from the v2 routes:
Duplicate detection (23505): The v2 route returns { data: null, error: "Duplicate name" } with status 409. Hooks should handle this in onError or show a toast.
Authorization (403): The v2 route returns { data: null, error: "User is not the owner" } with status 403. Hooks should roll back optimistic updates on this.
Server error (500): Automatically captured by Sentry in the v2 route. Hooks should show a generic error toast.
After removing legacy code, ESLint flags orphaned imports:
pnpm fix:oxfmt src/async/supabaseCrudHelpers/index.ts
pnpm fix:oxfmt src/types/apiTypes.ts
New types aren't consumed yet → ensure all usage sites import from the v2 route file, not apiTypes.ts.
If the v2 response shape differs from legacy (e.g., nullable fields added, phantom fields removed), update the hook's generic parameters and optimistic updater accordingly.
If the v2 route serves a different data shape, the React Query cache key may need updating. Check src/utils/constants.ts for the correct key constant.
Route cleanup is complete when:
postApi to v2 URLsupabaseCrudHelpers/index.tsapiTypes.tstrashtrash (if applicable)pnpm lint:types passespnpm lint:knip passes (no unused exports)testing
v2-route-audit
tools
release
databases
recollect-caller-migration
tools
prod-hotfix