--- name: web-performance description: Web performance as an up-front design decision, not a later optimization pass. Use when building any user-facing page or component, deciding what loads when, or fixing a slow load or Core Web Vitals (LCP, CLS, INP). The organizing principle is to split what the user needs for first paint from what can wait, and build to that split from the start. Covers render-blocking CSS/JS, preloading the LCP element, lazy-loading the rest, reserving space to stop layout shift, and image/font/JS cost. when_to_use: | - Building or structuring any user-facing page or component, decide the load strategy up front, not after - Deciding what to inline, preload, defer, or lazy-load - A page is slow to render, or Core Web Vitals (LCP, CLS, INP) need work - Adding images, fonts, scripts, or third-party tags to a page - Do NOT use for backend throughput tuning (that's elsewhere) or native apps --- # Web Performance: Decide It Up Front Performance is an architecture decision made at the start, not a cleanup pass at the end. The first question for anything user-facing is: what does the user need to see and interact with first, and what can wait. Build to that split. Loading everything eagerly and optimizing later is the expensive path, and it's the one Claude defaults to. ## Split first paint from later, and load each accordingly Sort every resource into two buckets and treat them differently: - **Critical, needed for first paint** (above the fold, the main content and its styles): put it in the initial HTML, inline the critical CSS (see css-structure), preload the largest image and the one critical font. - **Later** (below the fold, interactions, secondary features, third-party): defer it. Lazy-load below-fold images and iframes natively with `loading="lazy"`, no JavaScript library or IntersectionObserver needed, the browser handles it, and on an iframe it defers heavy third-party embeds like maps and video players too. Then `defer` or `async` non-critical scripts, dynamic-import offscreen components and routes, and load analytics and third-party tags late and async. ## Don't let CSS or JS block first paint CSS is render-blocking: a single large stylesheet delays the first paint until it's downloaded and parsed. Inline the above-the-fold slice and load the rest without blocking (``, or a `media` swap). A ` ``` `eagerness: moderate` triggers on hover or pointerdown. `prerender` renders the whole page in the background so the click is instant; `prefetch` is the cheaper fetch-only version. Use `prerender` for high-confidence links, since it actually runs the destination's JavaScript, guard one-time side effects like analytics behind the prerender state so they don't fire until the user actually lands. It's Chromium-first today, so treat it as progressive enhancement, quicklink or instant.page is the fallback for other browsers. ## Measure with the real metrics, against a budget set at the start Target Core Web Vitals, LCP, CLS, and INP, and set a performance budget when you start, not after it's slow. Lighthouse gives you the lab number; field data (CrUX or real-user monitoring) gives you the truth. The point of measuring is to hold the up-front decisions honest, not to discover at the end that the page is heavy. --- This skill is built to grow. Add a rule when a real performance problem has a stable, defensible fix.