Skip to content

feat: add Kotlin/JS browser target (SDK + sample app)#86

Merged
akshay2211 merged 2 commits into
mainfrom
feature/js-browser-target
Jun 27, 2026
Merged

feat: add Kotlin/JS browser target (SDK + sample app)#86
akshay2211 merged 2 commits into
mainfrom
feature/js-browser-target

Conversation

@akshay2211

@akshay2211 akshay2211 commented Jun 27, 2026

Copy link
Copy Markdown
Owner

Summary

Two commits enable Kotlin/JS browser targeting end-to-end:

  1. SDK (DrawBox) — adds js { browser() }, moves ImageDecoder.wasmJs.ktwebMain/ImageDecoder.web.kt so JS and WasmJS share the Skiko-based decode actual. One implementation, zero drift.
  2. Sample app (shared + webApp) — adds the matching JS targets, ships a legacy-JS ImageSaver actual, and gives the sample a main() + index.html so ./gradlew :webApp:jsBrowserDevelopmentRun actually renders DrawBox in a browser.

Both js and wasmJs run on top of Skiko for the canvas, so the implementation cost was small and the maintenance footprint shrinks for the SDK (one decoder, not two).

Closes #85.

Test plan

  • ./gradlew :DrawBox:compileKotlinJs :DrawBox:compileKotlinWasmJs :DrawBox:compileKotlinJvm :DrawBox:compileAndroidMain :DrawBox:compileKotlinIosArm64 :DrawBox:compileKotlinIosSimulatorArm64 — all SDK targets build.
  • ./gradlew :DrawBox:jvmTest --rerun-tasks — domain tests pass.
  • ./gradlew :shared:compileKotlinJs :webApp:compileKotlinJs — sample app compiles for the new target.
  • ./gradlew :webApp:jsBrowserDevelopmentRun — dev server serves `index.html` + `webApp.js` (52 MB dev bundle) at http://localhost:8080.
  • Manual: open http://localhost:8080 in a browser, confirm canvas renders + drawing modes work.
  • Production bundle: :webApp:jsBrowserProductionRun (untested in this PR).

Unlocks the SDK for legacy Kotlin/JS embedders. Both `js` and `wasmJs`
run on top of Skiko for the canvas backend, so the encoded-bytes →
ImageBitmap decode path is identical — kept in a single `webMain`
source set so the two targets share one actual and can't drift.

- DrawBox/build.gradle.kts: add `js { browser(); binaries.executable() }`.
- Move `wasmJsMain/io/ak1/drawbox/ImageDecoder.wasmJs.kt` →
  `webMain/io/ak1/drawbox/ImageDecoder.web.kt`. Same implementation
  (`org.jetbrains.skia.Image.makeFromEncoded(...).toComposeImageBitmap()`),
  now shared.

Sample apps are unchanged — this is SDK-only. Embedders publishing
their own JS sample now have an `io.ak1:drawbox-js` artifact to depend
on after the next release.

Closes #85
Extends PR #85 / #86's SDK-only JS target to the sample app so
`./gradlew :webApp:jsBrowserDevelopmentRun` renders DrawBox in a
legacy Kotlin/JS browser, on top of the same Skiko backend the
wasmJs sample already uses.

- shared/build.gradle.kts: add js { browser(); binaries.executable() }.
- shared/src/jsMain/.../ImageSaver.js.kt: legacy-JS actual for
  rememberImageSaver. Mirrors the WasmJS body but uses regular
  Array parts instead of JsArray<JsAny?> — the JS Blob ctor takes a
  dynamic-typed array directly, so WasmJS interop wrappers
  (`toJsString`, JsArray) aren't required here.
- webApp/build.gradle.kts: add js { browser(); binaries.executable() }
  alongside the existing wasmJs.
- webApp/src/jsMain/.../main.kt: ComposeViewport { App() } entry,
  mirroring the wasmJs main.
- webApp/src/jsMain/resources/index.html: minimal page that loads
  webApp.js.

Verified: webApp.js dev bundle serves at http://localhost:8080 (52 MB
in dev mode, eval-source-map), Compose Multiplatform UI mounts via
Skiko on legacy JS. Production bundle untested.

Closes #85
@akshay2211 akshay2211 changed the title feat: add Kotlin/JS browser target (closes #85) feat: add Kotlin/JS browser target (SDK + sample app) Jun 27, 2026
@akshay2211
akshay2211 merged commit 19984d7 into main Jun 27, 2026
3 checks passed
@akshay2211
akshay2211 deleted the feature/js-browser-target branch June 27, 2026 17:17
@akshay2211 akshay2211 mentioned this pull request Jun 28, 2026
10 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add Kotlin/JS browser target for legacy JS embedders

1 participant