Notes on Cal Newport’s “Deep Work”

! Note ! Personal notes on Cal Newport’s “Deep Work”. They haven’t been cleaned up for public consumption.

Questions / Things to Research

  • How to ensure that the lead metric you’re measuring is correlated
    with the lag measure that you’re ultimately trying to affect?
  • If one switches disciplines, can one handle more than 4 hours of
    deep work? If so, how big must the switch in disciplines be? Would
    you have to, for example, switch from mathematics to art, or is
    switching from something like physics to programming sufficient?


  • Nicholas Carr. The Shallows
  • William Power. Hamlet’s BlackBerry
  • John Freeman. The Tyranny of Email
  • Alex Soojung-Kim. The Distraction Addiction
  • Antonin-Dalmace Sertillanges. The Intellectual Life
  • Daniel Coyle. The Talent Code
  • Mihaly Csikszentmihalyi. Flow
  • Dreyfus & Kelly. All Things Shining
  • Hunt & Thomas. The Pragmatic Programmer
  • McChesney et al. The Four Disciplines of Execution
  • Joshua Foer. Moonwalking with Einstein


Newport’s hypothesis is that “deep work”, characterized by operating
at or near peak mental performance, is simultaneously valuable but not
sufficiently pursued in modern society. The modern office and modern
network tools present frequent distractions that prevent deep work by
interrupting conscious attempts at long-term concentration and focus.
Strategies to facilitate more deep work in your own life are


Deep work := professional activities performed in a state of
distraction-free concentration that push your cognitive abilities to
their limit. These efforts create new value, improve your skill, and
are hard to replicate.

Historical examples of deep workers:
– Carl Jung : Bollingen Tower retreats
– Michel de Montaigne : private library in southern tower
– Mark Twain : summer in shed on farm in NY
– Bill Gates : “Think Weeks”, often in lakeside cottages

Shallow work := non-cognitively demanding, logistical-style tasks,
often performed while distracted. These efforts tend not to create
much new value in the world and are easy to replicate.

Some evidence suggests that spending enough time in a state of frenetic
shallowness permanently reduces your capacity to perform deep work.

Network tools – like SMS, IM, email, and FaceBook – negatively
impact deep work.

Newport’s hypothesis : there exist significant economic and personal
opportunity for those prioritizing deep work. Simultaneously, those
with the ability to perform it are rare.

Part 1 of the book supports Newport’s hypothesis
Part 2 of the book lists strategies to cultivate more deep work in
your own life

Newport hypothesizes a future economic trend: machines will displace
more varied types of workers.

Workers with innate protections: 1) high-skilled workers (able to work
with exceedingly complex machines); 2) superstars (the
best-of-the-best taking jobs away from local talent whilst being able
to work wherever they like); 3) owners (those who own the exceedingly
complex machines).

Core abilities to thrive in that future trend:
1. Ability to quickly master hard things
2. Ability to produce at an elite level (with regard to quality and

These core abilities fundamentally depend on deep work

Deliberate practice := specific form of practice:
1. attention focused tightly on specific skill you’re trying to
improve, or idea you’re trying to master
2. receive timely feedback so that you can adjust your approach

Bottom Line = to learn hard things quickly you must focus intently
without distraction (i.e. deep work)

Some anecdotes regarding deep work’s ability to foster elite-level
performance are discussed

Attention Residue := when switching from Task A to Task B, mental
baggage that sticks around from A that prevents full focus on B

Principle of Least Resistance := a tendency toward behaviors that are
easiest in the moment, without clear feedback of their impact on the
bottom line.

Evidence suggests that deep work and craftsmanship are more conducive
to contentment than aimless relaxation.

The Rules:

Rule #1 = Work Deeply

Evidence suggests that one is bombarded all day by desires to do
anything BUT focus on work.

Willpower is like a muscle with finite reserves; to best facilitate
deep work, add routines and rituals: remove willpower from the

Build a routine around a time and quiet location for deep work.

There are different approaches to deep work:
1. monastic : eliminate or radically minimize shallow obligations.
Adherents = { Donald Knuth, Neal Stephenson }
2. bi-modal : divide your time between deep work and shallow work on
particular timescales, e.g. day, week, season. Adherents = { Carl
Jung }
3. rhythmic : generate regular routine for deep work (e.g. the chain
method). Adherents = { Jerry Seinfeld }
4. journalistic : fit deep work in whenever you can. Adherents = {
Walter Isaacson }

It may be helpful to ritualize time, space, decor, etc. Also where
you’ll work, duration, how you’ll work once you start, and how you’ll
support your work (e.g. snacks).

A ritual that sticks may require iteration and initial commitment via
force of will.

It may be helpful to make a grand gesture to cement your ritual;
e.g. drive two towns over to their library.

Paradoxically, collaboration is useful – though not of the “open
office floor-plan” style. People need the chance for serendipity when
their minds are ready but to focus otherwise (e.g. a hub-and-spoke

Discipline #1 = Focus on the Wildly Important

“Focus on a small number of wildly important goals. Focus, not on
saying ‘no’ to trivial distractions, but ‘yes’ to the small number of
subjects that arouse terrifying longing and let them crowd out all

Discipline #2 = Act on the Lead Measures

lag measure := things you’re ultimately trying to improve; when you
measure them, though, the driving performance is already in the past

lead measure := the new behaviors that will drive success on the lag

E.g. academic success:
lag measure : published papers per unit time
lead measure : hours of deep work per unit time

Discipline #3 = Keep a Compelling Scoreboard

A public display of your lead measure (e.g. a scoreboard of deep work
hours per day, tallied up per week).

Discipline #4 = Create a Cadence of Accountability

Use a weekly review (a la Allen) in which you 1) plan the workweek
ahead; 2) review this past week’s metrics; 3) understand why the
metrics were what they were; and 4) set next week’s metrics goals

Be Lazy (vs. frenetic)

Kreider said: “Idleness is not just a vacation, an indulgence or a
vice; it is as indispensable to the brain as vitamin D is to the body,
and deprived of it we suffer a mental affliction as disfiguring as
rickets. The space and quiet that idleness provides is a necessary
condition for standing back from life and seeing it whole, for making
unexpected connections and waiting for the wild summer lightning
strikes of inspiration — it is, paradoxically, necessary to getting
any work done.”

Downtime aids insight : evidence suggests that subconscious mental
work lets one make objectively better decisions.

Downtime also helps recharge the energy needed to work deeply.
Downtime includes things like: walking in nature; listening to music
while making dinner; having a casual conversation with friends;
exercise; etc. It DOES NOT include things like quickly checking your

The work that evening downtime replaces is usually not that important.

Note that elite workers can typically manage roughly 4 hours of deep
work without recharge.

Once you’re done for the day, you must really be done. Try a shutdown
ritual. It should ensure that all open loops on your projects are
closed so that you know what you need to do to pick things back up
again. Otherwise your mind may not be able to fully let go. You
should end your shutdown ritual with some signal that signifies it’s
complete (e.g. simply saying “shutdown complete”).

Rule #2 = Embrace Boredom

The ability to concentrate intensely is a skill that must be trained.
Evidence suggests that people who multitask all the time can’t filter
out irrelevant information.

There are two focii:
1. Improving your ability to concentrate intensely
2. Overcoming your desire for distraction

Limit the number of context switches throughout the day.

Schedule internet time and keep the blocks outside of it free from its
use. If you need a piece of information just take note of it until
your next internet break. If it’s absolutely crucial, at least delay
it for 5 or 10 minutes to work against the craving -> reward cycle.

Schedule internet use at home, too.

You don’t need to use the internet while e.g. waiting in line at the
supermarket, either.

“Work Like Teddy Roosevelt”
1. Identify a deep task
2. Estimate how long you’d normally set aside to complete the task
3. Set a deadline that drastically reduces the time in 2.

“Meditate Productively”
Take a period in which you’re occupied physically (but not mentally)
and focus your attention on a single well-defined professional

Be wary of distractions and looping. Looping is when your mind
rehashes already defined or decided things to try to save energy.
When you notice that you’re distracted or looping, just gently note it
and get back on track.

Structure your deep thinking. Carefully review the relevant variables
and store them in your working memory. Define the specific next-step
question to address.

Memorize a deck of cards. Use the mind palace approach: do a
walk-through of 5 rooms in your house; build an association between
cards and objects; put those objects in your walk-through. Then, you
can walk through your filled house again and reproduce the deck.

Rule #3 = Quit Social Media

Make an honest assessment of network tools. What are their upsides?
What are their downsides? How do they support your primary goals?

Apply the law of the vital few to your internet habits
1. Identify the main high-level goals in your professional and
personal life
2. List 2 or 3 of the most important activities that help you satisfy
the goals
3. Consider the network tools you use. For each tool and goal
combination, determine its upsides, downsides, or neutral effects.

Don’t use the internet to entertain yourself. Put more thought into a
better plan for your leisure time. As stated earlier, evidence
suggests that contentment is better served by e.g. mastery of an
instrument than watching YouTube videos.

Rule #4 = Drain the Shallows

Ruthlessly identify shallowness in your current schedule, then cull it
down to a bare minimum.

Schedule every minute of your day. Use a piece of lined paper. Split
up the paper into all of the 30-minute blocks of your work day. Feel
free to reschedule as the day goes on. The schedule isn’t meant to
be something you slavishly devote yourself to; it’s meant to keep
track of deep and shallow work. You can batch task blocks together
(e.g. handle all of your email in a 30 minute block).

If you’re not sure if a task is shallow or deep, then quantify its
depth by determining how long it would take a smart, recent college
graduate to learn to do it. Bias your work toward complex tasks.

Ask your boss for a shallow work budget. Get his/her buy-in. If he
says 100% or “as much as necessary” of your time should be devoted to
shallow work than realize that this position does not value deep
work. Find a new position that values deep work more.

Finish your work at a set time (fixed-schedule productivity). When
you’re done, be done.

Be vague when turning down shallow commitments (don’t leave the door
open for the asker to weasel their way in).

Become hard to reach. Make people who send you email do more work.
Limit publicly accessible contact information. Enact a “sender
filter” (e.g. state the acceptable reasons to be contacted): this will
set peoples’ expectations regarding receiving a response.

Do more work when you send or reply to email. Try a process-centric
approach: 1) identify the relevant project; 2) determine the shortest
process to reach a successful conclusion.

Default to not responding! If the email or request is ambiguous,
doesn’t interest you, or if your participation or lack thereof has no
strong outcome one way or the other, just don’t respond.

Notes from the Introduction to Meteor.js Development Coursera

Course offered by University of London & Goldsmiths, University of London

Note : The version of meteor.js used in the course creates a simpler starter application than currently shipping versions

1 Course Home

Overview : learn how to create complete, multi-user web sites using the Meteor.js framework and MongoDB

2 Course Info

  • We’ll implement: user authentication, security features, reactive templates, and routing using iron router
  • We’ll carry out database operations: inserting, removing, updating, sorting, and filtering data
  • By the end of the course, we should be able to:
    • Install Meteor.js and create a template web app
    • Use the Meteor.js packaging system
    • Write Meteor.js templates that can reactively display data
    • Use MongoDB: insert, remove, and update operations
    • Use MongoDB filters to search for and sort data
    • Add user authentication functionality to a website
    • Control what is displayed on the page using iron:router
    • Implement basic security features
  • We’ll complete the following assignments:
    • A server install
    • A programming assignment
    • 4 quizzes
    • Practice quizzes
  • The course is built on top of material from two previous courses in the specialization. Prerequisites include basic HTML, CSS, and JavaScript

3 Grades

  • Each week has a quiz worth 12%
  • Each week has a peer-graded assignment worth 13%
  • Each week you need to review your peers for 13%
  • Oddly enough, this adds up to a good deal more than 100%
  • Week 1 has a grading lecture that correctly breaks things down Grading and Assessment Information (text)

4 Discussion Forums

  • Q : In grading, why does the total add up to more than 100%? Is it so you can get a perfect score without completing every assignment?
  • [2017-02-12 Sun] : checked the forums a bit, not much going on
  • [2017-02-19 Sun] : checked the forums a bit again, not much going on
  • [2017-02-28 Tue] : checked the forums a bit again, not much going on; submitted a question about DRYing out code
  • [2017-03-06 Mon] : checked the forums a bit again, not much going on; no answer to my previous question

5 Week 1

  • Estimated time = 4h 55m

5.1 Course Overview

5.1.1 Overview (video)

As per the overview: Meteor.js to build multi-user, interactive web apps

5.1.2 Course Outline (text)

As per the Course Info

5.1.3 Grading and Assessment Information (text)

  • After each lesson, there are practice quizzes
  • Practice quizzes don’t count towards your grade for the course
  • Grading breakdown:
    • Each quiz (x4) = 10%
    • Each peer assessment (x2) = 30%
    • Pass mark = 65%

5.1.4 Why Meteor? (text)

  • Applications in Javascript, CSS, and HTML – no other server-specific language required
  • Uses an adapted version of the handlebars template library (used in a previous course in the specialization)
  • Provides easy-to-install dev environment that includes a web server and a database server
  • Provides an easy-to-use packaging system
  • Provides reactive data sources with a distributed data model so that apps will feel snappy to multiple users
  • Includes the capability to generate native iOS and Android apps from the same Javascript code base
  • Implements an isomorphic model so that you can run the same code base on the server and the client
  • Apps can be deployed on any server with Node.js and MongoDB support

5.2 Introduction

5.2.1 Overview (video)

  • Get up and running with Meteor.js : install, get first app up and running, and check it out in the web browser; then explore templates; then add user interactivity

5.2.2 URL for This Module (text)

5.2.3 Code for this Module (text)

  • I downloaded the code
  • I installed meteor via the instructions on the meteor webpage
  • I ran meteor npm install
  • I ran meteor update --patch
  • I ran meteor et voila! Site available at localhost:3000

5.3 From One to Many Users

5.3.1 From one to many users (video)

  • Previous courses in this specialization have worked on sites for single users
  • Review of the stack so far: { HTML, CSS, Javascript + Templates, Data } -> Web Browser
  • New addition to the stack: the Server (with Meteor.js)

5.3.2 From one to many users (quiz)

  • Simple, 2-question quiz

5.4 Install Meteor

5.4.1 URL for this lesson (text)

5.4.2 Install Meteor (video)

  • Start by installing meteor, create a starter application, and run the application
  • You can create a folder to create your application within; in there, you’d use: meteor create <application_name>
  • If you use meteor create, it’ll create a boilerplate application

5.4.3 Install Meteor (quiz)

  • Simple, 2-question quiz

5.5 Editing a Template

5.5.1 URL for this lesson (text)

5.5.2 Editing a template (video)

  • Finding out what the boilerplate files out, and how to implement templates the Meteor way
  • Template = SpaceBars, derived from HandleBars
  • I never knew that you could use open ./ to open Finder in the current directory your terminal is in
  • What does {{> hello}} mean? Should review handlebars. {{ triggers the template; > hello means find the hello template and render it
  • <template name="hello"> ... </template>
  • You can use the inspector in chrome to see exactly what was sent to the browser
  • In meteor, a “public” folder in the web application folder will hold static assets

5.5.3 Editing a template (quiz)

  • Simple, 2-question quiz

5.6 Sending Data to Templates with Helpers

5.6.1 Sending data to templates with helpers (video)

  • Javascript -> HTML template
  • Tests for code running in client or in server
  • Template helpers send data to template
  • e.g. var image_data = { img_src: "laptops.jpg", img_alt: "some laptops" }; Template.images.helpers(image_data);
  • Then you could use {{> images}} and <img src="img_src" alt="img_alt" />
  • To pass an array in, you’d need to do something like Template.images.helpers({images:image_data})
  • Iteration via {{#each images }} ... {{/each}}

5.6.2 Sending data to templates with helpers (quiz)

  • Simple, 2-question quiz

5.7 Convert to a Bootstrap Grid

5.7.1 URL for this lesson (text)

5.7.2 Convert to a Bootstrap Grid (video)

  • Additional functionality provided via packages
  • Like brew, package, etc.
  • We want to install the Bootstrap package!
  • meteor search . will download and display the latest list of packages
  • meteor search twbs will display packages that match the twbs terms (like the Twitter Bootstrap package)
  • Packages are added on a per-application basis
  • In our application, we use meteor add twbs:bootstrap
  • We don’t need to edit anything, bootstrap will automatically be used
  • Meteor checks your HTML and won’t run the app unless it’s valid

5.7.3 Convert to a Bootstrap Grid (quiz)

  • Simple, 2-question quiz

5.8 Responding to User Actions

5.8.1 Responding to user actions (video)

  • Basic interactivity!
  • JS file where the “serious work” takes place
  • Add class to tag like class=”js-image”; might want to prefix interactive classes with js to indicate they’re not layout based
  •{'click .js-image':function(event){ ... }});
  • You can bind data and event listeners in templates
  • lets you access the HTML tag in the DOM
  • You can use jQuery-style e.g. $("width", "50px");

5.8.2 Responding to user actions (quiz)

  • Simple, 2-question quiz

5.9 Introduction to Meteor Summary

5.9.1 Introduction to Meteor Summary (video)

  • Brief recap

5.9.2 Introduction to Meteor Summary (quiz)

  • More substantial 10-question quiz
  • I filled the form out, but realized that I couldn’t submit it without paying

5.9.3 Peer-graded Assignment (assignment)

  • I haven’t upgraded, so I won’t be able to submit the assignment
  • I DID, however, DO the assignment
  • I downloaded Meteor on my Mac via curl | sh
  • I created my app via meteor create my_first_app, the resulting text in the console was:
        Created a new Meteor app in 'my_first_app'.   

        To run your new app:                          
        cd my_first_app                             
        meteor npm install                          
        If you are new to Meteor, try some of the learning resources here:                
        meteor create --bare to create an empty app.  
        meteor create --full to create a scaffolded app.
  • I ran the app via meteor (from within the app directory) and viewed it in my web browser by navigating to localhost:3000
  • It was crashing initially, I used meteor npm install --save babel-runtime and restarted my app with meteor et voila!
  • I edited the h1 tag in my application’s client/main.html file as per the instructions and reloaded my browser

5.9.4 Review Your Peers

  • I haven’t upgraded, so I won’t be able to review my peers

6 Week 2

6.1 Learning Objectives:

  • Create a mongodb collection
  • Use mongodb find and insert operations
  • Operate a Bootstrap modal from Meteor
  • Use 3rd party Meteor packages to add functionality

6.2 Introduction

6.2.1 Overview (video)

  • 3 key operations in using databases: insertion, update, and deletion
  • Using mongodb (built in with Meteor.js)

6.2.2 URL for this module (text)

6.2.3 Code for this module (text)

  • I downloaded the two zip files

6.3 Meteor Distributed Data Model

6.3.1 Meteor distributed data model (video)

  • Meteor apps are slightly different from most other web applications with respect to data models
  • Each user has their own local copy of the data: people will see data changes in pseudo-realtime
  • Changes by a user are propagated back to the central database (reactive)
  • Then propagations go back out to all other users

6.3.2 Meteor distributed data model (quiz)

  • Simple, 2-question quiz

6.4 Create a Collection of Images

6.4.1 Create a collection of images (video)

  • See the theory in practice: store image data in a database
  • In mongo, data are called collections
  • e.g. Images = new Mongo.Collection("images");
  • e.g. console.log(Images.find().count());
  • We can put starter data in the database
  • We can create a new file called startup.js
  • In startup.js, we check if we’re running on the server, if there’s nothing in the collection, we’ll add some starter data (but only when the app is starting up)
  • if( Meteor.isServer ){ Meteor.startup(function(){ etc. }); }
  • meteor reset from the command line will wipe all of your databases (!careful!)

6.4.2 Create a collection of images (quiz)

  • Simple, 2-question quiz

6.5 Better Start-Up Script, Removing Items From a Collection

6.5.1 Better start-up script, removing items from a collection (video)

  • The lecturer DRY’d out the previous startup.js code : loop to add images to collections
  • Next up : allow template to access the data
  • In image_share.js : we use Template.images.helpers({images:Images.find()})
  • Lecturer modified CSS file to style thumbnail (min & max height = 500px)
  • Lecturer went to template in image_share.html and added a “delete” button; class=”js-del-image btn btn-warning”
  • The “js-del-image” lets us know that we need to tie that to an event handler
  • In image_share.js, we enable the delete functionality via:{
        'click .js-image':function(event){
        $("width", "50px");
        'click .js-image-del':function(event){
        var image_id = this._id; // this refers to the data the template was displaying; _id is a unique identifier auto-added by mongo
        console.log( image_id );
        Images.remove({ "_id" : image_id }); // this is a mongo filter
  • We want to use some jQuery to better indicate to the user what’s happening when they click delete
  • We add the ID into the template : <div class="col-xs-12 col-md-3" id="{{_id}}">
  • Now, here’s how we hide the component :
        $("#" + image_id ).hide('slow', function(){
        Images.remove({ "_id" : image_id });
  • Note that we move the remove command into the hide function

6.5.2 Better start-up script, removing items from a collection (quiz)

  • Simple, 2-question quiz

6.6 Add An Image Rating Function: Updating and Sorting

6.6.1 URL for this lesson (text)

6.6.2 Add an image rating function: updating and sorting (video)

  • Let user rate images by setting the number of stars
  • Sort images so that highest-rated images are shown first
  • 1st : HTML to template (for rating widget); is there a package on atmospherejs? Yup!
  • To add the package, we use: meteor add barbatus:stars-rating
  • Then we add a sub-template below our image (the package has given us the template for free)
        {{>starsRating mutable=true class="js-rate-image" id=_id }}
  • _id is the unique id that mongo gives to the image; the star sub-template is within the image template, so we have access to the data from the images
  • Now we need to add the star ratings to the database
  • We’ll add an event listener{
        'click .js-rate-image':function(event){
        console.log("you clicked a star");
        var rating = $(event.currentTarget).data("userrating");
        var image_id =;
        Images.update({_id:image_id}, {$set: {rating:rating}})); // Images is the mongodb collection
        // Images.update takes two arguments: the ID of the image you want to change and the property / value that you want to change
  • this refers to the data in the template
  • Now let’s sort the images by rating in this client portion
        Images.find({}, {sort:{rating:-1}});

6.6.3 Add an image rating function: updating and sorting (quiz)

  • Simple, 2-question quiz

6.7 Implement Image Adding With A Bootstrap Modal

6.7.1 Implement image adding with a Bootstrap Modal, part 1 (video)

  • Allow users to add content directly into database
  • Add form as new template:
        {{> image_add_form }}

        <template name="image_add_form">
        <form class="js-add-image">
        <input type="text" name="img_src" />
        <input type="text" name="img_alt" />
        <button class="btn btn-success">save</button>
  • Next step, create an event listener so that the server does something when the user submits the form{
        'submit .js-add-image':function(event){
        var img_src, img_alt;
        img_src =; // not jQuery because it's a form so we have access to the data more readily
        img_src =;

        Images.insert( { img_src:img_src, img_alt:img_alt, createdOn:new Date() } );
        console.log("src: " + img_src + " alt: " + img_alt );
        return false;
  • By default, submit will overwrite console (return false prevents this)
  • From the user perspective, it might be confusing because the image went to the bottom of the list; we’ll use createdOn to help with this
        images: Images.find({}, 
        {sort:{createdOn: -1, rating: -1}})

6.7.2 Implement image adding with a Bootstrap Modal, part 2 (video)

  • The form should look a little bit nicer and be a little more interactive
  • We’ll convert the form to sit in a bootstrap modal so that he user can hit a button and the form will appear, then disappear when the user’s done with it
        <template name="image_add_form">
        <div class="modal fade" id="image_add_form">
        <div class="modal-dialog">
        <div class="modal-content">
                <div class="modal-header">
                <div class="modal-title">
                <div class="modal-body">
                <!-- form goes here -->
                <div class="modal-footer">
                <button class=""btn btn-warning" data-dismiss="modal">cancel</button>
  • This starts hidden, so we need to add a button to the images template
        <template name="images">
        <button class="btn btn-success js-show-image-form">add image</button>


        'submit .js-add-image':function(event){
        $("#image_add_form").modal('hide'); // or show?!
        return false;


        'click .js-show-image-form:function(event){
  • Should go onto the bootstrap site to style the form a bit better

6.7.3 Implement image adding with a Bootstrap Modal (quiz)

  • Simple, 2-question quiz

6.8 Databases and collections summary

6.8.1 Databases and collections summary (video)

  • Recap of week 2!

6.8.2 Databases and collections summary (quiz)

  • More substantial 10-question quiz
  • I filled the form out, but still can’t submit it without paying

6.8.3 Peer-graded Assignment : Siteace part 1 : edit an event and a template

  • Project will be called siteace
  • Project will be used in weeks 3 and 4
  • Project will become a site that allows users to add web pages they find interesting
  • Task this week = complete the implementation of some event code so that websites are saved to the database, edit a template to make website links click-able
  • I downloaded and unzipped the starter code
  • I ran meteor npm install --save babel-runtime in the folder
  • No errors!
  • I ran meteor in the folder
  • I haven’t upgraded, so I won’t be able to submit the assignment
  • I DID, however, DO the assignment
  • My main.js modification looked like this:
        'click .js-add-site':function(event){
        var url = $('#url_input').val();// get the form value using jquery...
        var site = {"url":url};// create a simple object to insert to the collection
        console.log("You need to put some code in here that calls insert on the Websites collection");
        return false;
  • My main.html modification looked like this:
        <li><a href="http://{{site.url}}">{{site.url}}</a></li>

I think I completed this assignment a little incorrectly:

  1. After adding the insert command, sites weren’t automatically showing up in the list, I think this is because I added site, which has a url sub-field instead of just adding url directly
  2. If you add sites without http[s], then it’ll automatically try to create a local link. I fixed this by prefixing the href with http. That’s brittle.

6.8.4 Review your peers : Siteace part 1 : edit an event and a template

  • I haven’t upgraded, so I won’t be able to review my peers

7 Week 3

7.1 Introduction

7.1.1 Overview (video)

  • Authentication!

7.1.2 Code for this module (text)

  • I downloaded the two zip files

7.2 User authentication with Meteor.js

7.2.1 User authentication with Meteor.js (video)

  • Allows a user to log in, and customize the experience for them
  • Standard feature for most websites
  • A few packages: most basic form = store user accounts in local database
  • meteor add accounts-ui accounts-password
  • accounts-ui : templates for typical user behaviors (log in, reminders)
  • accounts-password : handles database aspect (user records)
  • In image_share.html, we can add one of the templates we get with accounts-ui
        {{> loginButtons }}
  • We also get things like emails (on the test server, it’ll be printed to the console)

7.2.2 User authentication with Meteor.js (quiz)

  • Simple, 2-question quiz

7.3 Tidying up the design with a navbar

7.3.1 Tidying up the design with a navbar (video)

  • Housekeeping!
  • Place login functionality in navbar
        <nav class="navbar navbar-default navbar-fixed-top">
        <div class="container">
        {{> loginButtons}}
  • navbar-default : basic styling
  • navbar-fixed-top : will always be visible at the top of the page
  • Make sure navbar doesn’t lay over things:
        body {
        padding-top: 60px;

7.3.2 Tidying up the design with a navbar (quiz)

  • Simple, 2-question quiz

7.4 Accessing user information

7.4.1 URL for this lesson (text)

7.4.2 Accessing user information (video)

  • Dig deeper into user authentication
  • We can display the username via something like:
        <h1>Welcome to image share, {{username}}!</h1>
  • Doesn’t work, yet. Need to provide a template helper function. In image_js:
        return Meteor.users().emails[0].address;
        } else {
        return "anonymous internet user";
  • The template helper will run twice: as soon as meteor can (in which case the user object won’t exist yet, so it’ll error); and after a user’s logged in, it’ll update that template
  • The user will be able to see the anonymous internet user thing briefly
  • Next we want to only display the add image button when the user’s logged in:
        {{#if currentUser}}
        <button class="btn btn-success js-show-image-form">add image</button>
  • Normally, currentUser would have to be bound to a template, but Meteor binds it to every template for us

7.4.3 Accessing user information (quiz)

  • Simple, 2-question quiz

7.5 Customizing the user registration form

7.5.2 Customizing the user registration form (video)

  • Modifying the user registration form with a username
  • We can pass an argument into the account package to do so:
        passwordSignupFields: "USERNAME_AND_EMAIL"
  • Now we want to greet the user by their username instead of their email:
        username: function(){
        if( Meteor.user ){
        return Meteor.user.username;
        } else {
        return "anonymous internet user";

7.5.3 Customizing the user registration form (quiz)

  • Simple, 2-question quiz

7.6 Attaching users to images

7.6.1 Attaching users to images (video)

  • Attach a user account to an image so we know, for each image, which user uploaded it
  • In image_share.js:{
        'submit .js-add-image':function(){
        var img_src, img_alt;

        img_src =;
        img_alt =;

        if( Meteor.user ){
        img_src: img_src,
        img_alt: img_alt,
        createdOn: new Date(),
        createdBy: Meteor.user()._id;
        return false;
  • Javascript notion of truthy (e.g. non-false) and falsey (e.g. non-true, not usable data)
  • Now, we want to make sure the user information has been added, so we’ll display it in the image template:
        <div class="thumbnail">
        <div class="caption">
        <p>User: {{getUser createdBy}}</p>
        var user = Meteor.users.findOne({ _id:user_id });
        if( user ){
        return user.username;
        } else {
        return "anon";
  • We access users differently than images – even though both are collections – because Meteor handles users slightly differently (security, etc.)

7.6.2 Attaching users to images (quiz)

  • Simple, 2-question quiz

7.7 Filtering images by user

7.7.2 Filtering images by user (video)

  • Filter to control which images are being displayed (e.g. by a particular user)
  • Make username click-able (in template)
        <div class="caption"> 
        User: <a href="#" class="js-set-image-filter">{{getUser createdBy}}</a>
  • Add event listener in Javascript{
        'click .js-set-image-filter':function(event){
        Session.set("userFilter", this.createdBy);
  • Session is a reactive data source that allows us to store temporary variables in key-value pair format
        if( Session.get("userFilter") ){
        return Images.find({createdBy:Session.get("userFilter")}, {sort: {createdOn:-1, rating:-1}});
        } else  {
        return Images.find({}, {sort: {createdOn:-1, rating:-1}});

7.7.3 Filtering images by user (quiz)

  • Simple, 2-question quiz

7.8 Removing the image filter

7.8.1 Removing the image filter (video)

  • No new techniques here: just more examples of previously used ones

7.8.2 Removing the image filter (quiz)

  • Simple, 2-question quiz

7.9 Infinite scroll

7.9.1 Infinite scroll (video)

  • Load data as needed
  • Simplest way of implementing an infinite scroll in the image gallery
  • Want to capture a scroll event from the browser; hard in the standard meteor way
  • We’ll use some slightly hacky jQuery; we also want to limit the initial number of images we show:
        if (Meteor.isClient) {

        Session. set("imageLimit", 8);
        lastScrollTop = 0;

        var scrollTop = $(this).scrollTop();

        // test if we're near the bottom of the window
        if( $(window).scrollTop() + $(window).height() > $(document).height() - 100 ){
        // test if we are going down
        var scrollTop = $(this).scrollTop();
        if (scrollTop > lastScrollTop ) {
        Session.set("imageLimit", Session.get("imageLimit") + 4 );
        lastScrollTop = scrollTop;


        return Images.find({}, {sort:{createdOn: -1, rating: -1 }, limit:Session.get("imageLimit")});

7.9.2 Infinite scroll (quiz)

  • Simple, 2-question quiz

7.10 User authentication summary

7.10.1 User authentication summary (video)

  • Recap of week 3!

7.10.2 User authentication summary (quiz)

  • More substantial 10-question quiz
  • I filled the form out, but still can’t submit it without paying

7.10.3 Peer-graded Assignment : Siteace part 2 : user authentication

  • I downloaded and unzipped the starter code
  • I ran meteor npm install --save babel-runtime in the folder
  • I haven’t upgraded, so I won’t be able to submit the assignment
  • I DID, however, DO the assignment
  • I found the assignment very straightforward and not very challenging

7.10.4 Review your peers : Siteace part 2 : user authentication

  • I haven’t upgraded, so I won’t be able to submit the assignment

8 Week 4

8.1 Introduction

8.1.1 Overview (video)

  • Find out how to deploy sites; “hack” into our own sites to examine security problems; implement security; routing

8.1.2 Code for this module (text)

  • I downloaded the two zip files

8.2 How to organize your code

8.2.1 How to organize your code (video)

  • As application grows, having all your code in one file becomes hard to maintain
  • We can set up special folders which the framework knows about
  • public folder used for public / static assets (e.g. images)
  • client and server are two more folders that meteor knows about
  • client folder would contain all of the info in the Meteor.isClient block
  • server folder would contain all of the info in the Meteor.isServer block
  • I think Meteor applications are set up like this by default now
  • You can use shared that will have files in use on both (but it’s not a special folder by default)
  • Collections are shared, so both client and server need access to them
  • Other special folders:
    • private only server needs to see them and it needs to use the assets API to access them
    • tests is just a playground and it won’t be sent to the client or the server

8.2.2 How to organize your code (quiz)

  • Simple, 2-question quiz

8.3 Hack into your site!

8.3.1 Hack into your site! (video)

  • Topic = basic security!
  • Some examples of behavior that users shouldn’t have access to (e.g. using the Javascript console to delete all the images in the image database)

8.3.2 Hack into your site! (quiz)

  • Simple, 2-question quiz

8.4 Make your site more secure

8.4.1 URL for this lesson (text)

8.4.2 Make your site more secure (video)

  • Securing your application : the basics
  • By default, Meteor puts a package in that helps you get up-and-running, but isn’t necessary for us
  • We use meteor remove insecure to remove the “insecure” package
  • By default, you’re then stopped from doing certain things with the database (e.g. adding pictures)
  • We create a lib folder; things in lib will be run first; it’s run on BOTH the client and server
  • We can put a collections.js file in there, along with security information:
        Images = new Mongo.Collection("images");

        // Set up security
        insert:function(userId, doc){
        if (Meteor.user()){
        doc.createdBy = userId; // force the image to be owned by the current user
        if( userId != doc.createdBy ){ 
        return false; }
        else {
        return true;
        } else {
        return false;
        remove:function(userId, doc){
        if (Meteor.user()){
        return true;

8.4.3 Make your site more secure (quiz)

  • Simple, 2-question quiz

8.5 Tidy up the project

8.5.1 Tidy up the project (video)

  • Cleaning up!
  • E.g. server doesn’t need any CSS or HTML files, so we make sure they’re all in the client folder
  • E.g. we can get rid of if (Meteor.isServer) if it’s in the server folder; ditto with client

8.5.2 Tidy up the project (quiz)

  • Simple, 2-question quiz

8.6 Routing with iron:router

8.6.1 URL for this lesson (text)

8.6.2 Routing with iron:router (video)

  • Adding a new feature: routing
  • Routing allows you to control which components of the application are shown at any given time
  • meteor add iron:router
  • We can define different places that the user can visit in the application, and we can define different things that’ll be displayed at each point
  • We’ll create templates to simplify things: e.g. for the navbar, etc:
        <template name="navbar">
  • The body tag will be empty; we’ll modify our routes
        Router.route('/', function() {

        Router.route('/images', function() {
  • Next up, rendering multiple templates into a single page

8.6.3 Routing with iron:router (quiz)

  • Simple, 2-question quiz

8.7 Better routing

8.7.1 Better routing (video)

  • Welcome page, single image, and back again using routing and templates
  • In main.js:
        layoutTemplate: 'ApplicationLayout' // default template for layout is ApplicationLayout

        Router.route('/', function() {
        this.render('welcome', { to: "main" });

        Router.route('/images', function() {
        this.render('navbar', { to: "navbar" });
        this.render('images', { to: "main" });

        Router.route('/image/:_id', function() {
        this.render('navbar', { to: "navbar" });
        this.render('image', { to: "main", data: function(){ return Images.findOne({_id:this.params._id}); }});
        <template name="ApplicationLayout">
        {{> yield "navbar" }}
        {{> yield "main" }}

        <template name="welcome">
        <div class="container">
        <div class="jumbotron">

        <template name="image>
        <div class="container">
        <a href="/images"><img class="single-img" src="/{{img_src}}" /></a>
  • Routes will make the browser back/forward buttons work properly

8.7.2 Better routing (quiz)

  • Simple, 2-question quiz

8.8 Security and routing summary

8.8.1 Security and routing summary (video)

  • Recap of week 4!

8.8.2 Security and routing summary (quiz)

  • More substantial 9-question quiz
  • I filled the form out, but still can’t submit it without paying

8.8.3 Peer-graded Assignment : Siteace : implementing discussions

  • I downloaded and unzipped the starter code
  • I ran meteor npm install in the folder
  • I haven’t upgraded, so I won’t be able to submit the assignment
  • I DID, however, DO the assignment
  • I found the assignment very straightforward and not very challenging

8.8.4 Review your peers : Siteace : implementing discussions

  • I haven’t upgraded, so I won’t be able to submit the assignment

Game Development Resources

Communities / Forums

Game Jams


Uncategorized Links

Developing Flex Applications on a Chromebook


In addition to a Ruby on Rails web application, SongLynx also has an Apache Flex component.  As SongLynx’s technical founder, being able to develop Flex applications is a primary requirement for my computer.  This post is the third in a series detailing how I set up a web development environment on a Samsung XE303C12 Chromebook.  The first post, which you can read here, describes why I needed to do so, as well as getting a Linux environment with Ruby on Rails, Emacs, Git, and PostgreSQL set up so that I can work on projects stored in Git repositories on BitBucket and push the changes to a live site hosted on Heroku.  The second (much shorter) post, located here, details how I configured Emacs more to my liking.  This post details how I set up the Apache Flex SDK and integrated it into my workflow.  My goals are:

  • Download and install SDK
  • SDK Setup (Command-line Access, etc.)
  • Editor Setup (An Emacs Editing Mode)
  • Hello World and Test in Chrome under ChromeOS

Downloading and Installing the SDK

Installing and configuring the Apache Flex SDK proved to be a lot more difficult than I originally anticipated.  I think there were several things at work: 1) there are a couple of “official” places to get the SDK, and they each have conflicting instructions; 2) the community has invested a decent amount of time and effort to get things running, but many of those posts have become outdated; and 3) support for Flex-allied technologies is not uniform across operating systems — Adobe’s AIR, for example, is no longer supported on Linux.  At any rate, on with the show.

Note: the instructions that follow are distilled from a fair amount of dead-ends; I’ve tried to ensure that I’ve untangled the various leads I followed and have only presented what’s necessary, but I can’t be sure that’s the case.

The first thing I did was download the SDK from its GitHub repository [1], navigated inside the directory, and switched branches:

git clone
cd flex-sdk
git checkout develop

I followed the README in the cloned repository (also available at the GitHub repository webpage) pretty closely; it seemed to work where the instructions on the Apache Flex web page and in Apache’s Wiki did not.  That being said, I think that some of the instructions are presented out-of-order; for example, telling you to set environment variables for packages that you don’t have yet seems a little odd.

The next thing I did was install the necessary additional packages: a legacy version of Adobe’s AIR SDK, an Adobe Flash Player content debugger, an Adobe Flash Player, Apache Flex Text Layout Framework, Apache Flex BlazeDS, Ant, and a Java SDK.

Note: I started in the directory /home/bill/Documents/workspace/flex.  workspace is where I keep subdirectories like ror and flex with sub-subdirectories for each of my projects.  Some packages we install below expect to be in the same parent directory as the Flex SDK; if you don’t do that, you need to set some additional environment variables.

Adobe’s AIR SDK

mkdir air-sdk
mv AdobeAIRSDK.tar air-sdk/
cd air-sdk/
tar -xvf AdobeAIRSDK.tar
cd ..

Flash Player Content Debugger

mkdir flashplayer-debugger
mv flashplayer_11_sa_debug.i386.tar.gz flashplayer-debugger/
cd flashplayer-debugger/
gunzip flashplayer_11_sa_debug.i386.tar.gz 
tar -xvf flashplayer_11_sa_debug.i386.tar 
cd ..

Flash Player

mkdir playerglobal
cd playerglobal/
mkdir 11.1
cp playerglobal11_1.swc 11.1/playerglobal.swc
cd ..

Apache Flex Text Layout Framework

git clone flex-tlf
cd flex-tlf
git checkout develop
cd ..

Apache Flex BlazeDS

git clone flex-blazeds
cd flex-blazeds
cd ..


sudo apt-get install ant

Java Development Kit

sudo apt-get install openjdk-7-jdk

Miscellaneous Configuration & Building

Then I needed to create ANT_HOME and JAVA_HOME environment variables and add them to my path.  I added the following code to the end of my ~/.bashrc file:

### Added by me to install Apache Flex 
export ANT_HOME="/usr/share/ant" 
export JAVA_HOME="/usr/lib/jvm/java-1.7.0-openjdk-armhf" 
export PATH="$PATH:$ANT_HOME/bin:$JAVA_HOME/bin"

Next, I moved into the flex-sdk directory and set up and environment properties file:


I added the following lines (you’ll see the start of each line commented out waiting for you to uncomment and fill it in).  Note that you’ll need to replace “bill” with your username.


Then, I built the SDK with

ant main

And I also built the the ASDoc tool with

ant asdoc-package


Command-Line Access

Next, I added the Flex SDK that I just compiled to my path, so that I needn’t specify the location of mxmlc every time I want to compile a program.  To do so, I added the following code to my .bashrc file:

### Added by me for access to the Flex command-line tools
export FLEX_HOME="/home/bill/Documents/workspace/flex/flex-sdk"
export PATH="$PATH:$FLEX_HOME/bin"

Emacs Configuration

I installed a mode for actionscript via M-x package-install RET actionscript-mode and adding the following to my ~/.emacs file:

;;===== Flex specific ===== 
;;(setq auto-mode-alist (append (list \
;; '("\\.as\\'" . actionscript-mode) \
;; '("\\.\\(xml\\|xsl\\|rng\\|xhtml\\|mxml\\)\\'" . nxml-mode) \
;; ;; add more modes here \
;; ) auto-mode-alist))

When I open a .mxml, it’ll use nxml-mode.  When I open a .as, it’ll use actionscript-mode.

End-to-End Test

Now that the SDK is installed, we’ve got access to the utilities from the command line without specifying the full path, and we’ve made editing our code in Emacs a little easier, I wanted to perform an end-to-end test.  I started by creating a simple Flex project:

cd ..
mkdir test-project
touch helloWorld.mxml

Then, I put the following code into helloWorld.mxml:

<?xml version="1.0" encoding="utf-8"?> 
<s:Application xmlns:fx="" 
               xmlns:mx="library://" width="640" height="480"> 
    <s:BasicLayout /> 
  <s:Label text="Hello World!" horizontalCenter="0" verticalCenter="0" /> 

After, I built the application from within its directory with:

mxmlc helloWorld.mxml

Finally, I copied it to my ~/Downloads folder and tested it in Chrome under ChromeOS.  Success!

Loose Ends

The steps I’ve described thus far give you sort of a minimally acceptable Flex development environment under Linux.  There are some loose ends that could be tied up to improve the experience, but I haven’t had time to track them all down.  Here’s a (non-exhaustive) list:

  • An Emacs editing mode that’ll properly account for files with both MXML and ActionScript components in them.  I think you could tinker with some of the existing multi-mode packages to do this — like mumamo, polymode, or multi-mode.
  • Having the SDK installed in a user directory is probably less than ideal.  I probably should have built it in /usr/local.
  • I haven’t been able to get the flash player debugger to work.  With simple projects it’s not such a big deal: you can build and then test under ChromeOS, but for projects where you actually need to debug, you might be in trouble.
  • I haven’t yet built or modified projects of any appreciable complexity; it’s probably a pain to build them unless you use Ant.


If you’ve followed along, at this point you should be able to develop and test Flex applications on your Samsung XE303C12.  There are definitely things that can be improved, some of which I’ve listed in the Loose Ends section above.


  1. apache / flex-sdk.  Retrieved 2016-05-03.
  2. tgrk / .emacs.  Retrieved 2016-05-03.



Basic Emacs Customization


After I set up a basic development environment on my Samsung XE303C12 Chromebook (details in this previous post), I wanted to customize my Emacs installation to better fit my workflow (Ruby on Rails web development, in particular).  Here’s the list of things I did:

  • Set up MELPA
  • Installed a theme (flatland-black)
  • Added a mode (web-mode)


I use MELPA (in addition to ELPA) to manage my Emacs packages.  I really don’t have an opinion on the MELPA vs. Marmalade debate: once upon a time I used MELPA and it’s worked for me, so I haven’t put any more thought into it.  For the base installation of Emacs installed via apt-get, I couldn’t find any of the common initialization files: no .emacs, no .emacs.d/init.el, and no site-start.el.  I made a .emacs file in my home directory and added the following, cribbed from [1], to enable MELPA packages:

(require 'package) ;; You might already have this line 
(add-to-list 'package-archives 
             '("melpa" . "")) 
(when (< emacs-major-version 24) 
 ;; For important compatibility libraries like cl-lib 
 (add-to-list 'package-archives '("gnu" . ""))) 
(package-initialize) ;; You might already have this line

A New Theme

After getting MELPA working, I wanted to install a new Emacs theme.  I like light-on-dark themes and syntax highlighting for editing code and text, so I wanted a theme that offered those things.  I’ve used flatland-black in the past, so I decided to go with that again this time.  I suppose if I ever switch to Sublime Text I’ll be in good shape, as this is a port of one of its themes for Emacs.  I installed the theme from within Emacs via:

M-x package-install RET flatland-theme

Where M indicates the meta-key (alt, typically) and RET indicates you press enter/return and it’ll prompt you for input; in this case, it wants the package name you’d like to install.

I then edited my .emacs file to have the theme load on startup by adding the following to the end (after the MELPA block we added earlier):

(load-theme 'flatland-black t)

Additional Modes

Emacs is installed with a bunch of modes, but editing embedded ruby files (.erb) is pretty painful without an additional mode.  I use web-mode [2], which supports a bunch of other types of embedded parts/blocks, like CSS and JavaScript.  I tried to install it from within Emacs via M-x package-install RET flatland-theme, but it failed.  I had to install it via:

M-x package-list-packages

package-list-package opens a mini-buffer with a list of all the packages available in the repositories told Emacs it can look in.  Then, I paged down to web-mode, selected it, switched to the newly opened mini-buffer that shows some details about it, and chose install.  I opened a .erb file and used M-x web-mode RET to ensure that the mode loaded correctly.

After I was sure that the mode worked, I edited my .emacs file so that web-mode would automatically be started when I opened embedded Ruby (and some additional) files;  The following is cribbed from [2]:

(require 'web-mode)
(add-to-list 'auto-mode-alist '("\\.phtml\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.tpl\\.php\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.[agj]sp\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.as[cp]x\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.erb\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.mustache\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.djhtml\\'" . web-mode))


If you’ve followed along, you’ve got easy access to a lot more Emacs packages from its package manager (thanks to MELPA), you’ve installed a nice theme, and you’ve added a new mode to handle embedded Ruby files (or embedded CSS, JavaScript, etc.). Even if you don’t like flatland-black or don’t want to use web-mode, you can modify the instructions in the latter two sections to install a theme or mode of your choice that better fits your workflow; in particular, you can use reference [3] to browse for a theme that fits your preferences and find out if it’s available from MELPA.


  1. [MELPA: ] Getting Started.  Retrieved 2016-04-30.
  2. web-mode.el.  Retrieved 2016-05-01.
  3. Emacs Themes.  Retrieved 2016-05-01.

Alienware Busted; Chromebook to the Rescue!


My new-ish — I bought it in late January — Alienware laptop conked out on me.  It won’t POST: the logo has a light but neither the fan nor the screen start.  I bought it at Microcenter, so I took it back there to the support center.  They’re sending it to Dell for repair: unfortunately it’s going to take 10 – 14 (!) business (!) days (!) to get it back.  In the interim, all I’ve got is my old, busted up MacBook Pro that the Alienware replaced (late-2011, cracked trackpad, etc.) and a Samsung XE303C12 Chromebook (circa late-2012).  I decided to try to set up a development environment on the aforementioned Chromebook, as the MBP is nightmarish to use unless I can plug in external peripherals (especially a mouse); that makes it pretty much only useful as a desktop.

This post chronicles the trials and tribulations of setting up a reasonable web development environment on the Chromebook.  Honestly, in retrospect, I probably should have just used a cloud-based development environment like or set up a cheap AWS micro instance and tailored it to my liking, but I like the added flexibility of being able to work offline.  I think I’m also probably cheap.  Here were my goals with this project, broken up into bite-sized pieces:

  • Clone a Ruby-on-Rails project from my BitBucket repository
  • Make modifications to said RoR project (preferably with my favorite editor, Emacs)
  • Test my modified RoR project locally in an environment as close as possible to a Heroku dyno
  • Push the modifications back to my BitBucket repository
  • Push the modified project to Heroku

The Samsung XE303C12

I can’t remember how much this thing originally cost me; it looks like the MSRP was $250USD when it was released, so probably close to that.  Right now, it’s available on Amazon for about $180USD; note that there’s a newer (and probably much more capable) model available at pretty much the same price.  Unsurprisingly, things have come a long way since 2012-2013.  😉

Here’s the spec sheet for the little Chromebook that could:  It’s got an Exynos 5 Dual processor,  a Samsung-designed implementation of the ARM Cortex-A15, 2GB of RAM, 16GB of eMMC storage, and an 11.6″ 1366 x 768 screen.  TL/DR?  It’s sort of slow, doesn’t have all that much memory, has a relatively small amount of slow(er) storage, and has a little screen.  I made specific choices with respect to the development environment to try to account for these shortcomings.

I should also note that I actually do enjoy using it, despite what I said above about its specifications.  I think the keyboard’s nice for the form-factor (it omits a lot of extraneous keys).  It’s also really light and the battery life is decent.

Setting up a Linux Environment

There are (at least) 2 ways to go about getting a Linux environment on a Chromebook: 1) ChrUbuntu and 2) Crouton.  ChrUbuntu will give you a full-fledged dual boot whereas Crouton runs side-by-side with ChromeOS.  I went with the latter because anecdotal evidence seemed to suggest that it was easier to set up.  I also haven’t maintained a full-blown Linux distribution on a laptop since college (early 2000’s) and my difficulty with it then colors my perception even now; that experience was probably my fault as I stubbornly insisted on using Slackware instead of one of the “beginner” distros.

The GitHub page for Crouton is here (; it’s got detailed instructions about things like enabling developer mode, downloading Crouton, and running it.  I also made heavy use of reference [3] (see below).  The particular command of interest for my setup was:

sudo sh ~/Downloads/crouton -r trusty -t audio,cli-extra,core,extension,keyboard,xfce,xiwi

That’ll install Ubuntu Trusty Tahr with the XFCE window manager, integration with ChromeOS tabs, and a few extras.  The Unity desktop is available, but given the specs I listed above, I thought I’d go with something more light-weight.  Note: this step takes awhile.

Initial Setup: Emacs, Git, Ruby, Rails, Etc.

Because I’ll be deploying my application to Heroku, I wanted an environment as similar to a Heroku dyno as possible for development and testing.  That means PostgreSQL instead of MySQL, among other things.

The first thing I did after starting XFCE4 was install emacs (gotta edit those config files somehow):

sudo apt-get install emacs

I also created ~/.bash_aliases and added alias emacs=”emacs -nw” because I dislike the default behavior of opening a new window for emacs; I also think the X version is ugly.

I realized that man wasn’t installed by default (?!), so I installed that as well with sudo apt-get install man.

Next, I installed Ruby, Rails, etc.  I mostly followed [4] here, so I started by installing the dependencies.  This is as per [4]: I didn’t prune out the MySQL or SQLite installations.  I also didn’t install PostgreSQL yet; I did that later.

sudo apt-get update
sudo apt-get install git-core curl zlib1g-dev build-essential libssl-dev libreadline-dev libyaml-dev libsqlite3-dev sqlite3 libxml2-dev libxslt1-dev libcurl4-openssl-dev python-software-properties libffi-dev

I’m using rbenv to manage versions.  Again, following [4]:

git clone ~/.rbenv
echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc
echo 'eval "$(rbenv init -)"' >> ~/.bashrc
exec $SHELL

git clone ~/.rbenv/plugins/ruby-build
echo 'export PATH="$HOME/.rbenv/plugins/ruby-build/bin:$PATH"' >> ~/.bashrc
exec $SHELL

git clone ~/.rbenv/plugins/rbenv-gem-rehash

rbenv install 2.3.0
rbenv global 2.3.0
ruby -v

gem install bundler

Next, I set up Git per [5]:

git config --global color.ui true
git config --global "YOUR NAME"
git config --global ""
ssh-keygen -t rsa -b 4096 -C ""

Note:  you’ve got to replace “YOUR NAME” and “” with … well … your name and email address, respectively.  Then, I went to my BitBucket account and added the new key with “Chromebook” as the label.  Finally, I tested my setup by successfully cloning my repository to my local machine.

I continued to set up Ruby on Rails.  I needed to install NodeJS (dependencies!  CoffeeScript, Asset Pipeline, etc.) and Rails.

curl -sL | sudo -E bash -
sudo apt-get install -y nodejs
gem install rails -v 4.2.6
rbenv rehash
rails -v

Getting Ready for Heroku

As I mentioned before, my end-goal was to deploy an application to Heroku.  To support that, I wanted my local development environment to match a Heroku dyno as closely as possible.  Thus, I needed PostgreSQL; I set that up next:

sudo sh -c "echo 'deb precise-pgdg main' > /etc/apt/sources.list.d/pgdg.list"
wget --quiet -O - | sudo apt-key add -
sudo apt-get update
sudo dpkg-reconfigure locales
sudo apt-get install postgresql-common
sudo apt-get install postgresql libpq-dev
sudo apt-get install postgresql-client

sudo service postgresql start

sudo -u postgres createuser YOURNAME -s
sudo -u postgres psql
postgres=# \password YOURNAME

The wget command above threw a warning near the end that I didn’t explore further.  I think it impacted my ability to get v9.5.  My slightly modified commands install v9.3.  The apt-get install postgresql-client was required to fix an “Error: You must install at least one postgresql-client-<version> package.” error.  The last line will provoke a prompt to set a password for your PostgreSQL user.

Setting up PostgreSQL proved to be the most difficult part thus far.  The commands I entered above are the end-result of beginning with the references listed below and additional iteration and Google-Fu to fix problems that cropped up.

At this point, I tested out my install by creating a new rails app, modifying config/database.yml (username & password and adding template: template0 to the default environment — otherwise you’ll get an error about an encoding mismatch when you try to create the database via rake db:create), running rails server, and checking the connection via Chrome in ChromeOS.

Next, I installed and configured the Heroku Toolbelt [8] via

wget -O- | sh
heroku login

The Heroku Toolbelt lets one provision dynos for an app, check their status, run commands on them, and push code to them — all from the command line.

End-to-End Test

Now that I’ve got everything installed, I performed an end-to-end test.  I created a new sample repository in my BitBucket account, cloned that repository to my Chromebook, modified that repository (by creating a Ruby on Rails application in it), pushed my changes back to BitBucket, pushed my changes to Heroku, and checked the live application on Heroku.

I created the repository in my BitBucket account via BitBucket’s web interface.  Then I set it up on my local machine, added a text file, and pushed it back to BitBucket:

mkdir sample-heroku-app
cd sample-heroku-app/

git init
git remote add origin
echo "Bill Mason" >> contributors.txt
git add contributors.txt 
git commit -m 'Initial commit with contributors'
git push -u origin master

After this, I backed up one directory and used the rails generator via rails new sample-heroku-app –database=postgresql.  I modified config/database.yml with my development environment credentials (including that template note above).  I then made a new controller via rails generate controller welcome, added an index page at app/views/welcome/index.html.erb, and added the corresponding route to config/routes.rb.  I also created the database with rake db:create.  Finally, I tested it locally by starting up the server (rails server) and connecting via Chrome in ChromeOS.

Next, I made the modifications necessary to deploy the application to Heroku.  I added rails_12factor in the Gemfile under the production environment, and ran bundle install.  I also wanted to ensure that my local environment and Heroku were running the same Ruby version.  I checked mine with ruby -v and added ruby ‘2.3.0’ to the end of the Gemfile.  Then, I committed the files and pushed them to BitBucket.

Now it was time to deploy.  I started by creating an app on Heroku via heroku create from the top-level directory of my application.  Then I pushed the application via git push heroku master and migrated the database via heroku run rake db:migrate.  Then, I visited the application in Chrome under ChromeOS (the application location will be listed in the push command; it might look something like



Now that I’ve got a fully functional environment, I backed it up.  To do so, I needed to log out of it (though not out of ChromeOS) and used sudo edit-chroot -f ~/ -b trusty, where trusty was the name of my setup.  I then moved the resulting .tar.gz to the ~/Downloads/ directory so that I could upload it to Google Drive.  This’ll let me more easily restore my working system if something goes wrong; after all, Chromebooks seem to like to “powerwash” the machine to factory settings if they run into problems.


If you followed along, at this point you should (hopefully) have a fully functional development environment capable of creating a Ruby on Rails application, editing it, pushing it live via Heroku, and putting it under source control via Git — all on your Samsung XE303C12.  This post might also serve as a starter in case you want to set up your XE303C12 to run Linux for something else.  Not bad for a little Chromebook, eh?


  1. Getting Started with Rails 4.x on Heroku.  Retrieved 2016-04-28.
  2. Heroku Postgres.  Retrieved 2016-04-28.
  3. W.  Thomas.  Chromebook for Web Development.  Retrieved 2016-04-28.
  4. Setup Ruby On Rails on Ubuntu 14.04 Trusty Tahr.  Retrieved 2016-04-28.
  5. Set up SSH for Git.  Retrieved 2016-04-28.
  6. Crouton Command Cheat Sheet.  Retrieved 2016-04-28.
  7. [Crouton] Keyboard.  Retrieved 2016-04-28.
  8. Heroku Toolbelt.  Retrieved 2016-04-29.

Kickstarter : Interesting Projects (2016-03-20 Edition)

Who doesn’t like browsing through new Kickstarter projects?  There are always a good share of unique products and services in the making.  Here are the most interesting ones I found when I took a look on March 20, 2016.

Disclaimer: It’s hard to keep on top of all the new projects being released, even if you check regularly.  The ones I’m interested in are often focused in categories like Comics, Games, and Technology.  I’m always on the lookout for people that round up interesting projects in other categories.

MovieSwap (Technology)

I think this is a pretty unique idea.  MovieSwap acts as a sort of warehouse that keeps your movies (anywhere from 1 movie to all of them).  Once MovieSwap has your DVDs, you can swap for other DVDs that you want to watch (which are then played over the net for you).  On the upside, you can always get your DVDs physically sent back to you.  On the downside, swaps you make are permanent: i.e. you’re not temporarily lending a stranger your DVD, you’re trading one of yours for one of theirs (potentially through an intermediary).  I’d assume that a service like this would run into legal trouble, but I guess there’s some precedent for it, at least in Europe.  Another downside is that you’ve got DVD-quality media.

Yfel’s Cavern (Games)

Skill trees, crafting, leveling, etc.  What’s not to like?  The animation is smooth.  The art (in a static sense) doesn’t quite grab me the way that Rogue Legacy or Nuclear Throne did, but it’s nice.

CONNEX-cable (Technology)

I’m not sure if it’s the most creative universal data cable, but it’s nice: avoid getting them tangled, decent length, sort of stylish.  The cost doesn’t even seem exorbitant (compared with, say, Apple’s in-house cables).

NAZ : A Historical Horror Comic (Comics)

Sounds like a mash-up between John Carpenter’s The Thing and a zombie movie.  I enjoy the art style, too.

Books I’d Like to Read

Until now, I didn’t have a canonical place to keep the list of books I’d like to read.  As a result, I have lists everywhere: text files on my computer, paper notes hidden in various folders in my desk and bookshelves, Scribbleton wiki entries, etc.  From now on, this’ll be my reference location.

  • Dweck, C.  Mindset.  (Saw it on Bill Gates’ list of favorite books he read in 2016)
  • Brooks, D.  The Road to Character.  (Saw it on Bill Gates’ list of favorite books he read in 2016)
  • Boye, K.  Kallocain.  (Referenced in 1984 wikipedia article)
  • Burgess, A.  1985.  (Referenced in 1984 wikipedia article)


  • As I find the other lists, add the entries to this list and delete/trash them
  • Add the 2016 reading list books to this list

In Search of a Template for a Game Design Document

Note: this post is currently in a rough form while I collect reference material, draft, and revise.


I’ve had a long-time interest in Game Design & Development.  Over the years I’ve even made a few terrible ones that will probably never see the light of day.  Most recently, I took a couple of courses related to game design & development on Coursera: “Introduction to Game Design” by California Institute of the Arts and “Introduction to Game Development” by Michigan State University.  The latter was mostly focused on the practical: the nuts-and-bolts of setting up Unity and making a few simple games.  The former was mostly focused on the theoretical: the necessity of balancing difficulty to modulate player frustration and keep them interested.  We even made several paper-based games, the descriptions of which served as simple game design documents.  If/when I get around to it, I may digitize my notes from both courses and upload them here.

I’ve been interested in finding a decent template that I can use (and modify to expand, if necessary) for video games.  It’s been in the back of my head for some time; this post is my attempt to get it out of there so I don’t use so many intermittent cycles on it anymore.  I put together a template in Google Docs which I expect to modify as I gather more experience in game design and development.  The template can be found here:


To-Do List:

  • Find examples of Game Design Documents from Indies and Major Studios (particularly of games I know so that I can see how the documents relate to the final product)

Game Design Document Template Links:


Reading Goals/Process for 2016

I love to read, but it’s often a “feast or famine” proposition for me.  I’m prone to suffering from analysis paralysis, and I feel that a healthy love for reading can become excessive/obsessive and feed into that (or be a form of procrastination that’s at least more socially acceptable than binging an entire series on Netflix over the course of a weekend).  I set a goal of reading 12 books this year, with a maximum of 25; that’s between one per month to roughly one every two weeks.  That’s on top of my usually daily reading of science, design, development, and general news articles.

I’ve decided to start with Tim Ferriss’ “The 4-Hour Workweek”.  Below you’ll find my list of other potential reads for this year.  It’s roughly sorted at the top.  It’s also subject to change (from simple reordering, all the way to adding or removing items).  I’ll also be checking in every so often to determine whether or not this process is achieving my goal of moderation in my level of reading.  One other approach I’ve been considering is shooting for a quantity of time reading per {day, week, whichever} rather than specifying the quantity of books.  I’ve got to let that idea marinate a little more, but I wanted to get a basic plan in place that can be modified later.  After all, “the key to success is to start”, yeah?

  • Ferriss, T.  The 4-Hour Workweek
  • Rowling, J. K.  Harry Potter and the Sorcerer’s Stone
  • Hunt & Thomas.  The Pragmatic Programmer
  • Catmull, E.  Creativity, Inc
  • Rogers, S.  Level Up
  • Aristotle.  Nicomachean Ethics, Politics, Rhetoric, or Poetics
  • Csikszentmihalyi, M.  Flow
  • McConnell, S.  Code Complete
  • L’Engle, M.  A Wrinkle in Time
  • Camus, A.  The Stranger
  • Rowling, J. K.  The Harry Potter series
  • Dostoevsky, F.  The Brothers Karamazov
  • McCarthy, C.  The Road
  • Plato.  The Republic
  • Lucretius.  On the Nature of Things
  • Aurelius, M.  Meditations
  • Alighieri, D.  The Divine Comedy
  • Machiavelli, N.  The Prince
  • Hobbes, T.  Leviathan,
  • de Spinoza, B.  Ethics
  • Milton, J.  Paradise Lost
  • Gibbon, E.  The Decline and Fall of the Roman Empire
  • Kant, I.  Critique of Pure Reason
  • Hegel, G. W. F.  The Philosophy of Right
  • Marx, K.  Capital
  • Voltaire.  Candide
  • Nietzsche, F.  Beyond Good and Evil
  • Russell, B.  The Problems of Philosophy
  • Heidegger, M.  What is Metaphysics?
  • Whitehead, A. N.  An Introduction to Mathematics
  • Hsieh, T.  Delivering Happiness
  • Ries, E.  The Lean Startup
  • Blank, S.  Four Steps to the Epiphany