SHPE site makeover

12 December 2014 |

I’m happy to announce that R3DM’s first project is done! It’s live at


For this project we originally went with ghostjs. We ran into issues in two main ways. When we first asked the developers about how to get ghost going on heroku we didn’t get much help. There are many blog posts floating around the blogosphere regarding how to accomplish this but it didn’t seem like the project was interested in this usecase. Secondly, once we got past the cosmetic stage - implementing our design as a ghost theme - we found that adding custom server side code fell under App territory. And that ghost’s App api was still under heavy development. Since then it seems like they’ve made more progress on that front Ghost App.

When we ran into these roadblocks we explored KeystoneJS. Keystone if a fairly new project as well but we were happy to see that it was built using node.js, mongoose, mongodb and express - technologies both I and Berkeley are very familiar with.

The first step was to recompile our ghost theme from handlebars to jade templates, keystone uses jade. After we did that we cleaned up the generated files and started familiarizing ourselves with keystone’s project structure.

Our first major server side functionality was importing Events data from Facebook’s Graph API. We originally attempted to build a Facebook app so we could manage shpe’s events through our website. But we had difficulty getting Facebook to understand exactly what it is we wanted to do (they rejected our application twice). So we went with plan B and built our functionality using the parts of the api that don’t require elevated privileges. The implication being that an administrator would first have to create the facebook event (as normal) then grab it’s id from the url and paste it into our site. Not a huge amount of work in my opinion.

For our build strategy we use gulp and bower.

The images are stored using cloudinary. Which was surprisingly nice. They have a freemium model and perform image manipulations on the fly by simply modifying the url with which you request images.

For analytics we use Google Analytics. A must to measure web traffic and demographics.


This is the first project where I used Stylus. Coming from a rails background I was already familiar with Sass and found stylus very interesting. The features are mached almost one-to-one with subtle differences. I find it hilarious when I asked a peer why stylus is better than sass - we both shrugged. It just feels better and more inline with the javascript way of doing things. It may only be due to the fact that it’s an npm module instead of a gem ;) I really enjoy the conditional assignment operator. I was first exposed to it while evaluating kuoto-swiss and compass-like response for stylus. We used kuoto-swiss to handle css vendor prefixing for styling our form’s placeholder text.

styling placeholder text

Italicized placeholder text

I’m really looking forward to learning more about stylus’s advanced features in the future.

We also originally built our frontend using Pure.css. At the time it seems like a decent enough framework, small and simple. We quickly switched over to Bootstrap due to it’s responsive navigation bar. I’m all for learning a lot but it seemed silly to rebuild a responsive navbar when Bootstrap’s is already so great.

Other things we used:

  • The events slider is built using slick - the last carousel you’ll ever need.
  • The stylus port of Bootstrap bootstrap-stylus - why isn’t there an official port? @mdo
  • For the gallery Bootstrap Image Gallery
  • The date selector in our forms is pickadate.js and amazing find.
  • The forms also use bootstrapvalidator to let the user know if any fields are obviously wrong right away.


One of the single most attractive features of Keystonejs is it’s AdminUI.

keystone's admin ui

Keystonejs’s adminUI

Keystone bills itself as a Content Management System. If it achieves even a quarter of the size Wordpress is that would be amazing. Delivering a site with a CMS is amazing for client work. You’re basically delivering a piece of software - a website or mobile app - that can be modified by a nontechnical person. This keeps costs low for the client and the developers aren’t bogged down by annoying little tweaks desired by the clients. It empowers the customer!


If you’re interested in a custom built site - perhaps you have an idea for a cool new phone app or the next website to revolutionize an industry - get in touch. R3DM is always looking for new and interesting work.

Halloween Update

31 October 2014 |

This month has been hectic.

I was holding off until we finished r3dm first project - redesigning the Society of Hispanic Engineers San Francisco website. It’s been really interesting to build. We’ve been using keystone js CMS and I inadvertantly became and expert in Facebook’s Graph API. You can see a preview here.

I won 6 months of free co-working at by participating in a hackathon. It’s great because I get to bike to downtown - so I get a workout - and I get to meet other devs in the same boat as me (flexible hours, freelancers, seed stage startups). If you’re in SF check it out.

I’m volunteering for Should be fun. It’s run by Substack and friends. Also been hanging out at Noisebridge a lot. They raised $30K through Indiegogo and we’re building all kinds of stuff like 3d-Printers and hacking the planet.

Why is it so damn hard to gitignore recursively

30 September 2014 |

I have a directory where I’m storing all my solution to courses. For many of these solutions I have installed node dependencies. These are stored in a node_modules directory in each folder. To ignore a directory recursively you can use the following .gitignore file

# .gitignore file

If you would like to remove any node_modules directories you’ve added accidentally you can use something like git rm --cached */node_modules -r (ymmv).

Why did this warrant a blog post? I was searching around online and on irc for the solution to my problem and there were a lot of misleading solutions such as /***/node_modules **/node_modules or even **/*node_modules. Now I know.

Related 1 2

Heroku Ghost.js example configuration

12 September 2014 |

We’re evaluating Ghost.js for our upcoming project at It’s pretty cool. Explicitly NOT a CMS for node.

Here’s our config file. Hopefully it saves some new devs some trouble. 1 2 3 4

The cool things to note are:

1) since heroku provides an environment variable DATABASE_URL you can specify your production database by passing it in. This is thanks to project knexjs which is a dependency of ghost.

2) heroku doesn’t support storing files. But you’re probably better off storing those in Amazon S3 + cdn anyway. This way just store the resulting urls in your heroku database.

This is a much cleaner solution, imho, than those provided elsewhere.

// # Ghost Configuration
// Setup your Ghost install for various environments
// Documentation can be found at

var path = require('path'),

config = {
    // ### Development **(default)**
    development: {
      url: 'http://localhost:9000',
      database: {
        client: 'pg',
        connection: {
          host: '',
          user: 'user',
          password: '',
          database: 'database',
          charset: 'utf8'
        debug: true
      server: {
        host: '',
        port: '9000'
      paths: {
        contentPath: path.join(__dirname, '/content/')

    // ### Production
    // When running Ghost in the wild, use the production environment
    production: {
      url: '',
      mail: {},
      database: {
        client: 'pg',
        connection: process.env.DATABASE_URL,
        debug: false,
        filestorage: false
      server: {
        host: '',
        port: process.env.PORT
    // ### Testing
    // Used when developing Ghost to run tests and check the health of Ghost
    // Uses a different port number
    testing: {
        url: '',
        database: {
            client: 'postgres',
            connection: {
                filename: path.join(__dirname, '/content/data/ghost-test.db')
        server: {
            host: '',
            port: '2369'
        logging: false

    // ### Testing MySQL
    // Used by Travis - Automated testing run through GitHub
    'testing-mysql': {
        url: '',
        database: {
            client: 'mysql',
            connection: {
                host     : '',
                user     : 'root',
                password : '',
                database : 'ghost_testing',
                charset  : 'utf8'
        server: {
            host: '',
            port: '2369'
        logging: false

    // ### Testing pg
    // Used by Travis - Automated testing run through GitHub
    'testing-pg': {
        url: '',
        database: {
            client: 'pg',
            connection: {
                host     : '',
                user     : 'postgres',
                password : '',
                database : 'ghost_testing',
                charset  : 'utf8'
        server: {
            host: '',
            port: '2369'
        logging: false

// Export config
module.exports = config;


Webgrep and monthly update

28 August 2014 |

So I haven’t been able to work on a solid blog post on any specific technology. I’d like my articles to be a lot like the articles you see on nettuts or sitepoint, just haven’t found tech I’m super passionate about like that this month.

Webgrep screenshot

The other day I was doing market research and was searching for affiliate marketing programs in different industries. After opening a bunch of website tabs and ctrl-F-ing on every page for ‘affiilate’ I look at rick and ask him, “why isn’t there a chrome extension or something that’ll do this for me?”. I whipped up the next day. Some friendly people on ##javascript (freenode irc channel) told me about Yahoo query language which acts as a free proxy for us. Next things I’d like to add are

  • ability to point the tool at a url
  • ability to drop in a word/excel doc
  • infer if the found word is inside a link and return that instead
  • filter by result found/not found/yql error
  • provide counter and spinner so user knows if the program is still executing

If I see there is demand for this tool I’d be willing to offer a pro version where you get access to a proxy I make and crawls sites Yahoo wont. If you have any other feature requests lmk.

Teaching at Hacker Coding Academy

14 July 2014 |

This post is secretly only for testing embedding jsfiddles in a webpage. But I might as well give the blog an update. I’m currently teaching part-time at Hacker Coding Academy a 12 week full stack Javascript Vocational school. I’m very excited to work on my communication skills and really learn what I know by passing it on.

Below is an assignment I’m playing around with. Would it be cool to design your own business card with html/css? Could be fun. <iframe width="100%" height="300" src="" allowfullscreen="allowfullscreen" frameborder="0"></iframe>

Adding unix aliases to OSX

10 June 2014 |

A part of mastering the commandline is extending it with your own custom commands. On any nix environment you should have access to config files, e.g., ~/.bashrc or ~/.profile. I add my aliases to my ~/.zshrc file. ZSH is pretty dope btw, definitely check it out.

Heres and excerpt of my .zshrc.

alias mkblog="jekyll build; jekyll serve -w"
alias gph="git push heroku master"
alias rr="rake routes"
alias corrun="cordova build android; cordova run android; adb logcat | grep CONSOLE"
function pyserver() {
  python -m SimpleHTTPServer "${1:-8765}";
alias tunnel="ssh harry@< took out my ip :p > -D 8080"

Vim-like mission control shortcut

08 May 2014 |

So I use iterm2 on my mac. And there’s a shortcut option-spacebar which switches back and forth between a desktop and iterm2 in fullscreen. I do most of my work that way, switching between a browser and code. Recently however I’ve been following some screencasts on youtube which required me to switch between broswer, fullscreen iterm2 and fullscreen youtube player. This was the perfect time to change the mission control shortcut on my mac. Screenshot of my Mission Control settings

As you can see I mapped moving one screen left or right to ⌥h and ⌥l so I can switch using vim-like keys.

AngularJS - UI-Router, Params and Ionic

14 April 2014 |

I’ve been learning ui-router and I’d like to share some things I’ve learned that took me a while to get. With bits of Ionic Framework.

Let’s say you have an abstract state with a child and another state and you want to trigger a transition from the controller to the other state. The following is a concrete example. I was building an ionic app that would grab a photo from the phones photolibrary and transition to another view, passing the fetched uri to the new view.


'use strict';

var app = angular.module('Txtbinge', ['ionic', 'firebase']);$ionicPlatform) {
  $ionicPlatform.ready(function() {
    if(window.StatusBar) {

app.config(function($stateProvider, $urlRouterProvider) {

  .state('app', {
    url: '/app',
    abstract: true,
    controller: 'AppController',
    templateUrl: 'templates/applayout.html'

  .state('app.home', {
    url: '/home',
    views: {
      'centerContent' :{
        templateUrl: 'templates/home.html'

  .state('crop-image', {
    url: '/crop-image/:imageURI',
    templateUrl: 'templates/crop-image.html',
    controller: 'CropController'


Here we set up all the states in our app. Note that the ‘crop-image’ state is going to require an ‘:imageURI’ param in it’s url.

'use strict';

app.controller('AppController', function($scope, $state, Camera) {

  $scope.newPost = function() {
    if( ) {
      Camera.getPicture().then(function(imageURI) {
        $scope.imagesrc = encodeURIComponent(imageURI);
        $state.go('crop-image', {imageURI:$scope.imagesrc});
      }, function(err) {
        console.log('error inside getPicture(): ' + err);
    } else {
      console.log('no camera');
      var str = encodeURIComponent('app/images/ionic.png');
      console.log('encoded uri is: ' + str);
      $state.go('crop-image', {imageURI:str});

app.controller('CropController', function($scope, $stateParams) {
  $scope.imageURI = $stateParams.imageURI;
  console.log('inside cropcontroller ' + $scope.imageURI);

The AppController is the main controller for this app. Accessible from any state inheriting from the app abstract state declared in app.js. Notice how we are fetching a uri from the photolibrary and passing it as a parameter for the CropController. We must first call encodeURIComponent() on this uri to pass the value around. Otherwise ui-router get’s confused - loading CropController but failing to change the url or load the template.


'use strict';

app.factory('Camera', ['$q', function($q) {
  function cameraSuccess(imageURI, q) {
    // hack until cordova 3.5.0 is released
    if (imageURI.substring(0,21) === 'content://') {
      var photoSplit=imageURI.split('%3A');
  return {
    getPicture: function() {
      var q = $q.defer(); { cameraSuccess(imageURI, q); },
                                  function(msg) {
                                  }, {
      return q.promise;

In camera-service.js we’ve wrapped all calls to the cordova-plugin-camera in an agularjs service. This is a good solution until the Ionic Framework provides guidance on interfacing with cordova plugins. See How to use Cordova plugins ….


When brew punks out

26 March 2014 |

Today I was trying to upgrade all my brew kegs with brew upgrade. But it trips up on libiconv. You might try like I did and call brew with sudo but you get this message

Error: Cowardly refusing to `sudo brew upgrade`
You can use brew with sudo, but only if the brew executable is owned by root.
However, this is both not recommended and completely unsupported so do so at
your own risk.

Interesting, so now what? We could login as root but that might complicate things. What I did was give myself (a non-root user) access to the file. Like so

sudo su
chown <username> /usr/local/Cellar/libiconv/

Now that directory belongs to the current user and brew has no issues modifying that directory! sudo chown -R $USER /usr/local/include

Using github pages environment variables

05 March 2014 |

This method is now outdated. Github Pages now exposes the site.github namespace

I use jekyll with github pages to build this blog. I also use disqus for comments. You just have to add a code snippet into the page. Problem is when developing with jekyll I usually like to test how things look locally and then push the site to github pages. Which means whenever I look at a blog post I haven’t pushed, Disqus will create a thread like localhost:4000/something.html in addition to the intended one I asked around and found a jekyll plugin for environment variables. But github pages disables plugins. So I dug through the site variable on both production and github pages and found github pages sets GH_ENV which I haven’t seen documented anywhere. Now I simply do

{% if site.GH_ENV == 'gh_pages' %}
  < disqus snippet >
{% endif %}

to get the disqus thread generated only if the post is being viewed on github pages.

Changing the owner of a heroku app with S3 assets

24 February 2014 |

I recently had to migrate a Heroku app that was under my personal accounts, Heroku and s3, to another user. But this app also had assets under Amazon Web Services Simple Storage Service which made the process more complicated. You can use something like bucket explorer to manage S3 with a gui. I’ll show you how to do it with aws-cli. I’m assuming you installed it and you’re familiar with the commandline in general.

Since we are using more than one aws account we should use a config file to store both sets of credentials. See AWS configuring environment. Place your personal credentials under default and make another set for the recipient.


  [profile client001]

Remember to clear your env variables if you were using them before. aws-cli defaults to using the env variables if present, even if you pass the --profile argument.

Now you should be able to do aws s3 ls and get your file listing. And aws s3 ls --profile client001 and get the client’s files. If you are dealing with a small amount of data < 1TB we can simply copy the files to our local machine and then copy them back to the new bucket. For larger amounts I have no clue :(

aws s3 cp s3://mybucket/ . --recursive

Note aws-cli cp command doesn’t support matching by * so you have to use the --recursive flag. You can test what will happen if you run the command, with the --dryrun flag.

You can copy the files to the new bucket like so.

aws s3 cp . s3://new-bucket --profile client001 --recursive

Note you may have to specifiy --region some-region for some reason specifying the region in my config file didn’t work.

You have to set the heroku env variables to the new aws credentials using the heroku toolbelt

heroku config:set AWS_ACCESS_KEY_ID=new_blah
heroku config:set AWS_SECRET_ACCESS_KEY=new_blah
heroku config:set AWS_S3_BUCKET=new_blah

and just transfer it using heroku’s system.

Bash script for creating a bootable usb stick on OS X

26 January 2014 |

Many times you have to create a bootable usb stick on a mac. I always follow the instructions at How to create a bootable USB stick on OS X. I created a quick bash script that makes this process faster

 1 #!/bin/bash
 2 HELP_STR="please provide location of .iso"
 3 if [ "$#" -lt 1 ]; then
 4   echo $HELP_STR
 5 else
 6   echo "`diskutil list`"
 7   echo "==============="
 8   echo "enter disk to eject"
 9   echo -e ">> \c"
10   read word
11   echo "ejecting: $word"
12   echo "`diskutil unmountDisk $word`"
13   echo "copying $1 to $word note this may take a while and there won't be a progress bar"
14   echo "`sudo dd if=$1 of=$word bs=1m`"
15 fi

Gist on Github

Getting started with emberjs and phonegap (work in progress)

30 December 2013 |

Source code for this project can be found here.

The ember app kit is currently the defacto starting point for any ember project.

You’re going to have to learn a little grunt and bower. The getting started tutorial on the ember site is a good starting point. To add bootstrap, moment.js and showdown.js add them to the end of the dependencies section. Note, bower in the ember-app-kit installs to the vendor/ directory as opposed to the bower_components which is usually the default.

 1 {
 2   "name": "ember-app-kit",
 3   "dependencies": {
 4     "handlebars": "~1.1.2",
 5     "jquery": "~1.9.1",
 6     "qunit": "~1.12.0",
 7     "ember": "~1.3.0-beta.4",
 8     "ember-data": "~1.0.0-beta.4",
 9     "ember-resolver": "git://",
10     "ic-ajax": "~0.2",
11     "ember-testing-httpRespond": "~0.1.1",
12     "bootstrap": "~3",
13     "momentjs": "",
14     "showdown": ""
15   },
16   "resolutions": {
17     "ember": "~1.3.0-beta.4"
18   }
19 }

putting an “” empty string seems to work fine. Then reference these assets from index.html as normal.

The next deviation deals with how handlebars is setup. In the tutorial you see dale declaring <script type="text/x-handlebars"> and writing his handlebars stuff right there. With EAK the templating is put into the templates/ directory. With application.hbs wrapping the other templates.


 1 <div class="navbar navbar-default" role="navigation">
 2   <div class="navbar-header">
 3     <a class="navbar-brand" href="#">Bloggr</a>
 4   </div>
 5   <div class="collapse navbar-collapse">
 6     <ul class="nav navbar-nav">
 7       <li><a href="#">Posts</a></li>
 8       <li><a>About</a></li>
 9     </ul>
10   </div>
11 </div>
13 {{outlet}}

We then add the about resource to router.js

In the tutorial tom simply adds a posts var for our sample data fixture. In EAK there’s a api-stub mechanism. Let’s use that instead.

You’ll need to read (and probably re-read) Using Modules & the Resolver

How to disable subtitles in VLC by default

18 September 2013 |

VLC is my media player of choice. One of my only complaints is that it loads subtitles by default. It’d be really nice if you could have them off by default, with the option of loading them if you need them.

This is how you do that. Go to Preferences > Show All (in the lower left corner) > Video > Subtitles/OCD Here you’ll see some checkboxes. Uncheck Autodetect subtitle file.

And that’s that. You can still load subtitles manually by going to Video > subtitles track > Open file… Navigate to your subtitles file and it’ll be loaded.