Learn how to build
modern user interfaces
for the web

High-quality videos, a private Discord server, and enough reference code to help you make the web what you always dreamed it could be.

Welcome to Build UI.

New course

Data fetching with React Server Components

See how this exciting new primitive simplifies your data-fetching code.

Building a users tableFree

Lesson 14:55

Use Prisma to fetch data directly inside of a Server Component.

Adding server-side paginationPro

Lesson 27:26

Use query params to paginate the list of users.

Polishing the pagination controlsPro

Lesson 316:17

Use Prisma's count function to build out the pagination area.

Adding client-side searchPro

Lesson 49:19

Create a Client Component that re-renders the users table whenever a user types in the search field.

Preserving query params across interactionsPro

Lesson 518:30

Refactor our URL logic to maintain all parameter values using URLSearchParams.

Adding Loading UIPro

Lesson 63:44

Render an instant loading screen while a Server Component fetches data.

Adjusting the loading boundaryPro

Lesson 76:46

Use a custom Suspense boundary to instantly render the static parts of a page.

Showing pending UI during searchPro

Lesson 83:42

Use a React Transition to render a spinner while a Server Component is updating.

Coming soon

Lesson 9

Debouncing client-side search

Wait until the user finishes typing before querying the database.

Recently completed

Tailwind Mastery

Learn Tailwind CSS from scratch by building a pixel-perfect Discord clone.

A taste of TailwindFree

Lesson 19:08

Get acquainted with Tailwind's utility-first approach by building a custom message component.

Scaffolding a multipanel layoutFree

Lesson 27:47

Use Tailwind's Flexbox utilities to make an application layout with fixed and flexible panels.

Making nested panels scrollablePro

Lesson 34:59

Choose which Flexbox panels should scroll when their contents overflow their container.

Customizing colorsPro

Lesson 43:32

Learn best practices for overriding and extending Tailwind's default colors with your brand’s palette.

Adding custom fontsPro

Lesson 56:44

Override the default typeface used by Tailwind with an imported font.

Building a server selector with SVGPro

Lesson 65:49

See how to maintain a utility-first workflow when styling icons by working with inline SVG elements.

Transitioning rounded cornersPro

Lesson 74:29

Generate a one-off corner transition using the Just-In-Time engine.

Styling active linksPro

Lesson 85:08

Conditionally apply classes to target different application states.

Building the active indicatorPro

Lesson 911:23

Use groups to style child elements based on an ancestor's pseudostate.

Eliminating duplication with componentsPro

Lesson 1010:05

See how a reusable component removes duplicate classes without the need for a CSS architecture.

Building the server headerPro

Lesson 117:17

Customize Tailwind's shadows to recreate Discord's floating header.

Styling the channel listPro

Lesson 127:17

Learn how to use spacing and group utilities to style a list of dynamic items.

Dynamic categories and channelsPro

Lesson 1312:35

Map over JSON data to dynamically build up the channel list.

Styling the active channelPro

Lesson 149:01

Use nested router segments to build an active channel link.

Using a state variable to style unread channelsPro

Lesson 157:28

Style a channel's unread state using a simple pattern to improve readability.

Animated collapsible categoriesPro

Lesson 164:55

Use React state and Tailwind transitions to animate a collapsed category's icon.

Controlling layout with truncated textPro

Lesson 178:25

Use the truncate utility to control which panel grows or shrinks based on the available space.

Using the forms plugin to style the search boxPro

Lesson 186:01

Learn how to work with @tailwindcss/forms to recreate Discord's search box.

Styling dynamic messages with componentsPro

Lesson 197:03

Extract two versions of our component from Lesson 1 to render each channel's messages.

Dynamic server and channel linksPro

Lesson 203:21

Round out the app by replacing the remaining static text and links with dynamic data.

Hiding desktop navigation on mobile screensPro

Lesson 217:07

Use Tailwind's mobile-first responsive utilities to customize the interface on small screens.


Framer Motion Recipes

Add beautiful animations to your React apps using Framer Motion.

Multistep wizardFree

Lesson 125:15

Learn the basics of state-based animation with Framer Motion.

Email clientPro

Lesson 216:43

Add animation to unmounting elements using the versatile AnimatePresence component.

Fixed header: Part 1Pro

Lesson 318:54

Use scroll-based animation to smoothly grow and shrink a fixed header.

Fixed header: Part 2Pro

Lesson 417:08

Add a fading nav and a blurred background effect by extracting a reusable Hook.

Carousel: Part 1Pro

Lesson 514:00

Learn how to use the `x` shorthand property to smoothly animate an image container.

Carousel: Part 2Pro

Lesson 622:04

Use an animated aspect ratio to create a navigation bar inspired by iOS Photos.

Resizable panelPro

Lesson 734:19

Use measured height to resize a panel with dynamic content.


Lesson 839:47

Animate an infinite monthly calendar using direction-aware dynamic variants.

New course

My first Remix app

Learn the essentials of this popular React framework by building a personal work journal app.

Scaffolding a new appFree

Lesson 112:31

Create a brand new Remix project and add tooling for TypeScript, Tailwind and Prettier.

Creating an entry formPro

Lesson 222:49

Build the frontend form and define an action for our first user flow.

Saving new entriesPro

Lesson 320:44

Set up Prisma and SQLite to persist our dynamic data.

Adding pending UIPro

Lesson 415:12

Improve our form's UX with validations, default values, and a styled pending state.

Loading entriesPro

Lesson 58:22

Use our homepage's loader to render dynamic entries from our backend.

Displaying entries by weekPro

Lesson 624:09

Map and reduce our dynamic entries into weekly groups using the date-fns library.

Creating the edit pagePro

Lesson 713:43

Define a new dynamic route that loads an entry based on the URL.

Editing entriesPro

Lesson 89:47

Build a form and action that lets users edit entries.

Making the entry form reusablePro

Lesson 910:20

Refactor our form component so it can be used to both create and edit entries.

Deleting entriesPro

Lesson 1010:25

Learn how progressive enhancement works in Remix by making a form to delete entries.

Adding an authenticated statePro

Lesson 1123:43

Add a login route that lets admins sign in using a session cookie.

Coming soon

Lesson 12

Customizing the public UI

Use our session to hide the interactive parts of our app for guests.

Do your React components compose?Free

7 months ago15:47

See how to make truly reusable UI components with forwardRef and prop forwarding.

Preserving draft comments with useGlobalStatePro

8 months ago16:37

Learn how to use `react-hooks-global-state` to maintain ephemeral application state.

Hiding a sidebar on mobile without a hydration mismatchPro

9 months ago26:30

Use the screen width to seed some React state in a way that's robust to server-side rendering.

Buy a lifetime membership

Get all current and future premium Build UI courses, forever.

We create courses for developers obsessed with pixel-perfect details and modern user interface engineering.

If you've ever cracked open the devtools to inspect Stripe's hero section, implemented a live buffered timeline like Twitter, or recreated your favorite iOS animation in React, Build UI was made for you.

one-time paymentearly-bird price

Watch everything, forever.

What you'll get when you join

Full access to all Build UI videos

Get full access to all of our current and future premium video content.

Private Discord

Ask questions and get answers from Sam, Ryan and other pro members.

Video summaries with code snippets

Easily reference videos with text summaries and copyable code snippets.

Source code

View the source code for every video right on GitHub.

Invoices and receipts

Get reimbursed from your employer for becoming a better coder!

Meet the team

Hey! We're Sam Selikoff and Ryan Toronto, and together we've been teaching frontend development for over eight years through our podcast, in-person trainings and conference talks, videos on Egghead and EmberMap, and more recently on our YouTube channels.

Check out our existing resources if you're hungry for more frontend content!

Frontend First Podcast Logo

Frontend First Podcast



Sam's YouTube

Ryan's YouTube