<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Well-Aware Technologies — Blog</title>
    <link>https://wellawaretech.com/blog/</link>
    <atom:link href="https://wellawaretech.com/blog/feed.xml" rel="self" type="application/rss+xml" />
    <description>Mostly SolidRT and the technology around it.  Sometimes the things I learn, build, and think about along the way.</description>
    <language>en</language>
    <lastBuildDate>Tue, 15 Sep 2026 09:00:00 GMT</lastBuildDate>
    <item>
      <title>HTML: Text, Eventually</title>
      <link>https://wellawaretech.com/blog/html-text-eventually/</link>
      <guid isPermaLink="true">https://wellawaretech.com/blog/html-text-eventually/</guid>
      <pubDate>Tue, 15 Sep 2026 09:00:00 GMT</pubDate>
      <dc:creator>Antoine van Wel</dc:creator>
      <description>Text was obvious. So naturally, it took a while</description>
      <content:encoded><![CDATA[<blockquote>
<p><em>Text was obvious. So naturally, it took a while</em></p>
</blockquote>
<p>When we wrote about the <a href="../html-new-beginnings/">rendering primitives</a> in SolidRT,
we glossed over <code>&lt;text&gt;</code> a little.
It looked simple enough. But there was more to it. </p>
<p>And <code>&lt;span&gt;</code> was actually the last element to arrive in SolidRT.</p>
<h2>Keeping It Simple</h2>
<p>When we first started implementing it, 
<code>&lt;text&gt;</code> really was just that: text.
As simple as it gets. 
There was no italic or bold text within a paragraph,
no different colors, no clickable links. Just text. No <code>&lt;span&gt;</code>, yet.</p>
<p>We could get a paragraph of richer text by just using multiple <code>&lt;text&gt;</code> elements inside a <code>&lt;view&gt;</code> with flexbox, giving each one its own properties.
But that is not how paragraphs are usually done.</p>
<h2>Keeping It Together</h2>
<p>There are rules about how text flows, where lines break, how words are shaped and how different runs of text fit together. A paragraph renderer handles all of that as one piece of text, rather than as a collection of independent elements.</p>
<p>Our renderer is Flutter’s Impeller - and Impeller’s paragraph renderer can do exactly that.
So the obvious thing to do was to put some structure around those pieces of text and let Impeller handle the paragraph.
In HTML, we would have a <code>&lt;p&gt;</code> element with <code>&lt;span&gt;</code> elements inside it.
And that’s what we needed: a way to mark up different runs of text within a <code>&lt;text&gt;</code> element where we could set properties or attach handlers to.</p>
<p>This made the implementation straightforward. 
<code>&lt;text&gt;</code> could contain spans, and the spans could provide the extra styling and behavior we needed, while Impeller continued to handle the actual paragraph layout.</p>
<p>But <code>&lt;span&gt;</code> is a bit of an oddball.</p>
<p>Most elements have their own layout and geometry. 
A <code>&lt;span&gt;</code> doesn’t. 
It contributes text to the paragraph, and the paragraph renderer determines where and how that text is laid out.
Shouldn’t it be named a <code>&lt;d-span&gt;</code> then? 
No, it isn’t detached either - it belongs to the paragraph, and cannot be laid out independently.</p>
<p>So even though it may look like a layout-attached element, it isn’t.
That means it’s fine to use it inside a detached text element, <code>&lt;d-text&gt;</code>.</p>
<p>We could have stopped here.</p>
<h2>Breaking It Up Again</h2>
<p>Earlier this year, Cheng Lou, who worked on the React core team at Facebook, released <a href="https://github.com/chenglou/pretext" target="_blank" rel="noreferrer">Pretext</a>.</p>
<p>Pretext is pretty <a href="https://www.youtube.com/watch?v=CUAuy5SWJcw" target="_blank" rel="noreferrer">awesome</a>. 
It gives much more control over paragraph rendering, 
while being more efficient, too.
And the good thing was, for us, that it would actually be easier to implement than in a browser.</p>
<p>Pretext measures words individually and then uses those 
measurements to lay out the paragraph.
But every browser has its own rules for deciding where lines break, and text doesn’t always behave the same way when measured separately from when it is actually laid out and drawn.
So that’s tricky for Pretext, which operates in browsers.</p>
<p>SolidRT has a much easier situation.
We don’t have multiple browser engines to match.
The same engine that measures the text is also responsible for laying it out and drawing it.
That meant we could move the core of Pretext into the engine - into fast Rust.</p>
<p>Text is split and shaped natively, once, and JavaScript gets the metrics it needs to lay out the paragraph.
The <code>&lt;text&gt;</code> element can then use the same engine for rendering, while providing an extra interface for more control, Pretext-style.</p>
<h2>Wrapping It Up</h2>
<p>For <code>&lt;text&gt;</code>, usage remains simple. 
It is still just a way to draw a paragraph like you’d expect, with <code>&lt;span&gt;</code> for styling and interaction within the text.
The difference is that paragraph rendering is not done anymore by Impeller.
Developers don’t have to know any of that. They just get faster text rendering.</p>
<p>And if you do want more control, the building blocks are right there.
<code>prepareText()</code> and <code>layoutNextLine()</code> can be imported directly from core, and used to build your own text flow. 
There is an example of this in <a href="https://github.com/wellawaretech/solidrt/blob/main/packages/core/examples/text-flow.tsx" target="_blank" rel="noreferrer"><code>text-flow.tsx</code></a>.</p>
<p>Which brings us back to where we started.</p>
<p>Text was one of the first things HTML gave us.</p>
<p>For SolidRT, it was the last piece to make its way into pixels.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Why?</title>
      <link>https://wellawaretech.com/blog/why/</link>
      <guid isPermaLink="true">https://wellawaretech.com/blog/why/</guid>
      <pubDate>Sat, 05 Sep 2026 09:00:00 GMT</pubDate>
      <dc:creator>Antoine van Wel</dc:creator>
      <description>An experiment gone wild</description>
      <content:encoded><![CDATA[<blockquote>
<p><em>An experiment gone wild</em></p>
</blockquote>
<p>I’m a Linux fanatic, and I write JavaScript a lot. Not because it’s a beautiful language, but because it runs everywhere. Websites, obviously. Apps, with React Native. Server-side and scripting with Node.js. Just about everywhere. </p>
<p>I’d been working on a fun website for a while, and was considering turning it into a product.
But it was really more suitable as a native application. A native <em>desktop</em> application, with a GUI. </p>
<p>Now what?</p>
<p>I liked React, and I had worked with React Native before. It’s pretty awesome - you scaffold an application, write some JavaScript and JSX, and then you just run it on your phone using a development app. <em>Native.</em> The whole process of getting an application from scratch running on your phone takes <em>minutes</em>. 
React Native has Android and iOS support, and unofficially Windows and macOS. But no Linux. No go.</p>
<p>Then there’s Electron. Everybody seems to be using Electron nowadays. 
But come on, including a <em>full browser</em> just to get to use JavaScript in a GUI? 
It’s not even simple - you cannot just run things in the browser and call the OS when you need to. 
You have a browser environment, a Node.js environment, and communication between them.</p>
<p>Then there are various options which use webviews. Webviews, really? 
Webviews really are browsers, only these are provided by the OS you are running on - which means you cannot rely on what you get. Good luck debugging that.
In the mobile world, the whole reason React Native became interesting was that you could use JavaScript without building your UI out of webviews. 
And now we’re back to building <em>desktop</em> applications with… <em>webviews</em>? Oh please.</p>
<p>Nothing came close to what I wanted. </p>
<p>This wasn’t the first time I was thinking about this, but something had changed. 
I had switched from Node.js to Bun. 
It supported JSX directly and could produce single file executables.
I remembered seeing that Bun could also use SDL via <code>node-sdl</code> - it stood out to me not because of Bun, but because I hadn’t realized before that SDL could be used together with JavaScript.
SDL was something I’d used myself way back, and it was widely used for building cross-platform games.
I guess that got the ball rolling. 
I was thinking executables, built with Bun, with a GUI on top of SDL, and using Skia for rendering. Every browser I knew of was using Skia, so it seemed like the obvious choice.
A GUI that would be managed with React via its universal renderer, just like React Native.</p>
<p>I decided to do an experiment.</p>
<p>First I got Bun talking to SDL, then added Skia to write to an SDL buffer shown in a window and put universal React in front. 
It worked. 
But I was a bit intimidated by React’s universal renderer - it was pretty complex and documentation was scarce. 
I recalled having read about SolidJS somewhere, which also had a universal renderer, but worked without a virtual DOM - that virtual DOM which gets in the way when you’re doing high-frequency animations. And I wanted animations.
So I gave SolidJS a chance - and it worked. And how!</p>
<p>From that moment on, I was hooked. I started a project, gave it a name: Electrosol. 
I added React Native’s layout engine, which got quickly replaced, because grids. 
It started to feel a lot like React Native - but different. 
It felt <em>better</em> somehow - but this was more of a gut feeling. After all I only had a prototype,
which was cute, but hardly groundbreaking. But I felt its potential. </p>
<p>Around Christmas 2025 I made up my mind how to continue with the project. 
I decided to go <em>all in</em>. 
This was just too good to let die.</p>
<p>I changed the name to Solid-RT: the Solid Runtime. 
The engine would be written in Rust, the render tree would be in Rust; the SolidJS part was meant to stay as lean as possible. 
As it turned out, Flutter had run into issues with Skia and was replacing it with a more modern renderer called Impeller. This seemed like the right direction to follow - so Skia was out, Impeller was in.
I had ideas where to take this, most of them long term.
I estimated that by February 2026 I would have a first decent version.</p>
<p>But then I got a new friend named Claude. 
And things started moving <em>fast</em>.</p>
<p>QuickJS came in to replace Bun as a JavaScript runtime. It could be embedded directly into Solid-RT, which unlocked Android and iOS - mobile was in. 
I also wanted the development experience I liked about React Native.
So a development app came to life, 
connecting devices to a dev server.
But that wouldn’t be restricted to mobile - <em>any</em> device could connect, including Windows or macOS.
Seeing my code update live across all my hardware, well - I got euphoric.</p>
<p>It felt like everything was coming together naturally. One thing led to another. The pieces just fit.</p>
<p>There were roadblocks, too - at least, that’s how they appeared at first.
Flutter supports custom fragment shaders. I had adopted Flutter’s renderer. Surely I’d get that too?
No. Impeller’s API did not give access to them.</p>
<p>Fragment shaders are where you get to tell the GPU what to do with every pixel. They open the door to effects and graphics that aren’t possible with the renderer’s built-in primitives alone.</p>
<p>But Flutter had a different approach to shaders.
That door appeared to be locked - I would have needed more from the Flutter project than Impeller alone.
But there turned out to be another door.
Impeller had an OpenGL backend. I could simply make a fragment shader in GL, and then feed the <em>result</em> into Impeller.
Fragment shaders were in.</p>
<p>March 2026, I decided to open source at least a part of the project.</p>
<p>I started a fresh project, copying over the parts I wanted to publish.
Solid-RT became SolidRT. 
The architecture kept evolving. 
I moved SolidRT to SolidJS 2. 
And I came to realize that what appeared to be a roadblock at first actually opened the door to much more than fragment shaders on the GPU.</p>
<p>A lot more. </p>
<p>Vertex shaders entered the picture. That meant I could start moving <em>much</em> more of the rendering work onto the GPU, instead of being limited to what Impeller exposed.
And I realized I was getting into territory where I could have a real advantage over Electron, React Native and Flutter.
The stakes went up, and the February estimate had gone out the window.</p>
<p>July 2026. “AI native” had become a thing and I came to my own conclusion about what that meant. </p>
<p>To me, it wasn’t about adding an AI assistant to the development workflow. 
If agents were going to be a first-class part of building applications, 
they needed to be able to interact with the applications themselves. 
Not just write code, but run it, inspect it, measure it, understand what was happening, then change it.</p>
<p>And I could do that because SolidRT owned the full flow - from JavaScript all the way down to the GPU, 
while running live on any device.
There wasn’t a browser, a webview, or any other layer in between. 
It controls <em>everything</em>.</p>
<p>I added MCP support. And things got wild.</p>
<p>I let agents build stuff, let them report on their findings, and took that feedback back to the core,
or used it to extend the MCP server.</p>
<p>That gave me a huge amount of insight in a very short time, and the process accelerated again.
By this time, agents were able to build full applications without intervention - they could control the mouse, 
keyboard, gamepads and even time. I would just sit back and watch them build, step through, try things, play.</p>
<p>What also surprised me was how quickly they started working around the limitations of interpreted JavaScript. 
When something was too heavy, they found another way. 
Shaders were already there and easy to use, so they simply started using the GPU.
When I introduced workers, they simply started offloading work from the main thread.</p>
<p>And as the applications got more ambitious, I started working on a 3D extension. 
That’s when I started hitting the limits of interpreted JavaScript hard, 
and this time there were no easy workarounds.</p>
<p>The answer was to add a spatial core in Rust to take over the heavy computations. 
I tried to keep it generic enough to be useful beyond 3D, which led to a 2D extension using the same core.</p>
<p>I was no longer comparing with Flutter and React Native - I was comparing with Three.js, Unity and Godot: the world of graphics and games.</p>
<p>And it all made sense. </p>
<p>— Antoine van Wel</p>
]]></content:encoded>
    </item>
    <item>
      <title>HTML: New Beginnings</title>
      <link>https://wellawaretech.com/blog/html-new-beginnings/</link>
      <guid isPermaLink="true">https://wellawaretech.com/blog/html-new-beginnings/</guid>
      <pubDate>Thu, 03 Sep 2026 09:00:00 GMT</pubDate>
      <dc:creator>Antoine van Wel</dc:creator>
      <description>What if HTML didn't start with documents, but with pixels?</description>
      <content:encoded><![CDATA[<blockquote>
<p><em>What if HTML didn’t start with documents, but with pixels?</em></p>
</blockquote>
<p>HTML started with documents and how they were connected. 
Its fundamental objects were text, headings, lists and links.</p>
<table>
<thead>
<tr>
<th>Tag</th>
<th>Description</th>
</tr>
</thead>
<tbody><tr>
<td><code>&lt;title&gt;</code></td>
<td>document title</td>
</tr>
<tr>
<td><code>&lt;h1&gt;</code>, <code>&lt;h2&gt;</code>, ..</td>
<td>heading level 1, 2, ..</td>
</tr>
<tr>
<td><code>&lt;p&gt;</code></td>
<td>paragraph</td>
</tr>
<tr>
<td><code>&lt;ul&gt;</code>, <code>&lt;dl&gt;</code></td>
<td>unordered, definition list</td>
</tr>
<tr>
<td><code>&lt;a&gt;</code></td>
<td>anchor, the start or destination of a link</td>
</tr>
</tbody></table>
<p>Combined with the internet, this started a revolution.</p>
<p>This article isn’t about the network, though. It’s about HTML itself — and what it might have looked like if it had started somewhere else.</p>
<p>HTML would evolve and add many things. 
Documents gained images, forms, buttons, canvas, video, and all the other things we now expect from a web page. 
HTML was no longer just describing documents; it had become a way to describe applications and interfaces.</p>
<p>The original idea remained: HTML describes what things are and how they relate to each other.
But what if HTML had started somewhere else? What if it hadn’t started with documents, but with pixels?</p>
<h2>What?</h2>
<p>Today, pixels are produced by specialized processors: GPUs.</p>
<p>But a GPU has no concept of what those pixels mean. 
It doesn’t know whether they came from a paragraph, a heading, a button or a video.
It works with more fundamental building blocks: geometry, textures, colors, transformations, and operations performed on them.</p>
<p>So what would our HTML look like if, instead of starting with documents, we started with what needs to be drawn?</p>
<p>We would need a small set of elements that covers everything that appears on screen. The most general of these is a path: a sequence of points and curves that can describe essentially any shape. But we use some shapes so often that writing them out as paths every time would be unnecessarily verbose. Lines, rectangles, and ovals give us convenient elements for those common cases.</p>
<p>Text can ultimately be reduced to paths too: each glyph is a shape. 
But describing text as a collection of paths is hardly convenient. So text gets its own element.</p>
<p>Text is usually grouped into paragraphs. But within a paragraph, different parts of the text may need different properties: a word can be bold or italic, use a different font or color, or even be clickable.
So we need a way to express that without affecting the surrounding text. We’ll call such a run of text a span.</p>
<p>And then there is pixel data itself. Images, video frames, and other generated pixel data don’t need to be broken down into shapes. We can put the pixels directly on screen.
A texture gives us that capability. It represents a block of pixel data that can be placed, transformed, and composited like any other visual element.</p>
<p>Together, these form our drawing primitives:</p>
<table>
<thead>
<tr>
<th>Element</th>
<th>Description</th>
</tr>
</thead>
<tbody><tr>
<td><code>&lt;path&gt;</code></td>
<td>arbitrary shapes</td>
</tr>
<tr>
<td><code>&lt;line&gt;</code></td>
<td>straight lines</td>
</tr>
<tr>
<td><code>&lt;rect&gt;</code></td>
<td>areas</td>
</tr>
<tr>
<td><code>&lt;oval&gt;</code></td>
<td>ellipses and circles</td>
</tr>
<tr>
<td><code>&lt;text&gt;</code></td>
<td>text</td>
</tr>
<tr>
<td><code>&lt;span&gt;</code></td>
<td>styled text run</td>
</tr>
<tr>
<td><code>&lt;texture&gt;</code></td>
<td>direct access to pixels</td>
</tr>
</tbody></table>
<p>With these elements, we can draw <em>anything</em>.</p>
<p>Now we know <em>what</em> to draw, we also need to know <em>how</em>.</p>
<h2>How?</h2>
<p>A rectangle is an area that can be filled with color, or outlined with a stroke.
The color could be a gradient, or blend in a certain way with what’s drawn
behind it.
This isn’t exclusive to rectangles — these properties apply to almost every drawing primitive. </p>
<p>We call this <em>paint</em>.</p>
<p>A paint describes <em>how</em> an element is rendered: fill or stroke, colors and gradients, stroke properties, blending. 
It is a separate concept from the shape — the same paint applies to a rectangle, a path or a run of text.</p>
<table>
<thead>
<tr>
<th>Paint property</th>
<th>Description</th>
</tr>
</thead>
<tbody><tr>
<td><code>color</code></td>
<td>a color or a gradient</td>
</tr>
<tr>
<td><code>drawStyle</code></td>
<td>fill, stroke or both</td>
</tr>
<tr>
<td><code>stroke*</code></td>
<td>stroke properties</td>
</tr>
<tr>
<td><code>blendMode</code></td>
<td>how the result combines with what is behind it</td>
</tr>
</tbody></table>
<p>We now know <em>what</em> to draw and <em>how</em> to paint it. But <em>where</em> do we put it?</p>
<h2>Where?</h2>
<p>In modern HTML, this has been solved by CSS: flex and grid layout.
We don’t need to reinvent this.
Flexbox and grid are great solutions for positioning.
We simply attach a layout to each element.</p>
<p>Our elements also need structure.
They need to live somewhere, and that structure needs to be nestable.</p>
<p>For this, we introduce a <em>view</em>.</p>
<p>Views provide structure for grouping other elements.
They don’t draw anything themselves.
In that sense, they are similar to a <code>&lt;div&gt;</code> in HTML.</p>
<table>
<thead>
<tr>
<th>Element</th>
<th>Description</th>
</tr>
</thead>
<tbody><tr>
<td><code>&lt;view&gt;</code></td>
<td>groups elements</td>
</tr>
</tbody></table>
<p>Views can also transform everything inside them.
They can translate, rotate and scale their content.
These transformations are independent of layout.</p>
<p>The layout engine sees the view’s layout geometry, 
while the renderer sees its transformed coordinate space.
Transformations like these are exactly the kind of work GPUs are good at.</p>
<h2>Where else?</h2>
<p>We now know <em>what</em> to draw, <em>how</em> to paint it, and <em>where</em> to put it. Or do we?</p>
<p>Imagine something as simple as a box with a background color and some text on top.
We need a rectangle, and we need text. 
But we also need to control their positions relative to each other.
A layout engine has an answer to this: absolute positioning.
But we would be (ab)using the layout engine for something that should be simple and fast. </p>
<p>So what if an element could simply opt out of layout?</p>
<p>And that is exactly what detached elements are.
They are the same primitives we already have, but without participating in layout:</p>
<table>
<thead>
<tr>
<th>Element</th>
<th>Description</th>
</tr>
</thead>
<tbody><tr>
<td><code>&lt;d-view&gt;</code></td>
<td>detached groups primitives</td>
</tr>
<tr>
<td><code>&lt;d-text&gt;</code></td>
<td>detached text</td>
</tr>
<tr>
<td><code>&lt;d-rect&gt;</code></td>
<td>detached areas</td>
</tr>
<tr>
<td><code>&lt;d-oval&gt;</code></td>
<td>detached ellipses and circles</td>
</tr>
<tr>
<td><code>&lt;d-line&gt;</code></td>
<td>detached straight lines</td>
</tr>
<tr>
<td><code>&lt;d-path&gt;</code></td>
<td>detached arbitrary shapes</td>
</tr>
<tr>
<td><code>&lt;d-texture&gt;</code></td>
<td>detached textures</td>
</tr>
</tbody></table>
<p>Detached elements are still part of the view they live in. 
They can be translated, rotated and scaled within that view. 
The only difference is that the layout engine is completely unaware of them.</p>
<h2>When?</h2>
<p>We know what to draw, how to paint it and where to put it. What we don’t know is <em>when</em> any of it needs to change.</p>
<p>The elements live in a render tree. 
That tree needs to be constructed, updated and torn down. 
Properties need to change as application state changes.</p>
<p>This is where SolidJS comes in.</p>
<p>SolidJS does exactly this: it manages the tree and updates the things that actually changed.
The result is a direct path from application state to the render tree.</p>
<p>So what would HTML look like if it had started with the pixels?</p>
<p>Six elements, each in a laid-out and a detached variant.
A span that lives only inside text.
A paint.
A view, which may itself be laid out or detached.
And a way to say when things change.</p>
<p>That is the whole vocabulary. Its fundamental objects are not documents, but the things we draw.</p>
<p>And it exists.</p>
<p>This is the foundation of SolidRT, the Solid Runtime.
It is developed in the open: <a href="https://github.com/wellawaretech/solidrt" class="url" target="_blank" rel="noreferrer">https://github.com/wellawaretech/solidrt</a></p>
<p>And if you’re thinking, “Hang on, isn’t this just HTML, SVG and Canvas?” — yes. Pretty much.</p>
<p>We just started from the other end.</p>
]]></content:encoded>
    </item>
  </channel>
</rss>
