<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: ken109</title>
    <description>The latest articles on DEV Community by ken109 (@ken109).</description>
    <link>https://dev.to/ken109</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F620702%2F08b04ba7-6c78-4016-91b7-a5880b86f8e2.png</url>
      <title>DEV Community: ken109</title>
      <link>https://dev.to/ken109</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ken109"/>
    <language>en</language>
    <item>
      <title>I Built a Live Wallpaper Engine for macOS — Here's How It Works</title>
      <dc:creator>ken109</dc:creator>
      <pubDate>Tue, 07 Apr 2026 15:00:00 +0000</pubDate>
      <link>https://dev.to/ken109/i-built-a-live-wallpaper-engine-for-macos-heres-how-it-works-5ed</link>
      <guid>https://dev.to/ken109/i-built-a-live-wallpaper-engine-for-macos-heres-how-it-works-5ed</guid>
      <description>&lt;p&gt;Your desktop wallpaper is a static image. It has been since the day you set it up. Mine was too.&lt;/p&gt;

&lt;p&gt;Then I thought: &lt;strong&gt;what if I could write a React component and have it run as my actual desktop wallpaper?&lt;/strong&gt; An audio visualizer that reacts to music. A system monitor showing real-time CPU usage. All built with the same tools I use every day.&lt;/p&gt;

&lt;p&gt;So I built it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Futoejwvpa9imf8n9dqe9.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Futoejwvpa9imf8n9dqe9.gif" alt="Audio Visualizer wallpaper running on macOS desktop" width="640" height="416"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Meet &lt;a href="https://fluxlay.com" rel="noopener noreferrer"&gt;&lt;strong&gt;Fluxlay&lt;/strong&gt;&lt;/a&gt; — a live wallpaper platform for macOS. Write a React component, and it becomes your desktop wallpaper. I built the desktop app, CLI, SDK, and a gallery (marketplace) for sharing wallpapers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Show me the code
&lt;/h2&gt;

&lt;p&gt;Here's an audio visualizer wallpaper. The entire thing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useAudio&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@fluxlay/react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;AudioVisualizer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;spectrum&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useAudio&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"visualizer"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;spectrum&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;
          &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"bar"&lt;/span&gt;
          &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;%`&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. This reacts to whatever music is playing on your Mac. In real time.&lt;/p&gt;

&lt;h2&gt;
  
  
  The SDK hooks
&lt;/h2&gt;

&lt;p&gt;The React SDK gives you access to desktop-level data through hooks:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Hook&lt;/th&gt;
&lt;th&gt;What it does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;useAudio()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;32-band frequency spectrum, RMS, peak&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;useSystemMonitor()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;CPU, memory, battery, network — live&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;useMousePosition()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Global cursor position&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;useMediaMetadata()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Current track, artist, album art&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;useShell()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Run declared shell commands&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;useTerminal()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Embed a terminal in your wallpaper&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Yes, you can put a terminal in your wallpaper. No, I don't know why you'd want to. But you can.&lt;/p&gt;

&lt;h2&gt;
  
  
  The CLI
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Dev server with hot reload&lt;/span&gt;
fluxlay dev ./my-wallpaper

&lt;span class="c"&gt;# Build and publish to the gallery&lt;/span&gt;
fluxlay build ./my-wallpaper
fluxlay publish ./my-wallpaper
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;fluxlay dev&lt;/code&gt; gives you hot reload straight to your desktop. Change a line of CSS, and your wallpaper updates instantly. The DX is genuinely fun.&lt;/p&gt;

&lt;h2&gt;
  
  
  Architecture
&lt;/h2&gt;

&lt;p&gt;Two layers. &lt;strong&gt;Rust handles the OS-level stuff — audio capture, system monitoring, window management. React handles the pixels.&lt;/strong&gt; They talk over HTTP + NDJSON streams.&lt;/p&gt;

&lt;p&gt;The Tauri 2 backend runs an embedded Axum server with streaming endpoints for audio FFT data, system metrics, mouse position, and media metadata. The React SDK subscribes to these streams via hooks. Clean separation. It works surprisingly well.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Tauri, not Electron
&lt;/h2&gt;

&lt;p&gt;A wallpaper runs 24/7 in the background. This is not a normal desktop app. Resource consumption is everything.&lt;/p&gt;

&lt;p&gt;Electron? 200MB+ binary. Noticeable memory footprint. For a wallpaper, that's a non-starter.&lt;/p&gt;

&lt;p&gt;Tauri 2 won because:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tiny footprint&lt;/strong&gt; — binary size and memory usage are in a completely different league&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rust&lt;/strong&gt; — audio FFT and system monitoring need to be fast and safe. Rust delivers both&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Direct access to macOS native APIs&lt;/strong&gt; — ScreenCaptureKit, CoreGraphics, CoreAudio&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Rendering a wallpaper behind desktop icons
&lt;/h2&gt;

&lt;p&gt;This was the hardest part. macOS doesn't just let you put a window behind the desktop icons. That's not how the window system works.&lt;/p&gt;

&lt;p&gt;I'm using &lt;code&gt;tauri-plugin-desktop-underlay&lt;/code&gt; to place the Tauri window at the desktop layer. It renders fullscreen, behind everything, acting as the wallpaper.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real-time streaming with NDJSON
&lt;/h2&gt;

&lt;p&gt;The SDK talks to the Tauri backend over &lt;strong&gt;HTTP + NDJSON (newline-delimited JSON) streams&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;React (useAudio) → HTTP GET /v1/audio-stream
                 ← { "spectrum": [...], "rms": 0.42, "peak": 0.87 }\n
                 ← { "spectrum": [...], "rms": 0.38, "peak": 0.91 }\n
                 ← ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I considered WebSocket, but NDJSON plays nicer with Tauri's built-in Axum server. Plus, you can debug it with &lt;code&gt;curl&lt;/code&gt;. That sold me.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real-time FFT in Rust
&lt;/h2&gt;

&lt;p&gt;Making wallpapers react to music means real-time audio analysis. Here's what happens on the Rust side:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Capture system audio output via macOS APIs&lt;/li&gt;
&lt;li&gt;FFT with &lt;strong&gt;rustfft&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Resample to &lt;strong&gt;32 logarithmic bands&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Calculate RMS and peak values&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The logarithmic scale matters. Human hearing is more sensitive to low frequencies. Linear scaling makes the visualizer look flat and boring. This single adjustment made the audio visualizer go from "meh" to "whoa."&lt;/p&gt;

&lt;h2&gt;
  
  
  The stack
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;Tech&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Desktop app&lt;/td&gt;
&lt;td&gt;Tauri 2 + Rust&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Wallpaper UI&lt;/td&gt;
&lt;td&gt;React 19&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SDK&lt;/td&gt;
&lt;td&gt;@fluxlay/react (hooks-based)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CLI&lt;/td&gt;
&lt;td&gt;Node.js&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Native module&lt;/td&gt;
&lt;td&gt;Rust + NAPI-RS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Website&lt;/td&gt;
&lt;td&gt;TanStack Start + Cloudflare Workers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;API&lt;/td&gt;
&lt;td&gt;Go + ConnectRPC&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;Honestly, there's a lot left to do:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Performance optimization&lt;/strong&gt; — a wallpaper runs constantly, so every percent of CPU matters. Heavy animations on multiple monitors still need work&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Windows support&lt;/strong&gt; — currently macOS only. Desktop layer APIs are completely different on Windows, so this is the biggest challenge&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SDK expansion&lt;/strong&gt; — Unity WebGL builds as wallpapers, more data sources&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Right now the gallery only has my own wallpapers — six of them. &lt;strong&gt;I'd love to see what other people build.&lt;/strong&gt; The SDK is open, the CLI handles publishing, and the gallery is ready for new creators.&lt;/p&gt;

&lt;h2&gt;
  
  
  Get started in 3 minutes
&lt;/h2&gt;

&lt;p&gt;"React for wallpapers" sounds niche. It is. But there's something deeply satisfying about passing &lt;code&gt;useAudio().spectrum&lt;/code&gt; into a &lt;code&gt;div&lt;/code&gt;'s &lt;code&gt;height&lt;/code&gt; and watching your desktop come alive.&lt;/p&gt;

&lt;p&gt;Here's how to try it:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Download the app&lt;/strong&gt; → &lt;a href="https://fluxlay.com" rel="noopener noreferrer"&gt;fluxlay.com&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Install the CLI&lt;/strong&gt; → &lt;code&gt;npm install -g @fluxlay/cli&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scaffold &amp;amp; run&lt;/strong&gt; → &lt;code&gt;fluxlay dev ./my-wallpaper&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That's it. You're editing a React app that renders directly on your desktop. The &lt;a href="https://fluxlay.com/docs/creator" rel="noopener noreferrer"&gt;docs&lt;/a&gt; walk you through the SDK hooks, publishing, and everything else.&lt;/p&gt;

&lt;p&gt;If you build something cool, I'd genuinely love to see it. Drop a link in the comments or publish it to the gallery.&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://fluxlay.com" rel="noopener noreferrer"&gt;fluxlay.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>react</category>
      <category>rust</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
