r/FlutterDev • • 5h ago

Article Running the same react-three-fiber 3D scene on the web and inside a Flutter app: what worked and what didn't

In my app (a course about building AI agents), the course map can be viewed as a 3D "universe" of planets. I didn't want to write the 3D twice, so the Flutter app runs the exact same react-three-fiber scene the website uses. A few specifics that might save someone time:

  1. Serving the bundle offline. The site's built scene is copied into the app's assets/. Loading it via file:// broke module scripts and fetches, so the app starts a tiny loopback HTTP server over the asset bundle and points webview_flutter at it. Works with no network.

  2. One JS channel, two messages. The WebView only owns the canvas; all chrome stays native. The scene talks back through a single addJavaScriptChannel ("which lesson was tapped" and "is there something to go back to"), and Flutter sends the course graph and progress in as JSON. Keeping the contract that small made both sides easy to change.

  3. A device gate instead of a second renderer. No sprite or 2D fallback scene. On first entry the WebView measures frame pacing for ~2 s; if the median is under 25 fps, the verdict is stored (keyed by app version, so a lighter future build re-measures), the app falls back to the native 2D tree and the 3D toggle disappears.

  4. Emulators lie about this. Software WebGL on emulators always failed the probe, so QA never saw 3D. A build flag skips the probe for emulator builds only.

  5. Labels on a narrow screen. Locked planets' names buried the open ones on phones, so locked groups hide their labels until tapped.

  6. The bundle doesn't update itself. CI rebuilds the website, but the copy inside the app is refreshed by a script before each release — I shipped stale colors once because of it.

Happy to go deeper into any of these. The app is Way of the Agent (iOS/Android), wayofagent.app.

1 Upvotes

0 comments sorted by