Sinatra
Sinatra is a minimal Rack-based DSL for building web apps — no forced structure, no ORM, no asset pipeline. Good for small apps, APIs, or when Rails would be overkill. Current major version (4.x) requires Ruby 3.0+ and Rack 3.
The classic style (single file)
require "sinatra"
get "/" do
"Hello, world"
end
get "/posts/:id" do
@post = Post.find(params[:id])
erb :show
end
post "/posts" do
Post.create(params[:post])
redirect "/posts"
end
Run with ruby app.rb (spins up a dev server on port 4567) or via rackup.
The modular style (recommended beyond a toy app)
require "sinatra/base"
class App < Sinatra::Base
set :views, File.join(__dir__, "views")
get "/" do
"Hello, world"
end
end
# config.ru
require_relative "app"
run App
Modular apps are just Rack apps — you can mount several together, and they don’t pollute the top-level namespace the way classic style does.
Routes
- Verbs:
get,post,put,patch,delete,options. - Named params:
get "/posts/:id"→params[:id]. - Splat params:
get "/say/*/to/*"→params[:splat](array). - Route conditions:
get "/", host_name: "example.com" do ... end.
Request / response
get "/search" do
params[:q] # query string params
request.body.read # raw body
content_type :json
status 201
headers "X-Custom" => "value"
end
halt 404, "Not found"— stop processing immediately.redirect "/somewhere", 301pass— decline the current route, fall through to the next matching one.
Views
Supports ERB, Haml, Slim, Builder, and others via Tilt. Templates live in views/ by default.
get "/" do
erb :index, locals: { title: "Home" }
end
Layouts: views/layout.erb wraps templates automatically unless layout: false is passed.
Filters & settings
before do
@user = User.find_by(id: session[:user_id])
end
after do
logger.info "request completed"
end
configure :production do
set :show_exceptions, false
end
set :name, valuedefines app-wide settings (sessions,public_folder,views, etc.).enable :sessionsturns on cookie-based sessions.
Middleware
Sinatra apps are Rack apps, so standard Rack middleware just works:
use Rack::Session::Cookie, secret: ENV["SESSION_SECRET"]
use Rack::Protection
Testing
Typically rack-test + Minitest or RSpec:
require "rack/test"
class AppTest < Minitest::Test
include Rack::Test::Methods
def app = App
def test_root
get "/"
assert last_response.ok?
assert_includes last_response.body, "Hello"
end
end
When to reach for it
Good fit: small internal tools, webhooks receivers, JSON APIs, prototypes. If you find yourself building an ORM layer, a plugin system, and a background job runner on top of it, that’s usually a sign to move to Rails or Hanami instead.