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