# What Aaron built and why Aaron Allen built his personal site with Hanami. The site looks like a standard blog but includes a number of backend features he uses daily: cross-posting to Bluesky and Mastodon, a private journal, a custom analytics engine, a messaging backend for contact form messages, a task manager that syncs with Linear and GitHub Issues, and an activity feed that aggregates commits, journal entries, posts, and tasks.
He chose Hanami because he found Rails overly prescriptive and had moved to Sinatra for freedom before discovering Hanami at RubyConf 2024. Since then he became a maintainer on the Hanakai team and started using Hanami for real projects.
# How Hanami organizes applications Hanami pushes toward small, single-purpose abstractions. The four core pieces Aaron highlights are:
- Relations: the low-level model layer that handles database queries.
- Repos: an optional higher-level persistence layer that wraps relations and returns plain data objects (structs) to avoid leaking persistence details.
This separation means a simple CRUD flow will typically be implemented across multiple classes: an Action for the HTTP interaction, a Repo or Relation for persistence, and an Operation for complex mutations.
# Supporting libraries in the Hanami ecosystem Aaron lists several supporting libraries that shape how Hanami apps are built:
- dry-system: provides dependency injection. Classes include a Deps module to declare what they need, and the system injects instances automatically.
- dry-types: offers a typing system used to validate and normalize inputs (Aaron notes he will show more about types later in the series).
- dry-monads: gives Success and Failure result objects used by both Operations and Actions, which can simplify control flow when combined with pattern matching.
# What this means for developers
The practical effect on Aaron's own site is a collection of focused pieces: separate endpoints for different actions, an operation layer for mutations, and a typed validation layer for incoming data. He plans to explain these choices and patterns in more depth in upcoming posts of the "Hanami, Why?" series.
# Example snapshot Aaron includes a short code sketch (truncated in the shared excerpt) showing an Action that injects an operation, validates params, calls the operation, and handles Success/Failure cases. That example demonstrates the intended flow: dependency-injected operations, parameter validation via types, and pattern-matched result handling.
# What to expect next