Command Palette

Search for a command to run...

Hectal
PHASE 25Advanced ~27 min· topic 9 of 9

Topic 25.9

Cross-Cutting Concerns: Performance, Accessibility, i18n and Security at Design Time

In one line

Some requirements touch every screen: performance budgets tied to Core Web Vitals, accessibility to WCAG 2.2 AA, localisation for many languages and directions, security boundaries (XSS, CSP, auth), and observability; deciding them at design time is cheap, retrofitting them is not, so bring the same checklist to every design.

Think of it like this

Building a school. Ramps for wheelchairs, fire exits, signs in two languages and a guard at the gate are planned on the drawing, before the walls go up. Adding a ramp after the steps are poured means breaking concrete. Performance, accessibility, languages, security and monitoring are the ramps and fire exits of a frontend: they cut across every room, so they go into the design.

Words you'll meet

New words in this topic, in plain English. Come back here whenever one feels fuzzy.

Core Web Vitals
Three speed measures from real visits: LCP (main content shows), INP (response to input) and CLS (layout jumping).
75th percentile (p75)
The value 75% of visits are better than. Budgets use it so most users, not just the fastest, get a good experience.
WCAG 2.2 AA
The usual accessibility target: a published set of testable rules at the middle (AA) level.
i18n / l10n
Internationalisation (making an app translatable) and localisation (actually adapting it for a language and region).
Logical properties
CSS like margin-inline-start that follows the reading direction, so layouts flip correctly for right-to-left languages.
XSS
Cross-site scripting: an attacker's script running inside your page. React's escaping prevents most of it.
CSP
Content Security Policy: a response header that tells the browser which scripts and resources may load.
Observability
Being able to see how the app behaves for real users: metrics, errors, logs, traces and alerts.

Step by step

01Put numbers on performance

Write the budget next to the requirements: LCP ≤ 2.5 s, INP ≤ 200 ms, CLS ≤ 0.1 at p75 on mobile, plus resource limits per route. Then name the design choices that keep you inside it.

budget.jsonwhole filejson
{
  "route": "/feed",
  "p75": { "lcpMs": 2500, "inpMs": 200, "cls": 0.1 },
  "resources": { "jsKbGzip": 170, "cssKbGzip": 30, "lcpImageKb": 100, "fonts": 2, "thirdPartyScripts": 1 }
}

02Name the accessibility requirements

Target WCAG 2.2 AA and list the patterns your design uses (combobox, dialog, feed, grid), how focus moves on navigation and in dialogs, what gets announced, and how charts and images are described. Put the hard parts into design-system components.

03Plan for many languages

Messages in catalogues with plurals, Intl for numbers and dates, logical CSS properties and dir, locale in the URL, translations split per locale. The live example shows how much formatting changes between locales.

04Draw the trust boundaries

Everything in the browser can be read and changed by the user, so the boundary is the server. Draw it on the architecture diagram and list what crosses it.

Draw the trust boundariesdiagram
Rendering diagram…

05Plan observability and the rollout

List the metrics (Core Web Vitals per route, error rate, API latency, the feature's success metric), the alerts and the dashboards. Ship behind a feature flag, compare metrics between flag on and off, and keep a rollback plan.

06Run the checklist

At the end of a design, go through the checklist in the code below. It takes two minutes and catches the gaps interviewers and reviewers look for.

Try it yourself

  1. 1

    Fix a route on paper, then in data

    In the budget example, decide which design changes would bring /product/42 under budget, then change its numbers to what you expect after the fix. Predict the console line first.

  2. 2

    Count in Arabic

    In the locale example, switch to ar-EG and click +1 several times. Arabic has six plural categories; predict which message appears for 2, then for 3 and for 11. Check by adding console.log(new Intl.PluralRules("ar-EG").select(11)).

  3. 3

    Break the layout with physical properties

    Change padding-inline-start and border-inline-start to padding-left and border-left. Switch to ar-EG. What looks wrong, and why do logical properties fix it?

Code & diagrams

A performance budget check, as CI would run it New tab

Each failure points to a design fix: `/product/42` needs a smaller, prioritised hero image with reserved space (LCP and CLS); `/dashboard` needs code splitting and transitions for heavy chart updates (JS and INP). The result is text plus colour, never colour alone.

Preview

Press Run to see the page.

Console

Nothing logged yet.

Expected console output

/feed: pass
/product/42: FAIL lcpMs 3100 > 2500, cls 0.18 > 0.1, lcpImageKb 240 > 100
/dashboard: FAIL inpMs 260 > 200, jsKb 210 > 170
One component, three locales: Intl formatting and direction New tab

Plural rules, digits, grouping, currency position, date order and "yesterday" all change with the locale, and none of it is hand-written. Switch to `ar-EG`: the layout flips because of `dir="rtl"`, and the blue bar moves to the right because the CSS uses logical properties.

Preview

Press Run to see the page.

Console

Nothing logged yet.

Expected console output

en-IN | 3 items in your cart | ₹12,34,567.50 | 15 Jan 2024 | yesterday
de-DE | 3 Artikel im Warenkorb | 1.234.567,50 ₹ | 15.01.2024 | gestern
ar-EG | ٣ منتجات في السلة | ‏١٬٢٣٤٬٥٦٧٫٥٠ ₹ | ١٥‏/٠١‏/٢٠٢٤ | أمس
The frontend design checklist (copy this into every design)markdown
## Requirements
- [ ] Functional requirements and what is out of scope
- [ ] Numbers: users, items per page, data sizes, freshness, concurrency
- [ ] Devices and networks to budget for (e.g. mid-range phone, 4G)

## Architecture
- [ ] Rendering per route (CSR / SSR / SSG / ISR / streaming / RSC) and why
- [ ] Component tree for the main screen
- [ ] Every piece of state labelled: server cache, URL, client store, local, form
- [ ] API layer: auth, timeouts, safe retries, errors, de-duplication
- [ ] Loading and error regions (Suspense + error boundaries), empty states

## Data model and interface
- [ ] Client types, normalised entities, ids (client ids for optimistic creates)
- [ ] Endpoints/messages with shapes, pagination cursors, real-time events, idempotency

## Performance
- [ ] Budgets: LCP <= 2.5 s, INP <= 200 ms, CLS <= 0.1 at p75; JS KB per route
- [ ] Code splitting, image sizing and priority, virtualisation, caching, prefetching

## Accessibility (WCAG 2.2 AA)
- [ ] Semantic HTML, keyboard paths, focus management, ARIA patterns used
- [ ] Live announcements, contrast, target size, reduced motion, text alternatives

## Internationalisation
- [ ] Message catalogues with plurals, Intl formatting, RTL with logical CSS
- [ ] Locale in URL, translations split per locale, long-text layouts

## Security
- [ ] No unsanitised HTML, safe URLs, CSP, HttpOnly cookies, CSRF
- [ ] Authorisation on the server for every read and write; secrets never in the bundle
- [ ] Third-party scripts listed and kept off sensitive pages

## Observability and rollout
- [ ] RUM per route, error reporting with source maps, traces, success metric
- [ ] Alerts, dashboards, feature flag, rollback plan

Break it on purpose

Errors are the best teachers. Make each change, read the error, guess what went wrong, then reveal the answer.

Break #1

Build sentences by joining strings

In the locale example, replace the plural lookup with const msg = n + " items in your cart"; and run it.

terminal
$ Console
── what you'll see ──
en-IN | 3 items in your cart | ₹12,34,567.50 | 15 Jan 2024 | yesterday
de-DE | 3 items in your cart | 1.234.567,50 ₹ | 15.01.2024 | gestern
ar-EG | 3 items in your cart | ‏١٬٢٣٤٬٥٦٧٫٥٠ ₹ | ١٥‏/٠١‏/٢٠٢٤ | أمس

Myth vs fact

Myth

Performance, accessibility and i18n can be added after launch.

Fact

They can, at many times the cost: retrofitting focus management, RTL layouts or server rendering touches every screen. Deciding them in the design is cheap.

Myth

A good Lighthouse score means real users have a fast site.

Fact

Lighthouse is a lab test on one machine. Core Web Vitals are judged on real users at p75, on their devices and networks; you need RUM to know.

Myth

React prevents all XSS.

Fact

React escapes text, but dangerouslySetInnerHTML, javascript: URLs, injected third-party scripts and server-rendered data in inline scripts can still open holes. CSP and code review cover what escaping doesn't.

Pro corner

Extra depth for experienced readers. New to this? Skip it for now and come back later.

  • ▸

    INP replaced FID (First Input Delay) as a Core Web Vital in March 2024. INP looks at all interactions on a page, not just the first, which is why long tasks during the whole session, such as heavy re-renders, now matter for the score.

  • ▸

    Budget per route and per device class: a dashboard used on desktops by staff and a product page used on phones by the public deserve different limits. A single global budget is either too loose or blocks the wrong teams.

  • ▸

    Intl data comes with the browser, so formatting adds nothing to your bundle; message catalogues and ICU parsing do. Precompiling messages at build time and splitting them per route keeps i18n cheap.

  • ▸

    In design reviews, ask "how will we know this is broken?" for each feature. If the answer is "a user tells support", the observability section is missing.

Remember this

  1. 1

    Performance budgets and Core Web Vitals. Core Web Vitals are Google's user-centred speed metrics, measured at the 75th percentile of real visits: LCP (Largest Contentful Paint, when the main content appears) good at ≤ 2.5 s; INP (Interaction to Next Paint, how fast the page responds to taps and keys) good at ≤ 200 ms; CLS (Cumulative Layout Shift, how much things jump) good at ≤ 0.1 (Phase 23.4). A performance budget turns them into limits the team checks automatically: for example "initial JavaScript ≤ 170 KB gzipped per route, LCP image ≤ 100 KB, no more than 2 web fonts". Design choices that serve the budget: server rendering or static generation for content pages, route-level code splitting, images with reserved sizes, virtualised long lists, keeping urgent updates fast with transitions, and third-party scripts loaded late or not at all.

  2. 2

    Accessibility requirements. State the target: WCAG 2.2 level AA. In a design that means: semantic HTML first (real buttons, links, headings, landmarks, labels, Phase 18.1); every interaction works by keyboard with visible focus and a sensible focus order; focus is managed on route changes, dialogs and dynamic content (Phase 18.2); custom widgets follow ARIA patterns (combobox, dialog, tabs, feed, grid, Phase 18.3–18.4); dynamic updates are announced through live regions; colour contrast is at least 4.5:1 for text; targets are at least 24×24 CSS px (WCAG 2.2); motion respects prefers-reduced-motion; charts and images have text alternatives. Build these into the design system so every team inherits them, and test with axe in CI plus a real screen reader before launch (Phase 18.5).

  3. 3

    Localisation (i18n). Internationalisation (i18n) means building the app so it can be translated and adapted; localisation (l10n) is doing it for each locale (Phase 22.5). Design decisions: no text in code (messages in catalogues with ICU plurals, because "1 item / 2 items" rules differ by language); numbers, currencies, dates and relative times formatted with the built-in Intl APIs; right-to-left languages (Arabic, Hebrew) handled with dir="rtl" and CSS logical properties (margin-inline-start instead of margin-left); layouts that survive text 30–50% longer than English; locale in the URL (/de/...) for SEO with hreflang links; and translations loaded per locale as separate chunks so nobody downloads all languages.

  4. 4

    Security boundaries. Write down where trust ends. XSS (cross-site scripting, running an attacker's script in your page) is prevented by React escaping text by default; the design forbids dangerouslySetInnerHTML except through a sanitiser (Phase 21.1–21.2) and validates URLs (javascript: links, Phase 21.3). A Content Security Policy (CSP), an HTTP header listing which scripts may run (with nonces for inline scripts), limits damage if something slips through (Phase 21.6). Auth: session tokens in HttpOnly, Secure, SameSite cookies rather than localStorage, CSRF protection for cookie-authenticated writes, and every authorisation decision on the server: the client only hides what the user can't use (Phase 21.4–21.5). Payments use the provider's hosted fields (Topic 25.6). Third-party scripts are a supply-chain risk: list them, load them late, and keep them off sensitive pages.

  5. 5

    Observability. If you can't see it, you can't keep it working. Plan RUM for Core Web Vitals per route and device class, error reporting with source maps and release tags (Phase 23.5), logs and traces that connect a frontend request to backend spans (a trace id header), product analytics for the feature's success metric, and alerts on regressions (error rate up after a release, LCP p75 over budget). A design doc should list the metrics, their targets, the dashboards and who gets paged.

  6. 6

    The checklist habit. Every design in this phase ended with the same questions: is it fast (budgets), usable by everyone (a11y), ready for other languages (i18n), safe (trust boundaries) and observable (metrics and alerts)? Saying them in the last ten minutes of an interview shows seniority; writing them into a design doc prevents expensive fixes. The checklist at the end of this topic is meant to be copied.

Explain it without notes

01

What are Core Web Vitals, their "good" thresholds, and how do they shape a frontend design?

02

Which accessibility requirements would you write into a frontend design?

03

How do you prepare a React app for many languages, including right-to-left?

04

Where are the security boundaries in a React frontend, and what do you put in the design doc?

05

What would you monitor after launching a new frontend feature?

Practice

01

Add a fonts limit of 2 to the budget example and a fonts value for each route; make /feed use 3 fonts.

02

Add hi-IN (Hindi) to the locale example with English-like plural forms, and check how the price is formatted.

Trade-offs

  • ↔

    Strict budgets keep the product fast but slow down feature work and need tooling; start with budgets on the few routes that matter most (landing, product, checkout) and widen later.

  • ↔

    A full i18n setup from day one costs time even if you launch in one language; at minimum keep text out of components and use Intl, which makes translation cheap later.

  • ↔

    A strict CSP blocks many attacks but breaks third-party widgets and inline scripts until they're refactored; roll it out in report-only mode first.

Done when you can

  • I can state Core Web Vitals targets and turn them into per-route budgets.

  • I can list the accessibility requirements of a design, with the ARIA patterns it needs.

  • I can design for localisation: catalogues, plurals, Intl, RTL and logical CSS.

  • I can draw the security boundary and list XSS, CSP and auth decisions.

  • I can plan observability: RUM, errors, traces, success metrics and alerts.

  • I can run the frontend design checklist at the end of any design.