RORK LABJP
MAX — Rork Max builds native Swift apps instead of React Native, targeting the whole Apple ecosystemDEVICES — From one description it spans iPhone, iPad, Apple Watch, Apple TV, Vision Pro, and iMessageNATIVE — It unlocks AR and LiDAR scanning, 3D games with Metal, Home Screen widgets, Dynamic Island, and on-device Core MLSEED — Rork raised a $15M seed led by Left Lane Capital, joined by Peak XV and a16z SpeedrunPAPERLINE — Rork acquired the app builder Paperline and plans to stay acquisitive for engineering talentMARKET — With 743,000+ monthly visits, and Gartner expects 75% of new apps to be low-code or no-code by end of 2026MAX — Rork Max builds native Swift apps instead of React Native, targeting the whole Apple ecosystemDEVICES — From one description it spans iPhone, iPad, Apple Watch, Apple TV, Vision Pro, and iMessageNATIVE — It unlocks AR and LiDAR scanning, 3D games with Metal, Home Screen widgets, Dynamic Island, and on-device Core MLSEED — Rork raised a $15M seed led by Left Lane Capital, joined by Peak XV and a16z SpeedrunPAPERLINE — Rork acquired the app builder Paperline and plans to stay acquisitive for engineering talentMARKET — With 743,000+ monthly visits, and Gartner expects 75% of new apps to be low-code or no-code by end of 2026
Articles/Dev Tools
Dev Tools/2026-07-15Advanced

My Rork sleep timer faded out on time — but the sound didn't

Rork writes sleep-timer fades against the wall clock with setInterval. The numbers say 30 minutes, but the real audio fades early or cuts out abruptly. Here is how to drive the fade from the actual playback position, why a logarithmic curve sounds natural, and the honest limit of JS fades when the screen is locked.

Rork507expo-av6sleep timerReact Native207audiohealing app2

Premium Article

After years of running a healing app called Relaxing Healing, I have learned that the moment the sound disappears shapes how the whole app feels. If the audio cuts off with a click right as someone is falling asleep, they wake up. That is why the sleep-timer fade-out, unglamorous as it is, matters as the final touch.

While prototyping a new healing app in Rork recently, I lost a few hours to exactly this feature. In the simulator the sound faded away beautifully after 30 minutes, but on a real device it felt off — the volume dropped sooner than expected, and the last few seconds cut out sharply. Tracing it back, Rork's generated code stacked up several classic audio-fade pitfalls. Anyone building in this genre will hit the same wall, so here is how I untangled it.

What Rork generates for a sleep timer

Ask Rork to "add a sleep timer that slowly lowers the volume after 30 minutes and stops," and you usually get something like this.

// A pattern Rork tends to generate
const FADE_MS = 30_000; // fade over the last 30 seconds
const TICK_MS = 200;
 
function startSleepTimer(sound, totalMinutes) {
  const stopAt = Date.now() + totalMinutes * 60_000;
 
  const id = setInterval(async () => {
    const remaining = stopAt - Date.now();
    if (remaining <= 0) {
      await sound.stopAsync();
      clearInterval(id);
      return;
    }
    if (remaining <= FADE_MS) {
      const volume = remaining / FADE_MS; // 1.0 -> 0.0
      await sound.setVolumeAsync(volume);
    }
  }, TICK_MS);
 
  return id;
}

It looks correct. It measures the remaining time with Date.now() and ramps the volume down linearly once the fade window opens. And the volume does go down. But this code drifts away from the real audio in three separate layers.

Why measuring against the wall clock drifts

The first problem is that setInterval is anchored to the wall clock. setInterval(fn, 200) does not fire at exactly 200ms. If the JS thread is busy decoding images or rendering a list, that 200ms stretches to 250ms or 400ms. For something like a fade, where smoothness is the whole point, that jitter turns directly into an uneven volume ramp.

Second, sound.setVolumeAsync() is asynchronous. Awaiting it every 200ms means that when the native side backs up, the callbacks pile on top of each other and the volume updates arrive in bursts.

Third, and most easily missed: the audio's playback position and the wall clock do not necessarily advance at the same rate. When the audio session recovers from an interruption (a phone call, another app's sound), or when a loop seam triggers a tiny rebuffer, the position of the sound you actually hear falls behind the wall clock. Watching only the wall clock, the timer decides "we're done" while sound is still playing, and it cuts out mid-fade.

AspectWall-clock setIntervalPosition-driven
Time referenceDate.now()actual positionMillis
When JS is busyinterval stretches, volume jittersnext update snaps to the right volume
After an interruptionsound and time diverge, cuts out earlystays in sync with the sound
Determinismaccumulated error, drifts each runvolume is a pure function of position

Thank you for reading this far.

Continue Reading

What follows includes implementation code, benchmarks, and practical content we hope you'll find useful. This site runs without ads — server and development costs are supported entirely by members like you. If it's been helpful, we'd be truly grateful for your support.

WHAT YOU'LL LEARN
Understand why Rork's setInterval fade drifts away from the real audio, and replace it with a playback-position-driven implementation you can trust
Get the concrete math for why a linear volume ramp sounds like it drops too fast, and how a logarithmic curve fixes the perceived fade
Learn the real limit of JS fades once the screen is locked, and the pragmatic fix of a pre-faded tail asset that always plays to the end
Secure payment via Stripe · Cancel anytime

Unlock This Article

Get full access to the rest of this article. Buy once, read anytime. This site is ad-free — your support goes directly toward keeping it running.

or
Unlock all articles with Membership →
Share

Thank You for Reading

Rork Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • Copy-paste ready implementation code
  • New advanced guides published daily
  • $5/mo or $10 for lifetime access
View Membership →

Related Articles

Dev Tools2026-05-13
Three Things I Got Stuck on When Implementing Ambient Sound in a Healing App with Rork
Three common pitfalls when implementing ambient looping audio in meditation and healing apps built with Rork: loop clicks, iOS silent mode, and battery drain — with working expo-av code.
Dev Tools2026-05-05
Build a Podcast App with Rork: Complete Guide to Background Audio, RSS Parsing & Offline Playback
A complete production-level guide to building a podcast app with Rork. Covers expo-av background audio setup, RSS feed parsing, offline episode downloads, and App Store submission — all with working code examples.
Dev Tools2026-03-28
Build a Music Player App with Rork — Audio Playback Implementation Guide Using expo-av
Learn how to build a music player app with Rork and expo-av. This step-by-step guide covers playback controls, seek bars, playlist management, and background audio with practical code examples.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links
See all →