Autoplay
Autocomplete
Previous Lesson
Complete and Continue
Remix (React Router) Bootcamp: Zero to Mastery
Introduction
Course Outline (5:40)
What is Remix? (2:20)
Why Remix? (6:36)
Remix vs React Router (2:12)
Intro to the Master Project (3:51)
The Recipe Page & Optimistic UI (7:23)
Finishing the Tour of the Master Project (5:38)
Exercise: Meet Your Classmates and Instructor
ZTM Plugin + Understanding Your Video Player
Course Resources
Set Your Learning Streak Goal
Remix Overview
Installing NodeJS (2:02)
Creating a React Router Project (1:29)
The Vite Config File (1:09)
Upgrading Remix and Future Flags (3:32)
Owning Your Entry Points (2:12)
What are Routes? (2:48)
Exercise: Identifying Server and Client Components in Remix Routes
Solution
Let's Have Some Fun (+ More Resources)
Basic Routes and Styling
An Explanation of New Imports
Nested Routing (6:31)
Exercise: Nested Routing in Remix
Solution
The Root Route (3:15)
Exercise: Understanding Matched Routes with useMatches
Solution
Remix's Special Components (3:41)
The Link API (3:05)
Adding Style with Links (7:13)
Exercise: Utilizing the links Route Export in Remix
Solution
Techniques for Component-Level CSS (7:44)
Setting Up Tailwind (3:38)
Using Tailwind - Part 1 (4:26)
Using Tailwind - Part 2 (5:45)
Using Tailwind - Part 3 (5:09)
Unlimited Updates
Introduction to Data Loading in Remix
What are Loaders? (9:34)
Exercise: Remix Loaders
Solution
Pending UI (9:06)
Exercise: Implementing Pending UI on Links in Remix
Solution
Why Load Before Route Transitions (9:43)
Sharing Data Between Routes (3:53)
Exercise: Revert the changes from the last lesson
Errors and Error Boundaries (5:52)
Exercise: Handling Errors with Error Boundaries in Remix
Solution
Installing Postgres with Docker (15:09)
Setting Up Prisma with Postgres (7:15)
Implement a New Life System
Master Project: Remix Recipes App (The Pantry Page)
Overview (2:25)
Setting Up the Pantry Route (11:03)
Redirects in Remix (7:04)
Exercise: Experimenting with HTTP Status Codes
Solution
Setting Up the Pantry Database Tables (13:12)
Seeding the Database (9:13)
Database UI Tools (9:36)
Loading Data into the Pantry UI (5:12)
Creating a Model Abstraction (10:37)
Building a Basic Shelf UI (10:53)
Intro to HTML Forms (21:34)
Exercise: Exploring Similarities Between HTML Forms and Anchor Tags in Remix
Solution
Enhancing the Search Bar with JavaScript (8:16)
Exercise: The FormData Object
Solution
Creating Shelves (14:11)
Enhancing the Create Shelf Button (8:09)
Deleting Shelves (18:45)
Handling Multiple Deletes (6:57)
Introducing useFetcher (7:30)
More Cases for useFetcher (2:05)
Server State in Remix (4:27)
Exercise: Understanding Concurrency in Remix
Solution
Editing Shelf Names (12:27)
Validating Forms with Zod (18:44)
Intro to Optimistic UI (9:19)
Optimistically Deleting Shelves (12:56)
Creating Shelf Items (7:21)
Deleting Shelf Items (11:56)
Optimistically Creating Shelf Items (21:45)
Suppressing the Layout Effect Warning (4:23)
Optimistically Deleting Shelf Items (8:17)
Additional Enhancements (14:16)
Course Check-In
Authentication Prerequisites
Overview (1:32)
The User Model (7:40)
The Login Route (10:10)
Intro to Cookies (2:24)
Setting Our First Cookie (3:41)
Cookie Attributes (7:27)
A Simple Auth Flow (6:20)
Remix's Cookie Helper (5:04)
Exercise: Cookies
Solution
Cryptographic Signatures (4:09)
Signing Cookies (1:45)
Signing Cookies in Remix (4:27)
Sessions (3:42)
Session Storage (4:02)
Session Storage in Remix (7:10)
Magic Link Authentication
Overview (2:45)
What is Authentication (2:02)
Overview of Magic Link Authentication (2:51)
Magic Link Structure (1:51)
Generating Magic Links (7:46)
Updating the Login Route (3:57)
Validation Route Overview (1:49)
Parsing the Magic Link Payload (8:36)
Validating the Expiration Time (3:09)
Validating the Nonce (6:04)
Finishing the Login (2:42)
The Sign Up Form (8:12)
The Sign Up Form Action (9:37)
Signing Up for Mailgun (3:48)
Setting Up the Mailgun Client (6:16)
Sending the Magic Link Email (6:08)
Showing the Check Email Message (2:19)
Authorization
Overview (2:52)
Authorization Rules for the Login Page (2:26)
Login Authorization Rule #1 (6:19)
Login Authorization Rule #2 (1:06)
Authorization Rules for the Pantry Page (5:54)
Pantry Authorization Rule #1 (2:42)
Pantry Authorization Rule #2 (1:40)
Pantry Authorization Rules #3-4 (2:15)
Pantry Authorization Rules #5-6 (3:43)
Pantry Authorization Rule #7 (2:22)
UI Updates Roadmap (2:15)
Adding an Error Boundary (7:30)
Hiding the App Nav Button (3:03)
Creating a Logout Route (5:28)
User Interface (The Recipe Page)
Overview (4:05)
Revisiting the Remix Philosophy (3:28)
Setting Up the Recipes Route (4:34)
Setting Up the Recipe Database Tables (3:55)
Updating the Seed Script (4:23)
Recipe Page Components (1:44)
The Recipes Loader (5:59)
Rendering the Recipe List (4:19)
Creating a Search Bar Component (7:46)
Supporting Search in the Loader (2:09)
The Create Recipe Form (4:51)
Setting Up the Recipe Detail Route (4:44)
Exercise: Exploring Dynamic Route Segments in Remix
Solution
Sorting the Recipes List (1:35)
Preserving the Search Parameters (6:17)
Recipe Link Pending UI (5:41)
Exercise: Writing your own Hook to Delay the Pending UI
Using Link Prefetch (8:19)
Recipe Detail Route Overview (1:39)
Overview of Step 1 - Creating an Input Component (6:40)
Displaying the Name and Total Time (10:13)
Rendering the Ingredients (7:24)
Rendering the Instructions (6:30)
Overview of Step 2 - Updating Recipes (1:03)
Saving the Recipe Name, Total Time, and Instructions (8:32)
FormData's getAll Function (4:01)
Updating the validateForm Function (8:28)
Updating the Ingredients (8:05)
Creating New Ingredients (7:28)
Addressing and Issue (4:08)
Adding Error Messages to the UI (7:39)
Exercise: Imposter Syndrome (2:55)
Overview of Step 3 - Deleting Recipes and Ingredients (0:32)
Deleting a Recipe (2:27)
Deleting Ingredients (3:38)
Authorization Rules for the Recipe Detail Route (1:50)
Recipe Detail Authorization Rule #1 (2:55)
Recipe Detail Authorization Rules #2-5 (2:07)
Enhancement Overview (2:34)
Overview of Step 1 - Saving Inputs on Change (1:19)
Saving Recipe Inputs on Change (8:22)
Creating an Ingredient Row Component (5:52)
Saving Ingredient Inputs on Change (4:03)
Persisting the Recipe Fetcher Data (6:50)
Persisting the Ingredient Fetcher Data (5:06)
Debouncing Form Inputs (2:06)
Creating a Hook for Debouncing (7:03)
Debouncing the Form Inputs (3:31)
Overview of Step 2 - The Case for Optimistic UI in the Side Bar (2:01)
Updating the Side Bar with useFetchers (5:46)
Overview of Step 3 (3:39)
Wiring up a Fetcher to Create New Ingredients (9:27)
Creating a Hook for Optimistically Rendering Ingredients (5:17)
Optimistically Rendering New Ingredients (4:58)
Updating the Default Enter Key Behavior (4:14)
Creating Mew Ingredients with the Enter Key (1:54)
Focusing the Amount Input on Create (4:47)
Optimistically Deleting Ingredients (3:43)
File Uploads
Overview (1:22)
Creating a File Input (3:26)
The Urlencoded Content Type (5:35)
The Multipart Content Type (5:29)
Parsing Multipart Forms (1:26)
Overview of Parsing Multipart Forms in Remix (5:16)
Remix's Built-In Upload Handlers (3:47)
Storing Images in the Public Directory (3:15)
Writing the Image URL to the Database (3:09)
Exercise: Implementing Custom File Upload Handler in Remix with Cloudinary Simulation
Solution
Remix Modals (The Grocery List)
Overview (3:29)
Updating the DB to Track Meal Plans (2:18)
Modals in Remix (4:29)
Setting up the Modal Route (4:59)
Creating some Components for the Modal (5:25)
Meal Plan Modal UI (5:43)
Passing Context to the Outlet (4:46)
Creating the Modal Action (5:22)
The Update Meal Plan Action Case (6:18)
Indicating which Recipes are in the Meal Plan (3:31)
The Meal Plan Filter Button (7:00)
The Meal Plan Filter Backend (2:26)
Preserving the Search State when Filtering (5:17)
Preserving the Filter State when Searching (3:48)
Overview of Next Steps and Setting up the Grocery List Route (2:21)
Defining the Grocery List Item Type (4:16)
Building the Grocery List Item Component (6:16)
Getting Started on the Grocery List Loader (6:16)
Formatting the Missing Ingredients (3:35)
Grouping Grocery List Items by the Ingredient Name (6:05)
Rendering the Grocery List (2:35)
Creating the Grocery List Route Action (4:28)
Adding Grocery Items to the Pantry (6:20)
The Grocery List Empty State (3:17)
Clearing the Meal Plan (6:13)
Resource Routes in Remix (The Settings Page)
Overview (1:28)
The PageLayout Component (4:05)
Setting up the Settings Route (2:30)
Intro to Resource Routes (2:38)
MIME Types (5:45)
Exercise: MIME Types
Solution
Overview of Customizing the Theme (2:33)
Renaming the Resource Route (1:45)
Controlling the Tailwind Theme with the Theme Resource Route (5:01)
Building the Form to Change the Site Theme (3:49)
Creating the Theme Cookie (2:08)
The App Settings Route Action (4:04)
The App Settings Route Loader (2:50)
Fixing the Off-By-One Issue (5:19)
Returning Dynamic CSS Based on the Theme Cookie (3:31)
Caching (The Discover Page)
Overview (0:52)
Redirecting the Home Page (1:17)
The Discover Page UI (4:37)
Discover Detail Page Setup (2:44)
Discover Detail Page UI (3:06)
Intro to Caching (1:47)
Private vs Server Caches (3:09)
Preview of Using the Browser Cache (3:41)
Caching Vocabulary (2:35)
The Default Browser Strategy (3:31)
The No-Store Strategy (1:23)
The Fixed-Time Strategy (1:21)
The Cache-Busting Strategy (4:09)
The Revalidate-Once-Stale Strategy (1:44)
Etags (4:03)
Responding to the If-None-Match Header (3:12)
The Stale-While-Revalidate Strategy (4:21)
Caching Full HTML Pages (2:28)
Responding to If-None-Match on HTML Requests (5:39)
Testing
Introduction to Testing (1:00)
Setting Up Playwright (1:59)
Writing our First Test (6:51)
Creating Dynamic Routes (7:00)
Implementing the Test Login Route (4:53)
Testing a Typical Pantry Page Flow (7:17)
Finishing up the Pantry Test (4:04)
The Playwright UI (2:22)
Creating a Delete User Test Endpoint (4:23)
Deleting Test Users (1:41)
Exercise: End-to-End Testing with Playwright
Solution
Deployment
Deployment Overview (0:44)
The Fly CLI (2:47)
Prisma MIgrations (3:27)
Creating the Database Server (3:14)
Creating the App Server (1:38)
Setting Environment Variables (3:26)
Deploying the App (1:09)
Appendix: Upgrading Remix
An Example of Upgrading Remix (13:51)
Where To Go From Here?
Thank You! (1:17)
Review This Course!
Become An Alumni
Learning Guideline
ZTM Events Every Month
LinkedIn Endorsements
Learning Guideline
This lecture is available exclusively for ZTM Academy members.
If you're already a member,
you'll need to login
.
Join ZTM To Unlock All Lectures