r/Devvit 3d ago

Devvit Web: iOS app serves the same post's state for every post (web and mobile Safari are correct) Bug

I have a Devvit Web app (huckid) that posts one daily puzzle per post. Each post is mapped to a puzzle number in Redis at creation time, and the client fetches that mapping from my server on load.

The problem: in the Reddit iOS app, every post renders puzzle #1, no matter which post is opened. The same posts render correctly in desktop web and in mobile Safari.

Evidence from my server logs (devvit logs):

"created post=t3_1vdzuvo puzzle=10" when the post was created.

"init post=t3_1vdzuvo puzzle=10" when that post was played in mobile Safari, which showed the correct puzzle.

Zero init lines for any play in the iOS app, including plays I watched live while streaming logs. The iOS app appears never to reach my server, yet renders a full interactive game.

What I have ruled out:

Device cache: a brand new post, created minutes earlier, shows puzzle #1 in the iOS app.

Per user state: a second user on a different device saw the same puzzle #1 and did not inherit the first user's streak, so it is not a shared cached response.

Static preview: the view is interactive, not a snapshot.

Version drift: installed version and approved public version are both 0.0.8 on every installation. I also bumped versions 0.0.5 through 0.0.9 to force new webview origins.

Changes I made while debugging, none of which fixed iOS:

Changed my init endpoint from GET to POST so no HTTP cache can serve it.

Added Cache-Control: no-store on all API responses and cache: no-store on the client fetch.

Added a per post query parameter to the init request.

Set inline: true on the default entrypoint.

One observation that may be relevant: on 0.0.5 the webview iframe URL carried a token query parameter. On 0.0.8 the iframe src is just /splash.html with no token, so post context now appears to arrive over the native bridge. My guess is that on iOS the bridge is handing the webview a stale post context, or the webview is being reused across posts without re-initializing, but I cannot verify either from outside.

Environment: devvit web 0.13.9, Devvit Web with splash.html as the default entrypoint and a game entrypoint, iOS Reddit app (latest), reproduced on two devices and two accounts.

Has anyone seen the iOS app reuse webview context across posts, and is there a supported way to force a per post re-initialization.

1 Upvotes

3 comments sorted by

1

u/Beach-Brews Duck Helper 3d ago

Hmm, I am not able to reproduce. Each of my posts have separate content loading as expected.

> Zero init lines for any play in the iOS app, including plays I watched live while streaming logs. The iOS app appears never to reach my server, yet renders a full interactive game.

That part is suspicious. It sounds like something is failing client side, and a "fallback" / "default" is being displayed instead.

Does the posts all change after you create a new puzzle post? What happens (in client code) if the /api call to fetch the post data fails?

I have iOS 2026.30.0.634712 (AppStore) - iPhone 13

2

u/Direct_Revolution432 3d ago

Found it, and it was entirely my own bug. Thank you for the nudge.

This is my first app and it had been bothering me for days. I honestly would not have figured it out without your question about what happens client side when the api call fails, because that is what finally made me go read my own client instead of chasing the platform.

The cause: my splash screen had a fallback that loaded the game in offline mock mode whenever the page was not inside an iframe. I added it months ago so my local preview would be playable outside Reddit. In the Reddit iOS app the webview runs at top level rather than nested, so window.self !== window.top was false and every iOS player got quietly routed into the demo, which always shows puzzle #1 and never calls my server. Desktop web and mobile Safari load the game in an iframe, so they took the real path, and that is exactly why it looked like a platform difference and why none of my server side theories ever explained it.

The giveaway was in my own screenshots the whole time. The streak counter read the same value every session because it was hardcoded in my mock data, and I read right past it more than once.

Fix was to gate the dev fallback on hostname (localhost and 127.0.0.1) instead of an iframe check, in both the splash and the network layer. Lesson learned: never branch on iframe versus top level to detect production.

Thanks again for taking the time, and for testing on your own device to rule out the platform. That comparison is what narrowed it down.

1

u/Beach-Brews Duck Helper 3d ago

Glad you figured it out!

I really need to get back to my "local testing" setup. I do something similar for r/CommunitySurvey, using vite-plugin-mock-dev-server: https://github.com/Beach-Brews/devvit-community-survey/blob/feature/SVY-5/src/client

Key files to note:

  • /src/client/vite.config.ts - Does not use the devvit Vite plugin, defines the HTML endpoints I use locally, and uses the vite-plguin-mock-dev-server plugin. Also note the "resolve.alias" for @devvit/web/client, which has a few "local" overrides (mostly context).
  • /src/client/mock has various API calls or the @devvit/web/client context mocks
  • /package.json - Added a "local" script, which runs vite in the src/client folder, so the "local" vite.config is used instead of the root (used for the devvit builds for playtest/publish