The Epic Stack

Kent C. Dodds
Kent C. Dodds

It's great that there are so many options in web development, but choosing between tools and frameworks can lead to decision fatigue.

Kent C. Dodds addresses this issue by introducing the Epic Stack, an opinionated yet flexible stack designed to streamline the development process.

The Epic Stack aims to strike a balance between flexibility and over-abstraction by minimizing third-party services, minimizing setup friction, and optimizing for offline development.

It's not just a project starter kit, but also a reference implementation with comprehensive documentation covering the "why and how" of each part of the stack.

Understanding the Epic Stack will equip you with a structured and adaptable approach to making more informed decisions in your development work, wheter you adopt the stack as-is or use it as a reference in creating your own!

Share this talk with your friends


Hey there Epic devs, my name is Kent C. Dodds and I am excited to talk with you about the Epic Stack. I want to make your life as a web developer epic and the Epic Stack is an important part of that. So normally before I give talks I always like to give people an opportunity to get up and

wake up their brains and get blood flowing. I'm not going to do that right here, but if you haven't moved in a little bit I want you to pause the video, move around a little bit, get blood flowing because it's an important aspect of your learning and retention. So take care of your brain. Alright I want to start with a content warning.

There's sadness ahead. So this is something that happened a few months ago a little north of me. So basically what happened is a builder was building a bunch of houses along a canyon

cliff and they just put a bunch of dirt up in one area where there wasn't enough to build a house and then they built a house on it and that dirt didn't stay put and so tragically

we have two houses that were completely destroyed due to a landslide of that dirt and it's honestly really really sad of course. Luckily nobody was hurt. They knew that these houses were going to fall over long before they did, but this is

something that I think that we're all really actually worried about as software engineers. We're not building houses necessarily but we are building applications and we're going to have to live with the consequences of our decisions for however long we're working on

the application and so while this sort of thing doesn't happen very often, so the likelihood is pretty low unless I suppose you're building on the edge of a cliff, the likelihood is relatively low but the risk is very large and we have the same sort of problem when we're making big decisions in building our applications.

We have low likelihood but high risk and that is why we struggle. Now something that is a little bit, not ironic I suppose, but interesting is this is the name of the builder that built those homes, Edge Homes. Building on the edge I guess, designed for life.

Not so sure about that, it's pretty sad. So let's talk about how this applies to us as web developers. First off I want to start off with just acknowledging how fantastic modern web development is because there are just so many awesome tools we have at our disposal to make awesome web applications.

Unfortunately it's also exhausting for the same reason and you know what was really exhausting? Putting this slide together. There's so many tools here and of course I'm not listing all of them, there's so, so many tools that you can use. Some of these things are competitors to each other so you wouldn't use them both in the

same app unless you were migrating from one to another. Some of these you absolutely would use together and you have to wire them together to make them all work together. It is, yeah there's a lot here except we are missing one, yeah I think, oh there it is.

My personal favorite, Remix has drastically simplified so much of web development in my life. But yeah, even still with all of these options it's just exhausting the amount of decisions

that we have to make and the real talk about this, the fact is that even though it is exhausting and we are concerned about making the wrong choice, the fact is almost whatever you choose will probably work out okay.

Whatever framework you use, whatever emailing client you're using, whatever template library, anything, whatever you choose, you can make it work. These tools exist because they solve real problems and they will solve those problems for you.

It will probably be fine and we all know this but still we just feel really indecisive because again the risk or the impact of a bad decision could be really big if you make the wrong choice. You have to live with that for a long time, so on the one time it will probably be fine

but on the other you have to live with it until you can migrate off of it or whatever and that's not fun either. We're worried about making a low likelihood but high risk decision like a house falling off a cliff which is just terrible, would be awful.

So once you have made the decision, we're not finished. Making the decision, that is a hard part here but it's not the only hard part. We also have to get everyone else aligned on the decision that we've made, especially when you've got junior engineers that you're trying to wrangle or senior engineers who

really like doing it the way that they've always done it. No matter where you sit on that spectrum, it can be really difficult to get everybody in line and making sure that we're all doing things in a consistent way and you don't end up with five different ways to show a modal on your page.

So even once you've done that, you're still having to wire everything together, it doesn't always work out perfectly well. Sometimes getting these tools to play nicely together can be a big challenge and really it's all just a distraction from what we're trying to do which is engage, which is just

ship our applications and that analysis paralysis that all of these decisions we have to make is just holding us back from being able to do that. So here's the deal. I've been around for a long time.

I've worked at small companies where I have been doing like small apps for a small number of users or even small companies for a medium size number of users, but I've also worked at large companies and shipped apps to millions of users all over the world and everywhere in between.

And of course in my own projects as well that get hundreds of thousands of visitors every month. So with all of that comes a lot of experience that I feel like when I see a web development problem I have a pretty good handle on good choices to make and I don't get stuck by all

the decisions I have to make and the worry that I'm going to make the wrong one and I can just plow ahead and make the right decision or a right decision and feel confident in that decision. The truth is I've got opinions that not everybody is super into and that is totally fine, but

the entire premise behind what I'm trying to tell you is that it's actually okay. Unless you're doing something morally wrong then your opinion is probably just fine. It will work out. So with that in mind I want to introduce something to you.

It's an opinionated project starter and reference and it's called the Epic Stack. The Epic Stack is first off a project starter. So NPX create epic app and you're off to the races creating an epic application with this project starter.

But it's also a reference implementation with sweet docs and so the idea is that most of us are not building new apps every single day. So as awesome as it is to have a project starter that isn't super awesome when you're slogging

through this application that's been you've been working on it for years or it's an application that's been around for decades and you're just trying to modernize it with the modern stuff. So the Epic Stack is also a reference implementation of how you do epic things for the web with

the modern tools that we have available to us and you can take a look at those. And on top of that we have decision documents where I justify the decisions that I have made as part of the Epic Stack so that you can judge for yourself whether those constraints that I'm talking about or whatever are going to work for your use case.

I feel like the Epic Stack will apply to most web developers projects but certainly there are some situations and some projects where it's not going to apply perfectly. And so having these decision documents that explain hey we chose SQLite and here's why we're doing going that direction or we chose this service for handling email and this is why we're doing that.

All of that can be really helpful as you're trying to decide should we adopt this aspect of the Epic Stack or should we just bootstrap our new app with the Epic Stack. So that's a hat tip to the Remix team that kind of tuned me into the benefit of decision documents. Super awesome.

So I want to talk also about the guiding principles that guide the Epic Stack and so if maybe we can align on some of these things then you can say hey like I feel confident that Kent and our team kind of align on the things that we feel like are important. And so here are some of those guiding principles.

First I want to limit services not just third party services where I definitely want to limit those but also even your own services. I know that the serverless architecture and mono or microservices and everything has gotten very popular and I think that it has a place in web development but I don't think that

it has a place in most of our applications. I don't feel like the microservice architecture justifies its complexity for most people and so we want to limit services. Additionally I feel really good about limiting the number of companies that you're paying for different services as well.

Like it just simplifies integrations and it simplifies the process of onboarding new people into your project of integrating these different services you're not having to wire so much together. And so as a guiding principle we're going to limit the number of services. Now we're of course like I'm not running this app in a NAS in my closet so we're saying

limit services not avoid them all together. But that is one of the guiding principles is to limit services. Another is to include only the most common use cases. So this is more along the lines of the project starter aspects of the Epic Stack.

And so the Epic Stack starter kind of gets you started with a notes taking application but most of us aren't building notes taking applications so we try to avoid going too far into building a bunch of features into that. There will be some things that are in there to be kind of an example for you but most

of it is built as an application so that it has the basic core functionality like authentication and database management and migrations and stuff like that. So want to limit the number of things that are in the project starter itself so you have fewer things to remove.

Along those lines we want to minimize the setup friction so if once you're getting started with a new application I want to reduce the number of things you have to remove but I also want to reduce the number of things you have to set up to get something deployed. And so even though we are using a service for hosting and we're using a service for sending email and different things like that I want to make it so you can actually deploy

as quickly as possible and then set up those things later on when you're ready. Another thing is to optimize for adaptability. I feel really confident in my decisions here but I understand that use cases change and the only consistent thing in our industry is the consistent change.

The constant change we're facing as web developers and so I want to be able to make it easy for you to adapt. So I want you to be able to use a different image hosting service or I want you to swap out email sending services or I want you to be able to change the way that we're doing authentication.

All of that stuff I want to make it easy for you to swap those things out while at the same time avoiding over abstraction. So this is another thing that I'm constantly thinking about as I'm developing the Epic Stack. I also want to make it so there's only one way to do something so that you don't have to make a bunch of decisions when you jump into the Epic Stack.

So we have one way to do our styling and we have one way to do our forms and all of that stuff. It's going to be just one way to do that. And then offline development is an important thing to me. I don't feel like as many people care about this as should because once you experience

the joy that is being able to turn off your internet connection and still productively develop your application, it's really really nice to do that. Not just because it's fun to go up into the mountains without an internet connection and be able to develop your application up there, which it is and I recommend it.

But the other benefit of offline development is it forces you into an architecture that makes your tests run faster and more reliably and just makes you more productive as a developer because you're not so reliant on other services to be up and running properly for you to be able to do your work.

So those are the guiding principles of the Epic Stack. Now I want to talk about a couple of the opinions that I've made. In fact, I expect some of you are really frustrated that I haven't actually told you the specific decisions that have been made because you're thinking like, oh, I want to know what these opinions are. Let's see if they align.

So here's what the Epic Stack looks like today. We have Remix. Remix is fabulous. It is the best way to build web applications that I have ever experienced. Remix is built on top of React, also the most popular web framework for a real good reason.

It's an awesome UI framework and library, whatever you want to call it. Some people call it a library. Some people call it a framework. I don't care. We're using React and it's awesome. And then here are the services that we're going to be or that we use in the Epic Stack. So is where we host our application. Fly is amazing.

You can deploy to multiple regions all over the world, have multiple instances, auto scaling, all works. But it's basically, you can think of it as serverless, but with long running servers. And so you don't have the drawbacks that come with running serverless because the thing is serverless breeds services.

You need to use more and more services if you're using serverless because so many things require a long running server, for example, a connection to a database. You need to have a long running server for that. You can't connect it on every function invocation. That would be a bad thing for performance. And so now we're going to use a service that will manage that connection for us, which is super annoying.

Or you'll just use a service for your database entirely, which, you know, that's a thing you can do. Absolutely. But as I want to limit the number of services I'm using, I like having a long running server. And the big reason why a lot of people don't like servers is because they have to manage them. Well, with, you don't have to manage them.

You still get auto scaling. You get long running servers. I love fly. I've been using them for years. They're fantastic. Fly also comes with built in support for Grafana and Sentry, which is super awesome as well. So you get some production monitoring going on in there and metrics and things.

We're using GitHub actions and GitHub for deployment, both staging and production. In the future, we very easily could have a temporary preview environment for pull requests and stuff like that. Fly is definitely capable of that. We're using Resend for sending email.

It's a really great service. And if you're not using a service for sending your emails, double check that users are getting your emails because it's just a really sad fact that if you're not building and constantly working on an email service, it's very likely that your users aren't going to get those emails.

It's just a fact of the sad world we live in. So we are using a service for emails. But again, you don't have to set it up until you're ready to actually go to production, which is nice. And then we've got Docker in here. Docker is awesome. And you don't have to touch it. You don't have to make your Docker file from the beginning. It's all generated for you.

But there will come a day where you're like, oh, I need to like have this thing installed on the box or whatever. And so you'll be really glad that you can change the Docker file when that time comes. So those are some of the things that we're using. We're also using Node.js. It's great.

And Express also works just fine. Actually, in a Remix application, you don't typically touch Express very much anyway. It's like a 500-line file that you pretty much will never touch. We're mostly working in Remix for our server-side stuff. And then, of course, we're using Tailwind because it's fabulous.

It's a fantastic way to build your styling for your application. And it comes with the benefit of not shipping like billions of kilobytes to your users of mostly unused CSS. So we're super, super fan of Tailwind. But we also have PostCSS for auto-prefixing.

And if you want to write like raw CSS and stuff like that, that could be really useful as well. And then we're using Prisma with SQLite as our database. SQLite plus is awesome because is working on a project, has released a project

called LiteFS that basically turns SQLite into something that you can do automatic backups and disaster recovery with. has this LiteFS cloud service that you can opt into and get backups. It's awesome.

And then also it makes it so you can do multi-region or multi-instance with SQLite. So even though SQLite is a file on the file system, you can still have multiple instances of your application running and all hitting a local file database. SQLite is super, super cool.

And it can definitely take you really far as far as like most applications will never grow outside of what SQLite can offer. Prisma is a fantastic ORM and makes it really easy. This is actually part of the portability or adaptability of the stack is if you do decide,

okay, we need to leave SQLite or whatever, you've got Prisma in place. And so doing that would be, will be a lot easier. I actually was using Prisma on my own website with Postgres. And when I moved over to SQLite, it was like a day. It was amazing. And Prisma made that possible. So Prisma is fabulous and handles your migrations really, really well.

I haven't seen anything as good as Prisma when it comes to migrations, it's fabulous. And then for our forms, we're getting type-safe progressively enhanced forms with Conform and Zod, two fantastic libraries that I'm super thrilled to be using in the Epic stack.

It just makes creating forms a really nice experience. So big fan of Conform and Zod. And then Radix for our reusable components and ShadCN for having them look really nice. And that's all wired up too, so you can easily install new ShadCN components and things like that.

Radix is just fabulous for accessible components. And yeah, because the web platform kind of comes short when it comes to some different components. There's a lot of work in the web platform to make common components that we need. But until then, we've got Radix and it's awesome. And then of course, we've got all the testing stuff too, testing library.

We have VTest and Playwright, super awesome testing frameworks. MSW is fantastic and FakerJS and all of those testing tools that you would expect and need in building a real application. And when you're bootstrapping a new app, it comes with all these tests.

And so if you're worried like, oh, I didn't build this, I don't know if I'm going to break it. Well, we've got tests in place so that you'll know when you're making an impact on something. And then of course, we've got the standard tools. We've got Prettier and TypeScript and ESLint and NPM, all of that stuff is all set up for you.

And so that is what the Epic stack offers as far as the tools are concerned. But then we have all the features. And I'm not going to read all of these things. You can pause the video and read through these if you want, but there's just a ton of features that are a big part of the Epic stack. So give that a look. And then we also have a bunch of examples.

And in fact, there's another example that showed up today that I forgot to add to this, but examples are constantly coming in. And so if you need to know, okay, so I'm doing single sign on with this enterprise and they're using OpenID Connect Auth.

And so I can look at the OpenID example and implement OpenID Connect. Or I'm using Socket.IO for real time stuff. We've got an example there. So examples all over the place and growing every day. So something you're not going to see in the Epic stack is more than one way to do the same thing.

And if you don't like that, if you want to do a different way to do something, then you can totally fork it and build all of your apps based off of your fork. I will not be offended. The Epic stack is really just a collection of opinions for people who are satisfied with

those opinions and want to get out of analysis paralysis land and into shipping land. So the Epic stack is a GitHub repo. You can go start it. I know that people sometimes will say, oh, stars are just a vanity metric. But the fact is that we do look at stars when we go to repos. Don't you lie to me.

You know that when you're comparing two libraries that are basically the same, you're going to choose the one that has more stars, probably. Maybe you'll look into the implementation. But the stars do matter for a lot of people. So give me a star. I would appreciate that. Help is definitely welcome, especially with regard to examples.

And we're also active in the discussions and on Discord. So come hang out with us there to both help other people and be helped as you're working and kind of evaluating the Epic stack. So I want to wrap up with just one last thing. So a couple of months ago, I was struggling with some decisions.

It was really painful. And the decision I was struggling with was what to do with Epic Web Dev. So the thing is that with Epic or with testing JavaScript, it was really easy to identify whether you're a customer of testing JavaScript because you're like, oh, I need to learn testing and I write JavaScript. So, boom, testing JavaScript. I'm a customer.

If you're hired on and you decide, oh, I'm going to be using React for this project. Oh, I need to know React, Epic React. I'm a customer. Awesome. And with web, it's just so broad that when you join a company and you say, yep, I'm going to continue being a web developer. Are you a customer of Epic Web Dev? I don't know. I'm not like maybe.

Yeah, I suppose the answer is you are, but like it was just difficult to really help people understand what the target audience was. And so that was when I realized that a big part of what I offer from Epic Web Dev is

helping people avoid the pain of making these types of decisions, these low likelihood but high impact, high risk decisions. And so Epic Web is not me teaching you everything there is to know about the web.

I'm not going to teach you every possible thing that you could do because one possible thing you could do is build a house on the edge of a cliff and it could roll off the side of the cliff. I want to teach you a recommended approach to building applications so that you can feel confident that you're going to do or have a lot of success.

And so that's where the Epic Stack came from. It was my take on how do we build an application? How do we get started? How do we build this particular feature in a way that's based on solid opinions and experience?

So that is what Epic Stack is and Epic Web has turned into how to build the Epic Stack. How does the Epic Stack work? And so everything that you learn in Epic Web is going to basically be building the Epic Stack. What has become the Epic Stack?

And that way you not only understand the fundamentals of these different aspects, like I understand now the fundamentals of authentication or I understand how to manage production database seeding or how to test this authenticated page, but you'll also have a deep understanding of how the Epic Stack works.

So if you do decide to go in that direction, you'll be very effective and efficient in working in that type of environment with those opinions. So Epic Web is basically the documentation for the Epic Stack. And what's really cool about this is that knowledge transfers really well.

So even if you're not using the Epic Stack, you can still hugely benefit from learning about it because that knowledge is so transferable to whatever it is that you actually are building. So the Epic Stack is intended to give you a firm foundation and I hope that it does that for you.

I just have one last thing for you and that is you are awesome. Thank you. See you later.

Related Talks