Blitz.js - The Fullstack React Framework

Blitz is a hyper productive framework for building fullstack React apps. You'll learn why I created Blitz, it's advantages and disadvantages, how it makes you so productive, and for what cases you should consider using Blitz.


Transcript


Intro


Hello everyone, it's so exciting to kick off the second day of React Summit. We had awesome talks yesterday, and I'm excited to talk this morning about Blitz and building fullstack React apps. So let's get into it.


Brandon's experience building fullstack React apps


I was building fullstack React apps for a few years, and I happily put up with the complexity and struggle required to do so. And I did that because I loved building user interfaces with React more than any other way. But the honeymoon ended and I became increasingly frustrated with REST, with GraphQL APIs, MobX-State-Tree, and a host of other API services and libraries, managing multiple servers, multiple deployments, et cetera. Anything that got in the way of me building features slowly depleted my morale.

I really wanted to love fullstack web development again. I wanted to be extremely productive again at building fullstack apps. I wanted to focus on building features instead of mostly marshaling data all around the universe.

So I decided enough was enough and I set out to build the best possible developer experience for fullstack React apps. Well, there were two fundamental things that I had to have in place to achieve the developer experience that I wanted.

Number one, I had to be monolithic. And a monolith means that there's only one thing. Everything is all together in one thing. So there's only one thing to develop, there's only one thing to deploy, there's only one thing to reason about as you think about your entire architecture. And a monolith is really awesome. And in my experience with Ru on Rails, I came to really appreciate the benefits of a monolith.

Secondly, it is no API. The API layer in React apps is the biggest source of complexity, headache, heartache, holes in the wall. Oh, well, Brandon, that's too much. It slows you down more than you would think about. And I knew that I had to go somehow.

Okay, Brandon, that sounds great, but how are we going to do this?


What is Blitz.js? 


Well, does it mean we have to go back to 2004 and do server-side rendering? I thought so. And I was prepared to embrace that because I wanted this developer experience without the API so bad that I was willing to go down that route. And in fact, when I first announced that I was working on Blitz, the initial prototype was server-side rendered. But the early Blitz contributors and myself were trying to figure out what the architecture of Blitz really would look like? We were exploring all sorts of things, model view controller, basically everything under the sun.

And so one day I was laying in a hammock in Thailand thinking about this and I asked myself, "What would this look like if it was easy?" So I thought about that for a bit and I realized that if it was easy, you could write functions that run on the server and then import them directly into your React components and use them directly. So you could use them without doing fetch calls or API endpoints or HTTP or any of that. It would just work. And so I was like, "Well, wow, that's pretty awesome. Like this could be a game changer." And turns out it was.

Okay, so now you know about the single biggest defining factor of what Blitz is. So let's talk about the second two.

I mentioned that I was just frustrated with fullstack web development with React, but throughout that entire time, there was one thing that constantly shone through the mess, and that was the Next.js.

Next is such a wonderful framework. It's so fast and flexible and it's a nice developer experience. And so it was so clear that it was a perfect thing to build on top of and add all the other things that you need for a fullstack web development.

Okay, so now we need a way to talk to the database. And back in February when I started Blitz, Prisma 2 was just coming out in beta, and it was just pretty obvious that this was going to be the modern way to access databases. And if you don't know about Prisma 2, it's awesome because you have a really nice schema that you can define and have declarative migrations from that schema. You generate a TypeScript client from that schema. And so you have fully typed database access. And then in Blitz, those types can flow all the way down to your front end. So everything is fully typed into end.


Foundational principles of Blitz.js


All right, so those are the three key factors of what Blitz is. Let's talk about the seven main fundamental features and principles that define everything else we do.

All right, fullstack and monolithic, I touched on that. One thing I wanted to mention is that a modern monolith scales much better than like Ru on Rails, for example. And that's because you can deploy Blitz to a serverless environment, not just a server. You can do both, but if you deploy serverless, all your server endpoints can be independently scalable as serverless functions. And so the whole scaling thing with a monolith just sort of goes away. So that's really awesome. Secondly, API not required. Number three, convention over configuration. Number four, loose opinions compared to strong opinions that are hard to go against. Number five, easy to start, easy to scale. Number six, stability. And number seven, community over code.

Okay, so let's talk about this API layer a bit and get into how we actually do this and how it works.

We abstract the API into your compile step. So as you're developing your app, like I mentioned, you don't do any API stuff. You just import the server functions into your front end, and then at compile time, we swap that out with an HTTP API. And so you do get client side rendering, but without any of the API headache.

And how you do that in a Blitz app is what we call queries and mutations. Now, this has nothing to do with GraphQL. We just use the same nomenclature, and they're just plain asynchronous JavaScript functions that always run on the server. If you're familiar with Ru on Rails or Laravel controller concept, what is basically replaced queries and mutations.

Now, of course you can always add an API to a Blitz app because there's zero restrictions that we give you. So we're 100% compatible with Next.js. And in fact, we have less restrictions than Next.js does. So you don't have to worry about Blitz getting in your way.


How does Blitz.js work? 


All right, so let's look at our architecture diagram here to maybe give you a rough idea of how this all fits together.

So along the top is client-side code, along the bottom is service-side code, and the purple boxes are pages, React pages. And so you can see that in a single app, you can have a server-side rendered page and a client-side rendered page side side, and they can use the same server code. So the green boxes at the bottom are a query and a mutation, and both of those pages use that same query. And then at build time, this middle layer is inserted automatically for you, which is a JSON HTTP API. So all your queries and mutations are exposed at a unique URL, and you can use that directly from mobile apps or third parties or anything else.


Convention over Configuration


Okay, let's talk about convention over configuration. This means default things just work. And it doesn't mean no configuration. It just means configuration is optional.

So most of the boring stuff is completely done for you out of the box. And this is especially... You especially get to see a lot of this principle whenever you generate a new app. And because it has so much stuff set up for you, basically all the things that you would set up, you would take like the first week or so of a new project and set up, all that's done. So we include ESLint, Prettier, Jest, Husky Git hooks and a number of other things just already set up for you.

Now, the big thing that's really, really awesome is authentication and authorization set up in new apps default. So that means when you run Blitz new in your app name and generate a new app, you can immediately sign up and log in as a user. And isn't that amazing? Like you don't have to ever do authentication stuff for so many projects because you get out of the box with Blitz.

And then if you want to add social login, we have a Passport.js adapter that you can just drop in on a single file and very easily add in like GitHub authentication or any other type of a thing that... Anything there's a Passport.js adapter for.


Getting into some Code


Okay, let's get into some code.

All right, so this is a sign up mutation that always runs on the server. And basically the same thing is what you'll get in a new app default. This will be generated for you. So you can see we export a default asynchronous function, and the first argument to that is the arguments to the mutation, and the second is a context parameter. And this context parameter is provided Middleware and Blitz. And so default, you have one Middleware configured, which is session Middleware, and that's built in session management from Blitz.

Okay, and so inside this mutation, the first thing we're going to do is validate the input. And we use a library called Zod that's really awesome for both the runtime validation and TypeScript types. So you're guaranteed that after this line, email and password are both strings and the password has a minimum length.

Okay, and then we're going to hash the password and then we're going to create a user in the database. This DB object is provided Prisma 2. And so you can see how nice it is just to create a user, set the email and password and you get that user back. And then secondly, the last thing we do before returning is to create a new session, which is how you log in, and you can set the user ID, roles, anything else you need in there to use on the front end. Fairly simple.

Now, how do we use this? Well, you import this direct function into your component. 

And so here is the signup form, and you can see we import... It's on the fifth line, I believe, we import that function that we were just looking at and we pass it to the user mutation hook inside the component. Okay, and then we can just use that mutation thing inside the hook. And so you just call it just a weight, just like a regular function there, and it just all works for you. So super slick.

All right, let's look at another one.

This is a git project query. And so you can see again, when we get some inputs and then the context parameter. And the first thing we do in this case is called session.authorize. And this is going to ensure that the user is logged in. If he's not it'll throw an error and that error will propagate all the way to the front end and it will show either a login form if they're not logged in, or it'll show an unauthorized page if they don't meet the required role. And of course you can customize that whatever you want, but that's the default setup. So we find the project and if we don't get the project and we throw a not found error. And again, that propagates to the front end and shows the 404 page.

All right, so let's use this thing. We simply import this function over into your component.

And inside this project component, the first thing we do is get the parameter from the route. So this is project ideas, a dynamic parameter that you get from the URL. And then we have a useQuery hook that you pass that query function we were just looking at. You pass it to useQuery. And then the second parameter to that is the argument. So where ID is equal to the ID of this route. And then you get that back and you just render it.

Now, one thing to note here is we have concurrent mode enabled in Blitz apps default. And so you're using suspense, which is really awesome. So you can see in this component, we don't have this entire else dance of if loading, show the loading, if error, show the error, if something else, show something... Whatever. It's just very simple. So it's really cool. And then in the page component toward the bottom half of the screen you can see we have the suspense component and the fallback or the error. And so really nice API. useQuery is built on top of React Query, and a React Query provides a ton of awesome stuff that you get default in here like caching all your server data, caching validation, polling, all these sorts of things. Really powerful features. And you just get it default.


Getting started with Blitz.js


Okay, so how do you get started with Blitz? Well, it's pretty hard. There's only two commands.

And first thing is install Blitz globally as a CLI. And then secondly is run Blitz new and pass it the name of your app. And that's it. And it'll just generate your app for you, install your dependencies and so forth. And then, like I mentioned, you can immediately sign up and log in as a user. And it's awesome.


Community over Code


All right, let's talk about community over code. So this is one of our foundational principles. People are far more important than anything else. And these are principles that we hold dearly in the Blitz community, but it's also principles that we as a tech community at large should really embrace and live . Secondly, we treat every person with dignity and worth regardless of who they are, what their beliefs. Every person is worthy of dignity and worth. We're all in this together. We all want to be productive, we all want to have fun in our jobs, and we're all more similar than we are different. So we can and should solve problems together.

We have an entire page on our documentation linked here that details how the Blitz community operates. We'll go through pretty much everything. And so you can get a good idea like if you want to be involved in the Blitz community or not or you just want to see how things operate, that's a good place to do so.


Contributing to Blitz.js


Okay, now let's talk about how you can contribute to Blitz. So we need your help. We love all the help we can get. We have a bunch of features in GitHub that are ready to work on, but they're just sitting there waiting for somebody to work on them. I'm working mostly full-time on Blitz and then doing consulting on the side. So far I'm contributing far the most, but we'd love anyone else to help in their free time as much as they can. We appreciate any type of contribution, whether it's code, documentation, improving documentation, tutorials, videos, blog posts, anything you can think of.

Secondly, donations and sponsorships. It's my goal to work full-time on Blitz without having to do consulting on the side. And then beyond that, I would love to pay other people to work on Blitz full-time too. So would love any type of donation or sponsorship that you can give us through GitHub. There's a button on our GitHub repo. And then secondly, the best place to get started here is the blitzjs.com documentation, which is linked here.


Links


Okay, so this concludes the end of my presentation. blitzjs.com is the best place to go to get started there. You can follow me at @flybayer on Twitter and @blitzjs on Twitter as well. And so I would love to answer your questions now and anytime later on Twitter. Anything, like just reach out. Happy to help answer questions. And I'd love for you to try out Blitz and then let me know how it goes. Thank you so much.

Brandon Bayer
32 min

Check out more articles and videos

Workshops on related topic