Watch PIP YouTube videos on macOS with pipcorn

With pipcorn you can spawn a picture-in-picture YouTube player on your Mac without installing anything!

Install it globally using npm, or run it directly using npx:

npx pipcorn https://www.youtube.com/watch?v=dQw4w9WgXcQ

Basically it’s a wrapper around ytdl (to get the MP4 URL) and open-pip-cli (to open a PIP player).

Love the name, too.

pipcorn Source (GitHub) →

Wombat Dressing Room, an npm publication proxy on GCP

When automating the publishing of an NPM package, 2FA can get in the way, as you can’t really automate entering a 2FA auth code off a cellphone. Enter Wombat Dressing Room from Google:

With Wombat Dressing Room, rather than an individual configuring two factor authentication in an authenticator app, 2FA is managed by a shared proxy server..

  • You publish to Wombat Dressing Room, and it enforces additional security rules, before redirecting to registry.npmjs.org.
  • Publishes are made from a single npm account with 2FA enabled (a bot account).
  • Publishes can be made using the npm CLI, by making Wombat Dressing Room the default registry (npm config set registry https://external-project.appspot.com).

The Wombat Dressing Room is deployed to Google App Engine. They’ve been using it themselves internally for over a year, in case you were wondering if it is “production ready”.

Wombat Dressing Room Introductory Post →
Wombat Dressing Room Proxy Source (GitHub) →

Building mobile-first web animations in React

Talk by Alex Holachek, as brought forward at React Conf 2019:

As the technology to create Progressive Web Apps continues to mature, React developers have the opportunity to write web apps that in some cases can rival native ones in terms of speed and convenience.

However, one barrier to feature parity is the difficulty of creating a native-like UI transition and interaction experience on the mobile web, especially on lower-end devices.

I’ll be discussing various considerations, tips and techniques to create a web app in React that looks, moves, and feels as close to a native mobile app as possible.

Think of gesture-driven animations like these here:

Slides →
Repo →

Smaller HTML Payloads with Service Workers

Philip Walton on how to progressively enhance your site by leveraging Service Workers to fetch partial HTML content and replace it in the DOM:

On this site, after a user visits once and the service worker is installed, that user will never request a full HTML page again. Instead the service worker will intercept requests for pages and just request the contents of those pages—everything inside the <main> element—and then the service worker will combine that content with the rest of the HTML, which is already in the cache.

By only requesting the contents of a page, the networks payloads become substantially smaller, and the pages can load quite a bit faster. For example, on this site over the past 30 days, page loads from a service worker had a 47.6% smaller network payloads, and a median First Contentful Paint (FCP) that was 52.3% faster than page loads without a service worker (416ms vs. 851ms).

The code is implemented using Workbox:

import {cacheNames} from 'workbox-core';
import {getCacheKeyForURL} from 'workbox-precaching';
import {registerRoute} from 'workbox-routing';
import {CacheFirst, StaleWhileRevalidate} from 'workbox-strategies';
import {strategy as composeStrategies} from 'workbox-streams';

const shellStrategy = new CacheFirst({cacheName: cacheNames.precache});
const contentStrategy = new StaleWhileRevalidate({cacheName: 'content'});

const navigationHandler = composeStrategies([
  () => shellStrategy.handle({
    request: new Request(getCacheKeyForURL('/shell-start.html')),
  }),
  ({url}) => contentStrategy.handle({
    request: new Request(url.pathname + 'index.content.html'),
  }),
  () => shellStrategy.handle({
    request: new Request(getCacheKeyForURL('/shell-end.html')),
  }),
]);

registerRoute(({request}) => request.mode === 'navigate', navigationHandler);

Smaller HTML Payloads with Service Workers →

🔗 Related: Unpoly, which uses HTML attributes to let you control partial fetches.

Full-stack apps with Apollo, a tutorial

The Apollo docs sports a very complete tutorial, combining TypeScript, GraphQL, and Apollo (of course):

In this tutorial, we’ll build an interactive app for reserving a seat on an upcoming SpaceX launch. Think of it as an Airbnb for space travel! All of the data is real, thanks to the SpaceX-API.

To populate the views, our app’s data graph will connect to two data sources: a REST API and a SQLite database.

As we want this example to resemble a real-world Apollo app, so we’ll also add common useful features like authentication, pagination, and state management.

Full-stack apps with Apollo, a tutorial →

Alpine.js – A rugged, minimal framework for composing JavaScript behavior in your markup.

Caleb Porzio‘s “Project X” recently got its official name: Alpine.js.

Alpine.js offers you the reactive and declarative nature of big frameworks like Vue or React at a much lower cost.

You get to keep your DOM, and sprinkle in behavior as you see fit.

It, like Vue which was one of its sources of inspirations, works by adding directives to your markup. Here’s a dropdown example:

<div x-data="{ open: false }">
    <button @click="open = true">Open Dropdown</button>

    <ul
        x-show="open"
        @click.away="open = false"
    >
        Dropdown Body
    </ul>
</div>

Alpine.js →

How to avoid large function signatures by using pending objects

Freek is developing Mailcoach to send out e-mail campaigns. Along with the development of the package he’s recording a video series on how he has created it. In this video he talks about using “pending objects” to make the API more readable.

In this video I demonstrate how to you can create a fluent API by using pending objects. We’ll take a look at how subscribers can be created in Mailcoach. As a bonus I explain how jobs are dispatched using a pending object in Laravel.

// Without pending objects
// ~> What do all these params mean?! 🤔
Subscriber::createWithEmail($email, $attributes, null, true, false, $myList);

// With pending objects
// ~> So readable. Much amaze. Wow.
Subscriber::createWithEmail($email)
  ->withAttributes($attributes)
  ->skipConfirmation()
  ->subscribeToList($myList);

Whilst the implementation is Laravel-specific, it can be applied to any (PHP) project. I especially like the trick where PHP’s __destruct() magic function is leveraged to combine functions with pending objects.

How to avoid large function signatures by using pending objects →

Cloud Run vs App Engine: What’s the difference?

Simple and to the point article, with a few commands included, by Dirk Hoekstra:

In a nutshell, you give Google’s Cloud Run a Docker container containing a webserver. Google will run this container and create an HTTP endpoint.

With Google’s App Engine however you tell Google how your app should be run. The App Engine will create and run a container from these instructions.

Have been using Cloud Run for a few projects recently and I really like it I must say! It just works™ without me having to think about it all too much, whilst also allowing me to finetune the environment.

Cloud Run vs App Engine →

💵 This linked article is stuck behind Medium’s metered paywall, which may prevent you from reading it. Open the link in an incognito window to bypass Medium’s ridiculous reading limit.

Clean code is not a goal


Photo by Kevin Ku on Unsplash

Dan Abramov on how he once overnight refactored a piece of WET code written by a colleague, but then got called out for doing so:

My boss invited me for a one-on-one chat where they politely asked me to revert my change. I was aghast. The old code was a mess, and mine was clean!

I begrudginly complied, but it took me years to see they were right.

There’s a fine balance to be found between code that works for the team and code that is clever/abstract/clean. Sometimes it’s better to write cheap code, as that’s not only cheaper to read, but also cheaper to maintain, cheaper to throw away, etc. — Abstractions are good, up to a certain extent.

On Twitter, Dan also said this about // @TODO comments:

/me nods in approval

Goodbye, Clean Code →

On a related note, be sure to also read Kent C. Dodds’ Avoid Hasty Abstractions