<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>SeaBear Studios — Ideas</title>
  <subtitle>SeaBear Studios — iOS/macOS development, web applications, technology security, and GenAI consulting.</subtitle>
  <link href="https://seabear.dev/feed.xml" rel="self"/>
  <link href="https://seabear.dev/"/>
  <updated>2026-05-19T00:00:00.000Z</updated>
  <id>https://seabear.dev/</id>
  <author>
    <name>SeaBear Studios</name>
    <email>hello@seabear.dev</email>
  </author>
  <entry>
    <title>The half-frame that became PersistentBackgroundNavigation</title>
    <link href="https://seabear.dev/ideas/seabearkit-persistent-background-navigation/"/>
    <id>https://seabear.dev/ideas/seabearkit-persistent-background-navigation/</id>
    <published>2026-05-19T00:00:00.000Z</published>
    <updated>2026-05-19T00:00:00.000Z</updated>
    <summary>A flicker I couldn&#39;t unsee in Tesserae&#39;s navigation, weeks of dead-end forum threads, and the structural fix that became SeaBearKit&#39;s first utility.</summary>
    <content type="html"><![CDATA[<p>There was a flicker in Tesserae I couldn't stop seeing. The root view had a color gradient with animated nodes drifting across the screen, slow and atmospheric. Every time I pushed a new view onto the NavigationStack, the gradient pulsed. Not for long. A single wrong-color half-frame as the transition logic recomputed the destination's chrome.</p>
<p>The user doesn't have words for it. They feel it.</p>
<p>I spent weeks chasing it. Every forum thread I found assumed the background was a property of the view, something you set with <code>.background(...)</code> and then chase around with modifiers when it misbehaves. I tried the modifier stack. I tried setting the background on the NavigationStack itself. I tried <code>.toolbarBackground(.hidden)</code>. I tried <code>Color.clear</code> on every layer I could find. Each attempt moved the artifact somewhere else without removing it.</p>
<p>The breakthrough was changing the question. The background wasn't supposed to be inside the thing that's transitioning. The background is the room. The views are the furniture being rearranged. You don't repaint the walls when you move a chair.</p>
<p>Structurally, that meant pulling the background out of the navigation hierarchy entirely. The app gets a <code>ZStack</code> at the root, the background sits as one sibling, the <code>NavigationStack</code> sits as the other. Then <code>.containerBackground(for: .navigation) { Color.clear }</code> tells the navigation chrome to stop drawing its own surface on top. The background never participates in a transition because it never tears down. Push, pop, present, dismiss; the nodes keep drifting.</p>
<p>I called it PersistentBackgroundNavigation. It worked the moment I wired it into Tesserae.</p>
<p>Two things from this are worth recording.</p>
<p>The first is that Apple's SwiftUI conventions encode an assumption that views own their visual surface. That assumption is right most of the time, and it's why nobody writes a tutorial on hoisting the background out of the hierarchy. It's also why the workaround took weeks to find: the convention is loud and the structural alternative is quiet.</p>
<p>The second is that the fix didn't feel like mine. It felt like something other people would also want. I had reached for it because Tesserae has a particular contemplative mood that breaks if anything chrome-related flinches between screens. But a quiet animated background under a navigation stack is a recurring idea, not a personal one. So I lifted the relevant files into a SwiftUI package, wrote a one-liner API for it, and shipped it. That package is SeaBearKit, and PersistentBackgroundNavigation is still the first utility in the README.</p>
<p>Some of the best small libraries come out of refusing to live with an artifact nobody else is bothered by.</p>
]]></content>
  </entry>
  <entry>
    <title>Dot notation came from jq, not design</title>
    <link href="https://seabear.dev/ideas/reverie-dot-notation/"/>
    <id>https://seabear.dev/ideas/reverie-dot-notation/</id>
    <published>2026-05-18T00:00:00.000Z</published>
    <updated>2026-05-18T00:00:00.000Z</updated>
    <summary>Reverie uses dot notation because the original CodexCLI was bash + jq, and jq&#39;s path syntax is dots. The interface accreted from the implementation.</summary>
    <content type="html"><![CDATA[<p>The original CodexCLI was a bash script that read and wrote keys in a single JSON file. To do that, it needed <a href="https://jqlang.github.io/jq/"><code>jq</code></a>. And jq's native path syntax for accessing nested data is dot notation: <code>.server.production.ip</code>.</p>
<p>So when a user typed <code>ccli set server.production.ip 192.168.1.100</code>, the script split the key on dots and built a jq expression. The dot notation was the cheapest possible adapter between user input and jq syntax. I could have used slashes or colons or any other separator, but I would have just translated them to dots inside the script. Skip the translation.</p>
<p>Now it's a CLI + MCP server in TypeScript with file-per-entry storage, and the dot notation stays. Partly muscle memory. Partly because every key in every store I've populated since then uses it. Partly because, looking back, it was the right answer all along, just for a different reason than the one I had.</p>
]]></content>
  </entry>
</feed>
