with one click
hanami-routing
// Expert guidance on building, configuring, and managing Hanami Routes
// Expert guidance on building, configuring, and managing Hanami Routes
[HINT] Download the complete skill directory including SKILL.md and all related files
| name | hanami-routing |
| description | Expert guidance on building, configuring, and managing Hanami Routes |
This skill provides expert guidance on defining, configuring, and managing Hanami routes (v2.x). It covers basic routes, resource routing, path matching, named helpers, scopes, redirects, and route inspection.
Create a basic route
config/routes.rb inside the Routes classget "/books", to: "books.index"
post "/books", to: "books.create"
put "/books/:id", to: "books.update"
patch "/books/:id", to: "books.update"
delete "/books/:id", to: "books.destroy"
Use blocks and Rack apps as endpoints
get "/hello" do
[200, {}, ["Hello from Hanami"]]
end
get "/rack-app", to: RackApp.new
get "/lambda", to: ->(env) { [200, {}, ["Lambda response"]] }
Define root route
root { "Hello from Hanami" }
# Or invoke an action
root to: "home"
Create collection resources
resources :books
Generates:
| HTTP Method | Path | Action |
|---|---|---|
| GET | /books | books.index |
| GET | /books/:id | books.show |
| GET | /books/new | books.new |
| POST | /books | books.create |
| GET | /books/:id/edit | books.edit |
| PATCH | /books/:id | books.update |
| DELETE | /books/:id | books.destroy |
Create singleton resources
resource :profile
Generates routes for /profile (no index, no :id) without a collection endpoint.
Filter resource actions
# Only specific actions
resources :books, only: [:index, :show]
# Exclude specific actions
resources :books, except: [:destroy]
Customize resource routes
# Custom URL path
resources :comments, path: "reviews"
# Custom action namespace
resources :books, to: "library.books"
# Custom route name
resources :books, as: :publications
Nest resources
resources :books do
resources :reviews
end
Generates nested routes like /books/:book_id/reviews. Actions are namespaced under the parent (e.g., books.reviews.index).
Mix basic routes within resources
resources :books do
get "/latest", to: "books.latest"
end
Use path variables
get "/books/:id", to: "books.show"
# In action:
request.params[:id] # => "1"
Multiple variables:
get "/books/:book_id/reviews/:id", to: "book_reviews.show"
# In action:
request.params[:book_id] # => "17"
request.params[:id] # => "6"
Add constraints to path variables
get "/books/:id", id: /\d+/, to: "books.show"
# GET /books/2 # matches
# GET /books/two # does not match
get "/books/award-winners/:year", year: /\d{4}/, to: "books.award_winners.index"
# GET /books/award-winners/2022 # matches
# GET /books/award-winners/2 # does not match
Use globbing for catch-all routes
get "/pages/*path", to: "page_catch_all"
# GET /pages/2022/my-page
# request.params[:path] # => "2022/my-page"
# Global catch-all (place last)
get "/*path", to: "unmatched"
Name routes for URL helpers
get "/books", to: "books.index", as: :books
get "/books/:id", to: "books.show", as: :book
Access helpers:
Hanami.app["routes"].path(:books)
=> "/books"
Hanami.app["routes"].path(:book, id: 1)
=> "/books/1"
Hanami.app["routes"].url(:book, id: 1)
=> #<URI::HTTP http://0.0.0.0:2300/books/1>
Configure base URL for url helpers
# config/app.rb
module Bookshelf
class App < Hanami::App
config.base_url = "https://bookshelf.example.com"
end
end
Use scopes for route prefixing and namespacing
scope "about" do
get "/contact-us", to: "content.contact", as: :contact # => /about/contact-us
get "/faq", to: "content.faq", as: :faq # => /about/faq
end
Named routes get prefix: :about_contact, :about_faq.
Scope with path variables
scope "authors/:author_id", as: :author do
resources :books, only: [:index, :show], to: "authors.books"
get "/news", to: "authors.news", as: :news
end
Generates:
GET /authors/:author_id/books authors.books.index :author_books
GET /authors/:author_id/books/:id authors.books.show :author_book
GET /authors/:author_id/news authors.news :author_news
Customize scope route name prefix
scope "authors/:author_id", as: :author do
get "send-feedback", to: "authors.send_feedback", as: [:send, :feedback]
# Named :send_author_feedback (array inserts scope prefix between elements)
end
Add redirects
# Basic redirect (301)
redirect "/old", to: "/new"
# Custom status code
redirect "/old", to: "/temporary-new", code: 302
# Absolute URL
redirect "/external", to: "http://hanamirb.org"
# Non-HTTP protocols
redirect "/custom", to: URI("xmpp://myapp.net")
List routes via CLI
bundle exec hanami routes
Output:
GET / home as :root
GET /books books.index
GET /books/:id books.show
GET /books/new books.new
POST /books books.create
GET /books/:id/edit books.edit
PATCH /books/:id books.update
DELETE /books/:id books.destroy
When assisting with Hanami Routing tasks, follow this workflow:
Identify the routing requirements
Choose the appropriate route type
resources for full CRUD collectionsresource for singleton endpointsProvide implementation guidance
Address naming and helper needs
as options for meaningful route namespath and url helpersbase_url when URL helpers need a domainGuide route inspection and debugging
bundle exec hanami routes for verificationReview and refine
When detailed information is needed about specific topics, consult the Hanami documentation:
config/routes.rb within the Routes classresources (plural) for collection resources, resource (singular) for singletons/*path) last to avoid shadowing other routesas names for all routes that need URL helpersbase_url config for production url helper outputresources for standard CRUD endpoints to reduce boilerplateas for all routes that will be referenced via URL helpers:books, :book)as to create meaningful prefixed route namesbundle exec hanami routes after adding or modifying routesonly and except to keep resource routes minimal when needed