Track Your Average Interval Pace With This Groovy UI  

For a while now I’ve been calculating my average interval running paces by hand. It’s been tedious, and today I needed an excuse to spend some quality time writing Vue. So I updated the little app that’s currently running at Distance.MartynChamberlin.com to include this feature. No more having to compute it all by hand. Here’s a screenshot of what it looks like for one of my recent runs on Strava.1 The UI needs some more refinement but it gets the job done for a 1.0 version.


  1. Admittedly this is a somewhat bizarre example because my lap distance turned out to be 2.00 miles rounded to the hundredth and the pace turned out to be 6:00/mi rounded to the second. What are the chances of deriving such perfect numbers if you tried? ↩︎

Vue Passes React in Popularity  

Dan Abramov, author of Redux, the de facto state manager for React:

Congratulations to @vuejs for surpassing React’s star count on GitHub! Seems like I almost captured a historical moment by accident.

The typical developer on the street thinks that the two winners for frontend web libraries are Angular and React. I’ve been stressing over and over again that there are actually three winners: Angular, React, and Vue. And that Vue, which is the newest of the three, took the best ideas from React and Angular and that it’s actually the best of the three. I’ve spent hundreds of hours in all of these frameworks — in the case of Angular and Vue, thousands of hours. I can say unequivocally that Vue has the lowest learning curve and simplest API, has significantly fewest gotchas, and enables the fastest development cycle, all the while sacrificing nothing in performance. And now I can finally say that in a mathematical, quantitative metric, Vue has surpassed React in popularity. React is officially in the rear view mirror. If you’re wanting to start a new project or migrate a legacy project to one of these new frameworks, choose Vue. By all means, play with the others so you’ll know what you’re saying no to, but come back to Vue. There’s a reason it’s the most starred of the three projects on GitHub.1


  1. Also, if you’re not on the JavaScript Weekly newsletter, you really need to be. It’s the moral equivalent of Drudge Report for JavaScript. ↩︎

Called It  

Ewan Spence, writing at Forbes:

Apple continues to use the proprietary lightning connector on its iOS-powered devices, but that could be set to change. According to a number of suppliers, Cupertino is looking to move the iPhone and iPad lines over to USB-C, just as it has with the MacBook family of laptops.

If this is true, then I was a year premature in what I still consider to be a valid argument. This contemplation makes me unlawfully gleeful because it means I’m going to be right and someone else is going to be very wrong.

Strava Brings Kudos to Other Networks  

Strava:

Our thumbs give kudos for effort and activity, not political rants or latte art. Kudos are how millions of Strava athletes share support for each other and spread positivity in our community, and now we’re spreading it even further.

I’m delighted to see Strava mock political rants and latte art for their uselessness. Strava is a social network for people who are too fit, too busy exercising, to whine and doodle. Strava people ship.

Apple Brings Apple Maps to the Web  

Yuge. Some of the stuff in the opening keynote was of less weight than this; it should’ve gotten a mention. Memoji, for instance. Nobody’s going to use that. Lots of people are going to use this.

The Verge: “Microsoft Has Reportedly Acquired GitHub”  

If true, then this is mind-blowing.1 If you’re a developer working on web technologies, it’s difficult to imagine what Apple could announce tomorrow at WWDC that in the long run would be bigger news than this.

Update: the acquisition is confirmed.


  1. It also makes the top-rated answer on Quora for this question look really silly. Anyone who actually thinks that Microsoft’s Visual Studio Team Services is better than GitHub is laughably insane. I’ve used them both extensively and there’s no comparison. The question at this point is this — will TFS and GitHub continue to exist alongside each other? I’d love to see TFS get cannibalized by GitHub. ↩︎

Back to the Mac  

This afternoon I built a mini web page that I can turn to throughout the workday in solace.

Here’s the thing: I get it. Windows has better enterprise software, and it makes sense that corporate America prefers — nay, mandates — the use of Windows software over Apple software.

But it burdens my heart that WWDC is this upcoming Monday and the only way I’ll be able to stream it from my skyscraper desk is via my iPhone, since Apple understandably restricts playback to its own devices. My Dell Latitude 7480 won’t be able to stream it. [Update: turns out this isn’t true. I was able to stream it from Edge on my Windows machine just fine. Apple’s restriction isn’t an arbitrary choice but rather having to do with whether your browser can support its video streaming requirements. Makes sense.] There are a finite number of months that one can go on in this condition. Using Windows for frontend web development is a losing strategy if you’re used to the finesse and vast superiority of macOS. Again, I quote Steve Jobs:

The problem with Microsoft is they just have no taste. They have absolutely no taste, and what that means is, and I don’t mean that in a small way, I mean that in a big way.

Visual Studio Live Share  

Visual Studio Live Share, announced as public beta three weeks and one day ago, is a game changer that is hard to overestimate. This is much bigger news than when GitHub announced Teletype for Atom in November 2017. Both tools allow one host and multiple guests to view and collaborate on files at the same time, but Visual Studio Live Share goes beyond that by allowing you to also share your computer’s local servers and port numbers — any of your choosing. For example, if you have a NodeJS server running on localhost:9000, or a Ruby on Rails server running on localhost:8080, or a Hugo server running on localhost:1313, you can share any of those with another developer on another network and another operating system. All they have to do is click a link that you provide, fire up a browser to the right port on localhost, and they’ll see exactly what you see on your own computer. Zero setup or configuration on their part required. It’s kind of like turning your computer into a server, except there’s zero hassle and full security. All the host and guest(s) need is VSCode installed, and that’s a fast free download. It’s been a while since I’ve been this excited about something in tech. I wish I’d had this in college. It would’ve been immensely useful.

The Definition of Insanity Is Misleading in Computer Science

The definition of insanity is doing the same thing over and over again and expecting difference results.”

Often this is quoted to mock someone who is trying to achieve something on a computer and duplicating the exact steps multiple times with the same unsuccessful output. But take this example:

<script>
  let i = 0;
  const buttonWasClicked = () => {
    i++;
    if (i === 3) {
      console.log('third time lucky');
    }
  }
</script>

<button 
  onClick="buttonWasClicked()">
  Button of Insanity
</button>

Here we see that the console only gets activity after the third click. While this example is overtly contrived, the principle behind it (i.e. a UI that responds differently depending on a state that itself may or may not be transparent to the end user) is extremely common in software. To develop this out a bit more, there are three kinds of user interfaces in computers:

  1. UIs that have zero bugs or flaws in them. This is Unicorn territory. They almost don’t exist, and when they do, they’re extremely basic UIs that are of little value.
  2. UIs that have bugs that are manifest 100% of the time. This is also pretty rare in software that’s regularly used because the bugs are incredibly obvious and tend to get fixed. Which leads us to the most common type of UIs:
  3. UIs that have bugs that only occur some of the time. One way to think of this is that component B has a bug that in and of itself is never manifest, but becomes manifest if component A gets into a certain state. This category can be sub-divided into two smaller sections.
    1. Sometimes it is the case that component A is by default in a state that causes the bug in component B to be manifest. This results in the bug usually being present, unless you first fix the state of component A. In terms of the above example, think of the <script> as component A and the <button> as component B. The latter has no bugs in it - it correctly wires to a function on the click event. Rather, the bug resides in component A: it only performs an action on the third click (i.e. it has to be in a certain state to work), whereas the user expects the button to perform the action on every click. The button is unreliable, but not completely broken. This is the scenario in which the user gets mocked for being insane. It’s ambiguous to the user if the fix to component A is circumstantial or requires a specific change in their user behavior, but either way, they’re innately aware that component B really will work eventually, they just need to figure out how. This isn’t insanity; it’s working with a UI that was built by a fallible software developer. This is the normal life of a computer user. We’ve all done it many times, and we’ll continue to do it as long as there are computers.
    2. Other times it is the case that component A is by default in a good state, which means component B works most of the time. When your job is to perform Quality Assurance and you get the occasional ticket from a user complaining that something isn’t working, and you test it and it’s working fine, that is caused by this situation. In this case, your job is to test the same thing over and over again with the hope of figuring out what the secret is to reliably breaking it.

In the code example above, you didn’t have to change hardware devices to tease out the working state. You didn’t have to change networks, or get past a blip in the current network. You didn’t have to wait through an outage in a outbound web service. You didn’t have to log out of user A and log in as user B. You didn’t have to switch from one browser to another. Often, you have to do one or more of these things to tease an issue out and get to the bottom of it, but here you didn’t, and often in real life you don’t. You just have to do the exact same thing (from your perspective, though since we know the code, it’s not the exact same thing) more than once.

In computer science there is no such thing as truly trying the exact same thing over and over again, even when, from the perspective of someone looking over your shoulder, you seemingly are. Hardware and software are never in the same state. They are constantly in flux. When a bug is only sometimes present, you may be assured that there is some variance somewhere, and it is your job to find it. It’s time to quit mocking this as insanity; it is what computer scientists do for a living.

The Gangsta Guide to Fixing the Position & Spacing of Footnote Backlinks in Hugo

Currently Hugo has two problems with its backlinks. First, take this multi-paragraph footnote in Markdown:

[^1-2018-05-26]: Some text

    > A blockquote

    Some more text

That renders with the backlink (↩︎) in a dedicated paragraph. It should instead be on the same line as “Some more text.” This is a burden in the land that affects more footnote systems than just Hugo’s, for the record.

The second problem is one that I universally fixed in Jekyll but that persists in Hugo, which is this: the backlink is not connected to the previous element via &nbsp; — there’s rather a pure whitespace. This results in the backlink sometimes appearing on a dedicated line in isolation, due to text-wrapping. Instead, if the backlink must text-wrap to the next line, it should should always take its previous word along with it for improved continuity.

Rather than monkey with Hugo core - I don’t have time for that right now, unfortunately - the solution to both of these issues can be derived with this pure ES6 JavaScript.

const fixFootnotes = () => {
  const footnotes = [...document.getElementsByClassName('footnote-return')];
  footnotes.forEach(footnote => {
    const previousContent = footnote.previousSibling.textContent;
    if (previousContent === '\n ') {
      // Hugo has needlessly created a dedicated DOM node for the backlink, due 
      // likely to a multi-paragraph footnote. The solution is to move the backlink 
      // inline with the last node that actually contains footnote content.
      const whitespace = document.createTextNode("\u00A0");
      [whitespace, footnote].forEach(element =>
        footnote.previousSibling.previousSibling.appendChild(element));
    } else {
      const lastTwoChars = previousContent.substr(previousContent.length - 2, previousContent.length);
      if (lastTwoChars === '\n ') {
        // Replace the whitespace prior to backlink with &nbsp; so the backlink is
        // never a widow.
        footnote.previousSibling.textContent = `${previousContent.substr(0, previousContent.length - 2)}\u00A0`;
      }
    }
  });
};
fixFootnotes();

Sure, it’s coding pretty close to the metal, but it works fantastically. I’m now using this code on Drinking Caffeine, and I invite you to be the judge on its superiority over the default behavior of backlinks in Hugo.1


  1. Once you have a grasp of how to do this level of DOM manipulation with JavaScript, an entire world of control opens up for you. It’s a good feeling. ↩︎

Many Reputable Companies Are No Longer Serving the EU Because of GDPR  

SJW dylanbeattie, on Twitter:

Company says: “Due to the GDPR, we are no longer able to offer our service to customers in the European Union.”

I hear: “You are not a customer. You never were. You are PRODUCT. Now that your privacy is protected by law, you are no longer worth anything to us. Go away.”

What dylanbeattie doesn’t seem to be aware of is that it’s not just the small minority of truly shady businesses that are forced to make changes to get complaint. It’s anyone collecting user data from EU citizens. By its very nature, the World Wide Web is accessible everywhere, including in the EU, which means any website collecting data is by default subject to GDPR’s overreaching jurisdiction. In the case of some very reputable businesses, the hassle of getting compliant with this burdensome mandate is simply not worth the effort. Many web-based businesses are pulling out of serving the EU because it’s not cost effective any more. From the Drip blog:

For some businesses, the cost of becoming GDPR-compliant is higher than not doing business with EU citizens to begin with, especially if you’re not purposefully courting them in the first place.

The soyboys in Clown World haven’t figured it out yet, but GDPR was a mistake.

Chrome Will Flag All Non-HTTPS Sites Starting in July  

From the Chrome Security blog, back on February 8:

For the past several years, we’ve moved toward a more secure web by strongly advocating that sites adopt HTTPS encryption. And within the last year, we’ve also helped users understand that HTTP sites are not secure by gradually marking a larger subset of HTTP pages as “not secure”. Beginning in July 2018 with the release of Chrome 68, Chrome will mark all HTTP sites as “not secure”.

A few thoughts on this.

  • First, a gentle reminder that calling these certificates SSL certificates is no longer using accurate nomenclature, despite some people still clinging onto the term.1 The correct term is TLS. Here’s a good article that explains, if you’re unfamiliar.
  • It’s amusing to me that Google is still using Blogger as its platform for content.
  • I’d love to see a future version of Chrome treat non-mobile-friendly sites with a similar harsh treatment.2
  • Lastly, if you have a site that doesn’t yet adhere to HTTPS, you can get with the program for free with Cloudflare. It’s what Drinking Caffeine has been using for a while now, and it rocks.

  1. GoDaddy, for instance:

    Get a little green lock for your site with a trusted SSL certificate. It shows your visitors that their data is safe, makes Google happy and speeds up load time on HTTP/2. It’s a win-win-win.

    Gross.

    ↩︎
  2. When I run a Google Mobile-Friendly Test on a certain obnoxiously curmudgeon site I get this:

    Page is not mobile friendly
    This page can be difficult to use on a mobile device

    Not groovy, JG.

    ↩︎

Connecting a Dell Latitude 7480 Laptop to an Apple Thunderbolt Display  

In case you’re ever needing to connect a Dell Latitude 7480 laptop to a discontinued Apple Thunderbolt Display, rest assured it’s possible. The Dell has a Thunderbolt 3 port, whilst the Apple Thunderbolt Display has a Thunderbolt 2 cable. The solution is to buy a $49 adapter. I picked one up today at Best Buy and my Thunderbolt Display works as expected, just as if you were connecting it to a MacBook Pro. Good times.

Javascript Trampolines  

This is a brilliant way to write recursive functions that are immune to the concerns of stack overflows. If you write JavaScript at all, I highly recommend pouring over this until you understand exactly what’s going on.

Cappuccino App  

This new reading app from the developers of Airmail looks promising. I’d love for it to replace Unread, which is an elegant app but has no character.1 The biggest thing I’d love to see changed about Cappuccino is the ability to read an entire blog post inside the app. Right now it only shows an above-the-fold excerpt. When viewing an article that is itself a link elsewhere, tapping the headline in Cappuccino takes you to the linked article, not the article that’s reposting it, which means there’s no way to view the full contents of the latter. Still though, it’s a great 1.0 MVP and I’m looking forward to the future polish.

The website cracks me up. Here’s the CSS font declaration:

* {
    font-family: avenir !important;
}

Since I use a Windows for work, this means the site renders as serif. I adore the fact that this team felt no need to try to make the website look decent on Windows. Their customer is someone who uses Apple products, so why should they care how it appears on Windows?


  1. Well, that and it’s used by a crowd that I want to distance myself from because of how laughably ridiculous they’ve gotten in their brazen, nonsensical SJW politics. That’s being reactionary, but whatever. It’s for this same reason that I despise Tweetbot (or I would if I still used or cared one ounce about Twitter, which I do not). ↩︎

Thoughts on GDPR Compliance  

For a while I’ve been wanting to build out a little web page that “types” out text to the screen and decided to do this in tandem with some thoughts on the General Data Protection Regulation (GDPR) that the EU is enforcing later this month.

One fun part of this was to make sure that the text doesn’t print out in a perfectly linear manner, since humans don’t type that way. Think of this as the moral equivalent of the hems and haws in the Google Duplex assistant.

The whole page resides in a single index.html file so feel free to poke around and look at how I built it. The callbacks in the JavaScript got pretty nested but I wanted to keep this as simple as possible and make it compatible in as many browsers as possible without having to resort to a polyfill for async/await.1


  1. Internet Explorer, I’m looking at you. ↩︎

Activating Buttons with the Keyboard in macOS  

Conorgriffin, writing at Stack Exchange:

For many dialog boxes you can select the option you want by pressing ⌘+firstletter where firstletter is the first letter of the option you want to select

I wonder how many macOS users know this combo, as well as the ⌥+⌘+Delete combo for rapidly deleting multiple threads in Messages.

What’s New In Chrome 66 DevTools  

If you make a living writing software that runs in a browser, this is mandatory viewing. The Chrome team is making the world’s best browser more and more great, again and again.

As an aside, it’s intriguing to me that Kayce’s sample at the end is using VueJS, not Angular. Just shows you just how influential Vue is becoming in the developer community.

Concerns Over the UI and UX of Windows 10 Compared to macOS

  • First there is the plague of rich text formatting when pasting from the clipboard. It persists by default across all the major applications, which is wrong; the clipboard should copy text as plain text, not rich text. There are many, many times in chat messaging and email where it is obvious that data was copied and pasted and took on an unwanted form. There are very few instances in which this is actually desired. This problem afflicts Skype for Business, Outlook, and OneNote, among others.1 2
  • Related, selecting text for the clipboard is a hassle. You know how it’s hard to select text in iTerm in macOS? Imagine if every major app was that hard to select, and that gives you an idea of how hard it is in Windows 10. By the time you’ve managed to actually select and copy some text, you don’t even care that it’s going to come out as rich text formatting. You’re just thankful you didn’t have to type it out all by hand like a slave. The software makes you work for it.
  • The operating system contains zero rounded corners. This is wrong. It creates mental fatigue. macOS correctly understood early on that rounded corners are important. Andy Hertzfeld:

    Steve [Jobs] suddenly got more intense. “Rectangles with rounded corners are everywhere! Just look around this room!”. And sure enough, there were lots of them, like the whiteboard and some of the desks and tables. Then he pointed out the window. “And look outside, there’s even more, practically everywhere you look!”. He even persuaded Bill to take a quick walk around the block with him, pointing out every rectangle with rounded corners that he could find.

  • Split screens are a nightmare to work with. On macOS, when you have two windows that share a screen, and you go to resize them, they always stay connected, and the blur that occurs on one of the windows is beautiful. On Windows, when you go to resize, an ugly vertical bar is the only thing that appears whilst you move your cursor, and then the windows redraw only when you release your cursor. They divorce very easily too, and while getting them glued back together is achievable, it’s a feat of patience. The software makes you work for it.

  • The methodology for getting to the unlock screen is archaic and idiotic. On macOS you merely tap any key on the keyboard, or move the mouse or trackpad, and you’re presented with the login screen. On Windows, you have to hit a key combination, CTRL + ALt + DELETE, before you can get to the login screen. This key combination is difficult to achieve with a single hand, and there is no need for it. You save no battery by making it harder to get to the login screen - tapping a key wakes up the computer just as much as it does on macOS. Rather, it merely creates an unnecessary step. It’s wasteful. It’s inefficient. Much of the OS is like this. I’m sure there’s a lengthy business explanation about why it’s needed, about how it came into being, about why it makes sense, about why Microsoft can’t get rid of it for reasons X and Y. But you know what? macOS figured out how to not need it, and macOS is used in business a lot, so it’s a solvable problem.

  • There is lunacy in having to open a second window by re-opening the same application. If I’m in Terminal on macOS and I want a new window, I just hit CMD + N. But in Windows, if I’m in Command Line and I want a new window, I have to go to the Start menu, search for it in the cluttered menu system, and reopen the application as though I have zero windows open. This is wasteful and counterintuitive.

  • The OS gets easily confused by having a non-high-density external monitor connected to a high-density laptop display. For example, let’s say you have a Chrome window open on the external monitor, and you accidentally hit CTRL + S, since the keys are mapped incorrectly on Windows. The dialog for saving the window appears at twice the size (i.e. it displays at @2x resolution of what it should be, thereby making it twice as big) because the OS thinks you’re handling this on the laptop high-density screen. Maybe this is just a Chrome bug, I don’t know. All I know is that this sort of thing happens a lot on Windows and it never happens on macOS on an identical setup.

  • And then there is the inferiority of the scrollbars that plague every application in Windows. On macOS and iOS, the presence or absence of a scrollbar within a UI does not affect the overall available width of that UI’s inner content, but it does in Windows 10. This means that text on a web page jumps around when the width changes. This occurs quite often. If you toggle something that adjusts the height of the page content, such that it goes from all fitting above the fold to not all fitting above the fold, you’ll introduce a scrollbar, and thereby inadvertently change the page width, which shifts the entire page content to the left. This also occurs when you open a hamburger menu or modal that overlays the screen and locks it with body: { overflow: hidden }.

There are other problems of course, but these are the ones that I’m reminded of every time I use Windows.

My experience is that most Windows aficionados either have never realized these innate problems with the operating system, or else they’re aware of them but simply don’t think they’re that big of a deal. But if you’ve used macOS for thousands of hours and can appreciate the difference between good software that works for you versus poor software that you must work for, you’ll see a night and day difference between the two operating systems. Windows has had many years to catch up with macOS and it hasn’t. At this point I’m not sure it ever will.

Steve Jobs in 1995:

The problem with Microsoft is they just have no taste. They have absolutely no taste, and what that means is, and I don’t mean that in a small way, I mean that in a big way.

23 years later, this still holds true.


  1. OneNote is truly a train wreck of an app, as is Skype for Business, but I won’t go into app-specific problems in this piece. ↩︎
  2. In fairness, this problem is a scourge for Notes in macOS. It’s largely for this reason I find Notes to be unusable (well, that and its unbearable color scheme and use of text shadow). Notes is one of the weakest applications in macOS. Thankfully it’s the of the very few default apps in macOS that doesn’t adhere to plain text formatting when pasting from the clipboard. ↩︎

It’s Not About the Code

The writing of software is only a small part of being a software developer. The other things that surround this — the human factors, the acceptance of business leadership and decision making that are outside the developer’s control, the grasping of the backstory of how a code base came into being in the precise way that it did, and the comprehension of why a change needs to be made and how and where to make it — all of these things combine to describe what it means to be a software developer. The actual writing and shipping of code is the very last step in an important process that involves many persons within a company, all of whom possess varying degrees of leadership and influence. This upstream process, though sometimes deemed by the developer to be tedious and plagued with inefficiencies, is crucial; it’s what separates startups who one day hope to be relevant from established companies who pay their way, make profit, and drive industry.

Any intelligent punk can write new code from scratch. That is what is taught and learned in university. That is the fun part, the easy part. Knowing how to implement software change in a preexisting, and therefore antiquated,1 project that’s already being used in a production context is the part that brings home the bacon. Knowing how to do this within the confines, constraints, and challenges of a technical team that is answerable to a higher, more powerful business team with minimum friction and maximum cohesion whilst striving to maintain integrity in the code is the job of the software developer. It’s a high calling, and the biggest mistake a developer can make is to presume that it’s all about the code. Ultimately the code has one job - to serve the best interests of the company, as defined by the business. The code is a means, not an end. The code needs to be the best is can possibly be, of course; but the code is not the purpose for which the company exists. It’s not about the code.


  1. Any software that has managed to survive long enough to see the light of production is by definition antiquated. ↩︎

How to Setup CSS Modules in Aurelia and Webpack 4

As of this writing, if you google “css modules in aurelia” the top two results are:

  • An NPM package that is deprecated.
  • A Medium article where the guy says “I haven’t beaten this one yet, but I’m getting close.” Then later on, “I’ll have to follow up with another post if I am ultimately able to get it all playing together nicely.” Which he never did.

If you dig into the comments of that Medium article though, you’ll find the solution by Sayan Pal, which I’ve confirmed in a working project. Essentially the solution lies with something like this:

// webpack.config.js
const cssRules = [
  {
    loader: 'css-loader',
    options: {
      modules: true,
      localIdentName: '[name]__[local]',
    }
  },
  // You can omit this loader if you're not wanting to support SASS.
  // But you should be wanting to support SASS. :)
  {
    loader: 'sass-loader',
  },
];

module.exports = {
  // Obviously your actual config file will have more than this in it.
  // This just demonstrates the modularized piece of it.
  module: {
    rules: [
      cssRules,
    ],
  },
};

In Sayan’s example, his localIdentName also includes a ___[hash:base64:5] piece which I personally don’t think you should ever need. You shouldn’t ever have two CSS files that are named the same thing, just like you shouldn’t ever have two view-models or views that are named the same thing, and CSS files have a one-to-one correlation to those if you’re going the modularized route. Hence, the double guarantee of uniqueness by appending a hash at the end of the classname merely serves to bloat the DOM and the resulting stylesheet, and it’s wasteful. But I digress.

Let’s say you create a hello-world.scss file that looks like so:

/* hello-world.scss */
.component {
  padding: 25px;
}

Next, per Sayan’s example, you’ll have a view-model that looks something like this:

// hello-world.js
const styles = require('./hello-world.scss');

export class HelloWorld {
  styles = styles;
}

Then in your view you’ll have something that looks like this:

<!-- hello-world.html -->
<template>
  <div class.one-time="styles.component">Hello world</div>
</template>

On Aurelia’s roadmap for 2018 is to get single-file component support. From the blog:

While Aurelia has focused primarily on optimizing UI workflows for teams working on the same components in parallel, we realize that smaller teams and individual developers have different workflows and needs. To address this, we’re hoping to enable a single-file component development story in 2018.

When that day comes, this solution should continue to work. Until then, you might wish you could import the CSS directly into the HTML files via a require tag, instead of importing it into in the JS files. After all, when the views can play musical chairs with the view-models, you’re allowed a level of dynamism that you can’t have with single-file components; you can mix and match different views with other view-models. Instead of a one-to-one relationship you can have a many-to-many relationship.

There are a couple of problems with importing modularized CSS into HTML files in Aurelia, however. First, you can’t extract CSS via the mini-css-extract-plugin when you’re using this sort of syntax in your HTML files:

<!-- hello-world.html -->
<template>
  <require from="./hello-world.scss" />
</template>

At least, if it’s possible, I haven’t seen how.

Moreover, even if you could do that, I’m don’t know how you would associate that CSS to its view-model instance. Clearly, modularized CSS in Aurelia can only work in the context a specific (i.e. non-dynamic) view-model. Unless of course you manually hand-write the compiled class names, like so:

<!-- hello-world.html -->
<template>
  <div class"hello-world__component">Hello world</div>
</template>

But nobody wants to do that.

The good news is that this will be a moot point once single-file components come around. We won’t be thinking in those categories at that point; we’ll have a one-to-one understanding of views and their view-models, which is (respectfully) how it should have been all along.1


  1. When it comes to Aurelia’s MVVM pattern, every single nifty, elegant thing you can do with a many-to-many relationship of views and view-models you can achieve with a one-to-one relationship. That’s a separate topic for another time. For now, suffice it to say that the secret is in having smart components and dumb components, i.e. HOC. ↩︎

CssGradient.io  

For years, whenever I’ve needed to create a CSS gradient I’ve this tool, which has served well. But of late, a new tool has come to the forefront. When you google “css gradient” the first result is now cssgradient.io. Today I checked it out and I was floored. Every now and then you enter a place that you immediately can tell has been carefully assembled by someone who really knows their craft. This is one of those places. The site can sing and dance. It’s built by a designer named Moe Amaya. He’s in a whole other league and I recommend checking out his other stuff too. Meanwhile, this gradient site is the site for all things gradients. It’s such a delightful app. Fantastic work.

The Dots Do Matter  

Fascinating story. You can argue that this is primarily Google’s fault, but if I were Netflix, I would change the product so you’re required to confirm your email address. If Netflix enforced that then this entire story could never have occurred. Confirming your email address is standard app behavior. I’m surprised Netflix doesn’t do this.

GitHub Requests a Username Change  

If I had to guess, the engineers were working through a weird bug or security patch issue and had a facepalm moment when they realized that the solution was to remove the malware username. It’s an embarrassing enough situation that I get why the company wouldn’t feel comfortable divulging to Joël the nitty gritty reasons of why the change was necessary.

Or maybe the change was just a stuffy corporate change dictated by the cyber security team. But I like to think it was the former.