SKILL.md

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