<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
  <id>https://jumplink.eu/en/blog/tags/android/feed.xml</id>
  <title>Pascal Garber – Android</title>
  <updated>2026-11-06T00:00:00Z</updated>
  <link rel="self" type="application/atom+xml" href="https://jumplink.eu/en/blog/tags/android/feed.xml"/>
  <link rel="alternate" type="text/html" href="https://jumplink.eu/en/blog/tags/android/"/>
  <author>
    <name>Pascal Garber</name>
    <uri>https://jumplink.eu/</uri>
  </author>
  <entry>
    <id>https://jumplink.eu/en/blog/learn6502-everywhere/</id>
    <title>Learn 6502 now runs on Linux, macOS, Windows and Android</title>
    <link rel="alternate" href="https://jumplink.eu/en/blog/learn6502-everywhere/"/>
    <published>2026-11-06T00:00:00Z</published>
    <updated>2026-11-06T00:00:00Z</updated>
    <summary>Learn 6502 Assembly now runs on Linux, macOS, Windows and Android, all from one TypeScript codebase. How gjsify makes that possible, and where AI fits in.</summary>
    <content type="html">&lt;p&gt;I&amp;#39;m happy to say that since version 0.9.0, &lt;a href=&quot;https://jumplink.eu/Learn6502/en/&quot;&gt;Learn 6502 Assembly&lt;/a&gt; runs on Linux, macOS, Windows and Android 🐧🍏🪟🤖. Learn 6502 already ran on a phone before, by the way: on my OnePlus 6T with &lt;a href=&quot;https://postmarketos.org/&quot;&gt;postmarketOS&lt;/a&gt;, as a regular GNOME app. What&amp;#39;s new is that it now runs on Android too.&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://jumplink.eu/blog/2026/learn6502-everywhere-phones.webp&quot; alt=&quot;Learn 6502 on two phones in autumn leaves: an OnePlus 6T with postmarketOS and GNOME Mobile on the left, a Samsung Galaxy S9 with /e/OS on the right&quot; loading=&quot;lazy&quot; title=&quot;Learn 6502 on two phones in autumn leaves: an OnePlus 6T with postmarketOS and GNOME Mobile on the left, a Samsung Galaxy S9 with /e/OS on the right&quot;&gt;&lt;figcaption&gt;Learn 6502 on two phones in autumn leaves: an OnePlus 6T with postmarketOS and GNOME Mobile on the left, a Samsung Galaxy S9 with /e/OS on the right&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;All downloads are on the &lt;a href=&quot;https://jumplink.eu/Learn6502/en/&quot;&gt;app page&lt;/a&gt;. On Linux, &lt;a href=&quot;https://flathub.org/apps/eu.jumplink.Learn6502&quot;&gt;Flathub&lt;/a&gt; is still the recommended way. What the app does is in the &lt;a href=&quot;https://jumplink.eu/en/blog/learn6502/&quot;&gt;first post&lt;/a&gt;. This one is about how a GNOME app gets onto four systems without me maintaining four apps.&lt;/p&gt;
&lt;h3&gt;One codebase, four systems&lt;/h3&gt;
&lt;p&gt;Learn 6502 is written in TypeScript, the interface in Blueprint for GTK 4 and libadwaita. That code runs everywhere, just on a different runtime each time:&lt;/p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;System&lt;/th&gt;&lt;th&gt;Runtime&lt;/th&gt;&lt;th&gt;GTK and Adwaita come from&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Linux&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://gjs.guide/&quot;&gt;GJS&lt;/a&gt;&lt;/td&gt;&lt;td&gt;the GNOME runtime in the Flatpak&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;macOS, Windows&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://nodejs.org/&quot;&gt;Node.js&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://gjsify.org/gjsify/projects/node-gi/&quot;&gt;&lt;code&gt;@gjsify/node-gi&lt;/code&gt;&lt;/a&gt; and a bundled GTK runtime&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Android&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://nativescript.org/&quot;&gt;NativeScript&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://gjsify.org/gjsify/adwaita/&quot;&gt;&lt;code&gt;@gjsify/adwaita-nativescript&lt;/code&gt;&lt;/a&gt;, real Android views styled like Adwaita&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;On Linux, Learn 6502 is a regular GJS app. For macOS and Windows I rebuilt the GJS runtime environment for Node.js. &lt;code&gt;@gjsify/node-gi&lt;/code&gt; loads &lt;code&gt;gi://&lt;/code&gt; namespaces like GLib, Gtk and Adw in Node.js and behaves like GJS while doing it. It started from &lt;a href=&quot;https://github.com/romgrk/node-gtk&quot;&gt;node-gtk&lt;/a&gt; and is now largely rewritten. So that I can rely on &amp;quot;behaves like GJS&amp;quot;, the same tests run on both runtimes.&lt;/p&gt;
&lt;p&gt;Android has no GTK. There the app runs in NativeScript, and &lt;code&gt;@gjsify/adwaita-nativescript&lt;/code&gt; builds native Android views from the same Blueprint files, styled like libadwaita. No WebView involved. GLib and GObject come through node-gi here too.&lt;/p&gt;
&lt;p&gt;That said, &amp;quot;no GTK on Android&amp;quot; isn&amp;#39;t quite true anymore. Florian &amp;quot;sp1rit&amp;quot; is working on an Android backend for GTK, and &lt;a href=&quot;https://geopjr.dev/&quot;&gt;GeopJr&lt;/a&gt; publishes unofficial test builds of GTK and Adwaita apps like the Adwaita Demo and Tuba on &lt;a href=&quot;https://gtk4android.geopjr.dev/&quot;&gt;GTK 4 Android&lt;/a&gt;. We&amp;#39;re experimenting with that too: &lt;code&gt;@gjsify/gi-runtime-android-gtk&lt;/code&gt; brings GTK 4 and libadwaita into a NativeScript app. Once that works well enough, we can drop our rebuilt Adwaita widgets and use real GTK on Android.&lt;/p&gt;
&lt;p&gt;The Android version is still experimental. The basics work: you can read the tutorial, write code and run it on the console. Expect a rough edge here and there, though.&lt;/p&gt;
&lt;h3&gt;And the other way round&lt;/h3&gt;
&lt;p&gt;The bridge goes both ways. &lt;a href=&quot;https://gjsify.org/gjsify/&quot;&gt;gjsify&lt;/a&gt; brings Node.js and Web APIs to GJS and implements them on GNOME&amp;#39;s own libraries: &lt;code&gt;node:fs&lt;/code&gt; on Gio, &lt;code&gt;fetch&lt;/code&gt; on Soup, &lt;a href=&quot;https://nodejs.org/api/sqlite.html&quot;&gt;&lt;code&gt;node:sqlite&lt;/code&gt;&lt;/a&gt; on libsqlite3.&lt;/p&gt;
&lt;p&gt;New is &lt;a href=&quot;https://gjsify.org/gjsify/projects/napi/&quot;&gt;&lt;code&gt;@gjsify/napi&lt;/code&gt;&lt;/a&gt;, an implementation of &lt;a href=&quot;https://nodejs.org/api/n-api.html&quot;&gt;Node-API&lt;/a&gt; for GJS. With it, GJS loads native Node.js addons, the &lt;code&gt;.node&lt;/code&gt; files compiled for Node.js. &lt;a href=&quot;https://github.com/WiseLibs/better-sqlite3&quot;&gt;better-sqlite3&lt;/a&gt; runs unmodified in GJS this way and returns byte-identical results to Node.js.&lt;/p&gt;
&lt;p&gt;I&amp;#39;m impressed by what AI makes possible now. Implementing Node-API for GJS or rebuilding the Adwaita widgets for Android would have been out of reach for me alone a few years ago.&lt;/p&gt;
&lt;p&gt;So the code is compatible in both directions. I pick the runtime when I build, not when I write the code.&lt;/p&gt;
&lt;p&gt;gjsify itself runs on GJS as well. Installing, building, testing, the Flatpak and the macOS and Windows packages all work on a machine without Node.js. Node.js is a runtime you can choose, not a requirement. More in &lt;a href=&quot;https://jumplink.eu/en/blog/why-gjsify/&quot;&gt;Why gjsify&lt;/a&gt; and &lt;a href=&quot;https://jumplink.eu/en/blog/macos-signing/&quot;&gt;Shipping GNOME apps for Linux, macOS and Windows with gjsify&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;One big experiment&lt;/h3&gt;
&lt;p&gt;gjsify is still in heavy development and really one big experiment. The idea is that any JavaScript, whether written for Node.js or the browser, should run in a native Adwaita app. A good part of that already works. The Excalibur.js game engine, three.js, socket.io and WebTorrent run on GJS through gjsify, checked with their own test suites. What is still missing is in the &lt;a href=&quot;https://github.com/gjsify/gjsify/tree/main/status&quot;&gt;project status&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;It started without AI&lt;/h3&gt;
&lt;p&gt;It all began with &lt;a href=&quot;https://github.com/gjsify/ts-for-gir&quot;&gt;ts-for-gir&lt;/a&gt;. I wanted to write GNOME apps in TypeScript and needed types for GTK and the other GObject libraries. There were no AI tools back then. It took me about three years of spare time until the parser and generator produced really good types. Today you write a generator like that with AI in a short time, and it even works well. There are new projects like &lt;a href=&quot;https://gtkx.dev/&quot;&gt;GTKX&lt;/a&gt; that also generate their bindings from GObject Introspection.&lt;/p&gt;
&lt;p&gt;I wrote Learn 6502 itself mostly by hand. A better AI autocomplete helped, and even that was worth a lot.&lt;/p&gt;
&lt;p&gt;gjsify started without AI too. I wrote some Node.js modules like &lt;code&gt;node:fs&lt;/code&gt; by hand and tried a lot of things. But the project was too big for one person. AI changed that, and today gjsify is built almost entirely through agentic coding.&lt;/p&gt;
&lt;p&gt;I set the rules. Linux standards like the &lt;a href=&quot;https://flatpak.github.io/xdg-desktop-portal/&quot;&gt;XDG desktop portals&lt;/a&gt;, GJS and Web standards always come first, and where an open standard exists, we use it. When an app is missing something, it gets built into gjsify with a test instead of being worked around in the app. That gives me very good results right now. Without it, Learn 6502 would not have made it to Android and Windows.&lt;/p&gt;
&lt;h3&gt;Why I use AI anyway&lt;/h3&gt;
&lt;p&gt;I know AI is frowned upon in the open source community, and for good reasons. The training data was taken without consent, the energy use is high, and the effects on society will be large. I see all of that very critically. But we won&amp;#39;t stop this by rejecting or ignoring AI.&lt;/p&gt;
&lt;p&gt;What we can do is use AI as a tool for more and better free software. Software that makes us less dependent on big corporations. And we should support open models together, so the best AI doesn&amp;#39;t end up controlled by a few people or companies.&lt;/p&gt;
&lt;p&gt;That is also why I started &lt;a href=&quot;https://jumplink.eu/steuererklaerung/&quot;&gt;Steuererklärung&lt;/a&gt;, an app that lets anyone in Germany do their tax return for free. People with little money are often the ones who don&amp;#39;t file a tax return, and that leaves them with even less. My goal is to make the app simple enough that this stops being a barrier.&lt;/p&gt;
&lt;h3&gt;Try it&lt;/h3&gt;
&lt;ul&gt;&lt;li&gt;Learn 6502: &lt;a href=&quot;https://jumplink.eu/Learn6502/en/&quot;&gt;downloads&lt;/a&gt;, &lt;a href=&quot;https://github.com/JumpLink/Learn6502&quot;&gt;source code&lt;/a&gt;, translate on &lt;a href=&quot;https://hosted.weblate.org/engage/eu-jumplink-learn6502/&quot;&gt;Weblate&lt;/a&gt;&lt;/li&gt;&lt;li&gt;gjsify: &lt;a href=&quot;https://gjsify.org/gjsify/&quot;&gt;documentation&lt;/a&gt;, &lt;a href=&quot;https://github.com/gjsify/gjsify&quot;&gt;GitHub&lt;/a&gt;, and to get started, &lt;a href=&quot;https://jumplink.eu/en/blog/gjsify-first-app/&quot;&gt;A GNOME app in TypeScript, in five minutes&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;I hope gjsify is a useful tool for you too. Feedback and bug reports are welcome on &lt;a href=&quot;https://github.com/gjsify/gjsify/issues&quot;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;</content>
    <category term="gjsify"/>
    <category term="GNOME"/>
    <category term="Android"/>
  </entry>
</feed>