Recent Posts

A Truly Minimum Viable Kitchen

published Feb 24, 2014

I read Matt Maroon’s Minimum Viable Kitchen post (and the ensuing Hacker News discussion) a while ago, and I’ve been thinking about it off and on since then.

Not about the post per-se, but about what a minimum viable kitchen was, and whether there was anything interesting in the concept.

In the original post, Matt goes into great detail on a huge list of things that are needed for a Minimum Viable Kitchen. It quickly becomes obvious that Matt is not a minimalist. The list includes things like a stand mixer, a scale, and a 10-piece pot and pan set. Nothing wrong with that. I own a stand mixer and a scale, and I use them all the time, but I certainly wouldn’t put them on my “dessert-island kitchen list”. I don’t own 10 pots and pans. I do agree that you need good quality ones, but 10 seems like a bit much, even for a non-minimal kitchen. I’d rather have the extra cupboard space.

Truly Minimal

So, let’s scale it back a bit. What is a truly minimalist kitchen, and what can you make with it?

I’m going to assume that you are living in a standard house that comes with a fridge, stove and oven. Let’s pretend you are just moving into your first place and have nothing else. What do you need to cook with? I’m going to ignore anything you use to eat, we’re just talking about getting food to the table here.

Okay how’s this for a first shot.

  1. A cutting board
  2. A chef’s knife
  3. Stuff to sharpen the knife (honing steel and sharpener)
  4. A 12” cast-iron frying pan with a lid
  5. A medium-sized pot
  6. A metal spatula and a metal spoon

With this and a few ingredients, you can make a lot of great meals.

  • A simple omelette with cheese, mushrooms and bacon
  • Broccoli and Beef Stir-Fry.
  • Roast Chicken surrounded by Onions and Garlic (Use the roasted garlic and drippings to make a gravy in the pan when the chicken is done.)
  • Chickpea curry with coconut sauce.
  • Rice pilaf
  • Fajitas
  • A frittata
  • This amazing Puerto Rican style Pork Shoulder
  • Pancakes
  • Home-fries
  • Corn Bread
  • Roasted beets on a bed of greens with fresh goat cheese, dressed with olive oil and balsamic vinegar

This is about as minimal as I can imagine. It’s almost viable, and probably would be fine for a while.

Why bother with a minimal kitchen anyways?

The whole point of this Minimum Viable Product (oops, sorry, kitchen) thing is to learn and learn quickly. So try this for a while and find out what you’re missing. Use all of your tools and listen carefully to yourself, and you’ll know what you’re missing. Think about what you’re making, what you can’t make that you’re craving, and what about your setup drives you crazy.

Do that for a while, and (carefully! cautiously!) buy a few things, and you’ll have a truly viable Kitchen.

No Excuses

published Apr 23, 2012

I wrote this in response to a post on HN. I could link to the post, but it doesn’t matter. There are posts like this all the time. Stop making excuses. Go build something.

This is going to sound more dramatic than it was, but here’s one way of summarizing the last five years of my life:

I was 35, working at a great job as a physicist. Amazing team (I was usually the dumbest guy in the room), amazing project, but I was bored. I knew that if this didn’t make me happy, I needed to get out. I read a few PG essays, caught the startup bug, and started coding in the evenings.

Within 8 months, with a brand-new daughter and another that was two, I was gone from that job, working on my own. In that 8 months I had taught myself web-dev from scratch.

I knew nothing of Ruby, HTML, CSS or JavaScript. I had a smattering of Unix knowledge and had been coding data-analysis in Python and C for a while, but the amount I had to learn was staggering. I bought tons of books, learned tons, and (luckily) had no idea how much I still had to learn.

The first startup idea (online graphing software for physicists – I didn’t exactly reach far for the idea) was a complete flop. That’s okay, though. I turned to consulting for a while. Gave some talks. Wrote part of a book. Met my co-founder by consulting for him for a while.

Now, things are good. Leanpub is growing steadily, and I couldn’t be happier.

The point is, that you can and should teach yourself some new skills. You’re way closer to being employable than I was, that’s for sure. It may take some evenings and weekends, but they’ll be some of the most fun evening and weekends you ever have. Find something that you want to do and build it. Fall in love with the idea, but be ready to dump it for something better.

The market for people with even a smattering of Rails knowledge is huge. iPhone dev is bigger. or Erlang. or fancy JavaScript using Socket.IO.

Location doesn’t matter. Age doesn’t matter (I’m 40 now, in Vancouver, not in SV, and I bet I could find 10 jobs at the drop of a hat). My blog isn’t huge. My startup hasn’t had “an exit”.

There are excuses, and there is getting out there and having a blast learning and making your life better.

Seems like an easy choice. Go kick some ass.

Getting up and running with Amber

published Dec 08, 2011

I was quite excited by Yehuda Katz’ announcement of Amber.js this morning. I had been intrigued by SproutCore, but hadn’t really liked how big it felt. So, when Yehuda said “If you played with SproutCore and liked the concepts but felt like it was too heavy, give Amber a try”, I listened.

The following is mostly just notes of what I learned. It’s not at all complete, but it should get you up and running and get you something to play with quickly.

Getting it on your machine

Assuming that you have git, Ruby 1.9.2 and a recent version of bundler installed, this is pretty straightforward. So, use rvm use 1.9.2 or the rbenv equivalent if you need to. These commands should do it:

    git clone
    cd amber.js
    bundle install
    rake dist

This will create sproutcore.js and sproutcore.min.js in the dist directory.

Creating Hello World

Now that we’ve got the Javascript files, we can make a new project skeleton for a hello world app. We want to end up with an helloworld.html file where we put our HTML, and a javascripts directory where we put some JS files to include.

mkdir hello_world
cd hello_world
mkdir javascripts
touch helloworld.html
cd javascripts
ln -s jquery-1.7.1.js jquery.js
ln -s <path-to-sproutcore.js>
cd ..

Okay, we’re all set now.

The first thing we’re going to do is create a SC application (it’s still called SC right now, presumably this will be renamed to Amber sometime soon) and a Planet model. We’ll then instantiate an instance of this model and show it off on the page.

Edit helloworld.html to look like this:

<title>Hello World</title>

<!-- JavaScript includes -->
<script type="text/javascript" src="javascripts/jquery.js"></script>
<script type="text/javascript" src="javascripts/sproutcore.js"></script>

<script type="text/javascript">
HelloWorld = SC.Application.create();

HelloWorld.Planet = SC.Object.extend({
  name: null,
  star: null,
  position: 0

HelloWorld.currentPlanet = HelloWorld.Planet.create({name: 'Earth', star: 'Sol', position: 3})


<script type="text/x-handlebars">
  Hello !



Let’s go through that step-by-step.

First, we load up jquery.js and sproutcore.js. Make sure to load jquery.js first or things will blow up.

Next, we set up our SproutCore (again, presumably soon to be Amber) application with

HelloWorld = SC.Application.create();

For now, I’m thinking of this as a name-space for the app.

Next, we make our Planet class.

HelloWorld.Planet = SC.Object.extend({
  name: null,
  star: null,
  position: 0

This sets up a planet with name, star and position attributes. The values of the hash are the default values.

Finally, we create an instance of a planet with HelloWorld.Planet.create, passing in a hash of attributes and assigning it to HelloWorld.currentPlanet.

That’s the end of the script.

Now comes the crazy part. We put a Handlebars template in the body tag, and it gets processed by Amber and stuck in to the DOM. The part inside the double-curly-braces gets replaced with what you would expect: the name of the planet we created. Also, it is bound to HelloWorld.currentPlanet, so any time the name of the planet changes, our view will change.

Play around with the demo.

Try opening up your JavaScript console and changing the name of the planet (hint: HelloWorld.currentPlanet.set('name', 'Venus')).

Hooking up a form

Okay, that’s useful, but we can’t expect our users to open up JavaScript consoles. Let’s hook our model up to a form.

To do this, we’ll create a view and a template. Notice that we’re taking a short-cut here and skipping the ‘C’ part of the MVC triumvarate. This is not a good idea, of course, but I’m getting tired and I don’t want to make this post too long.

The view is going to be a simple text field, so we’re going to extend SC.TextField. Put this at the bottom of your script block in the head of the HTML:

HelloWorld.PlanetNameView = SC.TextField.extend({
  insertNewline: function() {
    var value = this.get('value');
    if (value) {
      HelloWorld.currentPlanet.set('name', value);
      this.set('value', '');

And put this below the handlebars template in the body of the HTML:

<br />
<script type="text/x-handlebars">
Rename the planet: 

Here’s a demo to play around with.

I think that’s it for now. So far, this is looking pretty fun and magical.

Further Reading

If you’re intrigued, you can get more information from the Amber.js README and the SproutCore 2.0 Guides.

Speeding up Jekyll Generation

published Nov 18, 2011

One of the only complaints you’ll see out there about Jekyll is that when sites get bigger, it starts to slow down.

Luckily, this is easy to fix. Unfortunately, it’s apparently not obvious as you still see people complaining about it. Here’s my attempt at proselytizing for Jekyll :).

If you run jekyll --help, you’ll see that there’s a --limit_posts option. If you set this to 1, then you’ll only re-generate your most recent post when you save. This is usually exactly what you want. If you’re working on a slightly older post, then bump it up to 3 or 4.

Like this:

 jekyll --limit_posts 1

I’ve put this in a rake task

    namespace :jekyll do

      desc "start the jekyll server in auto mode"
      task :server, :num_posts do |t, args|
        num_posts = args[:num_posts]
        cmd = "jekyll --auto --server --pygments"
        cmd += " --limit_posts #{num_posts}" if num_posts
        puts "running #{cmd}"


So I can start Jekyll like this:

rake jekyll:server[1]

and only see the current post, and it’s blazing fast.

Opening up ports to your security group on EC2

published Nov 18, 2011

Say you have a cluster of EC2 instances that you want to be able to talk to each other, but you don’t want everyone in the world to be able to join in on the conversation. For example, I was just setting up a typical cluster of servers:

  • A rails app server
  • A DB server
  • A daemon server
  • A DB slave

I want all of these servers to be able to talk to each other over port 3306 (the MySQL port), but I don’t want the whole world to be able to connect over port 3306.

You need two things:

  1. A security group
  2. Your EC2 user id.

Assuming you have your ec2 command line tools set up already, here’s how you would do it. This will create a group called yoursecuritygroup with ports 22 (ssh), 80 (http) and 443 (https) open to the world, but with all other ports only open to other computers in the same security group.

$> ec2-create-group --description "yoursecuritygroup production" yoursecuritygroup
$> ec2-authorize yoursecuritygroup -p 22
$> ec2-authorize yoursecuritygroup -p 80
$> ec2-authorize yoursecuritygroup -p 443
$> ec2-authorize yoursecuritygroup -o yoursecuritygroup -u 1234-1234-1234

You need to add your user id here in place of 1234-1234-1234. You can find this by going to and scrolling to the bottom. You want your AWS Account ID.

Now when you spin up your instances, make sure to start them in the yoursecuritygroup group using the --group argument:

ec2-run-instances --key your-key --group yoursecuritygroup --block-device-mapping /dev/sda1=:100:false --instance-initiated-shutdown-behavior stop --disable-api-termination --instance-type m1.small  ami-a7f539ce

And you should be all set.