<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
    <channel>
      <title>Ply - Blog</title>
      <link>https://plyx.iz.rs/blog/</link>
      <description>Beautiful apps in Rust. Cross-platform. Dead simple.</description>
      <generator>Zola</generator>
      <language>en</language>
      <atom:link href="https://plyx.iz.rs/blog/rss.xml" rel="self" type="application/rss+xml"/>
      <lastBuildDate>Sun, 23 Aug 2026 00:00:00 +0000</lastBuildDate>
      <item>
          <title>Conquering IME, Community Projects, and the Road to Ply 2.0</title>
          <pubDate>Sun, 23 Aug 2026 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://plyx.iz.rs/blog/conquering-ime/</link>
          <guid>https://plyx.iz.rs/blog/conquering-ime/</guid>
          <description xml:base="https://plyx.iz.rs/blog/conquering-ime/">&lt;p&gt;It has been over 4 months since the &lt;a href=&quot;&#x2F;blog&#x2F;ply-1-1&#x2F;&quot;&gt;Ply 1.1 release&lt;&#x2F;a&gt; in April.&lt;&#x2F;p&gt;
&lt;p&gt;Life got busy in good ways: I went on my senior trip to Berlin, found a boyfriend, moved in with him, started my first job, finished &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheRedDeveloper&#x2F;flowquill&quot;&gt;Flowquill&lt;&#x2F;a&gt;, and went to university orientation camp. Between all that, Ply saw some heavy engineering work.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;rewriting-input-methods&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#rewriting-input-methods&quot; aria-label=&quot;Anchor link for: rewriting-input-methods&quot;&gt;🔗&lt;&#x2F;a&gt;Rewriting input methods&lt;&#x2F;h2&gt;
&lt;p&gt;Back in April, someone opened an issue showing that typing Chinese characters ended up reversed on Windows.&lt;&#x2F;p&gt;
&lt;p&gt;If you only type in English, input seems straightforward: hit a key, get a character code, draw a glyph. Yet for most of the world, text input relies on multi-stage composition. With Pinyin, Kana-to-Kanji, Hangul, dead keys, or mobile voice-to-text, keystrokes aren&#x27;t put down immediately. Ply had no real concept of an Input Method Editor (IME).&lt;&#x2F;p&gt;
&lt;p&gt;Over the past four months, I rewrote the OS-level input pipelines. On Windows, that meant dealing with Imm32 and Text Services Framework messages. Linux required supporting both legacy X11 XIM and Wayland &lt;code&gt;text-input-unstable-v3&lt;&#x2F;code&gt;. Android and iOS needed native virtual keyboard hooks and predictive text streams. On web, I built an invisible DOM bridge to sync canvas state. For macOS, I worked with a cloud Mac until 4 AM rewriting Cocoa input delegates.&lt;&#x2F;p&gt;
&lt;p&gt;The final diff was +4,884 lines and -1,019 lines, our largest single feature update so far. Input across all six platforms now behaves properly whether you type in English, Chinese, Japanese, or use accent keys.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-people-are-building&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#what-people-are-building&quot; aria-label=&quot;Anchor link for: what-people-are-building&quot;&gt;🔗&lt;&#x2F;a&gt;What people are building&lt;&#x2F;h2&gt;
&lt;p&gt;Seeing what developers build with Ply is easily one of the best parts of working on it.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;emergency-weather-tracking-rustywx&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#emergency-weather-tracking-rustywx&quot; aria-label=&quot;Anchor link for: emergency-weather-tracking-rustywx&quot;&gt;🔗&lt;&#x2F;a&gt;Emergency weather tracking (rustywx)&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;kerryhatcher&quot;&gt;@kerryhatcher&lt;&#x2F;a&gt; is building &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;kerryhatcher&#x2F;rustywx&quot;&gt;&lt;strong&gt;rustywx&lt;&#x2F;strong&gt;&lt;&#x2F;a&gt;, a radar and storm-tracking tool for EMA first responders, volunteer firefighters, and storm chasers on field laptops.&lt;&#x2F;p&gt;
&lt;p&gt;This hit close to home recently when I had to evacuate due to a forest fire one kilometer away. Being back home safe, it means a lot to know Ply may be used for real emergencies.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;3d-printed-pcb-stencils-vcode&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#3d-printed-pcb-stencils-vcode&quot; aria-label=&quot;Anchor link for: 3d-printed-pcb-stencils-vcode&quot;&gt;🔗&lt;&#x2F;a&gt;3D-printed PCB stencils (vcode)&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;pszsh&quot;&gt;@pszsh&lt;&#x2F;a&gt; (Jess) created &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;git.else-if.org&#x2F;jess&#x2F;vcode&quot;&gt;&lt;strong&gt;vcode&lt;&#x2F;strong&gt;&lt;&#x2F;a&gt;, a tool for 3D printing solder paste stencils. Normal slicers leave messy retraction blobs on tiny surface-mount pads. &lt;code&gt;vcode&lt;&#x2F;code&gt; uses Connected Fermat Spirals to generate continuous-line G-code. Jess built the interface in Ply and compiled it for both native desktop and WebAssembly.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;music-notation-cadenzier&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#music-notation-cadenzier&quot; aria-label=&quot;Anchor link for: music-notation-cadenzier&quot;&gt;🔗&lt;&#x2F;a&gt;Music notation (Cadenzier)&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;twilit-jack&quot;&gt;@twilit-jack&lt;&#x2F;a&gt; is working on &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;codeberg.org&#x2F;cadenzier&#x2F;cadenzier&quot;&gt;&lt;strong&gt;Cadenzier&lt;&#x2F;strong&gt;&lt;&#x2F;a&gt;, a music notation editor. They have been testing architecture patterns in Ply, finding ways to manage signal bubbling and nested layouts with minimal boilerplate.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;license&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#license&quot; aria-label=&quot;Anchor link for: license&quot;&gt;🔗&lt;&#x2F;a&gt;License&lt;&#x2F;h2&gt;
&lt;p&gt;The two games I built with Ply are now public on GitHub:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheRedDeveloper&#x2F;Stratum&quot;&gt;Stratum&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: The turn-based multiplayer strategy game that originally motivated Ply.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheRedDeveloper&#x2F;FungalEconomics&quot;&gt;Fungal Economics&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: A real-time strategy project centered around mycelial growth and resource networks.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;I used the new &lt;a href=&quot;&#x2F;noncommercial-license&#x2F;1&#x2F;&quot;&gt;Ply Noncommercial License 1&lt;&#x2F;a&gt; so anyone can study the code, mod it, or run private servers, while keeping commercial forks off the table. If you want concrete examples of shaders, networking, or UI state in Ply, check out the repos.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;next&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#next&quot; aria-label=&quot;Anchor link for: next&quot;&gt;🔗&lt;&#x2F;a&gt;Next&lt;&#x2F;h2&gt;
&lt;p&gt;Ply 1.2 is coming shortly, and I will do a dedicated release post once it ships.&lt;&#x2F;p&gt;
&lt;p&gt;Looking further out, planning for &lt;strong&gt;Ply 2.0&lt;&#x2F;strong&gt; is underway. The goal is to switch to an independent rendering backend. Dropping upstream dependencies will let us add first-class 3D support, combining Spline-like visual tooling with Ply&#x27;s immediate-mode ergonomics, 2D&#x2F;3D compositing, and zero ECS overhead.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;sponsorships&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#sponsorships&quot; aria-label=&quot;Anchor link for: sponsorships&quot;&gt;🔗&lt;&#x2F;a&gt;Sponsorships&lt;&#x2F;h2&gt;
&lt;p&gt;I plan to keep developing Ply regardless, but balancing school, work, and a cross-platform engine takes time.&lt;&#x2F;p&gt;
&lt;p&gt;I opened &lt;strong&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sponsors&#x2F;TheRedDeveloper&quot;&gt;GitHub Sponsorships&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; and &lt;strong&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;ko-fi.com&#x2F;redderdeveloper&quot;&gt;Kofi&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;. If Ply is useful to you or your project, backing it helps me focus more on Ply&#x27;s development.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;getting-started&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#getting-started&quot; aria-label=&quot;Anchor link for: getting-started&quot;&gt;🔗&lt;&#x2F;a&gt;Getting started&lt;&#x2F;h2&gt;
&lt;p&gt;If you want to learn more about Ply, you can take a look at the &lt;a href=&quot;&#x2F;docs&#x2F;getting-started&#x2F;&quot;&gt;interactive docs&lt;&#x2F;a&gt;, or as before you can drop by &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheRedDeveloper&#x2F;ply-engine&#x2F;discussions&quot;&gt;GitHub Discussions&lt;&#x2F;a&gt; to share what you are working on.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Ply 1.1: Building Polished UIs in Rust</title>
          <pubDate>Sun, 05 Apr 2026 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://plyx.iz.rs/blog/ply-1-1/</link>
          <guid>https://plyx.iz.rs/blog/ply-1-1/</guid>
          <description xml:base="https://plyx.iz.rs/blog/ply-1-1/">&lt;p&gt;When I released Ply 1.0, a months ago, the response was incredible. The project already hit 250 stars on GitHub. But we have been continuing to improve Ply.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-async-nightmare&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-async-nightmare&quot; aria-label=&quot;Anchor link for: the-async-nightmare&quot;&gt;🔗&lt;&#x2F;a&gt;The async nightmare&lt;&#x2F;h2&gt;
&lt;p&gt;Applications need to do background work. If you do this on the main thread, your game stutters and your app freezes. If you do it in the background in Rust, you usually end up drowning in &lt;code&gt;mpsc&lt;&#x2F;code&gt; channels and wrapping everything in &lt;code&gt;Arc&amp;lt;Mutex&amp;lt;T&amp;gt;&amp;gt;&lt;&#x2F;code&gt;. Getting the result back to the UI thread is a chore.&lt;&#x2F;p&gt;
&lt;p&gt;Ply 1.1 fixes this with the new &lt;code&gt;jobs&lt;&#x2F;code&gt; module.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F9E2AF;&quot;&gt;jobs&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;spawn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;  &amp;quot;save_game&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;  ||&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt; async move&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F9E2AF;&quot;&gt;    Storage&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;&amp;quot;my_app&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt;await&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;?&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;      .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;save_string&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;&amp;quot;save.json&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F9E2AF;&quot;&gt;        serde_json&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;to_string&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;game_state&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;map_err&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt; e&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;to_string&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;())&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;?&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;      )&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt;await&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;  },&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span&gt;result&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt;    if let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F9E2AF;font-style: italic;&quot;&gt; Err&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; result&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;      eprintln!&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;&amp;quot;Failed to save game: &lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;  },&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F9E2AF;&quot;&gt; jobs&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;is_running&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;&amp;quot;save_game&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ui&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;text&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;wave|Saving...&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt; |&lt;&#x2F;span&gt;&lt;span&gt;t&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt; t&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;color&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FAB387;&quot;&gt;0xAAAAAA&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;));&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You spawn a job. It runs in the background. When it finishes, the completion callback runs on the main layout thread automatically. No channels to wire up. No mutexes freezing your UI. Works on all platforms, even wasm.&lt;&#x2F;p&gt;
&lt;p&gt;Paired with the new &lt;code&gt;storage&lt;&#x2F;code&gt; feature for reading and writing files across all platforms, state management feels a lot more natural.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;polishing-ui&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#polishing-ui&quot; aria-label=&quot;Anchor link for: polishing-ui&quot;&gt;🔗&lt;&#x2F;a&gt;Polishing UI&lt;&#x2F;h2&gt;
&lt;p&gt;Creating a UI is easy. Making it feel good is hard. Ply 1.1 introduces a &lt;code&gt;Lerp&lt;&#x2F;code&gt; trait across the engine as well as perceptually smooth color blending.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; c&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F9E2AF;font-style: italic;&quot;&gt; Color&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;from_hex&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FAB387;&quot;&gt;0x1E1E1E&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;lerp_oklab&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F9E2AF;&quot;&gt;Color&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;from_hex&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FAB387;&quot;&gt;0x4CC9F0&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;),&lt;&#x2F;span&gt;&lt;span&gt; t&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Oklab interpolation keeps the perceived brightness consistent, which makes animations look professional.&lt;&#x2F;p&gt;
&lt;p&gt;We also added a complete standard set of easing functions. From &lt;code&gt;ease_out_cubic&lt;&#x2F;code&gt; to &lt;code&gt;ease_in_out_bounce&lt;&#x2F;code&gt;, you no longer need to write your own math functions to make a button press feel snappy.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;responsive-layouts&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#responsive-layouts&quot; aria-label=&quot;Anchor link for: responsive-layouts&quot;&gt;🔗&lt;&#x2F;a&gt;Responsive layouts&lt;&#x2F;h2&gt;
&lt;p&gt;Native layouts often feel rigid compared to the web. Ply&#x27;s layout engine now supports wrapping.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;ui&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;element&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;  .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;layout&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt;l&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt; l&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;wrap&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;wrap_gap&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FAB387;&quot;&gt;8&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;  .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;children&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt;ui&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #9399B2;font-style: italic;&quot;&gt;    &#x2F;&#x2F; Elements automatically flow to the next row&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;  });&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We also added &lt;code&gt;contain&lt;&#x2F;code&gt; and &lt;code&gt;cover&lt;&#x2F;code&gt; aspect ratios, plus weighted &lt;code&gt;grow!&lt;&#x2F;code&gt; sizing. You can now tell an element to take up exactly twice as much remaining space as its sibling using &lt;code&gt;grow!(weight: 2.0)&lt;&#x2F;code&gt;. Building a responsive grid now takes seconds instead of manual math.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-little-things&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-little-things&quot; aria-label=&quot;Anchor link for: the-little-things&quot;&gt;🔗&lt;&#x2F;a&gt;The little things&lt;&#x2F;h2&gt;
&lt;p&gt;There is a lot more in this release. We added setting scroll positions, drag-select for text inputs, a customizable scrollbar. Check out the full &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheRedDeveloper&#x2F;ply-engine&#x2F;releases&quot;&gt;changelog&lt;&#x2F;a&gt; for all the details as well as a migration guide.&lt;&#x2F;p&gt;
&lt;p&gt;You can try the new features right now in the browser on the &lt;a href=&quot;&#x2F;docs&#x2F;getting-started&#x2F;&quot;&gt;interactive docs&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Update your CLI to get started:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;cargo&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt; install plyx&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Go build something smooth.&lt;&#x2F;p&gt;
&lt;p&gt;Feel free to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheRedDeveloper&#x2F;ply-engine&#x2F;discussions&#x2F;new?category=show-and-tell&quot;&gt;present your project&lt;&#x2F;a&gt; or &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheRedDeveloper&#x2F;ply-engine&#x2F;issues&#x2F;new?template=question.md&quot;&gt;ask any questions&lt;&#x2F;a&gt; on &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheRedDeveloper&#x2F;ply-engine&quot;&gt;GitHub&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Building apps in Rust shouldn&#x27;t be this hard, so I made Ply.</title>
          <pubDate>Sun, 01 Mar 2026 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://plyx.iz.rs/blog/introducing-ply/</link>
          <guid>https://plyx.iz.rs/blog/introducing-ply/</guid>
          <description xml:base="https://plyx.iz.rs/blog/introducing-ply/">&lt;p&gt;I wanted to build a game in Rust. A multiplayer board game with a server, a client, and a common crate that holds all the shared game logic. Clean architecture. One language. Full control.&lt;&#x2F;p&gt;
&lt;p&gt;That&#x27;s when I ran into a wall.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;everything-i-tried-fell-short&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#everything-i-tried-fell-short&quot; aria-label=&quot;Anchor link for: everything-i-tried-fell-short&quot;&gt;🔗&lt;&#x2F;a&gt;Everything I tried fell short&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;bevy.org&#x2F;&quot;&gt;Bevy&lt;&#x2F;a&gt; crams you into an ECS that turns simple things into thousands of lines of virtual database queries. Its UI system is macro-and-node-based with &lt;code&gt;impl Bundle&lt;&#x2F;code&gt; and &lt;code&gt;..default()&lt;&#x2F;code&gt; scattered everywhere. Bevy&#x27;s architecture wouldn&#x27;t work with what I had spent weeks building for the server.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;iced.rs&#x2F;&quot;&gt;Iced&lt;&#x2F;a&gt; looked promising until I saw the code. &lt;code&gt;..default()&lt;&#x2F;code&gt; everywhere. &lt;code&gt;.into()&lt;&#x2F;code&gt; on every line. The nesting is unclear and everything reads backwards, where the top element ends up at the bottom of the code.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.egui.rs&#x2F;&quot;&gt;egui&lt;&#x2F;a&gt; was better, but you&#x27;re manually calling &lt;code&gt;.add_space()&lt;&#x2F;code&gt; for gaps and allocating rects. For a simple UI it&#x27;s fine. For a real app, it gets tiring fast.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;slint.dev&#x2F;&quot;&gt;Slint&lt;&#x2F;a&gt; impressed me with its clean nesting, but it&#x27;s a separate markup language. You can&#x27;t cleanly integrate it into Rust or connect it to your existing systems. &lt;code&gt;parent.width&lt;&#x2F;code&gt; references and &lt;code&gt;in property &amp;lt;real&amp;gt;&lt;&#x2F;code&gt; declarations don&#x27;t belong in a Rust codebase.&lt;&#x2F;p&gt;
&lt;p&gt;I also looked at non-Rust options. I&#x27;m an avid Unity developer including VR. I&#x27;ve had experiences with Unigine and opened Unreal once to get confused and irritated. They&#x27;re all too clunky. They give you zero control. Making a server and Godot work together with a shared crate? Not happening. I also had a terrible previous experience with Tauri trying to make a scooter rental app.&lt;&#x2F;p&gt;
&lt;p&gt;Eventually I found &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;macroquad.rs&#x2F;&quot;&gt;macroquad&lt;&#x2F;a&gt;. It said it would run anywhere, and it felt close to what I wanted, inspired by Love2D&#x27;s simplicity. But after a few hours, it was clear: if I kept going like this, I wouldn&#x27;t be done in years. Macroquad is a rendering library, not an app engine. No layout system, no text input, no UI structure at all.&lt;&#x2F;p&gt;
&lt;p&gt;So I needed something on top of it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;clay-and-hitting-the-wall&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#clay-and-hitting-the-wall&quot; aria-label=&quot;Anchor link for: clay-and-hitting-the-wall&quot;&gt;🔗&lt;&#x2F;a&gt;Clay, and hitting the wall&lt;&#x2F;h2&gt;
&lt;p&gt;I&#x27;d heard about &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;nicbarker&#x2F;clay&quot;&gt;Clay&lt;&#x2F;a&gt; from YouTube, a C layout library. I used Rust bindings and paired it with macroquad. I called it Clayquad.&lt;&#x2F;p&gt;
&lt;p&gt;At first, it was great. I could finally build my game at a reasonable speed. Then reality set in.&lt;&#x2F;p&gt;
&lt;p&gt;Bugs appeared everywhere. Use-after-frees. Race conditions in the C bindings. No texture management. I was &lt;code&gt;Box::leak&lt;&#x2F;code&gt;ing images every frame just to satisfy the borrow checker. The documentation was sparse, so everything took forever to figure out.&lt;&#x2F;p&gt;
&lt;p&gt;Then I hit hard limits. I wanted shaders. Impossible. I wanted rotation, one of the three fundamental graphics operations, and Clay couldn&#x27;t do it. Scrolling had to be implemented manually. Text input didn&#x27;t exist (those are only on, what, 99% of interactive applications?). I couldn&#x27;t even imagine cross-platform accessibility support.&lt;&#x2F;p&gt;
&lt;p&gt;I had to build something better.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;porting-rewriting-and-rewriting-again&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#porting-rewriting-and-rewriting-again&quot; aria-label=&quot;Anchor link for: porting-rewriting-and-rewriting-again&quot;&gt;🔗&lt;&#x2F;a&gt;Porting, rewriting, and rewriting again&lt;&#x2F;h2&gt;
&lt;p&gt;I kept building on top of Clayquad. The renderer, a text styling system, vector graphics support. Features kept stacking up through the end of 2025, but the foundation was still C. And the syntax was getting uglier with every feature I added. &lt;code&gt;.end()&lt;&#x2F;code&gt; calls everywhere, deep indentation for every nested element, declarations that were painful to read.&lt;&#x2F;p&gt;
&lt;p&gt;I started analyzing every UI framework I could find: Iced, egui, Slint, Bevy, HTML&#x2F;CSS, Qt&#x2F;QML. Studying what each one got right and wrong. I knew what the API should look like before I touched any code.&lt;&#x2F;p&gt;
&lt;p&gt;In February I focused on this project. I ported the layout engine to 100% Rust, stayed up until five in the morning getting it working. The next day I implemented the new API I&#x27;d been designing. Then came shaders, accessibility, the cli, networking... and this website.&lt;&#x2F;p&gt;
&lt;p&gt;I settled on &lt;strong&gt;builder pattern + closures&lt;&#x2F;strong&gt;. Closures cure the &lt;code&gt;.end()&lt;&#x2F;code&gt; problem. Builder methods are cleaner than specifying every property with &lt;code&gt;..Default::default()&lt;&#x2F;code&gt;. You can chain &lt;code&gt;.shader()&lt;&#x2F;code&gt; calls, choose &lt;code&gt;.degrees()&lt;&#x2F;code&gt; or &lt;code&gt;.radians()&lt;&#x2F;code&gt;, and everything stays readable.&lt;&#x2F;p&gt;
&lt;p&gt;One &lt;code&gt;use ply_engine::prelude::*&lt;&#x2F;code&gt; gives you everything. We use &lt;code&gt;Into&amp;lt;T&amp;gt;&lt;&#x2F;code&gt; everywhere. When &lt;code&gt;.background_color()&lt;&#x2F;code&gt; accepts &lt;code&gt;Into&amp;lt;Color&amp;gt;&lt;&#x2F;code&gt;, it takes hex integers, float tuples, or macroquad colors. When &lt;code&gt;.image()&lt;&#x2F;code&gt; accepts &lt;code&gt;Into&amp;lt;ImageSource&amp;gt;&lt;&#x2F;code&gt;, it takes file paths, embedded bytes, textures, or vector graphics. No &lt;code&gt;hex_to_macroquad_color!()&lt;&#x2F;code&gt; wrappers.&lt;&#x2F;p&gt;
&lt;p&gt;Every second you don&#x27;t spend looking up how to construct a &lt;code&gt;FloatingElementBuilder&lt;&#x2F;code&gt; is a second saved.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-philosophy&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-philosophy&quot; aria-label=&quot;Anchor link for: the-philosophy&quot;&gt;🔗&lt;&#x2F;a&gt;The philosophy&lt;&#x2F;h2&gt;
&lt;p&gt;The core principle behind every decision in Ply: &lt;strong&gt;make it easier while giving you full control.&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Why immediate-mode, rebuilding the UI every frame? Because it&#x27;s actually faster than tracking mutations. No matter how complicated your UI is, the layout takes a fraction of a percent of total frame time, most goes to libnvidia or the GPU. You have to redraw every frame anyway. Love2D already proved this works. Immediate-mode gives you complete control over what gets rendered and when.&lt;&#x2F;p&gt;
&lt;p&gt;Why a single prelude? Because no developer wants to manage imports. One import standardizes what you can do and eliminates useless boilerplate.&lt;&#x2F;p&gt;
&lt;p&gt;Why managers (&lt;code&gt;TEXTURE_MANAGER&lt;&#x2F;code&gt;, &lt;code&gt;MATERIAL_MANAGER&lt;&#x2F;code&gt;, &lt;code&gt;FONT_MANAGER&lt;&#x2F;code&gt;, &lt;code&gt;NET_MANAGER&lt;&#x2F;code&gt;)? Because everything runs in a loop, and there are few good ways to persist state between iterations. Back in Clayquad, you had three options for images: always loaded, loaded every frame, or build your own caching system. Ply&#x27;s managers handle all of that in the background. Tell the engine where your image is, it handles caching, eviction, and lifetime. The same pattern applies to materials, fonts, and network requests. All simplifying memory across frames so you never think about it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-1-0-looks-like&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#what-1-0-looks-like&quot; aria-label=&quot;Anchor link for: what-1-0-looks-like&quot;&gt;🔗&lt;&#x2F;a&gt;What 1.0 looks like&lt;&#x2F;h2&gt;
&lt;p&gt;Ply 1.0 ships with everything I wished existed when I started:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Layout engine&lt;&#x2F;strong&gt; with flexbox-like sizing, padding, gaps, alignment, scrolling, and floating elements&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Full text input&lt;&#x2F;strong&gt;: cursor, selection, undo&#x2F;redo, multiline, password mode, all keyboard shortcuts&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Rich text styling&lt;&#x2F;strong&gt;: inline colors, wave, pulse, gradient, typewriter, shadow, per character&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;GLSL shaders&lt;&#x2F;strong&gt; on any element, with built-in effects and a SPIR-V build pipeline&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Accessibility&lt;&#x2F;strong&gt; via AccessKit on desktop, JavaScript bridge on web&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Debug view&lt;&#x2F;strong&gt;: a Chrome DevTools-style inspector. No other Rust UI library has this&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;HTTP + WebSocket&lt;&#x2F;strong&gt; networking that never blocks the UI&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;TinyVG vector graphics&lt;&#x2F;strong&gt; with on-demand rasterization&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Rotation&lt;&#x2F;strong&gt;: both visual and shape-level&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Sound&lt;&#x2F;strong&gt; playback&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Cross-platform&lt;&#x2F;strong&gt;: Linux, macOS, Windows, Android, iOS, and web, all from one codebase&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;interactive-docs&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#interactive-docs&quot; aria-label=&quot;Anchor link for: interactive-docs&quot;&gt;🔗&lt;&#x2F;a&gt;Interactive docs&lt;&#x2F;h2&gt;
&lt;p&gt;Any engine is only as good as its documentation. An engine might have great features, but if it takes you two hours to figure them out, those features are just distractions.&lt;&#x2F;p&gt;
&lt;p&gt;Nobody should need to read as much source code as I did to build something. Nobody should need to make as many pull requests as I did. Everything should be easy to use.&lt;&#x2F;p&gt;
&lt;p&gt;So I built an &lt;a href=&quot;&#x2F;docs&#x2F;getting-started&#x2F;&quot;&gt;interactive documentation&lt;&#x2F;a&gt;. Live code playgrounds where you can tweak values and see the result instantly. Every concept has an interactive example. The docs teach by doing, not by lecturing.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;try-it&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#try-it&quot; aria-label=&quot;Anchor link for: try-it&quot;&gt;🔗&lt;&#x2F;a&gt;Try it&lt;&#x2F;h2&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;cargo&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt; install plyx&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;plyx&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt; init&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Two commands to get an app with a font from Google Fonts, feature flags, and a project structure.&lt;&#x2F;p&gt;
&lt;p&gt;Check out the &lt;a href=&quot;&#x2F;examples&#x2F;&quot;&gt;examples&lt;&#x2F;a&gt;, there&#x27;s a shader playground, a snake game, and a todo app. &lt;a href=&quot;&#x2F;&quot;&gt;On the home page&lt;&#x2F;a&gt; you&#x27;ll also find an interpreter so you can try some of ply&#x27;s syntax live. Everything runs in the browser.&lt;&#x2F;p&gt;
&lt;p&gt;Explore the &lt;a href=&quot;&#x2F;docs&#x2F;getting-started&#x2F;&quot;&gt;interactive docs&lt;&#x2F;a&gt;, they&#x27;ll show you interactive examples where you can tinker with the code right in the browser. The source is on &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheRedDeveloper&#x2F;ply-engine&quot;&gt;GitHub&lt;&#x2F;a&gt;, licensed under &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;opensource.org&#x2F;license&#x2F;0bsd&quot;&gt;Zero-Clause BSD&lt;&#x2F;a&gt;. Use it for anything, no attribution required.&lt;&#x2F;p&gt;
&lt;p&gt;Go build something.&lt;&#x2F;p&gt;
</description>
      </item>
    </channel>
</rss>
