Nextjs Code Quality Enforcer
Enforce Next.js best practices, proper file structure, component patterns, and TypeScript usage with automated code reviews and suggestions. Validates Next.js App Router conventions, Server/Client component patterns, proper imports, and TypeScript usage. Provides real-time feedback on code quality and adherence to Next.js best practices.
$ npx claude-code-templates@latest --hook="development-tools/nextjs-code-quality-enforcer" --yesRequires Claude Code. The command adds this hook to your project's .claudedirectory â nothing runs on ToolZip's servers.
What's inside this hook
Component source
{
"description": "Enforce Next.js best practices, proper file structure, component patterns, and TypeScript usage with automated code reviews and suggestions. Validates Next.js App Router conventions, Server/Client component patterns, proper imports, and TypeScript usage. Provides real-time feedback on code quality and adherence to Next.js best practices.",
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit|MultiEdit",
"hooks": [
{
"type": "command",
"command": "bash -c 'input=$(cat); FILE_PATH=$(echo \"$input\" | jq -r \".tool_input.file_path // empty\"); SUCCESS=$(echo \"$input\" | jq -r \".tool_response.success // false\"); if [ \"$SUCCESS\" = \"true\" ] && [[ \"$FILE_PATH\" =~ \\.(js|jsx|ts|tsx)$ ]] && [[ ! \"$FILE_PATH\" =~ node_modules ]]; then echo \"đ Next.js Code Quality Enforcer: Reviewing $FILE_PATH...\"; ISSUES=0; if [ -f \"$FILE_PATH\" ]; then if [[ \"$FILE_PATH\" =~ app/. ]]; then echo \"đ App Router file detected: $FILE_PATH\"; if [[ \"$FILE_PATH\" =~ page\\.(js|jsx|ts|tsx)$ ]] && ! grep -q \"export default function\" \"$FILE_PATH\" 2>/dev/null && ! grep -q \"export default async function\" \"$FILE_PATH\" 2>/dev/null; then echo \"â Page component must export default function\" >&2; ((ISSUES++)); fi; if [[ \"$FILE_PATH\" =~ layout\\.(js|jsx|ts|tsx)$ ]] && ! grep -q \"children\" \"$FILE_PATH\" 2>/dev/null; then echo \"â Layout component should accept children prop\" >&2; ((ISSUES++)); fi; if [[ \"$FILE_PATH\" =~ page\\.(js|jsx|ts|tsx)$ ]] && ! grep -q \"Metadata\" \"$FILE_PATH\" 2>/dev/null && ! grep -q \"metadata\" \"$FILE_PATH\" 2>/dev/null; then echo \"â ī¸ Consider adding metadata export for SEO\"; fi; if grep -q \"use client\" \"$FILE_PATH\" 2>/dev/null; then echo \"đĨī¸ Client Component detected\"; if ! grep -E \"(useState|useEffect|onClick|onChange|onSubmit)\" \"$FILE_PATH\" 2>/dev/null; then echo \"â ī¸ Client component without interactivity - consider Server Component\"; fi; else echo \"đ Server Component (default)\"; if grep -E \"(useState|useEffect|onClick|onChange|onSubmit)\" \"$FILE_PATH\" 2>/dev/null; then echo \"â Interactive features in Server Component - add \\\"use client\\\" directive\" >&2; ((ISSUES++)); fi; fi; fi; if [[ \"$FILE_PATH\" =~ \\.(jsx|tsx)$ ]]; then if ! grep -q \"import.React\" \"$FILE_PATH\" 2>/dev/null && grep -q \"<\" \"$FILE_PATH\" 2>/dev/null; then echo \"â ī¸ JSX without React import (Next.js 17+ handles this automatically)\"; fi; if ! grep -q \"FC\\|FunctionComponent\" \"$FILE_PATH\" 2>/dev/null && grep -q \"props\" \"$FILE_PATH\" 2>/dev/null && [[ \"$FILE_PATH\" =~ \\.tsx$ ]]; then echo \"đĄ Consider using React.FC or explicit prop types for TypeScript\"; fi; fi; if [[ \"$FILE_PATH\" =~ \\.js$ ]] && [ -f \"tsconfig.json\" ]; then echo \"đ JavaScript file in TypeScript project: $FILE_PATH\"; echo \"đĄ Consider migrating to TypeScript for better type safety\"; fi; if grep -q \"next/image\" \"$FILE_PATH\" 2>/dev/null; then echo \"â
Using next/image for optimized images\"; elif grep -q \"/dev/null; then echo \"đŧī¸ Regular
tag detected\"; echo \"đĄ Consider using next/image for better performance\"; fi; if grep -q \"next/link\" \"$FILE_PATH\" 2>/dev/null; then echo \"â
Using next/link for navigation\"; elif grep -q \"/dev/null && ! grep -q \"http\" \"$FILE_PATH\" 2>/dev/null; then echo \"đ Regular tag for internal links detected\"; echo \"đĄ Use next/link for internal navigation\"; fi; if grep -q \"getServerSideProps\\|getStaticProps\" \"$FILE_PATH\" 2>/dev/null; then echo \"â ī¸ Pages Router data fetching methods detected\"; echo \"đĄ Consider migrating to App Router with Server Components\"; fi; if grep -q \"className=.*{\" \"$FILE_PATH\" 2>/dev/null; then echo \"đ¨ Dynamic className detected\"; if ! grep -q \"clsx\\|classnames\\|cn(\" \"$FILE_PATH\" 2>/dev/null; then echo \"đĄ Consider using clsx or similar utility for className concatenation\"; fi; fi; if [ $ISSUES -eq 0 ]; then echo \"â
Code quality check passed for $FILE_PATH\"; else echo \"â Found $ISSUES code quality issues in $FILE_PATH\" >&2; exit 2; fi; else echo \"â File $FILE_PATH not found\"; fi; else echo \"âšī¸ Code quality check skipped (not a JavaScript/TypeScript file or failed operation)\"; fi'",
"timeout": 20
}
]
}
]
}
}
Related Claude Code Hooks
Smart Formatting
Smart code formatting based on file type. Automatically formats code using Prettier, Black, gofmt, rustfmt, and other language-specific formatters.
Lint On Save
Automatically run linting tools after file modifications. Supports ESLint for JavaScript/TypeScript, Pylint for Python, and RuboCop for Ruby.
Change Tracker
Track file changes in a simple log. Records which files were modified and when for easy tracking of Claude Code activity.
File Backup
Automatically backup files before editing. Creates timestamped backups in a .backups directory when files are modified.
Command Logger
Log all Claude Code commands to a file for audit and debugging purposes. Simple logging that records tool usage with timestamps.
Worktree Ghostty
Worktree Ghostty Layout. Opens a 3-panel Ghostty layout when creating worktrees: Claude Code (left) | lazygit (top-right) / yazi (bottom-right). Creates worktrees in a sibling directory (../worktrees/<repo>/<name>/) and cleans up on removal. macOS only. Requires: jq, Ghostty terminal, lazygit, yazi. Ghostty keybindings required: super+d = new_split:right, super+shift+d = new_split:down.
Catalog data and component content are sourced from the open-source davila7/claude-code-templates project (MIT license). ToolZip curates the listing and writes original descriptions; every component links back to its original source. Claude Code is a product of Anthropic. ToolZip is an independent catalog and is not affiliated with or endorsed by Anthropic.