<!-- mobian-agent-page publisher="dailydev" canonical="https://daily.dev/posts/the-joy-of-inertia-rails-painting-your-own-with-50-happy-little-lines-martian-chronicles-evil-mart-yr6vrhqwg" -->

---
title: The joy of Inertia Rails: painting your own with 50...
description: A deep-dive into how Inertia.js works by rebuilding it from scratch: a 50-line React client and a 16-line Rails renderer that implement the full Inertia...
canonical: https://daily.dev/posts/the-joy-of-inertia-rails-painting-your-own-with-50-happy-little-lines-martian-chronicles-evil-mart-yr6vrhqwg
twitter:card: summary_large_image
twitter:site: @dailydotdev
og:type: website
og:site_name: daily.dev
og:title: The joy of Inertia Rails: painting your own with 50 happy little lines—Martian Chronicles, Evil Martians’ team blog | daily.dev
og:description: A deep-dive into how Inertia.js works by rebuilding it from scratch: a 50-line React client and a 16-line Rails renderer that implement the full Inertia...
og:url: https://daily.dev/posts/the-joy-of-inertia-rails-painting-your-own-with-50-happy-little-lines-martian-chronicles-evil-mart-yr6vrhqwg
og:image: https://api.daily.dev/og/posts/yr6vrHQWG.png
og:image:alt: The joy of Inertia Rails: painting your own with 50 happy little lines—Martian Chronicles, Evil Martians’ team blog
og:image:width: 1200
og:image:height: 630
og:locale: en
---

> ## Documentation Index
> Fetch the complete documentation index at: https://daily.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# The joy of Inertia Rails: painting your own with 50 happy little lines—Martian Chronicles, Evil Martians’ team blog

**[Martian Chronicles](https://daily.dev/sources/evilmartians)** · 17 min read · 0 upvotes · 0 comments

## Summary

A deep-dive into how Inertia.js works by rebuilding it from scratch: a 50-line React client and a 16-line Rails renderer that implement the full Inertia protocol. The post explains the core idea (render HTML on first visit, JSON on subsequent visits via an X-Inertia header), walks through each feature as a small diff on that core (deploy refresh, forms with CSRF, partial reloads, deferred props), and argues that Inertia's wire format is small enough to read in one sitting. It concludes by auditing what the real inertia-rails gem adds on top and why that complexity is worth maintaining professionally.

## Full article

daily.dev links to this article rather than hosting it. Read it at the original source: <https://evilmartians.com/chronicles/the-joy-of-inertia-rails-painting-your-own-with-50-happy-little-lines>

## Questions this post answers

### What does the Inertia.js protocol actually send over the wire between client and server?

Inertia sends a small JSON page object containing four fields: component (the name of the component to render), props (its data), url (for the address bar), and version (an asset version string). On the first visit the server returns full HTML with this JSON embedded in a script tag; on later visits, a request header named X-Inertia: true tells the server to return just the JSON.

_Developers weighing Inertia against building a separate API and router can track deep-dives like this on daily.dev._

### How do I detect a stale JavaScript bundle after a deploy in an Inertia app?

The client sends the current asset version back to the server in an X-Inertia-Version header on every request; when it doesn't match the server's current version, the server responds with 409 Conflict and an X-Inertia-Location header, and the client's only reaction is to set window.location to that URL, forcing one real full-page reload to fetch fresh JavaScript.

_Teams debugging stale deploy issues can follow Rails and Inertia patterns like this on daily.dev._

### Why does Inertia Rails redirect form submissions with status 303 instead of 302?

A 303 See Other status tells the browser to always follow the redirect with a GET request regardless of the original method, which keeps Post/Redirect/Get safe; a plain 302 would cause fetch to replay PUT, PATCH, or DELETE against the redirect target instead of a GET, so the gem's middleware rewrites those redirects to 303 automatically.

_Developers implementing form flows in Rails apps can find protocol-level explanations like this on daily.dev._

## Similar posts on daily.dev

- [2 Martians, greenfield to MVP in 4 weeks: agentic coding on Rails—Martian Chronicles, Evil Martians’ team blog](https://daily.dev/posts/2-martians-greenfield-to-mvp-in-4-weeks-agentic-coding-on-rails-martian-chronicles-evil-martians--jfk5nweey) · Martian Chronicles · 5 upvotes · 1 comments
- [Hotwire vs Inertia.js: Which One Should You Use in Rails?](https://daily.dev/posts/hotwire-vs-inertia-js-which-one-should-you-use-in-rails--es8qkwmoh) · Ruby Flow · 1 upvotes · 1 comments
- [Optimistic UI in Rails with optimism... and Inertia—Martian Chronicles, Evil Martians’ team blog](https://daily.dev/posts/optimistic-ui-in-rails-with-optimism-and-inertia-martian-chronicles-evil-martians-team-blog-jybdae5yb) · Martian Chronicles · 0 upvotes · 0 comments
- [Inertia DevTools Is Now on the Chrome Web Store](https://daily.dev/posts/inertia-devtools-is-now-on-the-chrome-web-store-c9ycd2cqf) · Laravel News · 99 upvotes · 13 comments
- [Short Ruby Newsletter - edition 167](https://daily.dev/posts/short-ruby-newsletter---edition-167-avoofdae3) · RUBYLAND · 1 upvotes · 0 comments

---

Tags: [#javascript](https://daily.dev/tags/javascript), [#react](https://daily.dev/tags/react), [#rails](https://daily.dev/tags/rails)

[View this post on daily.dev](https://daily.dev/posts/the-joy-of-inertia-rails-painting-your-own-with-50-happy-little-lines-martian-chronicles-evil-mart-yr6vrhqwg)

```json
{"@context":"https://schema.org","@graph":[{"@type":"Organization","@id":"https://daily.dev/#organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180},"sameAs":["https://twitter.com/dailydotdev","https://github.com/dailydotdev","https://www.linkedin.com/company/daily-dev-ltd"]},{"@type":"WebSite","@id":"https://daily.dev/#website","url":"https://daily.dev","name":"daily.dev","publisher":{"@id":"https://daily.dev/#organization"},"potentialAction":{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https://daily.dev/search?q={search_term_string}"},"query-input":"required name=search_term_string"}}]}
{"@context":"https://schema.org","@type":"TechArticle","headline":"The joy of Inertia Rails: painting your own with 50 happy little lines—Martian Chronicles, Evil Martians’ team blog","url":"https://daily.dev/posts/the-joy-of-inertia-rails-painting-your-own-with-50-happy-little-lines-martian-chronicles-evil-mart-yr6vrhqwg","mainEntityOfPage":{"@type":"WebPage","@id":"https://daily.dev/posts/the-joy-of-inertia-rails-painting-your-own-with-50-happy-little-lines-martian-chronicles-evil-mart-yr6vrhqwg"},"datePublished":"2026-07-14T16:39:20.440Z","dateModified":"2026-09-13T19:27:37.200Z","description":"A deep-dive into how Inertia.js works by rebuilding it from scratch: a 50-line React client and a 16-line Rails renderer that implement the full Inertia...","image":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/4e0c72984162535d8ff85cb7bdef6786?_a=AQAEuop","thumbnailUrl":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/4e0c72984162535d8ff85cb7bdef6786?_a=AQAEuop","isAccessibleForFree":true,"articleSection":"Martian Chronicles","inLanguage":"en","publisher":{"@type":"Organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180}},"author":{"@type":"Organization","name":"Martian Chronicles","logo":"https://media.daily.dev/image/upload/t_logo,f_auto/v1/logos/6334c9de96a7414ebbf4b7667ba572c5","url":"https://daily.dev/sources/evilmartians"},"commentCount":0,"discussionUrl":"https://daily.dev/posts/the-joy-of-inertia-rails-painting-your-own-with-50-happy-little-lines-martian-chronicles-evil-mart-yr6vrhqwg","interactionStatistic":[{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":0},{"@type":"InteractionCounter","interactionType":{"@type":"CommentAction"},"userInteractionCount":0}],"keywords":"javascript,react,rails","timeRequired":"PT17M"}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://daily.dev"},{"@type":"ListItem","position":2,"name":"Martian Chronicles","item":"https://daily.dev/sources/evilmartians"},{"@type":"ListItem","position":3,"name":"The joy of Inertia Rails: painting your own with 50 happy little lines—Martian Chronicles, Evil Martians’ team blog"}]}
{"@context":"https://schema.org","@type":"FAQPage","@id":"https://daily.dev/posts/the-joy-of-inertia-rails-painting-your-own-with-50-happy-little-lines-martian-chronicles-evil-mart-yr6vrhqwg#faq","mainEntity":[{"@type":"Question","name":"What does the Inertia.js protocol actually send over the wire between client and server?","acceptedAnswer":{"@type":"Answer","text":"Inertia sends a small JSON page object containing four fields: component (the name of the component to render), props (its data), url (for the address bar), and version (an asset version string). On the first visit the server returns full HTML with this JSON embedded in a script tag; on later visits, a request header named X-Inertia: true tells the server to return just the JSON. Developers weighing Inertia against building a separate API and router can track deep-dives like this on daily.dev."}},{"@type":"Question","name":"How do I detect a stale JavaScript bundle after a deploy in an Inertia app?","acceptedAnswer":{"@type":"Answer","text":"The client sends the current asset version back to the server in an X-Inertia-Version header on every request; when it doesn't match the server's current version, the server responds with 409 Conflict and an X-Inertia-Location header, and the client's only reaction is to set window.location to that URL, forcing one real full-page reload to fetch fresh JavaScript. Teams debugging stale deploy issues can follow Rails and Inertia patterns like this on daily.dev."}},{"@type":"Question","name":"Why does Inertia Rails redirect form submissions with status 303 instead of 302?","acceptedAnswer":{"@type":"Answer","text":"A 303 See Other status tells the browser to always follow the redirect with a GET request regardless of the original method, which keeps Post/Redirect/Get safe; a plain 302 would cause fetch to replay PUT, PATCH, or DELETE against the redirect target instead of a GET, so the gem's middleware rewrites those redirects to 303 automatically. Developers implementing form flows in Rails apps can find protocol-level explanations like this on daily.dev."}}]}
```

