feat: web support [#237]#362
Conversation
There was a problem hiding this comment.
Pull request overview
This PR adapts the Clerk Flutter + Dart SDKs to work on web by removing dart:io-based image/file handling, introducing conditional IO/web persistors, and switching image/logo/avatar flows to operate on raw bytes (Uint8List) with web storage via IndexedDB/localStorage.
Changes:
- Replace
File-based image handling withUint8Listacross auth APIs and Flutter widgets (useImage.memory). - Split persistors into IO vs web implementations via conditional exports; add an IndexedDB-backed file-byte cache on web.
- Add web-focused dependencies (
universal_io,web) and a browser-only test scaffold for the web persistor.
Reviewed changes
Copilot reviewed 36 out of 36 changed files in this pull request and generated 11 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/clerk_flutter/test/utils/default_caching_persistor_web_test.dart | Adds browser-only tests for the web persistor behavior. |
| packages/clerk_flutter/pubspec.yaml | Updates dependencies (adds universal_io/web, changes clerk_auth reference). |
| packages/clerk_flutter/lib/src/widgets/user/clerk_user_profile.dart | Switches profile image update API from File to Uint8List. |
| packages/clerk_flutter/lib/src/widgets/user/clerk_user_button.dart | Switches org creation logo parameter from File to Uint8List. |
| packages/clerk_flutter/lib/src/widgets/ui/platform_styled_dialog.dart | Replaces dart:io platform check with universal_io. |
| packages/clerk_flutter/lib/src/widgets/ui/editable_profile_data.dart | Reads picked images as bytes and passes Uint8List through callbacks. |
| packages/clerk_flutter/lib/src/widgets/ui/clerk_cached_image.dart | Renders cached images from bytes via Image.memory. |
| packages/clerk_flutter/lib/src/widgets/ui/clerk_avatar.dart | Allows avatar override via bytes instead of a File. |
| packages/clerk_flutter/lib/src/widgets/organization/create_organization_panel.dart | Reads logo bytes and uses Image.memory preview. |
| packages/clerk_flutter/lib/src/widgets/organization/clerk_organization_profile.dart | Updates org logo update path to accept Uint8List. |
| packages/clerk_flutter/lib/src/widgets/organization/clerk_organization_list.dart | Wires org creation panel submission to Uint8List logo. |
| packages/clerk_flutter/lib/src/utils/get_cache_directory.dart | Adds conditional export for cache directory getter. |
| packages/clerk_flutter/lib/src/utils/get_cache_directory_web.dart | Web cache directory getter returns null. |
| packages/clerk_flutter/lib/src/utils/get_cache_directory_io.dart | IO cache directory getter uses path_provider. |
| packages/clerk_flutter/lib/src/utils/default_caching_persistor.dart | Adds conditional export for IO vs web caching persistor. |
| packages/clerk_flutter/lib/src/utils/default_caching_persistor_web.dart | Implements web persistor + IndexedDB byte cache and network fetch. |
| packages/clerk_flutter/lib/src/utils/default_caching_persistor_io.dart | Updates IO persistor to cache/stream bytes instead of File. |
| packages/clerk_flutter/lib/src/utils/clerk_file_cache.dart | Changes ClerkFileCache.stream contract to return bytes. |
| packages/clerk_flutter/lib/src/utils/clerk_auth_config.dart | Uses conditional cache-directory getter when constructing default persistor. |
| packages/clerk_flutter/example/pubspec.yaml | Switches example to local path deps for clerk_flutter/clerk_auth. |
| packages/clerk_flutter/example/macos/Flutter/GeneratedPluginRegistrant.swift | Updates generated plugin registration list. |
| packages/clerk_flutter/example/lib/main.dart | Removes exit(1) usage and returns instead (no dart:io). |
| packages/clerk_auth/pubspec.yaml | Adds universal_io/web deps and normalizes quoting. |
| packages/clerk_auth/lib/src/utils/logging.dart | Switches to universal_io and gates stdout.flush() for web. |
| packages/clerk_auth/lib/src/models/api/api_response.dart | Uses universal_io HttpStatus for web compatibility. |
| packages/clerk_auth/lib/src/clerk_auth/persistor.dart | Removes IO-only DefaultPersistor implementation from the shared file. |
| packages/clerk_auth/lib/src/clerk_auth/persistor_web.dart | Adds web DefaultPersistor backed by localStorage. |
| packages/clerk_auth/lib/src/clerk_auth/persistor_io.dart | Adds IO DefaultPersistor backed by filesystem JSON cache. |
| packages/clerk_auth/lib/src/clerk_auth/persistor_default.dart | Adds conditional export to pick IO vs web persistor. |
| packages/clerk_auth/lib/src/clerk_auth/http_service.dart | Removes dart:io dependency (uses pure http). |
| packages/clerk_auth/lib/src/clerk_auth/auth.dart | Updates avatar/logo APIs to accept Uint8List instead of File. |
| packages/clerk_auth/lib/src/clerk_api/token_cache.dart | Uses universal_io for headers/constants. |
| packages/clerk_auth/lib/src/clerk_api/telemetry.dart | Uses universal_io for web-safe IO symbols. |
| packages/clerk_auth/lib/src/clerk_api/api.dart | Switches uploads from File to byte uploads (Uint8List). |
| packages/clerk_auth/lib/clerk_auth.dart | Exports conditional default persistor entry point. |
| packages/clerk_auth/lib/clerk_auth_persistor_web.dart | Adds explicit web-only persistor entry point for web consumers. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
Hey @Silfalion 👋 Thank you for your contribution with this PR.
I've pushed these changes to your branch: Make sure you pull the changes before pushing to your branch |
40ab3a4 to
778acc3
Compare
|
I've fixed the merge conflicts after rebasing this branch on top of |
|
Hi @MarkOSullivan94 👋 Thank you as well for taking the time to check it. The lack of UI is due to the change in dependencies of clerk_auth. The PR works on both packages so clerk_flutter needs to use clerk_auth from the PR instead of the published one. Regarding this specifically, I should've mentioned a pubspec_overrides.yaml was needed for testing, sorry. Could you check again after adding it, please? |
|
@Silfalion I've just pushed another two commits, one is to add passkeys-js bundle which is required by |
|
No worries at all! And thank you for the commit. |
|
@Silfalion can you adjust the title and the description of the PR? The standard we use for the title is something like this:
We always do this for the description:
|
|
Of course, should I reference this issue? |
|
Done @MarkOSullivan94 :) |
|
I'm on vacation the rest of the week so further updates will come either from @shinyford or @slightfoot until I return on Monday |
|
Sounds good, have a good one! |
…ations # Conflicts: # packages/clerk_auth/lib/src/clerk_auth/persistor.dart
- Restore hosted clerk_auth version constraint (path: was dev-only) - Use barrel import for get_cache_directory instead of inline conditional - Add IndexedDB error handling in web persistor initialize() - Narrow catch block to http.ClientException in web persistor - Fix stale doc comments (files->bytes, localStorage->IndexedDB) - Rename misleading test to match actual assertions
1799263 to
fd6ead8
Compare
ca67e8b to
19aae58
Compare
|
BTW @Silfalion, |
1d60c62 to
37df739
Compare
|
Before merging we should get @slightfoot to review this PR |
|
@slightfoot @MarkOSullivan94 Any news on this, pretty please? |


Hi there, saw that we were waiting on the web support so thought I'd make a PR for it, hope this is ok. Summary down below.
Fixes: #237, #302
Depends on: #373
Summary
Add web platform support to the Clerk Flutter SDK.
DefaultPersistorinto platform-specific implementations(file system on native,
localStorageon web) using conditional exports. A separatebarrel file (
clerk_auth_persistor_web.dart) provides the web persistor to web-onlyconsumers, since
package:webcan't be exported from the main library.DefaultCachingPersistorinto IO (file-based) and web(IndexedDB) implementations with ETag support on both platforms.
dart:iousage withuniversal_ioacross widgets forcross-platform compatibility.
dart:iowithuniversal_ioin API, telemetry, and logging internals.Remove unused
is_webutility files.