Skip to main content
WireKit
Copy for LLM

wirekit:doctor

A no-side-effect diagnostic command that walks your installation and reports any drift between WireKit's expected setup and what your project actually has on disk. Run it after a fresh composer require pushery/wirekit, after every composer update, or whenever components look unstyled / non-interactive.

php artisan wirekit:doctor

wirekit:doctor is an alias of wirekit:verify — same checks, friendlier name. Both commands are idempotent and read-only; running them never modifies your project.

What it checks

The doctor walks every check in sequence, grouped into five sections:

1 · Asset publishing & freshness

Check Pass criterion
wirekit.css published File exists at public/vendor/wirekit/wirekit.css
wirekit.js published File exists at public/vendor/wirekit/wirekit.js
Asset freshness md5 hash of published copy matches the package source — catches forgotten vendor:publish --force after composer update
Built CSS contains WireKit utility rules Tailwind @source directive is correctly picking up WireKit blade templates and emitting matching utility classes

2 · Integration wiring

Check Pass criterion
Tailwind @source directive resources/css/app.css includes @source '../../vendor/pushery/wirekit/resources/views/**/*.blade.php';
config/wirekit.php published Config file exists in your config/ directory
Blade directives present Layout file contains @wirekitStyles (in <head>) AND @wirekitScripts (before </body>)
Bundle config config('wirekit.scripts.bundle') is 'full' or 'core'
CSS @import anti-pattern Warns if wirekit.css is @import-ed in app.css instead of using the @wirekitStyles directive

3 · Token alignment

Compares your Tailwind-side CSS custom properties against the matching WireKit-side tokens and reports every pair whose values disagree. Example: a --font-sans: 'Inter' declaration in your app.css against WireKit's --font-wk-sans: 'Instrument Sans' is reported as a mismatch. Pairs where either side is a var(...) reference (intentional alias) are skipped.

Token pair What it covers
--font-sans--font-wk-sans Sans serif font family — drives both Tailwind utilities (font-sans) AND WireKit chrome
--font-serif--font-wk-serif Serif font family
--font-mono--font-wk-mono Monospace font family
--color-accent--color-wk-accent Accent color — your brand primary vs. WireKit's primary surface
--color-accent-foreground--color-wk-accent-fg Accent foreground (for contrast against accent)
--radius--radius-wk Border radius scale — keeps Tailwind utilities visually consistent with WireKit components
--shadow--shadow-wk Box-shadow scale

For each pair the doctor emits one of three states:

  • ✓ aligned — the two tokens resolve to the same value (after normalization).
  • ⚠ mismatch — the values differ. Output includes both literal values plus an actionable fix hint.
  • i skipped — either the Tailwind side is a var(...) reference (intentional alias) or the token is unset on one side. Skipped checks don't count as warnings.

4 · Light/dark token symmetry

Compares the --color-wk-* tokens declared in your :root {} block against those in your .dark {} block. Missing entries on either side mean the corresponding component will inherit a stale value when the theme flips — your end-users see this as "looks wrong in dark mode" without an obvious cause.

Check Pass criterion
:root vs .dark color-token symmetry Every --color-wk-* declared in one block is also declared in the other

Output shapes:

  • — both blocks declare the same set of --color-wk-* tokens (or neither block exists; the check stays silent).
  • — at least one token is asymmetric. The warning lists the missing token names per block.

The check is scoped to color tokens only. Font, radius, and shadow tokens are intentionally theme-agnostic (declared once in :root, never repeated in .dark), so the doctor doesn't flag those.

5 · Alpine plugin cleanup hygiene

Static-analysis scan of your resources/js/ tree for custom Alpine plugins. Flags two anti-patterns that commonly produce silent TypeError console errors after Livewire morph / conditional render / SPA navigation tears down a host element while a browser-queued observer callback is still in flight.

Anti-pattern What the doctor looks for
Observer without destroy() A file containing new IntersectionObserver(...) / new MutationObserver(...) / new ResizeObserver(...) that has NO destroy() lifecycle method. Without destroy(), the observer holds the host-element reference forever and prevents garbage collection.
Unguarded in-callback disconnect() A file containing both .disconnect() AND an observer instantiation, but no if (! this._<observer>) return; early-return OR this._<observer>?.disconnect() optional-chaining form. Without the guard, callbacks queued before destroy() throw TypeError: Cannot read properties of null (reading 'disconnect').

Output shapes:

  • — no anti-patterns detected, OR resources/js/ doesn't exist (developers without custom plugins skip the check entirely).
  • — one or more files match a heuristic. The warning lists each file + the specific anti-pattern(s) detected.

Opt out for a file that intentionally uses a pattern the heuristic doesn't recognize (for example, the observer reference is captured in a closure-local variable rather than this._observer): add this comment marker anywhere in the file:

// wirekit-doctor: cleanup-ok

The doctor will skip that file. Use sparingly — most intentional exemptions in practice turn out to be bugs on closer inspection. See Authoring Custom Alpine Plugins for the canonical defensive-cleanup pattern WireKit's own plugins follow.

Example output

WireKit Integration Check

  ✓ wirekit.css published
  ✓ wirekit.js published
  ✓ wirekit.css is up to date
  ✓ Tailwind @source includes WireKit templates
  ✓ config/wirekit.php published
  ✓ Blade directives configured
  ✓ JS bundle configured: full
  ✓ Built app CSS contains WireKit utility rules

  Token alignment:
    ✓ Sans font: aligned (inter)
    ⚠ Serif font: mismatch — Tailwind `'Lora', serif` vs WireKit `'Playfair Display', serif`. Fix: php artisan wirekit:install --font-serif=<key>
    i Mono font: skipped (Tailwind-side token unset)
    ✓ Accent color: aligned (oklch(60% 0.2 250))
    i Accent foreground: skipped (var(...) reference — intentional alias)
    ✓ Border radius: aligned (0.5rem)
    i Shadow: skipped (Tailwind-side token unset)

  9 passed, 1 warnings, 0 failed

Common failures and fixes

Each subsection below quotes the exact doctor line that triggered it (in a code block) followed by what it means and how to fix it. The glyph indicates a warning; i is informational; confirms alignment.

Sans font mismatch

⚠ Sans font: mismatch — Tailwind 'Inter' vs WireKit 'Roboto'

Your font-sans Tailwind utilities will render Inter while WireKit components render Roboto. Pick one and run:

php artisan wirekit:install --font=<key>

(see wirekit:install flag table for available keys)

This writes BOTH --font-sans AND --font-wk-sans to the same family in your app.css — guaranteed alignment.

Accent color mismatch

⚠ Accent color: mismatch — Tailwind oklch(60% 0.2 250) vs WireKit oklch(50% 0.3 30)

Tailwind's bg-accent will render blue while <x-wirekit::button> renders red. Either:

  • Update your @theme { --color-accent: ... } block to match WireKit, or
  • Override --color-wk-accent in :root to match your brand

The token alignment doctor doesn't auto-fix color tokens (unlike fonts) because brand identity is too project-specific to template.

Sans font skipped (token unset)

i Sans font: skipped (token unset)

You haven't set --font-sans (or --font-wk-sans) — likely you're using the bundled WireKit defaults on both sides. No action required; the skip is informational.

Light/dark color-token asymmetry

⚠ Light/dark color-token symmetry — :root has 3 token(s) missing from .dark: --color-wk-bg-elevated, --color-wk-border, --color-wk-text-muted

Your :root {} declares color tokens that aren't repeated in .dark {} (or vice versa). When the theme flips, the missing-side block inherits whatever the cascade resolves to — usually a stale value from the other block. Developers see this as "the dark variant of this card looks wrong" without an obvious source.

Add the missing tokens to whichever block lacks them. Every WireKit-shipped color token has both a light and a dark value; the rule of thumb is one declaration per block per token.

resources/css/app.css not found

⚠ resources/css/app.css not found

You're running the doctor from a fresh checkout that hasn't run wirekit:install yet, OR your CSS lives at a non-standard path. Run wirekit:install first, or set up app.css manually per the Integration guide.

CI integration

wirekit:doctor exits with status code 1 when any check fails (warnings don't fail the build). Wire it into your CI:

# .github/workflows/test.yml
- name: WireKit integration check
  run: php artisan wirekit:doctor

Or as a Claude Code stop-hook:

// .claude/settings.json
{
  "hooks": {
    "Stop": [
      { "type": "command", "command": "php artisan wirekit:doctor" }
    ]
  }
}

Aliases and history

  • wirekit:doctor is the canonical name.
  • wirekit:verify is the back-compat alias — same code path, identical output.

See Also

  • wirekit:install — initial setup; provides the --font* flags that the doctor's token-alignment checks reference.
  • Integration guide — full setup from composer require through asset wiring.
  • Design Tokens — design-token reference (helpful when interpreting mismatch hints).