<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Hanakai</title>
  <subtitle>Let your Ruby bloom. Hanakai is a family of Ruby tools that help you write clearer, more maintainable apps.</subtitle>
  <link href="https://hanakai.org/feed.xml" rel="self" type="application/atom+xml"/>
  <link href="https://hanakai.org/" rel="alternate" type="text/html"/>
  <id>https://hanakai.org/feed.xml</id>
  <updated>2026-06-30T23:30:00+00:00</updated>
  <entry>
    <title>Hanami 3.0: In full bloom</title>
    <link rel="alternate" href="https://hanakai.org/blog/2026/06/30/hanami-3-0-in-full-bloom"/>
    <id>https://hanakai.org/blog/2026/06/30/hanami-3-0-in-full-bloom</id>
    <published>2026-06-30T23:30:00+00:00</published>
    <updated>2026-06-30T23:30:00+00:00</updated>
    <author>
      <name>Tim Riley</name>
    </author>
    <content type="html">&lt;p&gt;From the very beginning we set out to make Hanami a different kind of Ruby framework: clear, modular, and built to grow. Today it comes into full bloom. We’re thrilled to share &lt;strong&gt;Hanami 3.0&lt;/strong&gt; with you!&lt;/p&gt;
&lt;p&gt;This release rounds out the framework with three big new features: &lt;strong&gt;mailers&lt;/strong&gt;, &lt;strong&gt;internationalization&lt;/strong&gt;, and &lt;strong&gt;Minitest&lt;/strong&gt;. On top of that, your apps are now &lt;strong&gt;faster by default&lt;/strong&gt;, and your developer experience is sharper, from your logs all the way to your assets.&lt;/p&gt;
&lt;h2 id="first-class-mailers"&gt;
First-class mailers&lt;a href="#first-class-mailers" aria-hidden="true" class="anchor"&gt;&lt;span aria-hidden="true" class="anchor"&gt;&lt;/span&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Our long lost gem is back! Hanami apps now come with &lt;a href="/learn/hanami/v3.0/mailers"&gt;integrated mailers&lt;/a&gt;, which feel right at home next to your actions, views, and operations.&lt;/p&gt;
&lt;p&gt;Mailer classes describe everything you need to deliver an email:&lt;/p&gt;
&lt;div class="pre-wrapper" data-defo-copy-code&gt;
&lt;button type="button" class="pre-wrapper__button" aria-label="Copy"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" class="pre-wrapper__icon pre-wrapper__icon--copy" height="16" viewbox="0 0 256 256" width="16"&gt; &lt;path d="M172,164a12,12,0,0,1-12,12H96a12,12,0,0,1,0-24h64A12,12,0,0,1,172,164Zm-12-52H96a12,12,0,0,0,0,24h64a12,12,0,0,0,0-24Zm60-64V216a20,20,0,0,1-20,20H56a20,20,0,0,1-20-20V48A20,20,0,0,1,56,28H90.53a51.88,51.88,0,0,1,74.94,0H200A20,20,0,0,1,220,48ZM100.29,60h55.42a28,28,0,0,0-55.42,0ZM196,52H178.59A52.13,52.13,0,0,1,180,64v8a12,12,0,0,1-12,12H88A12,12,0,0,1,76,72V64a52.13,52.13,0,0,1,1.41-12H60V212H196Z"&gt;&lt;/path&gt; &lt;/svg&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" class="pre-wrapper__icon pre-wrapper__icon--check" height="16" viewbox="-13 0 276 276" width="16"&gt; &lt;path d="M232.49,80.49l-128,128a12,12,0,0,1-17,0l-56-56a12,12,0,1,1,17-17L96,183,215.51,63.51a12,12,0,0,1,17,17Z"&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/button&gt;&lt;pre class="syntax-highlighting"&gt;&lt;code&gt;&lt;span class="source ruby"&gt;&lt;span class="meta module ruby"&gt;&lt;span class="keyword control module ruby"&gt;module&lt;/span&gt;&lt;/span&gt;&lt;span class="meta module ruby"&gt; &lt;/span&gt;&lt;span class="meta module ruby"&gt;&lt;span class="entity name module ruby"&gt;Bookshelf&lt;/span&gt;&lt;/span&gt;
  &lt;span class="meta module ruby"&gt;&lt;span class="keyword control module ruby"&gt;module&lt;/span&gt;&lt;/span&gt;&lt;span class="meta module ruby"&gt; &lt;/span&gt;&lt;span class="meta module ruby"&gt;&lt;span class="entity name module ruby"&gt;Mailers&lt;/span&gt;&lt;/span&gt;
    &lt;span class="meta class ruby"&gt;&lt;span class="keyword control class ruby"&gt;class&lt;/span&gt;&lt;/span&gt;&lt;span class="meta class ruby"&gt; &lt;/span&gt;&lt;span class="meta class ruby"&gt;&lt;span class="entity name class ruby"&gt;Welcome&lt;/span&gt;&lt;/span&gt;&lt;span class="meta class ruby"&gt; &lt;span class="punctuation separator inheritance ruby"&gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span class="meta class ruby"&gt; &lt;/span&gt;&lt;span class="meta class ruby"&gt;&lt;span class="entity other inherited-class ruby"&gt;&lt;span class="support other namespace ruby"&gt;Bookshelf&lt;/span&gt;&lt;span class="punctuation accessor ruby"&gt;::&lt;/span&gt;&lt;span class="support class ruby"&gt;Mailer&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
      from &lt;span class="string quoted double ruby"&gt;&lt;span class="punctuation definition string begin ruby"&gt;"&lt;/span&gt;welcome@bookshelf.test&lt;span class="punctuation definition string end ruby"&gt;"&lt;/span&gt;&lt;/span&gt;
      to &lt;span class="punctuation section scope ruby"&gt;{&lt;/span&gt; &lt;span class="meta block parameters ruby"&gt;&lt;span class="punctuation definition parameters begin ruby"&gt;|&lt;/span&gt;&lt;/span&gt;&lt;span class="meta block parameters ruby"&gt;&lt;span class="variable parameter ruby"&gt;user&lt;/span&gt;:&lt;span class="meta block parameters ruby"&gt;&lt;span class="punctuation definition parameters end ruby"&gt;|&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; user&lt;span class="punctuation accessor ruby"&gt;.&lt;/span&gt;email &lt;span class="punctuation section scope ruby"&gt;}&lt;/span&gt;
      subject &lt;span class="punctuation section scope ruby"&gt;{&lt;/span&gt; &lt;span class="meta block parameters ruby"&gt;&lt;span class="punctuation definition parameters begin ruby"&gt;|&lt;/span&gt;&lt;/span&gt;&lt;span class="meta block parameters ruby"&gt;&lt;span class="variable parameter ruby"&gt;user&lt;/span&gt;:&lt;span class="meta block parameters ruby"&gt;&lt;span class="punctuation definition parameters end ruby"&gt;|&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; &lt;span class="string quoted double ruby"&gt;&lt;span class="punctuation definition string begin ruby"&gt;"&lt;/span&gt;Welcome to Bookshelf, &lt;span class="source ruby embedded source"&gt;&lt;span class="punctuation section embedded ruby"&gt;#{&lt;/span&gt;user&lt;span class="punctuation accessor ruby"&gt;.&lt;/span&gt;&lt;span class="support function builtin ruby"&gt;name&lt;/span&gt;&lt;span class="punctuation section embedded ruby"&gt;}&lt;/span&gt;&lt;/span&gt;!&lt;span class="punctuation definition string end ruby"&gt;"&lt;/span&gt;&lt;/span&gt; &lt;span class="punctuation section scope ruby"&gt;}&lt;/span&gt;

      expose &lt;span class="constant other symbol ruby"&gt;&lt;span class="punctuation definition constant ruby"&gt;:&lt;/span&gt;user&lt;/span&gt;
    &lt;span class="keyword control ruby"&gt;end&lt;/span&gt;
  &lt;span class="keyword control ruby"&gt;end&lt;/span&gt;
&lt;span class="keyword control ruby"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;As standalone objects, mailers are injectable via the &lt;a href="/learn/hanami/v3.0/app/container-and-components#injecting-dependencies-via-deps"&gt;Deps mixin&lt;/a&gt; and accessible wherever you need them. Call &lt;code&gt;.deliver&lt;/code&gt; and the mailer will use your input to prepare headers and render mail body templates, which work as a fully featured extension of your view layer.&lt;/p&gt;
&lt;p&gt;Mailers support multiple delivery methods. SMTP delivery works out of the box: populate some env vars for your SMTP host and you’re good to go. In test, your emails are accumulated in memory for you to inspect.&lt;/p&gt;
&lt;p&gt;If you need something more, you can also write your own delivery methods. In addition to a clean interface for these, Hanami Mailer provides hooks for threading delivery options all the way through your mailers, allowing new delivery methods to make the most of special features offered by email delivery providers.&lt;/p&gt;
&lt;p&gt;Like all our gems, Hanami Mailer is also designed for standalone use. Check out the comprehensive &lt;a href="https://github.com/hanami/hanami-mailer/#readme-ov-file"&gt;README&lt;/a&gt; for everything you need to know about using it in your Ruby app.&lt;/p&gt;
&lt;p&gt;Hanami Mailer leans on the venerable mail gem to handle all its low-level mail wrangling. Thank you to the &lt;a href="https://github.com/mikel/mail/graphs/contributors?all=1"&gt;mail maintainers&lt;/a&gt; for all their work over the years!&lt;/p&gt;
&lt;h2 id="built-in-internationalization"&gt;
Built-in internationalization&lt;a href="#built-in-internationalization" aria-hidden="true" class="anchor"&gt;&lt;span aria-hidden="true" class="anchor"&gt;&lt;/span&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Taking your apps to the world just got easier: i18n is now &lt;a href="/learn/hanami/v3.0/i18n"&gt;built right into Hanami&lt;/a&gt;. Bundle the &lt;a href="https://github.com/ruby-i18n/i18n"&gt;i18n gem&lt;/a&gt; and Hanami sets up a self-contained translation backend in your app and every slice, with &lt;code&gt;translate&lt;/code&gt; and &lt;code&gt;localize&lt;/code&gt; helpers ready to use across your actions and views.&lt;/p&gt;
&lt;p&gt;Your translations live in &lt;code&gt;config/i18n/&lt;/code&gt; in your app or slice:&lt;/p&gt;
&lt;div class="pre-wrapper" data-defo-copy-code&gt;
&lt;button type="button" class="pre-wrapper__button" aria-label="Copy"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" class="pre-wrapper__icon pre-wrapper__icon--copy" height="16" viewbox="0 0 256 256" width="16"&gt; &lt;path d="M172,164a12,12,0,0,1-12,12H96a12,12,0,0,1,0-24h64A12,12,0,0,1,172,164Zm-12-52H96a12,12,0,0,0,0,24h64a12,12,0,0,0,0-24Zm60-64V216a20,20,0,0,1-20,20H56a20,20,0,0,1-20-20V48A20,20,0,0,1,56,28H90.53a51.88,51.88,0,0,1,74.94,0H200A20,20,0,0,1,220,48ZM100.29,60h55.42a28,28,0,0,0-55.42,0ZM196,52H178.59A52.13,52.13,0,0,1,180,64v8a12,12,0,0,1-12,12H88A12,12,0,0,1,76,72V64a52.13,52.13,0,0,1,1.41-12H60V212H196Z"&gt;&lt;/path&gt; &lt;/svg&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" class="pre-wrapper__icon pre-wrapper__icon--check" height="16" viewbox="-13 0 276 276" width="16"&gt; &lt;path d="M232.49,80.49l-128,128a12,12,0,0,1-17,0l-56-56a12,12,0,1,1,17-17L96,183,215.51,63.51a12,12,0,0,1,17,17Z"&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/button&gt;&lt;pre class="syntax-highlighting"&gt;&lt;code&gt;&lt;span class="source yaml"&gt;&lt;span class="comment line number-sign yaml"&gt;&lt;span class="punctuation definition comment line number-sign yaml"&gt;#&lt;/span&gt; config/i18n/en.yml
&lt;/span&gt;&lt;span class="string unquoted plain out yaml"&gt;&lt;span class="entity name tag yaml"&gt;en&lt;/span&gt;&lt;/span&gt;&lt;span class="punctuation separator key-value mapping yaml"&gt;:&lt;/span&gt;
  &lt;span class="string unquoted plain out yaml"&gt;&lt;span class="entity name tag yaml"&gt;posts&lt;/span&gt;&lt;/span&gt;&lt;span class="punctuation separator key-value mapping yaml"&gt;:&lt;/span&gt;
    &lt;span class="string unquoted plain out yaml"&gt;&lt;span class="entity name tag yaml"&gt;index&lt;/span&gt;&lt;/span&gt;&lt;span class="punctuation separator key-value mapping yaml"&gt;:&lt;/span&gt;
      &lt;span class="string unquoted plain out yaml"&gt;&lt;span class="entity name tag yaml"&gt;title&lt;/span&gt;&lt;/span&gt;&lt;span class="punctuation separator key-value mapping yaml"&gt;:&lt;/span&gt; &lt;span class="string quoted double yaml"&gt;&lt;span class="punctuation definition string begin yaml"&gt;"&lt;/span&gt;Latest posts&lt;span class="punctuation definition string end yaml"&gt;"&lt;/span&gt;&lt;/span&gt;
    &lt;span class="string unquoted plain out yaml"&gt;&lt;span class="entity name tag yaml"&gt;create&lt;/span&gt;&lt;/span&gt;&lt;span class="punctuation separator key-value mapping yaml"&gt;:&lt;/span&gt;
      &lt;span class="string unquoted plain out yaml"&gt;&lt;span class="entity name tag yaml"&gt;created&lt;/span&gt;&lt;/span&gt;&lt;span class="punctuation separator key-value mapping yaml"&gt;:&lt;/span&gt; &lt;span class="string quoted double yaml"&gt;&lt;span class="punctuation definition string begin yaml"&gt;"&lt;/span&gt;Your post is live!&lt;span class="punctuation definition string end yaml"&gt;"&lt;/span&gt;&lt;/span&gt;
  &lt;span class="string unquoted plain out yaml"&gt;&lt;span class="entity name tag yaml"&gt;greetings&lt;/span&gt;&lt;/span&gt;&lt;span class="punctuation separator key-value mapping yaml"&gt;:&lt;/span&gt;
    &lt;span class="string unquoted plain out yaml"&gt;&lt;span class="entity name tag yaml"&gt;welcome&lt;/span&gt;&lt;/span&gt;&lt;span class="punctuation separator key-value mapping yaml"&gt;:&lt;/span&gt; &lt;span class="string quoted double yaml"&gt;&lt;span class="punctuation definition string begin yaml"&gt;"&lt;/span&gt;Welcome, %{name}!&lt;span class="punctuation definition string end yaml"&gt;"&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;From there, i18n helpers are everywhere you’d expect them! Like in your views:&lt;/p&gt;
&lt;div class="pre-wrapper" data-defo-copy-code&gt;
&lt;button type="button" class="pre-wrapper__button" aria-label="Copy"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" class="pre-wrapper__icon pre-wrapper__icon--copy" height="16" viewbox="0 0 256 256" width="16"&gt; &lt;path d="M172,164a12,12,0,0,1-12,12H96a12,12,0,0,1,0-24h64A12,12,0,0,1,172,164Zm-12-52H96a12,12,0,0,0,0,24h64a12,12,0,0,0,0-24Zm60-64V216a20,20,0,0,1-20,20H56a20,20,0,0,1-20-20V48A20,20,0,0,1,56,28H90.53a51.88,51.88,0,0,1,74.94,0H200A20,20,0,0,1,220,48ZM100.29,60h55.42a28,28,0,0,0-55.42,0ZM196,52H178.59A52.13,52.13,0,0,1,180,64v8a12,12,0,0,1-12,12H88A12,12,0,0,1,76,72V64a52.13,52.13,0,0,1,1.41-12H60V212H196Z"&gt;&lt;/path&gt; &lt;/svg&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" class="pre-wrapper__icon pre-wrapper__icon--check" height="16" viewbox="-13 0 276 276" width="16"&gt; &lt;path d="M232.49,80.49l-128,128a12,12,0,0,1-17,0l-56-56a12,12,0,1,1,17-17L96,183,215.51,63.51a12,12,0,0,1,17,17Z"&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/button&gt;&lt;pre class="syntax-highlighting"&gt;&lt;code&gt;&lt;span class="text html ruby"&gt;&lt;span class="text html basic"&gt;&lt;span class="comment block erb"&gt;&lt;span class="punctuation definition comment erb"&gt;&amp;lt;%#&lt;/span&gt; app/templates/posts/index.html.erb %&amp;gt;&lt;/span&gt;
&lt;span class="meta tag block any html"&gt;&lt;span class="punctuation definition tag begin html"&gt;&amp;lt;&lt;/span&gt;&lt;span class="entity name tag block any html"&gt;h1&lt;/span&gt;&lt;span class="punctuation definition tag end html"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="source ruby rails embedded html"&gt;&lt;span class="punctuation section embedded ruby"&gt;&amp;lt;%=&lt;/span&gt; t&lt;span class="punctuation definition group begin ruby"&gt;(&lt;/span&gt;&lt;span class="string quoted double ruby"&gt;&lt;span class="punctuation definition string begin ruby"&gt;"&lt;/span&gt;.title&lt;span class="punctuation definition string end ruby"&gt;"&lt;/span&gt;&lt;/span&gt;&lt;span class="punctuation definition group end ruby"&gt;)&lt;/span&gt; &lt;span class="punctuation section embedded ruby"&gt;%&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="meta tag block any html"&gt;&lt;span class="punctuation definition tag begin html"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="entity name tag block any html"&gt;h1&lt;/span&gt;&lt;span class="punctuation definition tag end html"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;And your actions:&lt;/p&gt;
&lt;div class="pre-wrapper" data-defo-copy-code&gt;
&lt;button type="button" class="pre-wrapper__button" aria-label="Copy"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" class="pre-wrapper__icon pre-wrapper__icon--copy" height="16" viewbox="0 0 256 256" width="16"&gt; &lt;path d="M172,164a12,12,0,0,1-12,12H96a12,12,0,0,1,0-24h64A12,12,0,0,1,172,164Zm-12-52H96a12,12,0,0,0,0,24h64a12,12,0,0,0,0-24Zm60-64V216a20,20,0,0,1-20,20H56a20,20,0,0,1-20-20V48A20,20,0,0,1,56,28H90.53a51.88,51.88,0,0,1,74.94,0H200A20,20,0,0,1,220,48ZM100.29,60h55.42a28,28,0,0,0-55.42,0ZM196,52H178.59A52.13,52.13,0,0,1,180,64v8a12,12,0,0,1-12,12H88A12,12,0,0,1,76,72V64a52.13,52.13,0,0,1,1.41-12H60V212H196Z"&gt;&lt;/path&gt; &lt;/svg&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" class="pre-wrapper__icon pre-wrapper__icon--check" height="16" viewbox="-13 0 276 276" width="16"&gt; &lt;path d="M232.49,80.49l-128,128a12,12,0,0,1-17,0l-56-56a12,12,0,1,1,17-17L96,183,215.51,63.51a12,12,0,0,1,17,17Z"&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/button&gt;&lt;pre class="syntax-highlighting"&gt;&lt;code&gt;&lt;span class="source ruby"&gt;&lt;span class="comment line number-sign ruby"&gt;&lt;span class="punctuation definition comment ruby"&gt;#&lt;/span&gt; app/actions/posts/create.rb
&lt;/span&gt;&lt;span class="meta function ruby"&gt;&lt;span class="keyword control def ruby"&gt;def&lt;/span&gt;&lt;/span&gt;&lt;span class="meta function ruby"&gt; &lt;span class="entity name function ruby"&gt;handle&lt;/span&gt;&lt;/span&gt;&lt;span class="meta function parameters ruby"&gt;&lt;span class="punctuation definition group begin ruby"&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span class="meta function parameters ruby"&gt;&lt;span class="variable parameter ruby"&gt;request&lt;/span&gt;&lt;span class="punctuation separator ruby"&gt;,&lt;/span&gt; &lt;span class="variable parameter ruby"&gt;response&lt;/span&gt;&lt;/span&gt;&lt;span class="meta function parameters ruby"&gt;&lt;span class="punctuation definition group end ruby"&gt;)&lt;/span&gt;&lt;/span&gt;
  response&lt;span class="punctuation accessor ruby"&gt;.&lt;/span&gt;flash&lt;span class="punctuation section array ruby"&gt;[&lt;/span&gt;&lt;span class="constant other symbol ruby"&gt;&lt;span class="punctuation definition constant ruby"&gt;:&lt;/span&gt;notice&lt;/span&gt;&lt;span class="punctuation section array ruby"&gt;]&lt;/span&gt; &lt;span class="keyword operator assignment ruby"&gt;=&lt;/span&gt; t&lt;span class="punctuation definition group begin ruby"&gt;(&lt;/span&gt;&lt;span class="string quoted double ruby"&gt;&lt;span class="punctuation definition string begin ruby"&gt;"&lt;/span&gt;.created&lt;span class="punctuation definition string end ruby"&gt;"&lt;/span&gt;&lt;/span&gt;&lt;span class="punctuation definition group end ruby"&gt;)&lt;/span&gt;
  &lt;span class="comment line number-sign ruby"&gt;&lt;span class="punctuation definition comment ruby"&gt;#&lt;/span&gt; ...
&lt;/span&gt;&lt;span class="keyword control ruby"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;And for everywhere else, the &lt;code&gt;"i18n"&lt;/code&gt; component is just one Deps mixin away:&lt;/p&gt;
&lt;div class="pre-wrapper" data-defo-copy-code&gt;
&lt;button type="button" class="pre-wrapper__button" aria-label="Copy"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" class="pre-wrapper__icon pre-wrapper__icon--copy" height="16" viewbox="0 0 256 256" width="16"&gt; &lt;path d="M172,164a12,12,0,0,1-12,12H96a12,12,0,0,1,0-24h64A12,12,0,0,1,172,164Zm-12-52H96a12,12,0,0,0,0,24h64a12,12,0,0,0,0-24Zm60-64V216a20,20,0,0,1-20,20H56a20,20,0,0,1-20-20V48A20,20,0,0,1,56,28H90.53a51.88,51.88,0,0,1,74.94,0H200A20,20,0,0,1,220,48ZM100.29,60h55.42a28,28,0,0,0-55.42,0ZM196,52H178.59A52.13,52.13,0,0,1,180,64v8a12,12,0,0,1-12,12H88A12,12,0,0,1,76,72V64a52.13,52.13,0,0,1,1.41-12H60V212H196Z"&gt;&lt;/path&gt; &lt;/svg&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" class="pre-wrapper__icon pre-wrapper__icon--check" height="16" viewbox="-13 0 276 276" width="16"&gt; &lt;path d="M232.49,80.49l-128,128a12,12,0,0,1-17,0l-56-56a12,12,0,1,1,17-17L96,183,215.51,63.51a12,12,0,0,1,17,17Z"&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/button&gt;&lt;pre class="syntax-highlighting"&gt;&lt;code&gt;&lt;span class="source ruby"&gt;&lt;span class="meta class ruby"&gt;&lt;span class="keyword control class ruby"&gt;class&lt;/span&gt;&lt;/span&gt;&lt;span class="meta class ruby"&gt; &lt;/span&gt;&lt;span class="meta class ruby"&gt;&lt;span class="entity name class ruby"&gt;Greeter&lt;/span&gt;&lt;/span&gt;&lt;span class="meta class ruby"&gt;
  &lt;/span&gt;&lt;span class="keyword other special-method ruby"&gt;include&lt;/span&gt; &lt;span class="support class ruby"&gt;Deps&lt;/span&gt;&lt;span class="punctuation section array ruby"&gt;[&lt;/span&gt;&lt;span class="string quoted double ruby"&gt;&lt;span class="punctuation definition string begin ruby"&gt;"&lt;/span&gt;i18n&lt;span class="punctuation definition string end ruby"&gt;"&lt;/span&gt;&lt;/span&gt;&lt;span class="punctuation section array ruby"&gt;]&lt;/span&gt;

  &lt;span class="meta function ruby"&gt;&lt;span class="keyword control def ruby"&gt;def&lt;/span&gt;&lt;/span&gt;&lt;span class="meta function ruby"&gt; &lt;span class="entity name function ruby"&gt;call&lt;/span&gt;&lt;/span&gt;&lt;span class="meta function parameters ruby"&gt;&lt;span class="punctuation definition group begin ruby"&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span class="meta function parameters ruby"&gt;&lt;span class="variable parameter ruby"&gt;name&lt;/span&gt;&lt;/span&gt;&lt;span class="meta function parameters ruby"&gt;&lt;span class="punctuation definition group end ruby"&gt;)&lt;/span&gt;&lt;/span&gt;
    i18n&lt;span class="punctuation accessor ruby"&gt;.&lt;/span&gt;t&lt;span class="punctuation definition group begin ruby"&gt;(&lt;/span&gt;&lt;span class="string quoted double ruby"&gt;&lt;span class="punctuation definition string begin ruby"&gt;"&lt;/span&gt;greetings.welcome&lt;span class="punctuation definition string end ruby"&gt;"&lt;/span&gt;&lt;/span&gt;&lt;span class="punctuation separator ruby"&gt;,&lt;/span&gt; &lt;span class="constant other symbol ruby"&gt;name&lt;span class="punctuation definition constant ruby"&gt;:&lt;/span&gt;&lt;/span&gt;&lt;span class="punctuation definition group end ruby"&gt;)&lt;/span&gt;
  &lt;span class="keyword control ruby"&gt;end&lt;/span&gt;
&lt;span class="keyword control ruby"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;We’ve got localization too. &lt;code&gt;localize&lt;/code&gt; formats your dates and times for the current locale, and ships with sensible defaults for English:&lt;/p&gt;
&lt;div class="pre-wrapper" data-defo-copy-code&gt;
&lt;button type="button" class="pre-wrapper__button" aria-label="Copy"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" class="pre-wrapper__icon pre-wrapper__icon--copy" height="16" viewbox="0 0 256 256" width="16"&gt; &lt;path d="M172,164a12,12,0,0,1-12,12H96a12,12,0,0,1,0-24h64A12,12,0,0,1,172,164Zm-12-52H96a12,12,0,0,0,0,24h64a12,12,0,0,0,0-24Zm60-64V216a20,20,0,0,1-20,20H56a20,20,0,0,1-20-20V48A20,20,0,0,1,56,28H90.53a51.88,51.88,0,0,1,74.94,0H200A20,20,0,0,1,220,48ZM100.29,60h55.42a28,28,0,0,0-55.42,0ZM196,52H178.59A52.13,52.13,0,0,1,180,64v8a12,12,0,0,1-12,12H88A12,12,0,0,1,76,72V64a52.13,52.13,0,0,1,1.41-12H60V212H196Z"&gt;&lt;/path&gt; &lt;/svg&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" class="pre-wrapper__icon pre-wrapper__icon--check" height="16" viewbox="-13 0 276 276" width="16"&gt; &lt;path d="M232.49,80.49l-128,128a12,12,0,0,1-17,0l-56-56a12,12,0,1,1,17-17L96,183,215.51,63.51a12,12,0,0,1,17,17Z"&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/button&gt;&lt;pre class="syntax-highlighting"&gt;&lt;code&gt;&lt;span class="source ruby"&gt;localize&lt;span class="punctuation definition group begin ruby"&gt;(&lt;/span&gt;&lt;span class="support class ruby"&gt;Date&lt;/span&gt;&lt;span class="punctuation accessor ruby"&gt;.&lt;/span&gt;&lt;span class="keyword other special-method ruby"&gt;new&lt;/span&gt;&lt;span class="punctuation definition group begin ruby"&gt;(&lt;/span&gt;&lt;span class="constant numeric ruby"&gt;2026&lt;/span&gt;&lt;span class="punctuation separator ruby"&gt;,&lt;/span&gt; &lt;span class="constant numeric ruby"&gt;5&lt;/span&gt;&lt;span class="punctuation separator ruby"&gt;,&lt;/span&gt; &lt;span class="constant numeric ruby"&gt;22&lt;/span&gt;&lt;span class="punctuation definition group end ruby"&gt;)&lt;/span&gt;&lt;span class="punctuation definition group end ruby"&gt;)&lt;/span&gt;
&lt;span class="comment line number-sign ruby"&gt;&lt;span class="punctuation definition comment ruby"&gt;#&lt;/span&gt; =&amp;gt; "Fri, 22 May 2026"
&lt;/span&gt;
localize&lt;span class="punctuation definition group begin ruby"&gt;(&lt;/span&gt;&lt;span class="support class ruby"&gt;Time&lt;/span&gt;&lt;span class="punctuation accessor ruby"&gt;.&lt;/span&gt;&lt;span class="keyword other special-method ruby"&gt;new&lt;/span&gt;&lt;span class="punctuation definition group begin ruby"&gt;(&lt;/span&gt;&lt;span class="constant numeric ruby"&gt;2026&lt;/span&gt;&lt;span class="punctuation separator ruby"&gt;,&lt;/span&gt; &lt;span class="constant numeric ruby"&gt;5&lt;/span&gt;&lt;span class="punctuation separator ruby"&gt;,&lt;/span&gt; &lt;span class="constant numeric ruby"&gt;22&lt;/span&gt;&lt;span class="punctuation separator ruby"&gt;,&lt;/span&gt; &lt;span class="constant numeric ruby"&gt;9&lt;/span&gt;&lt;span class="punctuation separator ruby"&gt;,&lt;/span&gt; &lt;span class="constant numeric ruby"&gt;5&lt;/span&gt;&lt;span class="punctuation definition group end ruby"&gt;)&lt;/span&gt;&lt;span class="punctuation separator ruby"&gt;,&lt;/span&gt; &lt;span class="constant other symbol ruby"&gt;format&lt;span class="punctuation definition constant ruby"&gt;:&lt;/span&gt;&lt;/span&gt; &lt;span class="constant other symbol ruby"&gt;&lt;span class="punctuation definition constant ruby"&gt;:&lt;/span&gt;short&lt;/span&gt;&lt;span class="punctuation definition group end ruby"&gt;)&lt;/span&gt;
&lt;span class="comment line number-sign ruby"&gt;&lt;span class="punctuation definition comment ruby"&gt;#&lt;/span&gt; =&amp;gt; "22 May 9:05 am"
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Like every aspect of Hanami, i18n is designed to work out of the box with minimal setup, but there are plenty of settings if you need something custom. Check out the &lt;a href="/learn/hanami/v3.0/i18n"&gt;i18n guide&lt;/a&gt; for the full picture.&lt;/p&gt;
&lt;p&gt;You can’t spell &lt;em&gt;internationalization&lt;/em&gt; without the i18n gem, which does all the heavy lifting for this new feature. So a big &lt;code&gt;en-AU&lt;/code&gt; “cheers, mates” to the &lt;a href="https://github.com/ruby-i18n/i18n/graphs/contributors?all=1"&gt;i18n maintainers&lt;/a&gt; — thank you for helping Rubyists the world over!&lt;/p&gt;
&lt;h2 id="now-with-minitest"&gt;
Now with Minitest&lt;a href="#now-with-minitest" aria-hidden="true" class="anchor"&gt;&lt;span aria-hidden="true" class="anchor"&gt;&lt;/span&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Hanami has always shipped with a ready-to-go RSpec setup. We’re delighted we can finally make the other half of you happy, thanks to our brand new Minitest support!&lt;/p&gt;
&lt;p&gt;Pick your testing framework when you generate an app:&lt;/p&gt;
&lt;div class="pre-wrapper" data-defo-copy-code&gt;
&lt;button type="button" class="pre-wrapper__button" aria-label="Copy"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" class="pre-wrapper__icon pre-wrapper__icon--copy" height="16" viewbox="0 0 256 256" width="16"&gt; &lt;path d="M172,164a12,12,0,0,1-12,12H96a12,12,0,0,1,0-24h64A12,12,0,0,1,172,164Zm-12-52H96a12,12,0,0,0,0,24h64a12,12,0,0,0,0-24Zm60-64V216a20,20,0,0,1-20,20H56a20,20,0,0,1-20-20V48A20,20,0,0,1,56,28H90.53a51.88,51.88,0,0,1,74.94,0H200A20,20,0,0,1,220,48ZM100.29,60h55.42a28,28,0,0,0-55.42,0ZM196,52H178.59A52.13,52.13,0,0,1,180,64v8a12,12,0,0,1-12,12H88A12,12,0,0,1,76,72V64a52.13,52.13,0,0,1,1.41-12H60V212H196Z"&gt;&lt;/path&gt; &lt;/svg&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" class="pre-wrapper__icon pre-wrapper__icon--check" height="16" viewbox="-13 0 276 276" width="16"&gt; &lt;path d="M232.49,80.49l-128,128a12,12,0,0,1-17,0l-56-56a12,12,0,1,1,17-17L96,183,215.51,63.51a12,12,0,0,1,17,17Z"&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/button&gt;&lt;pre class="syntax-highlighting"&gt;&lt;code&gt;&lt;span class="text plain"&gt;$ hanami new my_app --test=minitest
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;RSpec stays our default, but reach for Minitest and you’ll now get an equally complete setup, rather than having to build something yourself.&lt;/p&gt;
&lt;p&gt;A big thank you to Ryan Davis and all the contributors for their work on Minitest. Minitest ships with Ruby itself, and we’re glad to make it part of the Hanami story going forward.&lt;/p&gt;
&lt;h2 id="faster-by-default"&gt;
Faster by default&lt;a href="#faster-by-default" aria-hidden="true" class="anchor"&gt;&lt;span aria-hidden="true" class="anchor"&gt;&lt;/span&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Hanami 3.0 is significantly faster, and you can enjoy the benefits right from the get-go. In a &lt;a href="https://github.com/timriley/hanami-3.0-bench"&gt;test app&lt;/a&gt;, the same request runs &lt;strong&gt;around 3.7x faster over HTTP&lt;/strong&gt; while allocating a fraction of the memory.&lt;/p&gt;
&lt;p&gt;Hanami now &lt;strong&gt;memoizes your components by default&lt;/strong&gt;. This means that each component in your app’s containers is resolved just once and then reused, rather than built fresh every time it’s needed.&lt;/p&gt;
&lt;p&gt;This is the change you’ll really feel. We took an app whose action resolves a graph of nine components and renders a view, then measured the same request on 2.3 and 3.0. In 3.0, there were &lt;strong&gt;14x fewer allocations per request&lt;/strong&gt; and &lt;strong&gt;around 3.7x the throughput over HTTP&lt;/strong&gt; (and &lt;strong&gt;closer to 9x throughput&lt;/strong&gt; when measured in-process, where the server isn’t the bottleneck). Tail latency dropped too: p99 reduced from 20ms to 4ms as the per-request allocation churn and GC pauses went away.&lt;/p&gt;
&lt;p&gt;We also focused on improving performance across the hottest parts of the framework:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Hanami Action snapshots each action’s config up front rather than recomputing it per-request, and overall allocates far less per request. A minimal action drops from &lt;strong&gt;88 allocations to 14&lt;/strong&gt; — that’s &lt;strong&gt;84% fewer&lt;/strong&gt; — and runs around &lt;strong&gt;4.5x faster&lt;/strong&gt; in isolation.&lt;/li&gt;
&lt;li&gt;Hanami View gets the same config snapshot treatment, and also no longer decorates exposures by default. A minimal render drops from &lt;strong&gt;88 allocations to 39&lt;/strong&gt; and runs around &lt;strong&gt;2.9x faster&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The best part of all this? It’s a free lunch! Upgrade to 3.0 and your apps simply run faster, on less memory, all without any changes to your code.&lt;/p&gt;
&lt;p&gt;A special thank you to &lt;a href="https://github.com/cllns"&gt;Sean Collins&lt;/a&gt; for driving much of our performance work for 3.0. We love you 3.7x more than before!&lt;/p&gt;
&lt;h2 id="clearer-more-useful-logs"&gt;
Clearer, more useful logs&lt;a href="#clearer-more-useful-logs" aria-hidden="true" class="anchor"&gt;&lt;span aria-hidden="true" class="anchor"&gt;&lt;/span&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;We’ve given logs some love for 3.0, across both day-to-day development and production.&lt;/p&gt;
&lt;p&gt;In development, logs are now colorized by default. SQL statements are formatted to match your request logs, and they’re also syntax highlighted when the rouge gem is bundled.&lt;/p&gt;
&lt;p&gt;&lt;img src="/blog/assets/2026-06-30-hanami-3-0-in-full-bloom/logs.webp" alt="Hanami logs" width="2556" height="1564"&gt;&lt;/p&gt;
&lt;p&gt;SQL statements now log at the &lt;code&gt;:debug&lt;/code&gt; level rather than &lt;code&gt;:info&lt;/code&gt;, for quieter production logs, and you can tune this with &lt;code&gt;config.db.log_level&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;You can also conveniently set the log level from the env with &lt;code&gt;HANAMI_LOG_LEVEL&lt;/code&gt;, which takes precedence over any config in your app class.&lt;/p&gt;
&lt;p&gt;Underneath, Hanami now guarantees a consistent interface for its logger (even if you configure a third-party replacement), so you can always count on:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Structured logging&lt;/strong&gt;, via keyword args passed to the standard log methods.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tagged logging&lt;/strong&gt;, via &lt;code&gt;#tagged&lt;/code&gt; blocks.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Read our &lt;a href="/learn/hanami/v3.0/logger"&gt;revamped logger guide&lt;/a&gt; to learn more.&lt;/p&gt;
&lt;h2 id="smoother-asset-watching"&gt;
Smoother asset watching&lt;a href="#smoother-asset-watching" aria-hidden="true" class="anchor"&gt;&lt;span aria-hidden="true" class="anchor"&gt;&lt;/span&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;hanami assets watch&lt;/code&gt; now keeps pace with more of your work: it picks up newly added and removed entry points, and reacts to changes in static assets like images and fonts. In earlier versions, each of these meant restarting the watcher. Now it just keeps up, so you can stay in the flow!&lt;/p&gt;
&lt;p&gt;We also published a &lt;a href="https://github.com/hanami/hanami-assets/blob/main/SPEC.md"&gt;spec&lt;/a&gt; covering how any asset bundler can plug cleanly into Hanami. Our own bundler is based on esbuild, but we don’t want you to feel locked in! We’d love to see you bring your favorite bundler to Hanami.&lt;/p&gt;
&lt;h2 id="body-parsing-comes-to-hanami-action"&gt;
Body parsing comes to Hanami Action&lt;a href="#body-parsing-comes-to-hanami-action" aria-hidden="true" class="anchor"&gt;&lt;span aria-hidden="true" class="anchor"&gt;&lt;/span&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Hanami’s request body parsing has moved out of middleware and into Hanami Action, where it’s now driven by your &lt;code&gt;formats&lt;/code&gt; config. Your actions parse exactly the formats you accept, and you can configure this right alongside the rest of your content negotiation.&lt;/p&gt;
&lt;p&gt;Parsers for multipart form bodies and JSON work out of the box. And if you need something else, you can register your own:&lt;/p&gt;
&lt;div class="pre-wrapper" data-defo-copy-code&gt;
&lt;button type="button" class="pre-wrapper__button" aria-label="Copy"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" class="pre-wrapper__icon pre-wrapper__icon--copy" height="16" viewbox="0 0 256 256" width="16"&gt; &lt;path d="M172,164a12,12,0,0,1-12,12H96a12,12,0,0,1,0-24h64A12,12,0,0,1,172,164Zm-12-52H96a12,12,0,0,0,0,24h64a12,12,0,0,0,0-24Zm60-64V216a20,20,0,0,1-20,20H56a20,20,0,0,1-20-20V48A20,20,0,0,1,56,28H90.53a51.88,51.88,0,0,1,74.94,0H200A20,20,0,0,1,220,48ZM100.29,60h55.42a28,28,0,0,0-55.42,0ZM196,52H178.59A52.13,52.13,0,0,1,180,64v8a12,12,0,0,1-12,12H88A12,12,0,0,1,76,72V64a52.13,52.13,0,0,1,1.41-12H60V212H196Z"&gt;&lt;/path&gt; &lt;/svg&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" class="pre-wrapper__icon pre-wrapper__icon--check" height="16" viewbox="-13 0 276 276" width="16"&gt; &lt;path d="M232.49,80.49l-128,128a12,12,0,0,1-17,0l-56-56a12,12,0,1,1,17-17L96,183,215.51,63.51a12,12,0,0,1,17,17Z"&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/button&gt;&lt;pre class="syntax-highlighting"&gt;&lt;code&gt;&lt;span class="source ruby"&gt;formats&lt;span class="punctuation accessor ruby"&gt;.&lt;/span&gt;register&lt;span class="punctuation definition group begin ruby"&gt;(&lt;/span&gt;&lt;span class="constant other symbol ruby"&gt;&lt;span class="punctuation definition constant ruby"&gt;:&lt;/span&gt;custom&lt;/span&gt;&lt;span class="punctuation separator ruby"&gt;,&lt;/span&gt; &lt;span class="string quoted double ruby"&gt;&lt;span class="punctuation definition string begin ruby"&gt;"&lt;/span&gt;application/custom&lt;span class="punctuation definition string end ruby"&gt;"&lt;/span&gt;&lt;/span&gt;&lt;span class="punctuation separator ruby"&gt;,&lt;/span&gt; &lt;span class="constant other symbol ruby"&gt;parser&lt;span class="punctuation definition constant ruby"&gt;:&lt;/span&gt;&lt;/span&gt; &lt;span class="keyword operator arithmetic ruby"&gt;-&lt;/span&gt;&lt;span class="keyword operator comparison ruby"&gt;&amp;gt;&lt;/span&gt;&lt;span class="punctuation definition group begin ruby"&gt;(&lt;/span&gt;body&lt;span class="punctuation separator ruby"&gt;,&lt;/span&gt; env&lt;span class="punctuation definition group end ruby"&gt;)&lt;/span&gt; &lt;span class="punctuation section scope ruby"&gt;{&lt;/span&gt; &lt;span class="keyword operator ruby"&gt;...&lt;/span&gt; &lt;span class="punctuation section scope ruby"&gt;}&lt;/span&gt;&lt;span class="punctuation definition group end ruby"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Learn more in our &lt;a href="/learn/hanami/v3.0/actions/formats-and-media-types"&gt;formats and media types&lt;/a&gt; guide.&lt;/p&gt;
&lt;h2 id="simpler-views-with-undecorated-exposures"&gt;
Simpler views with undecorated exposures&lt;a href="#simpler-views-with-undecorated-exposures" aria-hidden="true" class="anchor"&gt;&lt;span aria-hidden="true" class="anchor"&gt;&lt;/span&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;&lt;a href="/learn/hanami/v3.0/views/input-and-exposures"&gt;View exposures&lt;/a&gt; are now undecorated by default. Your templates receive exactly what you expose, with no decoration unless you ask for it. This is a more predictable default, and avoids extra work when decoration isn’t strictly required.&lt;/p&gt;
&lt;p&gt;When you do want to decorate, the new &lt;code&gt;.decorate&lt;/code&gt; method makes those exposures stand out in your code. You can also bring back the old behaviour across a view with &lt;code&gt;config.decorate_exposures = true&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id="a-cleaner-foundation"&gt;
A cleaner foundation&lt;a href="#a-cleaner-foundation" aria-hidden="true" class="anchor"&gt;&lt;span aria-hidden="true" class="anchor"&gt;&lt;/span&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;A major new version is a chance to put the house in order:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;hanami-controller is now hanami-action.&lt;/strong&gt; The gem name finally matches the classes we’ve been using for years. Require it as &lt;code&gt;hanami-action&lt;/code&gt; or &lt;code&gt;hanami/action&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;hanami-validations has been retired.&lt;/strong&gt; Hanami Action now reaches for dry-validation directly for your action’s params and contracts, with one fewer gem in between.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Hanami 3.0 also requires Ruby 3.3 or newer.&lt;/p&gt;
&lt;p&gt;The result is fewer moving parts, clearer names for the gems we use, and a more approachable Hanami overall.&lt;/p&gt;
&lt;h2 id="and-much-more"&gt;
And much more!&lt;a href="#and-much-more" aria-hidden="true" class="anchor"&gt;&lt;span aria-hidden="true" class="anchor"&gt;&lt;/span&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;We’ve landed plenty of smaller refinements in 3.0 too:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;New &lt;code&gt;hanami generate provider&lt;/code&gt; and &lt;code&gt;hanami generate mailer&lt;/code&gt; generators.&lt;/li&gt;
&lt;li&gt;A &lt;code&gt;--force&lt;/code&gt; option across all generators, to overwrite existing files instead of stopping.&lt;/li&gt;
&lt;li&gt;A &lt;code&gt;--name&lt;/code&gt; option for &lt;code&gt;hanami new&lt;/code&gt;, to set the app namespace separately from the directory path: &lt;code&gt;hanami new my_bookshelf --name=bookshelf&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--gem-source=gem.coop&lt;/code&gt; for &lt;code&gt;hanami new&lt;/code&gt; installs gems &lt;a href="https://gem.coop/@hanami"&gt;from&lt;/a&gt; &lt;a href="https://gem.coop/@dry"&gt;our&lt;/a&gt; gem.coop namespaces.&lt;/li&gt;
&lt;li&gt;Generated apps require Puma 7.1 and drop app preloading boilerplate from &lt;code&gt;config/puma.rb&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;A &lt;code&gt;--template-engine&lt;/code&gt; option for &lt;code&gt;hanami new&lt;/code&gt; and &lt;code&gt;hanami generate&lt;/code&gt; creates templates for the given engine (&lt;code&gt;erb&lt;/code&gt;, &lt;code&gt;haml&lt;/code&gt;, or &lt;code&gt;slim&lt;/code&gt;). Set a project-wide default with &lt;code&gt;config.default_template_engine&lt;/code&gt; in your app class.&lt;/li&gt;
&lt;li&gt;Explicit redirect helpers in the router: &lt;code&gt;permanent_redirect&lt;/code&gt; (301) and &lt;code&gt;temporary_redirect&lt;/code&gt; (302), with plain &lt;code&gt;redirect&lt;/code&gt; now requiring an explicit &lt;code&gt;code:&lt;/code&gt; argument for clarity.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Hanami::Settings::CompositeStore&lt;/code&gt; for chaining settings lookups across multiple stores.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Hanami::Slice.with_slices&lt;/code&gt; returns a slice together with all its nested slices.&lt;/li&gt;
&lt;li&gt;Hanami View exposes the currently-rendering template name as &lt;code&gt;Hanami::View::Scope#template_name&lt;/code&gt; and &lt;code&gt;Hanami::View::Context#current_template_name&lt;/code&gt; (this supports our relative i18n key lookups).&lt;/li&gt;
&lt;li&gt;Raise a helpful error when a slice is called as a Rack app with no routes available.&lt;/li&gt;
&lt;li&gt;Various fixes: multipart uploads to the router, URL generation with array variables, duplicate routes on &lt;code&gt;generate action&lt;/code&gt;, and more.&lt;/li&gt;
&lt;li&gt;A beautiful new welcome screen, matching our Hanakai visuals. (Thank you &lt;a href="https://github.com/makenosound"&gt;Max&lt;/a&gt;!)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src="/blog/assets/2026-06-30-hanami-3-0-in-full-bloom/hanami-3-welcome-light.webp" alt="Welcome screen in light mode" width="3158" height="2264"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="/blog/assets/2026-06-30-hanami-3-0-in-full-bloom/hanami-3-welcome-dark.webp" alt="Welcome screen in dark mode" width="3158" height="2264"&gt;&lt;/p&gt;
&lt;h2 id="try-it-out"&gt;
Try it out&lt;a href="#try-it-out" aria-hidden="true" class="anchor"&gt;&lt;span aria-hidden="true" class="anchor"&gt;&lt;/span&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;You’re only a few commands away from a new Hanami 3.0 app:&lt;/p&gt;
&lt;div class="pre-wrapper" data-defo-copy-code&gt;
&lt;button type="button" class="pre-wrapper__button" aria-label="Copy"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" class="pre-wrapper__icon pre-wrapper__icon--copy" height="16" viewbox="0 0 256 256" width="16"&gt; &lt;path d="M172,164a12,12,0,0,1-12,12H96a12,12,0,0,1,0-24h64A12,12,0,0,1,172,164Zm-12-52H96a12,12,0,0,0,0,24h64a12,12,0,0,0,0-24Zm60-64V216a20,20,0,0,1-20,20H56a20,20,0,0,1-20-20V48A20,20,0,0,1,56,28H90.53a51.88,51.88,0,0,1,74.94,0H200A20,20,0,0,1,220,48ZM100.29,60h55.42a28,28,0,0,0-55.42,0ZM196,52H178.59A52.13,52.13,0,0,1,180,64v8a12,12,0,0,1-12,12H88A12,12,0,0,1,76,72V64a52.13,52.13,0,0,1,1.41-12H60V212H196Z"&gt;&lt;/path&gt; &lt;/svg&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" class="pre-wrapper__icon pre-wrapper__icon--check" height="16" viewbox="-13 0 276 276" width="16"&gt; &lt;path d="M232.49,80.49l-128,128a12,12,0,0,1-17,0l-56-56a12,12,0,1,1,17-17L96,183,215.51,63.51a12,12,0,0,1,17,17Z"&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/button&gt;&lt;pre class="syntax-highlighting"&gt;&lt;code&gt;&lt;span class="text plain"&gt;$ gem install hanami
$ hanami new my_app
$ cd my_app
$ bin/hanami dev
$ open http://localhost:2300
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;We’d love to hear how you go! Come say hi in our &lt;a href="https://discourse.hanakai.org"&gt;forum&lt;/a&gt; or our &lt;a href="https://discord.gg/KFCxDmk3JQ"&gt;chat&lt;/a&gt;. Our community is super friendly and always willing to help you on your Hanami journey.&lt;/p&gt;
&lt;h2 id="upgrading-from-23"&gt;
Upgrading from 2.3&lt;a href="#upgrading-from-23" aria-hidden="true" class="anchor"&gt;&lt;span aria-hidden="true" class="anchor"&gt;&lt;/span&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Already on 2.3? Our &lt;a href="/learn/hanami/v3.0/upgrade-notes"&gt;3.0 upgrade notes&lt;/a&gt; walk you through every step.&lt;/p&gt;
&lt;h2 id="thank-you-to-our-contributors"&gt;
Thank you to our contributors!&lt;a href="#thank-you-to-our-contributors" aria-hidden="true" class="anchor"&gt;&lt;span aria-hidden="true" class="anchor"&gt;&lt;/span&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Thank you to everyone who contributed to this release:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/aaronmallen"&gt;Aaron Allen&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/adamlassek"&gt;Adam Lassek&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/carolyncole"&gt;Carolyn Cole&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/inouire"&gt;Edouard&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/sandbergja"&gt;Jane Sandberg&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/joshuay03"&gt;Joshua Young&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/rkh"&gt;Konstantin Haase&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/kyleplump"&gt;Kyle Plump&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/StantonMatt"&gt;Matthew Stanton&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/makenosound"&gt;Max Wheeler&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/katafrakt"&gt;Paweł Świątkowski&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/parndt"&gt;Philip Arndt&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/rvmtz"&gt;Ramón Valles&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/cllns"&gt;Sean Collins&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/timriley"&gt;Tim Riley&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/wout"&gt;Wout&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/yosangwon"&gt;Yi Sangwon&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="thank-you-to-our-sponsors"&gt;
Thank you to our sponsors!&lt;a href="#thank-you-to-our-sponsors" aria-hidden="true" class="anchor"&gt;&lt;span aria-hidden="true" class="anchor"&gt;&lt;/span&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;This release is another huge step forward for Hanami, and there’s no way we could have done this without the support of our &lt;a href="/sponsor"&gt;sponsors&lt;/a&gt;. Thank you, from the bottom of my heart!&lt;/p&gt;
&lt;p&gt;Thank you to our business sponsors:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://sidekiq.org"&gt;Sidekiq&lt;/a&gt;&lt;/strong&gt;, our Platinum sponsor.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/baweaver"&gt;Brandon Weaver&lt;/a&gt;&lt;/strong&gt;, our Gold sponsor.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://www.honeybadger.io"&gt;Honeybadger&lt;/a&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;a href="https://www.fastruby.io"&gt;FastRuby.io&lt;/a&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;a href="https://www.appsignal.com"&gt;AppSignal&lt;/a&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;a href="https://serpapi.com"&gt;SerpApi&lt;/a&gt;&lt;/strong&gt;, our Silver sponsors.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And thank you to all the individuals supporting Hanakai through &lt;a href="https://github.com/sponsors/hanami"&gt;GitHub Sponsors&lt;/a&gt; and &lt;a href="https://opencollective.com/hanami"&gt;Open Collective&lt;/a&gt;. Your encouragement means the world!&lt;/p&gt;
&lt;p&gt;Hanami is in full bloom today, but a garden is never finished, and there’s plenty more we want to grow. Your support is what makes that possible. We’d love for you to &lt;a href="/sponsor"&gt;become a sponsor&lt;/a&gt;. &lt;svg class="emoji-logo emoji-logo--hanami inline" height="1em" width="1em" viewbox="0 0 164 159" fill="none" xmlns="http://www.w3.org/2000/svg"&gt; &lt;path fill-rule="evenodd" clip-rule="evenodd" d="m39.3087 98.5899c-3.805.37-7.7441-.02-11.6091-1.28l-7.8299-2.54c-15.09004-4.91-23.36005-21.14-18.45705-36.23s21.13505-23.36 36.22405-18.46l7.8309 2.55c3.864 1.25 7.281 3.25 10.145 5.79-1.524-3.51-2.369-7.3799-2.369-11.4399v-8.2301c0-15.87 12.8821-28.75003733 28.7481-28.75003733s28.7483 12.88003733 28.7483 28.75003733v8.2301c0 4.06-.845 7.9299-2.368 11.4399 2.863-2.54 6.28-4.54 10.145-5.79l7.83-2.55c15.09-4.9 31.321 3.37 36.224 18.46s-3.367 31.32-18.457 36.23l-7.83 2.54c-3.865 1.26-7.804 1.65-11.609 1.28 3.293 1.9401 6.25 4.5801 8.638 7.8601l4.84 6.663c9.326 12.837 6.476 30.829-6.36 40.155-12.837 9.327-30.829 6.477-40.1553-6.359l-4.84-6.661c-2.388-3.288-3.978-6.913-4.806-10.645-.828 3.732-2.418 7.357-4.806 10.645l-4.8391 6.661c-9.326 12.836-27.319 15.686-40.156 6.359-12.836-9.326-15.6859-27.318-6.3589-40.155l4.839-6.663c2.388-3.28 5.345-5.92 8.638-7.8601z" fill="#FF6C89"&gt;&lt;/path&gt; &lt;path d="m81.9919 50.5298c18.2971 0 33.1521 14.8601 33.1521 33.1601 0 18.2901-14.855 33.1481-33.1521 33.1481-18.297 0-33.1521-14.858-33.1521-33.1481 0-18.3 14.8551-33.1601 33.1521-33.1601z" fill="#FFC9C4"&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/p&gt;</content>
  </entry>
  <entry>
    <title>Help us test the Hanami 3.0 release candidate</title>
    <link rel="alternate" href="https://hanakai.org/blog/2026/06/16/help-us-test-hanami-3-0"/>
    <id>https://hanakai.org/blog/2026/06/16/help-us-test-hanami-3-0</id>
    <published>2026-06-16T13:00:00+00:00</published>
    <updated>2026-06-16T13:00:00+00:00</updated>
    <author>
      <name>Tim Riley</name>
    </author>
    <content type="html">&lt;p&gt;Today we’re sharing the &lt;strong&gt;release candidate for Hanami 3.0&lt;/strong&gt;, feature-complete and ready for testing. We’d love your help to give it a good workout before our final release—which, all going well, will be in just a couple of weeks!&lt;/p&gt;
&lt;h2 id="whats-coming-in-30"&gt;
What’s coming in 3.0&lt;a href="#whats-coming-in-30" aria-hidden="true" class="anchor"&gt;&lt;span aria-hidden="true" class="anchor"&gt;&lt;/span&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;There’s a lot I’m excited for in 3.0, but I’ll save the full announcement for when it ships. For now, here’s where we’d love your help with testing.&lt;/p&gt;
&lt;h3 id="built-in-i18n"&gt;
Built-in i18n&lt;a href="#built-in-i18n" aria-hidden="true" class="anchor"&gt;&lt;span aria-hidden="true" class="anchor"&gt;&lt;/span&gt;&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;Internationalization is now a built-in feature. Bundle the &lt;code&gt;i18n&lt;/code&gt; gem and Hanami loads your translations and makes translation and localization helpers available across your views and actions. See &lt;a href="https://discourse.hanakai.org/t/previewing-i18n-integration-in-hanami-3-0/1400/6"&gt;Previewing i18n integration in Hanami 3.0&lt;/a&gt; for details.&lt;/p&gt;
&lt;h3 id="first-class-mailers"&gt;
First-class mailers&lt;a href="#first-class-mailers" aria-hidden="true" class="anchor"&gt;&lt;span aria-hidden="true" class="anchor"&gt;&lt;/span&gt;&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;We’ve rebuilt &lt;a href="https://github.com/hanami/hanami-mailer"&gt;Hanami Mailer&lt;/a&gt; and integrated it into the framework, with generators, templates, and SMTP delivery. See &lt;a href="https://discourse.hanakai.org/t/previewing-mailers-in-hanami-3-0/1462/3"&gt;Previewing mailers in Hanami 3.0&lt;/a&gt; for more.&lt;/p&gt;
&lt;h3 id="minitest-support"&gt;
Minitest support&lt;a href="#minitest-support" aria-hidden="true" class="anchor"&gt;&lt;span aria-hidden="true" class="anchor"&gt;&lt;/span&gt;&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;We’ve created a new &lt;a href="https://github.com/hanami/hanami-minitest"&gt;Hanami Minitest&lt;/a&gt; gem to give you a fully integrated Minitest setup. Activate it with &lt;code&gt;hanami new --test=minitest&lt;/code&gt;. See all the details in &lt;a href="https://discourse.hanakai.org/t/feedback-on-hanami-minitest/1415/10"&gt;Feedback on Hanami Minitest&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id="memoized-components"&gt;
Memoized components&lt;a href="#memoized-components" aria-hidden="true" class="anchor"&gt;&lt;span aria-hidden="true" class="anchor"&gt;&lt;/span&gt;&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;Container components are now memoized by default: each is resolved once and reused, instead of being built fresh each time. This is one of several performance improvements landing in 3.0, and a good one to test. If you have a component that cannot safely be memoized, you can opt it out.&lt;/p&gt;
&lt;h3 id="improved-logging"&gt;
Improved logging&lt;a href="#improved-logging" aria-hidden="true" class="anchor"&gt;&lt;span aria-hidden="true" class="anchor"&gt;&lt;/span&gt;&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;Web and SQL logs are colorized by default in development. SQL queries are now logged as consistently structured entries, syntax highlighted when the &lt;code&gt;rouge&lt;/code&gt; gem is bundled. SQL logs are now emitted at the &lt;code&gt;:debug&lt;/code&gt; level for cleaner production logs, which you can adjust with &lt;code&gt;config.db.log_level&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Hanami ensures that structured and tagged logging is available even if you configure your own alternative logger. Emit structured logs via keyword args on the main log methods, and tagged logs via &lt;code&gt;tagged&lt;/code&gt; blocks. You can also now control the overall app log level via a &lt;code&gt;HANAMI_LOG_LEVEL&lt;/code&gt; env var.&lt;/p&gt;
&lt;h3 id="smoother-asset-watching"&gt;
Smoother asset watching&lt;a href="#smoother-asset-watching" aria-hidden="true" class="anchor"&gt;&lt;span aria-hidden="true" class="anchor"&gt;&lt;/span&gt;&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;hanami assets watch&lt;/code&gt; now keeps up with more of your changes: it picks up newly added or removed entry points, and reacts to edits to static assets like images and fonts. Previously, both meant restarting the watcher.&lt;/p&gt;
&lt;h3 id="other-changes"&gt;
Other changes&lt;a href="#other-changes" aria-hidden="true" class="anchor"&gt;&lt;span aria-hidden="true" class="anchor"&gt;&lt;/span&gt;&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;Here are a few more changes worth flagging, especially if you’re upgrading an existing app:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The actions gem is renamed from hanami-controller to hanami-action.&lt;/li&gt;
&lt;li&gt;The hanami-validations gem is retired. Hanami Action now checks for dry-validation directly.&lt;/li&gt;
&lt;li&gt;Views default to undecorated exposures.&lt;/li&gt;
&lt;li&gt;Request body parsing has moved into Hanami Action, driven by your formats config.&lt;/li&gt;
&lt;li&gt;Hanami now requires Ruby 3.3 or newer.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="upgrading-an-existing-app"&gt;
Upgrading an existing app&lt;a href="#upgrading-an-existing-app" aria-hidden="true" class="anchor"&gt;&lt;span aria-hidden="true" class="anchor"&gt;&lt;/span&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Already on 2.3? Our &lt;a href="/learn/hanami/v3.0/upgrade-notes"&gt;3.0 upgrade notes&lt;/a&gt; walk you through every step, from the required changes through to the optional new features above.&lt;/p&gt;
&lt;h2 id="try-it-out"&gt;
Try it out&lt;a href="#try-it-out" aria-hidden="true" class="anchor"&gt;&lt;span aria-hidden="true" class="anchor"&gt;&lt;/span&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;You can step into the 3.0 future with just a few commands:&lt;/p&gt;
&lt;div class="pre-wrapper" data-defo-copy-code&gt;
&lt;button type="button" class="pre-wrapper__button" aria-label="Copy"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" class="pre-wrapper__icon pre-wrapper__icon--copy" height="16" viewbox="0 0 256 256" width="16"&gt; &lt;path d="M172,164a12,12,0,0,1-12,12H96a12,12,0,0,1,0-24h64A12,12,0,0,1,172,164Zm-12-52H96a12,12,0,0,0,0,24h64a12,12,0,0,0,0-24Zm60-64V216a20,20,0,0,1-20,20H56a20,20,0,0,1-20-20V48A20,20,0,0,1,56,28H90.53a51.88,51.88,0,0,1,74.94,0H200A20,20,0,0,1,220,48ZM100.29,60h55.42a28,28,0,0,0-55.42,0ZM196,52H178.59A52.13,52.13,0,0,1,180,64v8a12,12,0,0,1-12,12H88A12,12,0,0,1,76,72V64a52.13,52.13,0,0,1,1.41-12H60V212H196Z"&gt;&lt;/path&gt; &lt;/svg&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" class="pre-wrapper__icon pre-wrapper__icon--check" height="16" viewbox="-13 0 276 276" width="16"&gt; &lt;path d="M232.49,80.49l-128,128a12,12,0,0,1-17,0l-56-56a12,12,0,1,1,17-17L96,183,215.51,63.51a12,12,0,0,1,17,17Z"&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/button&gt;&lt;pre class="syntax-highlighting"&gt;&lt;code&gt;&lt;span class="text plain"&gt;$ gem install hanami --pre
$ hanami new my_app
$ cd my_app
$ bin/hanami dev
$ open http://localhost:2300
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id="tell-us-how-you-go"&gt;
Tell us how you go!&lt;a href="#tell-us-how-you-go" aria-hidden="true" class="anchor"&gt;&lt;span aria-hidden="true" class="anchor"&gt;&lt;/span&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;This is the moment your feedback makes the biggest difference. If you hit a snag or just want to share how it went, come talk to us on our &lt;a href="https://discourse.hanakai.org"&gt;forum&lt;/a&gt; or &lt;a href="https://discord.gg/KFCxDmk3JQ"&gt;chat&lt;/a&gt;. We’d love to hear from you!&lt;/p&gt;
&lt;p&gt;Thank you to everyone who’s helped on the road to 3.0, and thanks in advance to everyone about to help us test it. &lt;svg class="emoji-logo emoji-logo--hanami inline" height="1em" width="1em" viewbox="0 0 164 159" fill="none" xmlns="http://www.w3.org/2000/svg"&gt; &lt;path fill-rule="evenodd" clip-rule="evenodd" d="m39.3087 98.5899c-3.805.37-7.7441-.02-11.6091-1.28l-7.8299-2.54c-15.09004-4.91-23.36005-21.14-18.45705-36.23s21.13505-23.36 36.22405-18.46l7.8309 2.55c3.864 1.25 7.281 3.25 10.145 5.79-1.524-3.51-2.369-7.3799-2.369-11.4399v-8.2301c0-15.87 12.8821-28.75003733 28.7481-28.75003733s28.7483 12.88003733 28.7483 28.75003733v8.2301c0 4.06-.845 7.9299-2.368 11.4399 2.863-2.54 6.28-4.54 10.145-5.79l7.83-2.55c15.09-4.9 31.321 3.37 36.224 18.46s-3.367 31.32-18.457 36.23l-7.83 2.54c-3.865 1.26-7.804 1.65-11.609 1.28 3.293 1.9401 6.25 4.5801 8.638 7.8601l4.84 6.663c9.326 12.837 6.476 30.829-6.36 40.155-12.837 9.327-30.829 6.477-40.1553-6.359l-4.84-6.661c-2.388-3.288-3.978-6.913-4.806-10.645-.828 3.732-2.418 7.357-4.806 10.645l-4.8391 6.661c-9.326 12.836-27.319 15.686-40.156 6.359-12.836-9.326-15.6859-27.318-6.3589-40.155l4.839-6.663c2.388-3.28 5.345-5.92 8.638-7.8601z" fill="#FF6C89"&gt;&lt;/path&gt; &lt;path d="m81.9919 50.5298c18.2971 0 33.1521 14.8601 33.1521 33.1601 0 18.2901-14.855 33.1481-33.1521 33.1481-18.297 0-33.1521-14.858-33.1521-33.1481 0-18.3 14.8551-33.1601 33.1521-33.1601z" fill="#FFC9C4"&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/p&gt;</content>
  </entry>
  <entry>
    <title>Welcome, SerpApi!</title>
    <link rel="alternate" href="https://hanakai.org/blog/2026/05/29/welcome-serpapi"/>
    <id>https://hanakai.org/blog/2026/05/29/welcome-serpapi</id>
    <published>2026-05-29T04:00:00+00:00</published>
    <updated>2026-05-29T04:00:00+00:00</updated>
    <author>
      <name>Tim Riley</name>
    </author>
    <content type="html">&lt;p&gt;We’re thrilled to welcome &lt;a href="https://serpapi.com"&gt;&lt;strong&gt;SerpApi&lt;/strong&gt;&lt;/a&gt; as a new silver-tier Hanakai sponsor!&lt;/p&gt;
&lt;div style="background: #fff; border-radius: 12px; padding: 2rem; margin: 0 auto calc(var(--spacing) * 3); max-width: 500px;"&gt;
  &lt;a href="https://serpapi.com" target="_blank"&gt;&lt;img src="/blog/assets/2026-05-29-welcome-serpapi/serp-api.webp" alt="SerpApi logo" style="display: block; margin: 0 auto; width: 100%;" width="690" height="178"&gt;&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;SerpApi is the world’s leading provider of search data, pioneering APIs that turn search engine results into structured, developer-ready information. Founded in 2017, the company enables developers and organizations around the world to integrate live search insights from sources like Google, Bing, and YouTube.&lt;/p&gt;
&lt;p&gt;SerpApi comes on board as we near the first anniversary of our &lt;a href="/sponsor"&gt;sponsorship program&lt;/a&gt;. Support like this has been instrumental in everything we’ve achieved this past year: &lt;a href="/blog/2025/11/12/hanami-23-racked-and-ready"&gt;shipping Hanami 2.3&lt;/a&gt;, &lt;a href="/blog/2026/05/01/welcome-to-hanakai"&gt;launching Hanakai&lt;/a&gt;, and cooking up a very special Hanami 3.0 release—more on that one soon!&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;SerpApi is proud to sponsor open source community initiatives and support the continued development of the Hanakai projects. At SerpApi, we are Rubyists at heart and want to see our ecosystem grow.&lt;/p&gt;
&lt;p&gt;— Josef Strzibny, Ruby Developer Advocate, &lt;a href="https://serpapi.com"&gt;SerpApi&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Thank you to Josef and the SerpApi team for reaching out to us and making this happen! Your support brings life to Hanakai and our vision for Ruby.&lt;/p&gt;
&lt;p&gt;If you or your business would like to join SerpApi in supporting our work, check out our &lt;a href="/sponsor"&gt;sponsorship options&lt;/a&gt;. We have something for everyone, and we’d love to welcome you to the family!&lt;/p&gt;</content>
  </entry>
  <entry>
    <title>Welcome to Hanakai</title>
    <link rel="alternate" href="https://hanakai.org/blog/2026/05/01/welcome-to-hanakai"/>
    <id>https://hanakai.org/blog/2026/05/01/welcome-to-hanakai</id>
    <published>2026-05-01T02:00:00+00:00</published>
    <updated>2026-05-01T02:00:00+00:00</updated>
    <author>
      <name>Tim Riley</name>
    </author>
    <content type="html">&lt;p&gt;If you’ve followed Hanami for a while, you’ll know we’re rather fond of flowers. Today our garden has grown: &lt;a href="/hanami"&gt;Hanami&lt;/a&gt;, &lt;a href="/dry"&gt;Dry&lt;/a&gt;, and &lt;a href="/rom"&gt;Rom&lt;/a&gt; — three projects that have lived alongside each other across a decade and billions of downloads — are finally coming together as one. Welcome to Hanakai! &lt;svg class="emoji-logo emoji-logo--hanakai inline" height="1em" width="1em" viewbox="0 0 216 216" fill="none" xmlns="http://www.w3.org/2000/svg"&gt; &lt;path d="M108.094 183.847C149.982 183.847 183.94 149.89 183.94 108.001C183.94 66.1126 149.982 32.1553 108.094 32.1553C66.2055 32.1553 32.248 66.1126 32.248 108.001C32.248 149.89 66.2055 183.847 108.094 183.847Z" fill="#FFD33B"&gt;&lt;/path&gt; &lt;path fill-rule="evenodd" clip-rule="evenodd" d="M109.27 0.0117188C112.826 0.0117188 115.705 2.90545 115.705 6.45546V20.1539C115.705 23.7039 112.826 26.5984 109.27 26.5984H106.73C103.174 26.5984 100.295 23.7039 100.295 20.1539C100.295 15.9865 100.295 10.5843 100.295 6.45546C100.295 2.90545 103.174 0.0117188 106.73 0.0117188H109.27Z" fill="#FFD33B"&gt;&lt;/path&gt; &lt;path fill-rule="evenodd" clip-rule="evenodd" d="M67.8515 7.74309C71.137 6.38221 74.9041 7.95397 76.2627 11.2338C77.8427 15.0483 79.91 20.0393 81.5048 23.8895C82.8633 27.1692 81.3113 30.9451 78.0258 32.306L75.679 33.278C72.3936 34.6389 68.6262 33.0665 67.2676 29.7867C65.6728 25.9365 63.6055 20.9455 62.0255 17.131C60.667 13.8512 62.2193 10.076 65.5048 8.71515L67.8515 7.74309Z" fill="#FFD33B"&gt;&lt;/path&gt; &lt;path fill-rule="evenodd" clip-rule="evenodd" d="M32.5437 30.7249C35.0583 28.2103 39.1401 28.2208 41.6503 30.731L51.3366 40.4173C53.8468 42.9275 53.8578 47.0099 51.3432 49.5245L49.5471 51.3206C47.0325 53.8352 42.9501 53.8242 40.4399 51.3139L30.7537 41.6277C28.2434 39.1175 28.2329 35.0356 30.7475 32.521L32.5437 30.7249Z" fill="#FFD33B"&gt;&lt;/path&gt; &lt;path fill-rule="evenodd" clip-rule="evenodd" d="M8.7237 65.4844C10.0846 62.1989 13.8597 60.6466 17.1395 62.0051L29.7952 67.2473C33.075 68.6058 34.6475 72.3732 33.2866 75.6587L32.3145 78.0054C30.9537 81.2909 27.1778 82.843 23.898 81.4844L11.2423 76.2423C7.96252 74.8837 6.39076 71.1166 7.75164 67.8312L8.7237 65.4844Z" fill="#FFD33B"&gt;&lt;/path&gt; &lt;path fill-rule="evenodd" clip-rule="evenodd" d="M0.0117188 106.727C0.0117188 103.171 2.90545 100.292 6.45546 100.292H20.1539C23.7039 100.292 26.5984 103.171 26.5984 106.727V109.267C26.5984 112.823 23.7039 115.702 20.1539 115.702H6.45546C2.90545 115.702 0.0117188 112.823 0.0117188 109.267C0.0117188 108.42 0.0117188 107.574 0.0117188 106.727Z" fill="#FFD33B"&gt;&lt;/path&gt; &lt;path fill-rule="evenodd" clip-rule="evenodd" d="M7.74309 148.146C6.38221 144.86 7.95397 141.093 11.2338 139.734L23.8895 134.492C27.1692 133.134 30.9451 134.686 32.306 137.971C32.63 138.754 32.954 139.536 33.278 140.318C34.6389 143.603 33.0665 147.371 29.7867 148.729L17.131 153.972C13.8512 155.33 10.076 153.778 8.71515 150.492C8.39113 149.71 8.06711 148.928 7.74309 148.146Z" fill="#FFD33B"&gt;&lt;/path&gt; &lt;path fill-rule="evenodd" clip-rule="evenodd" d="M30.7249 183.453C28.2103 180.939 28.2208 176.857 30.731 174.347C33.6505 171.427 37.4705 167.607 40.4173 164.661C42.9275 162.15 47.0099 162.139 49.5245 164.654L51.3206 166.45C53.8352 168.965 53.8242 173.047 51.3139 175.557L41.6277 185.243C39.1175 187.754 35.0356 187.764 32.521 185.25L30.7249 183.453Z" fill="#FFD33B"&gt;&lt;/path&gt; &lt;path fill-rule="evenodd" clip-rule="evenodd" d="M65.4834 207.273C62.198 205.912 60.6456 202.137 62.0041 198.858L67.2463 186.202C68.6048 182.922 72.3722 181.35 75.6577 182.71L78.0044 183.683C81.2899 185.043 82.842 188.819 81.4835 192.099L76.2413 204.755C74.8828 208.035 71.1157 209.606 67.8302 208.245L65.4834 207.273Z" fill="#FFD33B"&gt;&lt;/path&gt; &lt;path fill-rule="evenodd" clip-rule="evenodd" d="M106.727 215.985C103.171 215.985 100.292 213.092 100.292 209.542C100.292 205.413 100.292 200.011 100.292 195.843C100.292 192.293 103.171 189.399 106.727 189.399H109.267C112.823 189.399 115.702 192.293 115.702 195.843V209.542C115.702 213.092 112.823 215.985 109.267 215.985H106.727Z" fill="#FFD33B"&gt;&lt;/path&gt; &lt;path fill-rule="evenodd" clip-rule="evenodd" d="M148.146 208.255C144.86 209.616 141.093 208.044 139.734 204.764L134.492 192.109C133.134 188.829 134.686 185.053 137.971 183.692L140.318 182.72C143.603 181.359 147.371 182.932 148.729 186.211L153.972 198.867C155.33 202.147 153.778 205.922 150.492 207.283L148.146 208.255Z" fill="#FFD33B"&gt;&lt;/path&gt; &lt;path fill-rule="evenodd" clip-rule="evenodd" d="M183.453 185.267C180.939 187.782 176.857 187.771 174.347 185.261C171.427 182.342 167.607 178.522 164.661 175.575C162.15 173.065 162.139 168.982 164.654 166.468L166.45 164.672C168.965 162.157 173.047 162.168 175.557 164.678L185.243 174.364C187.754 176.875 187.764 180.957 185.25 183.471C184.651 184.07 184.052 184.669 183.453 185.267Z" fill="#FFD33B"&gt;&lt;/path&gt; &lt;path fill-rule="evenodd" clip-rule="evenodd" d="M207.273 150.509C205.912 153.794 202.137 155.347 198.858 153.988L186.202 148.746C182.922 147.387 181.35 143.62 182.71 140.335L183.683 137.988C185.043 134.702 188.819 133.15 192.099 134.509L204.755 139.751C208.035 141.109 209.606 144.877 208.245 148.162L207.273 150.509Z" fill="#FFD33B"&gt;&lt;/path&gt; &lt;path fill-rule="evenodd" clip-rule="evenodd" d="M215.985 109.271C215.985 112.827 213.092 115.706 209.542 115.706L195.843 115.706C192.293 115.706 189.399 112.827 189.399 109.271V106.731C189.399 103.175 192.293 100.296 195.843 100.296L209.542 100.296C213.092 100.296 215.985 103.175 215.985 106.731V109.271Z" fill="#FFD33B"&gt;&lt;/path&gt; &lt;path fill-rule="evenodd" clip-rule="evenodd" d="M208.254 67.8525C209.615 71.138 208.043 74.9051 204.763 76.2636C200.949 77.8437 195.958 79.911 192.108 81.5058C188.828 82.8643 185.052 81.3122 183.691 78.0268L182.719 75.68C181.358 72.3945 182.931 68.6271 186.21 67.2686L198.866 62.0265C202.146 60.6679 205.921 62.2203 207.282 65.5058L208.254 67.8525Z" fill="#FFD33B"&gt;&lt;/path&gt; &lt;path fill-rule="evenodd" clip-rule="evenodd" d="M185.266 32.5437C187.781 35.0583 187.77 39.1401 185.26 41.6503L175.574 51.3366C173.064 53.8468 168.981 53.8578 166.467 51.3432L164.671 49.5471C162.156 47.0325 162.167 42.9501 164.677 40.4399L174.364 30.7537C176.874 28.2434 180.956 28.2329 183.47 30.7475L185.266 32.5437Z" fill="#FFD33B"&gt;&lt;/path&gt; &lt;path fill-rule="evenodd" clip-rule="evenodd" d="M150.508 8.7237C153.793 10.0846 155.346 13.8597 153.987 17.1395L148.745 29.7952C147.386 33.075 143.619 34.6475 140.334 33.2866L137.987 32.3145C134.701 30.9537 133.149 27.1778 134.508 23.898L139.75 11.2423C141.108 7.96252 144.876 6.39076 148.161 7.75164L150.508 8.7237Z" fill="#FFD33B"&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/p&gt;
&lt;p&gt;With Hanakai, we’re building a single shared community around the gems you know and love. The gems will carry on, now cared for by a bigger, unified team. And with our beautiful new website, now you can discover our vision for Ruby more easily than ever.&lt;/p&gt;
&lt;p&gt;Loosely translated from the Japanese 花会, Hanakai means “flower fellowship”, sharing its first character 花 with Hanami, “flower viewing”. With this name, we carry forward Hanami’s spirit of nature and community. From today, our blossoms bloom together, and we invite you to join us!&lt;/p&gt;
&lt;h2 id="a-new-look-for-our-family"&gt;
A new look for our family&lt;a href="#a-new-look-for-our-family" aria-hidden="true" class="anchor"&gt;&lt;span aria-hidden="true" class="anchor"&gt;&lt;/span&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;To go with our new name, we’re unveiling our new look. This is a brand that truly reflects who we are as a community: friendly, humane, and a little bit fun!&lt;/p&gt;
&lt;p&gt;&lt;img src="/blog/assets/2026-05-01-welcome-to-hanakai/hanakai-logos.png" alt="Hanakai logos" width="1720" height="450"&gt;&lt;/p&gt;
&lt;p&gt;Our logos share a common spirit, while letting each project preserve its own identity. That’s how we want Hanakai to feel — for everyone.&lt;/p&gt;
&lt;p&gt;A huge thank you to &lt;a href="https://github.com/aaronmoodie"&gt;Aaron Moodie&lt;/a&gt; for bringing this vision to life. Aaron first joined us to design the &lt;a href="/blog/2024/02/27/hanami-210"&gt;welcome screen&lt;/a&gt; for new Hanami apps, and now he’s extended this welcome to the whole world. Thank you, Aaron, this is everything I could have hoped for!&lt;/p&gt;
&lt;h2 id="a-new-home-on-the-web"&gt;
A new home on the web&lt;a href="#a-new-home-on-the-web" aria-hidden="true" class="anchor"&gt;&lt;span aria-hidden="true" class="anchor"&gt;&lt;/span&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;You’re reading this on our brand new website, now at &lt;a href="https://hanakai.org"&gt;hanakai.org&lt;/a&gt;. Here we’ve brought everything together: &lt;a href="/"&gt;project&lt;/a&gt; and &lt;a href="/community"&gt;community&lt;/a&gt; info, our &lt;a href="/blog"&gt;blog posts&lt;/a&gt;, and &lt;a href="/learn"&gt;guides&lt;/a&gt; for every aspect of using our gems. Our refined typography and rebuilt search function make finding what you need a pleasure.&lt;/p&gt;
&lt;p&gt;Fittingly, this site is a Hanami app! It’s &lt;a href="https://github.com/hanakai-rb/site"&gt;fully open source&lt;/a&gt;, so you can check it out to see how we build Hanakai with Hanakai. All our guides &lt;a href="https://github.com/hanakai-rb/site/tree/main/content/guides"&gt;now live together&lt;/a&gt; as Markdown files inside this repo, ready for your contributions!&lt;/p&gt;
&lt;p&gt;Another huge thank you goes to &lt;a href="https://github.com/makenosound"&gt;Max Wheeler&lt;/a&gt; — every pixel of this site is Max’s work. He designed and built the entire frontend, and has been a thoughtful, generous collaborator the whole way through. It brings me so much joy just to click around and see everything fitting so well together. Thank you, Max, we couldn’t have done it without you.&lt;/p&gt;
&lt;p&gt;Getting this site together has been a big effort, so I have many more thanks to share. For starters, thank you to &lt;a href="https://github.com/josephinehall"&gt;Josephine Hall&lt;/a&gt; for taking over work on this while I focused on shipping a &lt;a href="/blog/2025/11/12/hanami-23-racked-and-ready"&gt;Hanami release&lt;/a&gt;; I needed that help! And thank you to &lt;a href="https://github.com/katafrakt"&gt;Paweł Świątkowski&lt;/a&gt;, &lt;a href="https://github.com/parndt"&gt;Philip Arndt&lt;/a&gt;, &lt;a href="https://github.com/mathewdbutton"&gt;Mathew Button&lt;/a&gt;, &lt;a href="https://github.com/marcoroth"&gt;Marco Roth&lt;/a&gt;, &lt;a href="https://github.com/alassek"&gt;Adam Lassek&lt;/a&gt;, &lt;a href="https://github.com/sandbergja"&gt;Jane Sandberg&lt;/a&gt; and &lt;a href="https://github.com/kamalogudah"&gt;Paul Oguda&lt;/a&gt; for their contributions along the way!&lt;/p&gt;
&lt;h2 id="whats-next"&gt;
What’s next&lt;a href="#whats-next" aria-hidden="true" class="anchor"&gt;&lt;span aria-hidden="true" class="anchor"&gt;&lt;/span&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Bringing Hanakai to you is a momentous shift for our corner of the Ruby world, and one we’ll certainly celebrate!&lt;/p&gt;
&lt;p&gt;But we haven’t stopped moving — there’s plenty to look forward to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A new release of &lt;a href="/learn/dry/dry-operation"&gt;Dry Operation&lt;/a&gt; with a slew of niceties.&lt;/li&gt;
&lt;li&gt;A feature-packed &lt;a href="/hanami"&gt;Hanami&lt;/a&gt; release. Keep an eye out for a release candidate soon!&lt;/li&gt;
&lt;li&gt;New “Hanami for Rails developers” guides.&lt;/li&gt;
&lt;li&gt;Our &lt;a href="/sponsor"&gt;sponsorship&lt;/a&gt; drive for 2026. Your support has brought us this far — help us take the next steps!&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="join-us"&gt;
Join us&lt;a href="#join-us" aria-hidden="true" class="anchor"&gt;&lt;span aria-hidden="true" class="anchor"&gt;&lt;/span&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Our new garden is open, and we’d love for you to join us:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Chat with us on &lt;a href="https://discord.gg/KFCxDmk3JQ"&gt;Discord&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Start a thread on &lt;a href="https://discourse.hanakai.org"&gt;our forum&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Subscribe to &lt;a href="https://buttondown.com/hanakai#subscribe-form"&gt;our newsletter&lt;/a&gt; to stay up to date with our announcements.&lt;/li&gt;
&lt;li&gt;Follow along on &lt;a href="https://ruby.social/@hanakai"&gt;Mastodon&lt;/a&gt; or &lt;a href="https://bsky.app/profile/hanakai.org"&gt;Bluesky&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Of all our projects, our community is by far our most important. With Hanakai, it’s stronger than ever, and ready to welcome you in. Here’s to many seasons ahead! &lt;svg class="emoji-logo emoji-logo--hanami inline" height="1em" width="1em" viewbox="0 0 164 159" fill="none" xmlns="http://www.w3.org/2000/svg"&gt; &lt;path fill-rule="evenodd" clip-rule="evenodd" d="m39.3087 98.5899c-3.805.37-7.7441-.02-11.6091-1.28l-7.8299-2.54c-15.09004-4.91-23.36005-21.14-18.45705-36.23s21.13505-23.36 36.22405-18.46l7.8309 2.55c3.864 1.25 7.281 3.25 10.145 5.79-1.524-3.51-2.369-7.3799-2.369-11.4399v-8.2301c0-15.87 12.8821-28.75003733 28.7481-28.75003733s28.7483 12.88003733 28.7483 28.75003733v8.2301c0 4.06-.845 7.9299-2.368 11.4399 2.863-2.54 6.28-4.54 10.145-5.79l7.83-2.55c15.09-4.9 31.321 3.37 36.224 18.46s-3.367 31.32-18.457 36.23l-7.83 2.54c-3.865 1.26-7.804 1.65-11.609 1.28 3.293 1.9401 6.25 4.5801 8.638 7.8601l4.84 6.663c9.326 12.837 6.476 30.829-6.36 40.155-12.837 9.327-30.829 6.477-40.1553-6.359l-4.84-6.661c-2.388-3.288-3.978-6.913-4.806-10.645-.828 3.732-2.418 7.357-4.806 10.645l-4.8391 6.661c-9.326 12.836-27.319 15.686-40.156 6.359-12.836-9.326-15.6859-27.318-6.3589-40.155l4.839-6.663c2.388-3.28 5.345-5.92 8.638-7.8601z" fill="#FF6C89"&gt;&lt;/path&gt; &lt;path d="m81.9919 50.5298c18.2971 0 33.1521 14.8601 33.1521 33.1601 0 18.2901-14.855 33.1481-33.1521 33.1481-18.297 0-33.1521-14.858-33.1521-33.1481 0-18.3 14.8551-33.1601 33.1521-33.1601z" fill="#FFC9C4"&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/p&gt;</content>
  </entry>
  <entry>
    <title>State of Hanami, December 2025</title>
    <link rel="alternate" href="https://hanakai.org/blog/2025/12/22/state-of-hanami-december-2025"/>
    <id>https://hanakai.org/blog/2025/12/22/state-of-hanami-december-2025</id>
    <published>2025-12-22T12:30:00+00:00</published>
    <updated>2025-12-22T12:30:00+00:00</updated>
    <author>
      <name>Tim Riley</name>
    </author>
    <content type="html">&lt;p&gt;I’m very pleased to share our &lt;strong&gt;State of Hanami&lt;/strong&gt; update for 2025! We’re back for our second time. If you want to get caught up, &lt;a href="https://hanakai.org/blog/2024/12/10/state-of-hanami-december-2024/"&gt;check out our update from last year&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This has been a pivotal year for Hanami, our first steps into a new era: we made a substantial new release, began unifying our ecosystem, expanded our team, launched our sponsorship program, and saw a real uptick in community activity.&lt;/p&gt;
&lt;p&gt;I’ll go into all these highlights below, before leaving you with some plans for 2026.&lt;/p&gt;
&lt;h2 id="our-biggest-release-yet"&gt;
Our biggest release yet&lt;a href="#our-biggest-release-yet" aria-hidden="true" class="anchor"&gt;&lt;span aria-hidden="true" class="anchor"&gt;&lt;/span&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;In November we &lt;a href="https://hanakai.org/blog/2025/11/12/hanami-23-racked-and-ready/"&gt;released Hanami 2.3&lt;/a&gt;. This was our first major release in a year, and it turned out to be our biggest release yet, with 32 different contributors choosing to make Hanami better. Hanami 2.3 introduced Rack 3 support, resource routing, improved media type handling, along with a wide range of DX improvements. We’d love for you to give it a try!&lt;/p&gt;
&lt;h2 id="our-ecosystem-came-together"&gt;
Our ecosystem came together&lt;a href="#our-ecosystem-came-together" aria-hidden="true" class="anchor"&gt;&lt;span aria-hidden="true" class="anchor"&gt;&lt;/span&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Our maintainers this year have been taking care of &lt;a href="https://dry-rb.org"&gt;Dry&lt;/a&gt; and &lt;a href="https://rom-rb.org"&gt;Rom&lt;/a&gt; in addition to Hanami. We’ve been working towards bringing these projects together under a single banner. As part of this, we’ve chosen a new overall project name, and have been developing a new website and unified branding. Together, these will reintroduce us to the Ruby world and give our users an easier time learning our tools. We plan to launch these in February, but in the meantime, you can check out the &lt;a href="https://github.com/hanakai-rb/site"&gt;source code&lt;/a&gt; and the &lt;a href="https://hanakai.org"&gt;in-progress&lt;/a&gt; live site (our guides are already &lt;a href="https://hanakai.org/learn/hanami/v2.3/getting-started"&gt;looking particularly fine&lt;/a&gt;).&lt;/p&gt;
&lt;h2 id="our-team-grew-again"&gt;
Our team grew again&lt;a href="#our-team-grew-again" aria-hidden="true" class="anchor"&gt;&lt;span aria-hidden="true" class="anchor"&gt;&lt;/span&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;This year we welcomed nine new people to our maintainers team:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/aaronmallen"&gt;Aaron Allen&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/afomera"&gt;Andrea Fomera&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/dcr8898"&gt;Damian C. Rossney&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/josephinehall"&gt;Josephine Hall&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/krzykamil"&gt;Krzysztof Piotrowski&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/makenosound"&gt;Max Wheeler&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/katafrakt"&gt;Paweł Świątkowski&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/radar"&gt;Ryan Bigg&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/svoop"&gt;Sven Schwyn&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These joined our existing team members, who have continued to work over the last year:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/aaronmoodie"&gt;Aaron Moodie&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/alassek"&gt;Adam Lassek&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/kyleplump"&gt;Kyle Plump&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/waiting-for-dev"&gt;Marc Busqué&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/flash-gordon"&gt;Nikita Shilnikov&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/parndt"&gt;Philip Arndt&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/cllns"&gt;Sean Collins&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/timriley"&gt;Tim Riley&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Thank you to all these beautiful people for giving their time to Hanami and for improving our part of the Ruby world!&lt;/p&gt;
&lt;p&gt;All up, our maintainers team is now 17 strong. This feels like a good foundation for us to step up and do even better work next year. If you’d like to get involved, we recommend helping to triage issues and evaluate pull requests.&lt;/p&gt;
&lt;h2 id="our-community-shone-through"&gt;
Our community shone through&lt;a href="#our-community-shone-through" aria-hidden="true" class="anchor"&gt;&lt;span aria-hidden="true" class="anchor"&gt;&lt;/span&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Our community took things to a new level this year:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;We launched &lt;a href="https://discord.gg/KFCxDmk3JQ"&gt;our Discord&lt;/a&gt; and saw it bring more community activity than ever before.&lt;/li&gt;
&lt;li&gt;We saw the launch of several new open source Hanami apps, including Princeton University Library’s &lt;a href="https://github.com/pulibrary/orcid_princeton_hanami"&gt;orcid_princeton_hanami&lt;/a&gt;, which is also running in production! Huge props to &lt;a href="https://github.com/carolyncole"&gt;Carolyn Cole&lt;/a&gt; for driving that project and &lt;a href="https://discourse.hanakai.org/t/converting-a-rails-app-feature-parity/1287"&gt;sharing her thoughts&lt;/a&gt; on the process. We also saw the release of Pat Allan’s &lt;a href="https://codeberg.org/patallan/playsmith"&gt;Playsmith&lt;/a&gt;, Ryan Bigg’s &lt;a href="https://github.com/radar/twist-v3"&gt;Twist v3&lt;/a&gt;, and our very own &lt;a href="https://github.com/hanakai-rb/site"&gt;upcoming website&lt;/a&gt;. Meanwhile, Paweł continues to keep &lt;a href="https://github.com/katafrakt/palaver"&gt;Palaver&lt;/a&gt; up to date as one of the most complete example apps out there.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/inouire"&gt;Edouard&lt;/a&gt; launched the new (commercial) &lt;a href="https://catalogue-studio.com/"&gt;Catalogue Studio&lt;/a&gt;, after leaving us a brilliant trail of “&lt;a href="https://discourse.hanakai.org/t/hanami-1-3-hanami-2-2-tips-notes-about-my-journey/1210"&gt;Tips and notes about &lt;span data-escaped-char&gt;[&lt;/span&gt;his&lt;span data-escaped-char&gt;]&lt;/span&gt; journey&lt;/a&gt;” from Hanami 1.3 to 2.2.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/afomera"&gt;Andrea Fomera&lt;/a&gt; arrived on the scene with a &lt;em&gt;meteorological&lt;/em&gt; level of energy. She contributed some key pieces to Hanami 2.3, and also created &lt;a href="https://github.com/afomera/hanami-omakase"&gt;hanami-omakase&lt;/a&gt; as a proving ground for Rails-alike features.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/radar"&gt;Ryan Bigg&lt;/a&gt; pointed his big blogging brain our way and penned his “&lt;a href="https://ryanbigg.com/2025/10/hanami-for-rails-developers-1-models"&gt;Hanami for Rails developers&lt;/a&gt;” series. With Ryan now on the team, we’re looking forward to creating our very own “for Rails devs” guides in the future!&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/andrew"&gt;Andrew Nesbitt&lt;/a&gt; shipped &lt;a href="https://github.com/andrew/hanami-sprockets"&gt;hanami-sprockets&lt;/a&gt;, an alternative asset bundler and proving ground for the pluggable bundlers we’d like to ship next year.&lt;/li&gt;
&lt;li&gt;Andrew also helped us get our new &lt;a href="https://github.com/hanakai-rb/awesome-hanakai"&gt;awesome-hanakai&lt;/a&gt; repo off the ground. There’s still a bit of tidying to do, but it exists, and that’s the important thing. If you have something awesome, now you know where to put it!&lt;/li&gt;
&lt;li&gt;Did I mention our Hanami 2.3 release saw input from 32 different contributors? This is amazing! Thanks in particular to &lt;a href="https://github.com/wout"&gt;Wout&lt;/a&gt; and &lt;a href="https://github.com/wuarmin"&gt;Armin&lt;/a&gt; for multiple helpful contributions across the year.&lt;/li&gt;
&lt;li&gt;Starting in August, I’ve also been sharing &lt;a href="https://timriley.info/tag/continuations"&gt;my weeknotes&lt;/a&gt; covering Hanami development. I hope you find them helpful!&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Our community is the most important thing to us. To reflect this, this year we made our community values clearer than ever, and placed them &lt;a href="https://hanamirb.org"&gt;front and centre on our website&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;We want the Hanami community to be a welcoming place for people who bring kindness, curiosity, and care. A place where people of all backgrounds and experience levels can feel respected, and can share and grow. A place for people to be proud of, and feel safe within.&lt;/p&gt;
&lt;p&gt;We do not tolerate nazis, transphobes, racists, or any kind of bigotry. See our &lt;a href="https://hanakai.org/conduct"&gt;code of conduct&lt;/a&gt; for more.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;We also &lt;a href="https://hanakai.org/blog/2025/09/02/hanami-adopts-contributor-covenant-3-0/"&gt;adopted the Contributor Covenant 3.0&lt;/a&gt;, which brings a more approachable text for our worldwide community, and places a helpful emphasis on restorative justice.&lt;/p&gt;
&lt;p&gt;I believe our values have played a big part in the health and growth of our community this year. Thank you to everyone for building a space we can all enjoy!&lt;/p&gt;
&lt;h2 id="we-went-out-into-the-world"&gt;
We went out into the world&lt;a href="#we-went-out-into-the-world" aria-hidden="true" class="anchor"&gt;&lt;span aria-hidden="true" class="anchor"&gt;&lt;/span&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Once again, we took ourselves to some conferences!&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Tim visited beautiful Riga, Latvia for &lt;a href="https://balticruby.org/archive/2025"&gt;Baltic Ruby&lt;/a&gt;, where he presented a new Murakami-themed introduction to Hanami, and thoughts on the importance of a diverse Ruby ecosystem. He also ran a hack session, where &lt;a href="https://github.com/ismasan"&gt;Ismael Celis&lt;/a&gt; used his &lt;a href="https://github.com/ismasan/sourced"&gt;sourced&lt;/a&gt; toolkit to create the &lt;a href="https://bsky.app/profile/ismaelcelis.com/post/3lrj5ltfvlc2a"&gt;world’s first event-sourced calculator built on Hanami&lt;/a&gt;, and &lt;a href="https://github.com/krzykamil"&gt;Krzysztof&lt;/a&gt; worked on the &lt;code&gt;db rollback&lt;/code&gt; command for Hanami 2.3. Thank you to Baltic Ruby for the invitation!&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/cllns"&gt;Sean&lt;/a&gt; attended &lt;a href="https://rockymtnruby.dev"&gt;Rocky Mountain Ruby&lt;/a&gt; in Boulder, Colorado, and spoke on &lt;a href="https://www.rubyevents.org/talks/slicing-and-dicing-through-complexity-with-hanami?back_to=%2Fevents%2Frocky-mountain-ruby-2025%2Ftalks%3Fscroll_top%3D1872&amp;amp;back_to_title=Rocky+Mountain+Ruby+2025"&gt;Slicing and Dicing through Complexity with Hanami&lt;/a&gt;. He also got to spend some quality time with some #HanamiFriends new and old!&lt;/li&gt;
&lt;li&gt;Tim was lucky enough to reprise his talk at both &lt;a href="https://www.xoruby.com/event/san-diego/"&gt;XO Ruby San Diego&lt;/a&gt; and &lt;a href="https://thoughtbot.com/blog/announcing-the-thoughtbot-open-summit-2025-full-schedule"&gt;thoughtbot Open Summit&lt;/a&gt;. Thanks to XO organiser &lt;a href="https://ruby.social/@jremsikjr"&gt;Jim Remsik&lt;/a&gt;, the San Diego talk was streamed to the internet, and the Open Summit was a native online event. We saw a good-sized group come together for each one, and I’m really glad I could share Hanami in such an open way. Thank you to Jim and thoughtbot for making these happen!&lt;/li&gt;
&lt;/ul&gt;
&lt;div style="display: flex; gap: 1rem;"&gt;
&lt;img src="/blog/assets/2025-12-22-state-of-hanami-december-2025/sean-at-rocky-mountain-ruby.webp" alt="Sean on stage at Rocky Mountain Ruby" style="flex: 1; max-width: calc(50% - 0.5rem);" width="1280" height="961"&gt;
&lt;img src="/blog/assets/2025-12-22-state-of-hanami-december-2025/tim-at-baltic-ruby.webp" alt="Matz joins the Hanami table at Baltic Ruby" style="flex: 1; max-width: calc(50% - 0.5rem);" width="1280" height="960"&gt;
&lt;/div&gt;
&lt;h2 id="we-launched-our-sponsorship-program"&gt;
We launched our sponsorship program&lt;a href="#we-launched-our-sponsorship-program" aria-hidden="true" class="anchor"&gt;&lt;span aria-hidden="true" class="anchor"&gt;&lt;/span&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;This year we launched our first ever &lt;a href="https://hanakai.org/sponsor"&gt;sponsorship program&lt;/a&gt; for Hanami, Dry and Rom. These are big and ambitious projects, and they need consistent attention for them to grow. Thanks to the support of the Ruby community, we made this happen! Since February this year, I’ve been able to commit a full business day every week towards the stewardship of our projects.&lt;/p&gt;
&lt;p&gt;This could not have happened without our founding patrons. Thank you to &lt;a href="https://sidekiq.org/"&gt;&lt;strong&gt;Sidekiq&lt;/strong&gt;&lt;/a&gt;, &lt;a href="https://github.com/baweaver"&gt;&lt;strong&gt;Brandon Weaver&lt;/strong&gt;&lt;/a&gt;, &lt;a href="https://www.honeybadger.io/?utm_source=hanami&amp;amp;utm_medium=paid-referral&amp;amp;utm_campaign=founding-patron"&gt;&lt;strong&gt;Honeybadger&lt;/strong&gt;&lt;/a&gt;, &lt;a href="https://www.fastruby.io/"&gt;&lt;strong&gt;FastRuby&lt;/strong&gt;&lt;/a&gt;, and &lt;a href="https://www.appsignal.com/"&gt;&lt;strong&gt;AppSignal&lt;/strong&gt;&lt;/a&gt; for your support! Your courage and belief is what got this thing off the ground in the first place.&lt;/p&gt;
&lt;p&gt;Thank you also to all the individuals who are supporting us &lt;a href="https://github.com/sponsors/hanami"&gt;through GitHub sponsors&lt;/a&gt;. There are 20 of you right now! There’s real power in numbers, and your support takes us further than we could go alone.&lt;/p&gt;
&lt;p&gt;We’ll run another sponsorship drive toward the middle of next year, but we are ready to accept your support at any time! &lt;a href="https://hanakai.org/sponsor"&gt;See our sponsorship site&lt;/a&gt; to learn more. A few more businesses, or growing from 20 to 40 individual supporters, would make a huge difference to our project. And as you can see from everything in this post, your support goes a long way.&lt;/p&gt;
&lt;p&gt;We have also ceased our relationship with Ruby Central as a fiscal host, following their removal of the Bundler and RubyGems.org maintainer teams from those projects, and their conduct thereafter. We stand with every maintainer.&lt;/p&gt;
&lt;h2 id="looking-forward-to-next-year"&gt;
Looking forward to next year&lt;a href="#looking-forward-to-next-year" aria-hidden="true" class="anchor"&gt;&lt;span aria-hidden="true" class="anchor"&gt;&lt;/span&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Just like &lt;a href="https://hanakai.org/blog/2024/12/10/state-of-hanami-december-2024/"&gt;last year&lt;/a&gt;, we have some goals we want to pursue across 2026:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Establish a twice-a-year release cycle for Hanami.&lt;/strong&gt; Right now we’re aiming for May and November.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Finish unifying our ecosystem.&lt;/strong&gt; We’ll launch our new site, finish rolling out our repo sync and release automation, then look at merging our forums.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prepare the future for Dry and Rom.&lt;/strong&gt; We want to reinvigorate these gems and make things easier for new contributors. This means triaging issues, bringing on focused maintainers, and developing roadmaps for the next phase of these projects.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enter a successful second year of funded maintenance.&lt;/strong&gt; Year one proved we could do this. Year two will show us whether we can sustain it. We’re looking forward to your support!&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We’ll share more on each of these as we work through the year.&lt;/p&gt;
&lt;p&gt;In the meantime, that’s it from us for 2025. Thank you to everyone who contributed to a wonderful year of improvements. We’re looking forward to continuing the work!&lt;/p&gt;</content>
  </entry>
  <entry>
    <title>Hanami 2.3: Racked and Ready</title>
    <link rel="alternate" href="https://hanakai.org/blog/2025/11/12/hanami-23-racked-and-ready"/>
    <id>https://hanakai.org/blog/2025/11/12/hanami-23-racked-and-ready</id>
    <published>2025-11-12T13:00:00+00:00</published>
    <updated>2025-11-12T13:00:00+00:00</updated>
    <author>
      <name>Tim Riley</name>
    </author>
    <content type="html">&lt;p&gt;Today we are excited to announce Hanami 2.3! With this release, we unlock Rack 3, introduce resource routes, and deliver dozens of quality-of-life improvements that make building with Hanami smoother than ever.&lt;/p&gt;
&lt;h2 id="built-for-rack-3"&gt;
Built for Rack 3&lt;a href="#built-for-rack-3" aria-hidden="true" class="anchor"&gt;&lt;span aria-hidden="true" class="anchor"&gt;&lt;/span&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;We are excited to bring Rack 3 support to Hanami! We now support both versions 2 and 3, so you can use whichever version of Rack suits your situation. We encourage you to upgrade Rack when you can, and we’re happy that Hanami can help you on this path.&lt;/p&gt;
&lt;p&gt;When you upgrade to Rack 3, check out the &lt;a href="https://github.com/rack/rack/blob/main/UPGRADE-GUIDE.md"&gt;Rack 3 upgrade guide&lt;/a&gt;. Hanami already handles the essential changes for you, but you may need to update your app code if you’re working with Rack request/response details.&lt;/p&gt;
&lt;h2 id="streamlined-from-route-to-response"&gt;
Streamlined from route to response&lt;a href="#streamlined-from-route-to-response" aria-hidden="true" class="anchor"&gt;&lt;span aria-hidden="true" class="anchor"&gt;&lt;/span&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;More than just Rack, we’ve refined all aspects of our routing and request handling layer. The biggest change is the return of resource-based routing.&lt;/p&gt;
&lt;p&gt;To set up RESTful routes, you’d previously add the following lines:&lt;/p&gt;
&lt;div class="pre-wrapper" data-defo-copy-code&gt;
&lt;button type="button" class="pre-wrapper__button" aria-label="Copy"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" class="pre-wrapper__icon pre-wrapper__icon--copy" height="16" viewbox="0 0 256 256" width="16"&gt; &lt;path d="M172,164a12,12,0,0,1-12,12H96a12,12,0,0,1,0-24h64A12,12,0,0,1,172,164Zm-12-52H96a12,12,0,0,0,0,24h64a12,12,0,0,0,0-24Zm60-64V216a20,20,0,0,1-20,20H56a20,20,0,0,1-20-20V48A20,20,0,0,1,56,28H90.53a51.88,51.88,0,0,1,74.94,0H200A20,20,0,0,1,220,48ZM100.29,60h55.42a28,28,0,0,0-55.42,0ZM196,52H178.59A52.13,52.13,0,0,1,180,64v8a12,12,0,0,1-12,12H88A12,12,0,0,1,76,72V64a52.13,52.13,0,0,1,1.41-12H60V212H196Z"&gt;&lt;/path&gt; &lt;/svg&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" class="pre-wrapper__icon pre-wrapper__icon--check" height="16" viewbox="-13 0 276 276" width="16"&gt; &lt;path d="M232.49,80.49l-128,128a12,12,0,0,1-17,0l-56-56a12,12,0,1,1,17-17L96,183,215.51,63.51a12,12,0,0,1,17,17Z"&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/button&gt;&lt;pre class="syntax-highlighting"&gt;&lt;code&gt;&lt;span class="source ruby"&gt;&lt;span class="comment line number-sign ruby"&gt;&lt;span class="punctuation definition comment ruby"&gt;#&lt;/span&gt; Previously...
&lt;/span&gt;get &lt;span class="string quoted double ruby"&gt;&lt;span class="punctuation definition string begin ruby"&gt;"&lt;/span&gt;/books&lt;span class="punctuation definition string end ruby"&gt;"&lt;/span&gt;&lt;/span&gt;&lt;span class="punctuation separator ruby"&gt;,&lt;/span&gt; &lt;span class="constant other symbol ruby"&gt;to&lt;span class="punctuation definition constant ruby"&gt;:&lt;/span&gt;&lt;/span&gt; &lt;span class="string quoted double ruby"&gt;&lt;span class="punctuation definition string begin ruby"&gt;"&lt;/span&gt;books.index&lt;span class="punctuation definition string end ruby"&gt;"&lt;/span&gt;&lt;/span&gt;&lt;span class="punctuation separator ruby"&gt;,&lt;/span&gt; &lt;span class="constant other symbol ruby"&gt;as&lt;span class="punctuation definition constant ruby"&gt;:&lt;/span&gt;&lt;/span&gt; &lt;span class="constant other symbol ruby"&gt;&lt;span class="punctuation definition constant ruby"&gt;:&lt;/span&gt;books&lt;/span&gt;
get &lt;span class="string quoted double ruby"&gt;&lt;span class="punctuation definition string begin ruby"&gt;"&lt;/span&gt;/books/:id&lt;span class="punctuation definition string end ruby"&gt;"&lt;/span&gt;&lt;/span&gt;&lt;span class="punctuation separator ruby"&gt;,&lt;/span&gt; &lt;span class="constant other symbol ruby"&gt;to&lt;span class="punctuation definition constant ruby"&gt;:&lt;/span&gt;&lt;/span&gt; &lt;span class="string quoted double ruby"&gt;&lt;span class="punctuation definition string begin ruby"&gt;"&lt;/span&gt;books.show&lt;span class="punctuation definition string end ruby"&gt;"&lt;/span&gt;&lt;/span&gt;&lt;span class="punctuation separator ruby"&gt;,&lt;/span&gt; &lt;span class="constant other symbol ruby"&gt;as&lt;span class="punctuation definition constant ruby"&gt;:&lt;/span&gt;&lt;/span&gt; &lt;span class="constant other symbol ruby"&gt;&lt;span class="punctuation definition constant ruby"&gt;:&lt;/span&gt;book&lt;/span&gt;
get &lt;span class="string quoted double ruby"&gt;&lt;span class="punctuation definition string begin ruby"&gt;"&lt;/span&gt;/books/new&lt;span class="punctuation definition string end ruby"&gt;"&lt;/span&gt;&lt;/span&gt;&lt;span class="punctuation separator ruby"&gt;,&lt;/span&gt; &lt;span class="constant other symbol ruby"&gt;to&lt;span class="punctuation definition constant ruby"&gt;:&lt;/span&gt;&lt;/span&gt; &lt;span class="string quoted double ruby"&gt;&lt;span class="punctuation definition string begin ruby"&gt;"&lt;/span&gt;books.new&lt;span class="punctuation definition string end ruby"&gt;"&lt;/span&gt;&lt;/span&gt;&lt;span class="punctuation separator ruby"&gt;,&lt;/span&gt; &lt;span class="constant other symbol ruby"&gt;as&lt;span class="punctuation definition constant ruby"&gt;:&lt;/span&gt;&lt;/span&gt; &lt;span class="constant other symbol ruby"&gt;&lt;span class="punctuation definition constant ruby"&gt;:&lt;/span&gt;new_book&lt;/span&gt;
post &lt;span class="string quoted double ruby"&gt;&lt;span class="punctuation definition string begin ruby"&gt;"&lt;/span&gt;/books&lt;span class="punctuation definition string end ruby"&gt;"&lt;/span&gt;&lt;/span&gt;&lt;span class="punctuation separator ruby"&gt;,&lt;/span&gt; &lt;span class="constant other symbol ruby"&gt;to&lt;span class="punctuation definition constant ruby"&gt;:&lt;/span&gt;&lt;/span&gt; &lt;span class="string quoted double ruby"&gt;&lt;span class="punctuation definition string begin ruby"&gt;"&lt;/span&gt;books.create&lt;span class="punctuation definition string end ruby"&gt;"&lt;/span&gt;&lt;/span&gt;
get &lt;span class="string quoted double ruby"&gt;&lt;span class="punctuation definition string begin ruby"&gt;"&lt;/span&gt;/books/:id/edit&lt;span class="punctuation definition string end ruby"&gt;"&lt;/span&gt;&lt;/span&gt;&lt;span class="punctuation separator ruby"&gt;,&lt;/span&gt; &lt;span class="constant other symbol ruby"&gt;to&lt;span class="punctuation definition constant ruby"&gt;:&lt;/span&gt;&lt;/span&gt; &lt;span class="string quoted double ruby"&gt;&lt;span class="punctuation definition string begin ruby"&gt;"&lt;/span&gt;books.edit&lt;span class="punctuation definition string end ruby"&gt;"&lt;/span&gt;&lt;/span&gt;&lt;span class="punctuation separator ruby"&gt;,&lt;/span&gt; &lt;span class="constant other symbol ruby"&gt;as&lt;span class="punctuation definition constant ruby"&gt;:&lt;/span&gt;&lt;/span&gt; &lt;span class="constant other symbol ruby"&gt;&lt;span class="punctuation definition constant ruby"&gt;:&lt;/span&gt;edit_book&lt;/span&gt;
patch &lt;span class="string quoted double ruby"&gt;&lt;span class="punctuation definition string begin ruby"&gt;"&lt;/span&gt;/books/:id&lt;span class="punctuation definition string end ruby"&gt;"&lt;/span&gt;&lt;/span&gt;&lt;span class="punctuation separator ruby"&gt;,&lt;/span&gt; &lt;span class="constant other symbol ruby"&gt;to&lt;span class="punctuation definition constant ruby"&gt;:&lt;/span&gt;&lt;/span&gt; &lt;span class="string quoted double ruby"&gt;&lt;span class="punctuation definition string begin ruby"&gt;"&lt;/span&gt;books.update&lt;span class="punctuation definition string end ruby"&gt;"&lt;/span&gt;&lt;/span&gt;
delete &lt;span class="string quoted double ruby"&gt;&lt;span class="punctuation definition string begin ruby"&gt;"&lt;/span&gt;/books/:id&lt;span class="punctuation definition string end ruby"&gt;"&lt;/span&gt;&lt;/span&gt;&lt;span class="punctuation separator ruby"&gt;,&lt;/span&gt; &lt;span class="constant other symbol ruby"&gt;to&lt;span class="punctuation definition constant ruby"&gt;:&lt;/span&gt;&lt;/span&gt; &lt;span class="string quoted double ruby"&gt;&lt;span class="punctuation definition string begin ruby"&gt;"&lt;/span&gt;books.destroy&lt;span class="punctuation definition string end ruby"&gt;"&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Now, all you need is one:&lt;/p&gt;
&lt;div class="pre-wrapper" data-defo-copy-code&gt;
&lt;button type="button" class="pre-wrapper__button" aria-label="Copy"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" class="pre-wrapper__icon pre-wrapper__icon--copy" height="16" viewbox="0 0 256 256" width="16"&gt; &lt;path d="M172,164a12,12,0,0,1-12,12H96a12,12,0,0,1,0-24h64A12,12,0,0,1,172,164Zm-12-52H96a12,12,0,0,0,0,24h64a12,12,0,0,0,0-24Zm60-64V216a20,20,0,0,1-20,20H56a20,20,0,0,1-20-20V48A20,20,0,0,1,56,28H90.53a51.88,51.88,0,0,1,74.94,0H200A20,20,0,0,1,220,48ZM100.29,60h55.42a28,28,0,0,0-55.42,0ZM196,52H178.59A52.13,52.13,0,0,1,180,64v8a12,12,0,0,1-12,12H88A12,12,0,0,1,76,72V64a52.13,52.13,0,0,1,1.41-12H60V212H196Z"&gt;&lt;/path&gt; &lt;/svg&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" class="pre-wrapper__icon pre-wrapper__icon--check" height="16" viewbox="-13 0 276 276" width="16"&gt; &lt;path d="M232.49,80.49l-128,128a12,12,0,0,1-17,0l-56-56a12,12,0,1,1,17-17L96,183,215.51,63.51a12,12,0,0,1,17,17Z"&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/button&gt;&lt;pre class="syntax-highlighting"&gt;&lt;code&gt;&lt;span class="source ruby"&gt;&lt;span class="comment line number-sign ruby"&gt;&lt;span class="punctuation definition comment ruby"&gt;#&lt;/span&gt; Now! 🥰
&lt;/span&gt;resources &lt;span class="constant other symbol ruby"&gt;&lt;span class="punctuation definition constant ruby"&gt;:&lt;/span&gt;books&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Resource routing is integrated with every aspect of routing. Resources can be customized, nested, and combined with scopes and ordinary routes. &lt;a href="https://guides.hanamirb.org/v2.3/routing/overview/#resource-routes"&gt;Learn more here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The improvements don’t stop there! With this release:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Route scopes can be given custom name prefixes.&lt;/li&gt;
&lt;li&gt;Routes can be named with a prefix that precedes scope prefixes.&lt;/li&gt;
&lt;li&gt;Router runtime performance is considerably improved for large numbers of routes.&lt;/li&gt;
&lt;li&gt;Multipart form and JSON request bodies are parsed by default.&lt;/li&gt;
&lt;li&gt;Action format and media type config is &lt;a href="https://guides.hanamirb.org/v2.3/actions/formats-and-media-types/"&gt;clearer and more flexible&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;You can access your subdomains via &lt;code&gt;Request#subdomains&lt;/code&gt;, and &lt;a href="https://guides.hanamirb.org/v2.3/actions/request-and-response/#request"&gt;configure your TLD length&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;When you add &lt;code&gt;'nonce'&lt;/code&gt; to your content security policy, nonces are automatically added to script and stylesheet tags.&lt;/li&gt;
&lt;li&gt;CSRF tokens are loaded from the &lt;code&gt;X-CSRF-Token&lt;/code&gt; header in addition to request params.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="dx-in-the-details"&gt;
DX in the details&lt;a href="#dx-in-the-details" aria-hidden="true" class="anchor"&gt;&lt;span aria-hidden="true" class="anchor"&gt;&lt;/span&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;We’ve also improved many more of your day-to-day interactions with Hanami:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;hanami new&lt;/code&gt; now initializes a Git repository for new apps. You can also provide &lt;code&gt;--skip-view&lt;/code&gt; to skip the view layer, as well as &lt;code&gt;--gem-source&lt;/code&gt;, so you can use &lt;a href="https://gem.coop"&gt;gem.coop&lt;/a&gt; from the get-go.&lt;/li&gt;
&lt;li&gt;New apps get a helpful &lt;code&gt;bin/setup&lt;/code&gt; script, as well as an improved README with a handy list of first steps.&lt;/li&gt;
&lt;li&gt;New apps also receive a &lt;code&gt;bin/hanami&lt;/code&gt; binstub, so you can invoke &lt;code&gt;bin/hanami&lt;/code&gt; without requiring a &lt;code&gt;bundle exec&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;hanami db rollback&lt;/code&gt; to easily rollback a database migration.&lt;/li&gt;
&lt;li&gt;Add your own methods to &lt;code&gt;hanami console&lt;/code&gt; via your own modules: add &lt;code&gt;config.console.include MyModule&lt;/code&gt; in your app class.&lt;/li&gt;
&lt;li&gt;Prefer Pry to IRB? Make it the default with &lt;code&gt;config.console.engine = :pry&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The console now prints a one-time warning when you access the &lt;code&gt;keys&lt;/code&gt; for an un-booted app or slice. You can also chose to boot your app preemptively with &lt;code&gt;hanami console --boot&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The default &lt;code&gt;Rakefile&lt;/code&gt; will automatically load custom tasks from &lt;code&gt;lib/tasks/&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://guides.hanamirb.org/v2.3/views/context/"&gt;View context&lt;/a&gt; classes are generated by default, so you can more easily see where to put custom view logic.&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;hanami generate&lt;/code&gt; command within a slice directory and the generated file will target that slice automatically.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We’ve made dozens more small improvements and fixes. Check out &lt;a href="https://github.com/hanami/hanami/blob/main/CHANGELOG.md"&gt;the changelogs&lt;/a&gt; to learn more.&lt;/p&gt;
&lt;h2 id="try-hanami-23"&gt;
Try Hanami 2.3&lt;a href="#try-hanami-23" aria-hidden="true" class="anchor"&gt;&lt;span aria-hidden="true" class="anchor"&gt;&lt;/span&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;There’s never been a better time to try Hanami. For this release we’ve made our &lt;a href="https://guides.hanamirb.org/v2.3/introduction/getting-started/"&gt;getting started guide&lt;/a&gt; more concise and easier to follow. Now you can get up and running faster than ever!&lt;/p&gt;
&lt;p&gt;Why don’t you give it a try? Your first Hanami app is just a few commands away:&lt;/p&gt;
&lt;div class="pre-wrapper" data-defo-copy-code&gt;
&lt;button type="button" class="pre-wrapper__button" aria-label="Copy"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" class="pre-wrapper__icon pre-wrapper__icon--copy" height="16" viewbox="0 0 256 256" width="16"&gt; &lt;path d="M172,164a12,12,0,0,1-12,12H96a12,12,0,0,1,0-24h64A12,12,0,0,1,172,164Zm-12-52H96a12,12,0,0,0,0,24h64a12,12,0,0,0,0-24Zm60-64V216a20,20,0,0,1-20,20H56a20,20,0,0,1-20-20V48A20,20,0,0,1,56,28H90.53a51.88,51.88,0,0,1,74.94,0H200A20,20,0,0,1,220,48ZM100.29,60h55.42a28,28,0,0,0-55.42,0ZM196,52H178.59A52.13,52.13,0,0,1,180,64v8a12,12,0,0,1-12,12H88A12,12,0,0,1,76,72V64a52.13,52.13,0,0,1,1.41-12H60V212H196Z"&gt;&lt;/path&gt; &lt;/svg&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" class="pre-wrapper__icon pre-wrapper__icon--check" height="16" viewbox="-13 0 276 276" width="16"&gt; &lt;path d="M232.49,80.49l-128,128a12,12,0,0,1-17,0l-56-56a12,12,0,1,1,17-17L96,183,215.51,63.51a12,12,0,0,1,17,17Z"&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/button&gt;&lt;pre class="syntax-highlighting"&gt;&lt;code&gt;&lt;span class="text plain"&gt;$ gem install hanami
$ hanami new my_app
$ cd my_app
$ bin/hanami dev
$ open http://localhost:2300
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;We’d love to hear how you go! Come join our &lt;a href="https://discord.gg/KFCxDmk3JQ"&gt;Discord&lt;/a&gt; or &lt;a href="https://discourse.hanakai.org"&gt;forum&lt;/a&gt; and share your experience with our lovely community.&lt;/p&gt;
&lt;p&gt;And if you’re a certified legend already rocking a Hanami app, make sure to check out the &lt;a href="https://guides.hanamirb.org/v2.3/upgrade-notes/v2.3/"&gt;upgrade notes&lt;/a&gt; for 2.3.&lt;/p&gt;
&lt;h2 id="thank-you-to-our-contributors"&gt;
Thank you to our contributors!&lt;a href="#thank-you-to-our-contributors" aria-hidden="true" class="anchor"&gt;&lt;span aria-hidden="true" class="anchor"&gt;&lt;/span&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Hanami 2.3 is a significant release: it comes courtesy of our &lt;strong&gt;biggest contributors group yet.&lt;/strong&gt; Thank you to all these wonderful humans!&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/aaronmallen"&gt;Aaron Allen&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/alassek"&gt;Adam Lassek&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/rickenharp"&gt;Alexander Gräfe&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/AlexanderZagaynov"&gt;Alexander Zagaynov&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/afomera"&gt;Andrea Fomera&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/baweaver"&gt;Brandon Weaver&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/dcr8898"&gt;Damian C. Rossney&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/davidcelis"&gt;David Celis&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/hanarimawi"&gt;Hana Rimawi&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/inouire"&gt;inouire&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/jaredcwhite"&gt;Jared White&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/josephinehall"&gt;Jojo Hall&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/krzykamil"&gt;Krzysztof Piotrowski&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/kyleplump"&gt;Kyle Plump&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/mathewdbutton"&gt;Mathew Button&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/maxemitchell"&gt;Max Mitchell&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/minaslater"&gt;Mina Slater&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/katafrakt"&gt;Paweł Świątkowski&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/p8"&gt;Petrik de Heus&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/parndt"&gt;Philip Arndt&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/robyurkowski"&gt;Rob Yurkowski&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/radar"&gt;Ryan Bigg&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/cllns"&gt;Sean Collins&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/masterT"&gt;Simon Thiboutôt&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/stephannv"&gt;stephannv&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/svoop"&gt;Sven Schwyn&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/seven1m"&gt;Tim Morgan&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/timriley"&gt;Tim Riley&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/WToa"&gt;William Tio&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/wout"&gt;Wout&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/wuarmin"&gt;wuarmin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/y-yagi"&gt;y-yagi&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There’s always room for more. Our community is &lt;a href="/community"&gt;inclusive and welcoming&lt;/a&gt;, and we’d love to have you join us.&lt;/p&gt;
&lt;h2 id="thank-you-to-our-patrons"&gt;
Thank you to our patrons! &lt;svg class="emoji-logo emoji-logo--hanami inline" height="1em" width="1em" viewbox="0 0 164 159" fill="none" xmlns="http://www.w3.org/2000/svg"&gt; &lt;path fill-rule="evenodd" clip-rule="evenodd" d="m39.3087 98.5899c-3.805.37-7.7441-.02-11.6091-1.28l-7.8299-2.54c-15.09004-4.91-23.36005-21.14-18.45705-36.23s21.13505-23.36 36.22405-18.46l7.8309 2.55c3.864 1.25 7.281 3.25 10.145 5.79-1.524-3.51-2.369-7.3799-2.369-11.4399v-8.2301c0-15.87 12.8821-28.75003733 28.7481-28.75003733s28.7483 12.88003733 28.7483 28.75003733v8.2301c0 4.06-.845 7.9299-2.368 11.4399 2.863-2.54 6.28-4.54 10.145-5.79l7.83-2.55c15.09-4.9 31.321 3.37 36.224 18.46s-3.367 31.32-18.457 36.23l-7.83 2.54c-3.865 1.26-7.804 1.65-11.609 1.28 3.293 1.9401 6.25 4.5801 8.638 7.8601l4.84 6.663c9.326 12.837 6.476 30.829-6.36 40.155-12.837 9.327-30.829 6.477-40.1553-6.359l-4.84-6.661c-2.388-3.288-3.978-6.913-4.806-10.645-.828 3.732-2.418 7.357-4.806 10.645l-4.8391 6.661c-9.326 12.836-27.319 15.686-40.156 6.359-12.836-9.326-15.6859-27.318-6.3589-40.155l4.839-6.663c2.388-3.28 5.345-5.92 8.638-7.8601z" fill="#FF6C89"&gt;&lt;/path&gt; &lt;path d="m81.9919 50.5298c18.2971 0 33.1521 14.8601 33.1521 33.1601 0 18.2901-14.855 33.1481-33.1521 33.1481-18.297 0-33.1521-14.858-33.1521-33.1481 0-18.3 14.8551-33.1601 33.1521-33.1601z" fill="#FFC9C4"&gt;&lt;/path&gt; &lt;/svg&gt;
&lt;a href="#thank-you-to-our-patrons" aria-hidden="true" class="anchor"&gt;&lt;span aria-hidden="true" class="anchor"&gt;&lt;/span&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;This is also our first major release since launching our &lt;a href="/sponsor"&gt;sponsorship program&lt;/a&gt;. I’d like to extend my deepest thanks to our founding patrons: &lt;a href="https://sidekiq.org"&gt;&lt;strong&gt;Sidekiq&lt;/strong&gt;&lt;/a&gt;, &lt;a href="https://github.com/baweaver"&gt;&lt;strong&gt;Brandon Weaver&lt;/strong&gt;&lt;/a&gt;, &lt;a href="https://www.honeybadger.io/?utm_source=hanami&amp;amp;utm_medium=paid-referral&amp;amp;utm_campaign=founding-patron"&gt;&lt;strong&gt;Honeybadger&lt;/strong&gt;&lt;/a&gt;, &lt;a href="https://www.fastruby.io/"&gt;&lt;strong&gt;FastRuby.io&lt;/strong&gt;&lt;/a&gt; and &lt;a href="https://www.appsignal.com/"&gt;&lt;strong&gt;AppSignal&lt;/strong&gt;&lt;/a&gt;. Without you, this release wouldn’t have been possible.&lt;/p&gt;
&lt;p&gt;Thank you also to the individuals supporting Hanami through our &lt;a href="https://github.com/sponsors/hanami"&gt;GitHub Sponsors&lt;/a&gt;. There are now 21 of you!&lt;/p&gt;
&lt;p&gt;We’d love for you to become a patron too. &lt;a href="/sponsor"&gt;Learn more here&lt;/a&gt;.&lt;/p&gt;</content>
  </entry>
  <entry>
    <title>Announcing Hanami 2.3 beta2</title>
    <link rel="alternate" href="https://hanakai.org/blog/2025/10/17/announcing-hanami-230beta2"/>
    <id>https://hanakai.org/blog/2025/10/17/announcing-hanami-230beta2</id>
    <published>2025-10-17T09:30:00+00:00</published>
    <updated>2025-10-17T09:30:00+00:00</updated>
    <author>
      <name>Tim Riley</name>
    </author>
    <content type="html">&lt;p&gt;Two weeks after &lt;a href="/blog/2025/10/03/announcing-hanami-230beta1"&gt;beta1&lt;/a&gt;, it’s time for 2.3 beta2!&lt;/p&gt;
&lt;p&gt;This will be our last beta, and we’re aiming for the full 2.3 release in two weeks. Read on to see what’s new.&lt;/p&gt;
&lt;h2 id="hanami-run-command"&gt;
&lt;code&gt;hanami run&lt;/code&gt; command&lt;a href="#hanami-run-command" aria-hidden="true" class="anchor"&gt;&lt;span aria-hidden="true" class="anchor"&gt;&lt;/span&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;You can now can run your own scripts and code snippets with the &lt;code&gt;hanami run&lt;/code&gt; command!&lt;/p&gt;
&lt;div class="pre-wrapper" data-defo-copy-code&gt;
&lt;button type="button" class="pre-wrapper__button" aria-label="Copy"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" class="pre-wrapper__icon pre-wrapper__icon--copy" height="16" viewbox="0 0 256 256" width="16"&gt; &lt;path d="M172,164a12,12,0,0,1-12,12H96a12,12,0,0,1,0-24h64A12,12,0,0,1,172,164Zm-12-52H96a12,12,0,0,0,0,24h64a12,12,0,0,0,0-24Zm60-64V216a20,20,0,0,1-20,20H56a20,20,0,0,1-20-20V48A20,20,0,0,1,56,28H90.53a51.88,51.88,0,0,1,74.94,0H200A20,20,0,0,1,220,48ZM100.29,60h55.42a28,28,0,0,0-55.42,0ZM196,52H178.59A52.13,52.13,0,0,1,180,64v8a12,12,0,0,1-12,12H88A12,12,0,0,1,76,72V64a52.13,52.13,0,0,1,1.41-12H60V212H196Z"&gt;&lt;/path&gt; &lt;/svg&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" class="pre-wrapper__icon pre-wrapper__icon--check" height="16" viewbox="-13 0 276 276" width="16"&gt; &lt;path d="M232.49,80.49l-128,128a12,12,0,0,1-17,0l-56-56a12,12,0,1,1,17-17L96,183,215.51,63.51a12,12,0,0,1,17,17Z"&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/button&gt;&lt;pre class="syntax-highlighting"&gt;&lt;code&gt;&lt;span class="text plain"&gt;$ bundle exec hanami run my_script.rb
$ bundle exec hanami run 'Hanami.app["repos.commit_repo"].all.count'
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id="improved-action-formats-config"&gt;
Improved action formats config&lt;a href="#improved-action-formats-config" aria-hidden="true" class="anchor"&gt;&lt;span aria-hidden="true" class="anchor"&gt;&lt;/span&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Our &lt;a href="//guides/hanami/v2.2/actions/formats-and-mime-types"&gt;previous approach&lt;/a&gt; to action formats config (&lt;code&gt;config.formats&lt;/code&gt; in action classes or &lt;code&gt;config.actions.formats&lt;/code&gt; in app or slice classes) made it too hard to configure and use your own custom formats. We’ve now overhauled this config and made it much more flexible.&lt;/p&gt;
&lt;p&gt;This is an important change and we’d love your help with testing. If you configure formats for your actions, please pull down this beta and give this a go!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Use &lt;code&gt;config.formats.register&lt;/code&gt; to register a new format and its media types.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This replaces &lt;code&gt;config.formats.add&lt;/code&gt;. Unlike &lt;code&gt;.add&lt;/code&gt;, it does &lt;em&gt;not&lt;/em&gt; activate the format as “accepted” at the same time. This makes it easier to &lt;code&gt;register&lt;/code&gt; your custom formats in app config or a base action class, while maintaining control over where you apply your format restrictions.&lt;/p&gt;
&lt;p&gt;A simple registration looks like this:&lt;/p&gt;
&lt;div class="pre-wrapper" data-defo-copy-code&gt;
&lt;button type="button" class="pre-wrapper__button" aria-label="Copy"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" class="pre-wrapper__icon pre-wrapper__icon--copy" height="16" viewbox="0 0 256 256" width="16"&gt; &lt;path d="M172,164a12,12,0,0,1-12,12H96a12,12,0,0,1,0-24h64A12,12,0,0,1,172,164Zm-12-52H96a12,12,0,0,0,0,24h64a12,12,0,0,0,0-24Zm60-64V216a20,20,0,0,1-20,20H56a20,20,0,0,1-20-20V48A20,20,0,0,1,56,28H90.53a51.88,51.88,0,0,1,74.94,0H200A20,20,0,0,1,220,48ZM100.29,60h55.42a28,28,0,0,0-55.42,0ZM196,52H178.59A52.13,52.13,0,0,1,180,64v8a12,12,0,0,1-12,12H88A12,12,0,0,1,76,72V64a52.13,52.13,0,0,1,1.41-12H60V212H196Z"&gt;&lt;/path&gt; &lt;/svg&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" class="pre-wrapper__icon pre-wrapper__icon--check" height="16" viewbox="-13 0 276 276" width="16"&gt; &lt;path d="M232.49,80.49l-128,128a12,12,0,0,1-17,0l-56-56a12,12,0,1,1,17-17L96,183,215.51,63.51a12,12,0,0,1,17,17Z"&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/button&gt;&lt;pre class="syntax-highlighting"&gt;&lt;code&gt;&lt;span class="source ruby"&gt;config&lt;span class="punctuation accessor ruby"&gt;.&lt;/span&gt;formats&lt;span class="punctuation accessor ruby"&gt;.&lt;/span&gt;register&lt;span class="punctuation definition group begin ruby"&gt;(&lt;/span&gt;&lt;span class="constant other symbol ruby"&gt;&lt;span class="punctuation definition constant ruby"&gt;:&lt;/span&gt;json&lt;/span&gt;&lt;span class="punctuation separator ruby"&gt;,&lt;/span&gt; &lt;span class="string quoted double ruby"&gt;&lt;span class="punctuation definition string begin ruby"&gt;"&lt;/span&gt;application/json&lt;span class="punctuation definition string end ruby"&gt;"&lt;/span&gt;&lt;/span&gt;&lt;span class="punctuation definition group end ruby"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&lt;code&gt;.register&lt;/code&gt; also allows you to register one or more media types for the different stages of request processing:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Provide &lt;code&gt;accept_types:&lt;/code&gt; to accept requests based on specific &lt;code&gt;Accept&lt;/code&gt; types in request headers.&lt;/li&gt;
&lt;li&gt;Provide &lt;code&gt;content_types:&lt;/code&gt; to accept requests based on specific &lt;code&gt;Content-Type&lt;/code&gt; request headers.&lt;/li&gt;
&lt;li&gt;Both the above are are optional. If you do not provide these, then the format’s &lt;em&gt;default&lt;/em&gt; media type (the required second argument) is used for each.&lt;/li&gt;
&lt;li&gt;This default media type is also set as the default &lt;code&gt;Content-Type&lt;/code&gt; response header when requests match that format.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Together, these allow you to register a format like this:&lt;/p&gt;
&lt;div class="pre-wrapper" data-defo-copy-code&gt;
&lt;button type="button" class="pre-wrapper__button" aria-label="Copy"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" class="pre-wrapper__icon pre-wrapper__icon--copy" height="16" viewbox="0 0 256 256" width="16"&gt; &lt;path d="M172,164a12,12,0,0,1-12,12H96a12,12,0,0,1,0-24h64A12,12,0,0,1,172,164Zm-12-52H96a12,12,0,0,0,0,24h64a12,12,0,0,0,0-24Zm60-64V216a20,20,0,0,1-20,20H56a20,20,0,0,1-20-20V48A20,20,0,0,1,56,28H90.53a51.88,51.88,0,0,1,74.94,0H200A20,20,0,0,1,220,48ZM100.29,60h55.42a28,28,0,0,0-55.42,0ZM196,52H178.59A52.13,52.13,0,0,1,180,64v8a12,12,0,0,1-12,12H88A12,12,0,0,1,76,72V64a52.13,52.13,0,0,1,1.41-12H60V212H196Z"&gt;&lt;/path&gt; &lt;/svg&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" class="pre-wrapper__icon pre-wrapper__icon--check" height="16" viewbox="-13 0 276 276" width="16"&gt; &lt;path d="M232.49,80.49l-128,128a12,12,0,0,1-17,0l-56-56a12,12,0,1,1,17-17L96,183,215.51,63.51a12,12,0,0,1,17,17Z"&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/button&gt;&lt;pre class="syntax-highlighting"&gt;&lt;code&gt;&lt;span class="source ruby"&gt;config&lt;span class="punctuation accessor ruby"&gt;.&lt;/span&gt;formats&lt;span class="punctuation accessor ruby"&gt;.&lt;/span&gt;register&lt;span class="punctuation definition group begin ruby"&gt;(&lt;/span&gt;
  &lt;span class="constant other symbol ruby"&gt;&lt;span class="punctuation definition constant ruby"&gt;:&lt;/span&gt;jsonapi&lt;/span&gt;&lt;span class="punctuation separator ruby"&gt;,&lt;/span&gt;
  &lt;span class="string quoted double ruby"&gt;&lt;span class="punctuation definition string begin ruby"&gt;"&lt;/span&gt;application/vnd.api+json&lt;span class="punctuation definition string end ruby"&gt;"&lt;/span&gt;&lt;/span&gt;&lt;span class="punctuation separator ruby"&gt;,&lt;/span&gt;
  &lt;span class="constant other symbol ruby"&gt;accept_types&lt;span class="punctuation definition constant ruby"&gt;:&lt;/span&gt;&lt;/span&gt; &lt;span class="punctuation section array ruby"&gt;[&lt;/span&gt;&lt;span class="string quoted double ruby"&gt;&lt;span class="punctuation definition string begin ruby"&gt;"&lt;/span&gt;application/vnd.api+json&lt;span class="punctuation definition string end ruby"&gt;"&lt;/span&gt;&lt;/span&gt;&lt;span class="punctuation separator ruby"&gt;,&lt;/span&gt; &lt;span class="string quoted double ruby"&gt;&lt;span class="punctuation definition string begin ruby"&gt;"&lt;/span&gt;application/json&lt;span class="punctuation definition string end ruby"&gt;"&lt;/span&gt;&lt;/span&gt;&lt;span class="punctuation section array ruby"&gt;]&lt;/span&gt;&lt;span class="punctuation separator ruby"&gt;,&lt;/span&gt;
  &lt;span class="constant other symbol ruby"&gt;content_types&lt;span class="punctuation definition constant ruby"&gt;:&lt;/span&gt;&lt;/span&gt; &lt;span class="punctuation section array ruby"&gt;[&lt;/span&gt;&lt;span class="string quoted double ruby"&gt;&lt;span class="punctuation definition string begin ruby"&gt;"&lt;/span&gt;application/vnd.api+json&lt;span class="punctuation definition string end ruby"&gt;"&lt;/span&gt;&lt;/span&gt;&lt;span class="punctuation separator ruby"&gt;,&lt;/span&gt; &lt;span class="string quoted double ruby"&gt;&lt;span class="punctuation definition string begin ruby"&gt;"&lt;/span&gt;application/json&lt;span class="punctuation definition string end ruby"&gt;"&lt;/span&gt;&lt;/span&gt;&lt;span class="punctuation section array ruby"&gt;]&lt;/span&gt;&lt;span class="punctuation separator ruby"&gt;,&lt;/span&gt;
&lt;span class="punctuation definition group end ruby"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Use &lt;code&gt;config.formats.accept&lt;/code&gt; to accept specific formats from an action.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;formats.accept&lt;/code&gt; replaces &lt;code&gt;Action.format&lt;/code&gt; and &lt;code&gt;config.format&lt;/code&gt;. You can access your accepted formats via &lt;code&gt;formats.accepted&lt;/code&gt;, which replaces &lt;code&gt;config.formats.values&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;To accept a format:&lt;/p&gt;
&lt;div class="pre-wrapper" data-defo-copy-code&gt;
&lt;button type="button" class="pre-wrapper__button" aria-label="Copy"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" class="pre-wrapper__icon pre-wrapper__icon--copy" height="16" viewbox="0 0 256 256" width="16"&gt; &lt;path d="M172,164a12,12,0,0,1-12,12H96a12,12,0,0,1,0-24h64A12,12,0,0,1,172,164Zm-12-52H96a12,12,0,0,0,0,24h64a12,12,0,0,0,0-24Zm60-64V216a20,20,0,0,1-20,20H56a20,20,0,0,1-20-20V48A20,20,0,0,1,56,28H90.53a51.88,51.88,0,0,1,74.94,0H200A20,20,0,0,1,220,48ZM100.29,60h55.42a28,28,0,0,0-55.42,0ZM196,52H178.59A52.13,52.13,0,0,1,180,64v8a12,12,0,0,1-12,12H88A12,12,0,0,1,76,72V64a52.13,52.13,0,0,1,1.41-12H60V212H196Z"&gt;&lt;/path&gt; &lt;/svg&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" class="pre-wrapper__icon pre-wrapper__icon--check" height="16" viewbox="-13 0 276 276" width="16"&gt; &lt;path d="M232.49,80.49l-128,128a12,12,0,0,1-17,0l-56-56a12,12,0,1,1,17-17L96,183,215.51,63.51a12,12,0,0,1,17,17Z"&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/button&gt;&lt;pre class="syntax-highlighting"&gt;&lt;code&gt;&lt;span class="source ruby"&gt;config&lt;span class="punctuation accessor ruby"&gt;.&lt;/span&gt;formats&lt;span class="punctuation accessor ruby"&gt;.&lt;/span&gt;accept &lt;span class="constant other symbol ruby"&gt;&lt;span class="punctuation definition constant ruby"&gt;:&lt;/span&gt;html&lt;/span&gt;&lt;span class="punctuation separator ruby"&gt;,&lt;/span&gt; &lt;span class="constant other symbol ruby"&gt;&lt;span class="punctuation definition constant ruby"&gt;:&lt;/span&gt;json&lt;/span&gt;
config&lt;span class="punctuation accessor ruby"&gt;.&lt;/span&gt;formats&lt;span class="punctuation accessor ruby"&gt;.&lt;/span&gt;accepted &lt;span class="comment line number-sign ruby"&gt;&lt;span class="punctuation definition comment ruby"&gt;#&lt;/span&gt; =&amp;gt; [:html, :json]
&lt;/span&gt;
config&lt;span class="punctuation accessor ruby"&gt;.&lt;/span&gt;formats&lt;span class="punctuation accessor ruby"&gt;.&lt;/span&gt;accept &lt;span class="constant other symbol ruby"&gt;&lt;span class="punctuation definition constant ruby"&gt;:&lt;/span&gt;csv&lt;/span&gt; &lt;span class="comment line number-sign ruby"&gt;&lt;span class="punctuation definition comment ruby"&gt;#&lt;/span&gt; Accepted formats are additive
&lt;/span&gt;config&lt;span class="punctuation accessor ruby"&gt;.&lt;/span&gt;formats&lt;span class="punctuation accessor ruby"&gt;.&lt;/span&gt;accepted &lt;span class="comment line number-sign ruby"&gt;&lt;span class="punctuation definition comment ruby"&gt;#&lt;/span&gt; =&amp;gt; [:html, :json, :csv]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The first format you give to &lt;code&gt;accept&lt;/code&gt; will also become the &lt;em&gt;default format&lt;/em&gt; for responses from your action, but &lt;em&gt;only&lt;/em&gt; if you haven’t already configured a default using the approach below.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Use config.formats.default=` to set an action’s default format.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This is a new capability. Assign an action’s default format using &lt;code&gt;config.formats.default=&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The default format is used to set the response &lt;code&gt;Content-Type&lt;/code&gt; header when the request does not specify a format via &lt;code&gt;Accept&lt;/code&gt;.&lt;/p&gt;
&lt;div class="pre-wrapper" data-defo-copy-code&gt;
&lt;button type="button" class="pre-wrapper__button" aria-label="Copy"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" class="pre-wrapper__icon pre-wrapper__icon--copy" height="16" viewbox="0 0 256 256" width="16"&gt; &lt;path d="M172,164a12,12,0,0,1-12,12H96a12,12,0,0,1,0-24h64A12,12,0,0,1,172,164Zm-12-52H96a12,12,0,0,0,0,24h64a12,12,0,0,0,0-24Zm60-64V216a20,20,0,0,1-20,20H56a20,20,0,0,1-20-20V48A20,20,0,0,1,56,28H90.53a51.88,51.88,0,0,1,74.94,0H200A20,20,0,0,1,220,48ZM100.29,60h55.42a28,28,0,0,0-55.42,0ZM196,52H178.59A52.13,52.13,0,0,1,180,64v8a12,12,0,0,1-12,12H88A12,12,0,0,1,76,72V64a52.13,52.13,0,0,1,1.41-12H60V212H196Z"&gt;&lt;/path&gt; &lt;/svg&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" class="pre-wrapper__icon pre-wrapper__icon--check" height="16" viewbox="-13 0 276 276" width="16"&gt; &lt;path d="M232.49,80.49l-128,128a12,12,0,0,1-17,0l-56-56a12,12,0,1,1,17-17L96,183,215.51,63.51a12,12,0,0,1,17,17Z"&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/button&gt;&lt;pre class="syntax-highlighting"&gt;&lt;code&gt;&lt;span class="source ruby"&gt;config&lt;span class="punctuation accessor ruby"&gt;.&lt;/span&gt;formats&lt;span class="punctuation accessor ruby"&gt;.&lt;/span&gt;accept &lt;span class="constant other symbol ruby"&gt;&lt;span class="punctuation definition constant ruby"&gt;:&lt;/span&gt;html&lt;/span&gt;&lt;span class="punctuation separator ruby"&gt;,&lt;/span&gt; &lt;span class="constant other symbol ruby"&gt;&lt;span class="punctuation definition constant ruby"&gt;:&lt;/span&gt;json&lt;/span&gt;

&lt;span class="comment line number-sign ruby"&gt;&lt;span class="punctuation definition comment ruby"&gt;#&lt;/span&gt; When no default is already set, the first accepted format becomes default
&lt;/span&gt;config&lt;span class="punctuation accessor ruby"&gt;.&lt;/span&gt;formats&lt;span class="punctuation accessor ruby"&gt;.&lt;/span&gt;default &lt;span class="comment line number-sign ruby"&gt;&lt;span class="punctuation definition comment ruby"&gt;#&lt;/span&gt; =&amp;gt; :html
&lt;/span&gt;
&lt;span class="comment line number-sign ruby"&gt;&lt;span class="punctuation definition comment ruby"&gt;#&lt;/span&gt; But you can now configure this directly
&lt;/span&gt;config&lt;span class="punctuation accessor ruby"&gt;.&lt;/span&gt;formats&lt;span class="punctuation accessor ruby"&gt;.&lt;/span&gt;default &lt;span class="keyword operator assignment ruby"&gt;=&lt;/span&gt; &lt;span class="constant other symbol ruby"&gt;&lt;span class="punctuation definition constant ruby"&gt;:&lt;/span&gt;json&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Previous format config methods are deprecated.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The previous format config methods (&lt;code&gt;Action.format&lt;/code&gt;, &lt;code&gt;config.format&lt;/code&gt;, &lt;code&gt;config.formats.add&lt;/code&gt;, &lt;code&gt;config.formats.values&lt;/code&gt;, and &lt;code&gt;config.formats.values=&lt;/code&gt;) continue to work, but are now deprecated and will be removed in Hanami 2.4.&lt;/p&gt;
&lt;p&gt;Switching to the methods above should be straightforward, and they give you significantly more flexibility. We hope you give them a go!&lt;/p&gt;
&lt;h2 id="thank-you-to-our-patrons"&gt;
Thank you to our patrons &lt;svg class="emoji-logo emoji-logo--hanami inline" height="1em" width="1em" viewbox="0 0 164 159" fill="none" xmlns="http://www.w3.org/2000/svg"&gt; &lt;path fill-rule="evenodd" clip-rule="evenodd" d="m39.3087 98.5899c-3.805.37-7.7441-.02-11.6091-1.28l-7.8299-2.54c-15.09004-4.91-23.36005-21.14-18.45705-36.23s21.13505-23.36 36.22405-18.46l7.8309 2.55c3.864 1.25 7.281 3.25 10.145 5.79-1.524-3.51-2.369-7.3799-2.369-11.4399v-8.2301c0-15.87 12.8821-28.75003733 28.7481-28.75003733s28.7483 12.88003733 28.7483 28.75003733v8.2301c0 4.06-.845 7.9299-2.368 11.4399 2.863-2.54 6.28-4.54 10.145-5.79l7.83-2.55c15.09-4.9 31.321 3.37 36.224 18.46s-3.367 31.32-18.457 36.23l-7.83 2.54c-3.865 1.26-7.804 1.65-11.609 1.28 3.293 1.9401 6.25 4.5801 8.638 7.8601l4.84 6.663c9.326 12.837 6.476 30.829-6.36 40.155-12.837 9.327-30.829 6.477-40.1553-6.359l-4.84-6.661c-2.388-3.288-3.978-6.913-4.806-10.645-.828 3.732-2.418 7.357-4.806 10.645l-4.8391 6.661c-9.326 12.836-27.319 15.686-40.156 6.359-12.836-9.326-15.6859-27.318-6.3589-40.155l4.839-6.663c2.388-3.28 5.345-5.92 8.638-7.8601z" fill="#FF6C89"&gt;&lt;/path&gt; &lt;path d="m81.9919 50.5298c18.2971 0 33.1521 14.8601 33.1521 33.1601 0 18.2901-14.855 33.1481-33.1521 33.1481-18.297 0-33.1521-14.858-33.1521-33.1481 0-18.3 14.8551-33.1601 33.1521-33.1601z" fill="#FFC9C4"&gt;&lt;/path&gt; &lt;/svg&gt;
&lt;a href="#thank-you-to-our-patrons" aria-hidden="true" class="anchor"&gt;&lt;span aria-hidden="true" class="anchor"&gt;&lt;/span&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Thank you to our &lt;a href="/sponsor"&gt;Hanami patrons&lt;/a&gt; who made this release possible! That’s &lt;a href="https://sidekiq.org"&gt;&lt;strong&gt;Sidekiq&lt;/strong&gt;&lt;/a&gt;, &lt;a href="https://github.com/baweaver"&gt;&lt;strong&gt;Brandon Weaver&lt;/strong&gt;&lt;/a&gt;, &lt;a href="https://www.honeybadger.io/?utm_source=hanami&amp;amp;utm_medium=paid-referral&amp;amp;utm_campaign=founding-patron"&gt;&lt;strong&gt;Honeybadger&lt;/strong&gt;&lt;/a&gt;, &lt;a href="https://www.fastruby.io/"&gt;&lt;strong&gt;FastRuby.io&lt;/strong&gt;&lt;/a&gt; and &lt;a href="https://www.appsignal.com/"&gt;&lt;strong&gt;AppSignal&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Thank you also to all the community members supporting Hanami through our &lt;a href="https://github.com/sponsors/hanami"&gt;GitHub Sponsors&lt;/a&gt;. There are now more than 20 of you!&lt;/p&gt;
&lt;p&gt;We’d love for you to become a patron too. &lt;a href="/sponsor"&gt;Learn more here.&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="improvements--fixes"&gt;
Improvements &amp;amp; fixes&lt;a href="#improvements--fixes" aria-hidden="true" class="anchor"&gt;&lt;span aria-hidden="true" class="anchor"&gt;&lt;/span&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;We’ve got even more improvements and fixes in this release:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The router sees a big runtime performance boost for large numbers of routes, addressing a performance regression that was introduced as part of some fixes in Hanami 2.2.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;hanami generate action&lt;/code&gt; now accepts a &lt;code&gt;--skip-tests&lt;/code&gt; flag.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;hanami generate action&lt;/code&gt; will add routes to slice-specific &lt;code&gt;config/routes.rb&lt;/code&gt; files, if present.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;hanami generate&lt;/code&gt; commands now graceully handle names given with mixed cases.&lt;/li&gt;
&lt;li&gt;In new apps, the &lt;code&gt;Types&lt;/code&gt; module now uses &lt;code&gt;Dry.Types(default: :strict)&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;In new apps, the generated &lt;code&gt;Guardfile&lt;/code&gt; now passes the environment from &lt;code&gt;ENV["HANAMI_ENV"]&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The view context no longer includes &lt;code&gt;"settings"&lt;/code&gt; as a default dependency. You can include this yourself if you need it.&lt;/li&gt;
&lt;li&gt;Errors for missing actions in routes now show friendlier, relative file paths.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With this release, we’ve also dropped support for Ruby 3.1. Hanami 2.3 will require Ruby 3.2 or later.&lt;/p&gt;
&lt;h2 id="we-need-your-help"&gt;
We need your help!&lt;a href="#we-need-your-help" aria-hidden="true" class="anchor"&gt;&lt;span aria-hidden="true" class="anchor"&gt;&lt;/span&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;We need your help with testing! In addition to the new action formats config, we’re still keen for feedback from people navigating the upgrade to Rack 3, which we enabled &lt;a href="/blog/2025/10/03/announcing-hanami-230beta1"&gt;as part of beta1&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you have a Hanami app, please try upgrading to 2.3.0.beta2, adopting Rack 3, and improving your action formats. We’d love to hear how you go!&lt;/p&gt;
&lt;h2 id="how-can-i-try-it"&gt;
How can I try it?&lt;a href="#how-can-i-try-it" aria-hidden="true" class="anchor"&gt;&lt;span aria-hidden="true" class="anchor"&gt;&lt;/span&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;div class="pre-wrapper" data-defo-copy-code&gt;
&lt;button type="button" class="pre-wrapper__button" aria-label="Copy"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" class="pre-wrapper__icon pre-wrapper__icon--copy" height="16" viewbox="0 0 256 256" width="16"&gt; &lt;path d="M172,164a12,12,0,0,1-12,12H96a12,12,0,0,1,0-24h64A12,12,0,0,1,172,164Zm-12-52H96a12,12,0,0,0,0,24h64a12,12,0,0,0,0-24Zm60-64V216a20,20,0,0,1-20,20H56a20,20,0,0,1-20-20V48A20,20,0,0,1,56,28H90.53a51.88,51.88,0,0,1,74.94,0H200A20,20,0,0,1,220,48ZM100.29,60h55.42a28,28,0,0,0-55.42,0ZM196,52H178.59A52.13,52.13,0,0,1,180,64v8a12,12,0,0,1-12,12H88A12,12,0,0,1,76,72V64a52.13,52.13,0,0,1,1.41-12H60V212H196Z"&gt;&lt;/path&gt; &lt;/svg&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" class="pre-wrapper__icon pre-wrapper__icon--check" height="16" viewbox="-13 0 276 276" width="16"&gt; &lt;path d="M232.49,80.49l-128,128a12,12,0,0,1-17,0l-56-56a12,12,0,1,1,17-17L96,183,215.51,63.51a12,12,0,0,1,17,17Z"&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/button&gt;&lt;pre class="syntax-highlighting"&gt;&lt;code&gt;&lt;span class="text plain"&gt;&amp;gt; gem install hanami --pre
&amp;gt; hanami new my_app
&amp;gt; cd my_app
&amp;gt; bundle exec hanami dev
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id="whats-included"&gt;
What’s included?&lt;a href="#whats-included" aria-hidden="true" class="anchor"&gt;&lt;span aria-hidden="true" class="anchor"&gt;&lt;/span&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Today we’re releasing the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;hanami v2.3.0.beta2&lt;/li&gt;
&lt;li&gt;hanami-assets v2.3.0-beta.2 (npm package)&lt;/li&gt;
&lt;li&gt;hanami-assets v2.3.0.beta2&lt;/li&gt;
&lt;li&gt;hanami-cli v2.3.0.beta2&lt;/li&gt;
&lt;li&gt;hanami-controller v2.3.0.beta2&lt;/li&gt;
&lt;li&gt;hanami-db v2.3.0.beta2&lt;/li&gt;
&lt;li&gt;hanami-reloader v2.3.0.beta2&lt;/li&gt;
&lt;li&gt;hanami-router v2.3.0.beta2&lt;/li&gt;
&lt;li&gt;hanami-rspec v2.3.0.beta2&lt;/li&gt;
&lt;li&gt;hanami-utils v2.3.0.beta2&lt;/li&gt;
&lt;li&gt;hanami-validations v2.3.0.beta2&lt;/li&gt;
&lt;li&gt;hanami-view v2.3.0.beta2&lt;/li&gt;
&lt;li&gt;hanami-webconsole v2.3.0.beta2&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For the full list of changes, please see each package’s own CHANGELOG.&lt;/p&gt;
&lt;h2 id="whats-next"&gt;
What’s next?&lt;a href="#whats-next" aria-hidden="true" class="anchor"&gt;&lt;span aria-hidden="true" class="anchor"&gt;&lt;/span&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;We have a short list of remaining fixes and improvements to make before our proper 2.3 release. See &lt;a href="https://github.com/orgs/hanami/projects/12/views/1"&gt;this GitHub project&lt;/a&gt; for details.&lt;/p&gt;
&lt;p&gt;We expect to be back with 2.3 in a couple of weeks.&lt;/p&gt;
&lt;h2 id="thank-you-to-our-contributors"&gt;
Thank you to our contributors!&lt;a href="#thank-you-to-our-contributors" aria-hidden="true" class="anchor"&gt;&lt;span aria-hidden="true" class="anchor"&gt;&lt;/span&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Thank you to all these amazing people who contributed to this release!&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/afomera"&gt;Andrea Fomera&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/baweaver"&gt;Brandon Weaver&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/kyleplump"&gt;Kyle Plump&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/minaslater"&gt;Mina Slater&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/cllns"&gt;Sean Collins&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/stephannv"&gt;stephannv&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/timriley"&gt;Tim Riley&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And thank you again for giving this beta a try! We’re looking forward to hearing your feedback. &lt;svg class="emoji-logo emoji-logo--hanami inline" height="1em" width="1em" viewbox="0 0 164 159" fill="none" xmlns="http://www.w3.org/2000/svg"&gt; &lt;path fill-rule="evenodd" clip-rule="evenodd" d="m39.3087 98.5899c-3.805.37-7.7441-.02-11.6091-1.28l-7.8299-2.54c-15.09004-4.91-23.36005-21.14-18.45705-36.23s21.13505-23.36 36.22405-18.46l7.8309 2.55c3.864 1.25 7.281 3.25 10.145 5.79-1.524-3.51-2.369-7.3799-2.369-11.4399v-8.2301c0-15.87 12.8821-28.75003733 28.7481-28.75003733s28.7483 12.88003733 28.7483 28.75003733v8.2301c0 4.06-.845 7.9299-2.368 11.4399 2.863-2.54 6.28-4.54 10.145-5.79l7.83-2.55c15.09-4.9 31.321 3.37 36.224 18.46s-3.367 31.32-18.457 36.23l-7.83 2.54c-3.865 1.26-7.804 1.65-11.609 1.28 3.293 1.9401 6.25 4.5801 8.638 7.8601l4.84 6.663c9.326 12.837 6.476 30.829-6.36 40.155-12.837 9.327-30.829 6.477-40.1553-6.359l-4.84-6.661c-2.388-3.288-3.978-6.913-4.806-10.645-.828 3.732-2.418 7.357-4.806 10.645l-4.8391 6.661c-9.326 12.836-27.319 15.686-40.156 6.359-12.836-9.326-15.6859-27.318-6.3589-40.155l4.839-6.663c2.388-3.28 5.345-5.92 8.638-7.8601z" fill="#FF6C89"&gt;&lt;/path&gt; &lt;path d="m81.9919 50.5298c18.2971 0 33.1521 14.8601 33.1521 33.1601 0 18.2901-14.855 33.1481-33.1521 33.1481-18.297 0-33.1521-14.858-33.1521-33.1481 0-18.3 14.8551-33.1601 33.1521-33.1601z" fill="#FFC9C4"&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/p&gt;</content>
  </entry>
  <entry>
    <title>Announcing Hanami 2.3 beta1</title>
    <link rel="alternate" href="https://hanakai.org/blog/2025/10/03/announcing-hanami-230beta1"/>
    <id>https://hanakai.org/blog/2025/10/03/announcing-hanami-230beta1</id>
    <published>2025-10-03T08:20:00+00:00</published>
    <updated>2025-10-03T08:20:00+00:00</updated>
    <author>
      <name>Tim Riley</name>
    </author>
    <content type="html">&lt;p&gt;After getting set up for &lt;a href="/sponsor"&gt;sponsorship&lt;/a&gt; (we still want to hear from you!), we’re back with a new Hanami release. Today we’re pleased to announce the first beta of Hanami 2.3.&lt;/p&gt;
&lt;h2 id="rack-3-support"&gt;
Rack 3 support&lt;a href="#rack-3-support" aria-hidden="true" class="anchor"&gt;&lt;span aria-hidden="true" class="anchor"&gt;&lt;/span&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;This one goes up to &lt;s&gt;eleven&lt;/s&gt; three.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;With this release, we introduce Rack 3 support to Hanami!&lt;/p&gt;
&lt;p&gt;We now support Rack versions 2 and 3, so you can use whichever version suits your situation. We still encourage you to upgrade Rack when you can, and we’re happy that Hanami is no longer a blocker on this path.&lt;/p&gt;
&lt;p&gt;To upgrade your app to Rack 3, update your Hanami gems to this beta release, then &lt;code&gt;bundle update rack&lt;/code&gt;. You should also check out the &lt;a href="https://github.com/rack/rack/blob/main/UPGRADE-GUIDE.md"&gt;Rack 3 upgrade guide&lt;/a&gt;. Most changes will be handled for you by the Hanami gems, but you may need to update some of your app code if you’re dealing with lower-level request/response details.&lt;/p&gt;
&lt;h2 id="thank-you-to-our-patrons"&gt;
Thank you to our patrons &lt;svg class="emoji-logo emoji-logo--hanami inline" height="1em" width="1em" viewbox="0 0 164 159" fill="none" xmlns="http://www.w3.org/2000/svg"&gt; &lt;path fill-rule="evenodd" clip-rule="evenodd" d="m39.3087 98.5899c-3.805.37-7.7441-.02-11.6091-1.28l-7.8299-2.54c-15.09004-4.91-23.36005-21.14-18.45705-36.23s21.13505-23.36 36.22405-18.46l7.8309 2.55c3.864 1.25 7.281 3.25 10.145 5.79-1.524-3.51-2.369-7.3799-2.369-11.4399v-8.2301c0-15.87 12.8821-28.75003733 28.7481-28.75003733s28.7483 12.88003733 28.7483 28.75003733v8.2301c0 4.06-.845 7.9299-2.368 11.4399 2.863-2.54 6.28-4.54 10.145-5.79l7.83-2.55c15.09-4.9 31.321 3.37 36.224 18.46s-3.367 31.32-18.457 36.23l-7.83 2.54c-3.865 1.26-7.804 1.65-11.609 1.28 3.293 1.9401 6.25 4.5801 8.638 7.8601l4.84 6.663c9.326 12.837 6.476 30.829-6.36 40.155-12.837 9.327-30.829 6.477-40.1553-6.359l-4.84-6.661c-2.388-3.288-3.978-6.913-4.806-10.645-.828 3.732-2.418 7.357-4.806 10.645l-4.8391 6.661c-9.326 12.836-27.319 15.686-40.156 6.359-12.836-9.326-15.6859-27.318-6.3589-40.155l4.839-6.663c2.388-3.28 5.345-5.92 8.638-7.8601z" fill="#FF6C89"&gt;&lt;/path&gt; &lt;path d="m81.9919 50.5298c18.2971 0 33.1521 14.8601 33.1521 33.1601 0 18.2901-14.855 33.1481-33.1521 33.1481-18.297 0-33.1521-14.858-33.1521-33.1481 0-18.3 14.8551-33.1601 33.1521-33.1601z" fill="#FFC9C4"&gt;&lt;/path&gt; &lt;/svg&gt;
&lt;a href="#thank-you-to-our-patrons" aria-hidden="true" class="anchor"&gt;&lt;span aria-hidden="true" class="anchor"&gt;&lt;/span&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;This is a our first release since launching our &lt;a href="/sponsor"&gt;sponsorship program&lt;/a&gt;. I’d like to extend a very warm thank you to the patrons who made this possible: &lt;a href="https://sidekiq.org"&gt;&lt;strong&gt;Sidekiq&lt;/strong&gt;&lt;/a&gt;, &lt;a href="https://github.com/baweaver"&gt;&lt;strong&gt;Brandon Weaver&lt;/strong&gt;&lt;/a&gt;, &lt;a href="https://www.honeybadger.io/?utm_source=hanami&amp;amp;utm_medium=paid-referral&amp;amp;utm_campaign=founding-patron"&gt;&lt;strong&gt;Honeybadger&lt;/strong&gt;&lt;/a&gt;, &lt;a href="https://www.fastruby.io/"&gt;&lt;strong&gt;FastRuby.io&lt;/strong&gt;&lt;/a&gt; and &lt;a href="https://www.appsignal.com/"&gt;&lt;strong&gt;AppSignal&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Thank you also to all the community members supporting Hanami through our &lt;a href="https://github.com/sponsors/hanami"&gt;GitHub Sponsors&lt;/a&gt;. There are now 20 of you!&lt;/p&gt;
&lt;h2 id="improvements"&gt;
Improvements&lt;a href="#improvements" aria-hidden="true" class="anchor"&gt;&lt;span aria-hidden="true" class="anchor"&gt;&lt;/span&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;This beta also brings a range of nice improvements to your Hanami experience:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Add your own methods to &lt;code&gt;hanami console&lt;/code&gt; via own modules. Add &lt;code&gt;config.console.include MyModule, AnotherModule&lt;/code&gt; to your app class.&lt;/li&gt;
&lt;li&gt;Prefer Pry to IRB? Make it the default with &lt;code&gt;config.console.engine = :pry&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;When you specify &lt;code&gt;'nonce'&lt;/code&gt; in your content security policy, a nonce is automatically added to &lt;code&gt;javascript_tag&lt;/code&gt; and &lt;code&gt;stylesheet_tag&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Access subdomains using &lt;code&gt;Request#subdomains&lt;/code&gt;, and configure your default TLD length with &lt;code&gt;config.actions.default_tld_length&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Redirect to absolute URLs in route definitions: &lt;code&gt;redirect '/example', to: https://example.com, code: 302&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;You can now use single-character slice names.&lt;/li&gt;
&lt;li&gt;Run any &lt;code&gt;hanami generate&lt;/code&gt; command inside a slice directory and the slice will automatically be used as the target for the new files.&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;hanami db rollback&lt;/code&gt; to easily rollback a database migration.&lt;/li&gt;
&lt;li&gt;Running &lt;code&gt;hanami new&lt;/code&gt; will now initialize a Git repository in your new app.&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;hanami new&lt;/code&gt; with &lt;code&gt;--skip-view&lt;/code&gt; to skip generating the view layer.&lt;/li&gt;
&lt;li&gt;The default &lt;code&gt;Rakefile&lt;/code&gt; will automatically load custom tasks from the conventional &lt;code&gt;lib/tasks/&lt;/code&gt; location.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;README.md&lt;/code&gt; in newly generated apps now includes some helpful instructions for next steps.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="fixes"&gt;
Fixes&lt;a href="#fixes" aria-hidden="true" class="anchor"&gt;&lt;span aria-hidden="true" class="anchor"&gt;&lt;/span&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;We’ve also fixed a bunch of bugs:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Allow access to autoloaded constants in &lt;code&gt;config/routes.rb&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Support &lt;code&gt;include Deps&lt;/code&gt; in repo classes.&lt;/li&gt;
&lt;li&gt;Avoid false negatives for content type matches in actions.&lt;/li&gt;
&lt;li&gt;Properly show database errors arising from &lt;code&gt;hanami db&lt;/code&gt; commands.&lt;/li&gt;
&lt;li&gt;Skip ENV var processing by Foreman (run via &lt;code&gt;hanami dev&lt;/code&gt; by default) to ensure consistent ENV loading across environemnts.&lt;/li&gt;
&lt;li&gt;Respect app inflections when running &lt;code&gt;hanami generate&lt;/code&gt; commands.&lt;/li&gt;
&lt;li&gt;Prevent &lt;code&gt;generate&lt;/code&gt; commands from overwriting files.&lt;/li&gt;
&lt;li&gt;Convert special characters to underscores in route helper names.&lt;/li&gt;
&lt;li&gt;Include all necessary gems when running &lt;code&gt;hanami new&lt;/code&gt; with the &lt;code&gt;--head&lt;/code&gt; option.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="we-need-your-help"&gt;
We need your help!&lt;a href="#we-need-your-help" aria-hidden="true" class="anchor"&gt;&lt;span aria-hidden="true" class="anchor"&gt;&lt;/span&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Our Rack 3 upgrade is one of the more intricate changes we’ve made, especially considering the broad ecosystem that depends on Rack. We need your help to make sure this goes smoothly!&lt;/p&gt;
&lt;p&gt;If you have a Hanami app, please try upgrading to 2.3.0.beta1 and Rack 3, and let us know how you go!&lt;/p&gt;
&lt;h2 id="how-can-i-try-it"&gt;
How can I try it?&lt;a href="#how-can-i-try-it" aria-hidden="true" class="anchor"&gt;&lt;span aria-hidden="true" class="anchor"&gt;&lt;/span&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;div class="pre-wrapper" data-defo-copy-code&gt;
&lt;button type="button" class="pre-wrapper__button" aria-label="Copy"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" class="pre-wrapper__icon pre-wrapper__icon--copy" height="16" viewbox="0 0 256 256" width="16"&gt; &lt;path d="M172,164a12,12,0,0,1-12,12H96a12,12,0,0,1,0-24h64A12,12,0,0,1,172,164Zm-12-52H96a12,12,0,0,0,0,24h64a12,12,0,0,0,0-24Zm60-64V216a20,20,0,0,1-20,20H56a20,20,0,0,1-20-20V48A20,20,0,0,1,56,28H90.53a51.88,51.88,0,0,1,74.94,0H200A20,20,0,0,1,220,48ZM100.29,60h55.42a28,28,0,0,0-55.42,0ZM196,52H178.59A52.13,52.13,0,0,1,180,64v8a12,12,0,0,1-12,12H88A12,12,0,0,1,76,72V64a52.13,52.13,0,0,1,1.41-12H60V212H196Z"&gt;&lt;/path&gt; &lt;/svg&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" class="pre-wrapper__icon pre-wrapper__icon--check" height="16" viewbox="-13 0 276 276" width="16"&gt; &lt;path d="M232.49,80.49l-128,128a12,12,0,0,1-17,0l-56-56a12,12,0,1,1,17-17L96,183,215.51,63.51a12,12,0,0,1,17,17Z"&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/button&gt;&lt;pre class="syntax-highlighting"&gt;&lt;code&gt;&lt;span class="text plain"&gt;&amp;gt; gem install hanami --pre
&amp;gt; hanami new my_app
&amp;gt; cd my_app
&amp;gt; bundle exec hanami dev
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id="whats-included"&gt;
What’s included?&lt;a href="#whats-included" aria-hidden="true" class="anchor"&gt;&lt;span aria-hidden="true" class="anchor"&gt;&lt;/span&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Today we’re releasing the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;hanami v2.3.0.beta1&lt;/li&gt;
&lt;li&gt;hanami-assets v2.3.0-beta.1 (npm package)&lt;/li&gt;
&lt;li&gt;hanami-assets v2.3.0.beta1&lt;/li&gt;
&lt;li&gt;hanami-cli v2.3.0.beta1&lt;/li&gt;
&lt;li&gt;hanami-controller v2.3.0.beta1&lt;/li&gt;
&lt;li&gt;hanami-db v2.3.0.beta1&lt;/li&gt;
&lt;li&gt;hanami-reloader v2.3.0.beta1&lt;/li&gt;
&lt;li&gt;hanami-router v2.3.0.beta1&lt;/li&gt;
&lt;li&gt;hanami-rspec v2.3.0.beta1&lt;/li&gt;
&lt;li&gt;hanami-utils v2.3.0.beta1&lt;/li&gt;
&lt;li&gt;hanami-validations v2.3.0.beta1&lt;/li&gt;
&lt;li&gt;hanami-view v2.3.0.beta1&lt;/li&gt;
&lt;li&gt;hanami-webconsole v2.3.0.beta1&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For the full list of changes, please see each package’s own CHANGELOG.&lt;/p&gt;
&lt;h2 id="whats-next"&gt;
What’s next?&lt;a href="#whats-next" aria-hidden="true" class="anchor"&gt;&lt;span aria-hidden="true" class="anchor"&gt;&lt;/span&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;We have a short list of remaining fixes and improvements to make before a proper 2.3 release. See &lt;a href="https://github.com/orgs/hanami/projects/12/views/1"&gt;this GitHub project&lt;/a&gt; for details.&lt;/p&gt;
&lt;p&gt;I anticipate we’ll do one more beta release, followed by the final 2.3 release.&lt;/p&gt;
&lt;h2 id="thank-you-to-our-contributors"&gt;
Thank you to our contributors!&lt;a href="#thank-you-to-our-contributors" aria-hidden="true" class="anchor"&gt;&lt;span aria-hidden="true" class="anchor"&gt;&lt;/span&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Thank you to all these amazing people who contributed to this release!&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/aaronmallen"&gt;Aaron Allen&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/alassek"&gt;Adam Lassek&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/AlexanderZagaynov"&gt;Alexander Zagaynov&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/afomera"&gt;Andrea Fomera&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/hanarimawi"&gt;Hana Rimawi&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/inouire"&gt;inouire&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/krzykamil"&gt;Krzysztof Piotrowski&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/kyleplump"&gt;Kyle Plump&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/maxemitchell"&gt;Max Mitchell&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/katafrakt"&gt;Paweł Świątkowski&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/cllns"&gt;Sean Collins&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/stephannv"&gt;stephannv&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/svoop"&gt;Sven Schwyn&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/seven1m"&gt;Tim Morgan&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/timriley"&gt;Tim Riley&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/WToa"&gt;William Tio&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/wout"&gt;Wout&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/wuarmin"&gt;wuarmin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/y-yagi"&gt;y-yagi&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And thank you again for giving this beta a try! We’re looking forward to hearing your feedback. &lt;svg class="emoji-logo emoji-logo--hanami inline" height="1em" width="1em" viewbox="0 0 164 159" fill="none" xmlns="http://www.w3.org/2000/svg"&gt; &lt;path fill-rule="evenodd" clip-rule="evenodd" d="m39.3087 98.5899c-3.805.37-7.7441-.02-11.6091-1.28l-7.8299-2.54c-15.09004-4.91-23.36005-21.14-18.45705-36.23s21.13505-23.36 36.22405-18.46l7.8309 2.55c3.864 1.25 7.281 3.25 10.145 5.79-1.524-3.51-2.369-7.3799-2.369-11.4399v-8.2301c0-15.87 12.8821-28.75003733 28.7481-28.75003733s28.7483 12.88003733 28.7483 28.75003733v8.2301c0 4.06-.845 7.9299-2.368 11.4399 2.863-2.54 6.28-4.54 10.145-5.79l7.83-2.55c15.09-4.9 31.321 3.37 36.224 18.46s-3.367 31.32-18.457 36.23l-7.83 2.54c-3.865 1.26-7.804 1.65-11.609 1.28 3.293 1.9401 6.25 4.5801 8.638 7.8601l4.84 6.663c9.326 12.837 6.476 30.829-6.36 40.155-12.837 9.327-30.829 6.477-40.1553-6.359l-4.84-6.661c-2.388-3.288-3.978-6.913-4.806-10.645-.828 3.732-2.418 7.357-4.806 10.645l-4.8391 6.661c-9.326 12.836-27.319 15.686-40.156 6.359-12.836-9.326-15.6859-27.318-6.3589-40.155l4.839-6.663c2.388-3.28 5.345-5.92 8.638-7.8601z" fill="#FF6C89"&gt;&lt;/path&gt; &lt;path d="m81.9919 50.5298c18.2971 0 33.1521 14.8601 33.1521 33.1601 0 18.2901-14.855 33.1481-33.1521 33.1481-18.297 0-33.1521-14.858-33.1521-33.1481 0-18.3 14.8551-33.1601 33.1521-33.1601z" fill="#FFC9C4"&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/p&gt;</content>
  </entry>
  <entry>
    <title>Hanami adopts Contributor Covenant 3.0</title>
    <link rel="alternate" href="https://hanakai.org/blog/2025/09/02/hanami-adopts-contributor-covenant-3-0"/>
    <id>https://hanakai.org/blog/2025/09/02/hanami-adopts-contributor-covenant-3-0</id>
    <published>2025-09-02T08:30:00+00:00</published>
    <updated>2025-09-02T08:30:00+00:00</updated>
    <author>
      <name>Tim Riley</name>
    </author>
    <content type="html">&lt;p&gt;Our community is the most precious part of Hanami. When you pick up Hanami, we want to make sure you have a great time. This is why we place our community values front and centre &lt;a href="https://hanamirb.org"&gt;on our home page&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;We want the Hanami community to be a welcoming place for people who bring kindness, curiosity, and care. A place where people of all backgrounds and experience levels can feel respected, and can share and grow. A place for people to be proud of, and feel safe within.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;It’s also why we govern our community spaces under the &lt;a href="https://www.contributor-covenant.org"&gt;Contributor Covenant&lt;/a&gt; code of conduct. This is the gold standard for community codes of conduct, and it’s served us well &lt;a href="https://github.com/hanami/hanami/commit/54ce22376146efcd8a76c0b281e5bb74a3ff16e1"&gt;for over ten years&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Today we’re delighted to adopt the new &lt;a href="https://www.contributor-covenant.org/version/3/0/code_of_conduct/"&gt;Contributor Covenant 3.0&lt;/a&gt;,&lt;/strong&gt; released just last month. This new version brings &lt;a href="https://ethicalsource.dev/blog/contributor-covenant-3/"&gt;a number of improvements&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Contributor Covenant 3.0 is designed to be more adaptable to different kinds of communities, both online and offline. It is written with clearer, less US-centric language, intended to be easier to understand and translate. The enforcement guidelines section has been reimagined as “Addressing and Repairing Harm,” reflecting an alignment with principles of restorative justice, including finding ways to safely reintegrate someone back into a community after an incident occurs.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;We’re pleased that this new version is more approachable for our worldwide community. We also welcome the focus on restorative justice. The examples of how people can make genuine amends to grow and rejoin a community are clear and well explained.&lt;/p&gt;
&lt;p&gt;These changes won’t affect how we interact day-to-day in our already lovely community, but do give us better tools for the rare times when conflicts need thoughtful resolution.&lt;/p&gt;
&lt;p&gt;Thank you to the &lt;a href="https://ethicalsource.dev"&gt;Organization for Ethical Source&lt;/a&gt; for their work on this new version!&lt;/p&gt;
&lt;p&gt;You can find our instance of the Contributor Covenant on &lt;a href="https://hanamirb.org/community/#code-of-conduct"&gt;our community page&lt;/a&gt;.&lt;/p&gt;</content>
  </entry>
  <entry>
    <title>Wrapping up our sponsorship drive</title>
    <link rel="alternate" href="https://hanakai.org/blog/2025/08/27/wrapping-up-our-sponsorship-drive"/>
    <id>https://hanakai.org/blog/2025/08/27/wrapping-up-our-sponsorship-drive</id>
    <published>2025-08-27T11:45:00+00:00</published>
    <updated>2025-08-27T11:45:00+00:00</updated>
    <author>
      <name>Tim Riley</name>
    </author>
    <content type="html">&lt;p&gt;After six posts (the &lt;a href="/blog/2025/06/03/become-a-hanami-dry-and-rom-patron"&gt;announcement&lt;/a&gt;, our &lt;a href="/blog/2025/06/11/hear-from-our-founding-patrons"&gt;founding patrons&lt;/a&gt;, a &lt;a href="/blog/2025/06/20/field-report-from-riga-and-the-rooftop"&gt;field report&lt;/a&gt;, meeting &lt;a href="/blog/2025/06/26/meet-tim-and-sean"&gt;Tim and Sean&lt;/a&gt;, the &lt;a href="/blog/2025/07/11/hanami-and-the-elephant-in-the-room"&gt;Rails elephant in the room&lt;/a&gt;, and a &lt;a href="/blog/2025/07/24/the-look-of-things-to-come"&gt;cuteness preview&lt;/a&gt;), it’s time to wrap up our sponsorship drive for 2025.&lt;/p&gt;
&lt;h2 id="howd-we-go"&gt;
How’d we go?&lt;a href="#howd-we-go" aria-hidden="true" class="anchor"&gt;&lt;span aria-hidden="true" class="anchor"&gt;&lt;/span&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Thanks to your support, we’ve entered a whole new era for Hanami, Dry and Rom. For the first time ever, Ruby has a &lt;em&gt;second&lt;/em&gt; framework backed by funding!&lt;/p&gt;
&lt;p&gt;Granted, we’re at only 0.2 of a full-time role, but a start is a start! We’re here for the long haul, and going from 0 to &lt;em&gt;something&lt;/em&gt; is one of the most important jumps we will make.&lt;/p&gt;
&lt;p&gt;We have you—the Ruby community—to thank for this.&lt;/p&gt;
&lt;p&gt;Thank you especially to &lt;a href="https://www.mikeperham.com"&gt;Mike Perham&lt;/a&gt; and &lt;a href="https://sidekiq.org"&gt;Sidekiq&lt;/a&gt;, &lt;a href="https://github.com/baweaver"&gt;Brandon Weaver&lt;/a&gt;, Joshua Wood and &lt;a href="https://www.honeybadger.io/?utm_source=hanami&amp;amp;utm_medium=paid-referral&amp;amp;utm_campaign=founding-patron"&gt;Honeybadger&lt;/a&gt;, Ernesto Tagwerker and &lt;a href="https://www.fastruby.io/"&gt;FastRuby&lt;/a&gt;, and Roy Tomeij and &lt;a href="https://www.appsignal.com/"&gt;AppSignal&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;These are our &lt;a href="/blog/2025/06/11/hear-from-our-founding-patrons"&gt;founding patrons&lt;/a&gt;, and without their support, this whole thing would never have got off the ground. They’ve committed $26k towards our first year of paid maintenance.&lt;/p&gt;
&lt;p&gt;These people are visionaries, going out of their way to support a brighter, better Ruby. Just look at how Brandon describes it:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;In Ruby diversity is our greatest strength, whether that be the people, the ideas, or the technologies we use. Ruby is not just one framework, nor is it just one person, it is a community of passionate people pushing the boundaries of what’s possible not just as individuals, but as a collective. I am happy to continue to fund efforts building upon that vision of the future.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Who &lt;em&gt;wouldn’t&lt;/em&gt; want this for Ruby? We’re doing everything we can to make this real.&lt;/p&gt;
&lt;p&gt;We’ve also been buoyed by new support from fellow community members. We’ve been delighted to welcome 15 new community patrons via our &lt;a href="https://github.com/sponsors/hanami"&gt;GitHub Sponsors&lt;/a&gt;. These are individuals who’re putting their own money towards Hanami, and together they’re contributing $260/month. Thank you!&lt;/p&gt;
&lt;p&gt;We’ve also established &lt;a href="https://rubycentral.org/news/ruby-central-announces-open-source-fiscal-sponsorship-program-hanami-support/"&gt;a partnership with Ruby Central&lt;/a&gt; as our fiscal host. Ruby Central gives us a very attractive fee structure (5% vs the 10% that Open Collective charges) and they have already handled the funds for most of our business patrons. This means more of your money goes directly to our work on tools for Rubyists.&lt;/p&gt;
&lt;p&gt;Ruby Central went out of their way to set this up for us, and I couldn’t think of a better partner for this. We share the same vision for Ruby’s future, and I’m excited to collaborate with them for many years to come!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;After all of this, how did we go? We’ve raised $29k (so far!). This is short of our initial $40k target, but fortunately, it’s still enough to support me at 1 day/week for this first year of paid maintenance.&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id="were-ready-are-you"&gt;
We’re ready. Are you?&lt;a href="#were-ready-are-you" aria-hidden="true" class="anchor"&gt;&lt;span aria-hidden="true" class="anchor"&gt;&lt;/span&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;While our sponsorship drive may be coming to an end, we’re ready to bring in new supporters at any time.&lt;/p&gt;
&lt;p&gt;Does your business already depend on our gear? (I’m sure there are a lot of you out there, with our billion gem downloads and counting across Hanami, Dry and Rom). Or do you want to step up and count yourself among the brave few willing to forge a healthier, kinder future for Ruby? If so, then come &lt;a href="/sponsor"&gt;talk to us&lt;/a&gt;!&lt;/p&gt;
&lt;h2 id="whats-next"&gt;
What’s next?&lt;a href="#whats-next" aria-hidden="true" class="anchor"&gt;&lt;span aria-hidden="true" class="anchor"&gt;&lt;/span&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Establishing our sponsorship was &lt;a href="/blog/2024/12/10/state-of-hanami-december-2024"&gt;one of our most important goals for 2025&lt;/a&gt;, and I’m very happy we’ve managed to get that done. While it did take a lot of time and brain space, we’ve still managed several other initiatives:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Upcoming release:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Moving towards a Hanami 2.3 release. Rack 3 support will be the centrepiece here, but this will bring in a range of small improvements and fixes too.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Brand and community:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Preparing new branding for our projects, along with a way to bring them together as a unified family. &lt;a href="/blog/2025/07/24/the-look-of-things-to-come"&gt;You’ve seen a preview of this already&lt;/a&gt;!&lt;/li&gt;
&lt;li&gt;Building our brand new website, which will provide a one-stop shop for everything Hanami, Dry and Rom. Guides, docs, news, community info and more.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Project maintenance:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Catching up on &lt;em&gt;housekeeping&lt;/em&gt;. First order of business is rolling out a tool to keep our 50+ GitHub repos in sync.&lt;/li&gt;
&lt;li&gt;Working on new contributor guidelines that will make it clear how you can become a maintainer, and empower our existing maintainers to take our gems to the next level.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;One more thing:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Personally, I’ve (finally!) found some time to work on my open source Hanami example app, Decaf Sucks. My current focus is &lt;a href="https://github.com/decafsucks/decafsucks/pull/32"&gt;adding streamlined Rodauth integration&lt;/a&gt;, something that feels completely “Hanami-native” and can serve as the foundation for an eventual rodauth-hanami gem.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With sponsorships in place, I can’t wait to bring you all of the above!&lt;/p&gt;
&lt;p&gt;Exciting stuff is on the way. If you want to help out or follow along, come say hi in &lt;a href="https://discord.gg/KFCxDmk3JQ"&gt;chat&lt;/a&gt; or &lt;a href="https://discourse.hanakai.org"&gt;our forum&lt;/a&gt;!&lt;/p&gt;</content>
  </entry>
</feed>
