There formed a subculture inside Ruby community, of people who love code that is as structured and declarative as possible, with an abstraction over anything that has a name, and a hierarchy of namespaces that map onto paths or grouping of similar things, rather than parts of a module or a library. There are many examples of libs like these out there (I won't name names). For example, libraries that let you write "service objects" declaratively with some block/lambda trickery.
I find this to be a fun way to play with and explore Ruby, but once it comes to building stuff for production, I encourage to take a bunch of steps back and rethink what is really being gained. Many of these libraries end up turning Ruby almost unrecognizable. And the fact is that if you sit down and try to rewrite the same thing into plain imperative ruby, you'd lose nothing (it won't even be longer), but you'd gain clarity and maintainability, because code becomes simple and obvious. I know this because I've done all of the above in the past, and it humbled me a number of times. I wish more people were trying to do this exercise of ruthlessly comparing their lib's solution to the same thing done in plain ruby. It may feel bad at first because it bursts the bubble of excitement one may've inflated while building a lib. But then I find it actually makes you more excited about Ruby again.
I haven't personally used Hanami, been following it from a distance, and I might be wrong in this impression, but I found it to be leaning a little too hard into the camp described above. That said, performance gains are certainly welcome.
Probably won't go over well, but, are either of these pleasant to use with some gradual type systems? Is Sorbet or something like that viable to use daily? Ruby is a great language, but I've spent enough of my life chasing down errors a type checker can catch for me.
Shopify uses Sorbet and a few companion projects (e.g., Spoom¹ and Tapioca²) to manage Rails projects of various sizes. While there are some holes, like you find with any gradual type system, I think you'll find the experience is quite good. The awesome-sorbet³ project has a comprehensive list of blog posts, conference presentations, and podcast episodes that dig into that deeper.
I find this to be a fun way to play with and explore Ruby, but once it comes to building stuff for production, I encourage to take a bunch of steps back and rethink what is really being gained. Many of these libraries end up turning Ruby almost unrecognizable. And the fact is that if you sit down and try to rewrite the same thing into plain imperative ruby, you'd lose nothing (it won't even be longer), but you'd gain clarity and maintainability, because code becomes simple and obvious. I know this because I've done all of the above in the past, and it humbled me a number of times. I wish more people were trying to do this exercise of ruthlessly comparing their lib's solution to the same thing done in plain ruby. It may feel bad at first because it bursts the bubble of excitement one may've inflated while building a lib. But then I find it actually makes you more excited about Ruby again.
I haven't personally used Hanami, been following it from a distance, and I might be wrong in this impression, but I found it to be leaning a little too hard into the camp described above. That said, performance gains are certainly welcome.