feat: add Lynx web platform support - #22
Open
Huxpro wants to merge 4 commits into
Open
Conversation
Add multi-environment build config (web + lynx) to rspeedy so the playground and template can produce browser-compatible bundles alongside native ones. Web bundles output to dist/web/ and are served by a new sparkling-web-shell package that renders them via <lynx-view>. - Create packages/sparkling-web-shell with @lynx-js/web-core 0.19.8 and @lynx-js/web-elements 0.11.3 - Add environments config to playground lynx.config.ts with separate distPath for web output - Filter web/ dir from native asset copies - Add build:web and dev:web scripts to playground - Update template app.config.ts with matching environments config
…olink) Add web platform support to sparkling-app-cli: - New `run:web` command: autolink → build web → start web shell in browser - `--platform` flag on `build` and `dev` commands (web/native/all) - Web-aware `autolink`: generates `.sparkling/web-autolink.ts` with `import 'pkg/web'` for modules declaring web support - `copy-assets` excludes `web/` subdirectory from native copies - `doctor --platform web` checks for @lynx-js/web-core and web shell - Updated types: `web` in PlatformConfig, MethodModuleConfig, AppConfig.paths
…entations Add a web dispatch layer to sparkling-method so pipe calls route to browser-native handlers when running in a web environment. Each method package now exports a ./web subpath that registers handlers at import time. - sparkling-method: web-registry.ts (registerWebMethod, isWebEnvironment), WebMethodHandler type, web intercept in LynxPipe.call() before NativeModules check - sparkling-navigation/web: router.open (History API + CustomEvent), router.close - sparkling-storage/web: getItem/setItem/removeItem via localStorage with namespacing - sparkling-media/web: chooseMedia (file input), downloadFile (fetch+blob), uploadFile/uploadImage (FormData), saveDataURL (unsupported stub)
…b option - Add web-registry to sparkling-method for dispatching pipe calls to browser-based handlers when NativeModules is unavailable - Update sparkling-web-shell with onNativeModulesCall bridge and spkPipe Worker stub for web-core RPC - Fix navigation web handler scheme parsing - Add CLI run:web command and --platform web flag to dev/build/autolink - Add web platform docs (guide, method implementations, limitations) - Add "Enable web platform?" prompt to create-sparkling-app - Add web sidebar entries to website rspress config - Rebuild playground native bundles
leeekyrie
marked this pull request as ready for review
April 28, 2026 15:24
Huxpro
referenced
this pull request
in Huxpro/sparkling
Jul 12, 2026
Companion to the web platform port: the /web method handlers added by upstream PR #22 shipped with no unit tests, which drops the sparkling-navigation/storage/media coverage gates below threshold once those files are collected. Add node jest tests that mock the browser globals (window.history, localStorage, file input, fetch/FormData) and exercise every handler branch, restoring the packages above their coverage thresholds. Kept separate so it can stack onto the web-support PR.
Huxpro
pushed a commit
to Huxpro/sparkling
that referenced
this pull request
Jul 12, 2026
…d globalProps Web-support improvements split out for a stacked PR onto the web platform work (tiktok#22). The previous shell destroyed and re-created a single <lynx-view> on every navigation, which cannot represent Sparkling's native container stack (no state preservation on back, no lifecycle, no globalProps). Now: - router.open STACKS a new <lynx-view> (own Worker heap); the previous view stays alive hidden underneath — router.close / browser back pops it and reveals the previous view with state intact - each view is injected with globalProps (containerID + queryItems parsed from its scheme) mirroring the native SDK's GlobalPropsUtils — required by anything that reads lynx.__globalProps on web, incl. sparkling-history - viewAppeared/viewDisappeared GlobalEvents are sent on stack transitions, mirroring the native ViewEventUtils contract - browser history entries carry the scheme stack in state; popstate reconciles the view stack (back pops live views, forward re-creates fresh heaps, reload rebuilds — matching native process-restore behavior) - sparkling-navigation web handlers slim down to validated event dispatch (sparkling:navigate / sparkling:close); the shell owns stack + history bookkeeping like the native SDK owns the activity stack, and the open handler now honors the replace option (previously ignored) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ARyWgB3243gQx1exWK61Qb
Merged
5 tasks
Huxpro
pushed a commit
to Huxpro/sparkling
that referenced
this pull request
Jul 12, 2026
Port the Web method layer from tiktok#22 so Sparkling methods can run in a browser (e.g. Lynx-on-web via @lynx-js/web-core), not just native. - sparkling-method: a `web-registry` (`registerWebMethod` / `getWebMethodHandler` / `isWebEnvironment`), a `WebMethodHandler` type, a `./web-registry` export, and a `LynxPipe.call` web-handler dispatch (a no-op on native, where the registry is empty). - sparkling-navigation / sparkling-storage / sparkling-media: `/web` handlers (router.open/close, storage get/set/remove, media choose/upload/download) behind a `./web` package export. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Si6NyRMutX8GJ5MuQ3BnfU
5 tasks
Huxpro
pushed a commit
to Huxpro/sparkling
that referenced
this pull request
Jul 12, 2026
…d globalProps Web-support improvements split out for a stacked PR onto the web platform work (tiktok#22). The previous shell destroyed and re-created a single <lynx-view> on every navigation, which cannot represent Sparkling's native container stack (no state preservation on back, no lifecycle, no globalProps). Now: - router.open STACKS a new <lynx-view> (own Worker heap); the previous view stays alive hidden underneath — router.close / browser back pops it and reveals the previous view with state intact - each view is injected with globalProps (containerID + queryItems parsed from its scheme) mirroring the native SDK's GlobalPropsUtils — required by anything that reads lynx.__globalProps on web, incl. sparkling-history - viewAppeared/viewDisappeared GlobalEvents are sent on stack transitions, mirroring the native ViewEventUtils contract - browser history entries carry the scheme stack in state; popstate reconciles the view stack (back pops live views, forward re-creates fresh heaps, reload rebuilds — matching native process-restore behavior) - sparkling-navigation web handlers slim down to validated event dispatch (sparkling:navigate / sparkling:close); the shell owns stack + history bookkeeping like the native SDK owns the activity stack, and the open handler now honors the replace option (previously ignored) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ARyWgB3243gQx1exWK61Qb
Huxpro
pushed a commit
to Huxpro/sparkling
that referenced
this pull request
Jul 26, 2026
…queryItems
On native containers, scheme query params reach the opened page via
lynx.__globalProps.queryItems, and each container gets a containerID.
The web router.open handler dropped everything except the page name, so
pages like the nav-chain playground demo always saw depth=1.
- router.open (web): carry all non-reserved scheme params in the browser URL
- web shell: build globalProps { queryItems, containerID, containerInitTime,
platform } per lynx-view, mirroring the native contract
Standalone web-support bugfix; can be extracted as a stacked PR onto the
web platform PR (tiktok#22).
Huxpro
pushed a commit
to Huxpro/sparkling
that referenced
this pull request
Jul 26, 2026
Native router.open already supports options.replace (swap current page instead of pushing). The web handler always did history.pushState, so router.replace()/redirect()-style cross-page navigation left the previous page on the stack (and could loop). Use history.replaceState when options.replace (or a top-level replace flag) is set. Standalone web-support bugfix; stacked-PR candidate onto tiktok#22.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
web+lynxenvironments) so Sparkling apps can produce browser-compatible bundles alongside native onessparkling-web-shellpackage — minimal rsbuild web host that renders Lynx bundles via<lynx-view>custom element with@lynx-js/web-coreand@lynx-js/web-elementssparkling-method/web-registry) that dispatches pipe calls to browser-based handlers whenNativeModulesis unavailable<input type="file">, fetch + blob download)run:webcommand,--platform webflag fordev/build/autolinkcreate-sparkling-appTest plan
cd packages/playground && pnpm build— verifydist/has*.lynx.bundleanddist/web/has web bundlespnpm dev:web— verify playground renders athttp://localhost:4200/?page=second,?page=card-view,?page=media-testquery paramsandroid/.../assets,ios/LynxResources) contain noweb/subdirectorysparkling-app-cli run:webfrom playground to test CLI path