# Introduction to Remix

> An introduction to Remix, the React framework that always runs on a server. Learn to scaffold a project with create-remix and load data with loader().

Author: [Flavio Copes](https://flaviocopes.com/about/) | Published: 2021-11-24 | Topics: [React](https://flaviocopes.com/tags/react/) | Canonical: https://flaviocopes.com/remix/

With this post I want to help you get started with [Remix](https://remix.run) with my usual 80/20 approach: skip the fluff, learn the core®

What's Remix? It's a [React](https://flaviocopes.com/react/)-based framework.

Do you know [Next.js](https://flaviocopes.com/nextjs/)? Or [SvelteKit](https://flaviocopes.com/svelte-getting-started/)? Well, Remix is something like that, but with some unique features that make it an interesting alternative. But it has no static site support, so it always needs a server. 

Which makes it good for some use cases, bad for others. 

Good for use cases where you have a database, dynamic data, user accounts with private data, and so on. Like with a Rails, Django or Laravel app.

We create a new Remix project using `npx`, so we don't have to install anything or even create a folder up front.

Just to in the folder that contains your projects (it's usually `dev` or `www` for me) and type

```sh
npx create-remix@latest
```

![Terminal prompt asking to install create-remix@latest package with Ok to proceed confirmation](https://flaviocopes.com/images/remix/Screen_Shot_2021-11-23_at_18.01.31.png)

Choose the folder you want to install to:

![Remix project setup asking where to create the app with my-remix-app folder suggestion](https://flaviocopes.com/images/remix/Screen_Shot_2021-11-23_at_18.01.57.png)

Pick the Remix App Server option, which is the built-in server (you can change that later):

![Remix deployment target selection menu showing Remix App Server as the selected option](https://flaviocopes.com/images/remix/Screen_Shot_2021-11-23_at_18.02.05.png)

Pick [JavaScript](https://flaviocopes.com/javascript/), or [TypeScript](https://flaviocopes.com/typescript/) if you prefer:

![Language selection prompt with TypeScript and JavaScript options, JavaScript is selected](https://flaviocopes.com/images/remix/Screen_Shot_2021-11-23_at_18.02.13.png)

Make sure you tell the installer to run `npm install` so that it can set up everything for you:

![Terminal showing npm install confirmation prompt with progress bar and Yes answer selected](https://flaviocopes.com/images/remix/Screen_Shot_2021-11-23_at_18.02.48.png)

Then `cd <foldername>` and run `npm run dev`.

![Terminal output showing Remix development server starting and running at localhost:3000](https://flaviocopes.com/images/remix/Screen_Shot_2021-11-23_at_18.04.17.png)

It's always nice to look at the result of the default installation:

![Remix starter page in browser showing Welcome to Remix with demos and resources sections](https://flaviocopes.com/images/remix/Screen_Shot_2021-11-23_at_18.06.52.png)

The code that generates this is this:

![VS Code file explorer showing Remix project structure with app, build, node_modules folders and config files](https://flaviocopes.com/images/remix/Screen_Shot_2021-11-23_at_18.11.35.png)

But we're only actually interested in the `app` folder, the rest is boilerplate/configuration:

![VS Code explorer focused on app folder showing routes, styles, and entry files structure](https://flaviocopes.com/images/remix/Screen_Shot_2021-11-23_at_18.13.05.png)

Let's analyze that.

We have 3 files in the `src` folder: 

- `entry.client.jsx`
- `entry.server.jsx`
- `root.jsx`

Which are used to set the overall site functionality, including the HTML output for all pages. They're the ones that if you touch them, the entire app will be affected. And that's where error handling happens, which is a first-class aspect in Remix, which is kind of cool.

Then we have a `routes` folder with an `index.jsx` file, and a `demos` folder which contains a few demo applications.

Let's start with `routes/index.jsx`.

It's a long React component:

```jsx
import { useLoaderData, json, Link } from "remix";

// Loaders provide data to components and are only ever called on the server, so
// you can connect to a database or run any server side code you want right next
// to the component that renders it.
// https://remix.run/api/conventions#loader
export let loader = () => {
  let data = {
    resources: [
      {
        name: "Remix Docs",
        url: "https://remix.run/docs"
      },
      {
        name: "React Router Docs",
        url: "https://reactrouter.com/docs"
      },
      {
        name: "Remix Discord",
        url: "https://discord.gg/VBePs6d"
      }
    ],
    demos: [
      {
        to: "demos/actions",
        name: "Actions"
      },
      {
        to: "demos/about",
        name: "Nested Routes, CSS loading/unloading"
      },
      {
        to: "demos/params",
        name: "URL Params and Error Boundaries"
      }
    ]
  };

  // https://remix.run/api/remix#json
  return json(data);
};

// https://remix.run/api/conventions#meta
export let meta = () => {
  return {
    title: "Remix Starter",
    description: "Welcome to remix!"
  };
};

// https://remix.run/guides/routing#index-routes
export default function Index() {
  let data = useLoaderData();

  return (
    <div className="remix__page">
      <main>
        <h2>Welcome to Remix!</h2>
        <p>We're stoked that you're here. 🥳</p>
        <p>
          Feel free to take a look around the code to see how Remix does things,
          it might be a bit different than what you’re used to. When you're
          ready to dive deeper, we've got plenty of resources to get you
          up-and-running quickly.
        </p>
        <p>
          Check out all the demos in this starter, and then just delete the{" "}
          <code>app/routes/demos</code> and <code>app/styles/demos</code>{" "}
          folders when you're ready to turn this into your next project.
        </p>
      </main>
      <aside>
        <h2>Demos In This App</h2>
        <ul>
          {data.demos.map(demo => (
            <li key={demo.to} className="remix__page__resource">
              <Link to={demo.to} prefetch="intent">
                {demo.name}
              </Link>
            </li>
          ))}
        </ul>
        <h2>Resources</h2>
        <ul>
          {data.resources.map(resource => (
            <li key={resource.url} className="remix__page__resource">
              <a href={resource.url}>{resource.name}</a>
            </li>
          ))}
        </ul>
      </aside>
    </div>
  );
}
```

Now,  this file could be simplified down to a super simple React component like this:

```jsx
export default function() {
  return (
    <div className="remix__page">
      Test
    </div>
  );
}
```

and if you do so and save the file, you'd see this in the app:

![Simple Test page displayed in browser showing minimal Remix component output](https://flaviocopes.com/images/remix/Screen_Shot_2021-11-23_at_19.23.22.png)

But this file is doing something more than just outputting some JSX. It's loading data on the server-side, via the `loader()` function:

```jsx
import { json } from "remix";

export let loader = () => {
  let data = {
    //.... some data
  };

  return json(data);
};
```

`json()` is a special utility to easily create a [JSON](https://flaviocopes.com/json/) endpoint that Remix will then call when the page loads, to fill it with the data it needs.

This `loader()` function is called before rendering, and only runs server-side.

To use this data in the component's JSX, we must import and call `useLoaderData()`:

```jsx
import { useLoaderData, json } from "remix"

export let loader = () => json({
    name: 'Flavio'
})

export default function() {
  let data = useLoaderData()

  return (
    <div className="remix__page">
      Hi {data.name}
    </div>
  )
}
```

![Browser showing Hi Flavio message demonstrating loader data being displayed in Remix component](https://flaviocopes.com/images/remix/Screen_Shot_2021-11-23_at_19.23.06.png)

The file also has a `meta()` function exported, which is used to set the page HTML head's meta data.

Routes are where the "meat" happens in Remix. Which is understandable since it was created by the people that made React Router, so the router is the center part of the app.

The official tutorial already talks about creating custom routes and handling forms, so I won't go in more details about that now.

I suggest you to take a look at that, especially at forms.

Why? Because forms are a big pain in React, so it's nice to see this very simple approach at allowing you to create forms without having to write lots and lots of boilerplate code.

I think that's the nicest part of Remix and I'd consider using this if I want to have a site with first-class forms, to avoid using libraries that I need to learn from scratch and are another dependency to worry about.

Another interesting thing is child routes, and how that basically replicates what we used to do with Ember and its outlets in the pre-React days, and it makes sense since I remember Ryan Florence being active in the Ember community back in the day.

And it's great to see progress in a field that has not seen any big incumbents, where Next.js is basically the elephant in the room and it's the thing I've defaulted to so far when it comes to writing an app.

And I'll still default to that for the time being. I like new tech, but it also takes a long time for it to become mature, have people write libraries, tutorials, etc etc.

But competition fosters innovation, so it's always good to have an option that is peculiar enough to not be a copycat of existing alternatives.
