Deploying Hugo to GitHub Pages with GitHub Actions

There are a lot of strategies to hosting in-repo docs on GitHub Pages (as opposed to a dedicated repo for docs). I’m going to cover how to publish docs that are stored on the master branch to the gh-pages branch. This approach has several benefits Only the Hugo “source” files live in master, while gh-pages contains the built HTML, etc. This keeps master clean and lean, and makes PR diffs much easier to review.


Configuring AWS PrivateLink in non-routable VPCs Consumers with Terraform

AWS VPCs make it possible to establish private network connections across AWS accounts with VPC Peering, essentially merging the networks into one. However, there is another option for cross-account/cross-VPC network access, with a much smaller surface area. PrivateLink is a bundle of services with some difficult-to-parse documentation, but it’s pretty powerful. Today I’m just going to cover a single use case: communicating between a central service provider to a set of consumers, living in non-routable VPC’s (no NAT gateway, no internet gateway, no public/elastic IPs), all in various AWS accounts.


Getting AWS Availability Zone IDs with Terraform

AWS Availability Zone names may look like unique identifiers, but they are mapped to physical availability zones essentially at random. This means that us-west-2b in one account may be the same physical availability zone as us-west-2a in another account. If you are doing certain kinds of cross-account networking mapping by name can result in errors. To solve this AWS provides the ID** of the availability zone, which *will* map to the same physical availability zone in every account.


JavaScript tests with Mocha and jspm

It’s no secret that I love jspm. I think it does everything right. I think Webpack requires far too much configuration. jspm is also much more standards-oriented, so I expect the patterns I learn and develop to last much longer, which is something I sorely need in JavaScript development. However, testing it is difficult bordering on silly. I just spent three days trying to get tests to work, and the solution I have for you isn’t perfect.


Center DIV Vertically and Horizontally with full width and height

There are way too many solutions to this online that just don’t work. I want a full-page absolutely centered DIV. It needs to center in the browser, which means forcing the correct height and width. This uses flexbox, so it doesn’t work in Internet Explorer (yes, even IE11… I thought we were passed this?) .center-on-page { height: 100vh; width: 100vw; display: flex; justify-content: center; align-items: center; } vh and vw are viewport relative units, which will cause this div to be the size of the entire browser.


Application Management and Crontab

This is part of my complete guide to Setting up a CentOS Digital Ocean droplet with Nginx for beginners. When working with Nodejs starting your applications and keeping them running is not always straightforward. There are tools to help you with this, like forever and pm2, but if you are doing any kind of deploy-and-build step you will need to have more of a plan than “run the application.” My application server management consists of five pieces


Installing Nodejs on CentOS

This is part of my complete guide to Setting up a CentOS Digital Ocean droplet with Nginx for beginners. Where to get it from Yum has a Nodejs package. I don’t recommend using it. It update slowly, and you are probably going to want to manage node and npm’s version yourself. I highly recommend installing and updating node yourself, without a package manager (other than npm). Later on, being able to update Nodejs though npm is going to make your life a lot easier.


Configuring Nginx as a Reverse Proxy (for NodeJS)

This is part of my complete guide to Setting up a CentOS Digital Ocean droplet with Nginx for beginners. Nginx is a highly-capable server, suitable for many use cases. The purpose of this guide is to show nginx’s use as a reverse proxy, not as the application server itself. It is assumed you will be using an application server, like NodeJS, to perform the rest of the work. If you don’t yet have Nginx installed, you can install it with

Configuring the firewall on CentOS

This is part of my complete guide to Setting up a CentOS Digital Ocean droplet with Nginx for beginners. If you just need the commands, here they are. Read on for an explanation of what is happening. sudo systemctl start firewalld sudo firewall-cmd --permanent --add-service=ssh sudo firewall-cmd --permanent --add-port=4444/tcp #if you changed default ssh port sudo firewall-cmd --permanent --add-service=http sudo firewall-cmd --permanent --add-service=https sudo firewall-cmd --permanent --add-service=smtp sudo firewall-cmd --reload sudo systemctl enable firewalld I am not going to bother repeating the excellent explanation of these commands from their source guide.

Configuring TimeZones and Network Time Protocol on CentOS

This is part of my complete guide to Setting up a CentOS Digital Ocean droplet with Nginx for beginners. If you just need the commands, here they are. Read on for an explanation of what is happening. sudo timedatectl list-timezones #copy your zone sudo timedatectl set-timezone region/timezone sudo yum install ntp sudo systemctl start ntpd sudo systemctl enable ntpd I am not going to bother repeating the excellent explanation of these commands from their source guide.


Install Fail2Ban on CentOS

This is part of my complete guide to Setting up a CentOS Digital Ocean droplet with Nginx for beginners. If you just need the commands, here they are. Read on for an explanation of what is happening. yum install epel-release #if you haven't already yum install fail2ban cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local nano /etc/fail2ban/jail.local #more on this below systemctl restart fail2ban.service systemctl enable fail2ban Most of this information came from this guide on servermom, except the last line that ensures the service starts at boot.


Setting up a CentOS Digital Ocean droplet with Nginx for beginners

If you want to get to the meat of the post, jump down to the guide. Intro I recently made the move from WebFaction, which offers a shared/managed host with SSH access, to Digital Ocean, which offers virtual private servers with SSH access. They are both billed as being “for developers”, but WebFaction does more work for you. The tradeoff is you don’t get root/sudo access. This wasn’t a problem for me until I wanted to automate SSL key installation with Let’s Encrypt.


Setup swap file on CentOS

This is part of my complete guide to Setting up a CentOS Digital Ocean droplet with Nginx for beginners. If you just need the commands, here they are. Read on for an explanation of what is happening. sudo fallocate -l 1G /swapfile sudo chmod 600 /swapfile sudo mkswap /swapfile sudo swapon /swapfile sudo sh -c 'echo "/swapfile none swap sw 0 0" >> /etc/fstab' I am not going to bother repeating the excellent explanation of these commands from their source guide.


React and jspm

I’ve been tinkering with React a lot lately; I am really loving it. Since I still believe that jspm offers a better development and bundling experience than WebPack (unless you need hot module reloading), I spend some time this week getting a solid project template down for React and jspm. Directory Structure Let’s just jump straight to the solution, and then break down the reasons. Project |--assets/ | |--css/ | |--fonts/ | |--images/ | +--stylus/ |--dist/ +--built.


jspm, jQuery Plugins, and ES6

jspm is a new package manager for JavaScript fornt-ends that comes with a universal module loading system. It integrates nicely with npm by adding a jspm property to the package.json that specifies what the jspm dependencies are. Mine looks like this: "jspm": { "directories": { "baseURL": "client" }, "dependencies": { "Magnific-Popup": "github:dimsemenov/Magnific-Popup@^1.0.0", "aurelia-bootstrapper": "^0.8.0", "aurelia-http-client": "^0.4.1", "bootstrap": "^3.3.1", "font-awesome": "^4.2.0", "jquery": "^2.1.3" } } One of the really cool things about jspm is that, while it uses npm to load packages, it allows multiple endpoints to be defined.

Durandal vs Angular

Yep, time to throw in my $.02. I’ve used Durandal on multiple personal projects, as well as a large professional project spanning several months. I have used Angular on two personal projects, and am currently using it at work. I have a lot more experience with Durandal than I do with Angular, so if I make any factual errors here feel free to let me know. I would love to be wrong about some of my gripes, since that would mean not having to deal with them.


MultipartForm FileUpload with RestSharp

RestSharp is handy .NET library for doing REST requests, and it claims to support Multi-part form/file uploads. It doesn’t provide any documentation on how to do this though, and I recently got tripped up trying to figure it out. It turns out to be pretty easy though. //The 2nd parameter is a short-hand of (stream) => fileStream.CopyTo(stream) request.AddFile("fileData", fileStream.CopyTo, filename); request.AlwaysMultipartFormData = true; //Add one of these for each form boundary you need request.

Setting up ConEmu with Git Bash on Windows

The Windows command prompt sucks. It just does. Every other terminal in every other operating system is better than it, and Microsoft doesn’t seem to care. ConEmu is here for you. If you want to know what it’s all about, Scott Hanselman has a blog on it with the details. That’s not what this bog is about. This blog is about getting ConEmu setup with Git Bash on Windows, because for some reason that is a pain in the ass.


Writing a Programming Book

I am writing a book on KnockoutJS. I’ve taught JavaScript and Knockout at work before, but I have never tried to produce a book on programming. I ran into some pretty big challenges trying to put the first chapter together. My first idea was drawn from experience teaching JavaScript at work, where I created interactive exercises for people to work through that were written alongside instructions and explanations. This was doomed to fail, since books are not interactive.

twitter bootstrap

Replacing the Durandal Modal with Boostrap's Modal

Durandal 2.1 is now in pre-release. Despite claiming to have upgraded Bootstrap to 3.1 Durandal is still using a non-responsible, non-bootstrap based modal dialog. Thankfully, switching it out is pretty easy. Somewhere early in your startup process, just dump this code in. It will replace both the custom modal dialog host, as well as the Message Box on app.showMessage. dialog.addContext('bootstrap', { addHost: function (dialogInstance) { var body = $('body'), host = $('<div class="modal fade"><div class="modal-dialog"><div class="modal-content"></div></div></div>'); host.


Q Promise resolves immediately when .done() is called

I just spent way to much time on this problem, and it turned out to be a wayward .done() attached to a promise that was getting passed downstream. Because done() returns nothing the next handler in the chain was resolving immediately, instead of waiting for the chain done() was attached to. Take a look at the code, the problem is pretty easy to miss. A normal, functioning chain A broken chain, with a done() in the middle


Being open-minded towards closed-minded people

This doesn’t specifically apply to the Brandon Eich saga, but it’s come up a lot lately in comments regarding that situation. The idea that being open-minded means being open to everyone, including closed-minded people. Some might call it “being tolerant of intolerance.” I think this is somewhat related to the concept that if someone speaks an opinion, because they have a right to speak it (under the 1st Amendment), that they have a right not to suffer an ill will for it.


Mozilla's new CEO

I am a fan of Popehat, a legal blog that focuses primarily on free speech issues. As they like to put it social actions, the many varieties of “speech” in the US, are protected by the 1st amendment. Unlike many parts of the Constitution these days we take the 1st amendment pretty seriously. The government is very limited in what it can do to you for your speech. “Protected” speech, in this sense, means protected from government initiated consequences (like jail or fines).


Echo is on.

Batch script is old. Batch script is quirky, and has the syntax of the aborted love child of bash and perl. This shouldn’t be news to anyone, but if you use batch script as infrequently as I do I have something that might be news. Consider the following block of code if %PORT% == 80 ( CALL someScript.bat set error=%errorlevel% if %error% neq 0 exit /b %error% ) Batch script parses blocks, like the blocks inside an if statement, before it executes them.


TFS MSBuild and Grunt

Getting Grunt working with TFS and MSBuild was a pain in the ass this week. There were several problems that took me several hours to figure out, so hopefulyl I can save you some pain with this. TFS’s 260 character limit on path names is very likely going to cause you problems, since npm nests internal dependencies. You probably figured this out pretty quickly, since you won’t be able to follow the best practice of checking in your NodeJS dependencies, but I wanted to spell this out since other problems on this list are caused by the first one.


Writing Javascript tests that will run on Windows and Linux with Grunt

I primarily develop at home on my Windows machine, but all of my web projects live on a Webfaction-hosted linux machine. To create a smooth deployment process with Grunt that will run my tests on either machine I used the PhantomJS node package. The trick here is that it can’t be copied over with the deployment; it needs to be installed by npm on the target machine to run properly. You can make this happen pretty easily by ensuring it’s installed globally on both machines, but still included in the package.


Magnific Popup and Durandal's Router

Magnific Popup is a great little jQuery plugin that creates responsive lightbox’s for images. I’ve used a few lightboxes, but this one definitely has the fewest number of issues when moving between desktop and mobile sizes. All of it’s documentation and examples, though, assume that you will be wrapping your <img> tag with an <a> tag, where Magnific will actually be pulling the information for the lightbox for. There is an integration issue here with Durandal, because the router plugin will cause any <a> with an href attribute to cause the router to try to navigate.


Relative Paths and PushState in Durandal

Modern browsers support the history.pushState api for changing the URL without actually navigating on the page. This is a nice replacement for hash-based navigation (where a hash-route is used to change the page without navigating, due to the hash not going to the server) since the URL looks like a normal, clean url. Other than smoother navigation, the implementation is invisible to the user. But the server has to support this.

FireBind: Knockout bindings for Firebase

Everybody loves Knockout (or they should, because it’s fantastic). I think less people know about Firebase, but its a very cool service. It basically provides a real-time backend for persistent data, along with either client libraries or a REST api for subscribing to the changes in that data. When I first found out about Firebase, I had already been working on a personal project that had been inspired by Meteor which had a similar cross-client-real-time-data backend.


Testing Durandal Code with Jasmine

Unit Testing in javascript is usually pretty straightforward. You pick a framework like Jasmine or QUnit, you write some tests, and you run them in your browser or in something headless like PhantomJS. I prefer Jasmine, due solely to exposure, for my test framework. I prefer PhantomJS for running my tests because it is fast and can be done from the terminal, or other browser-less environments like your SSH-to-your-server. Durandal+Jasmine presents two challenges to the standard setup here.


Organizing a Durandal Application

Durandal is currently my Javascript MV* framework of choice. It’s flexible, powerful, and written by the same guys who did the WPF MVVM framework Caliburn.Micro. Conventional Organization In it’s tutorial, and by way of using app.useConvention(), it opines on an organization for your client code that looks like this: client |--app | |--views | | +--shell.html | |--viewmodels | | +shell.js | +-main.js +--lib +--durandal When you compose a viewmodel, Durandal locates the view for it by replacing the viewmodels section of its path with views.


Setting up SSH Git deploy with Webfaction

I spent about three days trying to get this to work with an https server, but eventually gave in. There were too many issues related to the account the hook would run under for my limited linux experience to solve. So the SSH method will have to do for now. Setting up Git If you follow this guide through the Creating a new repository section, you should be good. For the sake of history, here are the installation steps from it


Setting up Webfaction Sendmail with Ghost

Ghost’s email guide leans pretty heavily on external services. It doesn’t seem to think most people will want to use the server they are running on. Setting up sendmail on Webfaction is pretty easy, since sendmail is installed on all their boxes. Just put this in your config.js mail: { transport: 'sendmail', fromaddress: 'no-reply@example.com', options: {} }, There is a weird gotcha here though. This didn’t work for me when I left off the options section entirely, and it also failed when I specified the full path to sendmail, as this section encourages you to.