Hackathon Starter Sinatra

A powerful, full-featured, and simple framework designed for use at Startup Weekend and hackathon style events.

View On GitHub ยป


profile pic

Hackathon Starter Sinatra is brought to you by @qrohlf.





Hackathon Starter Sinatra

This project is a minimalist starter framework intended to be used for small projects when speed of development is a priority. It was created to be used at "Startup Weekend" style events, where a significant portion of your development team may not have experience with Ruby or Rails - and where development time is measured in hours rather than days. It is licensed under the MIT License.

The project focuses on the following goals:

  • produce a framework optimized for fast development with a minimal learning curve
  • produce a set of tutorials for "how to do X" that can be followed by programmers with minimal Ruby experience


To run this project locally, you will need a Unix environment like Linux or OSX with the following tools installed:

Additionally, if you want to customize stylesheets, you will need a LESS compiler. Some good LESS compiler GUIs are CodeKit, LiveReload or SimpLess, or you can use the official node.js package via the command line.


  1. download the project

    git clone git@github.com:qrohlf/hackathon-starter-sinatra.git
    cd hackathon-starter-sinatra
  2. install dependencies

    bundle install --without production
  3. setup the environment variables

    mv .env.example .env
  4. setup the database

    rake db:migrate
    rake db:seed
  5. start the development server

  6. point your web browser to to see the app in action.


How do I...

Install Ruby

There are lots of different ways to install Ruby or update your Ruby version. Most linux distributions include a ruby package in their built-in repositories; however it is unlikely that this package is kept up-to-date with the latest version of Ruby. Most Ruby developers use a seperate tool like RVM or rbenv to manage their Ruby versions.

My personal preference is to use rbenv with the ruby-build and rbenv-gem-rehash plugins to install and manage Ruby versions. I'll show you how to install and use those tools here.


If you're on OSX, you can install all three of these things with Homebrew (and if you don't have Homebrew yet you should go install that now).

brew install rbenv ruby-build rbenv-gem-rehash
echo 'if which rbenv > /dev/null; then eval "$(rbenv init -)"; fi' >> ~/.bash_profile


If you're on Linux, your installation will look a bit different. Follow the GitHub checkout instructions on the rbenv readme to install rbenv. Make sure to pay attention to Ubuntu and Zsh-specific notes for steps 2 and 3 if you're installing on Ubuntu or use Zsh.

Once you've installed rbenv, clone the ruby-build and rbenv-gem-rehash repositories to finish the install:

git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build
git clone https://github.com/sstephenson/rbenv-gem-rehash.git ~/.rbenv/plugins/rbenv-gem-rehash

Installing & Using a New Ruby Version

Once you've got rbenv installed, you can install a new Ruby version with a single command:

rbenv install 2.1.1 #install Ruby 2.1.1

note that you can see a list of all the available Ruby versions by running rbenv install --list

You can then set your system to use the new Ruby version by default with

rbenv global 2.1.1

Or specify your ruby version in a specific directory with

cd hackathon-starter-sinatra
rbenv local 2.1.1

When using a new Ruby version for the first time, you'll probably want to install Bundler for that Ruby version:

gem install bundler

Hackathon Starter Sinatra requires you to use Ruby 2.1.1 (it doesn't matter whether you use the local or global method to set this).

Add a Model

If you're not familiar with ActiveRecord and ActiveRecord database migrations, follow this guide to create a new model for your application (replace 'example' with the name of your model, making sure to adjust for pluralization and capitalization).

First, create the database table where the model's data will be stored:

rake db:create_migration NAME=create_examples

Note that "examples" is plural. In ActiveRecord, the convention is that database table names are expected to be plural, while class names are singular. For more on this, see here.

Now look in your db/migrate directory. There should be a new file with your migration there. (It will be named something like 20140223171803_create_examples.rb). Open it and add your model details (documentation on how to write ActiveRecord migrations is available here).

My database migration looks like this:

class CreateExamples < ActiveRecord::Migration
  def change
    create_table :examples do |t|
        t.string :name
        t.text :description


Now you need to create your model class. Create a new file in models/ called Example.rb (note that the class name is singular and captialized). Open it and declare a subclass of ActiveRecord::Base like so:

class Example < ActiveRecord::Base

That's all the code you need. (For documentation on some fancier things you can do with ActiveRecord like validations and associations, see this guide).

Now, open a terminal and run your database migration:

rake db:migrate

This will create a table in your database called examples with the columns name, description, created_at, and updated_at . It will also update db/schema.rb with your app's updated database schema.

You can now create, read, update, and delete instances of your new model within your app. For example,

Example.create(name: 'foo', description: 'bar')

will create a new Example class and add it to the examples database.

Process Payments

This project provides an easy and robust way to securely process payments through integration with Stripe Checkout. To use Stripe for payment processing, you'll need an account (sign up here) and a set of API keys.

To get your stripe API keys, head over to the API keys section of your account settings (https://manage.stripe.com/account/apikeys) and copy the secret and publishable keys into the STRIPE_KEY_SECRET and STRIPE_KEY_PUBLIC of your .env file. I suggest copying the testing keys first so that you can make sure everything is working properly, then switch to the development keys when you're ready to deploy.

Your .env file should have something like this:

# Stripe secret key for server-side use

# Stripe publishable key for client-side use

(these are not actual API keys)

Next, you'll want to look at the checkout_button helper provided in app.rb. You can pass this helper an amount (in cents) and an options hash and it will output a fully-functional Stripe checkout button. The following option keys are supported (all values should be strings):

key value
:name What the charge is for
:description Additional details about the charge
:image URL for a 128x128 image to display for the charge
:item A url-safe string to pass to the charge callback

A sample call to the checkout_button helper might look like this:

checkout_button 500, {name: 'Example Charge Name', description: 'Pretty slick, eh?', item: 'example_charge'}

This creates a basic charge button for a $5 fee. When the user completes checkout with Stripe, a POST request will be issued to /charge/example_charge with a stripeToken parameter that can be used to charge the customer's card. The customer's card will not be charged until you explicity do so on the server.

Here is an example implementation of how to actually process the charge in the charge callback (taken straight from app.rb):

# process a charge for something
# see https://stripe.com/docs/tutorials/charges for details
post '/charge/:item' do 
    # Get the credit card details submitted by the form
    token = params[:stripeToken]

    # The cost of your item should probably be stored in your model 
    # or something. Everything is specified in cents
    charge_amounts = {'example_charge' => 500, 'something_else' => 200}; 

    # Create the charge on Stripe's servers - this will charge the user's card
        charge = Stripe::Charge.create(
            :amount => charge_amounts[params[:item]], # amount in cents. 
            :currency => "usd",
            :card => token,
            :description => "description for this charge" # this shows up in receipts
        title 'Payment Complete'
    rescue Stripe::CardError => e
        title 'Card Declined'
        flash.now[:warning] = 'Your card was declined'
        # The card has been declined
        puts "CardError"
    rescue Stripe::InvalidRequestError => e
        title 'Invalid Request'
        flash.now[:warning] = 'Something went wrong with the transaction. Did you hit refresh? Don\'t do that.'
    rescue => e
        puts e

    haml :charge

For documentation on Stripe's Ruby API, see here. Also, make sure to update your environment variables on the server when you deploy, since your .env file should not be checked in to git.


Why Sinatra and not Rails?

Rails is a great tool for speeding up development - if your whole team knows Rails. Otherwise, Sinatra is better.

For most hackathon-style micro applications, the full Rails framework introduces too much friction to the development process. It's got a deeply nested directory structure, lots of distracting boilerplate files, and too much implicit "magic" that can also trip up team members. Sinatra with ActiveRecord gives you the convenience of a Rails project with a flatter structure, less boilerplate to wade through, and more explicit code that is easier for people without Rails experience to follow.

Why no social logins?

Social logins are convenient, but can alienate privacy-minded users and require additional logic to handle the case when a user attempts to log in with multiple services. For the sake of simplicity, this project has opted to use a traditional email/password login system.

If your app needs social permissions, check out the excellent and well-documented OmniAuth project, which includes implementation examples for Sinatra.

Why no tests?

This is for a hackathon. TDD is great for longer-term projects, but it's unnecessary overhead when time is of the essence and bugs aren't a huge deal.