strugee.net

Posts from 2017

Show only posts from January February November December March April May June August October

From static to Stratic - part 1

So a couple days ago I published generator-stratic@1.0.0-beta.1 to npm. Since Stratic is now officially in beta, I thought I'd write up a guide to converting a regular, static site to a Stratic-powered blog.

Each step in this blog post (part 1 of 2[?]) will take you closer to having a fully-functional blog, but because of Stratic's decoupled design, you can work through them at your own pace. Each step will leave you with a functional environment (i.e. nothing will be "broken" such that you can't work on your website anymore).

You can see the steps in this post in action at straticjs/static-to-stratic. Each commit corresponds to a step in this post.

Let's get started!

Initial setup

The site we'll be converting is currently pretty simple. It has an index.html and a projects.html. Each of these includes /css/main.css and /js/main.js. Also, they both have a navigation section and a footer that are duplicated across each page. Each time Alyssa P. Hacker - the website's owner - makes a change to these (for example to fix the copyright year in the footer), she has to change both HTML files. The best way for her to add a new page will be to copy an existing HTML file and then change it. This is a little unideal.

Alyssa tracks her website on GitHub (in the example repository mentioned above). Here are links for the index.html and the projects.html we'll be working with.

Here's a visual of the project layout:

% tree .
.
├── css
│   └── main.css
├── index.html
├── js
│   └── main.js
└── projects.html

2 directories, 4 files

When Alyssa needs to preview her website, she manually runs http-server ..

Since Alyssa uses GitHub she publishes her website on GitHub Pages, so her website is in the master branch of her git repository. (Here we're assuming that the repository is called aphacker.github.io or something, instead of static-to-stratic.)

In addition to adding blog support, we'll improve Alyssa's website by reducing duplication while still allowing her to publish to GitHub Pages.

Step 1 - adding gulp

Before we do anything else, we need to add a build system. Stratic is designed to work with [gulpjs][], so that's the one we'll be using.

Adding gulp is super easy. First, we need to create a package.json, so we do npm init:

% npm init
This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sensible defaults.

See `npm help json` for definitive documentation on these fields
and exactly what they do.

Use `npm install <pkg> --save` afterwards to install a package and
save it as a dependency in the package.json file.

Press ^C at any time to quit.
name: (static-to-stratic)
version: (1.0.0)
description: Personal website of Alyssa P. Hacker
entry point: (index.js)
test command:
git repository: (https://github.com/straticjs/static-to-stratic.git)
keywords:
author: Alyssa P. Hacker <alyssaphacker@example.net>
license: (ISC) AGPL-3.0+
About to write to /Users/alex/Development/static-to-stratic/package.json:

{
  "name": "static-to-stratic",
  "version": "1.0.0",
  "description": "Personal website of Alyssa P. Hacker",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/straticjs/static-to-stratic.git"
  },
  "author": "Alyssa P. Hacker <alyssaphacker@example.net>",
  "license": "AGPL-3.0+",
  "bugs": {
    "url": "https://github.com/straticjs/static-to-stratic/issues"
  },
  "homepage": "https://github.com/straticjs/static-to-stratic#readme"
}


Is this ok? (yes) yes

A couple things to note here: in general, the defaults are fine to accept. We've provided a description and an author, but these are optional since this isn't actually going to be published on the npm registry. They're just kind of nice to have.

The same goes for the license, which in this case is the Affero GPL 3.0 or above - however, as the copyright holder you are of course free to choose whatever license you want. (Or no license, although I'd discourage you from doing that.)

Once we have a package.json, we can go ahead and install gulp and another module we'll need, ecstatic:

% npm install --save-dev gulp ecstatic

If you haven't used gulp previously, you'll also need to install gulp-cli:

% npm install -g gulp-cli

At this point, we'll need to move some files around. Now that we have a build system, we can organize our repository however we want instead of putting stuff exactly where we want it in production.

You can do this however you want. The organization that you'll find most projects using, though, is to put stuff in a src directory. Let's make that right now.

% mkdir src
% git mv *.html src
% git mv css src/styles
% git mv js src/scripts

Finally, create a file named gulpfile.js and put the following in it:

var gulp = require('gulp'),
    http = require('http'),
    ecstatic = require('ecstatic');

gulp.task('build:html', function() {
    gulp.src('src/*.html')
        .pipe(gulp.dest('dist'));
});

gulp.task('build:css', function() {
    gulp.src('src/styles/*')
        .pipe(gulp.dest('dist/css'));
});

gulp.task('build:js', function() {
    gulp.src('src/scripts/*')
        .pipe(gulp.dest('dist/js'));
});

gulp.task('watch', ['build'], function() {
    gulp.watch('src/*.html', ['build:html']);
    gulp.watch('src/styles/*', ['build:css']);
    gulp.watch('src/scripts/*', ['build:js']);
});

gulp.task('serve', ['watch'], function() {
        http.createServer(
                ecstatic({ root: __dirname + '/dist' })
        ).listen(8080);
});

gulp.task('build', ['build:html', 'build:css', 'build:js']);

gulp.task('default', ['serve']);

This gives us a pretty good starting point. This gulpfile defines a couple tasks that simply copy source files into dist. The watch task watches for changes and rebuilds when they occur, and the serve task starts up a server, replacing Alyssa's usage of http-server. This provides exactly the same workflow as before: Alyssa runs one command and then she can look at her site on localhost:8080. You can use different task names if you want (for example, html instead of build:html, etc.), but these are what generator-stratic gives you.

However, there's one problem: Alyssa can't deploy her site anymore. If she pushed like this, visitors would have to visit e.g. https://aphacker.github.io/src/projects instead of https://aphacker.github.io/projects! That's no good.

In order to rectify this, we'll create a new git branch, src. src will contain the source files, and we'll put the final, built site in master, which is what's served by GitHub Pages. So:

% git checkout -b src
% git push --set-upstream origin src

Great. Now, we need to add something to put the built files (i.e. the contents of dist) in master. We'll use the gh-pages module for this. First install it and a dependency we'll need:

% npm install --save-dev gh-pages gulp-util

Next, make it available in the gulpfile by adding a line at the end of require() statements:

var gulp = require('gulp'),
    http = require('http'),
    ecstatic = require('ecstatic');

And finally, add a deploy task somewhere in the gulpfile:

gulp.task('deploy', ['build'], function(done) {
    ghpages.publish(path.join(__dirname, 'dist'), { logger: gutil.log, branch: 'master' }, done);
});

Now whenever Alyssa wants to deploy a new version of her website, she just runs gulp deploy and it'll be taken care of for her. (ProTip™: change the default branch to src on GitHub. That way visitors and new clones see the source files, not the build files generated by a program.)

The very last thing we need to do is add a .gitignore file since we're installing Node modules and have a build directory now. We'll just use GitHub's, adding a line for dist/ at the end:

% curl https://raw.githubusercontent.com/github/gitignore/master/Node.gitignore > .gitignore
% echo "\ndist/\n" >> .gitignore

Now we've got a functionally equivalent development setup based on gulp. Success!

Step 2: converting HTML to Pug

The next step is to convert the HTML to Pug. Pug (formerly known as Jade) is a language that compiles to HTML. It lets you do useful things like inherit from a common layout as well as looping over JavaScript variables. If you're not familiar with Pug, you should go take a look at its syntax now.

The easiest way to do this conversion is to get a program to do it for you. Here's the one I used way back when; you may be able to find a better one. The generated Pug will be valid but not the prettiest - you may want to wait to clean it up since we're going to do some work to reduce the duplication soon.

Once you've got the converted Pug, you should rename the relevant HTML file to have a .pug extention, then replace the contents with the Pug. Do this for each HTML file.

The last step here is to make gulp build the Pug. Install gulp-pug:

% npm install --save-dev gulp-pug

Then add pug = require('gulp-pug') to the end of the var declaration at the top of your gulpfile. Finally, change your html task to look like this:

gulp.task('build:html', function() {
    gulp.src('src/*.pug')
        .pipe(pug({pretty: true}))
        .pipe(gulp.dest('dist'));
});

We'll also need to fix the watch task so it has:

gulp.watch('src/*.pug', ['build:html']);

which will watch Pug files instead of HTML files.

That's it! Alyssa's site is now building with Pug instead of HTML.

Step 3: splitting out the layout

Pug's looping and flow control constructs will be very useful to us later on, but we can get some immediate productivity wins by splitting out the site layout so it's not duplicated across every Pug file.

There's one tricky thing about this: the navigation is mostly the same between pages, but not quite - the page the user is currently on shouldn't be a link. We'll solve this by using a block directive for each link. That way, we can override just what needs to be changed, while introducing no duplication.

You'll have to figure out exactly what parts of your personal layout make sense to be split out. In Alyssa's case, there are three main things that are mostly or fully duplicated across pages:

  1. The navigation bar
  2. The footer
  3. Invisible metadata and script/style includes

These are what we'll split out. First, we'll make a copy of index.pug and put it in src/includes/layout.pug. (Again, you can organize your files however you want - but in projects generated by generator-stratic, utility Pug files go in src/includes.) Next, edit out the page-specific content and replace them with block directives. Finally, edit each navigation bar item so it has its own block directive, leaving the old code as the default for the block directive.

Here's what this looks like when we do this to Alyssa's site:

doctype html
html
  head
    meta(charset='UTF-8')
    link(href='/css/main.css', rel='stylesheet', type='text/css')
    block head
  body
    block heading
    nav
      ul
        block nav-homepage
          li
            a(href='/') Homepage
        block nav-projects
          li
            a(href='/projects') Projects

    block body

    footer
      p &copy; Copyright 2016 Alyssa P. Hacker.
    script(src='/js/main.js', type='text/javascript')

Note how I've replaced the h1 element (the contents of which vary per-page) with block heading, I've added a block head directive so we can specify the title per-page, I've made a block for each navigation link so we can override them if we want to individually (otherwise they'll have the default of being a link), and I've added block body for the main content. I've also cleaned out a bunch of the cruft the automatic converter put in there.

Now, we can edit index.pug so that it inherits from layout.pug - we'll use the extends keyword for this. Then we just fill in the content we want using block. Here's what this looks like after we're finished with Alyssa's site:

extends includes/layout.pug

block head
  title Alyssa P. Hacker's homepage

block heading
  h1 Alyssa P. Hacker's homepage

block nav-homepage
  li Homepage

block body
  p This is the homepage of Alyssa P. Hacker. You can check out the projects I've worked on #[a(href='/projects') here].

You'll note that I've cleaned out some cruft here, too. We have one last thing to fix: if we change the layout, nothing will get rebuilt. We can fix this by changing the watch task again so that the line for watching Pug files reads:

gulp.watch(['src/*.pug', 'src/includes/*.pug'], ['build:html']);

Sweet! index.pug is way shorter than what we had before and includes just the content now. We can do the same thing to projects.pug. Then Alyssa can, for example, correct the copyright year in layout.pug - i.e., once - and that change will go into both index.html and projects.html. I've gone ahead and made the change for her.

To give a high-level overview, here's what Alyssa's site looks like now:

% tree -I node_modules .
.
├── dist
│   ├── css
│   │   └── main.css
│   ├── index.html
│   ├── js
│   │   └── main.js
│   └── projects.html
├── gulpfile.js
├── package.json
└── src
    ├── includes
    │   └── layout.pug
    ├── index.pug
    ├── projects.pug
    ├── scripts
    │   └── main.js
    └── styles
        └── main.css

7 directories, 11 files

Next time...

This post is long enough already, so I'll stop here. We've converted Alyssa's site to have a really solid base, so next time we'll build on top of this work to add superpowered blog features, powered by Stratic.

Now go apply this to your own site!


RC week 6

This is week 6 of being at the Recurse Center.

(I feel obligated to point out that this is being published a week later than it's supposed to be because I got behind. I am, however, very confident that the following is accurate. I used GitHub history and location data to help me remember the parts that were fuzzy.)

Day 19

Not at RC. Total time at RC 0h0m.

Traveled back from FOSDEM.

Day 20

Arrived ~16:45, departed ~22:10, total time at RC 5h25m.

Somewhat unproductive day. Spent most of it just trawling the web. I was completely exhausted since I got back to my apartment from the airport at 3 in the morning. (My flight got in late, I waited at the airport for a while to see my sister, and at 12:30 I got on my train away from the AirTrain station except that it was in the wrong direction. Also, fun fact, subways and trains run really infrequently at 1 AM. Who knew!?)

I did, however, write the slides for the next day's Security Club presentation on the basics of cryptography. Started them pretty late, though, and mostly finished them at home, which was unfortunate since I was up real late again.

Day 21

Arrived ~13:00, departed ~22:00, total time at RC 9h0m.

Arrived with a little time to spare before teaching Cryptography Basics for Security Club. Didn't do much in the afternoon before leaving to walk down to the waterfront with 15 people or so, which took an hour and was really, really lovely, honestly. Especially since the Winter 1 batch is ending so soon.

Day 22

Arrived ~12:00, departed ~5:00, total time at RC 17h00m.

Spent the morning and early afternoon pairing with Jackie on icalc. We fixed a maddeningly weird bug where, when the user input an incorrect value, the operation type prompt would be displayed twice. You can see the fix here - the problem was that getchar() was retrieving the newline used to "submit" the operation type when the function was called again (recursively). In other words, the stdin stream had two characters on it - the incorrect character, and the newline. The solution was to just use a different function from libc that did this correctly. The entire process was pretty educational, since it required delving into C strings, the libc manpages, etc. After fixing that, Jackie and I paired on a JavaScript project that will display Bank of America account balances on the commandline (a non-trivial problem, since Bank of America requires JavaScript).

In the late afternoon, switched gears a bit to review a PRISM Break PR.

In the evening, I gave a presentation at Thursday night presentations entitled "Mercurial for Git folks". I put zero effort into slides and instead simply opened up a bunch of tabs and terminal windows with content I wanted to point to while I was talking. Then I got up there and just... talked about why Mercurial is neat. At the beginning I asked who used Git (most hands, including mine, went up) and who hated Git (a fair number of hands, including mine, went up). So that was pretty amusing. I talked about how the design was pretty similar to Git, how Mercurial has extensions (because it's written in Python), how that plays into its "disable confusing/dangerous stuff like the staging area and rebase by default" philosophy, and how I've been learning it by just using hg-git with GitHub. I thought it went pretty badly, because I didn't feel like it was very coherent. But the people I asked about it said it was actually pretty good, so that feels nice.

After that, we had the end-of-batch/goodbye Rose party. :'(

I spent a lot of time discussing politics and education with Stephanie, which was lovely, and had some other long and interesting conversations that I wish I remember but don't, truthfully. Spent quite a bit of time with Pieter, Heather, and David L messing around on top of the desk chairs, which completely filled Hopper. Eventually ended up sitting in Babbage with Rose, James, Heather, and some other folks (can't remember, honestly) just hanging out. We jacked the space heater way up so it felt like a sauna (aka reeeeeeal nice) and just talked about stuff. Around the 2-3 AM mark Heather and I got bundled up and went out to go to the pharmacy (which turned out to actually be literally right next door) and buy chocolate and nail polish. And then I spent somewhere between 1.5 to 2 hours painting my nails a fabulously sparkly red color called "Devil's Stare" from a brand called "Sinful Colors" - a combination which strikes me as being nothing short of wild.

At around 5 AM, everyone decided to go to sleep. I was the only person to go home, and honestly the only reason I did so was because I knew I'd want a shower in the morning. So I spent about 15 minutes trying to find the stupid switch to turn off the kitchen lights, finally gave up and went home, and fell asleep a short while after the sun rose.

Friday

Arrived ~18:00, departed ~1:15, total time at RC 7h15m. As always, Friday doesn't count as a day because RC is technically not in session.

Arrived exceedingly late since I woke up around, you know, 5. Got to RC and did very little before noticing a very large party leaving for dinner, which I joined and ate with (despite saying before I left that I'd had breakfast recently, so I "wasn't going to get anything"). We went out to get Chinese food, then went to a place that served Asian dessert of some kind (I've forgotten). It was beyond lovely, honestly.

(I also mentioned at dinner that I'd missed a week of blogging, so during a discussion with Chris about it I posted to a Zulip topic named "shame AJ" soliciting ideas for a punishment as well as moving the regular Iron Blogger meeting to Tuesday due to the Spring 1 introduction day.)

Executive summary

This week was particularly unproductive. I only did a little bit of work on icalc, my C project, and other than that the only really RC-related project I did was my security club presentation on cryptography basics. This was mostly because my sleep schedule was super messed up from Brussels, and then got messed up again (just as it was getting back to normal) on Thursday.

This week was also very emotional, since it was the Winter 1s' last week. To all my Winter 1 friends: you made my time at RC amazing and welcoming and exciting and wonderful and I loved being around you all. And I will miss you for a very long time. <3

(*starts crying a lil bit*)

Total time at RC 38 hours 40 minutes; cumulative time 239 hours 25 minutes.


Gender representation at RC

So I want to talk (real quick) about gender representation in tech. Specifically, the fact that it's abysmal. Women[1] usually account for, at most, 30% of the employees in a company and that number is often much lower. Even at the companies where it's 30%, that number is misleading because it doesn't adress management positions which are often much lower. (For reference, women accounted for about 59% of the overall workforce as of 2015, when the article I pulled those numbers from was published.) Here's an article that says that on average, women leave the industry within 7 years of being in it. Let me repeat that, because I didn't say they leave their jobs, or take a break. They completely leave the entire technology industry. And unfortunately it makes sense, since incidents of sexism in tech are rampant.

Unlike (most of) the rest of the tech world, the Recurse Center is mostly (completely?) gender-balanced. I want to point out that while for years I've believed in diversity, it didn't become clear to me how much implicit bias I held until I joined RC. I find that, having previously spent significant amounts of time in environments that were predominantly white, cis and male, I find myself needing to self-correct discriminatory and gender-based unconscious assumptions significantly less frequently at RC. In other words, my subconscious is making less incorrect, gender-based suggestions about what people are like that I then have to consciously reject. I would attribute this almost 100% to the fact that at RC I'm surrounded by lots of people who are a) super talented and know their shit and b) aren't male.

If I have a point to this blog post (and I'm not sure that I do), it'd be to underscore what many have said before me: representation and role models are important. Advocating for gender equality is good and important, but in the end what really matters is what's actually in people's heads. That's mostly influenced by what they see in their immediate lives, and that's why representation is so important - believing in equality is great, but presenting actual evidence to your subconscious that its biases are incorrect is a much more powerful way to improve the way you perceive the world.

If folks have any comments or different perspectives, I'd love to hear them privately or via WebMention.

[1]: I'm focusing on women here because I'm not aware of any statistics about non-binary people in tech. But it's worth noting that it's a huge problem for them, too.

Update February 22nd: the lovely Rachel Vincent from RC faculty says this about RC's gender-balancing:

Of the folks who are currently in-batch (Winter 2's and Spring 1's), ~36% identify as women. It's roughly the same for the community as a whole (~33%), though we don't have super accurate numbers because we don't update information on folks' gender. The most gender balanced batches were a little over 40% women. We're always pushing for 50/50, though. 😊 Our overall strategy is to try to get an applicant pool that is as gender balanced as possible, and we don't do any kind of balancing during the admissions process itself.


RC week 5

This is week 5 of being at the Recurse Center.

Day 15

Arrived ~10:20, departed ~16:30, arrived ~20:00, departed ~23:30, total time at RC 9h40m.

Somehow managed to get up early and arrive at my checkin early, despite being dead-tired (I couldn't get to sleep so I was running on ~5 hours of sleep). Spent most of today working on my HTTPS presentation, but took 30 minutes to an hour or so off to make a couple small improvements to my website - mostly just trimming the projects page and adding information to the contact page about how to communicate securely with me. Left for a while to have dinner with a friend and returned via the subway[1] to work on my HTTPS presentation some more.

(Note 1/31: I felt quite productive today, but in hindsight really didn't get a whole lot done since I was just so tired.)

[1]: which truthfully made me feel unreasonably accomplished since my phone died right as I looked up directions, but I got on the right subway and figured out I could transfer and take a closer line halfway through and eventually made it back anyway

Day 16

Arrived ~10:20, departed ~23:10, total time at RC 12h50m.

Spent - no joke - basically all of today working on my HTTPS presentation, which in addition to actually writing the content entailed reminding myself of how things like e.g. TLS False Start actually work. Reminding and/or properly learning (for False Start in particular I had a vague idea of how it worked before, but didn't really understand it).

Took about an hour off in the evening to help repaint a large stretch of wall in the space as part of the cleaning party. Then went back to HTTPS. Highly productive day.

Day 17

Arrived ~11:30, departed ~17:40, total time at RC 6h10m.

Caught up with some GitHub stuff in the morning before teaching HTTPS. We went for an hour and a half and still skipped the entire section on TLS performance because HTTPS is complicated and hacky and also really terrible. (As Claire put it, "I'm now terrified of browsing the web." Me too, Claire. Me too.) I think it went really well, even though it was a little overwhelming for everyone at times.

Spent a bit of time watching YouTube videos on how Diffie-Hellmann works and how Elliptic-Curve Diffie-Hellman (ECDHE) works - we'd touched on both of these during the presentation and I needed to put them in Zulip. The one on plain Diffie-Hellmann was just a refresher, but the one on ECDHE was something I'd previously tried to watch several times and had always been too confused. But, this time I got it! Whooo! So that felt awesome.

Left early to go home and sqeeze in some laundry before closing out the evening by going to an RC-organized talk on Crystal.

Day 18

Arrived ~10:30, departed ~14:30, total time at RC 4h0m.

Did just a smidge of work on pump.io before going to Abstract Salad Factory, then heading home to catch my flight to Brussels.

Friday

Not at RC. Total time at RC 0h0m.

In Brussels for FOSDEM.

Executive summary

This week had its ups and downs. I was really productive on the HTTPS stuff, but other than that I didn't reeeally get a lot done.

Total time at RC 32 hours 40 minutes; cumulative time 230 hours 45 minutes.


RC week 4

This is week 4 of being at the Recurse Center.

Day 11

Arrived ~10:50, departed ~23:20, total time at RC 12h30m.

Arrived 20 minutes late for my checkin, but checked in with Stanley and Heather anyway. Started an experiment where I turned on HTTPS Everywhere's "block all unencrypted requests" option, which has been, uh, interesting so far. Spent most of the day working on blog-related things - finishing up and publishing RC week 3 (which I just straight up forgot to publish on Saturday) along with Surveillance priorities which I finished exactly two minutes before[1] the start of this week's Iron Blogger challenge meeting. Other than that, poked a little at implementing OCSP stapling support in ejabberd, which is something I want to do for a number of reasons:

  1. It'll give me a chance to look at some Erlang, which will be a really interesting experience
  2. It'll give me a chance to try doing something with the OpenSSL API, which is a complete horror show but nonetheless something I would like (some) experience in
  3. I run ejabberd in production and, you know, really want stapling support

Ended the night by going to Fat Cat.

[1]: I actually already had a longer post mostly written, but I realized as I was going to finish it that the experiment that I was proposing had a) been done before and b) mostly failed. So I ended up writing "Surveillance priorities" from scratch in a hurry instead.

Day 12

Arrived ~10:50, departed ~17:50, total time at RC 7h0m.

Arrived late again, despite leaving a good 15 to 20 minutes earlier. Freaking subway. ANYWAY. Checked in on Zulip instead of in person. The day was semi-productive - I worked a little on my operational security presentation for tomorrow, but a lot of my time was spent talking with Rose, discussing the programming language I'm planning to work on/invent. Left early to do laundry at home and then closed out the evening by finishing my presentation as well as finding and reporting a (common and uninteresting) security vulnerability in a web application[2] - unnamed for obvious reasons.

As a side note, as Stanley put it, I'm RC famous! Kind of, I guess. \o/

[2]: I actually thought I found the same problem in another project, except it turned out that I totally missed something and so instead of being cool I ended up embarrassing myself on GitHub instead. Sadface :(

Day 13

Arrived ~10:35, departed ~00:10, total time at RC 13h35m.

Arrived in the middle of my checkin. Spent the morning taking care of some general maintenance tasks, including getting ready to present on operational security, which I did in the afternoon. Spent most of the rest of the day thinking about the design of my programming language and putting it together into a blog post. In the evening, started trying to fix a bug in Sandstorm which was breaking my production install. Also, had my Princeton interview via Skype, which I think went extremely well. Yay! My interviewer was awesome and we had a really interesting conversation.

As a side note, I got to wear my new libuv shirt today, and it is seriously the coolest shirt I've ever seen.

Day 14

Arrived ~10:35, departed ~1:40, total time at RC 15h5m.

Arrived in the middle of my checkin again (still better than earlier in the week, though). It wasn't anything groundbreaking, but it did give me the opportunity to get more hands-on Mercurial experience (and learn a lot about Mercurial's different branching styles). Working in an unfamiliar codebase was also a good experience, as was dealing with Sandstorm's custom UDP protocol. It wasn't really what I meant to do with the day, but also not a total wash.

Attended Thursday presentations followed by Game Night in the evening which was very fun - I played some poker, then lost at chess a bunch of times to Hussein (even when we played Blitz Chess, which he said he was bad at). Then we switched to Go for a while. Finished out the evening by just hanging out with Fenimore, Hussein, and James, which was a lot of fun.

Friday

Arrived ~15:10, departed ~23:50, total time at RC 8h40m. As always, Friday doesn't count as a day because RC is technically not in session.

Slept in pretty late today. Attended the monthly pump.io meeting immediately upon arrival (sadly Evan wasn't there). Spent the rest of the day responding to PRs - which took a lot of time but didn't actually result in a lot of code - then authoring a Huginn PR to [add titles][] to all pages.

Executive summary

In a shocking turn of events, this week was relatively productive, but could've been better. I challenged myself a little bit, but I think I can and should do more.

Checkins really helped. Even when I missed the checkin it provided motivation to get up and get moving. 10:30 may be a little too early for me though, so I'm not sure if I'll continue doing it next week.

Total time at RC 56 hours 50 minutes; cumulative time 198 hours 5 minutes.


~