How to Get Reliable Bitcoin Price Alerts  

Whenever there’s an asset that fluctuates as wildly as Bitcoin, there’s an opportunity to make easy money day trading. As a game, I’ve thrown $200 into Coinbase last week and I’ve already made a $7 profit. I expect to make several times that this week, and of course it’ll snowball as the amount increases. I’m not treating this as an actual investment strategy, more like a fun game when I’ve got 30 seconds of downtime throughout the day.

A vital aspect to this is having reliable price alerts. When Bitcoin goes up 3%, you sell. When it goes back down 3%, you buy. Rinse and repeat. Over and over.1 The problem is that Coinbase’s price alerts are not reliable. I have half a dozen price alerts set up, a few of which ought to have been triggered but have not. I’ve only gotten one price notification since I set up the app. This is leaving money on the table.

I’ve confirmed that CoinManager for iOS, linked in the Reddit thread, has push notifications that work. Its interface is inferior to Coinbase’s, but functional is a thousand times more important than beautiful in an either-or scenario. Until Coinbase fixes this bug, my advice is this: buy with Coinbase, and track with CoinManager. The fastest you can get CoinManager alerts is at 60 second intervals, but that should be good enough for anyone but the most serious Bitcoin investor.

  1. This sounds like an algorithm that ought to be automated via an implementation of Coinbase’s API. More on this later, maybe. ↩︎

The Return of the Russian Passenger  

This episode of Reply All is required listening. Top highlights:

  • You can buy Uber accounts for $4 to $7 on the dark web.
  • If you’re not using a password manager to maintain unique passwords for your sundry accounts on the web, you’re going to get hacked—it’s just a matter of time.1

  1. It’s too bad Secrets didn’t get mentioned in the further reading piece titled, “The Best Password Managers.” Secrets is better than LastPass and 1Password. ↩︎

How to Write a Failing Jest Test if Vuex State Is Modified Outside Mutation Handlers

If you’ve ever worked with Vuex in strict mode, you’ve likely come across this error:

Do not mutate vuex store state outside mutation handlers.

Since strict mode continuously does a deep watch on all of the data in all of your Vuex store modules, it’s very hard on performance, and it’s therefore disabled in production. And since your jest unit tests are oblivious to these errors, they’ll pass even if strict mode is catching this problem. As a result, it’s easy for production code to get into a state in which vuex store state is being modified outside mutations, and you only see the error when you’re developing locally in strict mode. Such was the case for me this past week, and I decided that it’d be nice to have a way to fail CI in this situation. The code below is the idea that I came up with.

import Vue from 'vue';
import Vuex from 'vuex';
// The store module we're wanting to test 
import movies from './index';


const store = new Vuex.Store({
  namespaced: true,
  modules: {
  strict: true

describe('movies store', () => {
  test('fetching movies should not alter Vuex state outside of mutations', () => {
    let cleanConsole = true;

    jest.spyOn(console, 'error').mockImplementation(() => {
      cleanConsole = false;

    return store.dispatch('movies/fetch', { username: 'martynchamberlin' }).then(() =>

It’s pretty simple, really. The idea is that we use jest’s spyOn method to keep track of any console.error calls that are made during the execution of the tested code. You can use this approach on a jest test for anything—you don’t have to be testing store code. You could have this on a helper class that you fear will have a proclivity to modify the store state directly.

The beautiful thing about tests is that once you’ve got them passing and integrated into your master branch, you never have to worry about a regression for the thing they’re testing. The peace of mind that this brings makes exploring solutions like this one well worth the effort.

Coinbase Asks Its Users to Invest Responsibly  

Brian Armstrong, CEO of Coinbase, writing at Medium:

We at Coinbase couldn’t be more excited by the explosion of interest in digital currencies. The last few weeks has seen an unprecedented increase in the price of digital currencies. More people are engaging with our platform than ever and that bodes well for the future of the digital currency. At the same time, it does create extreme volatility and stress on our systems. We take this very seriously and wanted to share some important thoughts.

This piece is a fascinating look into the bitcoin craze that’s mounted in anticipation of its debut on the Chicago Board Options Exchange tomorrow.

The Bitcoin Bubble Is Causing Everyday Consumers to Speculate in It  

Seth Fiegerman, writing for CNN:

When I saw the price of bitcoin fall to $9,500, I pressed buy, defying the wisdom of two finance titans and my wife. One hundred dollars, or 0.0101 bitcoins. (A few days later, I bought another $150.) By the time we got to our hotel, my stake had already gone up 10%. One week later, it was (briefly) up 100%. My wife’s opinion of me has reportedly decreased by the same amount.

I know a lot of people who are getting caught up in this right now and making money. The momentum is getting strong enough that you almost need a reason not to invest, or you’re going to. It’s low hanging fruit.

This Sunday is going to be a big day, too.

How to Pass Up All Events to a Parent Component in Vue

By default, if a Vue component only has one node in it (i.e. no child nodes), then all events that you attach to it from the parent will fire just like if it were a regular HTML element. But what if you have a child node that has children? In that case, you want to use v-on="$listeners", something that became possible a few months ago.

For example, if you have a component that looks like this:

  <div v-on="$listeners">
    <button>Hello world</button>

  export default {
    name: 'helloWorldButton'

Then you can consume that component like this:

  <hello-world-button @click="buttonWasClicked" />

  import helloWorldButton from './hello-world-button.vue';

  export default {
    name: 'parentComponent',
    components: {
    methods: {
      buttonWasClicked() {
        console.log('button was clicked');

When the button in that child is clicked, the buttonWasClicked method will be called.

How to Add an Invisible Row of Icons on an iOS Home Screen  

This how-to is 3 years old but it’s aged well.1 Ever since going from a black iPhone 7 to a white iPhone 8, I’ve quit using a pure black wallpaper, but I tried it out David Smith’s method just now and it works perfectly. You never have any indication that there are invisible icons on the first row.

I’m hopeful that in the future, iOS will allow transparency in the icons. That’d be huge. In addition to giving icon designers more options, it’d let us do this sort of thing with any wallpaper, not just a black one.

  1. Thanks to Manton for the link. ↩︎

“About a Month”  

Here’s what the Apple product page says regarding the battery life for its wireless keyboard, trackpad, and mouse:

A full charge is completed in about 2 hours, and provides enough power for about a month or more of usage.

My Magic Mouse 2 seems to run out of battery all the time, so I decided to track it between charges. It died on November 2 and then after a full recharge it died again today. That’s right at a month. I’m on it all day, 5-6 days per week, and I don’t turn it off at night.

A month of battery would be great if it weren’t for the fact that the lightening port for recharging the Magic Mouse 2 lies underneath it, which means you can’t use it while it’s recharging. And it always dies at the most inconvenient times.1 As a result, I keep my old Magic Mouse on hand, which takes two AA batteries, and I use it for about two hours once a month. Every time my new one is recharged and I switch back to it, I smile. It’s truly a superior mouse and more enjoyable to use, other than for this one hassle.

  1. There might be a notification that pops up when the battery is low, but I never see it because I have Do Not Disturb enabled perpetually. ↩︎

GitHub Panics Over Net Neutrality  


A free, open internet is once again at stake. Now more than ever before, it’s time to make a ruckus.


Two years ago, the Federal Communications Commission (FCC) passed the Open Internet Order—a set of regulations allowing people to freely access and interact with information online, and protecting them from potential discriminatory practices by internet service providers (ISPs).

It’s downright amusing how many misinformed grownups are panicking about something that is a non-issue.

The Story Behind the Orange and Blue Icons for VS Code  

Chris Dias, writing at the Visual Studio Code blog:

Thanks for all the passionate feedback. It has been very helpful, painful, and entertaining all at the same time. We’re changing the orange icon to blue for Stable and keeping green for Insiders.


For complete transparency, we want to share some history as we think it helps to understand how we arrived at orange in the first place.

This whole piece is a great read. I’d always thought the original blue VS Code icon was horrendously ugly. Chris explains why here — it’s because, “It was really meant to be a favicon.” Makes total sense. In contrast, the newest blue icon is by far the best looking rendition the company’s done. It’s one of the many reasons that VS Code is the IDE I currently use for everything.

This part scares me though:

We are exploring using a non-tilted icon for macOS based on @donysukardi’s comment here. We can’t say yet that we’ll do this, but we are going to explore it and either way, we’ll post updates in that issue.

I’m with jeffbox on this one, who “much prefers” the tilted version.

24 Pull Requests  

From the GitHub blog:

24 Pull Requests is an annual community-organized event encouraging developers to give back to open source projects over the holiday season. Be part of this year’s giving by submitting 24 pull requests between December 1 and December 24.

Using pull requests as a metric is a bit odd, because not all pull requests are created equal. This is akin to saying, “Track 24 runs on Strava.” Using that analogy, a more interesting metric would be to track the total number of miles run on Strava, or total amount of time spent running. If someone’s completed 24 runs on Strava, I have no idea what their level of output is compared to someone else who’s completed 24 runs.

It’s harder to quantify, but I think time spent is a more helpful metric for software development. After all, that’s how employers track it. If I spend 8 hours making 4 pull requests and you spend 8 hours making 1 pull request, we’re even. I’m not 3 ahead. You just had a harder problem to solve, and that needs to be acknowledged somehow.

Of course, in this particular initiative, the goal isn’t to be comparing oneself to other contributors, but rather to be making a concerted effort at improving open source software. Counting pull requests is a convenient way to do that. I get why this was the chosen metric; I just think it has a limitated use case.

Is macOS in “Full-Fledged Neglect” as a Result of Its Root Security Bug?  

Rui Carmo, writing at Tao of Mac about the recently popularized root security bug in macOS:

The fact that this has been out there in the wild for weeks (and apparently exploitable via Apple Remote Desktop, too) is amazing, and further damning evidence that Apple’s QA has been slipping beneath any sort of tolerable threshold.

It would actually be strange for the QA team to think to try this specific hack. The primary job of a QA team is not to invent weird edge cases. The failure here isn’t company-wide or institutional, unless you allow your confirmation bias to make it so. If we’re looking to point fingers, we should point them in this case at the engineers who made this bug, not the QA team. This bug is so specific that it’s difficult to imagine that the engineers didn’t deliberately manufacture it, either as a poorly judged inside joke, or as a sandboxed solution that they never meant to ship to everyone.

Rui goes on:

macOS seems to be falling into full-fledged neglect, and as a primarily UNIX user, I’m flabbergasted this kind of thing is even possible in 2017.

Despite its flaws, macOS is the best desktop operating system for many people. The root account bug is only a symptom of a bigger issue if you approach it with that presupposition, which I do not. This bug should only flabbergast people if it had remained in the wild for six months whilst Apple knew of it, but that’s not the case; Apple’s already issued the fix. No matter how first-class a team is, it will still ship bugs to its users. Therefore, you mustn’t judge an operating system’s health by whether it has obscure bugs, but by whether its engineers are dedicated to solving them. As Manton wrote, this means that “There’s hope for us small developers too.”  

Buried in the show notes of the latest episode of The Talk Show is a link to It’s a gambling site for election outcomes. The way it works is this: you buy a share on a specific bet (e.g. “Will the 2020 Republican nominee for president be a woman?”) for an amount of money between 1¢ and 99¢. If you’re right, you receive $1 for every share you bought. If you’re wrong, you get nothing. The higher the amount it costs to buy a share (i.e. the closer to a full dollar) the more likely it is that you’re going to be right, and hence the lower ROI.

  1. Sometimes Drinking Caffeine is nothing more than a commentary on the commentary at Daring Fireball. ↩︎

Ben Thompson, Master Persuader  

John Gruber, reflecting on Ben Thompson’s piece which was originally titled Why Ajit Pai is Right:

I find myself persuaded.

I wonder what other things about this administration that Ben could persuade Gruber as being well-reasoned instead of symptomatic of a kakistocracy.

This persuasion backs my belief that the only reason most Americans have been in favor Title II is because the overwhelming majority of media and corporations have backed it, not because people have actually sat down themselves and reasoned through it.

TypeScript at Lyft  

Mohsen Azimi, Lyft enginner writing at Medium:

In my early days as a JavaScript developer, when I learned about efforts to add types to JavaScript projects, the first question I asked myself was: why?

Now, as a seasoned JavaScript veteran, I cannot imagine writing JavaScript without support of a type system.

Great read. TypeScript isn’t going anywhere, and it’s clearly the winner amongst JavaScript supersets.

The So-Called “Crossroads”  

David Karp, announcing his end as CEO of Tumblr:

The internet is at a crossroads of which this team can play a fundamental role in shpaing.

By “crossroads,” I assume David’s referring to the battle over whether writers own the platforms upon which their works reside. I’m not convinced we’re at any such sort of crossroads.1 Calling late 2017 a crossroads makes for a nice sentence in a departure letter, but we won’t think back to this era as a critical juncture. Because Donald Trump is president and because people are restless, they like to say this sort of thing, but it holds no water. There will always be a coalition of creatives who are determined to own their online platforms, come what may. There will always be those who are lazy, or don’t care, or are ignorant, who have half-baked ideas that they’re looking to yak abroad, who won’t go through the effort to publish on their own territory, who will post to Facebook or similar. There will always be such a place for such people. And — this is just a guess but it’s a good guess — those people will always be the majority of web users who write online. There might have been a time when this wasn’t the case, but if so, then this croassroads occurred roughly a decade ago, when social media grew mainstream. If what we’re going through right now passes the criteria to be termed a crossroads, then we’d better get used to it, because crossroads are going to be indefinitely recurring in conjunction with the ebb and flow of web behavior.

My compliments to David Karp for making Tumblr’s mission in his absence sound exciting.

  1. If you’re into wordsmith pedantry, I’m not sure how you shape a crossroads exactly, but that’s an aside. ↩︎

Media Keys Do Not Work for iTunes  

I listen to Apple Music throughout the day, and not being able to use the play / pause button is debilitating. I’ve filed a bug report through Apple’s interface for this.

How to Create a JavaScript Object With a Dynamic Property

If you want an object obj with a property of hello and a value of world, you can do this:

const obj = {
  hello: 'world';

If the property name hello is determined elsewhere, you can do this:

// Pretend this 'hello' gets determined abroad
const propName = 'hello';

const obj = {};
obj[propName] = 'world';

This is a bit verbose, however. A more succinct way is this:

const propName = 'hello';
const obj = {
  [propName]: 'world'

It seems simple enough, but I only recently grasped that this syntax is possible. You might think that reducing two statements into one isn’t that much of a gain, but it becomes incredibly useful with CSS Modules in Vue:

<p :class="{ [$]: isRed }">
  Am I red?

This class expression wouldn’t be possible without this feature.

The Best Laptop Ever Made  

Marco Arment:

Apple has made many great laptops, but the 15-inch Retina MacBook Pro (2012–2015) is the epitome of usefulness, elegance, practicality, and power for an overall package that still hasn’t been (and may never be) surpassed.

This piece really resonates. I’ve used this computer as my primary workstation for 25 months and it’s still going strong. Some day I will have to buy its replacment, but Apple has yet to ship a laptop that is its superior.

Zwift Raises Its Monthly Subscription to $14.99  

Eric Min, CEO:

From a scrappy little team that could all fit around a table and share a meal, Zwift’s staff has grown to over a hundred people including programmers, artists, designers, testers, community managers, coaches, marketers, and an awesome support staff working to help Zwifters when they have questions.

In order to continue to make Zwift bigger, better and more beautiful, we are updating our membership price to $14.99 per month, effective today. As a way of saying thank you, however, to the awesome Zwifters who helped us get here, your pricing will not change for one year.

There’s nothing like Zwift. It’s one of my favorite pieces of software. I ride outdoors in the summer, but during rainy days and in the cold of winter, Zwift is where it’s at. I knew the company was growing but I had no idea that there are now more than a hundred people at it. That’s fantastic.

This price increase might be a slight barrier to new customers, but I can’t imagine that anyone who’s experienced Zwift will mind the jump when it happens. Grandfathering the old pricing to preexisting customers for a year isn’t something the company had to do, but it’s a nice touch.1

  1. Far better to reward preexisting customers than to offer signup incentives for which your loyal base isn’t eligible. ↩︎

GitHub Introduces Teletype for Atom  

From the GitHub blog:

Writing code with other developers can be a great way to onboard teammates, get to know how your peers think, and learn new skills. Unfortunately, writing code together can be difficult to coordinate.

Now social coding is easier than ever with Teletype for Atom—a new way to dive right into code with remote collaborators. Work together in real time with your own configurations in your own programming environment on any file you can open in Atom.

I hear BBEdit is going to get this any day now.

Ditch jQuery

After stewing over Alex Russell’s performance budget for some time, I reduced my JavaScript footprint last night from 105KB to 18KB by removing jQuery as a dependency.1 I rewrote my use of jQuery into pure JavaScript. As a result, the site loads faster — consistently under 100ms — with zero setbacks to the user experience.

jQuery has been called a “find something do something” library, and that’s an accurate description for it. It is not a robust library for reactively perculating state changes through a UI. If you want that, you’ll use VueJS or React or Angular. Since those libraries are heavier than my simple frontend needs at this site however, I chose to just go with pure JavaScript.

When jQuery was first released in August 2006, it solved a real need, because these aforementioned frameworks didn’t exist and native JavaScript was bad at “find something do something.” Eleven years later, that’s changed. jQuery is redundant. The native abilities in JavaScript to fetch DOM objects by class name, to manipulate those classes, and to transverse up and down the DOM from a specific object, are all only slightly more verbose than their jQuery equivalents.

Sure, it’s still a wee faster writing jQuery than pure JavaScript, but hardly for someone well-versed in the native abilities of JavaScript, and whatever miniscule time savings jQuery affords is not worth the additional 82-87KB in file size that results in its use.

For the more curious, here’s a gist of the pure JavaScript for Drinking Caffeine.

  1. Of that 18KB, 16KB of it is for PrismJS syntax highlighting. If I were fine doing without that, my JavaScript would be a mere 2KB. ↩︎

Javascript Spread Operator in Object Literals Available in Chrome but Not Safari  

Here’s another reason Chrome is better than Safari: because it adapts new JavaScript specifications faster.1 As of Chrome 60, which was released July 25 of this year, you can use the spread operator in object literals. If you pop open your browser console, this will work in Chrome but not Safari.

const user = { firstName: 'Martyn' }
const clonedUser = { ... user }

In Safari, you get this error:

SyntaxError: Unexpected token ‘…’. Expected a property name.

No, hey, sweetie, no.

  1. If you’re the sort of person who thinks this is a mute point because JavaScript shouldn’t be able to run in a browser in the first place, I have nothing to say to you other than that I hope you’re enjoying the weather in Philly. ↩︎