Sinatra: the restart-bound dev loop and the three-gem install
Classy web-development dressed in a DSL (official / canonical repo)
At a glance
- What is it?
- A reading of the sinatra/sinatra repository and the README that doubles as its manual. It covers the three-gem install line, the restart requirement that shapes daily work, first-match route ordering, four ways of reading one parameter, the breadth of the template engine list, and what a repository with no GitHub releases asks you to read instead.
- Who is it for?
- Sinatra suits small Ruby web apps and one-off services where a route is a block and nothing sits between the file and the response, and it suits teams willing to restart the server on every save or to add rerun or rack-unreloader themselves. It does not suit work that needs hot reloading out of the box, sessions that work without a secret and a middleware decision, or version tracking through release pages.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 117 days ago.
- What is it written in?
- Mainly Ruby, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on November 13, 2026, and from our analysis. They are not legal advice.
Star history
- sinatra/sinatra12,451 ★ · -3
| Repository | 2026-09-22 | 2026-11-13 |
|---|---|---|
| sinatra/sinatra | 12.5k | 12.5k |
-3 Stars in the last 52 days, measured from the daily GitHub snapshot. Compare with other projects
Editorial analysis
gem install sinatra rackup puma is three gems, not one
The smallest Sinatra app in the README is four lines long, and the install that feeds it names three gems:
gem install sinatra rackup pumaThe app itself is then run as an ordinary Ruby script:
ruby myapp.rband it answers at http://localhost:4567. Two things about that sequence deserve a second look. First, the gem list is not simply sinatra; rackup and puma are named alongside it, and the quick start does not say which piece each one contributes. Second, 4567 is the address that comes from running the file directly, which makes it both the thing to check when a browser shows nothing and the value you will be looking for later, since it is the only endpoint the quick start names.
The code you changed will not take effect until you restart the server
The README puts that constraint immediately after the hello world, in plain words: the code you changed will not take effect until you restart the server, and you should restart the server every time you change, or use a code reloader like rerun or rack-unreloader. There is no automatic reload in the documented path. That one sentence defines the daily loop of a Sinatra app: edit the file, stop the foreground process, run ruby myapp.rb again, reload the browser. The two reloader projects are offered as outside tools, and neither appears in the install line, so they are a decision you make rather than a default you get. What you give up is the ability to leave a server running and save a file, and on a large app that is repeated work at every save rather than a keystroke.
Routes are matched in definition order, so the first pattern wins
A route in Sinatra is an HTTP method paired with a URL-matching pattern and a block, and the order of definition is part of the behavior: routes are matched in the order they are defined, and the first route that matches the request is invoked. That single rule accounts for most routing confusion. A splat pattern declared above a specific one takes the request before the specific pattern is ever consulted, and a regular expression route declared early shadows the literal route underneath it. There is no specificity ranking to fall back on, no longest-match rule. The trailing slash is treated just as literally:
get '/foo' do
# Does not match "GET /foo/"
endSo /foo and /foo/ are two different routes, and any link, form post, or redirect that ends up with the extra slash reaches a route that does not exist until you write it.
One pattern shape hands you its match in four different forms
The manual shows the same idea of a captured value expressed four ways. Named parameters arrive in the params hash, or as block parameters when you prefer a local name. Splats collect into params['splat'] as an array, and the example shows exactly where the split lands:
get '/say/*/to/*' do
# matches /say/hello/to/world
params['splat'] # => ["hello", "world"]
end
get '/download/*.*' do
# matches /download/path/to/file.xml
params['splat'] # => ["path/to/file", "xml"]
endRegular expressions put their matches in params['captures'], optional segments use a trailing question mark as in /posts/:format?, and query strings attach to any route without appearing in the pattern at all. Since params is one flat hash regardless of origin, a path segment and a query key of the same name occupy the same slot, and a filename holding more than one dot changes what the splat example above hands you.
The template engine list is fourteen names wide and none is installed
The widest surface in the documentation is buried in the table of contents: template engines. Haml, Erb, Builder, Nokogiri, Sass, Scss, Liquid, Markdown, RDoc, AsciiDoc, Markaby, RABL, Slim, and Yajl are all named, with subsections around them for inline templates, named templates, associating file extensions with templates, adding your own template engine, and using custom logic for template lookup. Set against that breadth, the install line names three gems and not one of them is a template engine. When an engine becomes available, and what a missing one raises, is not answered by the quick start, so a Haml or Slim layout depends on a gem you have to think about yourself.
rack-protection and sinatra-contrib live beside lib/ in the same tree
Two directories sit next to lib/ at the top of the repository, and each is a distinct body of work inside one tree. rack-protection/ backs the section on configuring attack protection, while sinatra-contrib/ holds the extra library code that the main gem does not. The session story is split across three named subsections, Session Secret Security, Session Config, and Choosing Your Own Session Middleware, which together say something plain: a session store is something you choose rather than something that arrives switched on. The install line adds no session store to the gems it names. SECURITY.md sits at the top level of the repository.
No GitHub releases, so the version story lives in the repository
The repository has no GitHub releases. What it carries instead is a set of files: VERSION, CHANGELOG.md, RELEASING.md, MAINTENANCE.md, CONTRIBUTING.md, SECURITY.md, AUTHORS.md, and CODE_OF_CONDUCT.md, alongside a Rakefile, a Gemfile, sinatra.gemspec, .rubocop.yml, and .yardopts. So the answer to what changed in a version is read out of the tree rather than off a release page, and anything that tracks Sinatra by watching GitHub releases is watching a channel this repository does not publish to. The default branch main was last pushed on 2026-07-20, although no GitHub release is offered for download. Under examples/ sit four runnable files, simple.rb, chat.rb, lifecycle_events.rb, and stream.ru, the last a Rack file rather than a Ruby script, which lines up with the config.ru and streaming parts of the manual.
Editorial conclusion
Sinatra suits small Ruby web apps and one-off services where a route is a block and nothing sits between the file and the response, and it suits teams willing to restart the server on every save or to add rerun or rack-unreloader themselves. It does not suit work that needs hot reloading out of the box, sessions that work without a secret and a middleware decision, or version tracking through release pages. Before adopting it, confirm four things: which three gems you are actually installing, whether your front-end loop can absorb a restart, whether a routing order or a trailing slash in your URL plan depends on first-match semantics, and which template engine you need, since the install line names none.
Frequently asked questions
how to install sinatra
Run `gem install sinatra rackup puma`. Sinatra is distributed as a Ruby gem under the MIT license, and the quick start asks for rackup and puma alongside the sinatra gem itself.
how to use sinatra
Write a Ruby file that requires sinatra, define get and post blocks as routes, run `ruby myapp.rb`, and open http://localhost:4567. Remember that code changes take effect only after you restart the server.
what is sinatra
Sinatra is a DSL for quickly creating web applications in Ruby with minimal effort, where a route is an HTTP method paired with a URL-matching pattern and a block. The canonical repository is sinatra/sinatra and the project homepage is sinatrarb.com.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/sinatra-sinatra)Star history chart for your README
[](https://hysenlabs.com/projects/sinatra-sinatra)Was this useful?