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.

Newest course

Advanced Radix UI

Build rich UI components — without doing any of the boring work.

Animated Switch24:31

Learn how to work with Radix's unstyled primitives by building a robust switch component.

Apple Selector Group18:55

Build a dynamic selector group inspired by Apple.com's checkout flow.

iOS Slider1:01:43

Learn how to add custom interactions to Radix components by recreating the slider from iOS.

Animated Toast27:51

Delegate Radix's mounting logic to Framer Motion to animate a list of messages.

Recently completed

Ship an app with Remix

Learn this popular React framework by building and deploying your own Work Journal.

Scaffolding a new app12:31

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

Creating an entry form22:49

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

Saving new entries20:44

Set up Prisma and SQLite to persist our dynamic data.

Adding pending UI15:12

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

Loading entries8:22

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

Displaying entries by week24:09

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

Creating the edit page13:43

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

Editing entries9:47

Build a form and action that lets users edit entries.

Making the entry form reusable10:20

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

Deleting entries10:25

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

Adding an authenticated state23:43

Let admins sign in by adding a login route that creates a session cookie.

Adding a logout button6:48

Let admins sign out by creating a form that destroys the session.

Customizing the public UI5:01

Use the session to hide admin-only user flows from public guests.

Securing our app12:58

Learn how to secure our backend data from unauthorized requests.

Customizing the error pages13:19

Use an Error Boundary to provide better feedback to users when they encounter an exception.

Adding error messages to the login form13:37

Use the return value from our login action to show validation errors to the user.

Mobile redesign41:57

Give our UI a facelift on smaller screens using Tailwind CSS and some digital design best practices.

Desktop redesign18:46

Finish up our redesign by adapting the UI for larger screens.

Deploying our app16:14

Deploy your brand new Work Journal to Fly.io so you can share it with the world!

Data fetching with React Server Components

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

Building a users table4:55

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

Adding server-side pagination7:26

Use query params to paginate the list of users.

Polishing the pagination controls16:17

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

Adding client-side search9:19

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

Preserving query params across interactions18:30

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

Adding Loading UI3:44

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

Adjusting the loading boundary6:46

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

Showing pending UI during search3:42

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

Debouncing client-side search5:16

Wait until the user finishes typing before querying the database.


Framer Motion Recipes

Add beautiful animations to your React apps using Framer Motion.

Multistep wizard25:15

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

Email client16:43

Add animation to unmounting elements using the versatile AnimatePresence component.

Fixed header: Part 118:54

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

Fixed header: Part 217:08

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

Carousel: Part 114:00

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

Carousel: Part 222:04

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

Resizable panel34:19

Use measured height to resize a panel with dynamic content.


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

Tailwind Mastery

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

A taste of Tailwind9:08

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

Scaffolding a multipanel layout7:47

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

Making nested panels scrollable4:59

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

Customizing colors3:32

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

Adding custom fonts6:44

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

Building a server selector with SVG5:49

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

Transitioning rounded corners4:29

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

Styling active links5:08

Conditionally apply classes to target different application states.

Building the active indicator11:23

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

Eliminating duplication with components10:05

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

Building the server header7:17

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

Styling the channel list7:17

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

Dynamic categories and channels12:35

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

Styling the active channel9:01

Use nested router segments to build an active channel link.

Using a state variable to style unread channels7:28

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

Animated collapsible categories4:55

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

Controlling layout with truncated text8: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 box6:01

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

Styling dynamic messages with components7:03

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

Dynamic server and channel links3:21

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

Hiding desktop navigation on mobile screens7:07

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

Do your React components compose?15:47

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

Preserving draft comments with useGlobalState16:37

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

Hiding a sidebar on mobile without a hydration mismatch26:30

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

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