King Arthur Bake Mode

Happy Thanksgiving!

Earlier this month I was making the King Arthur Cardamom Buns and I saw this little Bake Mode toggle:

Bake Mode toggle in its inactive state

Bake Mode toggle in its active state

I used it as I continued to bake the buns, but all the time I was thinking, "That's really useful considering my hands are covered in flour and I don't want to type on my keyboard or whatever to have to wake the laptop up again." I was curious how it works because there are surely all kinds of battery and security implications for something that forces a device to stay active, right? So I wanted to dig into what Bake Mode is and how it works.

So first off, that toggle is just a little checkbox control:

<div class="cook-mode">
  <div class="cook-mode-toggle">
    <input class="visually-hidden" type="checkbox" id="cook-mode-toggle" />
    <label for="cook-mode-toggle">
      <svg xmlns="http://www.w3.org/2000/svg" width="47" height="24" viewBox="0 0 47 24" fill="none">
        <rect x="0.547241" y="0.5" width="45.0741" height="23" rx="11.5" fill="#EBEAEA" stroke="#CBCBCB"></rect>
        <ellipse cx="12.6128" cy="12" rx="8.3771" ry="8" fill="#CBCBCB"></ellipse>
      </svg>
      <span class="cook-mode-label">Bake Mode</span>
    </label>
  </div>
  <div class="cook-mode-description">Prevent your screen from going dark as you follow along.</div>
</div>

This control toggles this Drupal behavior:

Drupal.behaviors.cookMode = {
  nosleep: undefined,
  attach: function(context, settings) {
    once('cook-mode', '#cook-mode-toggle', context).forEach(function(toggleEl) {
      let noSleep = new NoSleep();
      toggleEl.addEventListener('click', function() {
        if (toggleEl.checked) {
          toggleEl.closest('.cook-mode').classList.add('checked');
          noSleep.enable();
        } else {
          toggleEl.closest('.cook-mode').classList.remove('checked');
          noSleep.disable();
        }
      });
    });
  }
}

Admittedly I don't know a ton about Drupal, but from what I can tell, a behavior is any kind of custom, globally available function in your Drupal app. If anyone is a Drupal expert, please feel free to correct me (reach out at joey@joeyreyes.dev). In this case, it's adding and removing checked to/from the .cook-mode element class list, which is just the toggle (to indicate that Cook/Bake Mode is active or inactive). It also calls a NoSleep() constructor. When the toggle is active, it calls noSleep.enable() and when it's inactive, it calls noSleep.disable().

Screen Wake Lock API

So what is NoSleep()? What could control whether your device can go to sleep or not?

In my research, I learned that there's a Screen Wake Lock API that's fairly new (released in Chrome last July) that does exactly this. Here's an abbreviated example from MDN:

// locking the screen from going to sleep:
let wakeLock = null;

try {
  wakeLock = await navigator.wakeLock.request("screen");
  statusElem.textContent = "Wake Lock is active!";
} catch (err) {
  // The Wake Lock request has failed - usually system related, such as battery.
  statusElem.textContent = `${err.name}, ${err.message}`;
}

// ...later on, releasing the lock and letting the screen sleep:
wakeLock.release().then(() => {
  wakeLock = null;
});

wakeLock.addEventListener("release", () => {
  // the wake lock has been released
  statusElem.textContent = "Wake Lock has been released";
});

However, the Screen Wake Lock API has pretty terrible browser support (not currently available in Firefox or Safari). If you want to use it, here's a blog post from Michael Walter Van Der Velden that adds some try...catch boilerplate to do a check if your browser supports it or not.

So then what is King Arthur's website doing differently to make this work across all browsers?

NoSleep.js

It turns out they're using a library called NoSleep.js. From a quick search, it appears that when you call noSleep.enable() (like in the Drupal behavior above), it plays a tiny, empty, silent MP4 video on the page on infinite loop until you call noSleep.disable() (or close that browser tab or whatever). If a video is playing on an active browser tab, your device won't go to sleep. Huh.

So yeah, this is what happens when you go into "Bake Mode" on the King Arthur site: a tiny, empty video plays to keep your device awake.

For what it's worth, I also found nosleep.page, which isn't a library, but just a page that puts both the Screen Wake Lock API and NoSleep.js approaches together. It first checks whether the Screen Wake Lock API is available in your browser and uses that if so, otherwise it uses NoSleep.js.

Anyway, I just found all of this interesting. I'll also say that the cardamom buns turned out super delicious, but next time I'll reduce the amount of cocoa powder.