require 'bundler/setup'

env = ENV.fetch('RACK_ENV', 'production')

Bundler.require(:default, env)

require 'hanami/router'
require 'hanami/controller'
require 'hanami/validations'
require 'haml'

module Dolly
  module Web
    module Controllers
      module Backups
        module Action
          def self.included(base)
            base.send(:include, Hanami::Action)
          end

          def render
            source = ::File.read(__dir__ + '/app/views' + self.class.to_s.gsub('Dolly::Web::Controllers', '').downcase.gsub('::', '/') + '.html.haml')
            self.body = Haml::Engine.new(source).render(binding)
          end
        end

        class Index
          include Action

          def call(params)
            @backups = Repos::Backups.all.map { |rec| Models::Backup.new(rec) }
            render
          end
        end

        class Show
          include Action

          params do
            required(:id).filled(:str?)
          end

          def call(params)
            halt 400 unless params.valid?

            @backup = { id: params[:id] }

            render
          end
        end
      end
    end

    App = Hanami::Router.new do
      get '/', to: Controllers::Backups::Index
      get '/backups', to: Controllers::Backups::Index
      get '/backups/:id', to: Controllers::Backups::Show
    end
  end
end

Dolly::App is a rack application and can be placed in a config.ru, such as run Dolly::Web::App

The repository and model was just a placeholder:

module Dolly

  module Web
    module Repos
      class Backups
        def self.all
          [{ id: 1, name: 'Foo' }, { id: 2, name: 'Bar' }]
        end

        def self.find(id)
          all.find { |rec| rec[:id] == id }
        end
      end
    end

    module Models
      class Backup < OpenStruct
      end
    end
  end
end