---
title: 'Humid 1.0: React server-side rendering in Rails can be easy! '
teaser: 'We''re releasing Humid 1.0. A few helper methods to help with React server-side
  rendering in Rails with mini_racer. '
tags: frontend,javascript,open-source,rails,ruby-on-rails,react
author: Johny Ho
published_on: 2026-08-04
---

I want React server-side rendering to be easy. There aren't a lot of React
server-side rendering tools in the Rails world: React on Rails has the
largest presence, but it has many bells and whistles that I'm not ready for. I
could sidecar Node.js but I really don't want another piece of infrastructure I
have to manage.

I just want something simple to use and easy to get started with. So we built
it. Today we’re announcing [Humid 1.0](https://github.com/thoughtbot/humid)!

<img src="https://raw.githubusercontent.com/thoughtbot/humid/main/images/svg/humid-icon.svg" width="150" alt="Humid">

[Humid](https://github.com/thoughtbot/humid) is just a few helpers for React
server-side rendering in Rails with `mini_racer`, a minimal and modern embedded
V8 for Ruby.

Install it

```ruby
gem "humid"
```

Write your renderer and wrap it with the `setHumidRenderer` global.

```jsx
//app/assets/javascript/server_rendering.jsx
import React from 'react'
import { renderToString } from 'react-dom/server'

const Greeting = ({ name }) => <h1>Hello {name}</h1>

setHumidRenderer((json) => {
  const props = JSON.parse(json)
  return renderToString(<Greeting {...props} />)
})
```

And render it from Ruby:

```ruby
require 'humid'
require 'mini_racer'

context = MiniRacer::Context.new
server_bundle = Rails.root.join("app/assets/builds/server_rendering.js")
props = JSON.generate({ name: "World" })

Humid.prepare(context, {application_path: server_bundle})
Humid.render(context, props)
# => <h1>Hello World</h1>
```

Best of all:

1. There's no separate Node.js process.
2. It's powered by the performance of [mini_racer](https://github.com/rubyjs/mini_racer/).
3. There's nothing that Humid does that you can't do by yourself: it's less than
200 lines of code.
4. [Instrumentation](https://github.com/thoughtbot/humid/tree/main#call-humidrender) and [Telemetry](https://github.com/thoughtbot/humid/tree/main#telemetry) included.
5. You can set `Humid.prepare`'s default options with an [initializer](https://github.com/thoughtbot/humid/tree/main#configuration).

## Design

Humid is designed with two goals in mind:

1. It’s for the common case where all data is gathered before rendering. Your
application fetches everything needed, passes it as props, and Humid returns the
rendered HTML in a single synchronous call.
2. It's a stepping stone for when you want to scale on the edge using
[Cloudflare V8 isolates](https://developers.cloudflare.com/workers/reference/how-workers-works/).
[mini_racer](https://github.com/rubyjs/mini_racer) is a bare V8 environment, if
your JS bundle works with `mini_racer`, it'll work on Cloudflare V8 isolates.

## Caveats

Humid renders synchronously. It does not support streaming or async data
fetching during render. Gather your data first, then pass it as props.

`mini_racer` is a bare V8 environment: no window, no document, no Node builtins.
Your build will need polyfills or shims. Here's [a working one](https://github.com/thoughtbot/humid/blob/main/sample/shim.js) for React.

`mini_racer` is thread safe, but not fork-safe. See [guidance here](https://github.com/thoughtbot/humid/tree/main#your-webserver) for your webserver.
