Scaffolding a new app

Scaffolding a new app

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

Video resources

Let's kick off our Work Journal by creating a brand new Remix app!

To start, we'll open our terminal and run

npx create-remix@latest

We'll name our app work-journal, and choose the defaults for the rest of the options:

  • Where would you like to create your app? work-journal
  • What type of app do you want to create? Just the basics
  • Where do you want to deploy? Remix App Server
  • TypeScript or JavaScript? TypeScript
  • Do you want me to run npm install? Yes

Our Remix app is ready to run! To start our dev server, we can run

npm run dev

and if we visit localhost:3000 in our browser, we'll see that our app is running, and the app/routes/index.tsx route is being rendered.

Pretty easy to get started!

Installing Tailwind CSS

Note: At the time of this recording Remix was in v1 and Tailwind support was unstable. If you're starting a new Remix app, follow Tailwind's docs for the latest instructions.

Next, let's add Tailwind to our project. At the time of this lesson, Tailwind support in Remix is not yet fully stable, but we can enable it with the future.unstable_tailwind option in remix.config.js:

// remix.config.js

/** @type {import('@remix-run/dev').AppConfig} */
module.exports = {
  future: {
    unstable_tailwind: true,
  },
};

Next, let's install Tailwind:

npm install -D tailwindcss
npx tailwindcss init

And we'll tell Tailwind where to find any utility classes we use by setting the content key of our tailwind.config.js to point to our app directory:

// tailwind.config.js

/** @type {import('tailwindcss').Config} */
module.exports = {
  content: ["./app/**/*.{js,jsx,ts,tsx}"],
  theme: {
    extend: {},
  },
  plugins: [],
};

Next, let's create an app/tailwind.css file with all the Tailwind directives:

/* app/tailwind.css */

@tailwind base;
@tailwind components;
@tailwind utilities;

then add it to our app by exporting a link to our new stylesheet in app/root.tsx:

// app/root.tsx

import type { LinksFunction } from "@remix-run/node";
import stylesheet from "~/tailwind.css";

export const links: LinksFunction = () => [
  { rel: "stylesheet", href: stylesheet },
];

Now let's restart our dev server

npm run dev

and try it out! We'll open app/routes/index.tsx, delete the default code, and add some markup that uses Tailwind:

// app/routes/index.tsx

export default function Index() {
  return (
    <div class="p-20">
      <p className="text-blue-500">Hello, Build UI!</p>
    </div>
  );
}

Everything's working! Tailwind is now set up as part of our dev server, and will trigger a rebuild any time we add new Tailwind classes to our React components.

Finally, make sure you have the Tailwind IntelliSense extension installed. It's a must-have when working with Tailwind projects.

Installing Prettier and the Tailwind CSS Prettier plugin

Next, let's add Prettier to our project.

We'll install it:

npm install --save-dev --save-exact prettier

and then create a .prettier.json file so our editor knows to use Prettier:

echo {}> .prettier.json

Now when we save, our code snaps into place.

Let's also add the Tailwind Prettier sorting plugin, which will sort our Tailwind classes according Tailwind's official recommended order, making our styling code more predictable.

We'll install it:

npm install -D prettier-plugin-tailwindcss

and now our classes re-sort on save.

Note: The video uses Prettier v2, which autoloaded plugins. Prettier v3 dropped this feature, so if you're on v3, be sure to add prettier-plugin-tailwindcss to your Prettier config.

Choosing a gray scale

Tailwind ships with five different gray scales: slate, gray, zinc, neutral, and stone. Instead of us having to remember whether we should type text-slate-500 or text-zinc-500 throughout our entire app, I like to remap the gray theme value to our chosen shade, so we can just use gray in all of our class names.

Let's go with the neutral gray scale for this app:

// tailwind.config.js

const colors = require("tailwindcss/colors");

/** @type {import('tailwindcss').Config} */
module.exports = {
  content: ["./app/**/*.{js,jsx,ts,tsx}"],
  theme: {
    extend: {
      colors: {
        gray: colors.neutral,
      },
    },
  },
  plugins: [],
};

Now let's set some global styles in our tailwind.css file:

/* tailwind.css */

@tailwind base;
@tailwind components;
@tailwind utilities;

html {
  @apply bg-gray-900 text-gray-200 antialiased;
}

And we see our new neutral gray scale has taken effect.

Prototyping the Index route

It's time to start building out the homepage of our Work Journal!

Using my personal journal as inspiration, let's write up and style a simple static version of the homepage:

// app/routes/index.tsx

export default function Index() {
  return (
    <div className="mx-auto max-w-7xl p-6">
      <h1 className="text-4xl text-white">Work journal</h1>
      <p className="mt-3 text-xl text-gray-400">
        Doings and learnings. Updated weekly.
      </p>

      <div className="mt-8">
        <ul>
          <li>
            <p>
              Week of Feb 2<sup>nd</sup>, 2023
            </p>

            <div className="mt-4 space-y-4">
              <div>
                <p>Work:</p>
                <ul className="ml-6 list-disc">
                  <li>First thing</li>
                </ul>
              </div>
              <div>
                <p>Learnings:</p>
                <ul className="ml-6 list-disc">
                  <li>First learning</li>
                  <li>Second learning</li>
                </ul>
              </div>
              <div>
                <p>Interesting things:</p>
                <ul className="ml-6 list-disc">
                  <li>Something cool!</li>
                </ul>
              </div>
            </div>
          </li>
        </ul>
      </div>
    </div>
  );
}

This is a good starting point. We can see that each entry has a different type – Work, Learning, or Interesting thing – and they also belong to a week.

We're now ready to start working on the dynamic parts of our app!

Links

Buy Ship an app with Remix

Buy the course

$199one-time payment

Get everything in Ship an app with Remix.

  • 5+ hours of video
  • 19 lessons
  • Private Discord
  • Summaries with code
  • Unlimited access to course materials

Lifetime membership

$349
access all coursesone-time payment

Get lifetime access to every Build UI course, including Ship an app with Remix, forever.

  • Access to all five Build UI courses
  • Full access to all future Build UI courses
  • New videos added regularly
  • Refactoring videos on React
  • Private Discord
  • Summaries with code

What's included

Stream or download every video

Watch every lesson directly on Build UI, or download them to watch offline at any time.

Live code demos

Access to a live demo of each lesson that runs directly in your browser.

Private Discord

Chat with Sam, Ryan and other Build UI members about the lessons – or anything else you're working on – in our private server.

Video summaries with code snippets

Quickly reference a lesson's material with text summaries and copyable code snippets.

Source code

Each lesson comes with a GitHub repo that includes a diff of the source code.

Invoices and receipts

Get reimbursed from your employer for becoming a better coder!