diff --git a/docs/website/content/blog/java-to-a-native-linux-app.md b/docs/website/content/blog/java-to-a-native-linux-app.md
new file mode 100644
index 0000000000..e324f24cd0
--- /dev/null
+++ b/docs/website/content/blog/java-to-a-native-linux-app.md
@@ -0,0 +1,99 @@
+---
+title: "Java To Native Linux App: One 5MB Binary, x64 And Arm"
+slug: java-to-a-native-linux-app
+url: /blog/java-to-a-native-linux-app/
+date: '2026-06-20'
+author: Shai Almog
+description: The new native Linux port compiles your Java to a single self-contained ELF through ParparVM and GTK3, with no JVM on the target machine. It runs on an ancient universal glibc, supports musl for Alpine, and ships for both x64 and arm64.
+feed_html: '
The new native Linux port compiles your Java to a single self-contained ELF through ParparVM and GTK3, with no JVM on the target machine. It runs on an ancient universal glibc, supports musl for Alpine, and ships for both x64 and arm64.'
+---
+
+
+
+[Yesterday's release post](/blog/native-linux-apple-watch-game-builder-crash-protection/) introduced the new native Linux desktop port. This post is the detailed version: what it is, why the hard parts were hard, and how to build one.
+
+The Linux port is the structural twin of the native Windows port from last week. It is the same idea the iOS port has used for years: ParparVM translates your Java and Kotlin bytecode to C, and the C is compiled and linked into a native binary. On Linux that binary is a single self-contained ELF. There is no JVM on the user's machine, none bundled, none downloaded, and none required.
+
+## What renders it
+
+Where the Windows port uses Direct2D and DirectWrite, the Linux port uses the GTK stack that every Linux desktop already has:
+
+- **GTK3, Cairo, Pango and GdkPixbuf** for windowing, 2D drawing, text and images.
+- **OpenGL ES (EGL)** for the 3D graphics API.
+- **GStreamer** for media playback, audio recording and the camera.
+- **WebKitGTK** for the `BrowserComponent`.
+- **libsecret, libnotify and GeoClue** for secure storage, notifications and location, with **libcurl** for networking.
+
+The native layer is real, not a set of stubs: 173 native methods across window, graphics, text, image, networking, sockets, services, text editing, browser, media, peers, GL, and printing. A real Codename One `Form` app translates to roughly 810 C files and renders 2D, 3D and the bundled material icon font correctly. The optimized build dead-strips code the app never reaches, so a non-trivial app fits in around 5MB, and it starts faster than most of the GNOME native apps already on the desktop. Because the default theme is material design, a plain Codename One app tends to look better than those apps too:
+
+
+
+The 3D layer is the same `com.codename1.gpu` API that renders through Metal on iOS and Direct3D on Windows; on Linux it goes through OpenGL ES. A glTF model loads and renders with its own materials:
+
+
+
+CSS gradients, transforms and the rest of the 2D feature set render through Cairo exactly as they do elsewhere:
+
+
+
+## The hard part is not rendering
+
+Rendering was the easy part. The two genuinely hard parts of shipping a Linux desktop binary are packaging and dependencies, and they are worth explaining because they shaped the whole design.
+
+**Packaging.** Linux has many package managers, and supporting all of them well is a project in itself. We did not want to get into that, so the Linux port produces one native binary that the user launches directly, the same model as the Windows port. No bundle directory, no installer required. The app's resources (the theme `.res`, images, localization, the icon font) are embedded straight into the ELF and read back at startup.
+
+**glibc.** This is the single worst thing about shipping a Linux binary, and the only thing worse is the alternative. A binary linked against a new glibc refuses to start on a machine with an older one, and "older" can mean a distribution from last year. The fix is to build against an old glibc, so the resulting binary needs only an ancient, universally present version. We compile against roughly `GLIBC_2.17`, which dates to 2013, so the ELF starts on essentially any mainstream desktop. GTK3 is linked dynamically and resolved from the system at startup; it has shipped on every Linux desktop since 2011.
+
+{{< mermaid >}}
+flowchart LR
+ A["Your Java / Kotlin"] --> B["ParparVM: bytecode to C"]
+ B --> C["zig cc against an old glibc"]
+ C --> D["Single self-contained ELF
resources embedded"]
+ D --> E["x64 or arm64"]
+ F["System libraries:
GTK3, Cairo, WebKitGTK, GStreamer"] -. resolved at startup .-> D
+{{< /mermaid >}}
+
+For distributions that use **musl instead of glibc**, Alpine being the obvious one, musl is an opt-in target where the GTK stack is itself musl-built. A musl binary does not run on glibc distributions and vice versa, so you pick the libc that matches where the app will run.
+
+## Building one
+
+Most projects build Linux the way they build every other port: on the build cloud, with nothing to install locally. New projects from the Initializr already carry the Linux build configuration, so the target is there from the first build. If you would rather build on your own machine, the native compile needs the GTK development stack on the build host (the machine that runs the binary only needs the ordinary runtime libraries, which any desktop already has), and you use the `local-linux-device` target:
+
+```bash
+mvn -pl common package -Dcodename1.platform=linux \
+ -Dcodename1.buildTarget=local-linux-device cn1:build
+```
+
+Both architectures come from build hints. zig is a self-contained cross-compiler, so a single host can build either one:
+
+```properties
+linux.arch=arm64
+```
+
+`linux.arch` accepts `x64` (default) or `arm64`, with `x86_64`, `amd64` and `aarch64` accepted as synonyms. To target Alpine, switch the C library:
+
+```properties
+linux.libc=musl
+```
+
+By default the build is optimized and strips symbols so the binary stays as small as the translated code allows. During development you can keep the symbols so a faulting address can be symbolized:
+
+```properties
+linux.debug=true
+```
+
+## Native Linux versus the executable jar
+
+Before this port, the way to run a Codename One app on Linux was to package it as an executable jar that runs on a JVM. That path still exists and still works. The difference is what ships and what the target needs: the executable jar carries Java bytecode and runs on a JVM that must be present, while the native port ships a single ELF that needs no JVM at all. Pick the jar when a JVM is already guaranteed on the target and you want one artifact across desktops; pick the native port when you want a self-contained binary that launches like any other Linux program.
+
+## Wrapping up
+
+The native Linux port completes the desktop story the Mac and Windows ports started: the same code base, compiled to a native binary, on all three desktops. It is new, so if you hit a distribution quirk or a dependency that does not resolve, please file it on the [issue tracker](https://github.com/codenameone/CodenameOne/issues) with the distribution and architecture you saw it on.
+
+---
+
+## Discussion
+
+_Join the conversation via GitHub Discussions._
+
+{{< giscus >}}
diff --git a/docs/website/content/blog/native-apple-watch-and-wear.md b/docs/website/content/blog/native-apple-watch-and-wear.md
new file mode 100644
index 0000000000..322163bc9f
--- /dev/null
+++ b/docs/website/content/blog/native-apple-watch-and-wear.md
@@ -0,0 +1,121 @@
+---
+title: "Just Watch"
+slug: native-apple-watch-and-wear
+url: /blog/native-apple-watch-and-wear/
+date: '2026-06-21'
+author: Shai Almog
+description: The new native Apple Watch port runs real Codename One UI on watchOS through a dedicated Core Graphics backend inside a SwiftUI shell, while Wear OS rides the existing Android pipeline. The same code base, branched with CN.isWatch(), reaches both platforms, seamlessly!
+feed_html: '
The new native Apple Watch port runs real Codename One UI on watchOS through a dedicated Core Graphics backend inside a SwiftUI shell, while Wear OS rides the existing Android pipeline. The same code base, branched with CN.isWatch(), reaches both platforms, seamlessly!'
+---
+
+
+
+[Friday's release post](/blog/native-linux-apple-watch-game-builder-crash-protection/) announced wearable support. This post covers both wearables in detail: how watchOS works, how Wear OS differs, and the small amount of code you write to reach either one.
+
+## Why a watch API at all
+
+Apple sees watch programming as a completely separate discipline from phone or desktop programming. It is a different API with a different logic, and that makes some sense given the device. The consequence is that several UI metaphors we take for granted are impractical or absent: there is no text field in the form you expect, and no browser. So it is fair to ask what the point of a watch API even is.
+
+The point is that reuse still happens. Many well known apps simply do not bother with a watch UI because it is such a chore, and yet the amount of work a watch screen actually needs is quite small. It is smaller still with Codename One, because the same Java or Kotlin code base that drives your phone app drives the watch app, and you decide per screen how much of it to show.
+
+## watchOS is not iOS
+
+The interesting engineering is on the Apple side. watchOS has no UIKit view hierarchy, no OpenGL ES and no Metal. None of the rendering paths the iOS port relies on exist there. So the watchOS port ships a dedicated **Core Graphics rendering backend** and a separate watch application target that hosts the Codename One runtime, the ParparVM-translated app, inside a SwiftUI shell. Every drawing operation, rectangles, lines, polygons, images, gradients, Core Text strings, clipping, transforms and alpha-mask shapes, is rendered through Core Graphics. The result is real Codename One UI on the watch:
+
+
+
+That is a screenshot from our test framework, which was never designed for a watch: it still has a text field. Because that is a Codename One text field it renders correctly and "just works" right up until you try to edit in it, which on a watch would not give the result you want. A UI actually built for the watch would leave the text field out and route input through the watch instead. It is a useful reminder that the same components render here, and that you still design the screen for the watch.
+
+The watch app is rooted in a generated SwiftUI `@main` shell that hosts the Codename One frames and forwards Digital Crown and tap input into the runtime. On device the watch slice compiles for `arm64_32`. In the default companion distribution the watch app is embedded in your iOS app so the pair installs together; a standalone distribution builds a watch-only product instead.
+
+The diagram below is the shape of it. `CN.isWatch()` is true on both wearables, so you adapt the UI for a small screen either way; what differs after that is the platform, not the check.
+
+{{< mermaid >}}
+flowchart TD
+ A["Your Java / Kotlin UI"] --> B["CN.isWatch() is true on both
adapt the UI for a small screen"]
+ B --> C{"Which platform?"}
+ C -->|"watchOS"| D["Watch root + tree-shaking
ParparVM slice (arm64_32)"]
+ D --> E["Core Graphics backend
inside a SwiftUI @main shell"]
+ C -->|"Wear OS"| F["Ordinary Android app
standard Android rendering"]
+{{< /mermaid >}}
+
+## A separate watch root keeps the app small
+
+The watch has a far smaller memory and CPU budget than the phone, so the less code that reaches it, the better. That is what `codename1.watchMain` is for. Instead of reusing your phone's main class, you point the watch build at its own entry class:
+
+```properties
+codename1.watchMain=com.mycompany.myapp.MyWatchMain
+```
+
+That entry class is the **root** the build starts from, and changing the root changes what gets compiled. ParparVM only translates the code that is actually reachable from the root it is handed; everything else is dropped (a tree-shaking, or dead-code-elimination, pass). When the watch has its own root, the reachability graph starts from a small watch UI rather than from your full phone app, so the phone-only screens, libraries, and assets the watch never calls fall away before the watch slice is even built. The binary that lands on the device that can least afford the weight is the leanest one. If you do not declare a `watchMain`, the watch reuses your phone main class and you get the full reachable graph instead.
+
+## Wear OS is just Android
+
+The Android side is much simpler, by design. A Wear OS app is an ordinary Android app that declares the watch hardware feature, so the existing Codename One Android port renders the watch UI through exactly the same pipeline it uses on phones and tablets. Almost everything that works on Android works on the watch with no special backend.
+
+## What you write
+
+Branch your UI at runtime with `CN.isWatch()`. This is the wearable analog of the `isTablet()` and `isDesktop()` checks you already use:
+
+```java
+Form f = new Form(BoxLayout.y());
+if (CN.isWatch()) {
+ // Compact, single column suited to a small screen
+ f.add(new Label("Hi Watch"));
+ f.getToolbar().setVisible(false);
+} else {
+ f.add(new SpanLabel("Welcome to the full size application"));
+}
+f.show();
+```
+
+A few practical guidelines for the watch branch: prefer a single vertical column that scrolls on the Y axis (the Digital Crown and the Wear OS rotary input scroll the focused container), keep interactive targets large and few, and on round screens keep content away from the corners using the form's safe-area insets. A watch device can be round or square, so query the insets rather than assuming a rectangle.
+
+## Enabling each build
+
+Both builds are additive: with the hints off, your phone builds are byte-for-byte unchanged. On Apple, one hint turns on the watch target, and the cloud build produces the watch slice as part of the regular iOS build:
+
+```properties
+watchNative.enabled=true
+```
+
+If you want a distinct watch entry point rather than reusing your phone main class, declare it and the watch slice is produced automatically:
+
+```properties
+codename1.watchMain=com.mycompany.myapp.MyWatchMain
+```
+
+On Android, one hint marks the build as a Wear OS app, which injects the watch hardware feature, declares the app standalone, and raises the minimum SDK to the Wear OS standalone baseline:
+
+```properties
+android.wear=true
+```
+
+A project can target both platforms at once by setting the watch hint and `android.wear=true` together.
+
+## What runs on the watch, and what does not
+
+Because watchOS lacks UIKit views, GPU rendering and several iOS frameworks, the APIs that depend on them are unavailable on the watch slice. They are guarded so the shared sources still link, and they degrade rather than crash.
+
+| Available on watchOS | Unavailable on watchOS |
+| --- | --- |
+| The full UI and layout system | `BrowserComponent` and web views |
+| `Graphics` drawing: gradients, transforms, clipping, Gaussian blur | Camera capture and `MediaPlayer` video |
+| `FontImage` and material icons | Native maps (`MapComponent`) |
+| Images and mutable images | Inline native text editors (text routes through the watch input controller) |
+| Networking, storage, JSON and XML | StoreKit in-app purchase |
+| The property and binding frameworks | |
+
+The watch slice runs the same garbage-collected ParparVM runtime as the iOS app, but the memory and CPU budgets on the watch are far smaller, so keep watch screens light. The generated project is a standard Xcode project, so you can open it and debug or profile the watch target with the native Xcode tools, and cloud builds support the watch target through the same iOS build.
+
+## Wrapping up
+
+A watch UI used to be a separate project. Here it is a branch in code you already wrote. This is a new port, so if a screen renders oddly on a real watch or a guarded API behaves unexpectedly, please file it on the [issue tracker](https://github.com/codenameone/CodenameOne/issues) with the device and watchOS or Wear OS version.
+
+---
+
+## Discussion
+
+_Join the conversation via GitHub Discussions._
+
+{{< giscus >}}
diff --git a/docs/website/content/blog/native-linux-apple-watch-game-builder-crash-protection.md b/docs/website/content/blog/native-linux-apple-watch-game-builder-crash-protection.md
new file mode 100644
index 0000000000..0234712602
--- /dev/null
+++ b/docs/website/content/blog/native-linux-apple-watch-game-builder-crash-protection.md
@@ -0,0 +1,110 @@
+---
+title: "Native Linux, Apple Watch, A Game Builder And Crash Protection"
+slug: native-linux-apple-watch-game-builder-crash-protection
+url: /blog/native-linux-apple-watch-game-builder-crash-protection/
+date: '2026-06-19'
+author: Shai Almog
+description: This week adds a native Linux desktop port, an Apple Watch and Wear OS port, a visual Game Builder with a high-level gaming API, and seamless crash protection that symbolicates native crashes and files them as GitHub issues. We also rebuilt the build cloud from the ground up.
+feed_html: '
This week adds a native Linux desktop port, an Apple Watch and Wear OS port, a visual Game Builder with a high-level gaming API, and seamless crash protection that symbolicates native crashes and files them as GitHub issues.'
+---
+
+
+
+This week brings a native Linux desktop port, an Apple Watch and Wear OS port, a visual Game Builder with a high-level gaming API, and a new crash-protection system, with a tutorial following each one over the coming days. There is also a large piece of work that you mostly should not have noticed: we rebuilt the build cloud, and that rebuild caused a few failed builds along the way. More on that below.
+
+## A native Linux desktop port
+
+[PR #5239](https://github.com/codenameone/CodenameOne/pull/5239) adds a native Linux port, the structural twin of the native Windows port we shipped last week. The same ParparVM pipeline that turns your Java/Kotlin bytecode into C, here targeting Linux through GTK3, Cairo, Pango and GdkPixbuf for rendering, OpenGL ES for 3D, GStreamer for media and camera, and WebKitGTK for the browser component. There is no JVM on the target machine: it is a single self-contained ELF you launch like any other program.
+
+We expected this to be painful, and parts of it were, but Linux turned out to be mostly developer friendly. A non-trivial app fits in 5MB, and on my Linux machine it started faster than most of the GNOME native apps already installed; thanks to the default material design theme it tends to look better too:
+
+
+
+Most things just work, including the camera and 3D. The hard part of Linux is not the rendering, it is packaging and dependencies. We deliberately stayed out of the package-manager rabbit hole and ship one native binary you launch directly, the same model as Windows. The other classic Linux problem is glibc; if that sentence means nothing to you, consider yourself fortunate. We solved it by compiling against a very old glibc (around `GLIBC_2.17`, from 2013) and linking GTK3 dynamically, both of which are present on essentially every desktop. We also support **musl for Alpine**, and both **x64 and arm64**. Like the other ports, this is not a local-only path: the Linux target builds on the build cloud, and new projects from the Initializr come wired for it. The architecture and the build are covered in {{< post-link path="/blog/java-to-a-native-linux-app" text="Saturday's post" >}}.
+
+## Codename One on your wrist: Apple Watch and Wear OS
+
+[PR #5252](https://github.com/codenameone/CodenameOne/pull/5252) adds a proper native Apple Watch (watchOS) port, alongside Wear OS support on the Android side. Apple treats watch programming as a completely separate discipline from phone or desktop programming: a different API, a different lifecycle, and UI metaphors we take for granted that simply do not exist on the watch (no text field as you know it, and no browser). That is a defensible design, and it raises a fair question: what is the point of a watch API at all?
+
+The answer is that reuse still happens. Many well known apps skip the watch entirely because it is such a chore, yet the amount of work a watch UI actually needs is small, and smaller still with Codename One. watchOS has no UIKit views, no OpenGL ES and no Metal, so the port ships a dedicated **Core Graphics rendering backend** and hosts the Codename One runtime inside a SwiftUI shell. The same Java code, branched with `CN.isWatch()`, renders real Codename One UI on the watch:
+
+
+
+That is a screenshot from our test framework, which was never designed for a watch: it still has a text field. Because that is a Codename One text field it renders correctly and "just works" right up until you try to edit in it, which on a watch would not give the result you want; a real watch UI would simply leave it out.
+
+Wear OS is simpler: a Wear OS app is an ordinary Android app, so the existing Android port renders it with the same pipeline it uses on phones. You enable each side with one build hint, and with the hints off your phone build is byte-for-byte unchanged. Both wearables are covered in detail in {{< post-link path="/blog/native-apple-watch-and-wear" text="Sunday's post" >}}.
+
+## A visual Game Builder
+
+[PR #5253](https://github.com/codenameone/CodenameOne/pull/5253) adds a visual game level editor on top of the `com.codename1.gaming` API from last week, plus a high-level data model and a streaming engine for large worlds. Instead of hand-placing every sprite in code, you draw the level, tag objects with the numbers your game needs (`lives`, `value`, `speed`), and the editor saves a small data file the runtime plays. Your code shrinks to the part that is actually yours: the rules.
+
+This is the special case in this week's release. Tuesday's post is a full overview of the editor, the data model, and the streaming engine for large worlds, and then **a three-part tutorial series starts Thursday** rather than a single follow-up. The first tutorial builds a playable 2D platformer, "Duke's Coffee Run", from an empty scene to a running game, including the part most tutorials skip: bringing in real art and slicing an animated sprite sheet for Duke.
+
+
+
+Two more parts follow on the next Thursdays: a blackjack card game, then a first-person 3D dungeon that scales up to large streaming worlds. The full picture of what the builder is and how it fits together is in {{< post-link path="/blog/the-codename-one-game-builder" text="Tuesday's overview" >}}. One important caveat: **the Game Builder and its high-level APIs are beta**. We are actively improving them and we want your feedback on the editor, the API shape, and the asset workflow. Tell us what works and what gets in your way through the [issue tracker](https://github.com/codenameone/CodenameOne/issues).
+
+## Seamless crash protection
+
+[PR #5001](https://github.com/codenameone/CodenameOne/pull/5001) replaces the old email-based crash protection tool with a new on-device client, `com.codename1.crash`, that we think leapfrogs the dedicated tools in this space. As we add more platforms, testing across all of them becomes a bigger challenge; this is the tool for dealing with that, and it is built to be seamless.
+
+It is seamless in three senses. You do not wire up anything complex: the build servers do the heavy lifting. It connects to GitHub issues instead of sending a barrage of emails. And it symbolicates native crashes on every operating system we support, so a faulting address on iOS, Android, Windows or Linux comes back as a readable stack. On the device, reports are written to storage before they are sent and only deleted after the server confirms receipt, so nothing is lost to a flaky connection; a failed send is retried on the next launch and the server deduplicates it.
+
+{{< mermaid >}}
+flowchart LR
+ A["App crashes on device"] --> B["Write report to Storage with eventId"]
+ B --> C["POST to the crash endpoint"]
+ C -->|2xx confirmed| D["Delete the stored report"]
+ C -->|offline or failed| E["Retry on next launch, server dedups by eventId"]
+ F["Release build on the cloud"] --> G["Upload mapping.txt / dSYM symbols"]
+ C --> H["Server symbolicates the native stack"]
+ G --> H
+ H --> I["A GitHub issue, not an email"]
+{{< /mermaid >}}
+
+Personal data is scrubbed on the device before anything leaves it: emails are partially redacted and long digit runs are collapsed, with rules you can override. It is opt-in and off by default; turning it on is two lines, and the full walkthrough is in {{< post-link path="/blog/seamless-crash-protection" text="Monday's post" >}}.
+
+```java
+CrashProtection.install();
+CrashProtection.setEnabled(true);
+```
+
+## Behind the scenes: a rebuilt build cloud
+
+Codename One was founded in 2012, back when Docker was a brand-new alpha product that few people had heard of, and a lot of the infrastructure underneath the build cloud dates back to that era. This week we did a major rebuild and re-architecture of it. The transition caused a few failed builds, and if one of yours was among them, we are sorry for the disruption.
+
+The end result is completely new infrastructure that is far easier to update going forward, with better isolation and security. We are nearly finished with the Mac side (that work continues over this weekend), and every other platform is done except for UWP and the Windows desktop builds. If a build behaves differently from how it did before, please tell us right away, ideally through the chat on our website, so we can act quickly.
+
+## Initializr now runs on the JavaScript port
+
+We quietly switched the [Codename One Initializr](https://start.codenameone.com) over to the new JavaScript port, and we hope you did not notice the difference. That is the goal: the JavaScript port should feel like every other port.
+
+It is also one of the hardest ports we have ever worked on. Every percentage point of compatibility and every bit of performance is a genuine fight. The work is ongoing, and the aim is to get the JavaScript port aligned with the rest and launch it in the near future.
+
+## From the community
+
+Francesco Galgani published another thoughtful piece, [Java was supposed to free us from the operating system; today Codename One is getting there](https://www.informatica-libera.net/content/java-was-supposed-to-free-us-from-the-operating-system-today-codename-one-is-getting-there). It is worth your time, and we are grateful for the writing and the perspective.
+
+A note on cadence: community activity is slowing down as everyone heads into the summer holidays, and we are not sure how quickly progress will continue through these months. We are still very much here, and we are looking for feedback on all of the above, so this is a good time to send it.
+
+## Upcoming attractions
+
+The tutorials follow this post; each link below goes live on its day:
+
+- **Saturday.** {{< post-link path="/blog/java-to-a-native-linux-app" text="The native Linux desktop port" >}}. PR [#5239](https://github.com/codenameone/CodenameOne/pull/5239).
+- **Sunday.** {{< post-link path="/blog/native-apple-watch-and-wear" text="The Apple Watch and Wear OS ports" >}}. PR [#5252](https://github.com/codenameone/CodenameOne/pull/5252).
+- **Monday.** {{< post-link path="/blog/seamless-crash-protection" text="Seamless crash protection" >}}. PR [#5001](https://github.com/codenameone/CodenameOne/pull/5001).
+- **Tuesday.** {{< post-link path="/blog/the-codename-one-game-builder" text="The Game Builder overview" >}}. PR [#5253](https://github.com/codenameone/CodenameOne/pull/5253).
+- **Thursday.** {{< post-link path="/blog/game-builder-2d-platformer" text="Game Builder tutorial 1, a 2D platformer" >}}. The first of three parts. PR [#5253](https://github.com/codenameone/CodenameOne/pull/5253).
+
+## Wrapping up
+
+The issue tracker is [here](https://github.com/codenameone/CodenameOne/issues) and it is the best place to reach us right now. The discussion forum is [here](https://www.codenameone.com/discussion-forum.html), and the Build Cloud console is at [`/console/`](https://cloud.codenameone.com/console/index.html). The [Playground](/playground/), [Initializr](/initializr/), and [Skin Designer](/skindesigner/) are where they have always been.
+
+---
+
+## Discussion
+
+_Join the conversation via GitHub Discussions._
+
+{{< giscus >}}
diff --git a/docs/website/content/blog/seamless-crash-protection.md b/docs/website/content/blog/seamless-crash-protection.md
new file mode 100644
index 0000000000..394792c4cb
--- /dev/null
+++ b/docs/website/content/blog/seamless-crash-protection.md
@@ -0,0 +1,114 @@
+---
+title: "Seamless Crash Protection That Symbolicates Native Crashes"
+slug: seamless-crash-protection
+url: /blog/seamless-crash-protection/
+date: '2026-06-22'
+author: Shai Almog
+description: The new com.codename1.crash client captures crashes on device, scrubs personal data before anything is sent, retries reliably through a storage-first queue, and lets the build cloud symbolicate native crashes and file them as GitHub issues instead of emails.
+feed_html: '
The new com.codename1.crash client captures crashes on device, scrubs personal data before anything is sent, retries reliably through a storage-first queue, and lets the build cloud symbolicate native crashes and file them as GitHub issues instead of emails.'
+---
+
+
+
+[Friday's release post](/blog/native-linux-apple-watch-game-builder-crash-protection/) introduced the new crash-protection system. This post is the detailed version: why it exists, what it does on the device, and how to turn it on.
+
+The motivation is portability. Every port we add widens the set of platforms an app can break on, and testing across all of them by hand does not scale. The old crash-protection tool emailed you a stack trace; that worked, but it did not symbolicate native crashes, and a busy app could bury you in mail. The new `com.codename1.crash` package replaces it with something seamless, and the seam it removes is the work you used to do yourself.
+
+Put plainly: once a product ships on several platforms and starts to grow, this is the only practical way to support it in production. Keeping up with crashes from devices you do not own, on operating systems you cannot all reproduce locally, is not realistic without something like it. That is the gap this fills.
+
+## Seamless in three ways
+
+**You wire up almost nothing.** The build servers do the heavy lifting, including the part that used to be impossible from the client: turning a native crash address into a readable stack.
+
+**It files GitHub issues, not emails.** Crashes land where you already track work, deduplicated, instead of arriving as a stream of messages.
+
+**It symbolicates native crashes on every platform we support.** Native faults on iOS, macOS, Windows (Win32) and Linux come back as symbolicated stacks, and obfuscated Android exceptions are deobfuscated back to your original class and method names. The cloud build keeps the symbols and applies them server-side, so every platform we ship is covered.
+
+## Storage-first delivery on the device
+
+The client is built so that a crash is not lost to a bad network. Every report is written to `Storage` with a fresh `eventId` before the upload is attempted, and the stored copy is deleted only after the server confirms receipt with a 2xx. If the device is offline or the upload fails, the report stays in storage and is drained on the next launch; the server deduplicates by the same `eventId`, so a retry never produces a duplicate.
+
+{{< mermaid >}}
+sequenceDiagram
+ participant App
+ participant Storage
+ participant Cloud
+ participant GitHub
+ App->>Storage: write report + eventId (before send)
+ App->>Cloud: POST report
+ alt confirmed (2xx)
+ Cloud-->>App: ok
+ App->>Storage: delete report
+ else offline or failed
+ Note over App,Storage: report kept, retried next launch
+ end
+ Note over Cloud: apply mapping.txt / dSYM symbols
+ Cloud->>GitHub: open or update an issue (dedup by eventId)
+{{< /mermaid >}}
+
+Symbolication is the half that needs the cloud. After a successful release build, the executor ships the build's symbol artifacts, `mapping.txt` for Android or the dSYM for iOS, to the server, which keeps them and applies them when a matching crash arrives. On iOS the existing signal handlers already convert native signals into JVM exceptions that flow through the same error handler, so a native crash and a Java exception travel the same path.
+
+## A real native crash, made readable
+
+Here is what that produces. The issue below was auto-filed for a native crash on iOS: a `NativeCrash`, a `Signal 11 (SIGSEGV)`, the sort of failure that is normally an opaque hex address with nothing to act on. Because the build's symbols were applied server-side, the issue carries a full symbolicated stack, and you can read straight down it, from the native-interface call that triggered the fault, through the Codename One event dispatch, back to the app code. The header captures what you need to triage without asking the user anything: package, app version, platform and OS version, first and last seen, occurrence count, and a fingerprint that ties recurrences of the same crash together.
+
+
+
+A crash that originates in a native interface is about the hardest case there is, and it still comes back legible. That holds across the ports: native faults on iOS, macOS, Windows and Linux are symbolicated, and obfuscated Android exceptions are deobfuscated to their original names.
+
+## Where the issues land: GitHub repo mappings
+
+Crashes are filed as issues on a GitHub repository you choose, and that repository does not have to be the one where your code lives. In the cloud console you map each app package to a destination repo; when a crash arrives for that package, the matching mapping decides which repository receives the auto-filed issue. The crash is filed straight on GitHub as an issue, and Codename One does not store the crash itself.
+
+
+
+You can connect more than one GitHub organization or account, so crashes can land in a repo on a different org from the one that holds your source. That separation is useful in practice: a private triage repo, a shared support repo, or a per-app repo, each decoupled from where the code actually lives.
+
+## Personal data is scrubbed before anything leaves the device
+
+Reports are scrubbed on the device, before the upload, by a `PiiScrubber`. The defaults are conservative: email addresses are partially redacted, keeping the first few characters of the local part and the full domain (so `joe***@example.com`), and runs of six or more consecutive digits are collapsed to `[num]`. URLs are left intact because they are usually needed to understand the crash.
+
+You can extend the scrubber for your own data. Subclass `PiiScrubber`, override `scrubMessage` and `scrubFrame` on top of the defaults, and register it:
+
+```java
+public class MyScrubber extends PiiScrubber {
+ @Override
+ public String scrubMessage(String message) {
+ // run the default email/digit rules first, then your own
+ String s = super.scrubMessage(message);
+ return s.replaceAll("ACCT-\\d+", "[acct]");
+ }
+}
+
+// during startup, before install()
+CrashProtection.setScrubber(new MyScrubber());
+```
+
+## Turning it on
+
+Crash protection is opt-in and off by default, and the choice is yours to make: it is persisted in `Preferences`. Install the handler during startup and enable uploads:
+
+```java
+CrashProtection.install();
+CrashProtection.setEnabled(true);
+```
+
+`install()` registers the crash handler and, on the next launch, drains any reports that were stored but not yet uploaded. In the simulator uploads are skipped, so you can call both methods unconditionally without sending test crashes to the cloud. `setEnabled(false)` stops uploads later without uninstalling.
+
+A few details worth knowing. The endpoint is fixed to the Codename One cloud, so there is nothing to configure there. On Android the new handler runs alongside the legacy `Log.bindCrashProtection` path, guarded so a bug in one cannot suppress the other, which means you can adopt the new system without losing the old behavior while you migrate.
+
+## A note on credentials
+
+Because reports can carry message text, treat the scrubber as part of your security surface. Never put an API key, token or password into a log message or an exception message in the first place: keep credentials out of the binary, fetch them from your own backend, and store them with `SecureStorage`. The default scrubber redacts common personal data, but it cannot know that a particular string is a secret, so the safe rule is that secrets never reach a log line.
+
+## Wrapping up
+
+With more platforms comes a wider testing surface, and this is the tool for dealing with it without adding work to your day: capture on device, scrub locally, deliver reliably, symbolicate in the cloud, and track in GitHub. Turn it on, and if anything about the flow surprises you, tell us on the [issue tracker](https://github.com/codenameone/CodenameOne/issues).
+
+---
+
+## Discussion
+
+_Join the conversation via GitHub Discussions._
+
+{{< giscus >}}
diff --git a/docs/website/content/blog/the-codename-one-game-builder.md b/docs/website/content/blog/the-codename-one-game-builder.md
new file mode 100644
index 0000000000..aacd8c83dd
--- /dev/null
+++ b/docs/website/content/blog/the-codename-one-game-builder.md
@@ -0,0 +1,99 @@
+---
+title: "The Codename One Game Builder: Draw The Level, Code The Rules"
+slug: the-codename-one-game-builder
+url: /blog/the-codename-one-game-builder/
+date: '2026-06-23'
+author: Shai Almog
+description: A visual level editor for the Codename One gaming API that saves a plain-data .game file the runtime plays, across 2D, isometric board, and 3D modes, plus a streaming engine for large open worlds. The orientation before the three hands-on tutorials.
+feed_html: '
A visual level editor for the Codename One gaming API that saves a plain-data .game file the runtime plays, across 2D, isometric board, and 3D modes, plus a streaming engine for large open worlds.'
+---
+
+
+
+[Friday's release post](/blog/native-linux-apple-watch-game-builder-crash-protection/) introduced the Game Builder and promised a tutorial series. This post is the orientation that sits in front of those tutorials: what the Game Builder is, how its pieces fit together, and why it exists. The hands-on builds start Thursday.
+
+Last week we shipped the `com.codename1.gaming` API: a game loop, sprites, scenes, pollable input, a low-latency sound pool, and Box2D physics, all running unchanged on every platform including iOS. That gave you the runtime. The missing half was authoring. Building a level purely in Java means dozens of `new Sprite(...)`, `setX`, and `setY` calls you cannot see until you run them and must recompile to tweak. The Game Builder ([PR #5253](https://github.com/codenameone/CodenameOne/pull/5253)) replaces that with a visual editor and a plain-data level file.
+
+## Draw the level, code only the rules
+
+The core idea is that a level is data, not code. You draw it in the editor, tag each object with the numbers your game needs (`lives`, `value`, `speed`), and the editor saves a small `.game` file. The runtime loads that file and realizes it into a scene of sprites. What is left for you to write is the part that is actually yours: the rules.
+
+
+
+The editor is itself a Codename One app (Java 17) with three panels that matter: the **Hierarchy** of layers and objects, the **Asset Library** of art you stamp down, and the **Inspector** for the selected object's transform and behavior values. Two Maven goals drive it:
+
+```bash
+mvn cn1:create-game-scene -DclassName=com.example.mygame.MyScene
+mvn cn1:gamebuilder
+```
+
+`create-game-scene` writes an empty `.game` level and a companion Java class into your project; `cn1:gamebuilder` opens the editor on it. Both goals are gated to Java 17.
+
+## One editor, three kinds of game
+
+The same editor and the same `.game` format author three modes, and the runtime realizes each one without your code changing shape:
+
+- **2D**, for side-scrollers and top-down games. A tile grid, layers for draw order, and sprites.
+- **Board**, an isometric projection for card and tabletop games, where pieces are data-driven elements on a board.
+- **3D**, for first-person and overhead 3D, with terrain you sculpt and a per-game-type preview (open, flight, race, or dungeon) complete with a radar.
+
+The three tutorials each build one of these, so the range is easiest to see as three finished games:
+
+
+
+
+
+The 3D editor sculpts terrain directly: height, holes, walls, pluggable surface materials, and smooth interpolated slopes, all previewed in the form factor of the game you are making.
+
+
+
+## From `.game` file to running game
+
+The data model lives in `com.codename1.gaming.level`: `GameLevel`, `GameElement`, `Layer`, `TileLayer`, `AssetCatalog`, and `IsoProjection`, with JSON load and save across all three modes. Your companion class loads the level and the editor regenerates the wiring for every object you named, so renaming or adding an object in the Inspector just updates your fields. The constructor and the update loop are yours:
+
+```java
+public class MyScene extends GameSceneView {
+ public MyScene(AssetCatalog catalog) {
+ super(loadLevel(), catalog); // realizes the level into a Scene of Sprites
+ setArcadeBehavior(true); // built-in run/jump/gravity/patrol/pickups (2D)
+ }
+
+ private static GameLevel loadLevel() throws java.io.IOException {
+ return GameLevel.load(Display.getInstance()
+ .getResourceAsStream(MyScene.class, "/MyScene.game"));
+ }
+
+ @Override
+ protected void onUpdate(double deltaSeconds) {
+ // your rules go here
+ }
+}
+```
+
+`GameSceneView` is a `GameView`, which is a regular Codename One `Component`, so you drop it into a `Form` and call `start()` to begin the loop. Because you edit `onUpdate` and not the generated block, re-running `cn1:gamebuilder` to tweak the level keeps your logic intact.
+
+## Large worlds that stream
+
+Some games outgrow a single hand-drawn level. The Game Builder ships a streaming engine for large and open worlds, and the editor has a **Large World** mode that edits and previews the active region. The pieces are a pluggable `Material` and `MaterialRegistry`; a chunked `StreamingTerrain` with a `ChunkProvider`, LRU paging, and support for negative coordinates; variable-size `TerrainFeature` objects for walls, ramps, and platforms; and loadable `Region` and `RegionProvider` types stitched into a `GameWorld` that streams neighboring regions in seamlessly. A `GameLevel` can persist an optional `GameWorld`, so a streaming world saves and loads like any other level.
+
+## A note on beta
+
+The Game Builder and the high-level gaming APIs are **beta**. They work, the tutorials are real games you can build start to finish, and they run on every platform. What is not yet settled is the shape: the editor's interactions, the API surface, and the asset workflow are all things we expect to refine. That is exactly why we are shipping it now and writing about it: we want your reports. If the editor fights you, an API reads wrong, or an asset will not import the way you expect, file it on the [issue tracker](https://github.com/codenameone/CodenameOne/issues) with the project or asset attached.
+
+## Where to go next
+
+The three tutorials build a real game each, in increasing order of ambition:
+
+- **Thursday.** {{< post-link path="/blog/game-builder-2d-platformer" text="A 2D platformer, Duke's Coffee Run" >}}. It covers the part most tutorials skip: bringing in real art and slicing an animated sprite sheet.
+- **The Thursday after.** {{< post-link path="/blog/game-builder-board-game" text="A blackjack card game, Duke Jack" >}}. Cards become data-driven elements on a felt table.
+- **The Thursday after that.** {{< post-link path="/blog/game-builder-3d-dungeon" text="A first-person 3D dungeon" >}}. Sculpt terrain and scale up to streaming worlds.
+
+Start with Thursday's platformer; it introduces every moving part you will reuse in the other two.
+
+---
+
+## Discussion
+
+_Join the conversation via GitHub Discussions._
+
+{{< giscus >}}
diff --git a/docs/website/static/blog/java-to-a-native-linux-app.jpg b/docs/website/static/blog/java-to-a-native-linux-app.jpg
new file mode 100644
index 0000000000..1051f600dd
Binary files /dev/null and b/docs/website/static/blog/java-to-a-native-linux-app.jpg differ
diff --git a/docs/website/static/blog/java-to-a-native-linux-app/chatview-linux.png b/docs/website/static/blog/java-to-a-native-linux-app/chatview-linux.png
new file mode 100644
index 0000000000..b6abbd510b
Binary files /dev/null and b/docs/website/static/blog/java-to-a-native-linux-app/chatview-linux.png differ
diff --git a/docs/website/static/blog/java-to-a-native-linux-app/css-gradients-linux.png b/docs/website/static/blog/java-to-a-native-linux-app/css-gradients-linux.png
new file mode 100644
index 0000000000..dc26a7aeaf
Binary files /dev/null and b/docs/website/static/blog/java-to-a-native-linux-app/css-gradients-linux.png differ
diff --git a/docs/website/static/blog/java-to-a-native-linux-app/gltf-3d-linux.png b/docs/website/static/blog/java-to-a-native-linux-app/gltf-3d-linux.png
new file mode 100644
index 0000000000..711cdd9f18
Binary files /dev/null and b/docs/website/static/blog/java-to-a-native-linux-app/gltf-3d-linux.png differ
diff --git a/docs/website/static/blog/native-apple-watch-and-wear.jpg b/docs/website/static/blog/native-apple-watch-and-wear.jpg
new file mode 100644
index 0000000000..1a83e0bf55
Binary files /dev/null and b/docs/website/static/blog/native-apple-watch-and-wear.jpg differ
diff --git a/docs/website/static/blog/native-apple-watch-and-wear/watch-bezel.png b/docs/website/static/blog/native-apple-watch-and-wear/watch-bezel.png
new file mode 100644
index 0000000000..2195caca05
Binary files /dev/null and b/docs/website/static/blog/native-apple-watch-and-wear/watch-bezel.png differ
diff --git a/docs/website/static/blog/native-linux-apple-watch-game-builder-crash-protection.jpg b/docs/website/static/blog/native-linux-apple-watch-game-builder-crash-protection.jpg
new file mode 100644
index 0000000000..e7356c7e3c
Binary files /dev/null and b/docs/website/static/blog/native-linux-apple-watch-game-builder-crash-protection.jpg differ
diff --git a/docs/website/static/blog/seamless-crash-protection.jpg b/docs/website/static/blog/seamless-crash-protection.jpg
new file mode 100644
index 0000000000..a87cdf473a
Binary files /dev/null and b/docs/website/static/blog/seamless-crash-protection.jpg differ
diff --git a/docs/website/static/blog/seamless-crash-protection/ios-crash-issue.png b/docs/website/static/blog/seamless-crash-protection/ios-crash-issue.png
new file mode 100644
index 0000000000..aced53e689
Binary files /dev/null and b/docs/website/static/blog/seamless-crash-protection/ios-crash-issue.png differ
diff --git a/docs/website/static/blog/seamless-crash-protection/repo-mappings.png b/docs/website/static/blog/seamless-crash-protection/repo-mappings.png
new file mode 100644
index 0000000000..e6743b0ac2
Binary files /dev/null and b/docs/website/static/blog/seamless-crash-protection/repo-mappings.png differ
diff --git a/docs/website/static/blog/the-codename-one-game-builder.jpg b/docs/website/static/blog/the-codename-one-game-builder.jpg
new file mode 100644
index 0000000000..1342776cd3
Binary files /dev/null and b/docs/website/static/blog/the-codename-one-game-builder.jpg differ
diff --git a/scripts/website/languagetool-accept-blog.txt b/scripts/website/languagetool-accept-blog.txt
index 4386cab996..799ed8927e 100644
--- a/scripts/website/languagetool-accept-blog.txt
+++ b/scripts/website/languagetool-accept-blog.txt
@@ -59,3 +59,25 @@ Catto
# Game-development vocabulary.
[Ss]tarfields?
+
+# Native desktop / watch port libraries and frameworks (this week's Linux,
+# Apple Watch and Windows ports). The shared guide list already carries the
+# GTK/Cairo/Pango/libc/Direct3D/ParparVM terms; these are the ones it lacks.
+GdkPixbuf
+WebKitGTK
+GeoClue
+GStreamer
+EGL
+Direct2D
+DirectWrite
+watchOS
+SwiftUI
+UIKit
+StoreKit
+dSYM
+
+# Symbolication verb forms beyond the guide list's symbolicate/symbolicated.
+[Ss]ymbolicat(e|es|ed|ing|ion)
+
+# Deobfuscation of Android stack traces via the mapping file.
+[Dd]eobfuscat(e|es|ed|ing|ion)