The Modern View Layer Rails Deserves: A Vision for 2025 and Beyond


Summarized using AI

The Modern View Layer Rails Deserves: A Vision for 2025 and Beyond

Marco Roth • July 10, 2025 • Philadelphia, PA • Talk

Introduction

The Modern View Layer Rails Deserves: A Vision for 2025 and Beyond is a talk presented by Marco Roth at RailsConf 2025, examining the current state and future potential of Rails view layer. The talk addresses how Rails' approach to server-rendered HTML and its templating system (primarily using ERB and Action View) has remained largely stable since inception. However, modern web development demands more reactivity, developer tooling, and seamless integration with advancements in front-end technologies.

Key Points

  • Historical Overview of Rails View Layer

    • Outlines the evolution of Action View and ERB in Rails, highlighting key improvements and additions since 2004, such as partials, layout support, and enhanced helpers.
    • Emphasizes the stability of Action View and ERB, with mostly additive changes and minimal breaking updates.
  • Challenges with the Current View Layer

    • Modern frontend expectations (complex UI, reactivity, robust tooling) outpace what Action View and ERB currently offer.
    • Existing solutions for challenges like componentization, encapsulation, and testing in Rails are often reliant on third-party libraries.
    • Tooling support for HTML ERB files lags behind JavaScript frameworks, both in diagnostics and developer experience.
  • Inspiration from the JavaScript Ecosystem

    • Noted for world-class tooling (e.g., Vite) offering immediate feedback, refactoring, and strong integration in editors.
    • Rails tools (Ruby LSP, etc.) have made progress, but HTML ERB templates still lack comparable support.
  • Introducing Herb: A Tooling Ecosystem for Rails Views

    • Herb is a new HTML-aware ERB parser, formatter, and linter designed for ERB files, written in C, leveraging the Prism Ruby parser.
    • Builds a unified syntax tree combining HTML and Ruby, supporting complex template structures and relationships (e.g., linking if/end blocks in ERB).
    • Tools in the Herb ecosystem include:
    • Formatter: Ensures consistent, automatically formatted view files.
    • Linter: Enforces view best practices, stylistic rules, and accessibility directly in the code and editor.
    • Highlighter: Syntax highlighting for ERB templates in terminal and editors.
    • Rewriter/Refactorer: Enables safe, automated refactoring of view code (e.g., replacing tags, sorting attributes).
    • Printer and Language Server: Enables conversion between parsed AST and source, provides deep editor integration for instant feedback and diagnostics.
    • Early integration with VS Code extension and possibilities for broader editor support.
  • Vision for the Future: The Herb Engine and Reactive Rails Views

    • Proposes a new HTML-templating engine for Rails that ensures only valid HTML is rendered, catching errors at compile-time.
    • Potential for LiveView-style reactivity in Rails: changing server-side data seamlessly updates only the relevant parts of the DOM, blurring lines between traditional server-rendered and client-reactive approaches.
    • Progressive enhancement via an ".herb" extension for files opting into stricter, reactive, or even client-side capable templates.
    • Envisioned capabilities include stricter error feedback, static analysis for accessibility, more efficient template compilation, and safe integration with external JS components or UI kits.

Conclusion / Takeaways

  • Rails view layer is foundational, but modernization is needed in tooling, reactivity, and developer experience.
  • The Herb toolset aims to bring advanced, integrated developer tooling to Rails views, making development as seamless as leading JS frameworks.
  • A new, stricter, and potentially reactive ERB engine could enable more maintainable, performant Rails applications without sacrificing its "HTML-over-the-wire" philosophy.
  • The vision is evolutionary, offering progressive adoption and backwards compatibility, to empower Rails developers with the tools they deserve for modern web development.

The Modern View Layer Rails Deserves: A Vision for 2025 and Beyond
Marco Roth • Philadelphia, PA • Talk

Date: July 10, 2025
Published: July 23, 2025
Announced: unknown

Rails revolutionized web development and continues to evolve, but its view layer has remained largely unchanged while frontend needs have evolved dramatically. Rails has maintained its relevance by adopting technologies like Turbolinks and now Turbo/Hotwire while preserving its core principles.

But today's developers face challenges the current view layer wasn't designed to solve: complex UI interactions, reactivity, robust tooling for large codebases, intergration with modern UI kits, and modern tooling expectations.

This talk explores how a new HTML-aware ERB parser (Herb) could enable a truly reactive Rails view layer, bringing LiveView-style reactivity while preserving the "HTML-over-the-wire" philosophy. It will integrate with existing LSPs, unlock powerful tooling, and enable reactive server-rendered templates that could be reused client-side.

I'll demonstrate what's possible through proof-of-concepts and early prototypes, showing how we can collectively advance Rails views for modern development.

RailsConf 2025

00:00:17.440 All right. Well, it's super exciting to be here. I'm really happy to be speaking at the final Railscon. It's such an
00:00:24.240 honor. And yeah, my name is Marco. I am a fullstack developer and open source
00:00:29.359 contributor. I love open source. I have been trying to help with maintaining
00:00:36.960 stimulus reflex and cable ready in the hot wire ecosystem and I've been on and off maintaining stimulus as well. The
00:00:44.640 last few months not so much anymore but I still keep an eye on the repo. But
00:00:49.680 today I want to talk about the rails view layer and more specifically action view.
00:00:55.840 So action view was first introduced in 2004 with the actual first release rails05
00:01:01.359 and it was part of this MVC framework but back then it was action pack that
00:01:07.040 was containing both control and the view part of that stack but we were already using ERB at the
00:01:14.640 time and ERB stands for embedded Ruby which means that we just have templates
00:01:21.040 and plain text files sprinkled with Ruby embeddings inside of
00:01:27.040 With Rails one in 2005, we got layouts and partials, which we already know and love and still use today. And in 2007
00:01:35.280 with Rails 2, we got the new HTML ERB file ending that we also still use
00:01:40.640 today. This replaced the RHTML um file ending from back then.
00:01:46.560 With um Rails free, we got HTML autoscaping and also the output safe
00:01:52.079 buffer from um in action view which meant that you didn't have to use the age helper anymore to render user
00:01:58.960 provided content to the um browser. We also got action view templates um
00:02:04.960 from the merge which provide a unified interface for um different file
00:02:10.640 handlers. You could kind of think of this as for ERB, for builder, for slim, for hammer, all of those kind of one
00:02:16.959 interface to handle them all. With race for one, we got action view variants,
00:02:22.239 which allows us to specify different variants for the same view, like the
00:02:27.599 mobile one or web one or a printer one, whatever you might fancy. And you also got the action view
00:02:33.840 extracted as its own gem for the first time in this release. With R 5.1 we got formwith still a well-known helper today
00:02:42.080 still quite useful and with 61 we got this very special
00:02:47.760 action component approach that was land in the beta early version of six rail 61
00:02:54.319 which then turned to be um view component Joel was kind of talking about this in
00:03:00.319 this talk in railscon 2019 and he was kind of explaining why this
00:03:05.599 is needed why it doesn't make sense and what is improved and what the issues are with action view.
00:03:11.280 Action view component didn't make it into Rails, but we got this render in um API that is actually useful for just
00:03:19.120 giving any class or any object the possibility to be rendered by Rails.
00:03:24.239 With Rails 7, we got hot by default. And with 7.1, we got partial strict locals,
00:03:31.200 which are the views um helpers or kind of the magic comment at the top of a
00:03:36.640 partial to kind of um define the templates or the the API for this
00:03:42.720 partial. But all in all, I would say this has been really stable. There hasn't been
00:03:48.080 too many changes to this whole um framework. There have been a lot of
00:03:53.120 things happening under the hood to make it more performant to make it more reliable. But most of these fe features
00:03:59.120 were additive not really like breaking which makes it really easy easy to rely
00:04:04.159 and build on but also means that there were a lot of other approaches that were
00:04:09.200 happening in the same time but still rails was always about server rendered
00:04:15.200 HTML and action view isn't going anywhere. Action view is here to stay
00:04:20.560 and so is Erb. And I just think it's as pure as it gets when it comes to
00:04:25.680 templating that you could just see the HTML next to your ear like Ruby snippets. And this is just the most
00:04:32.960 straightforward I can think of. Which means that the advanced tooling that we need is getting more important
00:04:39.199 especially now with hot wire being the default in Rails. We want to have this built in into the default like tooling
00:04:46.240 stack. In the last Rails survey, we also saw that Stimulus kind of rose up to the top
00:04:52.160 as the number one framework in the Rails um ecosystem. But we also are seeing the
00:04:57.919 same for the broader web community in the JavaScript state of ser um state of
00:05:02.960 JavaScript survey. We also saw um AlpineJS rise up from like up to like 8%
00:05:09.039 in 20 24 and HTMX which is similar to Turbo rise up to like 7% as well. So
00:05:15.600 it's all about service sites rendered HTML and HTML templating
00:05:22.160 but that doesn't come without the issues. So there are quite a few issues that we have and see that we somehow
00:05:27.600 need to address. Some of these are like partially solved with third-party um
00:05:33.759 libraries like view components encapsulation, the view boundaries and the usability aspect. Performance could
00:05:39.680 kind of be solved with that too. Tooling is still kind of still out like question
00:05:45.120 testing is kind of weird too because you have to do either full integration tests or full system tests which is quite
00:05:51.039 expensive and the more front logic you add um and complexity you add the more
00:05:56.160 complicated it gets to maintain these apps. So today I wanted to talk about a bit more like how we can improve the tooling
00:06:02.720 aspects and how we can improve the um like the view layer itself.
00:06:10.639 So what I one feature I love about Rails that I always liked was this index like this error page where it shows you the
00:06:16.880 error, it shows you the back back trace, it shows you the environment variables, it shows you even this console you can
00:06:22.880 interact with and it's really nice um experience to debug what's happening.
00:06:28.479 It's even kind of recognized in the broader web community that there's still nothing like it in any JavaScript framework these days. So it's still
00:06:36.000 interesting to see that this hasn't caught up in other um frameworks. But when it comes to like HTML ERB
00:06:42.400 templates, it's quite interesting. It's quite hard to figure out what went wrong. So in this case, obviously you
00:06:49.759 can see that there's a missing closing end tier.
00:06:57.520 There has been some work to make this better. Obviously, I think Aaron and John worked on this to make it um
00:07:03.039 better, but it's still not to the point where you can easily see what's wrong in most cases, especially syntax error are
00:07:09.440 quite tricky to figure out. But what we have in JavaScript in the JavaScript ecosystem is they have really awesome
00:07:15.919 tooling and that's something we can look at and kind of inspire us and take it over to Rails. So, here's example from
00:07:22.639 beat the bundler. they show you like this error message right away when you when they see a error where what's
00:07:29.840 happening and that's been the theme for VIT in general. They have this awesome
00:07:34.880 theme going on where they really set the bar high for how developer tooling
00:07:40.160 should look like. So V has really wellated workflow all the way through from like the view layer, the bundler,
00:07:48.479 serverside rendering, the dev server, hot reloading, testing documentation. It's a really nice coherent experience
00:07:55.360 from start to finish. And the thing is that people coming from these frameworks expect these tools to
00:08:01.520 be the same in our ecosystem in Rails and in Ruby. And I believe that every language that's like being um okay
00:08:10.720 created today or any tool created today should have tooling in mind to make it easier for people to get started with.
00:08:17.520 And yes, it's JavaScript. So you could say it's still like they
00:08:22.560 reinvent the wheel every week, but it's something we can learn from even as the
00:08:28.479 Rails community. And don't give too much credit to these frameworks for the most part. But I
00:08:34.080 think they figured out the view layer, they figured out the components, they figured out developer experience and the
00:08:40.800 whole tooling aspect as as a whole. But that's been the case for Rails too. I think they have really nice integrations
00:08:47.120 like every like all the gems work with each other. You just plug it in. It just always just worked. It seems just wrong
00:08:53.279 that the view layer doesn't have that kind of level of fidelity. Yeah, a lot of it's just plug and play.
00:08:59.600 You use this gem, use that gem, it just works. And that's why I think it makes sense
00:09:04.880 for us to also adopt this kind of level of um support for the view layer. If you
00:09:11.200 open any editor today, be it VS Code or any other one, and you open any JavaScript file, you just get good
00:09:18.720 tooling, instant feedback, diagnostics, refactoring tools, like this, all there. It's a great out of the box experience.
00:09:25.360 It just works. So, how does it compare to Ruby? Um,
00:09:31.279 the last decades it's been quite of a mix experience, but I feel like now with the Ruby LSP, this quite improve
00:09:38.320 improved quite a bit. Even now that VS Code is now recommending Ruby LSP as the default like tool to use
00:09:46.480 with Ruby, it's a one click installation and you get a great experience.
00:09:52.399 But that's not the case for HTML refile still. It's still a different story. And
00:09:57.600 that's why I've been trying to focus on that to make it easier for people to use Hot Wire and to use Vue tooling um as a
00:10:04.560 whole. That's why I was working on sim LSP that I showed off a few times over the years.
00:10:10.160 It's been going great. I think it's a nice tool. The same with Turbo LSP, but
00:10:15.760 the kind of problem was that they only support HTML.
00:10:21.120 If you aren't familiar with stimulus LSP, it's a tool to just show you what's wrong with your stimulus attributes with
00:10:27.120 your values. It also helps you autocomplete them. So, it's like easy to get to know what's actually should be in
00:10:32.959 this attribute. But yeah, no ERB support. It's HTML only. And a lot of
00:10:39.040 these Rails apps rely on these ERB helpers.
00:10:44.560 You can expect a view file to look like this, but it might not. They might just look like this, and then it doesn't
00:10:50.000 really help anymore. You get no diagnostics, no tooling support here.
00:10:55.279 And that's been the case, I think, in general for HTML ERB over the years.
00:11:00.640 and working on these tools or around these tools gave me some insights that I thought I want to tackle the bigger
00:11:05.680 picture and that's what Herb is. Um Herb is a set of tools um designed to work
00:11:12.959 with HTML ERB files and it's an ecosystem of tools. It's initially meant
00:11:20.480 to be a parser, a format on the lint for HMLB, but now that I was trying to build
00:11:26.320 this out, there were a lot of more utilities that kind of came up that we have now been building to kind of make
00:11:32.560 it even better. Some of these tools are needed for the tools above to make them work, but some of them are even like
00:11:39.760 nice use on themselves. So, first up, the parser. I talked about this at my Rubiki talk earlier this
00:11:46.640 April. Um, but to sum it up, it's a HTML aware EB parser. It's a new one. It's
00:11:53.120 written in C. It's built on Prism, the new Ruby parser to kind of parse out the
00:11:58.399 Ruby snippets in the year files. It's designed for tooling first and it has support for all the action view helpers.
00:12:06.720 So, what this does is it kind of builds up a tree, an int tree of HTML and ERB and brings it up into one tree. So you
00:12:13.760 have one syntax tree to look at to look um to do analysis on these um nodes
00:12:19.519 which means it has awareness of these files how they are structured the hierarchy but then the question is why
00:12:26.000 do we need a new tool and cannot just use no giri or prism like as individual tools already
00:12:32.320 and if you look at this file here for example um and you kind of say we split this up into two files and we extract
00:12:39.680 from the Ruby part the HTML and from the HTML part the Ruby You have a Ruby file and a HTML file and
00:12:45.519 you could say let's pass them to Prism and Noir respectively.
00:12:50.720 Let's parse them. We get a result back. But now we have two results which we cannot really piece back together
00:12:56.880 anymore. So we we lost kind of the HTML context where we were interpolating and using
00:13:02.560 these interpolation which doesn't really help. So even if we could piece them together,
00:13:07.839 we wouldn't be really be able to like allow or control these edge cases.
00:13:13.519 That's important. For example, here if you look at this snippet, you see that you have an opening tag and a closing
00:13:19.760 tag for the ERB for the ifs which belong together. And but in the middle you have this text. But any existing parser
00:13:27.440 wouldn't tell you that these two red blocks are related to each other. They are just individual ERB pieces. So you
00:13:33.600 have to know that these belong together. That's what Herb does. It looks at this
00:13:38.880 file. It finds the first block, looks for a matching end block and puts this
00:13:45.279 together in one node in the whole tree. And everything inside of it is
00:13:51.200 considered the children of this if block and that's kind of in the tree itself.
00:13:56.320 So we have now this hierarchy of how these nodes belong and relate to each other which really helps for the tooling
00:14:04.240 and this is quite different from this first approach where we had just one and the other and we couldn't really do
00:14:09.279 anything with that individually. So this opens a lot of doors to for us to understand analyze these documents and
00:14:16.720 the first one is now this formal. So the idea here is to make a HTML ERB
00:14:23.760 order for malo that can throw any file at either be it structured already or
00:14:29.199 unstructured and it will output when you save or run the CLI a nicely formatted
00:14:36.000 file. And that's I think something that's been missing for a long time. There has been
00:14:41.600 tools that did something similar but nothing to the point where I could set up easily or where I was happy with
00:14:47.839 results. Though I think this is really a nice change, but also you can integrate this into
00:14:53.440 your CI workflow to make sure that all the files are well formatted uh throughout your codebase.
00:14:59.519 And here's a little demo in the editor. So you save it and it kind of snaps right in. And you can mess with this,
00:15:05.519 indent it more, save it again, and it snaps right back. You save it. There we
00:15:10.560 go. So yeah, that's the first thing. The next thing is um the llinter. Um in
00:15:17.199 Ruby, we have this Ruby style guide to kind of show how you are supposed to write Ruby. Some of these rules are are
00:15:23.279 a little bit um aggressive, some of them aren't, but there's something to kind of configure and use. And it's really
00:15:29.360 valuable, but we don't really have anything like this for view files at all. And this guide should be um to
00:15:36.800 enforce the best practices and avoid common mistakes so we can kind of help people do the right thing in action
00:15:42.959 view. So here we have more diagnostics on how like common mistakes that you
00:15:49.120 see. Um some of them are HTML only some of them are HTML ERB some of them are
00:15:54.320 only Ruby but it's a limited set for now but we have more on the road map to add to these rules. We also have a few
00:16:02.000 accessibility rules um to make sure that we are um respecting all the area
00:16:08.800 attributes that we have more like links. We have all tags on images and all of that just like built in into um the
00:16:15.759 editor. Some of these are semantics but we also have some stylistic rules. Um one of
00:16:21.360 them is for example this one here that we just add white space around the ERB tags.
00:16:27.680 And you can see there's a link in this diagnostic. So you can click on it. It will open um the docs. It will show you
00:16:34.720 why this rule is important and what it enforces and why we think it's a good idea. Gives you some examples as you
00:16:40.720 might be used to from Rubocop. But now it also shows you in the docs itself why this specific example is not
00:16:47.600 good or what's wrong about it. And I haven't really seen this in any other lint docs. I'm wondering why. But I
00:16:54.399 think it just makes sense to put the rules together why this is wrong in the docs directly. So if you have any ideas
00:17:01.040 for llinter rules, what you want to kind of enforce in HTML files, please open an issue and you can see what you can do.
00:17:09.520 It also comes with a CLI um with nice error outputs and kind of um showing you
00:17:14.720 the context where stuff is happening. So we have um syntax highlighting, we have
00:17:20.240 um dimming so you know which line is the right thing and um pinpointing the location and at the end you get a
00:17:26.240 summary of all the rules that are violated in your run. There's also simple mode for a more
00:17:32.160 compact view so you don't have like this these long boxes of um context.
00:17:38.480 Yeah, this is powered by another kind of utility library called the herb highlighter. It's for syntax highlighting. And I just realized that I
00:17:45.679 was looking for a library to highlight HTML ERB. Then I realized that I just built a parser to to build like these
00:17:53.280 tools. And then I was like, okay, maybe I should just do it myself. So this is that kind of package for showing the
00:17:59.520 context in the in the terminal. Then one other thing that's kind of interesting is like a rewriter or a
00:18:07.120 refactoring tool. So you can say I want to replace all span tags with div tags.
00:18:12.320 I want to replace all data attributes with something else or values inside
00:18:17.679 attributes. And that's something that's been very common in the JavaScript communities using like plugins like
00:18:24.160 tailwinds prettier. So the idea here is that you kind of sort the classes in the right way that makes sense what's like
00:18:30.720 the most impactful and or group them in some way. But now since we have like
00:18:35.919 these tools, we can also enforce this like not just on HTML elements directly but also on all these tag helpers to
00:18:42.640 kind of have them enforced on both which is really cool. But yeah, this gives us
00:18:47.840 the confidence to like refactor these views reliably. That just makes sense that we weren't really able before with
00:18:53.520 just search and replays. Another utility is the herb printer. The
00:18:59.120 idea here is that you have um some HTML or some ERB. When you parse it, you get
00:19:05.039 the whole tree, but now when you have this tree, you want to get it back to the source. So the printer just takes
00:19:10.720 this tree and brings it back to the source code, which also means when we mutate the tree, we can do stuff in it.
00:19:19.200 And then this is going to be useful for when you want to build auto corrector for the llinter. So we can parse it,
00:19:25.840 change the tree, print it back to source and then write it to the file again. And then finally to kind of tie it all
00:19:32.480 together, it's a her language server. For now, this is a independent language server you have to install separately,
00:19:38.240 but I hope that this will get integrated maybe sometime upstream somewhere. But
00:19:43.520 yeah, the idea here is you can install this in your editor. We have a few supported ones already, maybe more to
00:19:49.520 come. But the idea here is that you just have linear editor, you edit it and you get instant feedback of what might be
00:19:56.400 wrong. There are par errors, there are closing tag errors, there are um opening tag
00:20:02.559 errors and even Ruby errors from Prism now that you can see that something is missing like
00:20:08.640 these are end missing or if you just have a if by itself you can also see there's going to be a conditional
00:20:14.880 missing. So yeah, that's this this is them the VS code language server and you have some
00:20:20.240 specific optimizations for VS code. So you have a setting screen, you have the
00:20:26.160 status bar which is analyzing the views and you have a nice view to see how your
00:20:31.280 application is doing, how many files are um have lint errors or um failed to
00:20:36.720 parse which is going to be helpful for us to diagnose and improve the pars for everybody else.
00:20:41.919 If there's anything that's wrong, you have this nice little quick fix to open a issue on GitHub with some context
00:20:48.320 already. So it's easy for us to diagnose what's might be wrong. There's more stuff to do. You can say we
00:20:54.559 can detect unused partials, unused views, maybe do jumper definitions for these render calls. So you can click
00:21:00.559 between them. There's a lot of things we can do now with this tooling. And one more thing we have for all the
00:21:07.520 tools I want to build on this with a language service which is going to be used probably by the stimulus and the
00:21:12.720 trip. I um have a working work version of this
00:21:18.159 locally. I was able to just go in and replace the HTML language service from VS Code with my language service. And
00:21:25.760 now all of a sudden just this works. And this is just great to see that um these
00:21:31.840 simul diagnostics also work on these ERB tags now which is cool. This is not live
00:21:37.200 yet. I have to still wrap this up but um what I have to share now is this new version of herb which includes um the
00:21:45.679 llinter the formatter in the preview. We have this VS code extension and the language server improvements and some
00:21:50.960 more bug fixes on parsing. But yeah, um this is like what we have
00:21:56.880 today, but this doesn't really answer the vision aspect of um the whole thing. So what I want to talk about now is what
00:22:03.360 we now that we have these tools, I realized that we could maybe do even more now that have the whole
00:22:08.960 introspection. And I was thinking that there might be a possibility to do a new ERB engine. But
00:22:16.720 for me, it's important to say here that this is a vision. This is not life. We
00:22:22.720 need to explore what we have, what we could do, and um even if none of this is viable in production, I think there's a
00:22:29.360 chance for this to just be helpful in development or tooling. So yeah, there we go. Um so yeah, a rendering engine
00:22:36.400 for ERB. Um what we have right now is a string template engine, which means we just concatenate strings. But what we
00:22:43.840 really want is a HTML templating engine, an engine that cannot produce invalid
00:22:50.480 HTML. And if you kind of look around what we have in the whole ecosystem right now, a
00:22:56.400 lot of tools also in other languages. And one of them really sticks out with the Fenix live view.
00:23:03.200 This is written in Elixir. And what Elixir has is a like the regular Elixir
00:23:08.799 files, but they also have the EX, which is equivalent to ERB. The syntax is
00:23:14.559 pretty much the same, but the one thing they have, but we don't have is a heek um templates, which is HTML and EX like
00:23:22.320 combines. But we don't have this in Ruby. So that's kind of where the name is coming
00:23:28.880 from or where the name was initially inspired from that we could have a herp engine that's only produces or can
00:23:36.240 produce valid HTML when you render out these templates. So when you take a regular ERB file
00:23:42.480 today and render it through the ERB engine using action view, now we have this missing closing tag here. But if
00:23:50.000 you just pass this to action view to the templates and use the ERB handler, we
00:23:55.120 compile this, it will just do the thing. It will just add the strings together and it will just um um render this out.
00:24:02.640 But what we could do now with a new engine using herb, we could say we take the same partial, we try to render this
00:24:10.080 this time using a herb handler and we try to compile this templates. This would just crash and say I'm not
00:24:16.960 compiling and it will also give you the diagnostics and the errors where something went wrong and that's just the
00:24:24.480 whole idea here that we don't that we cannot produce valid invalid HTML.
00:24:29.760 If you take this further, we can also say is there like a like reactive templates that we can do with this? And
00:24:36.880 the inspiration here is also again elixir with their live view.
00:24:42.159 So if we kind of take this to rails, what we could say is we could look at view files and we can render this out
00:24:48.640 for the first time. We have this items array with three items. We render this out. So we have this rendered view. But
00:24:55.840 now items changes and it gets in the f fourth item and somehow we keep to have
00:25:01.279 like track of that. Not sure how yet but we have to keep track of this somehow. But what we could say now is that items
00:25:07.760 changed. Let's look in the view where we are using items. And we can see that we are using items
00:25:13.679 here. So maybe we can just say let's render this block where we are using this only once. So you render this for
00:25:21.039 the fourth item. Get this snippet of just the four. And since we know how
00:25:26.159 this is being rendered, we can just insert into the DOM because we know where this should be inserted into.
00:25:32.240 Obviously, this requires JavaScript on the client too, but this would um um
00:25:38.400 make this a lot more like declarative, right? You don't have to say this should be
00:25:44.880 um rendered here and appended there and like you have to do no frames, nothing. It just like figures it out by itself,
00:25:50.960 which is what we want in the end, I think. So yeah, ERB is kind of here to stay. I
00:25:57.120 think action view is here to stay, but we want to make action view more Railsy
00:26:03.440 or like more keep it level up by keeping it railsy. That's the whole idea of this
00:26:09.360 reaction view that I um was thinking of. So Hak is for Phoenix live view, Herb
00:26:15.840 could be for Rails reaction view. And there are like multiple levels of how we
00:26:20.960 could kind of go or where we could go with this. But the first one would be to just say let's give better feedback to
00:26:27.360 these errors. So this screen again instead of doing this and showing more
00:26:34.080 more showing something like this we could say let's show all the errors right here and it doesn't render but it
00:26:40.000 will show this diff is open and closed and there's some syntax error here too.
00:26:46.159 And level two would be to say let's build this actual engine. So it doesn't even
00:26:51.200 compile to go from the string template engine to a HTML templating langu engine engine.
00:26:56.880 And this would need to be backwards compatible obviously. But it's only as
00:27:02.240 long backwards compatible as you are writing valid HTML. So if you give it a
00:27:07.919 template, it will just crash, right? But that's good because you want to know where you have in HTML in the application. That's what you want to
00:27:13.919 fix. But we can take this even further and say let's add checks for HTML 5. Let's
00:27:19.840 add accessibility checks right into it because we have already rendered out the whole page. So we can do more static
00:27:26.240 analysis for accessibility. We could also do more um checks for um crossite
00:27:32.400 scripting and unsafe interpolation or um yeah more like checks that we can
00:27:37.679 do at static analysis time. Since these don't really kind of crash the whole engine and wouldn't like crash
00:27:43.919 out the whole process, we could kind of annotate them and show them on the first render of the page and show them in the
00:27:49.520 top right corner. There's probably also more we can do with action view and optimizations of
00:27:55.600 how it compiles and how it renders these templates behind the scenes.
00:28:00.720 And um I guess Hartley did some um of that exploration on the first thing that in his talk but there's also more um
00:28:08.000 from John here where he was trying to or he where he is pre-ompiling templates in
00:28:13.120 in on boots. So it's um more memory efficient. But the thing is that we
00:28:19.520 could probably do more advanced tools. Oh more advanced optimizations now that we have all the introspection.
00:28:25.440 Maybe something like inlining all the partials directly, so you're gonna have to do an actual render call anymore or
00:28:31.919 other things. So that's probably model explore. I haven't really dug into this yet, but that's something to check out.
00:28:38.880 Then for the fourth level, we could say, yeah, let's bring these reactive views actually to our view layer.
00:28:45.840 And I was thinking to keep it kind of um backwards compatible, so you don't have to kind of replace your whole app with
00:28:52.240 all these new views. What you would do is you would kind of rename your EAB file to um a herb file and with that you
00:29:00.640 opt in into this new stricter engine and with that you also get just these
00:29:05.919 progress progressive enhancements. You can gradually adopt this um where it makes sense. You don't have to do an all
00:29:13.120 on offering approach where you say yeah replace it all or go all in on react. We can just say in this space um place it
00:29:20.240 makes sense. Yeah. Yeah. And only use it where we actually need it. And with this one like simple change, we
00:29:27.360 can kind of really pinpoint and make sure that we only do this where it makes sense by still keeping it railsy and
00:29:35.120 action view as we used to have it. So technically this also allows for more
00:29:41.360 syntax to be introduced. Um, and if you look at something like rocks from Cameron, we might be able to also say
00:29:49.039 let's use something like JSX inspired syntax to render some of these components. I'm not saying this is the
00:29:54.720 syntax you want to go for, but it's something we could explore now that we kind of say we have this breaking change in this opt-in mechanism.
00:30:02.720 The next level would be to say client side templates. Um Joel was saying talking about this in his talk too where
00:30:09.520 he was saying we should pass in values not whole objects like only primitive values. And if you only do that we can
00:30:16.640 say with a limited set of ERB not all the whole spectrum we could do what
00:30:21.760 React is doing with the other way around from going from the client to the server side. We could say let's bring our ERB
00:30:28.240 views to the client. They could transpile to React or to web components or whatever it is. doesn't
00:30:34.399 really matter, but it would give us some ideas on how to implement optimistic UI
00:30:40.720 updates while keeping and reusing our views from the server side. Or it might
00:30:46.000 help us to improve offline functionality because we can reuse our views and can use them on the client. Or we say we
00:30:54.080 want to have some smaller interactions. We don't require a full server um um
00:30:59.200 handshake or like back and forth. to just do these smaller interaction pieces.
00:31:05.039 And for the last level, which is probably too ambitious, but still going to show it um would be to say let's
00:31:11.279 bring in the external components from other ecosystems. So you don't have to say we have to
00:31:17.520 throw it all away, but we say we only want again on certain pages we want to have more.
00:31:24.000 Now you could say this is what inertia rails already does in a way. But the thing with inertia is that you have to
00:31:29.360 say I want to have all of it in react and it's that's all there is. So you cannot say I want to have only this
00:31:34.799 piece in react and this other piece not. So it has like all or nothing. So what I'm thinking of is more like input maps
00:31:41.600 rails where you say I want to import these components from chat or something
00:31:46.720 else or from our local app and then you are able to use those in your view in
00:31:52.880 your EB view and the engine knows how to deal with those how to hydrate those and
00:31:58.080 how to um make them render on the client. This is similar to turbo mount but with
00:32:04.480 a difference that it's tightly integrated right into the engine. It has tooling built in. There's no setup and
00:32:10.159 it works out of the box. Again, this is only to show what would be possible, could be possible, but I think it's
00:32:17.039 still fun to explore. So, yeah, what's next? I want to finish the format or
00:32:22.799 bring it to a stage where it's really nice and good to use and to make it configurable too and to work on reaction
00:32:29.760 more to make that uh maybe even viable. I have a talk at Euroku later this year
00:32:36.399 where I want to show like at least a prototype of that bring it to life and
00:32:41.440 see what we can do. So yeah, to conclude, I think Prism had a big effect on the
00:32:47.200 whole tooling and internals of Ruby and I think that Herb could have a different um effect for templating in general and
00:32:56.080 given that we have built awesome tools in the whole community, I think this is now the time to bring the same care and
00:33:02.320 love to the view layer. And with Herb, I think we have this to level it up.
00:33:08.480 In the end, I'm still I love Ruby and that's why I'm here today. I want to keep using Ruby and um I want to keep it
00:33:15.039 as attractive as possible for people to use. I want to thank these people who some in
00:33:21.200 some way made this today possible what we have and the contributors that
00:33:26.559 directly contributed to the repo. So yeah, check it out on her tools.dev or
00:33:31.679 give it a star on GitHub. And one thing I want to ask is please run it on your
00:33:37.279 apps. If it breaks, great. We can improve it for everybody else. If it doesn't break, awesome.
00:33:44.159 Um, or use the VS Code extension to figure it out. But that's all I have for today. Thank you so much.
Explore all talks recorded at RailsConf 2025
Cirdes Henrique
Matheus Richard
Evan Phoenix
Albert Pazderin
Vladimir Dementyev
Joe Leo
David Heinemeier Hansson
Alicia Rojas
+77