Skip to content

Building "Today" — A Playdate Companion for Deep Work

Posted on:Aug 19, 2026

I got a shiny lil playdate back in 2024. It’s a cute yellow handheld gaming console with a crank on the side. Made by Panic and Teenage Engineering, it comes with 16 MB of RAM (yes, mb not gb!) Here’s me playing root bear on it.

My playdate My playdate

I was reflecting on how my attention span is shrinking, especially after hitting 30s. Of course, it’s also due to the proliferation of short-form video content but still, the fact remains that I wish to increase my deep work hours.

So I thought why not play around with their SDK and build something? Let the hacking begin!

Requirements

I want to open an app and get into focus mode. It should work for me before anyone else!

  1. I don’t want a forced break in between. Pomodoro worked for me years back but now it doesn’t.
  2. It should be minimal. It should not compete for attention. Getting out of the way is a success metric.
  3. Aim to hit 5 hours of deep work a day.

Design Decisions

  1. No menu or options. Everything is highly opinionated.
  2. App doesn’t let you start a session on weekends.
  3. Play some white noise to get into the zone.

With the above in place, I iterated a few times (56 builds to be exact!) and got to a point where I can use the app myself.

The Sequential Session Ladder

You cannot jump cold into 60 minutes of deep focus. The app acts as a warm-up sequence across 8 distinct ranks:

RankState NameCost to EnterCumulative Work Time
FNewbieStart state0 min
EApprentice5 min5 min
DPractitioner10 min15 min
CProfessional15 min30 min
BExpert30 min60 min (1 hr)
AMaster60 min120 min (2 hr)
SElite60 min180 min (3 hr)
SSChampion60 min240 min (4 hr)
SSSLegend60 min300 min (5 hr)

Once a session ends, the app automatically transitions to the next title card and begins the next rank. You don’t need to manually click to advance.


Custom Ambient Sounds

At first, I spent some time exploring the SDK and found out that I can generate white noise using the synth oscillator (snd.synth.new(snd.kWaveNoise)). But even after trying out multiple variations, that didn’t sound very good. So I decided to use actual audio recordings instead.

I went to freesound.org and listened to 100+ samples. Out of that, I hand-picked 11 samples. Each file was around 20-50 MB. This made the app pretty heavy at 365 MB! The official SDK recommends keeping the app size under 40MB. I ended up with a 3 MB footprint at the end. Let’s see how:

  1. Kept 3 sounds: ocean waves, rain & thunder, forest birds + played them all together.
  2. To make it sound organic, I varied the start offsets, pitch and volume for each track. This prevented the sound from being monotonous. Result: a unique noisescape profile each time!
  3. Normalized all files so one does not overpower the other.
  4. Added a sine waveform for periodic volume breathing to prevent static/monotonous looping textures.
  5. Transcoded them to MP3 at 48kbps mono @ 22.05kHz (Playdate’s hardware features a single built-in mono speaker and 16-bit audio output, making 48k mono @ 22kHz sound virtually identical to the original files)

Hardware Speaker Volume Maximization

  1. Digital Headroom & RMS (Root Mean Square) Peak Boosting: Audio tracks initially had low digital peak headroom (~10% to 30% of max 32767 digital limit), resulting in quiet playback on the physical Playdate mono speaker:
    • Ocean Waves (Original): Peak = 3,461 (9.9% headroom), RMS = 349.5
    • Rain & Thunder (Original): Peak = 10,451 (31.7% headroom), RMS = 264.4
    • Forest Birds (Original): Peak = 8,252 (15.5% headroom), RMS = 279.3
  2. FFmpeg Peak Maximization: Peak-normalized all 3 MP3 files to ~90% digital headroom (~30,000 peak amplitude) without clipping distortion.
    • Ocean Waves (Maximized): RMS = 3017.7 (9x louder digital output)
    • Rain & Thunder (Maximized): RMS = 747.8 (3x louder digital output)
    • Forest Birds (Maximized): RMS = 995.5 (3.5x louder digital output)
  3. Software Gain & Layer Weights: Raised default masterVolume to 1.0 (100%) and increased layer weight ranges to 0.550.95.

I’m happy with the current version. Works as intended!

You can try it out here: https://swapagarwal.itch.io/today