◉RORK LABJP
●SDK58 — Expo SDK 58 is still in beta (September 15). Stable lands after React Native 0.88 ships, planned for October 12, and Expo Modules 2.0 stays beta until then●10/22 — 24 days until Apple opens Volume Purchasing. Multiseat purchases have been on by default since September 16, so decide now whether to keep them●REVIEW — A common question: the automated pre-review check flags a missing entitlement you never added. One developer opened the .ipa, confirmed it, and passed without a rebuild●NEW — Building the same list screen with Opus 5.5 and GPT-6 Sol, and how we chose effort●NATIVE — After Shopify's back-to-native post, someone built the same app in React Native and native and measured on device. Useful input for any migration debate●CREDITS — How far does "no credits for AI errors" actually go? We are logging a day where the same fix was requested three times to draw the line●SDK58 — Expo SDK 58 is still in beta (September 15). Stable lands after React Native 0.88 ships, planned for October 12, and Expo Modules 2.0 stays beta until then●10/22 — 24 days until Apple opens Volume Purchasing. Multiseat purchases have been on by default since September 16, so decide now whether to keep them●REVIEW — A common question: the automated pre-review check flags a missing entitlement you never added. One developer opened the .ipa, confirmed it, and passed without a rebuild●NEW — Building the same list screen with Opus 5.5 and GPT-6 Sol, and how we chose effort●NATIVE — After Shopify's back-to-native post, someone built the same app in React Native and native and measured on device. Useful input for any migration debate●CREDITS — How far does "no credits for AI errors" actually go? We are logging a day where the same fix was requested three times to draw the line
Articles/App Dev
◇ App Dev/2026-09-29Intermediate

Your Expo Router App Flashes the Sign-In Screen on Every Launch. Rebuild the Guard With a Third State: Not Known Yet

Signed in, yet the sign-in screen flashes at launch; signed out, yet the screen never changes. How I rebuilt Expo Router Protected routes around three Supabase auth states, including the one the docs never name, and where the _layout.tsx files have to live.

expo-router3Supabase35authentication5Protected routesRork574

✦ Premium Article

The evening I connected Supabase sign-in to a prototype I'd built in Rork, I kept relaunching the app on my iPhone. I was signed in. And yet, on every launch, the sign-in screen appeared for a split second before the home screen took over.

At first I told myself it was my imagination. Then I recorded the screen and stepped through it frame by frame, and there it was: the sign-in screen, drawn and then discarded. A second symptom rode along with it. Tapping sign out changed nothing on screen; only killing the app and reopening it brought the sign-in screen back.

The same symptoms are gathered in expo/expo issue #37305. It has been open since June 2025, with 26 comments so far: people stuck on a black screen, people whose sign-out never refreshes the view, people who copied the documentation word for word and still got nowhere.

What I'd like to say first is that Protected routes were not broken. I was. I had been holding "is this person signed in?" as a yes or a no, and reality has a third answer, "I don't know yet." At launch, an app is almost always sitting in that third state.

I was forcing a three-valued reality into a two-valued guard

Stack.Protected takes a boolean guard. Signed in means true, otherwise false. That design is fine.

The trouble was what I did with the moment right after launch, when the session hadn't been read yet. I rounded it down to false. While session was null, the app treated me as signed out and drew the sign-in screen. A few hundred milliseconds later the session finished loading, the guard flipped, and the home screen replaced it.

Actual stateTwo-valued guardWhat gets drawnThree-valued handling
Not read yetfalse (null rounded down)Sign-in screen, brieflyDraw neither
Signed outfalseSign-in screenSign-in screen
Signed intrueHomeHome

It was the same shape as a bug I'd fixed in my wallpaper app, where a test device with the ad-free purchase showed one ad right after launch. The purchase state hadn't finished loading, and the code treated "not loaded" as "not purchased." The moment I introduced a "not known yet" state, the ad stopped appearing. As an indie developer I've fallen into this hole more than once, and here I was falling into it again with authentication.

While the answer is unknown, draw neither screen. The entire fix fits in that sentence.

What you need

PieceRequirementNote
An Expo project generated by Rorkexpo-router 5 or later (SDK 53+)Protected routes arrived in SDK 53
@supabase/supabase-jsv2The version Rork installs via Connect Supabase is enough
expo-splash-screenBundledUsed to hold the splash while the state is unknown
A device or Expo GoOne iOS or Android deviceSomething that can record its screen makes verification easier

A project connected through Rork's Connect Supabase already has a client along the lines of lib/supabase.ts, storage adapter included. Keep all of it. The only thing we replace is how the auth state is held.

✦

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
✦You'll be able to trace the sign-in flash at launch back to the exact value your _layout.tsx hands to guard, instead of guessing
✦You'll have an AuthProvider that holds three states, not known, signed out, and signed in, wired to Supabase and Expo Router in a form that runs today
✦You'll avoid the black screen and the stuck sign-out that fill a 26-comment issue thread, by placing group layouts correctly and keeping guards flat
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 $15 for lifetime access
View Membership →

Related Articles

⬡ Dev Tools2026-03-25
Rork × Supabase Auth & Realtime Guide — Building a Backend Without Code
Learn how to combine Rork with Supabase to implement authentication and real-time data sync. A practical step-by-step guide from user registration to real-time chat functionality.
◇ App Dev2026-09-18
The three lines I check when prebuild stops on the standard SDK 57 Swift AppDelegate error
Turning on ios.enableSceneSupport for iOS 27 can stop prebuild cold. The cause was not my SDK version but the shape of AppDelegate.swift. Here are the three lines to check, and why copying the SDK 58 migration steps by hand will break your build.
◇ App Dev2026-09-16
The Token I Deleted Came Back After a Restart — Detecting Failed SecureStore Deletes
On Android, getItemAsync can report null right after sign-out while the value is still sitting on disk. Here is how I rewrote a sign-out path that was verifying deletion by reading instead of by the delete result.
📚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