Getting Friends Together - A Postmortem

Shortly after graduating college I began working on a mobile app to help get friends together offline. Over the next several years I learned more than I could imagine about building apps, working on side projects, and trying to solve the problem of easily coordinating plans with friends. I'm not the only one who has tried to build such an app. A couple of the most recent attempts to solve this problem include Danny Trinh's Free, Max Stoller's Tuesday, and Google's Who's Down. These types of apps are so common that it's practically the "Stairway to Heaven" for mobile apps. Given how many people are trying to solve this problem I figured it'd be helpful to share some lessons I learned along the way.


When building an app, your solution must be 10x better than the current one. Being slightly better isn't enough to sway people away from what they're currently using.

With Flock, the existing solution was text messaging. There were numerous ways that we thought Flock was better than text messaging: 1) you could leave and join the conversations whenever you wanted (this was pre iOS 8...) 2) the focal point of the conversation was always stuck to the top of the screen 3) You could create plans with an activity, time, and location in just 3 taps and 4) it created an easy way to passively see if anyone in your network was in the area and interested in hanging out (as opposed to creating a massive group text with everyone in your network).

In our mind these were real improvements over text messaging. However, was it 10x better than the alternative of creating group messages with your friends? Probably not. Additionally, there are plenty of ways why text messaging is better than Flock. Text messaging is faster. It is also universal. 100% of your friends can be reached via SMS, however to invite a friend to hangout on Flock they need to be on the app. Most people that join Flock have very few friends already on the app.

Single Player vs Multiplayer Mode

Flock, and apps like it, are example of "network effect" apps. I like to describe these types of apps as "Multiplayer" games. The more people that are on it, the better the experience is going to be. In Flock's case, it can't just be anyone, but specifically your friends. 

The vast majority of people that download Flock do not have enough friends to make it useful. Asking people to share the app with their friends was much more challenging than we expected. People care about convenience. Downloading an app, inviting all your friends, and then friending all of not convenient. At all. 

If I were doing it all over again I would attack this problem two-fold. For one, I would eliminate the need to individually friend people within Flock. Instead, I would ask people to connect their phone contacts (and possibly FB/Twitter) and assume that anyone who you are connected with of those networks should be considered your friend.

Additionally, I'd try to make Flock more useful even if you didn't have a bunch of friends on the app. If you want to create something useful in this space for people outside of the very small tech community, you have to assume that most people are going to be playing on "single player" mode at first. For apps like Flock, this could mean blending the discovery functionality of apps like Sosh and YPlan with the coordination piece of getting friends together. 

Don't discriminate the green bubbles

I mentioned it a bit in the 10x section, but it's important enough to re-iterate: don't discriminate against non-iPhone users. In the U.S., especially the tech community, iPhones are fairly popular. However, when creating an app to make plans with friends, "popular" is not enough. You don't need to create apps with full functionality on every platform, but it's necessary to at least allow people to join events on non-iOS platforms. This could be done through a lightweight website or a smart SMS/Twilio integration. One challenge with this is that it makes it much harder to prototype quickly. However, given the polished nature of the competition (SMS and messaging apps), it seems like it's the nature of the beast.

Simple Explanation

When you work on a new project, you're constantly giving people the elevator pitch on what exactly you're doing and why it's such a good idea. For Flock, this consisted of me describing how I missed the incredible social environment of college, where you could just stick your head out your dorm room and rally a group of friends to grab dinner, go to the gym, or grab drinks at a bar. After a minute of two of me blabbering most people vaguely understood what we were trying to do. However, there was no good way for me to explain the idea in a sentence or two.

At first, it's not a huge deal if it takes a minute or two to explain. You're going to be the one explaining the idea, and the receiver is going to be family or good friends, so they'll listen to you even if they get bored after the first 10 seconds.

However, if you want a social app to expand, you can't expect that you're going to be the one explaining it to every single person that downloads the app. If it's successful, it's almost certainly going to be from word of mouth sharing. In order for this to happen, the explanation and value proposition needs to be short and sweet. 


Not being able to explain Flock concisely was a symptom of our app trying to do too many things. We wanted to cover every social activity that you may do with your friends. Lunch? Check. Working out? Check. Going to see the movies? Check. 

The more you try and do, the worst job you're going to do at each of those items. For new apps that need to be 10x better than the competition, this leads to problems. In retrospect, I'd focus on one main use case like grabbing food:

"'I'm Hungry' is an app to make sure you never eat alone. When you're hungry you tap the big green button in the middle of the screen and it sends a notification to all your friends in the area to see if they're also hungry."

Great Experience, Very Fun Space

There is no question that trying to make an app to get friends together is challenging. The competition is strong, and there are a lot of dynamics that make it hard create a good experience for early users (network effect, cross platform support, etc.). However, not only do I not regret trying to tackle this problem, but I highly recommend others to try and tackle it. 

Do I think you have a good chance of succeeding? Nope. Will there ever be an app that succeeds in this space? Maybe not. However, there are two aspects of solving this problem that I really love. 

First, it's a space that is extremely easy to relate to. A problem that you're trying to solve first and foremost for yourself. This will make it both extremely fun and also help you empathize with your users. 

Secondly, by working on a consumer facing app in a space with very well done alternatives (SMS, messaging apps, etc.), coming up with a polished and elegant solution is extremely important. Even if your idea doesn't end up working out, you'll gain a ton of valuable experience related to creating intuitive and user friendly interfaces. With the consumerization of enterprise and the heavy focus on simple and convenient interfaces, this will certainly help you with whatever you decide to work on next if your app doesn't work out.    

How to Create an Angular App Using Yeoman and Deploy It to Heroku

Step 1: Install Yeoman

Yeoman is a tool to help easily create new projects. You can use its generators to create all different types of web apps (Angular, Backbone, Ember, and many more).

Having node and npm installed on your computer is a requirement for using Yeoman. If you do not have the installed on your computer, follow these installation instructions here.

Once node and npm are installed, install Yeoman by running:

npm install -g yo

Step 2: Create an Angular App using the Yeoman Anglar Generator

Now that Yeoman is installed, you can easily create an Angular app by following the instructions below. These are taken from the yeoman angular generator repo readme, which can be found here.

Install generator-angular:  

npm install -g generator-angular

Make a new directory and cd into it:

mkdir project-name && cd project-name

Create the angular app (the app name parameter is optional): 

yo angular [app-name]

You will be asked if you want yeoman to install SASS (with Compass), Twitter Bootstrap, and include various angular modules. You can learn more about these opitons under the “Configure your generator” here. Below I do not install SASS or Bootstrap, but do include the various angular modules, so I type 'y', 'y', and then press enter.


After letting yeoman do its magic, you can run the app locally with the following command:

grunt serve

You should now see something like this on localhost:9000:


Step 3: Add a Server to the App

This step is taken primarily from Brad Barrow’s awesome tutorial, with some slight updates to make it work using the latest version of Express (a web development framework for node.js).

As Brad explains, the angular app created by Yeoman is static, so we can’t expect it to work on Heroku out of the box. In order for Heroky to be able to serve the pages for us we need to add a server to the app.

The server’s dependencies include Gzippo, Morgan, and Express.

To install these dependencies run:

npm install gzippo express morgan --save

Next, create a server file called web.js in the root directory

var gzippo = require('gzippo');
var express = require('express');
var morgan = require('morgan');
var app = express();

app.use(gzippo.staticGzip("" + __dirname + "/dist"));
app.listen(process.env.PORT || 5000);

Now that the server file has been created, we need grunt to build the /dist directory that we are serving in line 6 of our web.js file.

We can create this directory by running:

grunt build

Step 4: Add Heroku Dependencies

By default the dist that we just createdis included in the .gitignore file:


Since Heroku uses git to deploy, we need to remove `dist` from the .gitignore file. As Brad explains nicely in his tutorial:

“It’s worth noting that the dist/ directory is ignored by git by default (they assume you only want to version control the development project, not the compiled app). Since Heroku uses git to deploy, we’ll need to remove dist/ from .gitignore to make sure it gets committed.”

Note: While this gets the app up and running on Heroku, it is bad practice to version control the compiled app. I looked around but couldn’t figure out how to compile an angular app on the server on Heroku. If anyway knows of a good way to do this I’d love to hear from you and add it to this post!

Next, we need to turn the project directory into a git repo by running:

git init

In addition to making it a git repo we need to create a Procfile, which Heroku uses to understand how to start the app.

Create the Procfile in the root directly just like the web.js file and inlcude the following line, which tells Heroku to use NodeJS to run our web.js file.

web: node web.js

The next step requires that you have a Heroku account and the Heroku Toolbelt installed. You can get setup with a Heroku account here and download the Heroku Toolbelt here.

Once you have a Heroku account and the Heroku Toolbelt installed, you can create a Heroku app by running:

heroku create YOUR_APP_NAME

The next step is to commit all the code and push it to Heroku:

git add .
git commit -m "Create angular app using Yeoman"
git push heroku master

You need at least 1 web worker to get your app running. You can scale your Heroky web worker to 1 by running the following command:

heroku ps:scale web=1

Ta da, now your app should be running at <your_app_name> To quickly open your app run:

heroku open

Let me know if you have any questions or any problems while setting up and deploying your app!

Getting Into CSS3 Animations

I recently had the opprtunity to dive into some CSS3 animations. I’ve used libraries like animate.css and done animations with javascript, but never did any custom CSS3 work.

The Task

We recently updated our ‘tracking’ iconography at SeatGeek to match our new iPhone app. The lead designer created the heart icon with different states in a PSD and also created the animation below:


What is CSS3 Animation?

In CSS, animation is an effect that lets an element gradually change styles. You create the animations with the @keyframes keyword, which is followed by the name of the animation.

@keyframes heartAnimation {
  /* Animation code goes here */

To make the animation cross browser compatible you need to use vendor prefixes:

@keyframes heartAnimation {
  /* IE 10+ */

@-webkit-keyframes heartAnimation {
  /* Safari 4+ */

@-moz-keyframes heartAnimation {
  /* Fx 5+ */

@-o-keyframes heartAnimation {
  /* Opera 12+ */

However, for the rest of this post I will exclude the vendor prefixes for the sake of space.

The next step is to add the animation effects and decide when they happen. You can do this with either percentages from 0% to 100% or with the ‘from’ and ‘to’ keyword for simple animations with just a starting and ending state. Below is an example for changing the background color from yellow to blue, and then yellow to green to blue.

@keyframes colorChange {
  from {background: yellow;}
  to   {background: blue;}

@keyframes colorChange {
  0%   {background: yellow;}
  50%  {background: green;}
  100% {background: blue;}

Once the keyframes are created, you can call the animations as CSS properties. For example the code below would run the colorChange animation above 2 times for a 2s duration:

.color-animation {
  animation-name: changeColor;
  animation-iteration-count: 2;
  animation-duration: 2s;

/* Shorthand */
.color-animation {
  animation: changeColor 2 2s;

You can check out all the CSS3 animation properties here

Planning Out the Animation

After watching the gif several times, I realized it was a slight contraction followed by an expansion to a size slightly larger than the original size, and then back to the original size.

Heart Clicked Animation

Using the CSS3 keyframes and animation syntax above, here is the code I used to make the animation in the gif at the top of this page. It uses the css transform and property to scale the image.

@keyframes heartAnimation {
  0%  {transform: scale(1,1)}
  20% {transform: scale(0.9,0.9)}
  50% {transform: scale(1.15,1.15)}
  80% {transform: scale(1,1)}

.toggle-animation {
  animation: heartAnimation 0.7s; // no iteration count is needed as the default is 1 time

For the image, I was using a sprite, so I also needed to change the position of the image to get the red background:

.toggle-animation {
  background: url('../images/animation-example-sprite.png') no-repeat -320px 0;
  animation: heartAnimation 0.7s; // no iteration count is needed as the default is 1 times

Loading Animation

For a loading state, I made the heart white and pulsate in-and-out infinitely. It also scales down and back to the original size, instead of getting slightly larger than the original size before going to the original state like in the heartAnimation code above. Below is the code for the loading state:

@keyframes loading {
  0% {transform: scale(1,1) }
  50% {transform: scale(0.8,0.8) }
  100% {transform: scale(1,1) }

/* Notice the added 'infinite' to is used to make the animation-iteration-count */

.toggle-loading {
  background: url('../images/animation-example-sprite.png') no-repeat -160px 0; // make background white
  animation: loading 1s infinite;
  -webkit-animation: loading 1s infinite;
  -moz-animation: loading 1s infinite;
  -o-animation: loading 1s infinite;

Check Out Demos of the Animations

Here is a site I built to demo the animations:

Below is the JS I used to make the animations happen when each icon is clicked. The JS adds and removes the classes that I added the animation properties to.


  $('.animation-1 .image').on('click', function(){

  $('.animation-2 .image').on('click', function(){

  $('.animation-3 .image').on('click', function(){


Sorting a Rails Resource Based on a Calculated Value

The Setup

I recently went to a mobile payments hackathon and worked on a reminder app with my co-founder of Flock. You input the name of your item and the day of the month that it’s due. The app then shows you how long you have to complete the given task based on a green to red spectrum inspired by Clear.


Being a hackathon project, we wanted to keep the app simple. It contained a Reminder model with 2 attributes: 1) name and 2) day of the month you want to complete the task.

The Problem

I got to a point where I wanted to sort the items by number of days left until the item was due.

If I had a column in the database called ‘days_until_due’ I could have used the order method:

Reminder.order('days_until_due ASC')

But I didn’t have a database column called ‘days_until_due’…

This got me asking myself, “What’s the best way to sort a model based on a calculated value instead of a value stored in the database?”

The Solution

After googling around I stumbled upon a nice solution. It suggested creating an instance method to calculate the value, and then creating a class method that combines a query with the sort_by method.

Step 1: Create an instance method to calculate the value

In reminder.rb, I created an instance method to find out how many days until the item is due based on the day of the month the item was supposed to be completed by and the current date:

Step 2: Create a class method to query and sort the model

Again in reminder.rb, I then created a class method, which combined a query, sort_by, and the instance method from above.

def self.sorted_by_days_until_due

You may be asking yourself what is going on in that one line method? Let’s break it down step by step. First, Reminder.all returns an array of all the reminders (unsorted).

Reminder.all.class # => Array

Next, I call the sort_by method on this array. This method takes a block as an argument and generates a sorted array by mapping the values through the given block. If no block is given, an enumerator is returned instead. Below is an example:

array = ["Michael", "Adam", "Jen"]

array.sort_by{|word| word.length} # => ["Jen", "Adam", "Michael"] 

array.sort_by # => #Enumerator: ["Michael", "Adam", "Jen"]:sort_by

Now you’re probably asking yourself, but how does ‘&:days_until_due’ translate into a block? It has to do with procs and blocks. If you’re unfamiliar with these terms, you should check out a post I wrote discussing these parts of ruby. In one sentence, the ‘&:’ syntax is converting the instance method into a proc, and then converting the proc into a block, which is what Array#sort_by takes as an argument.

Below I will make the example above look like the method I used in my reminder app.

array = ["Michael", "Adam", "Jen"]

# Passing in a block directly
array.sort_by{|word| word.length} # => ["Jen", "Adam", "Michael"] 

# Creating a proc and converting the block to a proc using the '&' syntax
proc = :length.to_proc # => # 
array.sort_by(&proc) # => ["Jen", "Adam", "Michael"]

# Creating a proc and converting the block to a proc in one step
array.sort_by(&:length) # => ["Jen", "Adam", "Michael"]

The above syntax works by combining implicit type casting with the ‘&’ operator. The ‘&’ operator is used in an argument list to convert a Proc instance into a block. If you combine the operator with something other than a Proc instance, implicit type casting will try to convert it to a Proc instance using the to_proc method. Since Symbol#to_proc exists, when we pass a symbol after the ‘&’ operator, it is converted into a proc, which is then converted into a block.

Going back to my original problem, all this talk about procs and blocks and type casting is what allowed me to create the following one line method:

def self.sorted_by_days_until_due

This method allowed me to succinctly include a sorted array of reminders in my view with the following:

@reminders = Reminder.sorted_by_days_until_due

Now back to coding!

Deploying a Rails App With Capistrano (Part 2)

My last post outlined using Capistrano to deploy my 6-week long Flatiron School project. The post included a brief introduction of Capistrano, including what it is and the steps to get a Capfile (where Capistrano reads instructions from) into your app.

In this post, I am going to continue to walk through a basic deploy.rb file. If you don’t know what what a deploy.rb file is you should check out the earlier post first.

require 'bundler/capistrano' # for bundler support

set :application, "set your application name here"
set :repository,  "set your repository location here"

set :user, 'USERNAME'
set :deploy_to, "/home/#{ user }/#{ application }"
set :use_sudo, false

set :scm, :git

default_run_options[:pty] = true

role :web, ""  # Your HTTP server, Apache/etc
role :app, ""  # This may be the same as your `Web` server

# if you want to clean up old releases on each deploy uncomment this:
# after "deploy:restart", "deploy:cleanup"

# if you're still using the script/reaper helper you will need
# these

# If you are using Passenger mod_rails uncomment this:
namespace :deploy do
 task :start do ; end
 task :stop do ; end
 task :restart, :roles => :app, :except => { :no_release => true } do
   run "#{try_sudo} touch #{File.join(current_path,'tmp','restart.txt')}"

In the previous post I left off with the set ‘:scm, :git line’, so I will start with the following line:

default_run_options[:pty] = true

This is included to make sure Capistrano interacts properly with the shell on our server. For example, when using github your server needs to be able to access your repo. This capistrano config setting is needed for the password prompt from git to work so you can access it.

role :web, "" # Your HTTP server, Apache/etc
role :app, "" # This may be the same as your Web server

The above two lines assign the web and app ‘roles’ to specific servers. Capistrano roles allow you to have different servers handle different parts of the app (server for app, server for handling requests, and server for the database). We used one server for all aspects so assigned all roles to the same server.

Since we used Passenger, we also uncommented the :deploy namespace as is instructed in the standard deploy.rb file. This part of the file is an example of Capistrano’s task-oriented nature. Similar to rake tasks, we can create ‘cap’ tasks with the task keyword. For example, take the following 3 lines of code:

task :hello do
  puts "Hello World"

We can run this code with the following command in the terminal:

cap hello

We also used a common capistrano task to symlink specific files that were purposely excluded from our git repo. For example, we had an application.yml file with our Crunchbase API key and gmail username/password. Since we open sourced the repo, we had to make sure that file was included in our .gitignore. Because capistrano is getting the code from github, we have to manually link these ignored files to the server in order for them to be included. The following task helps us do just that. ruby

task :symlink_config, :roles => :app do 
  run "ln -nfs #{shared_path}/config/application.yml #{release_path}/config/application.yml"

In order for the symlink to work though, the file must already be in the shared folder on the server. You can securely copy a file from your local machine using a variation of the following command:

scp config/application.yml example@123.456.789.12:/home/example/example_app/shared

And that concludes my Capistrano configuration process. To deploy and update the app I simply run the following command:

cap deploy

If you’re interested in learning more about deploying a rails app with Capistrano, there is a good railscast and also a nice wiki on Github.

Deploying a Rails App With Capistrano (Part 1)

I recently graduated from the Flatiron School, where I worked on a 6-week long project with a group of 3 other students. Our project, HireMe, is a CRM platform to help manage the interview process. We built the app using Rails and deployed it onto a cloud server using Capistrano (along with Nginx and Passenger). For side projects I’ve used Heroku, so this was my first time deploying to my own server.

What is Capistrano?

Capistrano is a remote server automation and deployment tool written in ruby. Put simply, it helps you get your code on a server and easily run commands on a server so your application is ready for the world to use.

Using Capistrano

The first step in using capitstrano is installing the capistrano gem on your local machine. Capistrano only requires that your have access to your server via Secure Shell (SSH).

gem install capistrano

Once the gem is installed the next step is to cd into your repository’s directory and run the following command:

capify .

This creates a Capfile, which is where Capistrano reads instructions from. This is what it looks like out of the package:

load 'deploy'
# Uncomment if you are using Rails' asset pipeline
    # load 'deploy/assets'
load 'config/deploy' # remove this line to skip loading any of the default tasks

The capify command also creates a file in the config directory called deploy.rb, which the Capfile loads from as you can see above. The deploy file contains information about the servers you want to connect to and the tasks you want to run on those servers.

Below is the default deploy.rb file:

set :application, "set your application name here"
set :repository,  "set your repository location here"

# set :scm, :git # You can set :scm explicitly or Capistrano will make an intelligent guess based on known version control directory names
# Or: `accurev`, `bzr`, `cvs`, `darcs`, `git`, `mercurial`, `perforce`, `subversion` or `none`

role :web, "your web-server here"                          # Your HTTP server, Apache/etc
role :app, "your app-server here"                          # This may be the same as your `Web` server
role :db,  "your primary db-server here", :primary => true # This is where Rails migrations will run
role :db,  "your slave db-server here"

# if you want to clean up old releases on each deploy uncomment this:
# after "deploy:restart", "deploy:cleanup"

# if you're still using the script/reaper helper you will need
# these

# If you are using Passenger mod_rails uncomment this:
# namespace :deploy do
#   task :start do ; end
#   task :stop do ; end
#   task :restart, :roles => :app, :except => { :no_release => true } do
#     run "#{try_sudo} touch #{File.join(current_path,'tmp','restart.txt')}"
#   end
# end

We worked off of an awesome deployment guide by Spike Grobstein that recommended starting with the following deploy.rb file:

require 'bundler/capistrano' # for bundler support

set :application, "set your application name here"
set :repository,  "set your repository location here"

set :user, 'USERNAME'
set :deploy_to, "/home/#{ user }/#{ application }"
set :use_sudo, false

set :scm, :git

default_run_options[:pty] = true

role :web, ""                          # Your HTTP server, Apache/etc
role :app, ""                          # This may be the same as your `Web` server

# if you want to clean up old releases on each deploy uncomment this:
# after "deploy:restart", "deploy:cleanup"

# if you're still using the script/reaper helper you will need
# these

# If you are using Passenger mod_rails uncomment this:
namespace :deploy do
 task :start do ; end
 task :stop do ; end
 task :restart, :roles => :app, :except => { :no_release => true } do
   run "#{try_sudo} touch #{File.join(current_path,'tmp','restart.txt')}"

This version differs slightly from the default deploy.rb file, namely adding lines to set the user information, where to deploy to, and a couple other small settings. Below are some exaplanations of each of the lines in this file.

set :application, "studentbody"

This code sets the application variable. It will become the name of the overarching folder on the server and is also used in the deploy_to location a couple lines below.

set :repository,  "set your repository location here"

set :repository,  ""

The repository variable tells Capistrano where to find your code. We used a github hosted repository.

set :user, 'USERNAME'

The above line sets the name of the user we are deploying as. For example if you are SSHing into your server with the following command ‘ssh example@192.241.555.55’ then you’d set :user to example.

set :deploy_to, "/home/#{ user }/#{ application }"

This command sets the location of deployment. In the case where the the user is jsmith11 and the app name is example-app, the above code would deploy the app to ‘/home/jsmith11/example-app’ directory on the remote server.

set :use_sudo, false

The user_sudo variable tells Capistrano whether or not to prefix sudo infront of all commands. Sudo is a prefix that allows you to run programs with the security priveledges of another user (commonly used with the superuser/root). In our case we were deploying to a location that our user owned, so we set this to false.

set :scm, :git

The scm variable sets the source-code-management system, which in our case was git.

In a follow up post I will talk more about the rest of the deploy.rb file, custom tasks we ran in our HireMe app, and getting the app up and running using the ‘cap deploy’ command.

How to Deploy an App in 5 Minutes Using Roots

The Ingredients

  • node.js: server-side JavaScript
  • heroku: cloud platform as a service to help you easily deploy your apps
  • roots (the special sauce): a tool for quickly building beautiful and efficient web products

The Steps

1. Install node

If you don’t have node.js, install it from

2. Install roots

Once node.js is installed, you can can install roots in the terminal with the following command:

npm install roots -g # prefix with sudo if you get a permission error

3. Create a new roots project

You can create a new roots project with the following command in the terminal:

roots new [name of project] # i.e. roots new new_project

4. Start the local server

Once you’ve switched into the new project folder, you can start the app on localhost:1111 with the following command:

roots watch

5. Deploy to heroku

Now you’re one small command away from having your app up on Heroku for the world to see:

Yes, it’s that easy. If you don’t believe me checkout the app I made while going through the roots tutorial.

roots deploy

Checkout your own app with the following command:

heroku open

Note: The standard homepage markup is placed in a views folder with the name ‘index.jade’. If you don’t want to use the default roots stack (jade, stylus, and coffeescript), you can revert to an html, css, and javascript stack by adding the —basic flag to your roots new command.

Awesome features

In addition to helping you get an app up and running in just a couple minutes, roots also has a ton of amazing built in features.

LiveReload: lets you see your markup and styling changes without having to refresh your browser Axis | Better CSS: a css library built on top of stylus that helps take the pain out of traditional css

Axis in action

An example of how Axis makes css easier is how it simplifies border radius. The following code shows how to create a border radius that works across different browsers: first using standard css, and then using Axis.

/* Standard css border radius styling */
div {
  -webkit-border-radius: 5px;
  -moz-border-radius: 5px;
  border-radius: 5px;

/* Using axis to add a border radius */
  border-radius: 5px; /* vendor prefixes are added automatically */

The button in the example page uses the following code:

.button a
  simple-button: blue 15

Border-radius? Included. An easy on the eyes blue? Included. Darken on hover? Included. Yep, it’s super convenient. There are a lot of other cool features you can check out via the library’s documentation.

This is just the tip of the iceberg

There are a lot of other awesome features that I haven’t talked about above – for example dynamic content and js templates. The roots creator, @jescalan, has some great video tutorials that you can find here if you are interested in learning more.

What Is the Difference Between a Block, a Proc, and a Lambda in Ruby?

What are blocks, procs, and lambdas?

Coder Talk: Examples of closures in ruby.

Plain old english: Ways of grouping code we want to run.

# Block Examples

[1,2,3].each { |x| puts x*2 }   # block is in between the curly braces

[1,2,3].each do |x|
  puts x*2                    # block is everything between the do and end

# Proc Examples             
p = { |x| puts x*2 }
[1,2,3].each(&p)              # The '&' tells ruby to turn the proc into a block 

proc = { puts "Hello World" }                     # The body of the Proc object gets executed when called

# Lambda Examples            
lam = lambda { |x| puts x*2 }

lam = lambda { puts "Hello World" }

While it looks like these are all very similar, there are subtle differences that I will cover below.

Differences between Blocks and Procs

1. Procs are objects, blocks are not

A proc (notice the lowercase p) is an instance of the Proc class.

p = { puts "Hello World" }

This lets us call methods on it and assign it to variables. Procs can also return themselves.  # prints 'Hello World'
p.class # returns 'Proc'
a = p   # a now equals p, a Proc instance
p       # returns a proc object '#'

In contrast, a block is just part of the *syntax* of a method call. It doesn’t mean anything on a standalone basis and can only appear in argument lists.

{ puts "Hello World"}       # syntax error  
a = { puts "Hello World"}   # syntax error
[1,2,3].each {|x| puts x*2} # only works as part of the syntax of a method call

2. At most one block can appear in an argument list

In contrast, you can pass multiple procs to methods

def multiple_procs(proc1, proc2)

a = { puts "First proc" }
b = { puts "Second proc" }


Differences between Procs and Lambdas

Before I get into the differences between procs and lambdas, it is important to mention that they are both Proc objects.

proc = { puts "Hello world" }
lam = lambda { puts "Hello World" }

proc.class # returns 'Proc'
lam.class  # returns 'Proc'

However, lambdas are a different ‘flavor’ of procs. This slight difference is shown when returning the objects.

proc   # returns '#Proc:0x007f96b1032d30@(irb):75'
lam    # returns 'Proc:0x007f96b1b41938@(irb):76 (lambda)'

The (lambda) notation is a reminder that while procs and lambdas are very similar, even both instances of the Proc class, they are also slightly different. Below are the key differences.

1. Lambdas check the number of arguments, while procs do not

lam = lambda { |x| puts x }    # creates a lambda that takes 1 argument                    # prints out 2                       # ArgumentError: wrong number of arguments (0 for 1),2,3)                # ArgumentError: wrong number of arguments (3 for 1)

In contrast, procs don’t care if they are passed the wrong number of arguments.

proc = { |x| puts x } # creates a proc that takes 1 argument                   # prints out 2                      # returns nil,2,3)               # prints out 1 and forgets about the extra arguments

As shown above, procs don’t freak out and raise errors if they are passed the wrong number of arguments. If the proc requires an argument but no argument is passed then the proc returns nil. If too many arguments are passed than it ignores the extra arguments.

2. Lambdas and procs treat the ‘return’ keyword differently

‘return’ inside of a lambda triggers the code right outside of the lambda code

def lambda_test
  lam = lambda { return }
  puts "Hello world"

lambda_test                 # calling lambda_test prints 'Hello World'

‘return’ inside of a proc triggers the code outside of the method where the proc is being executed

def proc_test
  proc = { return }
  puts "Hello world"

proc_test                 # calling proc_test prints nothing

So what is a closure?

Coder Talk: ‘A function or a reference to a function together with a referencing environment. Unlike a plain function, closures allow a function to access non-local variables even when invoked outside of its immediate lexical scope.’ – Wikipedia

Plain old english: Similar to a suitcase, it’s a group of code that when opened (i.e. called), contains whatever was in it when you packed it (i.e. created it).

# Example of Proc objects preserving local context

def counter
  n = 0
  return { n+= 1 }

a = counter            # returns 1            # returns 2

b = counter            # returns 1            # returns 3

Background Part 1: Lambda Calculus and Anonymous Functions

Lambda get its name from a type of calculus introduced in the 1930s to help investigate the foundations of mathematics. Lambda calculus helps make computable functions easier to study by simplifying its semantics. The most relevant of these simplifications is that is treats functions ‘anonymously’, meaning that no explicit names are given to functions.

sqsum(x,y) = x*x + y*y  #<-- normal function
(x,y) -> x*x + y*y #<-- anonymous function                        

Generally speaking, in programming the term lambda refers to anonymous functions. These anonymous functions are very common and explicit in some languages (i.e. Javascript) and implicit in others (i.e. Ruby).

Background Part 2: Where Does the Name Proc Come From

Proc is short for procedure, which is a set of instructions packaged as a unit to perform a specific task. In different languages these may be called functions, routines, methods, or the generic term callable units. They are usually made to be called multiple times and from multiple times in a program.

Summary Differences

  1. Procs are objects, blocks are not
  2. At most one block can appear in an argument list
  3. Lambdas check the number of arguments, while procs do not
  4. Lambdas and procs treat the ‘return’ keyword differently

How jQuery and AJAX Actually Work

As someone who loves UX and design, it is not surprising that I’ve been wanting to learn about JavaScript – the language of the browser that allows for cool client side interactions. I’ve used many JS libraries, but wanted to dive deeper into AJAX. Before today I didn’t even know what it meant, just that it was something I wanted to know more about.

So What is AJAX?

AJAX, or Asynchronous Javascript And XML, is a client side technique for communication with a web server. In other words, it allows you to fetch data ‘in the background’ without having to reload a whole page.

In a typical web request, you send a URL request to the server and the server responds with the corresponding HTML, CSS, and JavaScript that generates a full new page in your browser.

In contrast, in a typical AJAX request, the HTML, CSS, and JavaScript is already loaded. Instead of making a URL request for another whole page, you use JavaScript to talk to the server and receive smaller pieces of information that can range from HTML to other data formats like JSON and XML. The JavaScript then acts on the response and updates the page accordingly, without having to refresh the entire page.

What does an AJAX request look like?

$.ajax(url, settings)

At a high level an AJAX request consists of the URL you a making a request to, and then corresponding settings to handle the response. Below are a few of the more popular callbacks that make up the settings:

  • success: what to do if the URL request is successful
  • error: what to do if the URL request is unsuccessful
  • timeout: how long to allow the URL request to run before an error message pops up
  • beforeSend: runs before the AJAX request, good place to put a spinner
  • complete: runs after both success and error, good place to stop a spinner


/* Example 1 */
$.ajax('index.html', {
  success: function(response) {

Example 1: makes a request to ‘index.html’ and then inserts the response into the item in the DOM that has a class called “hello-world”

/* Example 2 */
$.ajax('profile.html?userId=1', {
  success: function(response) {

/* Example 3 */
$.ajax('profile.html', {
  success: function(response) {
  data: {"userId": 1}

/* Example 4 */
$.ajax('profile.html', {
  success: function(response) {
  data: {"userId": $(".show").data("userId")}

Corresponding HTML to go with Example 4 

<div class="show" data-userId="1"></div>

These three examples all make a request to the url ‘profile.html?userId=1’ and show the various ways to send parameters with a request. In example 2 the data is put manually into the URL. In example 3 the data is put into a JavaScript object. Lastly, in example 4 the AJAX request pulls data from HTML, which when combined with ERB tags can make the request very dynamic.

/* Example 5 */
$.ajax('index.html', {
  success: function(response) {
  timeout: 3000,
  beforeSend: function() {
  complete: function() {

Example 5 demonstrates some of the callback settings. In this AJAX request, if the response is not successfully made it will stop the request after 3 seconds (3000 milliseconds). It also demonstrates common code for adding a loading animation while the request is being made.

Using the Twitter API to Find People


Over the last year I’ve become a huge Twitter fan. So much so that I had to move it off the front page of my phone so I wouldn’t be (as) distracted throughout the day. In addition to my personal account, I have several accounts for projects I’m working on. I use these accounts to discover and interact with people that may be interested in these apps.

To discover people that I think may be interested, I look at recent followers of similar apps. While this process worked alright, it was a very manual. Also, one of the apps I’m working on is only available in NYC, and there was no way to search for people only living in NYC and the surrounding area.

Using the Twitter API

I decided that I could use the Twitter API to help automate this process. For example, let’s pretend that I am creating starting a Ruby Motion meetup in NYC. I’d like to find people in the NYC area that are interested in Ruby Motion. Using Twitter, I can find these people a couple of different ways:

  1. Look for people that follow @RubyMotion
  2. Look for people that recently tweeted “#rubymotion”

In addition to finding people that match either of the criteria above, I also want to make sure they live in the NYC area.

Getting Started

I first looked into the best way to access the Twitter API from a ruby environment. As Twitter is a very popular app, I figured there was likely a good gem. After searching for ‘Twitter’ on, I ended up deciding to go with the ‘Twitter’ gem. After installing this gem in the terminal, I required the rubygems gem and twitter gem in my ruby file.

require 'rubygems'
require 'twitter'

Next I read the gem documentation on github, and followed the steps to register and authorize my app. After registering my app on the Twitter Developer site, it was just a few lines of code before I was up and running.

Twitter.configure do |config|
  config.consumer_key = "**********************"
  config.consumer_secret = "*****************************************"
  config.oauth_token = "**************************************************"
  config.oauth_token_secret = "*****************************************"

Now I was up and running! To tweet about the new meetup was just a simple line away:

Twitter.update("Come on out to our Ruby Motion meetup next Tuesday @ 6:30pm!")

Now for finding relevant people:

nyc_accounts = {}
index = 0
cursor = -1

# Loop through pages 1-10
while index <15 do

    # Iterate through followes
    followers = Twitter.followers("RubyMotion", :cursor => -1)

    # Save the users 
    followers.users.each do |user|
      rubymotion_accounts[user.screen_name] = user.location if user.location.downcase =~ /(nyc|york)/i

    cursor = followers.next_cursor

The code above makes a call to the Twitter API to grab the followers for a sprcific Twitter account, in this case RubyMotion. The way the Twitter API works, each call returns an object that contains an array of 20 seperate hashes, which contain information about each of the followers. Because the API rate limits of the Twitter API are relatively small, I decided to loop through only 15 pages of followers.

Next, I went through each Twitter object and added the username and location of the follower if the location contained either nyc or york (using regular expressions). The result is a hash where the keys are usernames and the values are locations for, containing information of people that follow RubyMotion and have a location that contains either ‘NYC’ or ‘York’.

rubymotion_accounts_2 = {}"#rubymotion", :count => 100, :result_type => "recent").results.each do |status|
  rubymotion_accounts_2[status.attrs[:user][:screen_name]]=status.attrs[:user][:location] if status.attrs[:user][:location].downcase =~ /(nyc|york)/i

For the second call, I a utilizing the search method, and querying the most recent 100 tweets that contain the #rubymotion tag. This call returns a Twitter object that contains an array of all the tweets. Each item of the array contains a hash with information about the user. I then saved the username and location of the tweeter if the location of that person contained ‘NYC’ or ‘York’ again.

Saving the data into a database:

require "sqlite3"
require 'open-uri'

db = "twitter-bot.db"

db.execute <<-SQL
  create table twitter_handles (
    twitter_handle TEXT,
    city TEXT

rubymotion_accounts.each do |handle, city|
  db.execute("INSERT INTO twitter_handles (twitter_handle, city) 
              VALUES (?, ?)", [handle, city])

rubymotion_accounts_2.each do |handle, city|
  db.execute("INSERT INTO twitter_handles (twitter_handle, city) 
              VALUES (?, ?)", [handle, city])

Lastly, I wrote a schema.rb file to create a table and iterate through the 2 hashes I created above and insert the information into the new data.

Areas of Future Exploration

One problem I kept on running into was exceeding my API rate limit. For example, in the first API call, the reason I only scroll through 15 pages is because the Twitter API only allows me to make 15 calls within a 15 minute window. While finding 300 relevant people seems like a lot, when you add the location constraint it ends up not being that many people. Similarly in the 2nd API call, I only grab the last 100 tweets because that is all the API lets me grab at a time. This made it really hard to find many people that were relevant for this specific search. When I ran this search I actually ended up with no results because, presumably because of the 100 tweets grabbed, no users were located in New York.

Building a Mobile App Landing Page

Over the last year I’ve been working on a mobile app called Flock. To get ready for our launch, I created a new landing page to allow people to easily download the app. On a desktop browser, it allows people to input their phone number and receive a text on their phone with a link to download the app. On a mobile device, it allows people to download the app directly.


The Ingredients

  • Twilio: An API to make and receive phone calls and send and receive text messages. I used this service to send a text message to desktop users containing a link to download the app.
  • fancyBox: Tool for displaying images, html content and multi-media in a Mac-style “lightbox” that floats overtop of web page
  • Creative Buttons: Button inspirations from Codrops
  • SASS/Bourbon/Neat:
    • SASS: A CSS extension that adds nested rules, variables, mixins, and selector inheritance
    • Bourbon: A mixin library for SASS
    • Neat: A grid framework for SASS with Bourbon

Sending a Text

My first step was to get the text message part of the landing page working. High level I wanted to be able to send users a text message with a link to download Flock on their iPhone. To do this, I created a form to collect a user’s phone number, and then utilized a Twilio gem to send a message to the collected number.

Using the ‘twilio-ruby’ gem I was able to get a text message up and running relatively quickly by creating a form and adding the Twilio logic in the route associated with that form.

 def send_text
    number = params[:number] # grab user's number from form and assign to 'number' variable
    account_sid = '**********************************' # received after creating an account with Twilio
    auth_token = '********************************' # same as above
    @client = account_sid, auth_token # create a Twilio client (used to send messages)
    @client.account.sms.messages.create( # method on client to create an sms message
      :from => '+15555555555', # my Twilio number in actual code
      :to => number, # user's number
      :body => 'Download Flock and do more together:' # text message content
    redirect_to root_path

Making it Look Pretty Part 1: Adding a fancyBox

I wanted to use javascript on the “SEND ME A LINK” button so that the website didn’t have to load a new page to display the number form. Not wanting to re-invent the wheel, I looked around for js plugins and ended up choosing fancyBox, a library to easily implement “lightbox” popups.

To implement this plugin, there were a couple main steps:

  1. Create a hidden div containing the number form
  2. Link a button to the hidden div
  3. Add the necessary js from fancyBox
# STEP 1: Add hidden div containing form
# Note: id = "number_form"

<div style="display:none" class="text" id="number_form">
    <%= form_tag(send_text_path, :method => :post) do %>
      <%= text_field_tag(:number, nil, :placeholder => '555-555-5555')%><br>
      <%= submit_tag("Submit") %>
    <% end %>

# STEP 2: Creata a button that links to the hidden div
# Note: class = "fancybox" and href = "#number_form" (id of div from STEP 1)

<a href="#number_form" class="fancybox"><div>SEND ME A LINK</div></a>

# STEP 3: Add the fancyBox js to show the div when the button is clicked
# Note: I am calling the function "fancybox" on all links
#       that have a class named "fancybox" (from STEP 2)

<script type="text/javascript">
    $(document).ready(function() {
        maxWidth: 900,
        helpers : {
            overlay : {
                css : {
                    'background' : 'rgba(0, 0, 0, 0.8)'


Making it Look Pretty Part 2: A Fancy Button


Once I got the fancyBox working, I wanted to customize the styling of the form. Earlier in the week I stumbled across an awesome link from Codrops that had examples of many different buttons using CSS. I chose my favorite and added the appropriate CSS.

The button I chose gives a 3D effect by creating a shadow and making the shadow smaller / shifting down the button while hovering over the button, and removing the shadow all together when clicked.

input[type=submit] {
    border: none;
    cursor: pointer;
    width: 100%;
    padding: 15px 0px;
    margin: 15px 0px;
    text-transform: uppercase;
    position: relative;
    background: $green;
    box-shadow: 0 6px #527a52;
    font-family: "proxima-nova", "sans-serif";
    font-style: italic;
    font-weight: 800;
    font-size: 1.2em;
    color: white;
    border-radius: 0 0 5px 5px;

    box-shadow: 0 4px #527a52;
    top: 2px;

      box-shadow: 0 0 #527a52;
      top: 6px;


Making it Look Pretty Part 3: Responsive Design

Once I got the button looking sharp on a desktop browser, I then wanted to make the page responsive for mobile users. Not only did I want to change the styling so it looked good on a phone, but I also wanted to change the main button so that when a user opens the site on their iPhone the “SEND ME A LINK” button turns into a “DOWNLOAD THE APP” button that takes him or her directly to the App Store.

I made the button (and rest of the website) responsive using Bourbon and Neat. Bourbon is a mixin library for SASS, and Neat is a grid framework for SASS with Bourbon.

// STEP 1: Define a mobile breakpoint (Neat version of CSS media query)
$break_four: new-breakpoint(max-width 585px);

// STEP 2: Define style to hide elements where class = "mobile"

.mobile {
 display: none;

// STEP 3: Hide items where class = "desktop" and show 
//         items where class = "mobile" at breakpoint

@include media($break_four) {
  .desktop {
    display: none;
  .mobile {
    display: block;

// STEP 4: Add classes where appropriate

<div id="button">  
    <a href="#number_form" class="desktop fancybox"><div>SEND ME A LINK</div></a>
    <a href="" class="mobile"><div>DOWNLOAD THE APP</div></a>

And that’s how to create a simple landing page for a mobile app!

Quitting My Job and Learning to Program

Pulling the Ripcord


About 6 months ago I quit my job to dive head first into the startup world. I made the decision in December, gave two weeks notice, and moved from Atlanta to NYC in January.

Why I Quit

I worked as an investment banking analyst, helping financial services and technology companies raise money and make strategic decisions. As a liberal arts major in college with business running through my blood, it was the perfect job for me right out of school. I wanted to learn as much as possible about the business world in the shortest amount of time, and there is no question investment banking is a great place to do that. I learned a ton.

I think it’s wrong to think you’re necessarily going to learn the most by paying your dues. People who work at a big company aren’t engaged. That’s a slower trajectory. But if you’re young and jump in, sure you’re going to make a bunch of mistakes but you’re going to learn quickly.
— Mike Rothenberg, 28 year old who raised a $5mm seed fund while sleeping on couches last Summer

However, after a steep learning curve for the first 6-9 months, the job became repetitive. The long hours became increasingly painful as I didn’t feel like I was getting much out of the job besides a nice paycheck. To me, the most valuable part of any job, especially right out of school, is thelearning opportunity.

That’s why I chose investment banking.

It’s also why I quit.

Why Programming?



What I Told People (Including Myself)

I want to build my own apps. Coding is the ‘literacy of the 21st century.’ There are 25x more startups looking for engineers than business people. I want to be closer to the product.

How it Actually Went Down

In reality, I decided to learn to program because I thought it’d be a great way to break into the startup world. Startups are hot, and it’s hard to find a job as a biz dev / financial analyst. I figured it would be a good way to differentiate myself from all the other bankers and consultants. My plan was to move to NYC and learn coding basics for a month or two while looking for jobs. Worst case I figured I’d spend time learning SQL and position myself for a data analyst position.

So What Happened?

I didn’t stick to my plan. After meeting with potential employers and doing some ‘casual internships,’ I began to realize excel is excel, financial statements are financial statments, and while it’d likely be more fun analyzing numbers and data for a startup (and in a hoodie), it wasn’t going to be drastically different from what I just left.

At the same time, I began to fall in love with building stuff. First I used my basic HTML and CSS knowledge to build a landing page for a mobile appI’m working on. Next, I learned Javascript and JQuery to add fun client side interactions. The more time I put into it the more stuff I was immediately able to do. It was awesome.

“The people who actually learn to code don’t do it because they think they should. They do it because they had no other option. It was either learn or fail.” - Vin Vacanti, Yipit

Fast-forward 6 months and I’m getting ready to launch a web app that was ‘just another idea’ a little over a month ago. I’ve never learned so much in such a short time. In the past 2 weeks alone I’ve learned how to integrate Facebook, Foursquare, Google Maps, and Stripe (payments) into the site.

Stumbling on Happiness

Although I didn’t see it coming, I can’t explain how happy I am to have stumbled upon the world of coding. The work is challenging and rewarding in a way that is unlike anything I’ve ever done.

I’m extremely exited to continue this learning adventure at the Flatiron School over the next 12 weeks.

Build, break, learn.

Analyst Program Takeaways

I recently left my job as an investment banking analyst to pursue something more entrepreneurial.  While it’s the right time for me to move on, I’ve learned an incredible amount over the last 18 months and want to share a couple lessons I’ve learned along the way.        

The points I expand upon are a couple of my favorite lessons from a list that has been floating around Wall Street for the past couple years called “101 Things I Learnt as an Analyst.”

While this post is told from the point of view of an investment banking analyst, these lessons can be broadly applied and are especially relevant for entry level positions.


“I don’t know” is a good answer

The first couple days on the job every colleague will tell a first year analyst, “You have a couple months where there is no such thing as a stupid question.”  While I don’t believe this is completely true, I think that knowing your limitations and asking for help is one of the best qualities an analyst can have.  In my opinion, intelligence has much more to do with experience than raw talent; if you don’t know how to do something it is likely because you’ve never been exposed to that task. Don’t try to pretend you know how to do everything and let your ego get in the way of learning.  Instead, ask for help.  First ask your fellow colleagues (i.e. first year analysts if you just started), and then if they don’t know slowly move up the food chain.  This rule doesn’t just apply to your first 3 months on the job.  If you’re not consistently asking questions it means you are not pushing yourself to learn more and get better at what you do.


Be Humble

There are a lot of type-A personalities in investment banking.  Having usually done fairly well in school their whole lives, analysts come into the program thinking they know everything.  DCF - check.  Accretion / Dilution - check.  Excel skills - check.  The reality is that most of the stuff you learn in school will be completely useless on the job.  Instead of being able to regurgitate theories and case studies, what will become important is learning the specifics of your new environment.  From formatting ppt slides to financial models, there is no objective “right” and “wrong”; instead, it is “how your boss likes it” and “wrong.” In order to be successful, it is important to be humble and try to learn as much as possible about how the people you work with like stuff to be done.   


Believe nothing is beneath you

Attention to detail is critical because someone will notice

Most incoming analysts understand the importance of attention to detail.  However, most people think about it in terms of numbers.  While there in no question that the accuracy of numbers is very important, attention to detail for non-critical tasks (i.e. formatting, email signatures) is just as important.  As a new analyst, your first tasks will likely not involve complicated financial models.  Most errors you make and markups you receive will be related to formatting (consistent fonts, alignment, decimal places).  Only once you show you can perform these tasks quickly and accurately will you be given more responsibility.  Whether it’s ordering dinner, inputting numbers from a pdf into excel, or recreating ppt slides into your firm’s format and colors, make sure you take every task seriously.  Make sure nothing is beneath you.


If you think about it, there is usually an easier way

Take a step back and attempt to think of the usual things in a new, different way

Bankers love to throw man hours at tasks.  One reason for this is that it is a very competitive industry and people love to show they are working hard.  One way to show you are working hard is to work long hours.  However, a lot of the time there is usually a much more efficient way to complete any given task, which relates to a good quote from Jason Fried & David Heinemeier Hansson’s Rework:

“Workaholics aren’t heroes. They don’t save the day, they just use it up. The real hero is already home because she figured out a faster way to get things done.”

While there is no question that investment banking requires very long hours, many tasks are done inefficiently. One way to become more efficient is putting in extra work upfront. As an investment banking analyst, examples include building easy-to-use and dynamic excel backups and learning the functionality of common tools and databases like Excel, Outlook, CapIQ and FactSet.  There are so many neat shortcuts and good resources that can save you an incredible amount of time in the long run if you put in the time and effort upfront.  In addition to saving time, I’ve also noticed that automating processes helps with accuracy.  Below are a couple of my favorite shortcuts and functions (we used Microsoft XP and Office 2007):

Excel / PowerPoint - F12: Shortcut for “Save As,” great for quickly saving new versions of documents (also a big fan of version control w/ military time, i.e. Model_v1.22.13_1300)

Excel - F5, alt + S, O, X: A shortcut to find hardcoded numbers in excel, perfect for helping make sure your file is accurate, especially useful when using previous files that may not follow banker excel etiquette (i.e. inputs blue, formulas black, other sheets green, and red for caution)

Outlook - Ctrl + Shift + V: shortcut to archive emails into personal folders in outlook, allowing you to save time while keeping organized

Microsoft - Making keyboard shortcuts to commonly used files: Probably all banks work off of shared networks, and in order to to access these files you have to navigate through a lot of different folders.  That’s a lot of double clicks.  Make a shortcut folder, and assign a keyboard shortcut.  For example, to access our shared “Technology” folder I would just press “Ctrl + shift + t”

Excel - Alt, M, M, D: This shortcut allows you to name cells in excel.  Instead of having to constantly reference commonly used assumptions in far away cells (i.e. tax rate, company name, ticker) this allows you to quickly call that cell by typing the intuitive name you give it).  It also makes your models easier to understand.  Instead of seeing “A4 * [Other Tab]B2” in the formula bar, users of your model will see “A4 * Tax_Rate”


Intellectual boredom is the enemy

One of the main reasons I chose investment banking was the learning opportunity.  I took a liberal arts approach to college, so my first couple years out of school I wanted to soak up as much business knowledge as possible.  After the past 18 months, I can confirm that there is no better and faster way to quickly learn the ins-and-outs of the business world than an IB analyst program.  From financial statement analysis to more qualitative skills like navigating a large corporate environment, it is a well worthwhile experience. When my program started in summer 2011, I was beyond eager.  My zealousness made it easy to work late hours and led to me staying late and coming in on weekends when I didn’t have to. I was working a ton, but I was also learning a ton - and to me that is the best compensation someone right out of school can receive.  

While the learning curve in investment banking is steep, at some point it begins to level off.  This is when I knew I needed to move on.  In addition to tasks becoming repetitive, my interest in finance began to fade as I became intrigued and inspired by the startup community.  I left investment banking for the same reason I chose it a couple years earlier.  Put yourself in a position where you are eager to learn.  It will benefit you and the company you work for more than you can imagine.


Be concise

Being concise demonstrates you’ve put time into thinking about what you’re saying.  When done correctly, it will transform your communication into something as simple, elegant, and easy to understand as the latest Apple product.