That’s a Radish!

I’ve been building things on the web for a long time. My very first websites — now lost on a discarded hard drive — probably predate WordPress, which was released in 2003. Along the way, I’ve tried dozens of languages, frameworks and content management systems.

Broadly speaking, there are roughly three “eras” of build tooling I can remember.

The first was the CMS era — WordPress, Movable Type, Expression Engine. We’d run on LAMP stacks, rendering pages live from a database.

The second was the static site generator era — Jekyll, Metalsmith, Middleman. We realized our websites actually didn’t have anything that varied per request, and it was more efficient to just render all the pages ahead of time.

The final is the single-page app era — React, Gatsby, Next.js. As JavaScript frameworks matured and we started building richer web apps, developers began to use those same technologies for static websites too.

That last move has earned a lot of criticism. And it’s somewhat deserved: what is the benefit of reimplementing big chunks of what browsers give you for free for your tech blog?

But that’s only half the story. The proliferation of single-page apps has resulted in a way better developer experience. React’s component model is a significant improvement over the nested templates we were using before. CSS modules make it much easier to encapsulate elements. Having the entire npm ecosystem at your fingertips is incredibly convenient. And using linters to check your markup for a11y issues is just good for the web!

What if you could have the (lack of) runtime footprint from the static site generator era without giving up the tooling improvements from the single-page app era?

All of which is a long way of saying: I built a static site generator! It’s called Radish.

Let’s face it: web developers making static site generators is a bit of a meme. It’s a fun personal project until they get the crazy idea that it might become the next Jekyll. Why would this be any different?

Maybe it won’t be! But there are a couple reasons I’ve been really enjoying building sites with Radish:

Radish is Based on React

“Traditional” static site generators like Hugo — which I’ve used a lot and do really like — work with templates. You write HTML with placeholders for your data, and there might be some clunky ways to add logic like loops or conditions. Composition happens via “partials” and “shortcodes”, which are just nested templates. There’s no real encapsulation, especially when it comes to CSS.

With Radish, all your pages are just React components. You can keep logic in your JSX or extract it to helper functions to organize it. Composition is seamless: just import any other other components. You can write in MDX, which means you can even use components within your content. CSS modules come baked in; there’s no worrying whether two components accidentally share a class name.

At this point, you might be wondering why not just use something like Gatsby. I’ve used it before, and although it’s a bit too heavy for my taste, I could probably have gotten over that. But there’s actually one big difference…

Radish Has No Runtime

When you load a Gatsby site, you’re actually downloading a full React app to run in your browser. That’s fine if you’re building a big app with a lot of complicated UI interactions, but it’s overkill if you’re just making a small website.

That’s why Radish ships no client-side JavaScript by default. It doesn’t render markup to later bolt a React app on top. It just outputs plain HTML and CSS. This is important: it means fewer bytes sent over the wire, which means faster loading pages that consume less memory. It means you spend less time and energy reinventing things that browsers provide for free, like routing.

Let me pause here and say that I like React. My day job involves working on a React app, and so does my main side project. This article is about a React-based static site generator I built!

But React is not the solution to every problem the web throws at you. There are a ton of websites that would work great as plain HTML and CSS. For sites like that, React is actually harmful: you’re sending at least 40kb of JavaScript over the wire (not including any other libraries you’re using on top of that) and your page probably won’t be interactive until it all loads. And those libraries might not implement functionality that browsers support by default, like resetting focus when a route changes.

All that said, Radish doesn’t prevent you from using JavaScript entirely. If you import a script in one of your components, Radish will bundle all its dependencies and give you a URL that you can use with a <script> tag. It’s perfect for adding libraries or lightweight interaction. For example, this blog loads (which prefetches links so that page transitions are faster) and also has some JavaScript for the custom audio players.

More generally, I want Radish to help developers fall into the pit of success when building websites. I want a11y lining so I know I’m following best practices with regard to accessibility. I want a service worker so my site can work offline. I want the page to preload critical assets like fonts. And most critically, I don’t want to jump through hoops or go out of my way to enable these things.

As someone with a deep love for the web, I really like the Remix philosophy of learning a framework and learning the web platform at the same time. Radish isn’t a framework, but it tries to follow the ethos. There’s no magic — just HTML, CSS and a dash of web features that help your website be the best it can be.

If all that sounds interesting, please check out Radish! I really like it, and I hope you do too.