HookStack
Back to catalogue
WorkflowPostToolUse· Write|EditPostToolUseAfter tool execution · non-blocking· non-blocking

Front-end visual check reminder

Never ship UI you only saw in the diff

After editing any front-end file — styles (css/scss/less…), markup (html), or components (tsx/jsx/vue/svelte/astro) — injects a reminder to verify the change actually renders in the browser. Detects the file kind by extension and tells the agent to load it in the preview, screenshot/snapshot it, check the console, and test the affected interaction or responsive state instead of assuming the diff looks right. Universal: fires on any project, no stack required.

What does the Front-end visual check reminder hook do?

Front-end visual check reminder is a Claude Code PostToolUse hook matching Write|Edit. It fires automatically at that lifecycle event — outside the model, so it can't be skipped or forgotten. Never ship UI you only saw in the diff.

As a PostToolUse hook it runs after the action, reacting to what just happened rather than blocking it. Because it is a deterministic Node.js script, it executes on every matching event without relying on the model to remember — the guarantee that makes agentic workflows safe to automate.

Use cases

  • Catch layout, spacing, or color regressions the diff hides
  • Stop the agent from marking a UI change done without looking at it
  • Prompt a browser preview + screenshot on every css/html/component edit

Tags

#frontend#ui#visual#preview#verification#css#html#tsx

settings.json fragment

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": "node $CLAUDE_PROJECT_DIR/.claude/hooks/post-edit-visual-check.mjs"
          }
        ]
      }
    ]
  }
}

Script · .claude/hooks/post-edit-visual-check.mjs

#!/usr/bin/env node
// @hookstack post-edit-visual-check
// Rappelle de vérifier le rendu UI après l'édition d'un fichier front-end
// (PostToolUse Write|Edit). Détecte le type de fichier par extension — styles
// (css/scss…), markup (html), composants (tsx/jsx/vue/svelte/astro) — et injecte
// un additionalContext demandant à l'agent de constater le rendu dans le
// navigateur (preview/screenshot) plutôt que de supposer que ça marche.
import { readFileSync } from 'fs';
import { fileURLToPath } from 'url';

// Famille de fichiers front-end → libellé du type de changement à vérifier.
const FRONTEND_KINDS = [
  { re: /\.(css|scss|sass|less|styl|pcss)$/i, kind: 'styles' },
  { re: /\.(html?|svelte|vue|astro)$/i, kind: 'markup/component' },
  { re: /\.[jt]sx$/i, kind: 'component' },
];

export function run(input) {
  const filePath = input.tool_input?.file_path ?? '';
  const match = FRONTEND_KINDS.find(({ re }) => re.test(filePath));
  if (!match) return null;

  const name = filePath.split('/').pop();
  return {
    hookSpecificOutput: {
      hookEventName: 'PostToolUse',
      additionalContext:
        `You edited a front-end file (${name} — ${match.kind}). ` +
        'Before considering this done, verify the change actually renders correctly in the browser: ' +
        'load it in the preview and inspect it (snapshot/screenshot, check the console for errors, ' +
        'and test the affected interaction/responsive state). ' +
        'Do not assume the UI looks right from the diff alone — look at it.',
    },
  };
}

/* v8 ignore next 5 */
if (process.argv[1] === fileURLToPath(import.meta.url)) {
  const input = JSON.parse(readFileSync(0, 'utf8'));
  const result = run(input);
  if (result) process.stdout.write(JSON.stringify(result));
}

Learn more

Related hooks