Est. 2006 Intermediate

Camping (Ruby framework)

Camping is why the lucky stiff's miniature Ruby web framework - a complete MVC stack that fits in a single source file of a few kilobytes, small enough to read in one sitting and strange enough to have changed how Ruby thought about web frameworks.

Created by why the lucky stiff (_why), with later maintenance by Magnus Holm, Karl Oscar Weber and the Camping community

Paradigm Object-oriented Ruby, arranged as a Model-View-Controller web framework. Heavy use of metaprogramming, module reopening and DSL construction - controllers are classes generated by a route-building method, and views are Ruby methods that emit HTML
Typing Dynamic, strong and duck-typed - inherited wholesale from Ruby, the host language
First Appeared 2006 (version 1.0 checked in January 17, 2006 and announced on RedHanded on January 18, 2006)
Latest Version 3.2.6, released August 9, 2024

Camping is a Ruby web framework that is famous for a single property: it is tiny. The framework’s entire implementation lives in one file, and the project enforces the constraint with a test in its Rakefile that fails the build if that file grows past a byte limit. For most of Camping’s life that limit was 4,096 bytes, which is where the original tagline - the 4k pocket full-of-gags web microframework - came from. It has since been raised twice, and the repository now describes itself as the 5k pocket full-of-gags web microframework.

Inside those few kilobytes is not a toy. Camping is a genuine Model-View-Controller framework with routing, controllers, views, sessions, helpers, a server command and a project layout. The premise, stated in its own README, is that you should be able to keep a complete fledgling web application in a single file like an old CGI script, but organise it the way Rails would - and then split the models, views and controllers into separate files later, if the thing you built turns out to matter.

It was written by why the lucky stiff, and it shows. Camping is one of the small number of software projects that is simultaneously a working tool, a joke, and an argument about what programming should feel like.

History and Origins

In January 2006, Ruby on Rails was roughly two years old and had made Ruby famous. _why - the pseudonymous author of Why’s (Poignant) Guide to Ruby, Hpricot, Markaby, and later Shoes - was not much of a Rails user. On January 18, 2006 he posted Camping is a Microframework to his blog RedHanded; the project’s CHANGELOG dates the 1.0 checkin to the day before.

The announcement post is characteristic. Rather than a feature list, it opened with the framework’s source printed out as a dense mural of Ruby, the whole thing visible at once. In the comments, asked whether Camping could handle e-commerce, _why suggested Rails - then reversed himself on hearing the operation in question was a small mail-order outfit: now you’re talking!! That exchange is Camping’s scope statement. It was for the small thing you would otherwise not have built at all.

Development was fast through 2006. Camping.goes - the method that generates a complete application namespace under a name of your choosing - arrived in 1.2 that same January. Sessions, WEBrick and Mongrel handlers came in 1.4 in April. Version 1.5, in October 2006, made the ActiveRecord dependency lazy, loading it only if an application actually referenced a model. A 1.6 was written and never released.

Then, in August 2009, _why deleted his accounts and websites and disappeared from public view. Camping was one of several widely-used libraries suddenly without an author. Unlike some of his other work, it survived: the code was MIT-licensed, mirrors of the source existed, and a group of Ruby programmers - Magnus Holm foremost among them - moved it to GitHub and kept going. The gemspec still lists why the lucky stiff as the author, and always has.

Design Philosophy

The size limit is the design. Most frameworks talk about minimalism; Camping made it a build failure. The Rakefile’s check:size task compares lib/camping.rb against a hard constant and errors out if it is over. A companion check:lines task rejects overly long lines, so the constraint cannot be met by simply deleting newlines. Every feature proposal has therefore had to answer a question no other framework asks its contributors: what are you willing to remove to fit this in? The 2.3 release notes record the outcome bluntly - “Increase camping test limit to 5120 bytes. We needed just a bit more space.”

Two copies of the truth. Because the compressed source is close to unreadable, Camping ships camping-unabridged.rb - the same framework, fully commented and documented, at around 34 KB - alongside the roughly 5 KB camping.rb that actually gets loaded. A Rake task checks that the two remain equivalent. It is an unusual and rather elegant answer to the obvious objection that golfed code cannot be maintained.

One file, then more files. Camping never claimed a single file was the end state. The README frames it as a starting point: begin in one file, move things out as the application grows. Rails compatibility of concepts was deliberate, so that graduating from Camping to Rails involved rearranging code rather than relearning the shape of a web application.

Whimsy is load-bearing. The naming is not incidental decoration. Applications are camps; plugins are gear, added with the gear method; the startup directory is kindling; the logging wrapper is Firewatch; the exception handler is CampGuide. This is the same sensibility that produced Why’s (Poignant) Guide to Ruby, and it is a substantial part of why the project attracted maintainers willing to keep it alive for twenty years without a commercial sponsor.

Key Features

An application in one file

The canonical Camping skeleton, from the project’s own README:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
require 'camping'

Camping.goes :Blog

module Blog::Models
  class Post < Base; belongs_to :user; end
  class Comment < Base; belongs_to :user; end
  class User < Base; end
end

module Blog::Controllers
  class Index
    def get
      @posts = Post.find :all
      render :index
    end
  end
end

module Blog::Views
  def layout
    html do
      head { title "My Blog" }
      body do
        h1 "My Blog"
        self << yield
      end
    end
  end

  def index
    @posts.each do |post|
      h1 post.title
    end
  end
end

Camping.goes :Blog is the hinge. It creates the Blog module and populates it with fresh copies of Models, Controllers, Views and the framework’s base classes, so that several independent Camping applications can coexist in one Ruby process without colliding.

Routing by class name, or by pattern

By default a controller’s route is derived from its class name - Index handles /, Info handles /info - and HTTP verbs map to instance methods, so def get handles GET and def post handles POST. For anything more structured, the R method builds a controller class bound to explicit patterns:

1
2
3
4
5
6
7
8
module Blog::Controllers
  class Post < R '/post/(\d+)'
    def get(id)
      @post = Blog::Models::Post.find(id)
      render :view
    end
  end
end

Captured groups arrive as method arguments. The R helper works in reverse too - given a controller and arguments, it generates the URL - so links in views stay in sync with routes. Camping 3.x reportedly added Sinatra-style routing helpers alongside this original scheme.

Views written in Ruby

Camping’s views are Ruby methods, not templates. h1 post.title emits an <h1>; nesting is done with blocks. This comes from Markaby (“markup as Ruby”), another _why project, which Camping carries as the mab gem. It is compact to the point of being startling the first time you see it, and it means views are ordinary Ruby with ordinary Ruby control flow.

Since 2.1, this is no longer mandatory: Tilt integration lets views be written in ERB, Haml or any other Tilt-supported engine, with Markaby-style methods remaining the default.

Persistence, unbundled

Camping 1.x expected ActiveRecord, though from 1.5 it only loaded it if you referenced Models::Base. Camping 3.0 removed the ActiveRecord dependency entirely in favour of a looser arrangement in which you bring your own database layer; 3.2.6 added a Model::Base stub for use with Sequel. For a framework this size, staying out of the persistence business is the only tenable position.

Evolution

VersionDateWhat changed
1.0January 2006Initial release; announced on RedHanded
1.2January 23, 2006Camping.goes, file uploads, the R route helper
1.4April 11, 2006Sessions, WEBrick and Mongrel handlers, URL helper
1.5October 3, 2006ActiveRecord made optional/autoloaded; console mode; FastCGI directory server
1.6never releasedMarkaby made optional; r404/r500/r501 error hooks
2.0April 9, 2010Rebuilt on Rack; middleware support; cookie sessions
2.1August 19, 2010Tilt templates; Camping.options; Ruby 1.9 support
2.1.532March 21, 2013Last release before a nine-year gap (2013-2022)
2.2never releasedActiveRecord 6.1 migrations, deprecation cleanup
2.3July 28, 2022gear plugin system; multiple apps restored; size limit raised to 5,120 bytes
3.0March 2023 (gem April 18, 2023)Modern Rack/Rackup; ActiveRecord removed; camping new generator; KDL config
3.1June 22, 2023Zeitwerk autoloading; reloader rewritten for nested app directories
3.2.6August 9, 2024Falcon as default server; logging gear; current release

The shape of that table is the story. Camping had an intense first year under its author, a productive community rework in 2010, then went effectively dormant from 2013 to 2022 - a stretch long enough that most listings still describe it as an abandoned curiosity. The 2022-2024 revival, driven largely by Karl Oscar Weber with Magnus Holm’s earlier work as the base, brought it onto modern Rack, modern Ruby (3.2.6 requires Ruby 3.1.2 or newer) and a modern project layout, without abandoning the single-file mode or the byte limit that defines it.

Running Camping Today

There is no official Docker image, which is why the Docker section of this page is empty; Camping is distributed as a gem.

1
2
3
4
5
6
7
8
9
gem install camping

# Generate a new camp (the name must be CamelCased)
camping new Donuts
cd donuts
bundle install

# Run it in development
bundle exec camping -e development

The 3.x generator produces a conventional project directory rather than a single script, and the current release bundles Falcon as its default server. Running a classic single-file Camping app - the examples/blog.rb in the repository, for instance - still works, which is a reasonable claim for a framework whose file format has survived three major versions.

Anyone running an application written against Camping 1.x should expect real work to upgrade: 2.0 moved the whole framework onto Rack and changed the session model, and 3.0 removed the ActiveRecord assumption that most 1.x applications were built on.

Current Relevance

Camping is a niche framework and always was. Cumulative RubyGems downloads across all versions are approximately 138,000 as of July 2026 - a rounding error next to Rails or Sinatra - and the GitHub repository sits at under a thousand stars. Nobody is building a startup on it.

What it has instead is unusual persistence. Twenty years after the first release, and seventeen years after its author walked away, Camping is still getting releases, still has maintainers, still has a book in its repository and a chat channel with people in it. Very few frameworks of any size survive the loss of their creator; almost none survive it by two decades while remaining recognisably the same thing.

Its practical audience today is roughly what it was in 2006: people who want a small web application - an internal tool, a wiki, a webhook receiver, a personal site - without the ceremony of a full framework, and who enjoy the fact that they could read the entire framework over a coffee if they wanted to.

Why It Matters

It made the microframework a category in Ruby. Before Camping, the Ruby web conversation was Rails and a handful of larger alternatives. Camping demonstrated that a real MVC stack could fit in a file, and Sinatra is widely reported to have begun as an attempt to take Camping further without becoming Rails. Sinatra in turn became a reference point for small route-block web frameworks well beyond Ruby, though the lines of influence between Sinatra and later frameworks in other languages are more often asserted than documented. Camping is the ancestor most of them have never heard of.

It is a rare readable framework. Web frameworks are normally opaque to their users - hundreds of files, layers of indirection, magic you take on trust. Camping’s dual source, with the documented 34 KB version and the compressed 5 KB version checked against each other, means the entire request lifecycle is available to be read straight through. For anyone who has wondered what a framework actually does between the socket and the controller method, it is one of the best available texts.

It is evidence that constraints produce design. The byte limit forced Camping’s contributors to make an explicit tradeoff on every single feature for two decades. The result is a framework with almost no speculative generality in it, and a set of ideas - route generation that works in both directions, applications as namespaces you can mount several of, views as plain methods - that are sharper than they would have been with unlimited room.

And it is a piece of Ruby’s cultural history. Camping belongs to a period when Ruby’s most influential figure was an anonymous author publishing cartoon-illustrated books and libraries named after camping gear, and when the language’s identity was built as much on delight as on productivity. The framework outlived its author’s public existence because the people who found it charming refused to let it die. That is not the usual reason software survives, and it is worth noticing that it worked.

Sources

Timeline

2006
why the lucky stiff releases Camping 1.0 - the CHANGELOG dates the initial checkin to January 17, 2006, and the announcement post Camping is a Microframework appears on his blog RedHanded on January 18, 2006. The 1.0 gem is published to RubyGems on January 18, 2006, the same day. The pitch is a complete Model-View-Controller web application in a single file, in a framework whose own source is a few kilobytes
2006
A rapid run of releases follows through the spring: 1.2 (January 23) introduces Camping.goes, the method that stamps out a fresh application namespace, along with file uploads and the R route helper; 1.3 (January 28) adds the bin/camping launcher; 1.4 (April 11) adds sessions plus WEBrick and Mongrel handlers
2006
Version 1.5 ships October 3, 2006, dropping the hard ActiveRecord requirement in favour of autoloading it only when an application refers to Models::Base, and adding a console mode and a FastCGI server capable of serving a whole directory of applications
2009
why the lucky stiff withdraws from the internet in August 2009, taking his sites and accounts offline. Camping - like Markaby, Hpricot, Shoes and the rest of his catalogue - is left in the hands of whoever wanted to pick it up. Version 1.5.180 is published on August 20, 2009, and the project moves to community maintenance on GitHub
2010
Camping 2.0 is released April 9, 2010, the first major rework by the community maintainers. Camping is rebuilt on Rack: every application now responds to #call, Rack middleware can be inserted with Camping.use, session state becomes an alias for the Rack session, and the ActiveRecord-backed session store is replaced by session cookies
2010
Camping 2.1 arrives on August 19, 2010 - Whyday, the community's annual commemoration of _why's disappearance. It adds Tilt integration so views can be written in ERB, Haml or anything else Tilt supports rather than only Markaby, rebuilds Camping::Server on Rack::Server, and improves Ruby 1.9 support
2013
Version 2.1.532 is published March 21, 2013 after a trickle of point releases (2.1.467 in 2011, 2.1.523 in 2012, 2.1.531 in February 2013). It is the last Camping release for nine years; the project goes quiet, and a planned 2.2 is written but never shipped
2022
Camping 2.3 is released July 28, 2022, ending the dormant period. It restores support for mounting multiple applications, adds a plugin system through the gear method and a url_prefix mounting option - and raises the framework's self-imposed source size limit to 5,120 bytes, having run out of room
2023
Camping 3.0 ships in 2023 (dated March 18, 2023 in the CHANGELOG, with the 3.0.0 gem published April 18). It is the largest break in the project's history: modern Rack and Rackup underneath, ActiveRecord removed as a required dependency, a camping new project generator, KDL-based configuration files and a set of Camping Tools utilities
2023
The 3.1 series (June 2023) rewrites the reloader around nested app directories and adopts Zeitwerk for autoloading, moving Camping from single-file scripts toward a conventional multi-file project layout while keeping the single-file mode intact
2024
The 3.2 series lands through June and August 2024, adding default logging middleware, integration tests and the Firewatch logging gear, and making Falcon the default bundled server. Version 3.2.6, published August 9, 2024, is the most recent release on RubyGems as of July 2026

Notable Uses & Legacy

Sinatra

Sinatra, begun by Blake Mizerany around 2006 and first released publicly in September 2007, is widely reported to have been inspired by Camping - the idea being to take Camping's small-framework approach a little further without growing as large as Rails. Sinatra went on to become the default small Ruby web framework, which makes Camping's most consequential descendant a framework rather than an application.

Junebug

A minimalist wiki built on Camping with a SQLite backend, packaged as the junebug-wiki gem. Running it produced a self-contained folder holding the database, uploaded images and the start/stop script - the clearest demonstration of Camping's pitch that a whole web application can be something you copy around like a file.

Cheat (cheat.errtheblog.com)

Chris Wanstrath's command-line cheat-sheet service, announced on Err the Blog in 2006, was originally backed by a small Camping wiki with a YAML store; the cheat gem simply fetched sheets from it. The service is no longer online, but its Camping era is a well-documented example of a real, publicly used service on the framework.

Reststop

A community library adding RESTful resource routing on top of Camping controllers, distributed as its own gem. It is representative of the small ecosystem of add-ons and meta-packages that reportedly grew around a framework deliberately too small to include such features itself.

The Camping Book and the framework's own source

Camping's distribution ships two copies of itself: camping-unabridged.rb, a fully documented roughly 34 KB version, and camping.rb, the compressed roughly 5 KB mural generated from it, with a Rake task that verifies the two are semantically equal. The pair, together with The Camping Book chapters in the repository, has been used for years as a teaching text for reading a complete web framework end to end.

Language Influence

Influenced By

Influenced

Sinatra

Running Today

Run examples using the official Docker image:

docker pull
Last updated: