Skip to content
A lightweight asset management system for Rack
Ruby Other
Find file
Pull request Compare This branch is 26 commits behind master.
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.


Pinion is a Rack application that serves assets, possibly transforming them in the process. It is generally useful for serving Javascript and CSS, and things that compile to Javascript and CSS such as Coffeescript and Sass.


There are a lot of tools that accomplish very similar things in this space. Pinion is meant to be a very simple and lightweight solution. It is driven by these core goals (bold goals are implemented):

  • Simple configuration and usage.
  • No added syntax to your assets (e.g. no //= require my_other_asset)
  • Recompile all compiled assets when they change (or dependencies change) in development and set mtimes
  • Recompile asynchronously from requests (no polling allowed)
  • Compile assets one time in production


$ gem install pinion

You should add pinion to your project's Gemfile.


The easiest way to use Pinion is to map your desired asset mount point to a Pinion::Server instance in your

require "pinion"
require "your_app.rb"

MOUNT_POINT = "/assets"
pinion =
# Tell Pinion each type of conversion it should perform
pinion.convert :scss => :css # Sass and Coffeescript will just work if you have the gems installed
pinion.convert :coffee => :js # Conversion types correspond to file extensions. .coffee -> .js
pinion.convert :styl => :css do |file_contents|
  Stylus.compile file_contents # Requires the stylus gem
# Tell Pinion the paths to watch "public/javascripts" "public/scss" "public/stylus"

  # Boom
  run pinion

map "/" do
  # You should pass pinion into your app in order to use its helper methods.

In your app, you will use pinion's helper methods to construct urls:

  <title>My App</title>
  <link type="text/css" rel="stylesheet" href="<%= pinion.asset_url("/assets/style.css") %>" />
  <%# Shorthand equivalent %>
  <%= pinion.css_url("style.css") %>

Production usage

In production, you may wish to concatenate and minify your assets before you serve them. This is done through using asset bundles. Pinion provides a predefined bundle type, :concatenate_and_uglify_js, for your convenience.

You can bundle files by putting this in your app:

<%= @pinion.js_bundle(:concatenate_and_uglify_js, "main-bundle",
    ) %>

In development, the individual <script> tags for each asset will be emitted; in production, a single asset (main-bundle.js) will be produced.

The :concatenate_and_uglify_js bundle type simply concatenates JS files and runs them through Uglifier. No default CSS bundle type is provided (but the built-in Sass conversion type emits minified code in production, and typically you'll let Sass/Less/Stylus handle concatenation for you).

You can define your own bundle types and their behavior if you like:

# The block is passed an array of `Pinion::Asset`s; it should return the content of the bundled files.
Pinion::BundleType.create(:concatenate_js_only) do |assets|
  # Demo code only; you need to be a bit more careful in reality. See the definition of
  # :concatenate_and_uglify_js for hints."\n")

Note that in production mode, asset URLs will have the md5sum of the asset inserted into them:

<link type="text/css" rel="stylesheet" href="/assets/style-698f462d2f43890597ae78df8286d03f.css" />
<script src="/assets/test-bundle-cd94852076ffa13c006cf575dfff9e35.js"></script>

and these assets are served with long (1-year) expiry, for good cacheability.


  • Currently, Pinion sidesteps the dependency question by invalidating its cache of each file of a particular type (say, all .scss files) when any such source file is changed.
  • The order that paths are added to the watch list is a priority order in case of conflicting assets. (For intance, if foo/bar and foo/baz are both on the watch list, and both of the files foo/bar/style.scss and foo/baz/style.scss exist, then foo/bar/style.scss will be used if a request occurs for /style.css.)

You can see an example app using Pinion and Sinatra in the example/ directory. Run bundle install in that directory to get the necessary gems, then run it:

rackup                     # Development mode
RACK_ENV=production rackup # Production mode


Pinion was written by Caleb Spare (cespare). Inspiration from sprockets.

Contributions from:


Pinion is released under the MIT License.

Something went wrong with that request. Please try again.