Production resilience pass. Addresses error states, text overflow, i18n prep, edge cases, loading states, and input validation. Use when asked to "harden this", "make it production ready", "handle edge cases", or before shipping UI to real users.
Strengthens UI components for production by handling edge cases, text overflow, loading states, and input validation.
/plugin marketplace add howells/arc/plugin install arc@howellsThis skill inherits all available tools. When active, it can use any tool Claude has access to.
<tool_restrictions>
EnterPlanMode — BANNED. Execute phases below directly.ExitPlanMode — BANNED. You are never in plan mode.
</tool_restrictions>Strengthen UI against real-world usage. Designs that only work with perfect data aren't production-ready.
Announce at start: "I'm using the harden skill to make this production-resilient."
<important> **This skill is user-interactive. Do NOT spawn agents.** Hardening decisions need context — what's likely vs. paranoid, what's worth the complexity. </important><required_reading> Read these using the Read tool:
${CLAUDE_PLUGIN_ROOT}/rules/interface/forms.md — Form behavior and validation${CLAUDE_PLUGIN_ROOT}/rules/interface/interactions.md — Interactive states, destructive actions${CLAUDE_PLUGIN_ROOT}/rules/interface/content-accessibility.md — Accessible content
</required_reading>Read all files for the target component/page. Identify:
Work through each hardening dimension:
Every text element needs an overflow strategy:
<!-- Single line — truncate -->
<p class="truncate">Long text gets ellipsis...</p>
<!-- Multi-line — clamp -->
<p class="line-clamp-3">Shows 3 lines then ellipsis...</p>
<!-- Headings — balance wrapping -->
<h1 class="text-balance">Heading wraps elegantly</h1>
<!-- Body — pretty wrapping -->
<p class="text-pretty">Body text avoids orphans</p>
<!-- Flex children — prevent overflow -->
<div class="min-w-0"><!-- Required in flex to allow truncation --></div>
<!-- URLs and long words -->
<p class="break-all">superlongdomainname.com/path/to/thing</p>
Check:
min-w-0 where neededbreak-all or break-words)Every data-driven view needs an empty state:
<!-- Not just "No items" — provide context and action -->
<div class="flex flex-col items-center gap-4 py-12 text-center">
<p class="text-gray-500">No projects yet</p>
<p class="text-sm text-gray-400">Create your first project to get started.</p>
<button class="...">Create project</button>
</div>
Check:
Every async operation needs loading feedback:
<!-- Skeleton loading — preferred over spinners -->
<div class="animate-pulse space-y-4">
<div class="h-4 w-3/4 rounded bg-gray-200"></div>
<div class="h-4 w-1/2 rounded bg-gray-200"></div>
</div>
<!-- Button loading — disable + spinner + keep label -->
<button disabled class="disabled:opacity-50" aria-busy="true">
<Spinner class="size-4 animate-spin" />
Save changes
</button>
<!-- Inline loading -->
<div aria-busy="true" aria-live="polite">Loading...</div>
Check:
disabled, aria-busy)aria-busy and aria-live for screen readersEvery operation that can fail needs error handling:
<!-- Inline field error -->
<input aria-invalid="true" class="border-red-500 focus:ring-red-500" />
<p class="mt-1 text-sm text-red-500" role="alert">Email address is required</p>
<!-- Page-level error with retry -->
<div class="flex flex-col items-center gap-4 py-12 text-center" role="alert">
<p class="text-red-500">Something went wrong loading your data.</p>
<button onclick="retry()">Try again</button>
</div>
Error messages must:
Check:
aria-invalid and role="alert"Even if not translating yet, prepare the UI:
<!-- Use logical properties (RTL-safe) -->
<div class="ms-4 me-2 ps-3 pe-3"> <!-- Not ml-4 mr-2 pl-3 pr-3 -->
<!-- Budget 30-40% more space for translations -->
<!-- "Save" (EN) → "Speichern" (DE) → "Enregistrer" (FR) -->
<button class="min-w-[120px]">Save</button> <!-- Don't constrain to exact content width -->
Use the Intl API for dates, numbers, currency:
// Not: "March 5, 2026" or toLocaleDateString()
new Intl.DateTimeFormat('en', { dateStyle: 'medium' }).format(date)
new Intl.NumberFormat('en', { style: 'currency', currency: 'USD' }).format(price)
Check:
ms-*, me-*, ps-*, pe-* not ml-*, mr-*)Intl APITest mentally with extreme inputs:
| Scenario | What breaks? |
|---|---|
| 0 items | Empty state needed |
| 1 item | Singular/plural text? Layout with single child? |
| 1,000+ items | Pagination or virtual scroll needed? |
| 500-char user name | Text overflow? Layout break? |
| Slow network (3G) | Loading state needed? Optimistic UI? |
| Offline | Error handling? Cache? |
| Double-click submit | Duplicate prevention? |
| Paste into input | Allowed? Sanitized? |
| Browser back | State preserved? Scroll restored? |
Check:
disabled after click, idempotency keys)Validate client-side for UX, server-side for security:
<!-- Set constraints with HTML attributes -->
<input
type="email"
required
maxlength="255"
autocomplete="email"
class="..."
/>
<!-- Accept free text, validate after -->
<!-- NEVER block typing -->
<!-- MUST allow submitting incomplete forms to surface validation -->
Check:
type for keyboard (email, tel, url, number)autocomplete and name for login/address formsmaxlength on text inputsaria-describedbyPresent findings grouped by impact:
For each finding: describe the issue, show the fix with Tailwind classes, apply after approval.
After fixes:
<arc_log>
After completing this skill, append to the activity log.
See: ${CLAUDE_PLUGIN_ROOT}/references/arc-log.md
Entry: /arc:harden — [Component/page] hardened ([# issues found, # fixed])
</arc_log>
<success_criteria> Harden is complete when:
Activates when the user asks about AI prompts, needs prompt templates, wants to search for prompts, or mentions prompts.chat. Use for discovering, retrieving, and improving prompts.
Search, retrieve, and install Agent Skills from the prompts.chat registry using MCP tools. Use when the user asks to find skills, browse skill catalogs, install a skill for Claude, or extend Claude's capabilities with reusable AI agent components.
Creating algorithmic art using p5.js with seeded randomness and interactive parameter exploration. Use this when users request creating art using code, generative art, algorithmic art, flow fields, or particle systems. Create original algorithmic art rather than copying existing artists' work to avoid copyright violations.