Hi, I'm Richard Caceres, a Developer, Designer, and Musician. 

As of January 2016, I'm a software engineer at the Internet Archive. Previously I helped build Cargo Collective and worked on many great websites with OSK Studio and Use All Five. I also co-created wowlist.org. And last but not least, there are also a handful of open source projects and libraries under my name on Github.

I'm born, raised, and currently live in the San Francisco, Bay Area.

Follow me on Twitter, or send me an

This website is a hybrid blog and portfolio. Scroll down to see what I have been up to.

Google Frightgeist

Every day, over 3 billion searches take place on Google, and Google Trends gives us an unparalleled look at what the world is searching for. Google News Lab puts that data to use — from powering insightful journalism to helping you pick out your Halloween costume.

For this fun Halloween microsite for the Google Creative Lab, my role was to take raw data from the Google Trends team and process it to produce an JSON api for the frontend. During the week leading up to Halloween, the site was featured on the homepage of Google.

Site: https://frightgeist.withgoogle.com
Agency: Use All Five
Launch Date: Oct 20, 2015
Technologies: Google App Engine, Python, JSON

Android Experiments

Android was created as an open and flexible platform, giving people more ways to come together to imagine and create. Developers everywhere have used the unique capabilities of the platform to push the limits of what’s possible on phones, tablets, watches and beyond.

Android Experiments is a website by Google designed to showcase the creative possibilities of the Android platform.

This was my first project working together with both Use All Five and the Google Creative Lab. My role was to build the CMS and API that powered the frontend. At the Creative Lab's request, the backend was written in the Go programming language.

Site: https://www.androidexperiments.com
Agency: Use All Five
Launch Date: August 12, 2015
Technologies : Google App Engine, Go, Polymer

Google News Lab

Google News Lab is a website designed to help journalists learn the best ways to use Google tools for reporting and storytelling.

I was brought onto this project, because of my knowledge of Python and Django. Django turned out to be a really great fit allow us to rapidly develop and evolve and content management system and API.

It was easy to add features such as converting the CMS and API to have translations in over a dozen languages.

The application runs on Google App Engine and utilizes Google Cloud Storage and Google Cloud SQL.

Site: https://newslab.withgoogle.com/
Agency: Use All Five
Launch Date: June 19, 2015
Technologies : Google App Engine, Cloud SQL, Cloud Storage, Memcache, Django

Announcing this timeline

This website is a hybrid blog and portfolio. As someone with a diverse set of interests, a timeline is the best way to catalog my output. The filters showcase my different hats, but when it comes to it, everything I do is bound by myself and the passage of time.

Also, check out the about page.

Announcing django-cache-decorator

I have been using Django for over two years, and I have grown to love the rich feature set it comes with. Yes, there's a lot one ends up not using, but it is great that these things are there for when one needs it. It's worth noting that these extra features do not cause a performance impact. Django can be stripped down and is capable of returning < 10ms responses.

Django offers many interfaces with swappable backends. For example you can use the same ORM functions for interacting with Postgres or Mysql. Or you can send Email directly from the server or via a commercial service like SendGrid (3rd party). Or you can choose from a variety of cache backends: In-memory, Memcache, or Redis (3rd party).

And once one has experience with the Django framework, it is really quick to develop web applications. These are all reasons why it's compelling to invest further into Django.

I have put together a simple python package to make it easy to add caching to any function in a django project. It's called django-cache-decorator.

Installation

pip install django-cache-decorator  

Example Usages

from django_cache_decorator import django_cache_decorator

@django_cache_decorator(time=0)
def geocodeGoogleAddressJson(location):  
   """Cache indefinitely until cache is reset or expired"""
   ...


@django_cache_decorator(time=500, cache_key="TagManager:popularTags")
def popularTags(self):  
   """Cache for 500 seconds. Specify a custom cache key"""
    ...


@django_cache_decorator(time=0, cache_type='redis')
def reverse_geocode(lng, lat):  
   """Cache indefinitely with redis backend"""
   ...

How it works

When the @django_cache_decorator is applied to a function, it'll cache the results of that function. If no cache_key is passed, a cache key will be generated automatically from the function name and the arguments. See the function cache_get_key for details.

The decorator also supports the argument cache_type to specify which backend to use.

Ex Machina

In April 2015, I worked on the websites for the critically acclaimed film, Ex Machina.

Ex Machina Official Website - I helped implement the desktop and mobile site.

Ava Sessions - I added the feature to Geocode the user locations with GeoIP and show contextual weather information. I implemented the backend API that received image uploads from the client and created various thumbnails and uploaded them to Amazon S3.

I also helped architect and implement the mobile website. Since the desktop site was built with React, it was possible to create a separate root component that reused but differently composed components from the desktop site.

Most credit, however, is due to Osk Studio for their design and coding.

Using polling to update an EmberJS Route's model

On a website where content is updated frequently, it is useful to have theses updates show up to other users without them having to press refresh.

A robust solution would be to use web sockets or a full library like OrbitJs. But a really simple solution is to just use polling.

Ember-Data models have a reload method which reloads itself from the server (see reload. It's really easy to wrap this call into a polling mechanism (setInterval). This works great when you just want to update one model (ie /posts/123). And then it's nice to package this into a mixin that can be added to any route.

Here's the code.

mixins/polling-route-model.js

import Ember from 'ember';

export default Ember.Mixin.create({  
  /**
   Property to store the interval
   */
  polling_model_interval: null,

  /**
   Create the polling interval
   */
  activate: function() {
    this._super();
    this.clearInterval();
    var self = this;
    this.polling_model_interval = setInterval(function() {
      var obj = self.get('currentModel');
      if(
          obj.get('isLoaded') 
          && ! obj.get('isDirty') 
          && ! obj.get('isSaving')
          && ! obj.get('isDeleted')
          && ! obj.get('isError')
          && ! obj.get('isNew')
          && obj.get('isValid')
      ) 
      {
        obj.reload();
      }
    }, 20000);
  },

  /**
   Destroy the polling interval on deactivate
   */
  deactivate: function() {
    this._super();
    this.clearInterval();
  },

  /**
   Helper to clear the interval
   */
  clearInterval: function() {
    if(this.polling_model_interval) {
      clearInterval(this.polling_model_interval);
    }
  },
});

routes/post.js

import Ember from 'ember';  
import PollingRouteModel from "../mixins/polling-route-model";

export default Ember.Route.extend(PollingRouteModel, {  
  // your route code
});

I designed and built this wooden keyboard stand. It's designed so that the final height of the keybed is the exact height of a Steinway Grand Piano (28 1/8").

Announcing a Puppet module for Dokku

I am excited to announce that I published a Puppet module for installing Dokku. Dokku is a great tool for easily hosting and deploying projects. It's basically a copy of Heroku that can be installed on Ubuntu 14.04. I recommend Digital Ocean for $5 a month.

With Puppet and this module, you can declaratively install Dokku.

Links:
- https://forge.puppetlabs.com/rchrd2/dokku
- https://github.com/rchrd2/puppet-dokku

Installation

puppet module install rchrd2-dokku  

Usage

node web {  
  # install dokku
  class {'dokku':
    version => 'v0.3.12',
  }

  # install dokku plugins
  dokku::plugin { "dokku-rebuild":
    source => "https://github.com/scottatron/dokku-rebuild.git",
    version => "master",
  }
  dokku::plugin { "dokku-pg-plugin":
    source => "https://github.com/rchrd2/dokku-pg-plugin.git",
    version => "master",
  }
}

https://github.com/rchrd2/puppet-dokku

How to install Ghost with NPM and Dokku

Today I installed Ghost, a blog app, on my very own server!
I installed it with dokku, a mini Heroku clone.


Installation notes

On the server, create an app

dokku apps:create blog  
dokku config:set blog NODE_ENV=production  

Turns out it worked best to install Ghost via npm, because it's already built.

I have it installed, but I need to setup a shared directory.

On the server, add the shared directory

dokku docker-options:add blog "-v /home/dokku/blog/shared:/app/shared"  
dokku docker-options blog  

So... I needed to modify Ghost and things got crazy. Turns out the npm package isn't directly what is in the repo. It contains the built files. So I had to build the files and add those to my fork (in a branch). After that, it worked!

Nice! It works! Hallelujah!

What's really nice is I have a repo that only has the bare minimum to run ghost plus a theme.

It looks like this:

/themes
   /casper
config.js  
index.js  
package.json  
README.md  

Code samples

package.json

{
  "name": "blog",
  "version": "0.0.1",
  "description": "blog.rchrd.net",
  "main": "index.js",
  "dependencies": {
     "ghost": "rchrd2/Ghost#package"
  },
  "devDependencies": {},
  "scripts": {
    "start": "node index",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "Richard Caceres",
  "license": "ISC"
}

index.js

var path = require('path');  
var ghost = require('ghost');

ghost({  
    config: path.join(__dirname, 'config.js')
}).then(function (ghostServer) {
    ghostServer.start();
});

config.js

var path = require('path'),  
    config;

config = {  
  production: {
      url: 'http://blog.rchrd.net',
      mail: {},
      database: {
          client: 'sqlite3',
          connection: {
              filename: path.join(__dirname, '/shared/content/data/ghost.db')
          },
          debug: false
      },

      server: {
          host: '0.0.0.0',
          port: '5000'
      },
      paths: {
          contentPath: path.join(__dirname, '/shared/content/'),
          themePath: path.join(__dirname, '/themes')
      }
  },
  development: {
      url: 'http://localhost:2368',
      database: {
          client: 'sqlite3',
          connection: {
              filename: path.join(__dirname, '/content/data/ghost-dev.db')
          },
          debug: false
      },
      server: {
          host: '127.0.0.1',
          port: '2368'
      },
      paths: {
          contentPath: path.join(__dirname, '/content/'),
          themePath: path.join(__dirname, '/themes')
      }
  } 
}

// Export config
module.exports = config;