> ## Documentation Index
> Fetch the complete documentation index at: https://docs.appsignal.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Hanami

export const VersionRequirements = ({versions = []}) => {
  if (!Array.isArray(versions) || versions.length === 0) {
    return null;
  }
  const boundaries = {
    upper: " or lower",
    exact: "",
    lower: " or higher"
  };
  const containerStyle = {
    marginTop: "0.5rem",
    marginBottom: "1.5rem"
  };
  const lineStyle = {
    display: "block",
    margin: "0 0 0.35rem 0",
    fontSize: "0.875rem",
    lineHeight: "1.4"
  };
  const pillBaseStyle = {
    display: "inline-block",
    padding: "0.1em 0.4em",
    borderRadius: "0.25rem",
    border: "1px solid",
    fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace",
    fontSize: "0.85em",
    fontWeight: 500
  };
  const pillColors = {
    "AppSignal for Elixir": {
      background: "#f3e8ff",
      borderColor: "#e9d5ff",
      color: "#9333ea"
    },
    "AppSignal for Front-end": {
      background: "#fef9c3",
      borderColor: "#fde68a",
      color: "#ca8a04"
    },
    "AppSignal for Go": {
      background: "#ccfbf1",
      borderColor: "#99f6e4",
      color: "#0d9488"
    },
    "AppSignal for JavaScript": {
      background: "#fef9c3",
      borderColor: "#fde68a",
      color: "#ca8a04"
    },
    "AppSignal for Node.js": {
      background: "#dcfce7",
      borderColor: "#bbf7d0",
      color: "#16a34a"
    },
    "AppSignal for Python": {
      background: "#dbeafe",
      borderColor: "#bfdbfe",
      color: "#2563eb"
    },
    "AppSignal for Ruby": {
      background: "#fee2e2",
      borderColor: "#fecaca",
      color: "#dc2626"
    },
    "AppSignal for Rust": {
      background: "#ffedd5",
      borderColor: "#fed7aa",
      color: "#ea580c"
    }
  };
  const defaultPillColor = {
    background: "#f4f4f5",
    borderColor: "#e4e4e7",
    color: "#52525b"
  };
  const getPillStyle = name => ({
    ...pillBaseStyle,
    ...pillColors[name] || defaultPillColor
  });
  const getBoundText = bound => {
    return boundaries[bound] || boundaries.lower;
  };
  return <div style={containerStyle}>
      {versions.map((v, i) => <p key={`${v.name}-${v.version}-${v.bound || "lower"}-${i}`} style={lineStyle}>
          This feature requires{" "}
          <code style={getPillStyle(v.name)}>{v.name}</code> version {v.version}
          {getBoundText(v.bound)}.
        </p>)}
    </div>;
};

<VersionRequirements
  versions={[
{ name: "AppSignal for Ruby", version: "3.3.0" },
{ name: "Hanami", version: "2" }
]}
/>

[Hanami](https://hanamirb.org/) are officially supported. Instrumenting Hanami applications requires some manual setup. Follow the installation steps in AppSignal, starting by clicking 'Add app' on the [accounts screen](https://appsignal.com/accounts).

<Note>
  Is your application using a combination of Rails, Grape, Hanami, Padrino or Sinatra? Follow our guide for [instrumenting multiple Rack applications](/ruby/integrations/rack-libraries).
</Note>

<Tip>
  This page describes the integration for the Hanami framework, installed via
  the "hanami" gem. The Hanami::API framework (from the "hanami-api" gem) is not
  supported.
</Tip>

## Installation

After installing the AppSignal gem, add the AppSignal integration after requiring `hanami/boot` in the `config.ru` file.

<CodeGroup>
  ```ruby Ruby theme={null}
  # config.ru
  require "appsignal" # Add this require
  require "hanami/boot"

  # Load the Hanami integration
  Appsignal.load(:hanami)
  # Start AppSignal
  Appsignal.start

  run Hanami.app

  # For Ruby gem 3.11 and older
  require "appsignal/integrations/hanami" # Add this line
  ```
</CodeGroup>

## Exception handling

Hanami doesn't have any exception handling by default. The web server (like Puma or Unicorn) will show a basic "internal server error" page if an error occurs in the app. These unhandled exceptions will be reported to AppSignal automatically.

The [Hanami exception handling guide](https://guides.hanamirb.org/v2.1/actions/exception-handling/) explains how to add custom exception handling to Hanami applications to render custom error pages. Handled exceptions will not be reported to AppSignal automatically.

We recommend adding the following code to the application's base Action class found in `app/action.rb` to add exception handling for `StandardError`. This way, adding exception handling to every action class is unnecessary.

In the `handle_standard_error` method, configured by `handle_exception`, call the `Appsignal.report_error` helper to report the exception to AppSignal and not miss any errors reported by your app. (Use the `Appsignal.set_error` helper when using Ruby gem version 3 or older.)

<CodeGroup>
  ```ruby Ruby theme={null}
  # app/action.rb
  # auto_register: false
  # frozen_string_literal: true

  require "hanami/action"

  module MyHanamiApp
    class Action < Hanami::Action
      handle_exception StandardError => :handle_standard_error

      private

      def handle_standard_error(request, response, exception)
        # Report the error to AppSignal
        Appsignal.report_error(exception)

        # Render custom error page
        response.status = 500
        response.body = "Sorry, something went wrong handling your request"
      end
    end
  end
  ```
</CodeGroup>

After you add the `Appsignal.report_error` method to the Hanami exceptions you want to report, AppSignal will report these errors whenever they occur.
