Scaffolding a new app
Create a brand new Remix project and add tooling for TypeScript, Tailwind and Prettier.
19 lessons · 5:00:25
- 1Scaffolding a new app12:31
- 2Creating an entry form22:49
- 3Saving new entries20:44
- Adding pending UI15:12
- Loading entries8:22
- Displaying entries by week24:09
- Creating the edit page13:43
- Editing entries9:47
- Making the entry form reusable10:20
- Deleting entries10:25
- Adding an authenticated state23:43
- Adding a logout button6:48
- Customizing the public UI5:01
- Securing our app12:58
- Customizing the error pages13:19
- Adding error messages to the login form13:37
- Mobile redesign41:57
- Desktop redesign18:46
- Deploying our app16:14
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
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
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
- Summaries with code
- Video downloads
- Working code demos
- Private Discord
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!