First impressions with Remix

Warning: This post is a train of thoughts. At one point, I start ranting. Later, I eat my own words. Enjoy the ride. 🚂

Previously, I tried and didn't quite like Blitz.

New day, new kid on the block. Remix is a full stack framework for building web applications using JavaScript. The contributors are some of the bigger names in the community. The website looks promising. Let's give it a go.

Getting started is fairly simple:

$ npx create-remix@latest
$ cd my-remix-app
$ npm run dev

The initial project skeleton offers some ideas of what it's about:

$ tree -I "node_modules|build"
├── app
│   ├── entry.client.tsx
│   ├── entry.server.tsx
│   ├── root.tsx
│   ├── routes
│   │   ├── demos
│   │   │   ├── about
│   │   │   │   ├── index.tsx
│   │   │   │   └── whoa.tsx
│   │   │   ├── about.tsx
│   │   │   ├── actions.tsx
│   │   │   ├── correct.tsx
│   │   │   ├── params
│   │   │   │   ├── $id.tsx
│   │   │   │   └── index.tsx
│   │   │   └── params.tsx
│   │   └── index.tsx
│   └── styles
│       ├── dark.css
│       ├── demos
│       │   └── about.css
│       └── global.css
├── package.json
├── package-lock.json
├── public
│   └── favicon.ico
├── remix.config.js
├── remix.env.d.ts
└── tsconfig.json
8 directories, 22 files

So: TypeScript, npm, regular CSS files. client and server entrypoints. Dynamic parameters via $id in the filename.

Looks sensible, but first reaction is if this is a full-stack framework, where is the database? Maybe it's not "that" kind of full-stack.

No tests either, for probably the same reason: you can't satisfy everyone in the JS community. I was complaining about Prisma being a default in my Blitz post, so maybe it's better this way.

SPA woes

Isomorphic React is used for writing the templates, which I like. JSX is still my preferred DSL for writing views, because it's not really a DSL.

What I like less and warning, this may come across as incredibly weird is that after I added a new route to /posts, and the application did a pleasant refresh on its own, clicking on the new link triggers a client-side route navigation.

Yeah, I know, why am I complaining about a React application behaving like a single page application? Because I'm still holding out for the hope that, one day, someone marries the developer experience of using React with optional client-side rendering by default.

What am I on about? Single language, sane componenting, a good DSL for views, hot code refreshes, predictable UI, types and props, pure functions, scoped/purged/shaken/stirred CSS, but without a 200KB bundle. The accepted default nowadays is that every application should start out as a single-page application. After years of trying to make that work, I now firmly believe it is the wrong one. Client-side rendering should be opt in.

Next.js, the current favoured server-side React framework, does allow disabling runtime JavaScript since a little while ago. I use this feature right here on this blog. You, the user, would gain nothing from being able to transition to the homepage of this blog without a request to my server. The pages load instantaneously. A properly oiled, cached, statically rendered multi page application is virtually indistinguishable in practice from a SPA, for most use cases. But it is so much easier to build and run.

Well right, back to Remix, not to another rant about SPAs. Maybe I'll find a way to disable JS later.

MVCing in the view

Pretty soon into the tutorial, I'm mixing controller fetching logic right in the view, executing code on both the client and the server to load a couple of posts.

This is great, and it demonstrates why jsx is such a good language for writing views and view-related glue code. Sure, it's not testable/maintainable to do this forever, so of course they immediately show you how to abstract that away into a proper model. But the fact that you can just prototype it so easily before that is great.

Next up is a bit about reading markdown frontmatter using Node.js which honestly feels a bit out of place and not really Remix specific. I didn't bother implementing it as I didn't see what I'd gain. I caught on quite late that the point of the tutorial is to implement a simple blog with Markdown posts. The tutorial doesn't explicitly mention it at the start, but "Developer blog" is the title of the guide that I could have noticed earlier.

CSS doesn't seem to be undergoing any special treatment, unlike styled-jsx in Next.js and other similar frameworks. Just Webpack module-style imports. Purging is left to the reader. Fair enough. There's so many ways to do it, this seems like a sensible decision.

Finally, some action

Getting to the Actions section, and building forms. Yes. I fscking love forms, and it's refreshing that so do the Remix devs.

And holy smokes, they actually work without JavaScript! And it has errors that ALSO work without JavaScript. Dear God, finally. I've been wanting this for ages.

I like the design of the route action API. Not magical, colocated with the view. Trivial to test, just a pure function. Really smart.

Then the tutorial ends. The next thing I went looking for is some configuration flag to completely switch off client-side JavaScript in the production app, while maintaining it for hot code reloading and other development concerns.

I found that the other tutorial, the Jokes app, does have some database setup instructions. I still don't know if I like Prisma, but it's a choice. Props for showing users of the framework how to do it regardless.

And I found what I was looking for as well! Clean, clear instructions for how to run a Remix project without client-side JavaScript:

Did you notice that our app isn't loading any JavaScript before now? 😆 This actually is pretty significant. Our entire app can work without JavaScript on the page at all. This is because Remix leverages the platform so well for us.

Wow. All you do is just add or remove <Scripts /> from the root component. And it's in the official docs, not a hack.


Upon reviewing my earlier rant, I can confirm that Remix does in fact tick every single box I mentioned that I was looking for. The day I was holding out for has come.

For the first time in a long time, I actually feel an itch I haven't felt in a while. That I want to take this tool and use it to build cool shit in my spare time.

Chapeau bas. Good job, Remix devs.