> This file extends [common/hooks.md](../common/hooks.md) with web-specific hook recommendations. # Web Hooks ## Recommended PostToolUse Hooks Prefer project-local tooling. Do not wire hooks to remote one-off package execution. ### Format on Save Use the project's existing formatter entrypoint after edits: ```json { "hooks": { "PostToolUse": [ { "matcher": "Write|Edit", "command": "pnpm prettier --write \"$FILE_PATH\"", "description": "Format edited frontend files" } ] } } ``` Equivalent local commands via `yarn prettier` or `npm exec prettier --` are fine when they use repo-owned dependencies. ### Lint Check ```json { "hooks": { "PostToolUse": [ { "matcher": "Write|Edit", "command": "pnpm eslint --fix \"$FILE_PATH\"", "description": "Run ESLint on edited frontend files" } ] } } ``` ### Type Check ```json { "hooks": { "PostToolUse": [ { "matcher": "Write|Edit", "command": "pnpm tsc --noEmit --pretty false", "description": "Type-check after frontend edits" } ] } } ``` ### CSS Lint ```json { "hooks": { "PostToolUse": [ { "matcher": "Write|Edit", "command": "pnpm stylelint --fix \"$FILE_PATH\"", "description": "Lint edited stylesheets" } ] } } ``` ## PreToolUse Hooks ### Guard File Size Block oversized writes from tool input content, not from a file that may not exist yet: ```json { "hooks": { "PreToolUse": [ { "matcher": "Write", "command": "node -e \"let d='';process.stdin.on('data',c=>d+=c);process.stdin.on('end',()=>{const i=JSON.parse(d);const c=i.tool_input?.content||'';const lines=c.split('\\n').length;if(lines>800){console.error('[Hook] BLOCKED: File exceeds 800 lines ('+lines+' lines)');console.error('[Hook] Split into smaller modules');process.exit(2)}console.log(d)})\"", "description": "Block writes that exceed 800 lines" } ] } } ``` ## Stop Hooks ### Final Build Verification ```json { "hooks": { "Stop": [ { "command": "pnpm build", "description": "Verify the production build at session end" } ] } } ``` ## Ordering Recommended order: 1. format 2. lint 3. type check 4. build verification