- Define routes as `get '/users/:id' do; user = User.find(params[:id]); json user; end` — use `params[:name]` for path params and `params[:query]` for query strings.
- Use `halt 404, json({ error: 'Not found' })` to short-circuit and send an HTTP error response immediately.
- Set `content_type :json` at the top of `before do` or per route when returning JSON.
- Use Sinatra modular style (`class App < Sinatra::Base`) for testable, mountable apps — classic style is for single-file scripts only.
- Enable `use Rack::Session::Cookie, secret: ENV['SESSION_SECRET']` for session management — never hardcode the secret.
- Define typed routes with `get '/posts/:id' do; post = Post.find_by(id: params[:id].to_i); halt 404, json({ error: 'not found' }) unless post; json post; end` — always validate and cast `params` before use.
- Use `before do` for shared setup (auth, content type) and `after do` for response cleanup: `before do; content_type :json; @current_user = authenticate_request!; end`.
- Structure non-trivial apps with `Sinatra::Base` subclasses: `class ApiApp < Sinatra::Base; register Sinatra::Contrib; ... end` — mount in `config.ru` with `run ApiApp`.
- Handle errors globally: `error 404 do; json({ error: 'not found' }); end; error 500 do; json({ error: 'internal error' }); end`.
- Parse JSON request bodies with `request.body.rewind; JSON.parse(request.body.read)` inside POST/PATCH/PUT routes — wrap in a `before` filter for routes that always consume JSON.
- Use `halt 422, json({ errors: errors })` for validation failures — never return a 200 with an error payload.