React Server Components: What Designers Need to Know

React Server Components (RSC) changed how React apps work at a fundamental level, and most explanations are written for backend engineers. If you're a designer who codes (or a frontend developer who cares about user experience), here's what actually matters about RSC and how it affects the things you build.

The One-Sentence Version

Server Components render on the server and send HTML to the browser. They never run in the browser. This means they can access databases and APIs directly, and they don't add to your JavaScript bundle size.

Why This Matters for UX

Before RSC, every React component shipped as JavaScript to the browser. A product page with a database query would need: an API route to fetch data, a client-side fetch call, a loading state, an error state, and the component itself. Five pieces for one page.

With RSC, the component itself makes the database call, renders to HTML, and sends the result. The browser gets a fully rendered page immediately. No loading spinners. No layout shift as data arrives. No JavaScript for components that don't need interactivity.

For users, this means faster initial page loads and less visual jank. For designers, it means your carefully designed layouts appear as designed from the first frame, not after a cascade of loading states.

The 'use client' Boundary

In Next.js (the most common way to use RSC), components are Server Components by default. When a component needs browser features (onClick handlers, useState, useEffect, browser APIs), you add 'use client' at the top of the file.

// This is a Server Component (default)
// Can access database, read files, use secrets
async function ProductList() {
  const products = await db.query('SELECT * FROM products');
  return products.map(p => <ProductCard product={p} />);
}

// This is a Client Component
'use client'
function AddToCartButton({ productId }) {
  const [loading, setLoading] = useState(false);
  return <button onClick={() => addToCart(productId)}>Add to Cart</button>;
}

The mental model: Server Components handle data and layout. Client Components handle interaction. The boundary between them is the 'use client' directive.

Design Implications

Loading states become optional, not mandatory. Server Components can await data before rendering. Instead of designing skeleton screens for every data-dependent component, you can design the final state and know it'll appear complete.

Bundle size affects design choices less. That rich data visualization library? If it renders on the server, it doesn't bloat the client bundle. You can use heavier tools for server-rendered content without penalizing mobile users.

Streaming changes the loading pattern. Next.js can stream Server Components as they resolve. A page with a fast header and slow product list can show the header immediately while the products load. This looks like progressive page building rather than all-or-nothing loading.

What You Can't Do in Server Components

Anything that needs the browser:

  • Event handlers (onClick, onChange, onSubmit)
  • State (useState, useReducer)
  • Effects (useEffect, useLayoutEffect)
  • Browser APIs (window, document, localStorage)
  • Third-party libraries that use any of the above

If your component needs any of these, it's a Client Component. Most interactive UI elements (forms, modals, dropdowns, drag-and-drop, animations triggered by user action) need to be Client Components.

The Practical Architecture

For a typical page, the architecture looks like:

  • Page layout (Server): Fetches data, defines structure
  • Static content (Server): Text, images, cards that don't change
  • Interactive islands (Client): Buttons, forms, modals, real-time updates

Think of it as a mostly-static page with interactive islands. The page shell and content are server-rendered. The interactive bits are client-side JavaScript. This "islands" mental model helps designers understand where performance budgets apply and where they don't.

Styling Considerations

CSS works the same in both component types. Tailwind classes, CSS modules, and global styles all work identically. The one gotcha: CSS-in-JS libraries that use runtime JavaScript (styled-components, emotion) need the 'use client' directive. If you're using Tailwind (as most Next.js projects do in 2026), this isn't an issue.

Real-World Impact

At RAXXO Studio, I use 'use client' on page components because the app is highly interactive (video upload, content editing, real-time previews). But a marketing page or blog could be entirely Server Components with tiny Client Component islands for interactive elements.

The key insight for designers: RSC doesn't change what you can design. It changes how fast your designs load and how the loading experience feels. Design for the final state, not for loading states, and let the architecture handle the transition.

See RSC in action at studio.raxxo.shop, built on Next.js with the App Router.