1---
2name: harden
3description: "Make interfaces production-ready: error handling, empty states, onboarding flows, i18n, text overflow, and edge case management. Use when the user asks to harden, make production-ready, handle edge cases, add error states, design empty states, improve onboarding, or fix overflow and i18n issues."
4argument-hint: "[target]"
5user-invocable: true
6---
7
8Strengthen interfaces against edge cases, errors, internationalization issues, and real-world usage scenarios that break idealized designs.
9
10## Assess Hardening Needs
11
12Identify weaknesses and edge cases:
13
141. **Test with extreme inputs**:
15 - Very long text (names, descriptions, titles)
16 - Very short text (empty, single character)
17 - Special characters (emoji, RTL text, accents)
18 - Large numbers (millions, billions)
19 - Many items (1000+ list items, 50+ options)
20 - No data (empty states)
21
222. **Test error scenarios**:
23 - Network failures (offline, slow, timeout)
24 - API errors (400, 401, 403, 404, 500)
25 - Validation errors
26 - Permission errors
27 - Rate limiting
28 - Concurrent operations
29
303. **Test internationalization**:
31 - Long translations (German is often 30% longer than English)
32 - RTL languages (Arabic, Hebrew)
33 - Character sets (Chinese, Japanese, Korean, emoji)
34 - Date/time formats
35 - Number formats (1,000 vs 1.000)
36 - Currency symbols
37
38**CRITICAL**: Designs that only work with perfect data aren't production-ready. Harden against reality.
39
40## Hardening Dimensions
41
42Systematically improve resilience:
43
44### Text Overflow & Wrapping
45
46**Long text handling**:
47```css
48/* Single line with ellipsis */
49.truncate {
50 overflow: hidden;
51 text-overflow: ellipsis;
52 white-space: nowrap;
53}
54
55/* Multi-line with clamp */
56.line-clamp {
57 display: -webkit-box;
58 -webkit-line-clamp: 3;
59 -webkit-box-orient: vertical;
60 overflow: hidden;
61}
62
63/* Allow wrapping */
64.wrap {
65 word-wrap: break-word;
66 overflow-wrap: break-word;
67 hyphens: auto;
68}
69```
70
71**Flex/Grid overflow**:
72```css
73/* Prevent flex items from overflowing */
74.flex-item {
75 min-width: 0; /* Allow shrinking below content size */
76 overflow: hidden;
77}
78
79/* Prevent grid items from overflowing */
80.grid-item {
81 min-width: 0;
82 min-height: 0;
83}
84```
85
86**Responsive text sizing**:
87- Use `clamp()` for fluid typography
88- Set minimum readable sizes (14px on mobile)
89- Test text scaling (zoom to 200%)
90- Ensure containers expand with text
91
92### Internationalization (i18n)
93
94**Text expansion**:
95- Add 30-40% space budget for translations
96- Use flexbox/grid that adapts to content
97- Test with longest language (usually German)
98- Avoid fixed widths on text containers
99
100```jsx
101// ❌ Bad: Assumes short English text
102<button className="w-24">Submit</button>
103
104// ✅ Good: Adapts to content
105<button className="px-4 py-2">Submit</button>
106```
107
108**RTL (Right-to-Left) support**:
109```css
110/* Use logical properties */
111margin-inline-start: 1rem; /* Not margin-left */
112padding-inline: 1rem; /* Not padding-left/right */
113border-inline-end: 1px solid; /* Not border-right */
114
115/* Or use dir attribute */
116[dir="rtl"] .arrow { transform: scaleX(-1); }
117```
118
119**Character set support**:
120- Use UTF-8 encoding everywhere
121- Test with Chinese/Japanese/Korean (CJK) characters
122- Test with emoji (they can be 2-4 bytes)
123- Handle different scripts (Latin, Cyrillic, Arabic, etc.)
124
125**Date/Time formatting**:
126```javascript
127// ✅ Use Intl API for proper formatting
128new Intl.DateTimeFormat('en-US').format(date); // 1/15/2024
129new Intl.DateTimeFormat('de-DE').format(date); // 15.1.2024
130
131new Intl.NumberFormat('en-US', {
132 style: 'currency',
133 currency: 'USD'
134}).format(1234.56); // $1,234.56
135```
136
137**Pluralization**:
138```javascript
139// ❌ Bad: Assumes English pluralization
140`${count} item${count !== 1 ? 's' : ''}`
141
142// ✅ Good: Use proper i18n library
143t('items', { count }) // Handles complex plural rules
144```
145
146### Error Handling
147
148**Network errors**:
149- Show clear error messages
150- Provide retry button
151- Explain what happened
152- Offer offline mode (if applicable)
153- Handle timeout scenarios
154
155```jsx
156// Error states with recovery
157{error && (
158 <ErrorMessage>
159 <p>Failed to load data. {error.message}</p>
160 <button onClick={retry}>Try again</button>
161 </ErrorMessage>
162)}
163```
164
165**Form validation errors**:
166- Inline errors near fields
167- Clear, specific messages
168- Suggest corrections
169- Don't block submission unnecessarily
170- Preserve user input on error
171
172**API errors**:
173- Handle each status code appropriately
174 - 400: Show validation errors
175 - 401: Redirect to login
176 - 403: Show permission error
177 - 404: Show not found state
178 - 429: Show rate limit message
179 - 500: Show generic error, offer support
180
181**Graceful degradation**:
182- Core functionality works without JavaScript
183- Images have alt text
184- Progressive enhancement
185- Fallbacks for unsupported features
186
187### Edge Cases & Boundary Conditions
188
189**Empty states**:
190- No items in list
191- No search results
192- No notifications
193- No data to display
194- Provide clear next action
195
196**Loading states**:
197- Initial load
198- Pagination load
199- Refresh
200- Show what's loading ("Loading your projects...")
201- Time estimates for long operations
202
203**Large datasets**:
204- Pagination or virtual scrolling
205- Search/filter capabilities
206- Performance optimization
207- Don't load all 10,000 items at once
208
209**Concurrent operations**:
210- Prevent double-submission (disable button while loading)
211- Handle race conditions
212- Optimistic updates with rollback
213- Conflict resolution
214
215**Permission states**:
216- No permission to view
217- No permission to edit
218- Read-only mode
219- Clear explanation of why
220
221**Browser compatibility**:
222- Polyfills for modern features
223- Fallbacks for unsupported CSS
224- Feature detection (not browser detection)
225- Test in target browsers
226
227### Onboarding & First-Run Experience
228
229Production-ready features work for first-time users, not just power users. Design the paths that get new users to value:
230
231**Empty states**: Every zero-data screen needs:
232- What will appear here (description or illustration)
233- Why it matters to the user
234- Clear CTA to create the first item or start from a template
235- Visual interest (not just blank space with "No items yet")
236
237Empty state types to handle:
238- **First use**: emphasize value, provide templates
239- **User cleared**: light touch, easy to recreate
240- **No results**: suggest a different query, offer to clear filters
241- **No permissions**: explain why, how to get access
242
243**First-run experience**: Get users to their "aha moment" as quickly as possible.
244- Show, don't tell -- working examples over descriptions
245- Progressive disclosure -- teach one thing at a time, not everything upfront
246- Make onboarding optional -- let experienced users skip
247- Provide smart defaults so required setup is minimal
248
249**Feature discovery**: Teach features when users need them, not upfront.
250- Contextual tooltips at point of use (brief, dismissable, one-time)
251- Badges or indicators on new or unused features
252- Celebrate activation events quietly (a toast, not a modal)
253
254**NEVER**:
255- Force long onboarding before users can touch the product
256- Show the same tooltip repeatedly (track and respect dismissals)
257- Block the entire UI during a guided tour
258- Create separate tutorial modes disconnected from the real product
259- Design empty states that just say "No items" with no next action
260
261### Input Validation & Sanitization
262
263**Client-side validation**:
264- Required fields
265- Format validation (email, phone, URL)
266- Length limits
267- Pattern matching
268- Custom validation rules
269
270**Server-side validation** (always):
271- Never trust client-side only
272- Validate and sanitize all inputs
273- Protect against injection attacks
274- Rate limiting
275
276**Constraint handling**:
277```html
278<!-- Set clear constraints -->
279<input
280 type="text"
281 maxlength="100"
282 pattern="[A-Za-z0-9]+"
283 required
284 aria-describedby="username-hint"
285/>
286<small id="username-hint">
287 Letters and numbers only, up to 100 characters
288</small>
289```
290
291### Accessibility Resilience
292
293**Keyboard navigation**:
294- All functionality accessible via keyboard
295- Logical tab order
296- Focus management in modals
297- Skip links for long content
298
299**Screen reader support**:
300- Proper ARIA labels
301- Announce dynamic changes (live regions)
302- Descriptive alt text
303- Semantic HTML
304
305**Motion sensitivity**:
306```css
307@media (prefers-reduced-motion: reduce) {
308 * {
309 animation-duration: 0.01ms !important;
310 animation-iteration-count: 1 !important;
311 transition-duration: 0.01ms !important;
312 }
313}
314```
315
316**High contrast mode**:
317- Test in Windows high contrast mode
318- Don't rely only on color
319- Provide alternative visual cues
320
321### Performance Resilience
322
323**Slow connections**:
324- Progressive image loading
325- Skeleton screens
326- Optimistic UI updates
327- Offline support (service workers)
328
329**Memory leaks**:
330- Clean up event listeners
331- Cancel subscriptions
332- Clear timers/intervals
333- Abort pending requests on unmount
334
335**Throttling & Debouncing**:
336```javascript
337// Debounce search input
338const debouncedSearch = debounce(handleSearch, 300);
339
340// Throttle scroll handler
341const throttledScroll = throttle(handleScroll, 100);
342```
343
344## Testing Strategies
345
346**Manual testing**:
347- Test with extreme data (very long, very short, empty)
348- Test in different languages
349- Test offline
350- Test slow connection (throttle to 3G)
351- Test with screen reader
352- Test keyboard-only navigation
353- Test on old browsers
354
355**Automated testing**:
356- Unit tests for edge cases
357- Integration tests for error scenarios
358- E2E tests for critical paths
359- Visual regression tests
360- Accessibility tests (axe, WAVE)
361
362**IMPORTANT**: Hardening is about expecting the unexpected. Real users will do things you never imagined.
363
364**NEVER**:
365- Assume perfect input (validate everything)
366- Ignore internationalization (design for global)
367- Leave error messages generic ("Error occurred")
368- Forget offline scenarios
369- Trust client-side validation alone
370- Use fixed widths for text
371- Assume English-length text
372- Block entire interface when one component errors
373
374## Verify Hardening
375
376Test thoroughly with edge cases:
377
378- **Long text**: Try names with 100+ characters
379- **Emoji**: Use emoji in all text fields
380- **RTL**: Test with Arabic or Hebrew
381- **CJK**: Test with Chinese/Japanese/Korean
382- **Network issues**: Disable internet, throttle connection
383- **Large datasets**: Test with 1000+ items
384- **Concurrent actions**: Click submit 10 times rapidly
385- **Errors**: Force API errors, test all error states
386- **Empty**: Remove all data, test empty states
387
388Remember: You're hardening for production reality, not demo perfection. Expect users to input weird data, lose connection mid-flow, and use your product in unexpected ways. Build resilience into every component.
389