
Explore Remix from the ground up, uncover what Remix is and why it's amazing, and preview its basics and more advanced features.
Remix builds on React to blend server-side and front-end code in the same project, enabling full-stack React apps with automatic code splitting and server-side pre-rendering for better SEO.
Explore Remix vs Next.js, comparing Remix’s always-on-server rendering with Next.js’s build-time static generation and optional per-request server rendering, discuss hosting implications and why Remix’s API feels more enjoyable.
Explore Remix routing, data fetching and mutations, layouts, styling, authentication, error handling, deployment, and practical crud examples through a complete example app.
Engage with this video on demand course by watching at your pace, coding along, and building projects; use the course slides, code, Q&A, and the Discord community to deepen learning.
Create a new Remix application, explore the generated files, and master routing and URL configuration. Learn data fetching and manipulation, styling, and metadata to build a solid, scalable Remix app.
Create a new remix project with npx create-remix after installing node.js, choose a basic remix app server with JavaScript, install dependencies, and open the project in your editor.
Explore the remix project's root configuration, package.json dependencies, and scripts, then understand how the app folder and routes define pages and how route.jsx serves as the page wrapper.
Remix file-based routing defines pages via the routes folder, with index.jsx as the starting page and demo.jsx creating a new route such as /demo.
Explore how Remix handles routing with a Link component for client-side navigation, replacing anchors to avoid reloading and balance finished HTML delivery with SEO-friendly, single-page app behavior.
Build a more exciting Remix project by adding a notes feature, creating a notes route, and implementing a notes page that displays My notes and links from the starting page.
Explore styling options in Remix apps, including Tailwind and vanilla CSS, and register global and page-specific styles via the root route and links.
Learn how to surface component styles in remix by integrating a NewNote component and CSS, using links to share styles across routes with a surfacing links approach.
Discover how to style the active link in Remix.js apps by using the NavLink component and its active CSS class in a shared main navigation placed in the root skeleton.
Learn how Remix handles form submissions by default, sending a post request from the new note form to the notes route and enabling full stack handling without client-side preventDefault.
Learn how to implement server-side form handling in remix using the action function, handling non-get requests, and storing submissions in a notes.json file via a notes.js utility.
Extracts form data in the remix action, creates a note with title, content, and an ISO id, updates notes.json via get stored notes, and redirects the user.
Fetches notes data from notes.json using the Remix loader to supply a notes prop to the NoteList component, rendering date, title, and content with server-side pre-rendering.
Fetch and render notes by making the loader async with getStoredNotes to retrieve notes.json, and pass data to the component via useLoaderData.
Learn how Remix blends backend and frontend by replacing the default HTML form with Remix's Form component to submit data, trigger actions, and fetch loaders without full page reloads.
Learn to use the useNavigation hook in Remix to disable the submit button during submission, show dynamic labels, and inspect submission details for better user feedback.
Learn to validate form input in Remix actions and return data for error messages, using useActionData and conditional rendering to show feedback without page reload.
Learn to implement a custom error boundary in Remix to replace the default error page, using the root component or route-specific boundaries with the error prop and Link.
Learn how to generate backend error responses with Remix using json, throw, and 404 status, and render them via route catch boundary and root catch boundary with useCatch.
Learn to implement dynamic routes in Remix by creating a dollar-sign file (noteid.jsx), rendering note details, and linking from the notes list with relative and absolute paths.
Fetch data for dynamic routes using Remix's loader function to load a single note from notes.json by matching the route parameter noteId, then access it in the component with useLoaderData.
Explore handling missing data in a Remix dynamic route by throwing a 404 error for a non-existent note id, triggering a catch boundary or the root error handler.
Learn to add page metadata in Remix with the meta function, setting titles and descriptions for the tab bar and search results, and understand merging with root metadata.
Master Remix core concepts, routing, dynamic routes, loaders, actions, and data fetching, while learning error boundaries and styling with the links function to build your first Remix app.
Explore deeper Remix routing and layouts, learn about routes, nested routes, and non-page routes, and practice building more complex websites with advanced yet approachable concepts.
Explore a feature-rich Remix app to manage expenses, including login and user authentication, adding, editing, deleting, exporting data, and built-in analytics across months.
Begin the Remix course project by creating a Remix project, setting up routes, and adding layouts, styles, and non-page components while repeating Remix essentials and exploring public and protected routes.
Learn to define static and dynamic routes in a Remix project, using dot notation for nested paths, including pricing, auth, and expenses routes such as raw, add, id, and analysis.
Organize nested paths in Remix by moving nested routes into an expenses folder, renaming expenses.jsx to index.jsx, and applying layout routes to load default components for each folder.
Discover Remix layout routes and how a shared wrapper with outlet supports nested layouts and shared elements across pages, such as a common header or expenses section.
Extract components and styles into the app folder beside routes, then configure routes to load shared, expenses, and auth CSS via a links function and tilde alias.
Explore wiring auth and expense components in Remix routes, render the AuthForm, Chart, and ExpenseStatistics, and set up a shared expenses layout with add and edit overlays.
Replace index.jsx and pricing.jsx with updated marketing pages using the pricing plan component and static imagery, served from the public folder with dummy data and no data fetching.
Learn how Remix layout routes enable a persistent header across pages by importing the main header into the root route and rendering it above the outlet, avoiding repeated code.
Wrap the expense form in a modal component to render as an overlay on the expenses list, using Remix layout routes to share content between add and id pages.
Learn how to add links in Remix by replacing anchor tags with the Remix link component, using the to prop and relative paths like dot dot to navigate between expenses.
Learn to use relative links with Remix's Link component, pass the expense ID as a prop, and navigate to /expenses/<id> to load the edit page.
Close modals by clicking the backdrop in Remix apps with an onClose prop. Use the useNavigate hook to programmatically navigate to the parent route.
We replace anchors with Remix links, use nav link for active highlighting and the to prop in the header, avoiding full page reloads and enabling programmatic navigation.
Explore pathless layout routes in Remix to load page-specific css without adding url paths. Wrap routes such as expenses, analysis, index, pricing, and marketing to share styles across pages.
Discover how pathless layout routes let you swap headers for different route groups like marketing, expenses, and login, load them in the app, and keep clean urls.
Explore resource routes in Remix by exporting standalone loaders that return data for a route, triggered by get requests, and accessed with useLoaderData for data-only endpoints like /expenses/raw.
explore splat routes in remix by adding a dollar sign .jsx that activates when no route matches and exposes path segments under the asterisk key in params, enabling redirects.
Explore Remix routes and learn to use URL search parameters to toggle auth form modes between login and signup, updating links with Remix Link and useSearchParams.
Enhance the expenses page in remix.js by adding an expenses-actions section with links to add expense and to load raw data.
Explore Remix features like layout routes with nested paths, pathless layouts, splat and resource routes, and programmatic navigation. Use search params to encode user interface states and link between routes.
Learn to fetch data, perform mutations, and manage loaders and actions in Remix.js, connect a real database, explore data submission without forms, and share data across routes.
Learn to set up a MongoDB Atlas database for a Remix.js project, including a free tier cluster, creating a user, IP whitelisting, and linking backend data with the frontend.
Install Prisma and connect a remix application to mongodb, configuring a schema.prisma and the connection url to manage data in remix-expenses.
Define an expense model in Prisma schema to auto generate an id, store title, amount, date, and date added with now, and map to MongoDB _id.
Add an action to a Remix route to handle expense form submissions and store data in MongoDB via Prisma, using a server-side .server.js file to keep backend logic secure.
Create a server-side addExpense function using Prisma to store a new expense in MongoDB, mapping form data (title, amount as number, date as date) after running npx prisma generate.
Implement an async Remix action to destructure the request, convert submitted formData to an expenseData object with fromEntries, call addExpense, and redirect to /expenses after creation.
Add server-side validation with a validation.server.js that checks title and amount, returns an errors object on failure, and uses useActionData to display errors without database writes.
Learn how to submit forms programmatically in Remix by using the useSubmit hook, preventing default, validating client-side, and posting data to a specified action.
Replace the regular form with a Remix form to stay in a single-page app, and use navigation to show visual feedback by disabling submit button and showing 'saving...' during submission.
Fetch expenses from the database using a Remix loader and a getExpenses function with Prisma findMany, ordered by date descending, then access the data in the component with useLoaderData.
Explore how Remix loaders return data or a json-based response, how Remix wraps raw data into a response for front-end use, and how loaders run on the back-end.
Loads a single expense by id via a dynamic Remix route, using a loader and useLoaderData to prepopulate the edit form with title, amount, and date.
Explore how nested loaders in Remix run in parallel, with the expenses loader and expense id loader executing together on reload. Learn to reuse parent route data to avoid requests.
Use useMatches to access the parent route's loader data from a child route. Retrieve the specific expense by id via the matches array and useParams to align with the URL.
Learn how to update an existing expense using a dedicated updateExpense function with Prisma, including form data extraction, validation, and redirection back to the expenses list.
Learn to delete a specific expense by using a Remix form with method delete, sending the request to /expenses/{id} via a dynamic id, and routing it to the corresponding action.
Learn how one action handles update and delete through forms in Remix, using post, patch, and delete methods. The lecture shows routing by request.method and a delete expense in expenses.server.js.
Explore behind-the-scenes submissions in Remix using useFetcher and fetcher, sending delete requests without navigation and optionally confirming user intent before proceeding.
Learn to extract the auth mode from the request URL using search parameters, retrieve form data with Remix's action function, and branch login versus signup logic in the backend.
Enhance the authentication form by using the useNavigation (or useTransition) hook to update the submit button caption to authenticating... and disable it during submission, with backend validation via action data.
Implement error handling in Remix by adding a shared Document component and root-level catch boundary and error boundary, using useCatch to display status text and messages with a fallback.
Remix's error boundary uses the error prop to implement default error handling logic when unhandled errors occur, crafting generic messages like 'failed to delete expense' to avoid exposing details.
Explore handling no expenses by returning loader data and conditionally rendering a no expenses section instead of throwing an error, and learn when to use cache boundaries to improve UX.
Learn how to handle invalid expense ids in a Remix component using useMatches, exploring options from adding a new expense to displaying an invalid id fallback.
practice time guides you to replace dummy data with actual expenses from the database, load expenses, and throw an error if none exist, shown via a catch boundary.
Practice loading expenses with a Remix loader, fetch expenses, handle missing data with a custom catch boundary, and display a chart and statistics when data exists.
Explore advanced Remix concepts by handling loaders and actions, submitting forms both traditionally and via fetcher, and sharing loader data across routes with error handling.
Explore how to implement authentication in a Remix.js practical guide, adding signup and login, managing sessions, keeping users logged in, and protecting pages and data across the app.
Continue building the Remix project from the code snapshot, set up a MongoDB backend with a .env file containing the database URL and credentials, and implement user authentication in Remix.
Learn how user authentication works in a Remix driven website, including validating credentials, signing and sending a backend session cookie, and guarding protected resources with cookie checks.
Implement authentication by adding a user model linked to expenses, enforce unique emails, and initialize MongoDB with Prisma db push. Prepare the database, create users, and secure expenses per user.
implement server-side credentials validation in a remix app by adding a validate credentials function, handling validation errors with use action data, and returning error objects to the auth form.
During signup, create a user with email and password, check for existing users with Prisma, and throw a 422 status when the email exists, kept in auth.server.js to prevent exposure.
Hash passwords with bcrypt before storing them in the database and use Prisma to create the user. Handle 422 errors with a try-catch to deliver a clear, user-friendly signup message.
Implement a login function in auth.server.js to authenticate users by email and password using bcryptjs, and throw 401 on invalid credentials; finally, create a session cookie.
Use Remix.js to create cookie-based sessions with createCookieSessionStorage, sign cookies using a secret, and configure secure, sameSite lax, httpOnly cookies with a 30-day max age in production.
Create and commit a user session in Remix.js, store the authenticated user ID in session storage, and attach a set-cookie header via redirect to enable login and access to /expenses.
Use a Remix loader to extract the user id from the session and conditionally render login or logout in the header.
Learn to implement a logout flow in Remix by posting to /logout, destroying the user session with sessionStorage, clearing the cookie, and redirecting to the home page.
Learn to protect routes in Remix.js by adding a require user session guard in loaders that redirects unauthenticated users to /auth, ensuring nested loaders also check authentication.
Protect expenses.analysis and expenses.raw routes by invoking requireUserSession in their loaders to block access when not logged in, and explain why pathless routes cannot cover them due to loader execution.
Link expenses to users by passing userId and Prisma connect, then filter expenses by userId so only the current user's data loads.
Learn how to implement authentication in Remix by creating users, validating credentials, managing cookies and sessions, protecting routes, and linking expenses to user IDs.
Explore deployment workflows for Remix apps, apply metadata and headers to routes and pages, adjust project and server configurations, and walk through a complete deployment example.
Add dynamic and static metadata to Remix routes by exporting a meta function, merge root metadata with child routes, and allow child routes to override titles and descriptions.
Explore why custom page response headers matter in Remix, how loaders and actions return responses, and how to add your own headers alongside default ones when serving pages.
Learn to attach response headers in Remix by configuring global and page-specific headers with the headers function, including cache-control max-age, and understand when to cache in development versus production.
Learn how to use nested headers in Remix to centralize cache control across parent and child routes, leveraging action, loader, and parent headers for consistent header behavior.
Explain how action and loader headers in Remix set custom response settings, including cache-control, and how headers are accessed in the page headers function during client navigation.
Learn how to disable JavaScript on select Remix pages to reduce downloads, by using a page-specific handle flag and useMatches to conditionally load scripts.
Explore the Remix config file and its key options, including ignoring dot files in routes, setting the assets built directory, and bundling server dependencies for ES modules compatibility.
Explore deployment options for Remix apps by using adapters to target different platforms, such as Netlify, and learn to copy app, public, prisma folders, and dependencies for easy deployment.
Deploy a Remix website to Netlify by syncing files, updating dependencies, linking GitHub, configuring database url and session secret, and generating Prisma before deployment.
Finish this course with a strong Remix foundation by practicing daily, building demo projects, and rebuilding course projects from memory to dive deeper into Remix and its advanced features.
Remix is a strongly growing React framework that (vastly!) simplifies the process of building feature-rich, interactive fullstack React applications and websites.
With Remix, backend and frontend code work together seamlessly, and, as a developer, you don't have to worry about managing multiple, separated projects or codebases. Instead, you implement your backend logic next to your frontend code and let Remix handle the rest.
In this course, you will learn how to build fullstack React.js applications and websites with Remix from the ground up. All key Remix concepts are covered in-depth and taught step-by-step, slowly building up on each other. By the end of this course you will therefore be able to build your own Remix fullstack websites!
As part of this course, you will build two major demo projects, including an "Expenses Management Website" where users can sign up, manage their expenses and view expense analytics. As part of this project, you will learn how to perform CRUD (Create, Read, Update, Delete) operations with Remix and how to connect your React app to a database.
The following concepts are covered in great detail in this course:
What Remix is & how it works
Remix vs NextJS
Adding routes and pages
Working with nested routes
Managing (potentially nested) layouts
Combining pages with non-page components
Styling pages and components
Fetching data (also for nested pages)
Submitting data - via forms & programmatically
Handling data submissions on the backend
Storing data in databases & fetching data from databases
Validating user input
Authenticating users (signup & login)
Managing sessions via cookies
Optimizing Remix applications
Deploying Remix applications
And much more!