<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <updated>2026-07-11T19:36:26Z</updated>
  <generator>https://nostr.ae</generator>

  <title>Nostr notes by </title>
  <author>
    <name></name>
  </author>
  <link rel="self" type="application/atom+xml" href="https://nostr.ae/npub1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzqujme.rss" />
  <link href="https://nostr.ae/npub1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzqujme" />
  <id>https://nostr.ae/npub1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzqujme</id>
  <icon></icon>
  <logo></logo>


  <title>Nostr notes on gitnostr.com/web&#43;nostr:gitnostr.com/quartz-onyx</title>
  <link href="https://nostr.ae/r/gitnostr.com/web&#43;nostr:gitnostr.com/quartz-onyx" />
  <link rel="self" type="application/atom+xml" href="https://nostr.ae/r/gitnostr.com/web&#43;nostr:gitnostr.com/quartz-onyx.rss" />
  <id>https://nostr.ae/r/gitnostr.com/web&#43;nostr:gitnostr.com/quartz-onyx</id>
  <icon>https://gitnostr.com/icon.png</icon>
  <logo>https://gitnostr.com/icon.png</logo>



  <entry>
    <id>https://nostr.ae/nevent1qqstflzy48c6pwyxha4me35cjj5qdnp39n6pgk3tc9yjtqxvej08wfcpx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzyrmj3k0xuuzgxk88pyc0tjnykzthwrvcnnxcdp20ucvwm2wg5wqsvku73l5</id>
    
      <title type="html">You can watch the Bitcoin Spam War live in realtime at ...</title>
    
    <link rel="alternate" href="https://nostr.ae/nevent1qqstflzy48c6pwyxha4me35cjj5qdnp39n6pgk3tc9yjtqxvej08wfcpx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzyrmj3k0xuuzgxk88pyc0tjnykzthwrvcnnxcdp20ucvwm2wg5wqsvku73l5" />
    <content type="html">
      You can watch the Bitcoin Spam War live in realtime at &lt;a href=&#34;https://bitcoin-spam-war.vercel.app/&#34;&gt;https://bitcoin-spam-war.vercel.app/&lt;/a&gt;
    </content>
    <updated>2026-07-11T19:36:26Z</updated>
  </entry>

  <entry>
    <id>https://nostr.ae/nevent1qqs9w3m5cjdkysewkmyp0pw9thcj5dtfnr9lal23m3p8fm4mnt7dzvqpx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzyz4ya5lqutyqu54hdcjnd0hhny9rlytqgndmfkgktwem65u4k439xl9lcv6</id>
    
      <title type="html">Oh no scary hacker man is gonna make a meme</title>
    
    <link rel="alternate" href="https://nostr.ae/nevent1qqs9w3m5cjdkysewkmyp0pw9thcj5dtfnr9lal23m3p8fm4mnt7dzvqpx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzyz4ya5lqutyqu54hdcjnd0hhny9rlytqgndmfkgktwem65u4k439xl9lcv6" />
    <content type="html">
      In reply to &lt;a href=&#39;/nevent1qqsrmjal8dvct4c6kxezuuynhrlgp2t7vqgzegjq5qcy2tq4tqngzxqnt8g9w&#39;&gt;nevent1q…8g9w&lt;/a&gt;&lt;br/&gt;_________________________&lt;br/&gt;&lt;br/&gt;Oh no scary hacker man is gonna make a meme  &lt;br/&gt;&lt;br/&gt;
    </content>
    <updated>2026-07-05T17:24:11Z</updated>
  </entry>

  <entry>
    <id>https://nostr.ae/nevent1qqsxy0a8j25dej2n33unt9ypnumhew24v7vvtzwwup7vwrkld8ndfzcpx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzyqalp33lewf5vdq847t6te0wvnags0gs0mu72kz8938tn24wlfze6z7j4d5</id>
    
      <title type="html">If you ever wanted to run a big server that indexes Nostr users ...</title>
    
    <link rel="alternate" href="https://nostr.ae/nevent1qqsxy0a8j25dej2n33unt9ypnumhew24v7vvtzwwup7vwrkld8ndfzcpx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzyqalp33lewf5vdq847t6te0wvnags0gs0mu72kz8938tn24wlfze6z7j4d5" />
    <content type="html">
      If you ever wanted to run a big server that indexes Nostr users filtering out bots and throwaway accounts, serves their kind:0 metadata via a normal relay interface, allow them to be searched via NIP-50, you could try this: &lt;blockquote class=&#34;border-l-05rem border-l-strongpink border-solid&#34;&gt;&lt;div class=&#34;-ml-4 bg-gradient-to-r from-gray-100 dark:from-zinc-800 to-transparent mr-0 mt-0 mb-4 pl-4 pr-2 py-2&#34;&gt;quoting &lt;br/&gt;&lt;span itemprop=&#34;mentions&#34; itemscope itemtype=&#34;https://schema.org/Article&#34;&gt;&lt;a itemprop=&#34;url&#34; href=&#34;/naddr1qqykummnw3e8v6t9wupzqwlsccluhy6xxsr6l9a9uhhxf75g85g8a709tprjcn4e42h053vaqvzqqqrhny8e9429&#34; class=&#34;bg-lavender dark:prose:text-neutral-50 dark:text-neutral-50 dark:bg-garnet px-1&#34;&gt;naddr1qq…9429&lt;/a&gt;&lt;/span&gt; &lt;/div&gt;  &lt;/blockquote&gt;
    </content>
    <updated>2026-07-04T15:51:00Z</updated>
  </entry>

  <entry>
    <id>https://nostr.ae/nevent1qqsqa2cfq6l3xc5n8wx5ypz0yfxqmd0t8ufhdvyk6lyqylc7dnfll5gpx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzypp3shk7edn43y5zfvdr0ftl8eq8l00zaknjqx3c9xuv7ja8ck60qahxz6s</id>
    
      <title type="html">## Local CI-parity run vs current upstream main Verified this PR ...</title>
    
    <link rel="alternate" href="https://nostr.ae/nevent1qqsqa2cfq6l3xc5n8wx5ypz0yfxqmd0t8ufhdvyk6lyqylc7dnfll5gpx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzypp3shk7edn43y5zfvdr0ftl8eq8l00zaknjqx3c9xuv7ja8ck60qahxz6s" />
    <content type="html">
      In reply to &lt;a href=&#39;/nevent1qqs0gdd2ztscv7klylh7pphnstjmn0qnzyjl7npgq0hsc4dt4t9m4ccpz3mhxue69uhhyetvv9ujumn8d96zuer9wck3wc8h&#39;&gt;nevent1q…wc8h&lt;/a&gt;&lt;br/&gt;_________________________&lt;br/&gt;&lt;br/&gt;## Local CI-parity run vs current upstream main&lt;br/&gt;&lt;br/&gt;Verified this PR against `vitorpamplona/amethyst` master tip `74446e39cd` (current as of 2026-06-26 ~10:25 GMT&#43;10).&lt;br/&gt;&lt;br/&gt;### Rebase&lt;br/&gt;&lt;br/&gt;- Fetched PR tip `7ad166b5` from `refs/nostr/f435aa12…` on the maintainer&amp;#39;s relay.ngit.dev mirror&lt;br/&gt;- Rebased onto `upstream/main` (74446e39cd, &#43;666 commits since this PR&amp;#39;s `merge-base` 6cc62f13)&lt;br/&gt;- **Result: clean rebase, zero conflicts**&lt;br/&gt;- Rebased tip: `c421cd0043f2a93f512d9f07bf937a33a935d7d4`&lt;br/&gt;- Diff vs main: 14 files, &#43;1,483 / −14 — same shape as the published PR&lt;br/&gt;&lt;br/&gt;### CI-equivalent gradle runs&lt;br/&gt;&lt;br/&gt;Mirrored `.github/workflows/build.yml`:&lt;br/&gt;&lt;br/&gt;| CI job | Tasks | Result |&lt;br/&gt;|---|---|---|&lt;br/&gt;| `lint` | `spotlessCheck :quartz:verifyKmpPurity :commons:verifyKmpPurity` | ✅ PASS (48s) |&lt;br/&gt;| `build-desktop` (test slice) | `:quartz:jvmTest :commons:jvmTest :nestsClient:jvmTest :cli:test :desktopApp:test` | ✅ PASS (~3 min) |&lt;br/&gt;| `test-and-build-android` (test slice) | `:amethyst:testPlayDebugUnitTest :amethyst:testFdroidDebugUnitTest` | ✅ PASS, TZ=UTC (~2 min) |&lt;br/&gt;| `test-and-build-android` (lint slice) | `:amethyst:lintFdroidBenchmark :amethyst:lintPlayBenchmark -PdisableAbiSplits=true` | ✅ PASS (4m 2s), zero errors |&lt;br/&gt;&lt;br/&gt;### Test totals&lt;br/&gt;&lt;br/&gt;5,269 tests across `commons:jvmTest` (949), `quartz:jvmTest` (2,558), `amethyst:testPlayDebugUnitTest` (752), `amethyst:testFdroidDebugUnitTest` (725), `desktopApp:test` (285).&lt;br/&gt;&lt;br/&gt;**0 failures · 0 errors · 18 skipped (all pre-existing).**&lt;br/&gt;&lt;br/&gt;PR-specific new tests:&lt;br/&gt;&lt;br/&gt;- `MockNamecoinHistoryProviderTest`: 17/17 ✅&lt;br/&gt;- `NamecoinSettingsTest`: 26/26 ✅&lt;br/&gt;- `NamecoinResolutionRowTest`: 21/21 ✅&lt;br/&gt;&lt;br/&gt;### Lint&lt;br/&gt;&lt;br/&gt;Zero lint errors. One new style warning surfaced — `NamecoinSettingsSection.kt:118`, `ModifierParameter`: `modifier: Modifier = Modifier` should be the first optional parameter. Same severity as ~50 other warnings already in the codebase. Easy follow-up, not a blocker.&lt;br/&gt;&lt;br/&gt;### Caveats&lt;br/&gt;&lt;br/&gt;- `:quartz:iosSimulatorArm64Test` and `:amethyst:assembleBenchmark` skipped (PR doesn&amp;#39;t touch iOS-consumed commonMain; `verifyKmpPurity` already gates JVM-only leaks; benchmark APK packaging is artifact-only).&lt;br/&gt;- The PR was test-rebased and run locally; the published kind:1618 event itself still points at the original tip `7ad166b5` on top of `6cc62f13`. The rebased branch is ready to push when merge is opened on the GitHub side.&lt;br/&gt;- `CalendarFeedGroupingTest.groupByDayKey_multipleEventsSameDay_collectIntoOneBucket` is timezone-flaky on non-UTC hosts (uses literal Unix timestamps that cross local midnight on `Australia/Sydney`). Reproduces on bare `upstream/main` — unrelated to this PR. Passes under `TZ=UTC` matching CI runner.&lt;br/&gt;&lt;br/&gt;### Summary&lt;br/&gt;&lt;br/&gt;**Merge-safe against current `main`. Zero conflicts, zero test regressions, zero lint errors.**
    </content>
    <updated>2026-06-26T00:44:52Z</updated>
  </entry>

  <entry>
    <id>https://nostr.ae/nevent1qqs02lr9evzgkhe60lwehzu7zywvzc6geu8fwtv9d0pf2gtthzra5scpx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzypp3shk7edn43y5zfvdr0ftl8eq8l00zaknjqx3c9xuv7ja8ck60q4se5ju</id>
    
      <title type="html">## Local CI-parity run vs current upstream main Verified this PR ...</title>
    
    <link rel="alternate" href="https://nostr.ae/nevent1qqs02lr9evzgkhe60lwehzu7zywvzc6geu8fwtv9d0pf2gtthzra5scpx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzypp3shk7edn43y5zfvdr0ftl8eq8l00zaknjqx3c9xuv7ja8ck60q4se5ju" />
    <content type="html">
      In reply to &lt;a href=&#39;/nevent1qqs0gdd2ztscv7klylh7pphnstjmn0qnzyjl7npgq0hsc4dt4t9m4ccpz3mhxue69uhhyetvv9ujumn8d96zuer9wck3wc8h&#39;&gt;nevent1q…wc8h&lt;/a&gt;&lt;br/&gt;_________________________&lt;br/&gt;&lt;br/&gt;## Local CI-parity run vs current upstream main&lt;br/&gt;&lt;br/&gt;Verified this PR against `vitorpamplona/amethyst` master tip `74446e39cd` (current as of 2026-06-26 ~10:25 GMT&#43;10).&lt;br/&gt;&lt;br/&gt;### Rebase&lt;br/&gt;&lt;br/&gt;- Fetched PR tip `7ad166b5` from `refs/nostr/f435aa12…` on the maintainer&amp;#39;s relay.ngit.dev mirror&lt;br/&gt;- Rebased onto `upstream/main` (74446e39cd, &#43;666 commits since this PR&amp;#39;s `merge-base` 6cc62f13)&lt;br/&gt;- **Result: clean rebase, zero conflicts**&lt;br/&gt;- Rebased tip: `c421cd0043f2a93f512d9f07bf937a33a935d7d4`&lt;br/&gt;- Diff vs main: 14 files, &#43;1,483 / −14 — same shape as the published PR&lt;br/&gt;&lt;br/&gt;### CI-equivalent gradle runs&lt;br/&gt;&lt;br/&gt;Mirrored `.github/workflows/build.yml`:&lt;br/&gt;&lt;br/&gt;| CI job | Tasks | Result |&lt;br/&gt;|---|---|---|&lt;br/&gt;| `lint` | `spotlessCheck :quartz:verifyKmpPurity :commons:verifyKmpPurity` | ✅ PASS (48s) |&lt;br/&gt;| `build-desktop` (test slice) | `:quartz:jvmTest :commons:jvmTest :nestsClient:jvmTest :cli:test :desktopApp:test` | ✅ PASS (~3 min) |&lt;br/&gt;| `test-and-build-android` (test slice) | `:amethyst:testPlayDebugUnitTest :amethyst:testFdroidDebugUnitTest` | ✅ PASS, TZ=UTC (~2 min) |&lt;br/&gt;| `test-and-build-android` (lint slice) | `:amethyst:lintFdroidBenchmark :amethyst:lintPlayBenchmark -PdisableAbiSplits=true` | ✅ PASS (4m 2s), zero errors |&lt;br/&gt;&lt;br/&gt;### Test totals&lt;br/&gt;&lt;br/&gt;5,269 tests across `commons:jvmTest` (949), `quartz:jvmTest` (2,558), `amethyst:testPlayDebugUnitTest` (752), `amethyst:testFdroidDebugUnitTest` (725), `desktopApp:test` (285).&lt;br/&gt;&lt;br/&gt;**0 failures · 0 errors · 18 skipped (all pre-existing).**&lt;br/&gt;&lt;br/&gt;PR-specific new tests:&lt;br/&gt;&lt;br/&gt;- `MockNamecoinHistoryProviderTest`: 17/17 ✅&lt;br/&gt;- `NamecoinSettingsTest`: 26/26 ✅&lt;br/&gt;- `NamecoinResolutionRowTest`: 21/21 ✅&lt;br/&gt;&lt;br/&gt;### Lint&lt;br/&gt;&lt;br/&gt;Zero lint errors. One new style warning surfaced — `NamecoinSettingsSection.kt:118`, `ModifierParameter`: `modifier: Modifier = Modifier` should be the first optional parameter. Same severity as ~50 other warnings already in the codebase. Easy follow-up, not a blocker.&lt;br/&gt;&lt;br/&gt;### Caveats&lt;br/&gt;&lt;br/&gt;- `:quartz:iosSimulatorArm64Test` and `:amethyst:assembleBenchmark` skipped (PR doesn&amp;#39;t touch iOS-consumed commonMain; `verifyKmpPurity` already gates JVM-only leaks; benchmark APK packaging is artifact-only).&lt;br/&gt;- The PR was test-rebased and run locally; the published kind:1618 event itself still points at the original tip `7ad166b5` on top of `6cc62f13`. The rebased branch is ready to push when merge is opened on the GitHub side.&lt;br/&gt;- `CalendarFeedGroupingTest.groupByDayKey_multipleEventsSameDay_collectIntoOneBucket` is timezone-flaky on non-UTC hosts (uses literal Unix timestamps that cross local midnight on `Australia/Sydney`). Reproduces on bare `upstream/main` — unrelated to this PR. Passes under `TZ=UTC` matching CI runner.&lt;br/&gt;&lt;br/&gt;### Summary&lt;br/&gt;&lt;br/&gt;**Merge-safe against current `main`. Zero conflicts, zero test regressions, zero lint errors.**
    </content>
    <updated>2026-06-26T00:43:58Z</updated>
  </entry>

  <entry>
    <id>https://nostr.ae/nevent1qqsftsx0hlufs3sddukvt6u4mhvq7ndae45yjye5nvx7zsl6x477f2spx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzypp3shk7edn43y5zfvdr0ftl8eq8l00zaknjqx3c9xuv7ja8ck60q7afd87</id>
    
      <title type="html">## Local CI-parity run vs current upstream main Verified this PR ...</title>
    
    <link rel="alternate" href="https://nostr.ae/nevent1qqsftsx0hlufs3sddukvt6u4mhvq7ndae45yjye5nvx7zsl6x477f2spx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzypp3shk7edn43y5zfvdr0ftl8eq8l00zaknjqx3c9xuv7ja8ck60q7afd87" />
    <content type="html">
      In reply to &lt;a href=&#39;/nevent1qqs0gdd2ztscv7klylh7pphnstjmn0qnzyjl7npgq0hsc4dt4t9m4ccpz3mhxue69uhhyetvv9ujumn8d96zuer9wck3wc8h&#39;&gt;nevent1q…wc8h&lt;/a&gt;&lt;br/&gt;_________________________&lt;br/&gt;&lt;br/&gt;## Local CI-parity run vs current upstream main&lt;br/&gt;&lt;br/&gt;Verified this PR against `vitorpamplona/amethyst` master tip `74446e39cd` (current as of 2026-06-26 ~10:25 GMT&#43;10).&lt;br/&gt;&lt;br/&gt;### Rebase&lt;br/&gt;&lt;br/&gt;- Fetched PR tip `7ad166b5` from `refs/nostr/f435aa12…` on the maintainer&amp;#39;s relay.ngit.dev mirror&lt;br/&gt;- Rebased onto `upstream/main` (74446e39cd, &#43;666 commits since this PR&amp;#39;s `merge-base` 6cc62f13)&lt;br/&gt;- **Result: clean rebase, zero conflicts**&lt;br/&gt;- Rebased tip: `c421cd0043f2a93f512d9f07bf937a33a935d7d4`&lt;br/&gt;- Diff vs main: 14 files, &#43;1,483 / −14 — same shape as the published PR&lt;br/&gt;&lt;br/&gt;### CI-equivalent gradle runs&lt;br/&gt;&lt;br/&gt;Mirrored `.github/workflows/build.yml`:&lt;br/&gt;&lt;br/&gt;| CI job | Tasks | Result |&lt;br/&gt;|---|---|---|&lt;br/&gt;| `lint` | `spotlessCheck :quartz:verifyKmpPurity :commons:verifyKmpPurity` | ✅ PASS (48s) |&lt;br/&gt;| `build-desktop` (test slice) | `:quartz:jvmTest :commons:jvmTest :nestsClient:jvmTest :cli:test :desktopApp:test` | ✅ PASS (~3 min) |&lt;br/&gt;| `test-and-build-android` (test slice) | `:amethyst:testPlayDebugUnitTest :amethyst:testFdroidDebugUnitTest` | ✅ PASS, TZ=UTC (~2 min) |&lt;br/&gt;| `test-and-build-android` (lint slice) | `:amethyst:lintFdroidBenchmark :amethyst:lintPlayBenchmark -PdisableAbiSplits=true` | ✅ PASS (4m 2s), zero errors |&lt;br/&gt;&lt;br/&gt;### Test totals&lt;br/&gt;&lt;br/&gt;5,269 tests across `commons:jvmTest` (949), `quartz:jvmTest` (2,558), `amethyst:testPlayDebugUnitTest` (752), `amethyst:testFdroidDebugUnitTest` (725), `desktopApp:test` (285).&lt;br/&gt;&lt;br/&gt;**0 failures · 0 errors · 18 skipped (all pre-existing).**&lt;br/&gt;&lt;br/&gt;PR-specific new tests:&lt;br/&gt;&lt;br/&gt;- `MockNamecoinHistoryProviderTest`: 17/17 ✅&lt;br/&gt;- `NamecoinSettingsTest`: 26/26 ✅&lt;br/&gt;- `NamecoinResolutionRowTest`: 21/21 ✅&lt;br/&gt;&lt;br/&gt;### Lint&lt;br/&gt;&lt;br/&gt;Zero lint errors. One new style warning surfaced — `NamecoinSettingsSection.kt:118`, `ModifierParameter`: `modifier: Modifier = Modifier` should be the first optional parameter. Same severity as ~50 other warnings already in the codebase. Easy follow-up, not a blocker.&lt;br/&gt;&lt;br/&gt;### Caveats&lt;br/&gt;&lt;br/&gt;- `:quartz:iosSimulatorArm64Test` and `:amethyst:assembleBenchmark` skipped (PR doesn&amp;#39;t touch iOS-consumed commonMain; `verifyKmpPurity` already gates JVM-only leaks; benchmark APK packaging is artifact-only).&lt;br/&gt;- The PR was test-rebased and run locally; the published kind:1618 event itself still points at the original tip `7ad166b5` on top of `6cc62f13`. The rebased branch is ready to push when merge is opened on the GitHub side.&lt;br/&gt;- `CalendarFeedGroupingTest.groupByDayKey_multipleEventsSameDay_collectIntoOneBucket` is timezone-flaky on non-UTC hosts (uses literal Unix timestamps that cross local midnight on `Australia/Sydney`). Reproduces on bare `upstream/main` — unrelated to this PR. Passes under `TZ=UTC` matching CI runner.&lt;br/&gt;&lt;br/&gt;### Summary&lt;br/&gt;&lt;br/&gt;**Merge-safe against current `main`. Zero conflicts, zero test regressions, zero lint errors.**
    </content>
    <updated>2026-06-26T00:42:19Z</updated>
  </entry>

  <entry>
    <id>https://nostr.ae/nevent1qqsg0xgspylv0hkmlv2fa3mfm9lvr6plx6ya0q2vkw753wurc0uazvgpx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzypuxx3lncrfmuenaqvcvvftme4xywjwr254tuq788qxu5fp9lxrnc49pak2</id>
    
      <title>Nostr event nevent1qqsg0xgspylv0hkmlv2fa3mfm9lvr6plx6ya0q2vkw753wurc0uazvgpx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzypuxx3lncrfmuenaqvcvvftme4xywjwr254tuq788qxu5fp9lxrnc49pak2</title>
    
    <link rel="alternate" href="https://nostr.ae/nevent1qqsg0xgspylv0hkmlv2fa3mfm9lvr6plx6ya0q2vkw753wurc0uazvgpx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzypuxx3lncrfmuenaqvcvvftme4xywjwr254tuq788qxu5fp9lxrnc49pak2" />
    <content type="html">
      GM. You can&amp;#39;t comply your way to freedom.
    </content>
    <updated>2026-06-25T14:09:44Z</updated>
  </entry>

  <entry>
    <id>https://nostr.ae/nevent1qqsfxj7hakh6pew7cgn5v8x8hr826vnfvy93dtk6u5mdg9wqerm3edcpx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzyzzxxpmg3gy7cyffvl4s2388320g33y02pcjcw0dfy0l9dh6qxdwsllcez3</id>
    
      <title type="html">Why BIP-110 Is Going To Win ...</title>
    
    <link rel="alternate" href="https://nostr.ae/nevent1qqsfxj7hakh6pew7cgn5v8x8hr826vnfvy93dtk6u5mdg9wqerm3edcpx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzyzzxxpmg3gy7cyffvl4s2388320g33y02pcjcw0dfy0l9dh6qxdwsllcez3" />
    <content type="html">
      Why BIP-110 Is Going To Win&lt;br/&gt; &lt;video controls width=&#34;100%&#34; class=&#34;max-h-[90vh] bg-neutral-300 dark:bg-zinc-700&#34;&gt;&lt;source src=&#34;https://blossom.primal.net/5e34cfbfa3a2ac412d22c19cdfd964d537bb362b007460d1a03b31937fa87248.mp4&#34;&gt;&lt;/video&gt; 
    </content>
    <updated>2026-06-23T12:50:47Z</updated>
  </entry>

  <entry>
    <id>https://nostr.ae/nevent1qqsfh60yt6mljwzkwqc7rywxpapwg3w72kzplnkhxp8h89lssg7lc8spx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzyrslez8cudu8s3v8cgeh7n4epfrvpsrz93pwwlt4a39rw5slxrmzy56e65r</id>
    
      <title type="html">Pretty sure total node count during BIP148 was more like 5k-7k, ...</title>
    
    <link rel="alternate" href="https://nostr.ae/nevent1qqsfh60yt6mljwzkwqc7rywxpapwg3w72kzplnkhxp8h89lssg7lc8spx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzyrslez8cudu8s3v8cgeh7n4epfrvpsrz93pwwlt4a39rw5slxrmzy56e65r" />
    <content type="html">
      In reply to &lt;a href=&#39;/nevent1qqsfxj7hakh6pew7cgn5v8x8hr826vnfvy93dtk6u5mdg9wqerm3edcpp4mhxue69uhkummn9ekx7mqterg7h&#39;&gt;nevent1q…rg7h&lt;/a&gt;&lt;br/&gt;_________________________&lt;br/&gt;&lt;br/&gt;Pretty sure total node count during BIP148 was more like 5k-7k, not 100k. There aren’t even 100k today. Not sure why you keep repeating that figure?
    </content>
    <updated>2026-06-23T16:32:38Z</updated>
  </entry>

  <entry>
    <id>https://nostr.ae/nevent1qqsg2azel89lgwr288vdtt2uv7fu0vrr6t7slua4wlv8mlz5dp02w7spx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzyqnku0kt8ek29wpa9grnnwd552msm4fc55887esp2hgpae87t4wpyvlvfk6</id>
    
      <title>Nostr event nevent1qqsg2azel89lgwr288vdtt2uv7fu0vrr6t7slua4wlv8mlz5dp02w7spx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzyqnku0kt8ek29wpa9grnnwd552msm4fc55887esp2hgpae87t4wpyvlvfk6</title>
    
    <link rel="alternate" href="https://nostr.ae/nevent1qqsg2azel89lgwr288vdtt2uv7fu0vrr6t7slua4wlv8mlz5dp02w7spx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzyqnku0kt8ek29wpa9grnnwd552msm4fc55887esp2hgpae87t4wpyvlvfk6" />
    <content type="html">
      eden access test 193455Z
    </content>
    <updated>2026-06-20T19:34:56Z</updated>
  </entry>

  <entry>
    <id>https://nostr.ae/nevent1qqsqqqq99uv7qnhxdmqum27g35eh5g6cu9p7fdn7nnnmsc60xn076lgpx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzyz8z0la4exacehgpxxk7dmayn4tdgqd4gfxelhu6v0s8f4f8kpc4cap0su9</id>
    
      <title type="html">Def gonna be doing that. I thought it was just the roots but ...</title>
    
    <link rel="alternate" href="https://nostr.ae/nevent1qqsqqqq99uv7qnhxdmqum27g35eh5g6cu9p7fdn7nnnmsc60xn076lgpx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzyz8z0la4exacehgpxxk7dmayn4tdgqd4gfxelhu6v0s8f4f8kpc4cap0su9" />
    <content type="html">
      In reply to &lt;a href=&#39;/nevent1qqs0pevg39rerk0wvxrq238929tglycqtyup3j9rfh3tpy76ygcwy0sppamhxue69uhkummnw3ezumt0d5u8yx2a&#39;&gt;nevent1q…yx2a&lt;/a&gt;&lt;br/&gt;_________________________&lt;br/&gt;&lt;br/&gt;Def gonna be doing that. I thought it was just the roots but I&amp;#39;ll def chop and drop em too now!&lt;br/&gt;&lt;br/&gt;I&amp;#39;ve been sticking the spent flowers into the dirt next to my strawberries in hopes of clickbaiting some pollinators... lol probably futile but its fun
    </content>
    <updated>2026-06-12T21:19:10Z</updated>
  </entry>

  <entry>
    <id>https://nostr.ae/nevent1qqsqqqrzwl0v0a67vfrkft9qtkt239j2r99sxtr50hvxjw2nk3hekngpx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzyz8z0la4exacehgpxxk7dmayn4tdgqd4gfxelhu6v0s8f4f8kpc4ccz4wpc</id>
    
      <title type="html">Thank you! Its my first time growing flowers so I went with ...</title>
    
    <link rel="alternate" href="https://nostr.ae/nevent1qqsqqqrzwl0v0a67vfrkft9qtkt239j2r99sxtr50hvxjw2nk3hekngpx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzyz8z0la4exacehgpxxk7dmayn4tdgqd4gfxelhu6v0s8f4f8kpc4ccz4wpc" />
    <content type="html">
      In reply to &lt;a href=&#39;/nevent1qqs9hddcn9rtxznkdw6pmayperzjrndcyf4jdv35upl9rc7hjqkgx6qprfmhxue69uhhyetvv9ujumn0wd68yurvv438xtnrdaksy6rpva&#39;&gt;nevent1q…rpva&lt;/a&gt;&lt;br/&gt;_________________________&lt;br/&gt;&lt;br/&gt;Thank you! Its my first time growing flowers so I went with something easy.
    </content>
    <updated>2026-06-12T18:25:19Z</updated>
  </entry>

  <entry>
    <id>https://nostr.ae/nevent1qqsqqq8l7v6fdu9mcrttm3al796uwqex7c0g6m9umnryndranxaphwcpx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzyz8z0la4exacehgpxxk7dmayn4tdgqd4gfxelhu6v0s8f4f8kpc4cd50dh5</id>
    
      <title type="html">Picked some marigolds from the garden today. Buying cut flowers ...</title>
    
    <link rel="alternate" href="https://nostr.ae/nevent1qqsqqq8l7v6fdu9mcrttm3al796uwqex7c0g6m9umnryndranxaphwcpx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzyz8z0la4exacehgpxxk7dmayn4tdgqd4gfxelhu6v0s8f4f8kpc4cd50dh5" />
    <content type="html">
      Picked some marigolds from the garden today. &lt;br/&gt;Buying cut flowers feels wasteful.&lt;br/&gt;But cutting self-grown flowers produces more flowers. #gardenstr #flowerstr&lt;br/&gt; &lt;img src=&#34;https://blossom.primal.net/c280324d25d81d18fd148c502e9d788839cf5920414ff04d66cc8699064fe714.jpg&#34;&gt; &lt;br/&gt; &lt;img src=&#34;https://blossom.primal.net/1336cdf24c0b53f2d79a51f9426d58b3b396368a6e80e0843b83a78fed0c1fc0.jpg&#34;&gt; 
    </content>
    <updated>2026-06-12T17:43:26Z</updated>
  </entry>

  <entry>
    <id>https://nostr.ae/nevent1qqsqxvr8qwjd9hn4g2hvaq263803vuptellvw2m8hxrpf5adyykd95gpx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzypg58smnmud4fznh670vwne8y4w39xmftdfzm76m7s6f3wjt2qwljmnwdp3</id>
    
      <title type="html">Lobbying has turned classical party based politics into ...</title>
    
    <link rel="alternate" href="https://nostr.ae/nevent1qqsqxvr8qwjd9hn4g2hvaq263803vuptellvw2m8hxrpf5adyykd95gpx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzypg58smnmud4fznh670vwne8y4w39xmftdfzm76m7s6f3wjt2qwljmnwdp3" />
    <content type="html">
      Lobbying has turned classical party based politics into corruption-ridden corporatism. &lt;br/&gt;&lt;blockquote class=&#34;border-l-05rem border-l-strongpink border-solid&#34;&gt;&lt;div class=&#34;-ml-4 bg-gradient-to-r from-gray-100 dark:from-zinc-800 to-transparent mr-0 mt-0 mb-4 pl-4 pr-2 py-2&#34;&gt;quoting &lt;br/&gt;&lt;span itemprop=&#34;mentions&#34; itemscope itemtype=&#34;https://schema.org/Article&#34;&gt;&lt;a itemprop=&#34;url&#34; href=&#34;/nevent1qqsyl9hrqmtm8dq3plduqjamhm036w6axtx0j09qpa0r8f6eqcpcamqzypxhsss9z7pwp5l7kq6dz59dc2mt4e8w8dyhseunhlaydzm0twttxsnrsdq&#34; class=&#34;bg-lavender dark:prose:text-neutral-50 dark:text-neutral-50 dark:bg-garnet px-1&#34;&gt;nevent1q…rsdq&lt;/a&gt;&lt;/span&gt; &lt;/div&gt; ⚡️🇺🇸 NEW - Rep Massie: “I think the biggest crime I committed against the swamp…was showing the American people that somebody on the right could join somebody on the left and get something done, which is releasing the Epstein files, that everybody knew needed to be done. That’s probably the ONLY bill that has passed Washington DC in the last ten years, that lobbyists haven’t written. It was written by me and Ro Khanna…that’s when they decided I had to be taken out, that I was becoming effective so they wanted to eliminate me...” &lt;br/&gt;&lt;video controls width=&#34;100%&#34; class=&#34;max-h-[90vh] bg-neutral-300 dark:bg-zinc-700&#34;&gt;&lt;source src=&#34;https://blossom.primal.net/5605dcac7b8fde7e003959fb221791f6dff0dc424e581894d6c4443a8f18b502.mp4&#34;&gt;&lt;/video&gt; &lt;/blockquote&gt;
    </content>
    <updated>2026-05-26T18:29:50Z</updated>
  </entry>

  <entry>
    <id>https://nostr.ae/nevent1qqsxprj4pj02j6g8u7pmnsuvh8y5773vtj56zm6udv5wz2qck4xmtvgpx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzyqxyt475tmdsltw6gg2axm9qmx46p3m3hpwnw9mkfw9p9r27gsly6erejqn</id>
    
      <title type="html">My situation is complex since I don’t fall into conventional ...</title>
    
    <link rel="alternate" href="https://nostr.ae/nevent1qqsxprj4pj02j6g8u7pmnsuvh8y5773vtj56zm6udv5wz2qck4xmtvgpx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzyqxyt475tmdsltw6gg2axm9qmx46p3m3hpwnw9mkfw9p9r27gsly6erejqn" />
    <content type="html">
      In reply to &lt;a href=&#39;/nevent1qqsg2fg7zph2zyc3jxtfncg9tp7uz4puafp8r9dpmxhzvh7yw2mtcuqprdmhxue69uhhyetvv9ujumt0wd68ymewdejhgam0wf4j76j4gq2&#39;&gt;nevent1q…4gq2&lt;/a&gt;&lt;br/&gt;_________________________&lt;br/&gt;&lt;br/&gt;My situation is complex since I don’t fall into conventional categories like most people too.
    </content>
    <updated>2026-05-23T22:05:49Z</updated>
  </entry>

  <entry>
    <id>https://nostr.ae/nevent1qqspc0jntgelxgdqymmyhx2kgusdc9xrxgrdesgqm6ug4jtardkanjspx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzyz85wj4mwrpesllhaylam8spewk79kk44ze5d8ap4w3fnq36rnhgj0q58rd</id>
    
      <title type="html">ROBERT JOHNSON — Crossroads Psalms Lost Delta Blues Tapes ...</title>
    
    <link rel="alternate" href="https://nostr.ae/nevent1qqspc0jntgelxgdqymmyhx2kgusdc9xrxgrdesgqm6ug4jtardkanjspx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzyz85wj4mwrpesllhaylam8spewk79kk44ze5d8ap4w3fnq36rnhgj0q58rd" />
    <content type="html">
      ROBERT JOHNSON — Crossroads Psalms  Lost Delta Blues Tapes&lt;br/&gt;&lt;a href=&#34;https://www.youtube.com/watch?v=oHlo1zYonlg&#34;&gt;https://www.youtube.com/watch?v=oHlo1zYonlg&lt;/a&gt;&lt;br/&gt;#music #blues &lt;br/&gt;&lt;br/&gt;
    </content>
    <updated>2026-05-26T15:39:41Z</updated>
  </entry>

  <entry>
    <id>https://nostr.ae/nevent1qqswxf3zyplgkfqax8rhjnaerjyvsrtamrjav8qpv80awdl75085uyqpx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzyqnxs90qeyssm73jf3kt5dtnk997ujw6ggy6j3t0jjzw2yrv6sy22fnprgy</id>
    
      <title type="html">Vibe coding our way to feature parity with github 😄 ...</title>
    
    <link rel="alternate" href="https://nostr.ae/nevent1qqswxf3zyplgkfqax8rhjnaerjyvsrtamrjav8qpv80awdl75085uyqpx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzyqnxs90qeyssm73jf3kt5dtnk997ujw6ggy6j3t0jjzw2yrv6sy22fnprgy" />
    <content type="html">
      Vibe coding our way to feature parity with github 😄 &lt;blockquote class=&#34;border-l-05rem border-l-strongpink border-solid&#34;&gt;&lt;div class=&#34;-ml-4 bg-gradient-to-r from-gray-100 dark:from-zinc-800 to-transparent mr-0 mt-0 mb-4 pl-4 pr-2 py-2&#34;&gt;quoting &lt;br/&gt;&lt;span itemprop=&#34;mentions&#34; itemscope itemtype=&#34;https://schema.org/Article&#34;&gt;&lt;a itemprop=&#34;url&#34; href=&#34;/nevent1qqs2rw78yg7yhd8wgnfkjaye3ryw26gqu25asdv55pcqujnp2xmf30cvh75dv&#34; class=&#34;bg-lavender dark:prose:text-neutral-50 dark:text-neutral-50 dark:bg-garnet px-1&#34;&gt;nevent1q…75dv&lt;/a&gt;&lt;/span&gt; &lt;/div&gt; Adds a read-only branches view to repository pages. The view is linked next to Commits, supports switching between Nostr state and specific git servers, shows branch counts per source, and compares each branch ahead/behind the default branch. &lt;/blockquote&gt;
    </content>
    <updated>2026-05-21T15:41:45Z</updated>
  </entry>

  <entry>
    <id>https://nostr.ae/nevent1qqsq79tg98jhtrwwluey3q228xmyq64w9ns7uuraunfxr2297cw0hmgpx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzyz465zw6k87rll7pgz0ak2938qev6sp3wpxymases5jl5l4yv6ldymu7wt8</id>
    
      <title type="html">I was thinking just yesterday, when I got a notification for a ...</title>
    
    <link rel="alternate" href="https://nostr.ae/nevent1qqsq79tg98jhtrwwluey3q228xmyq64w9ns7uuraunfxr2297cw0hmgpx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzyz465zw6k87rll7pgz0ak2938qev6sp3wpxymases5jl5l4yv6ldymu7wt8" />
    <content type="html">
      In reply to &lt;a href=&#39;/nevent1qqsras2aw46uf2ecf4e7pu5cghjuyka704rj63kpt230gj8tahqwexc58sk4x&#39;&gt;nevent1q…sk4x&lt;/a&gt;&lt;br/&gt;_________________________&lt;br/&gt;&lt;br/&gt;I was thinking just yesterday, when I got a notification for a comment in a 7 year old PR, “man, it would be nice to have a zapping pot for getting a PR merged”.
    </content>
    <updated>2026-05-13T21:36:15Z</updated>
  </entry>

  <entry>
    <id>https://nostr.ae/nevent1qqsras2aw46uf2ecf4e7pu5cghjuyka704rj63kpt230gj8tahqwexcpx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzyqnxs90qeyssm73jf3kt5dtnk997ujw6ggy6j3t0jjzw2yrv6sy22w0hyfu</id>
    
      <title type="html">Zaps coming to gitworkshop. I can&amp;#39;t wait to start zapping ...</title>
    
    <link rel="alternate" href="https://nostr.ae/nevent1qqsras2aw46uf2ecf4e7pu5cghjuyka704rj63kpt230gj8tahqwexcpx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzyqnxs90qeyssm73jf3kt5dtnk997ujw6ggy6j3t0jjzw2yrv6sy22w0hyfu" />
    <content type="html">
      Zaps coming to gitworkshop. I can&amp;#39;t wait to start zapping issues and PRs :D&lt;br/&gt;&lt;blockquote class=&#34;border-l-05rem border-l-strongpink border-solid&#34;&gt;&lt;div class=&#34;-ml-4 bg-gradient-to-r from-gray-100 dark:from-zinc-800 to-transparent mr-0 mt-0 mb-4 pl-4 pr-2 py-2&#34;&gt;quoting &lt;br/&gt;&lt;span itemprop=&#34;mentions&#34; itemscope itemtype=&#34;https://schema.org/Article&#34;&gt;&lt;a itemprop=&#34;url&#34; href=&#34;/nevent1qgs2qzx779ted7af5rt04vzw3l2hpzfgtk0a2pw6t2plaz4d2734vngpzemhxue69uhhyetvv9ujuerfw36x7tnsw43z7qpqrz70z20d82nwsdr5r34fqhxyhkqprjgqyl5kdjl62nf9wdgv8a6q26mee6&#34; class=&#34;bg-lavender dark:prose:text-neutral-50 dark:text-neutral-50 dark:bg-garnet px-1&#34;&gt;nevent1q…mee6&lt;/a&gt;&lt;/span&gt; &lt;/div&gt; Thanks for this contribution. I made some fixes eg. sending to repository relays and added some few extras. &lt;br/&gt;Zap a repo:&lt;br/&gt; &lt;img src=&#34;https://haven.danconwaydev.com/000583373b717b867b96e6d1fd02223b5bc08aef6cb49aa74df5c954fd48c0ee.png&#34;&gt; &lt;br/&gt;Zap thread items such as comments:&lt;br/&gt; &lt;img src=&#34;https://haven.danconwaydev.com/42c9d0fff67f60840bc9a354d1cbc8668171fdd0632bade060dc8a977dd9f88b.png&#34;&gt; &lt;br/&gt;Expand to see comments:&lt;br/&gt; &lt;img src=&#34;https://haven.danconwaydev.com/49aade5f610ba76e40ef883016afd687d545f696522b3f66f99f582ed789a432.png&#34;&gt; &lt;br/&gt;Show notable zaps a seperate thread item if 500 sats&#43; or 19&#43; characters in the message:&lt;br/&gt; &lt;img src=&#34;https://haven.danconwaydev.com/bcd507ce7449f4d579ab583ee7430ffb5bbeab380006ffd9f35eb25729679e27.png&#34;&gt; &lt;br/&gt;Show zap total in Issue/PR list:&lt;br/&gt; &lt;img src=&#34;https://haven.danconwaydev.com/ac4924168dcb781e54abc2c6ebe6c6e8d2c910f33f02623a8fb912ab0dcf1cf1.png&#34;&gt; &lt;br/&gt;Add to notifications:&lt;br/&gt; &lt;img src=&#34;https://haven.danconwaydev.com/e8448baeef76956f365307aaa0bff411228af5c99e32aea0d6ea904260b20592.png&#34;&gt;  &lt;/blockquote&gt;
    </content>
    <updated>2026-05-13T16:48:08Z</updated>
  </entry>

  <entry>
    <id>https://nostr.ae/nevent1qqs8jfmm6gpg8lpql2dxjhfexh24ulydfexs0u0q4xddcylv20mhqaqpx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzyq0fwa4z87uy2p96es56qtz4g4lcxmtgwkapuj5st4pqgqn3d26ggsg0xss</id>
    
      <title>Nostr event nevent1qqs8jfmm6gpg8lpql2dxjhfexh24ulydfexs0u0q4xddcylv20mhqaqpx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzyq0fwa4z87uy2p96es56qtz4g4lcxmtgwkapuj5st4pqgqn3d26ggsg0xss</title>
    
    <link rel="alternate" href="https://nostr.ae/nevent1qqs8jfmm6gpg8lpql2dxjhfexh24ulydfexs0u0q4xddcylv20mhqaqpx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzyq0fwa4z87uy2p96es56qtz4g4lcxmtgwkapuj5st4pqgqn3d26ggsg0xss" />
    <content type="html">
      Test
    </content>
    <updated>2026-05-13T13:17:36Z</updated>
  </entry>

  <entry>
    <id>https://nostr.ae/nevent1qqswsg7rug8vg0wf3670z2qgcyqrn5wtpqang4h0qp2kj0ydz2fqzmqpx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzyru5lpjg4t8vnzqt5enlks303pkh07n8ejl98pj9k83p6h2cpcs5uqxz3my</id>
    
      <title type="html">Gridiron Price: 100 SAT #zapsnag ...</title>
    
    <link rel="alternate" href="https://nostr.ae/nevent1qqswsg7rug8vg0wf3670z2qgcyqrn5wtpqang4h0qp2kj0ydz2fqzmqpx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzyru5lpjg4t8vnzqt5enlks303pkh07n8ejl98pj9k83p6h2cpcs5uqxz3my" />
    <content type="html">
      Gridiron&lt;br/&gt;&lt;br/&gt;Price: 100 SAT&lt;br/&gt;&lt;br/&gt;#zapsnag&lt;br/&gt; &lt;img src=&#34;https://cdn.nostrcheck.me/043babfd106165ea3f837190e8024297082099c23c5024b53e195faeb8f6086a.jpeg&#34;&gt; 
    </content>
    <updated>2026-05-05T17:10:56Z</updated>
  </entry>

  <entry>
    <id>https://nostr.ae/nevent1qqsyh89hvuy7lhld77asu76lu9mq66fc3l8gnt5hzq3atdczc43kqfcpx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzyzsq3hh327t0h2dq6matqn5064cgj2zanl2stkj6s0lg4t2h5dty6vflxn5</id>
    
      <title type="html">Its probably because the client you are using doesnt support ...</title>
    
    <link rel="alternate" href="https://nostr.ae/nevent1qqsyh89hvuy7lhld77asu76lu9mq66fc3l8gnt5hzq3atdczc43kqfcpx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzyzsq3hh327t0h2dq6matqn5064cgj2zanl2stkj6s0lg4t2h5dty6vflxn5" />
    <content type="html">
      In reply to &lt;a href=&#39;/nevent1qqspuw882q7upddjzs33pkl4m3dx4flq0mqnnqgy9w7gdh67mtnxvaspzemhxue69uhhyetvv9ujuerfw36x7tnsw43z76u7uzl&#39;&gt;nevent1q…7uzl&lt;/a&gt;&lt;br/&gt;_________________________&lt;br/&gt;&lt;br/&gt;Its probably because the client you are using doesnt support showing the git PR kind.&lt;br/&gt;&lt;a href=&#34;https://gitworkshop.dev/nevent1qy28wumn8ghj7un9d3shjtnwva5hgtnyv4mqqgrwmpmlfdc8vzjvemlk4z055lccugf3w4tyer4sl4yujt2tva057v49nc6t&#34;&gt;https://gitworkshop.dev/nevent1qy28wumn8ghj7un9d3shjtnwva5hgtnyv4mqqgrwmpmlfdc8vzjvemlk4z055lccugf3w4tyer4sl4yujt2tva057v49nc6t&lt;/a&gt;&lt;br/&gt;&lt;br/&gt;The nostr link has relay hints:&lt;blockquote class=&#34;border-l-05rem border-l-strongpink border-solid&#34;&gt;&lt;div class=&#34;-ml-4 bg-gradient-to-r from-gray-100 dark:from-zinc-800 to-transparent mr-0 mt-0 mb-4 pl-4 pr-2 py-2&#34;&gt;quoting  &lt;span itemprop=&#34;mentions&#34; itemscope itemtype=&#34;https://schema.org/Article&#34;&gt;&lt;a itemprop=&#34;url&#34; href=&#34;/nevent1qy28wumn8ghj7un9d3shjtnwva5hgtnyv4mqqgrwmpmlfdc8vzjvemlk4z055lccugf3w4tyer4sl4yujt2tva057v49nc6t&#34; class=&#34;bg-lavender dark:prose:text-neutral-50 dark:text-neutral-50 dark:bg-garnet px-1&#34;&gt;nevent1q…nc6t&lt;/a&gt;&lt;/span&gt; &lt;/div&gt; Introduces a trusted third party — the service — that faithfully signs&lt;br/&gt;repo state announcements on the user&#39;s behalf, enabling Git-over-SSH&lt;br/&gt;without a Nostr signing plugin, trading trustlessness for convenience&lt;br/&gt;and simpler onboarding. Users retain GRASP backup, redundancy, and&lt;br/&gt;collaboration benefits, and can remove the proxy pubkey from maintainers&lt;br/&gt;to return to a fully self-signed setup at any time. &lt;/blockquote&gt;
    </content>
    <updated>2026-05-05T08:21:50Z</updated>
  </entry>

  <entry>
    <id>https://nostr.ae/nevent1qqstxqcs9a0yjuz0vcl645lpv29nnctm8yahakxg42y0ak24e93zy8gpx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzyzsq3hh327t0h2dq6matqn5064cgj2zanl2stkj6s0lg4t2h5dty6lv9xzk</id>
    
      <title type="html">I decided to interpret this as &amp;#34;until you fix the client that ...</title>
    
    <link rel="alternate" href="https://nostr.ae/nevent1qqstxqcs9a0yjuz0vcl645lpv29nnctm8yahakxg42y0ak24e93zy8gpx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzyzsq3hh327t0h2dq6matqn5064cgj2zanl2stkj6s0lg4t2h5dty6lv9xzk" />
    <content type="html">
      In reply to &lt;a href=&#39;/nevent1qqs0a2eftnynq6lh3e0xs4qd2r2lg27cr76m4k35z9emy8qps2lukxqpzemhxue69uhhyetvv9ujuerfw36x7tnsw43z7u4ynzj&#39;&gt;nevent1q…ynzj&lt;/a&gt;&lt;br/&gt;_________________________&lt;br/&gt;&lt;br/&gt;I decided to interpret this as &amp;#34;until you fix the client that produced the note without the reference&amp;#34; for maxium PoW. So here is the GRASP ssh proxy idea:&lt;blockquote class=&#34;border-l-05rem border-l-strongpink border-solid&#34;&gt;&lt;div class=&#34;-ml-4 bg-gradient-to-r from-gray-100 dark:from-zinc-800 to-transparent mr-0 mt-0 mb-4 pl-4 pr-2 py-2&#34;&gt;quoting  &lt;span itemprop=&#34;mentions&#34; itemscope itemtype=&#34;https://schema.org/Article&#34;&gt;&lt;a itemprop=&#34;url&#34; href=&#34;/nevent1qvzqqqqx2gpzpgqgmmc409hm4xsdd74sf68a2uyf9pwel4g9mfdg8l5244t6x4jdqy88wumn8ghj7mn0wvhxcmmv9uq3camnwvaz7tmwva5hgtnyv9hxxmmwwashjer9wchxxmmd9uqzqmkcwl6twpmq5nxwla4gna987x8zzvt42exgav8af8yj6jm8ta8nhas6xr&#34; class=&#34;bg-lavender dark:prose:text-neutral-50 dark:text-neutral-50 dark:bg-garnet px-1&#34;&gt;nevent1q…s6xr&lt;/a&gt;&lt;/span&gt;&lt;br/&gt; &lt;/div&gt; Introduces a trusted third party — the service — that faithfully signs&lt;br/&gt;repo state announcements on the user&#39;s behalf, enabling Git-over-SSH&lt;br/&gt;without a Nostr signing plugin, trading trustlessness for convenience&lt;br/&gt;and simpler onboarding. Users retain GRASP backup, redundancy, and&lt;br/&gt;collaboration benefits, and can remove the proxy pubkey from maintainers&lt;br/&gt;to return to a fully self-signed setup at any time. &lt;/blockquote&gt;&lt;br/&gt;and here is the client fix PR:&lt;blockquote class=&#34;border-l-05rem border-l-strongpink border-solid&#34;&gt;&lt;div class=&#34;-ml-4 bg-gradient-to-r from-gray-100 dark:from-zinc-800 to-transparent mr-0 mt-0 mb-4 pl-4 pr-2 py-2&#34;&gt;quoting  &lt;span itemprop=&#34;mentions&#34; itemscope itemtype=&#34;https://schema.org/Article&#34;&gt;&lt;a itemprop=&#34;url&#34; href=&#34;/nevent1qy28wumn8ghj7un9d3shjtnwva5hgtnyv4mqqgzu8399x2zfwdz6rff7psc0qzvfamesu3jklxh5qwukcvcemdk8p5w7mm3d&#34; class=&#34;bg-lavender dark:prose:text-neutral-50 dark:text-neutral-50 dark:bg-garnet px-1&#34;&gt;nevent1q…mm3d&lt;/a&gt;&lt;/span&gt; &lt;/div&gt; Bare NIP-19 bech32 identifiers typed or pasted into the compose box were&lt;br/&gt;previously published as-is in event content, without the nostr: URI prefix.&lt;br/&gt;NoteContent&#39;s lenient renderer masked this locally, but any spec-compliant&lt;br/&gt;client would fail to recognise the references, and p/q tag extraction was&lt;br/&gt;correspondingly incomplete.&lt;br/&gt;&lt;br/&gt;Rather than re-implement the identifier-scanning regex at each call site,&lt;br/&gt;this introduces two small shared helpers and routes both the live preview&lt;br/&gt;and the publish handler through them, so what the user sees in preview is&lt;br/&gt;exactly what gets signed.&lt;br/&gt;&lt;br/&gt;src/lib/nostrIdentifier.ts&lt;br/&gt;  - findUrlRanges(text): scan once for http(s)://… spans, so every scanner&lt;br/&gt;    in this file shares the same definition of &#39;inside a URL&#39;.&lt;br/&gt;  - findNip19InText(text): scans text for NIP-19 identifiers, returns only&lt;br/&gt;    matches that successfully nip19.decode(). Uses findUrlRanges to skip&lt;br/&gt;    identifiers anywhere inside a URL span — including already-prefixed&lt;br/&gt;    ones, so &lt;a href=&#34;https://example.com/nostr:nevent1&#34;&gt;https://example.com/nostr:nevent1&lt;/a&gt;... no longer emits a stray&lt;br/&gt;    q tag. nsec1 is never matched.&lt;br/&gt;  - normalizeNip19ToNostrUri(text): rewrites bare identifiers to their&lt;br/&gt;    nostr: URI form (NIP-21) and returns the scan results alongside the&lt;br/&gt;    rewritten text, so callers don&#39;t pay for two decode passes.&lt;br/&gt;&lt;br/&gt;src/lib/composedNoteTags.ts&lt;br/&gt;  - buildComposedNoteTags({ content, quotedEvent, ... }): single source of&lt;br/&gt;    truth for every content-derived tag on a composed note. Emits t, p&lt;br/&gt;    (NIP-27), q (NIP-18), emoji (NIP-30), imeta (NIP-92), and&lt;br/&gt;    content-warning (NIP-36) tags, and returns the NIP-21-normalised&lt;br/&gt;    content alongside. The explicit quoted-event widget is now an input to&lt;br/&gt;    the builder — it appends the nostr: URI to the (normalised) content&lt;br/&gt;    and emits the q tag internally, so callers can&#39;t forget the dedupe&lt;br/&gt;    step or drift preview and publish. Reply-specific NIP-10 tags remain&lt;br/&gt;    in handleSubmit because they depend on replyTo rather than on content.&lt;br/&gt;&lt;br/&gt;src/components/ComposeBox.tsx&lt;br/&gt;  - mockEvent (preview) and handleSubmit (publish) make the same&lt;br/&gt;    buildComposedNoteTags call, including contentWarning and quotedEvent.&lt;br/&gt;    Removed the quote-widget branch from handleSubmit: the builder now&lt;br/&gt;    owns it.&lt;br/&gt;&lt;br/&gt;Covers NIP-21 (nostr: URI scheme) for npub1/nprofile1/note1/nevent1/naddr1/&lt;br/&gt;nrelay1, NIP-27 p-tag extraction for both npub1 and nprofile1 mentions,&lt;br/&gt;and NIP-18 q-tag emission for every inline nostr:note1/nevent1/naddr1&lt;br/&gt;reference with duplicates against the quoted-event widget suppressed. &lt;/blockquote&gt;
    </content>
    <updated>2026-05-05T08:17:06Z</updated>
  </entry>

  <entry>
    <id>https://nostr.ae/nevent1qqsvafz464mw03ga4h08mke8zvavchl4t4plvzgsvv6hhjhqj3fdyyspx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzyz96jftqtgnw8tanjdgwwmt27n3hayd3ul5rfcl6jyw4gmuwrn736s2csuk</id>
    
      <title type="html">&amp;#34;US Central Command announces the participation of 15,000 ...</title>
    
    <link rel="alternate" href="https://nostr.ae/nevent1qqsvafz464mw03ga4h08mke8zvavchl4t4plvzgsvv6hhjhqj3fdyyspx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzyz96jftqtgnw8tanjdgwwmt27n3hayd3ul5rfcl6jyw4gmuwrn736s2csuk" />
    <content type="html">
      &amp;#34;US Central Command announces the participation of 15,000 troops, 100 aircraft, and guided-missile destroyers in Operation &amp;#34;Freedom,&amp;#34; announced by Donald Trump to free ships from the Strait of Hormuz.&amp;#34;&lt;br/&gt;&lt;br/&gt;Lel, Project Epic Fury didn&amp;#39;t ahbe congressional approval, so he ended it 1 day before, then started a new one, also without approval 🤡&lt;br/&gt;&lt;br/&gt;Even AmeriKKKan laws are working exactly as designed - to NOT work 😁😆&lt;br/&gt;&lt;br/&gt;Anyway, looking forward to Iran 🇮🇷 wiping the floor with them 🍿 
    </content>
    <updated>2026-05-04T08:40:14Z</updated>
  </entry>

  <entry>
    <id>https://nostr.ae/nevent1qqsvmkwt53v8hxz05z65wg55cu3etljec5z4e95jufw3j3asw9pw9lqpx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzypp5l9uexcnlreslznh27cx24r8aemqs5kfv4luz2ryz2ffd2jxp26davg7</id>
    
      <title type="html">#nevent1q…uxyz It&amp;#39;s a kind:1618 pull request event, it ...</title>
    
    <link rel="alternate" href="https://nostr.ae/nevent1qqsvmkwt53v8hxz05z65wg55cu3etljec5z4e95jufw3j3asw9pw9lqpx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzypp5l9uexcnlreslznh27cx24r8aemqs5kfv4luz2ryz2ffd2jxp26davg7" />
    <content type="html">
      In reply to &lt;a href=&#39;/nevent1qqs0a2eftnynq6lh3e0xs4qd2r2lg27cr76m4k35z9emy8qps2lukxqprfmhxue69uhhq7tjv9kkjepwve5kzar2v9nzucm0d5hsekjtdt&#39;&gt;nevent1q…jtdt&lt;/a&gt;&lt;br/&gt;_________________________&lt;br/&gt;&lt;br/&gt;&lt;blockquote class=&#34;border-l-05rem border-l-strongpink border-solid&#34;&gt;&lt;div class=&#34;-ml-4 bg-gradient-to-r from-gray-100 dark:from-zinc-800 to-transparent mr-0 mt-0 mb-4 pl-4 pr-2 py-2&#34;&gt;quoting &lt;span itemprop=&#34;mentions&#34; itemscope itemtype=&#34;https://schema.org/Article&#34;&gt;&lt;a itemprop=&#34;url&#34; href=&#34;/nevent1qvzqqqqx2gpzpgqgmmc409hm4xsdd74sf68a2uyf9pwel4g9mfdg8l5244t6x4jdqy88wumn8ghj7mn0wvhxcmmv9uq32amnwvaz7tmjv4kxz7fwdenkjapwv3jhvtcqyphdsal5kurkpfxvalm238620uvwyych24jv36c06jwf949kwh60xgxuxyz&#34; class=&#34;bg-lavender dark:prose:text-neutral-50 dark:text-neutral-50 dark:bg-garnet px-1&#34;&gt;nevent1q…uxyz&lt;/a&gt;&lt;/span&gt;&lt;br/&gt; &lt;/div&gt; Introduces a trusted third party — the service — that faithfully signs&lt;br/&gt;repo state announcements on the user&#39;s behalf, enabling Git-over-SSH&lt;br/&gt;without a Nostr signing plugin, trading trustlessness for convenience&lt;br/&gt;and simpler onboarding. Users retain GRASP backup, redundancy, and&lt;br/&gt;collaboration benefits, and can remove the proxy pubkey from maintainers&lt;br/&gt;to return to a fully self-signed setup at any time. &lt;/blockquote&gt;It&amp;#39;s a kind:1618 pull request event, it doesn&amp;#39;t work on most clients.&lt;br/&gt;&lt;a href=&#34;https://gitworkshop.dev/npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr/nos.lol/grasp/prs/nevent1qy88wumn8ghj7mn0wvhxcmmv9uq32amnwvaz7tmjv4kxz7fwdenkjapwv3jhvtcqyphdsal5kurkpfxvalm238620uvwyych24jv36c06jwf949kwh60xevh5ul&#34;&gt;https://gitworkshop.dev/npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr/nos.lol/grasp/prs/nevent1qy88wumn8ghj7mn0wvhxcmmv9uq32amnwvaz7tmjv4kxz7fwdenkjapwv3jhvtcqyphdsal5kurkpfxvalm238620uvwyych24jv36c06jwf949kwh60xevh5ul&lt;/a&gt;
    </content>
    <updated>2026-05-02T07:45:38Z</updated>
  </entry>

  <entry>
    <id>https://nostr.ae/nevent1qqsz2xqef22n5at2e6xfys9x952v5s94x47ps6a4qryveks22trpnxcpx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzyr02k7w6lgwzhe955mf6egf40dk25zm5f06x44ff5khyvs5g270xsrs2vsu</id>
    
      <title>Nostr event nevent1qqsz2xqef22n5at2e6xfys9x952v5s94x47ps6a4qryveks22trpnxcpx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzyr02k7w6lgwzhe955mf6egf40dk25zm5f06x44ff5khyvs5g270xsrs2vsu</title>
    
    <link rel="alternate" href="https://nostr.ae/nevent1qqsz2xqef22n5at2e6xfys9x952v5s94x47ps6a4qryveks22trpnxcpx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzyr02k7w6lgwzhe955mf6egf40dk25zm5f06x44ff5khyvs5g270xsrs2vsu" />
    <content type="html">
       &lt;img src=&#34;https://haven.downisontheup.ca/dcd0c1ebcd28cb922b09498f5ef0204e59a653f5913f2db0cea9546a0535f9d8.jpg&#34;&gt; 
    </content>
    <updated>2026-04-28T18:28:27Z</updated>
  </entry>

  <entry>
    <id>https://nostr.ae/nevent1qqsw3s6tfg56kemajf5qzkpp8fqxycapvm85gvneh9452ra4fcvdsugpx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzyqqx2vktn9kjssx2fkthres07j8cuvwd6fm3esmu527j7zla3u5tgy6kms6</id>
    
      <title type="html">I give you Rob Zombie... ...</title>
    
    <link rel="alternate" href="https://nostr.ae/nevent1qqsw3s6tfg56kemajf5qzkpp8fqxycapvm85gvneh9452ra4fcvdsugpx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzyqqx2vktn9kjssx2fkthres07j8cuvwd6fm3esmu527j7zla3u5tgy6kms6" />
    <content type="html">
      I give you Rob Zombie...&lt;br/&gt; &lt;img src=&#34;https://i.nostr.build/rvtB59tSBRpLNyj4.jpg&#34;&gt; &lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;a href=&#34;https://a.nostr.build/z6pVlHkbZwVwzHjA.mp3&#34;&gt;https://a.nostr.build/z6pVlHkbZwVwzHjA.mp3&lt;/a&gt;
    </content>
    <updated>2026-04-23T04:27:35Z</updated>
  </entry>

  <entry>
    <id>https://nostr.ae/nevent1qqsfkr7aup09jshu5u0jntsvr2taahjgdpx77pe606epf37udfmnvuqpx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzypp3shk7edn43y5zfvdr0ftl8eq8l00zaknjqx3c9xuv7ja8ck60ql75rr4</id>
    
      <title type="html">follow-up patch adds WebSocket (WSS) transport — enables ...</title>
    
    <link rel="alternate" href="https://nostr.ae/nevent1qqsfkr7aup09jshu5u0jntsvr2taahjgdpx77pe606epf37udfmnvuqpx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzypp3shk7edn43y5zfvdr0ftl8eq8l00zaknjqx3c9xuv7ja8ck60ql75rr4" />
    <content type="html">
      In reply to &lt;a href=&#39;/nevent1qqsxwm9uu4rzhf2r87y6r005ltsar23dreyjq48kr9sk5mkmxl5pduch99x66&#39;&gt;nevent1q…9x66&lt;/a&gt;&lt;br/&gt;_________________________&lt;br/&gt;&lt;br/&gt;follow-up patch adds WebSocket (WSS) transport — enables browser/wasm use of nip05/namecoin and works on networks where raw TCP is blocked. same pinned certs, same RPC, just different framing.&lt;blockquote class=&#34;border-l-05rem border-l-strongpink border-solid&#34;&gt;&lt;div class=&#34;-ml-4 bg-gradient-to-r from-gray-100 dark:from-zinc-800 to-transparent mr-0 mt-0 mb-4 pl-4 pr-2 py-2&#34;&gt;quoting  &lt;span itemprop=&#34;mentions&#34; itemscope itemtype=&#34;https://schema.org/Article&#34;&gt;&lt;a itemprop=&#34;url&#34; href=&#34;/nevent1qqsytgl9hh9qkn5xp9l7xf2sjm4z4ksajns8uwnqpgu3ve3aktavxsqpp4mhxue69uhkummn9ekx7mqpzemhxue69uhhyetvv9ujuurjd9kkzmpwdejhgqg0waehxw309ahx7um5wghx6mmdqy28wumn8ghj7un9d3shjtnwva5hgtnyv4mqzynhwden5te0va5hgmn0wd68ytnrdaksygzrrp0dajm8tzfgyjc6x7jh70jq07779md8yqdrs2dcea9603d57qsflk5q&#34; class=&#34;bg-lavender dark:prose:text-neutral-50 dark:text-neutral-50 dark:bg-garnet px-1&#34;&gt;nevent1q…lk5q&lt;/a&gt;&lt;/span&gt; &lt;/div&gt; From d307275490adbc6b012399e2d5200c4b963a4ba6 Mon Sep 17 00:00:00 2001&lt;br/&gt;From: M &lt;m@Ms-MacBook-Pro.local&gt;&lt;br/&gt;Date: Sun, 19 Apr 2026 21:57:33 &#43;1000&lt;br/&gt;Subject: [PATCH] feat(nip05/namecoin): add WebSocket (WSS) transport&lt;br/&gt;&lt;br/&gt;Adds WS/WSS as an alternative transport to TCP&#43;TLS for ElectrumX&lt;br/&gt;name resolution. Enables browser/wasm use of nip05/namecoin and&lt;br/&gt;improves resilience on networks where raw TCP is blocked.&lt;br/&gt;&lt;br/&gt;New: Transport enum on ElectrumxServer, DefaultElectrumXServersWSS,&lt;br/&gt;WebSocket client via github.com/coder/websocket (zero transitive&lt;br/&gt;deps, already a transitive dep of nostrlib). Pinned-cert TLS trust&lt;br/&gt;is shared between TCP&#43;TLS and WSS \u2014 the public operators serve the&lt;br/&gt;same certificate on the adjacent ports (:50002 / :50004 on testls,&lt;br/&gt;:57002 / :57004 on nmc2.bitcoins.sk).&lt;br/&gt;&lt;br/&gt;Zero API break: the new Transport field on ElectrumxServer is a&lt;br/&gt;zero-valued enum that preserves the v1 UseSSL semantics. Every&lt;br/&gt;call site from the previous patch compiles and behaves unchanged.&lt;br/&gt;&lt;br/&gt;Tests: new unit test stands up an httptest WebSocket server via&lt;br/&gt;coder/websocket&#39;s accept helper and exercises the whole dial \u2192&lt;br/&gt;read \u2192 parse flow over WS framing, offline. Integration tests&lt;br/&gt;(build tag integration) add two WSS cases against the live public&lt;br/&gt;servers on :50004, mirroring the existing TCP test fixtures.&lt;br/&gt;&lt;br/&gt;Follow-up to the patch event at&lt;br/&gt;&lt;span itemprop=&#34;mentions&#34; itemscope itemtype=&#34;https://schema.org/Article&#34;&gt;&lt;a itemprop=&#34;url&#34; href=&#34;/nevent1qqs8yepuma694y6saym8ny4wtfzymlgu2htusvweyjzpamc0rgn8pyq&#34; class=&#34;bg-lavender dark:prose:text-neutral-50 dark:text-neutral-50 dark:bg-garnet px-1&#34;&gt;nevent1q…8pyq&lt;/a&gt;&lt;/span&gt;&lt;br/&gt;(original subpackage). Rebase-clean on top of it.&lt;br/&gt;&lt;br/&gt;Signed-off-by: M &lt;m@Ms-MacBook-Pro.local&gt;&lt;br/&gt;---&lt;br/&gt; nip05/namecoin/doc.go                        |   8 &#43;-&lt;br/&gt; nip05/namecoin/electrumx.go                  | 139 &#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;----&lt;br/&gt; nip05/namecoin/electrumx_integration_test.go |  50 &#43;&#43;&#43;&#43;&#43;&lt;br/&gt; nip05/namecoin/servers.go                    |  70 &#43;&#43;&#43;&#43;&#43;&#43;&#43;&lt;br/&gt; nip05/namecoin/websocket.go                  | 105 &#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&lt;br/&gt; nip05/namecoin/websocket_test.go             | 195 &#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&lt;br/&gt; 6 files changed, 524 insertions(&#43;), 43 deletions(-)&lt;br/&gt; create mode 100644 nip05/namecoin/websocket.go&lt;br/&gt; create mode 100644 nip05/namecoin/websocket_test.go&lt;br/&gt;&lt;br/&gt;diff --git a/nip05/namecoin/doc.go b/nip05/namecoin/doc.go&lt;br/&gt;index 7189a38..82bbce2 100644&lt;br/&gt;--- a/nip05/namecoin/doc.go&lt;br/&gt;&#43;&#43;&#43; b/nip05/namecoin/doc.go&lt;br/&gt;@@ -28,6 &#43;28,10 @@&lt;br/&gt; //	    // ...&lt;br/&gt; //	}&lt;br/&gt; //&lt;br/&gt;-// No external dependencies beyond the Go standard library and the&lt;br/&gt;-// fiatjaf.com/nostr types.&lt;br/&gt;&#43;// Two transports are supported: raw TCP&#43;TLS (the default, selected&lt;br/&gt;&#43;// by the zero value of ElectrumxServer.Transport) and WebSocket over&lt;br/&gt;&#43;// TLS (TransportWSS). The WSS path uses github.com/coder/websocket —&lt;br/&gt;&#43;// a zero-transitive-dep library that also compiles cleanly under&lt;br/&gt;&#43;// GOOS=js GOARCH=wasm, enabling browser use. Pinned-cert trust is&lt;br/&gt;&#43;// shared between the two transports.&lt;br/&gt; package namecoin&lt;br/&gt;diff --git a/nip05/namecoin/electrumx.go b/nip05/namecoin/electrumx.go&lt;br/&gt;index 4fbabdb..b7757d5 100644&lt;br/&gt;--- a/nip05/namecoin/electrumx.go&lt;br/&gt;&#43;&#43;&#43; b/nip05/namecoin/electrumx.go&lt;br/&gt;@@ -42,9 &#43;42,24 @@ var (&lt;br/&gt; 	ErrServersUnreachable = errors.New(&#34;namecoin: all ElectrumX servers unreachable&#34;)&lt;br/&gt; )&lt;br/&gt; &lt;br/&gt;&#43;// rpcConn is the transport-agnostic RPC connection abstraction. Both&lt;br/&gt;&#43;// TCP (newline-delimited) and WebSocket (pre-framed) implementations&lt;br/&gt;&#43;// satisfy it so that the name_show flow can be written once.&lt;br/&gt;&#43;type rpcConn interface {&lt;br/&gt;&#43;	// writeRequest serialises and sends a single JSON-RPC request.&lt;br/&gt;&#43;	// Implementations are responsible for any framing the wire format&lt;br/&gt;&#43;	// requires (TCP appends a newline, WS does not).&lt;br/&gt;&#43;	writeRequest(ctx context.Context, method string, params []any, id int64) error&lt;br/&gt;&#43;	// readResponse returns one JSON-RPC response, blocking until one&lt;br/&gt;&#43;	// is available or the context/deadline fires.&lt;br/&gt;&#43;	readResponse(ctx context.Context) (string, error)&lt;br/&gt;&#43;	// close releases the underlying transport.&lt;br/&gt;&#43;	close() error&lt;br/&gt;&#43;}&lt;br/&gt;&#43;&lt;br/&gt; // ElectrumClient is a minimal, query-only Namecoin ElectrumX client.&lt;br/&gt;-// It opens a short-lived TCP/TLS socket per request, which is plenty&lt;br/&gt;-// for interactive CLI use.&lt;br/&gt;&#43;// It opens a short-lived socket per request, which is plenty for&lt;br/&gt;&#43;// interactive CLI use.&lt;br/&gt; type ElectrumClient struct {&lt;br/&gt; 	ConnectTimeout time.Duration&lt;br/&gt; 	ReadTimeout    time.Duration&lt;br/&gt;@@ -68,18 &#43;83,22 @@ func (c *ElectrumClient) NameShow(ctx context.Context, identifier string, server&lt;br/&gt; 	if err != nil {&lt;br/&gt; 		return nil, err&lt;br/&gt; 	}&lt;br/&gt;-	defer conn.Close()&lt;br/&gt;&#43;	defer conn.close()&lt;br/&gt; &lt;br/&gt;-	_ = conn.SetDeadline(time.Now().Add(c.ReadTimeout))&lt;br/&gt;&#43;	// Give the whole request sequence a deadline. For TCP this is&lt;br/&gt;&#43;	// enforced by net.Conn.SetDeadline; for WS the per-call context&lt;br/&gt;&#43;	// carries the budget instead.&lt;br/&gt;&#43;	reqCtx, cancel := context.WithTimeout(ctx, c.ReadTimeout)&lt;br/&gt;&#43;	defer cancel()&lt;br/&gt; &lt;br/&gt;-	reader := bufio.NewReader(conn)&lt;br/&gt;&#43;	next := func() int64 { return c.requestID.Add(1) }&lt;br/&gt; &lt;br/&gt; 	// 1. Negotiate protocol version. The response is consumed and&lt;br/&gt; 	//    discarded — we only care that the socket is alive.&lt;br/&gt;-	if err := c.sendRPC(conn, &#34;server.version&#34;, []any{&#34;nak-namecoin/0.1&#34;, electrumProtocolVersion}); err != nil {&lt;br/&gt;&#43;	if err := conn.writeRequest(reqCtx, &#34;server.version&#34;, []any{&#34;nak-namecoin/0.1&#34;, electrumProtocolVersion}, next()); err != nil {&lt;br/&gt; 		return nil, err&lt;br/&gt; 	}&lt;br/&gt;-	if _, err := reader.ReadString(&#39;\n&#39;); err != nil {&lt;br/&gt;&#43;	if _, err := conn.readResponse(reqCtx); err != nil {&lt;br/&gt; 		return nil, fmt.Errorf(&#34;namecoin: read version response: %w&#34;, err)&lt;br/&gt; 	}&lt;br/&gt; &lt;br/&gt;@@ -88,10 &#43;107,10 @@ func (c *ElectrumClient) NameShow(ctx context.Context, identifier string, server&lt;br/&gt; 	scriptHash := electrumScriptHash(script)&lt;br/&gt; &lt;br/&gt; 	// 3. Fetch transaction history for that scripthash.&lt;br/&gt;-	if err := c.sendRPC(conn, &#34;blockchain.scripthash.get_history&#34;, []any{scriptHash}); err != nil {&lt;br/&gt;&#43;	if err := conn.writeRequest(reqCtx, &#34;blockchain.scripthash.get_history&#34;, []any{scriptHash}, next()); err != nil {&lt;br/&gt; 		return nil, err&lt;br/&gt; 	}&lt;br/&gt;-	histLine, err := reader.ReadString(&#39;\n&#39;)&lt;br/&gt;&#43;	histLine, err := conn.readResponse(reqCtx)&lt;br/&gt; 	if err != nil {&lt;br/&gt; 		return nil, fmt.Errorf(&#34;namecoin: read history response: %w&#34;, err)&lt;br/&gt; 	}&lt;br/&gt;@@ -108,19 &#43;127,19 @@ func (c *ElectrumClient) NameShow(ctx context.Context, identifier string, server&lt;br/&gt; 	latest := entries[len(entries)-1]&lt;br/&gt; &lt;br/&gt; 	// 4. Fetch the verbose transaction.&lt;br/&gt;-	if err := c.sendRPC(conn, &#34;blockchain.transaction.get&#34;, []any{latest.TxHash, true}); err != nil {&lt;br/&gt;&#43;	if err := conn.writeRequest(reqCtx, &#34;blockchain.transaction.get&#34;, []any{latest.TxHash, true}, next()); err != nil {&lt;br/&gt; 		return nil, err&lt;br/&gt; 	}&lt;br/&gt;-	txLine, err := reader.ReadString(&#39;\n&#39;)&lt;br/&gt;&#43;	txLine, err := conn.readResponse(reqCtx)&lt;br/&gt; 	if err != nil {&lt;br/&gt; 		return nil, fmt.Errorf(&#34;namecoin: read transaction response: %w&#34;, err)&lt;br/&gt; 	}&lt;br/&gt; &lt;br/&gt; 	// 5. Get the current block height so we can compute expiry.&lt;br/&gt;-	if err := c.sendRPC(conn, &#34;blockchain.headers.subscribe&#34;, []any{}); err != nil {&lt;br/&gt;&#43;	if err := conn.writeRequest(reqCtx, &#34;blockchain.headers.subscribe&#34;, []any{}, next()); err != nil {&lt;br/&gt; 		return nil, err&lt;br/&gt; 	}&lt;br/&gt;-	headerLine, _ := reader.ReadString(&#39;\n&#39;)&lt;br/&gt;&#43;	headerLine, _ := conn.readResponse(reqCtx)&lt;br/&gt; 	currentHeight := parseBlockHeight(headerLine)&lt;br/&gt; &lt;br/&gt; 	if currentHeight &gt; 0 &amp;&amp; latest.Height &gt; 0 {&lt;br/&gt;@@ -161,10 &#43;180,23 @@ func (c *ElectrumClient) NameShowWithFallback(ctx context.Context, identifier st&lt;br/&gt; 	return nil, fmt.Errorf(&#34;%w: last error: %v&#34;, ErrServersUnreachable, lastErr)&lt;br/&gt; }&lt;br/&gt; &lt;br/&gt;-// dial opens a TCP connection to the server, upgrading to TLS when&lt;br/&gt;-// UseSSL is set. Honours both context cancellation and our connect&lt;br/&gt;-// timeout, whichever fires first.&lt;br/&gt;-func (c *ElectrumClient) dial(ctx context.Context, server ElectrumxServer) (net.Conn, error) {&lt;br/&gt;&#43;// dial picks the right transport implementation based on the server&lt;br/&gt;&#43;// configuration and returns a ready-to-use rpcConn.&lt;br/&gt;&#43;func (c *ElectrumClient) dial(ctx context.Context, server ElectrumxServer) (rpcConn, error) {&lt;br/&gt;&#43;	switch effectiveTransport(server) {&lt;br/&gt;&#43;	case TransportTCPTLS, TransportTCP:&lt;br/&gt;&#43;		return c.dialTCP(ctx, server)&lt;br/&gt;&#43;	case TransportWSS, TransportWS:&lt;br/&gt;&#43;		return c.dialWebSocket(ctx, server)&lt;br/&gt;&#43;	default:&lt;br/&gt;&#43;		return nil, fmt.Errorf(&#34;namecoin: unknown transport %d&#34;, server.Transport)&lt;br/&gt;&#43;	}&lt;br/&gt;&#43;}&lt;br/&gt;&#43;&lt;br/&gt;&#43;// dialTCP opens a raw TCP connection to the server, upgrading to TLS&lt;br/&gt;&#43;// when the effective transport is TCPTLS. Honours both context&lt;br/&gt;&#43;// cancellation and our connect timeout, whichever fires first.&lt;br/&gt;&#43;func (c *ElectrumClient) dialTCP(ctx context.Context, server ElectrumxServer) (rpcConn, error) {&lt;br/&gt; 	dialer := &amp;net.Dialer{Timeout: c.ConnectTimeout}&lt;br/&gt; 	address := net.JoinHostPort(server.Host, strconv.Itoa(server.Port))&lt;br/&gt; &lt;br/&gt;@@ -173,34 &#43;205,41 @@ func (c *ElectrumClient) dial(ctx context.Context, server ElectrumxServer) (net.&lt;br/&gt; 		return nil, fmt.Errorf(&#34;namecoin: dial %s: %w&#34;, address, err)&lt;br/&gt; 	}&lt;br/&gt; &lt;br/&gt;-	if !server.UseSSL {&lt;br/&gt;-		return raw, nil&lt;br/&gt;&#43;	var nc net.Conn = raw&lt;br/&gt;&#43;	if effectiveTransport(server) == TransportTCPTLS {&lt;br/&gt;&#43;		cfg := tlsConfigFor(server)&lt;br/&gt;&#43;		tlsConn := tls.Client(raw, cfg)&lt;br/&gt;&#43;&lt;br/&gt;&#43;		// Run the handshake with a deadline so a silent server doesn&#39;t hang&lt;br/&gt;&#43;		// the call beyond what the caller asked for.&lt;br/&gt;&#43;		if deadline, ok := ctx.Deadline(); ok {&lt;br/&gt;&#43;			_ = tlsConn.SetDeadline(deadline)&lt;br/&gt;&#43;		} else {&lt;br/&gt;&#43;			_ = tlsConn.SetDeadline(time.Now().Add(c.ConnectTimeout))&lt;br/&gt;&#43;		}&lt;br/&gt;&#43;		if err := tlsConn.HandshakeContext(ctx); err != nil {&lt;br/&gt;&#43;			raw.Close()&lt;br/&gt;&#43;			return nil, fmt.Errorf(&#34;namecoin: TLS handshake with %s: %w&#34;, address, err)&lt;br/&gt;&#43;		}&lt;br/&gt;&#43;		// Clear the handshake deadline — we&#39;ll set fresh per-request&lt;br/&gt;&#43;		// deadlines below.&lt;br/&gt;&#43;		_ = tlsConn.SetDeadline(time.Time{})&lt;br/&gt;&#43;		nc = tlsConn&lt;br/&gt; 	}&lt;br/&gt; &lt;br/&gt;-	cfg := tlsConfigFor(server)&lt;br/&gt;-	tlsConn := tls.Client(raw, cfg)&lt;br/&gt;&#43;	_ = nc.SetDeadline(time.Now().Add(c.ReadTimeout))&lt;br/&gt;&#43;	return &amp;tcpRPCConn{conn: nc, reader: bufio.NewReader(nc)}, nil&lt;br/&gt;&#43;}&lt;br/&gt; &lt;br/&gt;-	// Run the handshake with a deadline so a silent server doesn&#39;t hang&lt;br/&gt;-	// the call beyond what the caller asked for.&lt;br/&gt;-	if deadline, ok := ctx.Deadline(); ok {&lt;br/&gt;-		_ = tlsConn.SetDeadline(deadline)&lt;br/&gt;-	} else {&lt;br/&gt;-		_ = tlsConn.SetDeadline(time.Now().Add(c.ConnectTimeout))&lt;br/&gt;-	}&lt;br/&gt;-	if err := tlsConn.HandshakeContext(ctx); err != nil {&lt;br/&gt;-		raw.Close()&lt;br/&gt;-		return nil, fmt.Errorf(&#34;namecoin: TLS handshake with %s: %w&#34;, address, err)&lt;br/&gt;-	}&lt;br/&gt;-	// Clear the handshake deadline — the caller sets its own read&lt;br/&gt;-	// deadline afterwards.&lt;br/&gt;-	_ = tlsConn.SetDeadline(time.Time{})&lt;br/&gt;-	return tlsConn, nil&lt;br/&gt;&#43;// tcpRPCConn is the newline-delimited JSON-RPC transport over raw&lt;br/&gt;&#43;// TCP or TCP&#43;TLS. This matches the shape every Electrum / ElectrumX&lt;br/&gt;&#43;// client has used for the last decade.&lt;br/&gt;&#43;type tcpRPCConn struct {&lt;br/&gt;&#43;	conn   net.Conn&lt;br/&gt;&#43;	reader *bufio.Reader&lt;br/&gt; }&lt;br/&gt; &lt;br/&gt;-// sendRPC writes a JSON-RPC 2.0 request (newline-terminated, per&lt;br/&gt;-// Electrum&#39;s line-delimited protocol) to the connection.&lt;br/&gt;-func (c *ElectrumClient) sendRPC(w net.Conn, method string, params []any) error {&lt;br/&gt;-	id := c.requestID.Add(1)&lt;br/&gt;&#43;func (t *tcpRPCConn) writeRequest(ctx context.Context, method string, params []any, id int64) error {&lt;br/&gt; 	payload := map[string]any{&lt;br/&gt; 		&#34;jsonrpc&#34;: &#34;2.0&#34;,&lt;br/&gt; 		&#34;id&#34;:      id,&lt;br/&gt;@@ -212,12 &#43;251,30 @@ func (c *ElectrumClient) sendRPC(w net.Conn, method string, params []any) error&lt;br/&gt; 		return fmt.Errorf(&#34;namecoin: marshal rpc request: %w&#34;, err)&lt;br/&gt; 	}&lt;br/&gt; 	encoded = append(encoded, &#39;\n&#39;)&lt;br/&gt;-	if _, err := w.Write(encoded); err != nil {&lt;br/&gt;&#43;	if deadline, ok := ctx.Deadline(); ok {&lt;br/&gt;&#43;		_ = t.conn.SetWriteDeadline(deadline)&lt;br/&gt;&#43;	}&lt;br/&gt;&#43;	if _, err := t.conn.Write(encoded); err != nil {&lt;br/&gt; 		return fmt.Errorf(&#34;namecoin: write rpc request: %w&#34;, err)&lt;br/&gt; 	}&lt;br/&gt; 	return nil&lt;br/&gt; }&lt;br/&gt; &lt;br/&gt;&#43;func (t *tcpRPCConn) readResponse(ctx context.Context) (string, error) {&lt;br/&gt;&#43;	if deadline, ok := ctx.Deadline(); ok {&lt;br/&gt;&#43;		_ = t.conn.SetReadDeadline(deadline)&lt;br/&gt;&#43;	}&lt;br/&gt;&#43;	line, err := t.reader.ReadString(&#39;\n&#39;)&lt;br/&gt;&#43;	if err != nil {&lt;br/&gt;&#43;		return &#34;&#34;, err&lt;br/&gt;&#43;	}&lt;br/&gt;&#43;	return line, nil&lt;br/&gt;&#43;}&lt;br/&gt;&#43;&lt;br/&gt;&#43;func (t *tcpRPCConn) close() error {&lt;br/&gt;&#43;	return t.conn.Close()&lt;br/&gt;&#43;}&lt;br/&gt;&#43;&lt;br/&gt; // historyEntry is one row of `blockchain.scripthash.get_history`.&lt;br/&gt; type historyEntry struct {&lt;br/&gt; 	TxHash string&lt;br/&gt;diff --git a/nip05/namecoin/electrumx_integration_test.go b/nip05/namecoin/electrumx_integration_test.go&lt;br/&gt;index 1458d4d..64ac17c 100644&lt;br/&gt;--- a/nip05/namecoin/electrumx_integration_test.go&lt;br/&gt;&#43;&#43;&#43; b/nip05/namecoin/electrumx_integration_test.go&lt;br/&gt;@@ -49,3 &#43;49,53 @@ func TestIntegration_ResolveAtTestlsBit(t *testing.T) {&lt;br/&gt; 		t.Errorf(&#34;m@testls.bit pubkey = %s, want %s&#34;, got, testlsMPubkey)&lt;br/&gt; 	}&lt;br/&gt; }&lt;br/&gt;&#43;&lt;br/&gt;&#43;// --- WSS (WebSocket over TLS) integration tests -----------------------&lt;br/&gt;&#43;//&lt;br/&gt;&#43;// These hit the same ElectrumX operators as the TCP tests above, but&lt;br/&gt;&#43;// over the WebSocket endpoints (ports 500xx&#43;2 on testls, 570xx&#43;2 on&lt;br/&gt;&#43;// nmc2.bitcoins.sk). Same pinned certs, same JSON-RPC protocol, just&lt;br/&gt;&#43;// different framing. The assertions match the TCP path because the&lt;br/&gt;&#43;// Namecoin blockchain is the source of truth.&lt;br/&gt;&#43;&lt;br/&gt;&#43;func TestIntegration_ResolveTestlsBit_WSS(t *testing.T) {&lt;br/&gt;&#43;	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)&lt;br/&gt;&#43;	defer cancel()&lt;br/&gt;&#43;&lt;br/&gt;&#43;	client := NewElectrumClient()&lt;br/&gt;&#43;	result, err := client.NameShowWithFallback(ctx, &#34;d/testls&#34;, DefaultElectrumXServersWSS)&lt;br/&gt;&#43;	if err != nil {&lt;br/&gt;&#43;		t.Fatalf(&#34;NameShowWithFallback(d/testls, WSS): %v&#34;, err)&lt;br/&gt;&#43;	}&lt;br/&gt;&#43;	if result == nil {&lt;br/&gt;&#43;		t.Fatal(&#34;nil result&#34;)&lt;br/&gt;&#43;	}&lt;br/&gt;&#43;	pk, _, err := extractNostrFromValue(result.Value, &amp;parsedIdentifier{&#34;d/testls&#34;, &#34;_&#34;, true})&lt;br/&gt;&#43;	if err != nil {&lt;br/&gt;&#43;		t.Fatalf(&#34;extractNostrFromValue: %v&#34;, err)&lt;br/&gt;&#43;	}&lt;br/&gt;&#43;	if pk != testlsRootPubkey {&lt;br/&gt;&#43;		t.Errorf(&#34;testls.bit (WSS) pubkey = %s, want %s&#34;, pk, testlsRootPubkey)&lt;br/&gt;&#43;	}&lt;br/&gt;&#43;}&lt;br/&gt;&#43;&lt;br/&gt;&#43;func TestIntegration_ResolveAtTestlsBit_WSS(t *testing.T) {&lt;br/&gt;&#43;	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)&lt;br/&gt;&#43;	defer cancel()&lt;br/&gt;&#43;&lt;br/&gt;&#43;	client := NewElectrumClient()&lt;br/&gt;&#43;	result, err := client.NameShowWithFallback(ctx, &#34;d/testls&#34;, DefaultElectrumXServersWSS)&lt;br/&gt;&#43;	if err != nil {&lt;br/&gt;&#43;		t.Fatalf(&#34;NameShowWithFallback(d/testls, WSS): %v&#34;, err)&lt;br/&gt;&#43;	}&lt;br/&gt;&#43;	if result == nil {&lt;br/&gt;&#43;		t.Fatal(&#34;nil result&#34;)&lt;br/&gt;&#43;	}&lt;br/&gt;&#43;	pk, _, err := extractNostrFromValue(result.Value, &amp;parsedIdentifier{&#34;d/testls&#34;, &#34;m&#34;, true})&lt;br/&gt;&#43;	if err != nil {&lt;br/&gt;&#43;		t.Fatalf(&#34;extractNostrFromValue: %v&#34;, err)&lt;br/&gt;&#43;	}&lt;br/&gt;&#43;	if pk != testlsMPubkey {&lt;br/&gt;&#43;		t.Errorf(&#34;m@testls.bit (WSS) pubkey = %s, want %s&#34;, pk, testlsMPubkey)&lt;br/&gt;&#43;	}&lt;br/&gt;&#43;}&lt;br/&gt;diff --git a/nip05/namecoin/servers.go b/nip05/namecoin/servers.go&lt;br/&gt;index b76c889..71c8551 100644&lt;br/&gt;--- a/nip05/namecoin/servers.go&lt;br/&gt;&#43;&#43;&#43; b/nip05/namecoin/servers.go&lt;br/&gt;@@ -1,15 &#43;1,59 @@&lt;br/&gt; package namecoin&lt;br/&gt; &lt;br/&gt;&#43;// Transport selects how an ElectrumX server is dialed. The zero value&lt;br/&gt;&#43;// is TransportTCPTLS, matching the traditional Electrum client path&lt;br/&gt;&#43;// and the behaviour shipped in v0.1.x. Callers that want WebSocket&lt;br/&gt;&#43;// (for example, browser/wasm targets or restricted networks that&lt;br/&gt;&#43;// block raw TCP) set this to TransportWSS.&lt;br/&gt;&#43;type Transport int&lt;br/&gt;&#43;&lt;br/&gt;&#43;const (&lt;br/&gt;&#43;	// TransportTCPTLS is raw TCP &#43; TLS with newline-delimited JSON-RPC.&lt;br/&gt;&#43;	// This is the default and what most Namecoin ElectrumX clients use.&lt;br/&gt;&#43;	TransportTCPTLS Transport = iota&lt;br/&gt;&#43;	// TransportTCP is plaintext TCP — rarely used in practice but&lt;br/&gt;&#43;	// supported for completeness / local testing.&lt;br/&gt;&#43;	TransportTCP&lt;br/&gt;&#43;	// TransportWSS is WebSocket over TLS, using the ElectrumX WS&lt;br/&gt;&#43;	// endpoint (ports 500xx&#43;2 on typical public servers). Messages&lt;br/&gt;&#43;	// are pre-framed by the WebSocket layer and MUST NOT carry a&lt;br/&gt;&#43;	// trailing newline.&lt;br/&gt;&#43;	TransportWSS&lt;br/&gt;&#43;	// TransportWS is plaintext WebSocket.&lt;br/&gt;&#43;	TransportWS&lt;br/&gt;&#43;)&lt;br/&gt;&#43;&lt;br/&gt; // ElectrumxServer is a single Namecoin ElectrumX endpoint.&lt;br/&gt; type ElectrumxServer struct {&lt;br/&gt; 	Host string&lt;br/&gt; 	Port int&lt;br/&gt; 	// UseSSL indicates TLS should be negotiated over the raw socket.&lt;br/&gt;&#43;	// Kept for backwards compat with v0.1.x callers. When Transport&lt;br/&gt;&#43;	// is the zero value, UseSSL selects between TransportTCPTLS&lt;br/&gt;&#43;	// (UseSSL=true) and TransportTCP (UseSSL=false).&lt;br/&gt; 	UseSSL bool&lt;br/&gt; 	// UsePinnedTrustStore enables the pinned-cert trust anchor bundle&lt;br/&gt; 	// for servers that present self-signed certificates. This is the&lt;br/&gt; 	// norm for the public Namecoin ElectrumX ecosystem.&lt;br/&gt; 	UsePinnedTrustStore bool&lt;br/&gt;&#43;	// Transport selects the dial transport. Zero value keeps v0.1.x&lt;br/&gt;&#43;	// semantics: if UseSSL is true it&#39;s TCP&#43;TLS, otherwise plain TCP.&lt;br/&gt;&#43;	// Set explicitly to TransportWSS / TransportWS for WebSocket.&lt;br/&gt;&#43;	Transport Transport&lt;br/&gt;&#43;}&lt;br/&gt;&#43;&lt;br/&gt;&#43;// effectiveTransport resolves the transport to use for a server,&lt;br/&gt;&#43;// reconciling the legacy UseSSL bool with the explicit Transport&lt;br/&gt;&#43;// field. The explicit Transport wins when non-zero.&lt;br/&gt;&#43;func effectiveTransport(s ElectrumxServer) Transport {&lt;br/&gt;&#43;	if s.Transport != TransportTCPTLS {&lt;br/&gt;&#43;		return s.Transport&lt;br/&gt;&#43;	}&lt;br/&gt;&#43;	// Zero value: fall back to UseSSL for v0.1.x compatibility.&lt;br/&gt;&#43;	if s.UseSSL {&lt;br/&gt;&#43;		return TransportTCPTLS&lt;br/&gt;&#43;	}&lt;br/&gt;&#43;	return TransportTCP&lt;br/&gt; }&lt;br/&gt; &lt;br/&gt; // DefaultElectrumXServers is the built-in list of public Namecoin&lt;br/&gt;@@ -24,11 &#43;68,37 @@ var DefaultElectrumXServers = []ElectrumxServer{&lt;br/&gt; 	{Host: &#34;46.229.238.187&#34;, Port: 57002, UseSSL: true, UsePinnedTrustStore: true},&lt;br/&gt; }&lt;br/&gt; &lt;br/&gt;&#43;// DefaultElectrumXServersWSS is the WSS-preferred server list. It&lt;br/&gt;&#43;// points at the same operators as DefaultElectrumXServers but uses&lt;br/&gt;&#43;// their WebSocket-over-TLS endpoints. Useful for:&lt;br/&gt;&#43;//&lt;br/&gt;&#43;//   - Browser / wasm targets, where raw TCP is unavailable and the&lt;br/&gt;&#43;//     only viable transport is the browser&#39;s WebSocket API (which&lt;br/&gt;&#43;//     `github.com/coder/websocket` targets natively when compiled&lt;br/&gt;&#43;//     with GOOS=js GOARCH=wasm).&lt;br/&gt;&#43;//   - Restricted networks that block the traditional ElectrumX ports&lt;br/&gt;&#43;//     but allow outbound HTTPS/WSS.&lt;br/&gt;&#43;//   - Environments that prefer WSS on policy grounds (aligns with the&lt;br/&gt;&#43;//     broader Nostr ecosystem, which is WSS-everywhere).&lt;br/&gt;&#43;//&lt;br/&gt;&#43;// Ports are the ElectrumX convention of ELECTRUM_PORT&#43;2 for the WSS&lt;br/&gt;&#43;// endpoint. Both listed operators expose these alongside their&lt;br/&gt;&#43;// TCP&#43;TLS ports, sharing the same TLS certificate.&lt;br/&gt;&#43;var DefaultElectrumXServersWSS = []ElectrumxServer{&lt;br/&gt;&#43;	{Host: &#34;electrumx.testls.space&#34;, Port: 50004, Transport: TransportWSS, UsePinnedTrustStore: true},&lt;br/&gt;&#43;	{Host: &#34;nmc2.bitcoins.sk&#34;, Port: 57004, Transport: TransportWSS, UsePinnedTrustStore: true},&lt;br/&gt;&#43;	{Host: &#34;46.229.238.187&#34;, Port: 57004, Transport: TransportWSS, UsePinnedTrustStore: true},&lt;br/&gt;&#43;}&lt;br/&gt;&#43;&lt;br/&gt; // PinnedElectrumXCerts is the PEM-encoded bundle of server&lt;br/&gt; // certificates we trust in addition to the system roots. These are&lt;br/&gt; // copied verbatim from the Kotlin Amethyst reference implementation.&lt;br/&gt; //&lt;br/&gt; // To refresh: `echo | openssl s_client -connect HOST:PORT 2&gt;/dev/null | openssl x509 -outform PEM`&lt;br/&gt;&#43;//&lt;br/&gt;&#43;// The same certificates are served on the WSS endpoints (adjacent&lt;br/&gt;&#43;// ports on the same host), so a single pinned bundle covers both&lt;br/&gt;&#43;// transports.&lt;br/&gt; var PinnedElectrumXCerts = []string{&lt;br/&gt; 	// electrumx.testls.space:50002 — expires 2027-05-04.&lt;br/&gt; 	// Also covers the i665jpwsq46zlsdbnj4axgzd3s56uzey5uhotsnxzsknzbn36jaddsid.onion:50002&lt;br/&gt;diff --git a/nip05/namecoin/websocket.go b/nip05/namecoin/websocket.go&lt;br/&gt;new file mode 100644&lt;br/&gt;index 0000000..5e849d7&lt;br/&gt;--- /dev/null&lt;br/&gt;&#43;&#43;&#43; b/nip05/namecoin/websocket.go&lt;br/&gt;@@ -0,0 &#43;1,105 @@&lt;br/&gt;&#43;package namecoin&lt;br/&gt;&#43;&lt;br/&gt;&#43;import (&lt;br/&gt;&#43;	&#34;context&#34;&lt;br/&gt;&#43;	&#34;encoding/json&#34;&lt;br/&gt;&#43;	&#34;fmt&#34;&lt;br/&gt;&#43;	&#34;net&#34;&lt;br/&gt;&#43;	&#34;net/http&#34;&lt;br/&gt;&#43;	&#34;strconv&#34;&lt;br/&gt;&#43;&lt;br/&gt;&#43;	&#34;github.com/coder/websocket&#34;&lt;br/&gt;&#43;)&lt;br/&gt;&#43;&lt;br/&gt;&#43;// wsReadLimit is the maximum size of a single WebSocket message we are&lt;br/&gt;&#43;// willing to accept from an ElectrumX server. Verbose transactions&lt;br/&gt;&#43;// from `blockchain.transaction.get` can legitimately run to tens of&lt;br/&gt;&#43;// kilobytes; 1 MiB is generous but keeps us safely bounded.&lt;br/&gt;&#43;const wsReadLimit int64 = 1 &lt;&lt; 20&lt;br/&gt;&#43;&lt;br/&gt;&#43;// dialWebSocket opens a WebSocket (plain or TLS) RPC connection to&lt;br/&gt;&#43;// the given ElectrumX server. It reuses the same pinned-cert TLS&lt;br/&gt;&#43;// config as the TCP&#43;TLS transport so operators who serve a single&lt;br/&gt;&#43;// self-signed certificate across both ports are handled identically.&lt;br/&gt;&#43;func (c *ElectrumClient) dialWebSocket(ctx context.Context, server ElectrumxServer) (rpcConn, error) {&lt;br/&gt;&#43;	transport := effectiveTransport(server)&lt;br/&gt;&#43;	scheme := &#34;ws&#34;&lt;br/&gt;&#43;	if transport == TransportWSS {&lt;br/&gt;&#43;		scheme = &#34;wss&#34;&lt;br/&gt;&#43;	}&lt;br/&gt;&#43;	address := net.JoinHostPort(server.Host, strconv.Itoa(server.Port))&lt;br/&gt;&#43;	url := scheme &#43; &#34;://&#34; &#43; address&lt;br/&gt;&#43;&lt;br/&gt;&#43;	// Bound the dial to our connect timeout, in addition to honouring&lt;br/&gt;&#43;	// any deadline on the caller&#39;s context.&lt;br/&gt;&#43;	dialCtx, cancel := context.WithTimeout(ctx, c.ConnectTimeout)&lt;br/&gt;&#43;	defer cancel()&lt;br/&gt;&#43;&lt;br/&gt;&#43;	opts := &amp;websocket.DialOptions{}&lt;br/&gt;&#43;	if transport == TransportWSS {&lt;br/&gt;&#43;		// Build an http.Transport that carries the same *tls.Config&lt;br/&gt;&#43;		// the TCP&#43;TLS path uses. The custom VerifyPeerCertificate is&lt;br/&gt;&#43;		// transport-agnostic, so pinned-cert trust continues to work&lt;br/&gt;&#43;		// over WebSocket&#39;s HTTP upgrade handshake.&lt;br/&gt;&#43;		tlsCfg := tlsConfigFor(server)&lt;br/&gt;&#43;		opts.HTTPClient = &amp;http.Client{&lt;br/&gt;&#43;			Timeout: c.ConnectTimeout &#43; c.ReadTimeout,&lt;br/&gt;&#43;			Transport: &amp;http.Transport{&lt;br/&gt;&#43;				TLSClientConfig:     tlsCfg,&lt;br/&gt;&#43;				TLSHandshakeTimeout: c.ConnectTimeout,&lt;br/&gt;&#43;			},&lt;br/&gt;&#43;		}&lt;br/&gt;&#43;	}&lt;br/&gt;&#43;&lt;br/&gt;&#43;	conn, _, err := websocket.Dial(dialCtx, url, opts)&lt;br/&gt;&#43;	if err != nil {&lt;br/&gt;&#43;		return nil, fmt.Errorf(&#34;namecoin: websocket dial %s: %w&#34;, url, err)&lt;br/&gt;&#43;	}&lt;br/&gt;&#43;	conn.SetReadLimit(wsReadLimit)&lt;br/&gt;&#43;&lt;br/&gt;&#43;	return &amp;wsRPCConn{conn: conn}, nil&lt;br/&gt;&#43;}&lt;br/&gt;&#43;&lt;br/&gt;&#43;// wsRPCConn is the WebSocket JSON-RPC transport. Unlike the TCP&lt;br/&gt;&#43;// variant, WebSocket messages are pre-framed by the protocol layer,&lt;br/&gt;&#43;// so requests MUST NOT carry a trailing newline and responses arrive&lt;br/&gt;&#43;// as whole JSON messages per frame.&lt;br/&gt;&#43;type wsRPCConn struct {&lt;br/&gt;&#43;	conn *websocket.Conn&lt;br/&gt;&#43;}&lt;br/&gt;&#43;&lt;br/&gt;&#43;func (w *wsRPCConn) writeRequest(ctx context.Context, method string, params []any, id int64) error {&lt;br/&gt;&#43;	payload := map[string]any{&lt;br/&gt;&#43;		&#34;jsonrpc&#34;: &#34;2.0&#34;,&lt;br/&gt;&#43;		&#34;id&#34;:      id,&lt;br/&gt;&#43;		&#34;method&#34;:  method,&lt;br/&gt;&#43;		&#34;params&#34;:  params,&lt;br/&gt;&#43;	}&lt;br/&gt;&#43;	encoded, err := json.Marshal(payload)&lt;br/&gt;&#43;	if err != nil {&lt;br/&gt;&#43;		return fmt.Errorf(&#34;namecoin: marshal rpc request: %w&#34;, err)&lt;br/&gt;&#43;	}&lt;br/&gt;&#43;	if err := w.conn.Write(ctx, websocket.MessageText, encoded); err != nil {&lt;br/&gt;&#43;		return fmt.Errorf(&#34;namecoin: write rpc request: %w&#34;, err)&lt;br/&gt;&#43;	}&lt;br/&gt;&#43;	return nil&lt;br/&gt;&#43;}&lt;br/&gt;&#43;&lt;br/&gt;&#43;func (w *wsRPCConn) readResponse(ctx context.Context) (string, error) {&lt;br/&gt;&#43;	_, data, err := w.conn.Read(ctx)&lt;br/&gt;&#43;	if err != nil {&lt;br/&gt;&#43;		return &#34;&#34;, err&lt;br/&gt;&#43;	}&lt;br/&gt;&#43;	return string(data), nil&lt;br/&gt;&#43;}&lt;br/&gt;&#43;&lt;br/&gt;&#43;func (w *wsRPCConn) close() error {&lt;br/&gt;&#43;	return w.conn.Close(websocket.StatusNormalClosure, &#34;&#34;)&lt;br/&gt;&#43;}&lt;br/&gt;&#43;&lt;br/&gt;&#43;// Compile-time interface checks — catch drift early if the rpcConn&lt;br/&gt;&#43;// signature ever evolves.&lt;br/&gt;&#43;var (&lt;br/&gt;&#43;	_ rpcConn = (*tcpRPCConn)(nil)&lt;br/&gt;&#43;	_ rpcConn = (*wsRPCConn)(nil)&lt;br/&gt;&#43;)&lt;br/&gt;diff --git a/nip05/namecoin/websocket_test.go b/nip05/namecoin/websocket_test.go&lt;br/&gt;new file mode 100644&lt;br/&gt;index 0000000..ad5682a&lt;br/&gt;--- /dev/null&lt;br/&gt;&#43;&#43;&#43; b/nip05/namecoin/websocket_test.go&lt;br/&gt;@@ -0,0 &#43;1,195 @@&lt;br/&gt;&#43;package namecoin&lt;br/&gt;&#43;&lt;br/&gt;&#43;import (&lt;br/&gt;&#43;	&#34;context&#34;&lt;br/&gt;&#43;	&#34;encoding/json&#34;&lt;br/&gt;&#43;	&#34;net/http&#34;&lt;br/&gt;&#43;	&#34;net/http/httptest&#34;&lt;br/&gt;&#43;	&#34;net/url&#34;&lt;br/&gt;&#43;	&#34;strconv&#34;&lt;br/&gt;&#43;	&#34;strings&#34;&lt;br/&gt;&#43;	&#34;testing&#34;&lt;br/&gt;&#43;	&#34;time&#34;&lt;br/&gt;&#43;&lt;br/&gt;&#43;	&#34;github.com/coder/websocket&#34;&lt;br/&gt;&#43;)&lt;br/&gt;&#43;&lt;br/&gt;&#43;// fakeElectrumXWSHandler returns an http.Handler that upgrades incoming&lt;br/&gt;&#43;// connections to WebSocket and serves canned JSON-RPC responses for the&lt;br/&gt;&#43;// sequence the ElectrumClient issues during NameShow.&lt;br/&gt;&#43;//&lt;br/&gt;&#43;// The response ordering mirrors the real RPC sequence:&lt;br/&gt;&#43;//   1. server.version               → any non-error result&lt;br/&gt;&#43;//   2. blockchain.scripthash.get_history → one entry pointing at a fake txid&lt;br/&gt;&#43;//   3. blockchain.transaction.get   → one vout with a NAME_UPDATE that&lt;br/&gt;&#43;//                                     matches the requested name and a&lt;br/&gt;&#43;//                                     value whose &#34;nostr&#34; field is a&lt;br/&gt;&#43;//                                     known hex pubkey&lt;br/&gt;&#43;//   4. blockchain.headers.subscribe → a height far enough below our&lt;br/&gt;&#43;//                                     fake tx height that the name is&lt;br/&gt;&#43;//                                     well within its expiry window&lt;br/&gt;&#43;//&lt;br/&gt;&#43;// This exercises the whole WS dial → read → parse path end-to-end&lt;br/&gt;&#43;// without hitting the network.&lt;br/&gt;&#43;func fakeElectrumXWSHandler(t *testing.T, identifier, pubkeyHex string) http.Handler {&lt;br/&gt;&#43;	// Build the NAME_UPDATE script hex we want the client to parse&lt;br/&gt;&#43;	// back out of the &#34;transaction&#34;.&lt;br/&gt;&#43;	value := `{&#34;nostr&#34;:&#34;` &#43; pubkeyHex &#43; `&#34;}`&lt;br/&gt;&#43;	script := []byte{opNameUpdate}&lt;br/&gt;&#43;	script = append(script, pushData([]byte(identifier))...)&lt;br/&gt;&#43;	script = append(script, pushData([]byte(value))...)&lt;br/&gt;&#43;	script = append(script, op2Drop, opDrop)&lt;br/&gt;&#43;	// Stub P2PKH-ish tail so the parser&#39;s &#34;we don&#39;t care what follows&lt;br/&gt;&#43;	// the DROPs&#34; assumption holds.&lt;br/&gt;&#43;	script = append(script, 0x76, 0xa9, 0x14)&lt;br/&gt;&#43;	scriptHex := hexString(script)&lt;br/&gt;&#43;&lt;br/&gt;&#43;	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {&lt;br/&gt;&#43;		conn, err := websocket.Accept(w, r, nil)&lt;br/&gt;&#43;		if err != nil {&lt;br/&gt;&#43;			t.Logf(&#34;ws accept: %v&#34;, err)&lt;br/&gt;&#43;			return&lt;br/&gt;&#43;		}&lt;br/&gt;&#43;		defer conn.Close(websocket.StatusInternalError, &#34;test server shutting down&#34;)&lt;br/&gt;&#43;&lt;br/&gt;&#43;		ctx := r.Context()&lt;br/&gt;&#43;&lt;br/&gt;&#43;		respond := func(id any, result any) {&lt;br/&gt;&#43;			payload := map[string]any{&lt;br/&gt;&#43;				&#34;jsonrpc&#34;: &#34;2.0&#34;,&lt;br/&gt;&#43;				&#34;id&#34;:      id,&lt;br/&gt;&#43;				&#34;result&#34;:  result,&lt;br/&gt;&#43;			}&lt;br/&gt;&#43;			raw, _ := json.Marshal(payload)&lt;br/&gt;&#43;			if err := conn.Write(ctx, websocket.MessageText, raw); err != nil {&lt;br/&gt;&#43;				t.Logf(&#34;ws write: %v&#34;, err)&lt;br/&gt;&#43;			}&lt;br/&gt;&#43;		}&lt;br/&gt;&#43;&lt;br/&gt;&#43;		for {&lt;br/&gt;&#43;			_, data, err := conn.Read(ctx)&lt;br/&gt;&#43;			if err != nil {&lt;br/&gt;&#43;				return&lt;br/&gt;&#43;			}&lt;br/&gt;&#43;			var req struct {&lt;br/&gt;&#43;				ID     any    `json:&#34;id&#34;`&lt;br/&gt;&#43;				Method string `json:&#34;method&#34;`&lt;br/&gt;&#43;			}&lt;br/&gt;&#43;			if err := json.Unmarshal(data, &amp;req); err != nil {&lt;br/&gt;&#43;				t.Logf(&#34;ws request parse: %v&#34;, err)&lt;br/&gt;&#43;				return&lt;br/&gt;&#43;			}&lt;br/&gt;&#43;			switch req.Method {&lt;br/&gt;&#43;			case &#34;server.version&#34;:&lt;br/&gt;&#43;				respond(req.ID, []string{&#34;ElectrumX 1.16.0&#34;, electrumProtocolVersion})&lt;br/&gt;&#43;			case &#34;blockchain.scripthash.get_history&#34;:&lt;br/&gt;&#43;				respond(req.ID, []map[string]any{&lt;br/&gt;&#43;					{&#34;tx_hash&#34;: &#34;deadbeefcafebabe&#34;, &#34;height&#34;: 600000},&lt;br/&gt;&#43;				})&lt;br/&gt;&#43;			case &#34;blockchain.transaction.get&#34;:&lt;br/&gt;&#43;				respond(req.ID, map[string]any{&lt;br/&gt;&#43;					&#34;txid&#34;: &#34;deadbeefcafebabe&#34;,&lt;br/&gt;&#43;					&#34;vout&#34;: []map[string]any{&lt;br/&gt;&#43;						{&#34;scriptPubKey&#34;: map[string]any{&#34;hex&#34;: scriptHex}},&lt;br/&gt;&#43;					},&lt;br/&gt;&#43;				})&lt;br/&gt;&#43;			case &#34;blockchain.headers.subscribe&#34;:&lt;br/&gt;&#43;				respond(req.ID, map[string]any{&#34;height&#34;: 600010})&lt;br/&gt;&#43;			default:&lt;br/&gt;&#43;				respond(req.ID, nil)&lt;br/&gt;&#43;			}&lt;br/&gt;&#43;		}&lt;br/&gt;&#43;	})&lt;br/&gt;&#43;}&lt;br/&gt;&#43;&lt;br/&gt;&#43;func hexString(b []byte) string {&lt;br/&gt;&#43;	const hexDigits = &#34;0123456789abcdef&#34;&lt;br/&gt;&#43;	out := make([]byte, 0, len(b)*2)&lt;br/&gt;&#43;	for _, v := range b {&lt;br/&gt;&#43;		out = append(out, hexDigits[v&gt;&gt;4], hexDigits[v&amp;0x0f])&lt;br/&gt;&#43;	}&lt;br/&gt;&#43;	return string(out)&lt;br/&gt;&#43;}&lt;br/&gt;&#43;&lt;br/&gt;&#43;func TestWebSocketTransport_NameShow(t *testing.T) {&lt;br/&gt;&#43;	identifier := &#34;d/wsfake&#34;&lt;br/&gt;&#43;	pubkey := &#34;aaaa000000000000000000000000000000000000000000000000000000000001&#34;&lt;br/&gt;&#43;&lt;br/&gt;&#43;	ts := httptest.NewServer(fakeElectrumXWSHandler(t, identifier, pubkey))&lt;br/&gt;&#43;	defer ts.Close()&lt;br/&gt;&#43;&lt;br/&gt;&#43;	// Parse the httptest URL so we can point the client at it as&lt;br/&gt;&#43;	// host&#43;port with the plain-WS transport. httptest.Server is HTTP,&lt;br/&gt;&#43;	// so TransportWS (not WSS) is what we want here — it verifies the&lt;br/&gt;&#43;	// framing/routing independently of the TLS plumbing.&lt;br/&gt;&#43;	u, err := url.Parse(ts.URL)&lt;br/&gt;&#43;	if err != nil {&lt;br/&gt;&#43;		t.Fatal(err)&lt;br/&gt;&#43;	}&lt;br/&gt;&#43;	port, err := strconv.Atoi(u.Port())&lt;br/&gt;&#43;	if err != nil {&lt;br/&gt;&#43;		t.Fatal(err)&lt;br/&gt;&#43;	}&lt;br/&gt;&#43;&lt;br/&gt;&#43;	srv := ElectrumxServer{&lt;br/&gt;&#43;		Host:      u.Hostname(),&lt;br/&gt;&#43;		Port:      port,&lt;br/&gt;&#43;		Transport: TransportWS,&lt;br/&gt;&#43;	}&lt;br/&gt;&#43;&lt;br/&gt;&#43;	client := NewElectrumClient()&lt;br/&gt;&#43;	client.ConnectTimeout = 3 * time.Second&lt;br/&gt;&#43;	client.ReadTimeout = 5 * time.Second&lt;br/&gt;&#43;&lt;br/&gt;&#43;	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)&lt;br/&gt;&#43;	defer cancel()&lt;br/&gt;&#43;&lt;br/&gt;&#43;	result, err := client.NameShow(ctx, identifier, srv)&lt;br/&gt;&#43;	if err != nil {&lt;br/&gt;&#43;		t.Fatalf(&#34;NameShow over WS: %v&#34;, err)&lt;br/&gt;&#43;	}&lt;br/&gt;&#43;	if result == nil {&lt;br/&gt;&#43;		t.Fatal(&#34;NameShow returned nil result&#34;)&lt;br/&gt;&#43;	}&lt;br/&gt;&#43;	if result.Name != identifier {&lt;br/&gt;&#43;		t.Errorf(&#34;name = %q, want %q&#34;, result.Name, identifier)&lt;br/&gt;&#43;	}&lt;br/&gt;&#43;	if !strings.Contains(result.Value, pubkey) {&lt;br/&gt;&#43;		t.Errorf(&#34;value = %q, want to contain %q&#34;, result.Value, pubkey)&lt;br/&gt;&#43;	}&lt;br/&gt;&#43;}&lt;br/&gt;&#43;&lt;br/&gt;&#43;func TestEffectiveTransport(t *testing.T) {&lt;br/&gt;&#43;	cases := []struct {&lt;br/&gt;&#43;		in   ElectrumxServer&lt;br/&gt;&#43;		want Transport&lt;br/&gt;&#43;	}{&lt;br/&gt;&#43;		// v0.1.x shape: UseSSL=true, Transport unset → TCPTLS.&lt;br/&gt;&#43;		{ElectrumxServer{UseSSL: true}, TransportTCPTLS},&lt;br/&gt;&#43;		// v0.1.x shape: UseSSL=false, Transport unset → plain TCP.&lt;br/&gt;&#43;		{ElectrumxServer{UseSSL: false}, TransportTCP},&lt;br/&gt;&#43;		// Explicit Transport wins over UseSSL when non-zero.&lt;br/&gt;&#43;		{ElectrumxServer{UseSSL: true, Transport: TransportWSS}, TransportWSS},&lt;br/&gt;&#43;		{ElectrumxServer{UseSSL: false, Transport: TransportWS}, TransportWS},&lt;br/&gt;&#43;		{ElectrumxServer{UseSSL: false, Transport: TransportTCPTLS}, TransportTCP}, // TCPTLS is zero value; falls back to UseSSL&lt;br/&gt;&#43;	}&lt;br/&gt;&#43;	for i, tc := range cases {&lt;br/&gt;&#43;		if got := effectiveTransport(tc.in); got != tc.want {&lt;br/&gt;&#43;			t.Errorf(&#34;case %d: effectiveTransport(%&#43;v) = %d, want %d&#34;, i, tc.in, got, tc.want)&lt;br/&gt;&#43;		}&lt;br/&gt;&#43;	}&lt;br/&gt;&#43;}&lt;br/&gt;&#43;&lt;br/&gt;&#43;func TestDefaultElectrumXServersWSS(t *testing.T) {&lt;br/&gt;&#43;	if len(DefaultElectrumXServersWSS) == 0 {&lt;br/&gt;&#43;		t.Fatal(&#34;DefaultElectrumXServersWSS is empty&#34;)&lt;br/&gt;&#43;	}&lt;br/&gt;&#43;	for _, srv := range DefaultElectrumXServersWSS {&lt;br/&gt;&#43;		if srv.Transport != TransportWSS {&lt;br/&gt;&#43;			t.Errorf(&#34;%s:%d has Transport=%d, want WSS&#34;, srv.Host, srv.Port, srv.Transport)&lt;br/&gt;&#43;		}&lt;br/&gt;&#43;		if !srv.UsePinnedTrustStore {&lt;br/&gt;&#43;			t.Errorf(&#34;%s:%d: WSS default servers must pin the trust store&#34;, srv.Host, srv.Port)&lt;br/&gt;&#43;		}&lt;br/&gt;&#43;	}&lt;br/&gt;&#43;}&lt;br/&gt;-- &lt;br/&gt;2.50.1 (Apple Git-155)&lt;br/&gt;&lt;br/&gt; &lt;/blockquote&gt;
    </content>
    <updated>2026-04-19T12:00:28Z</updated>
  </entry>

  <entry>
    <id>https://nostr.ae/nevent1qqsxwm9uu4rzhf2r87y6r005ltsar23dreyjq48kr9sk5mkmxl5pducpx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzypp3shk7edn43y5zfvdr0ftl8eq8l00zaknjqx3c9xuv7ja8ck60qmszfea</id>
    
      <title type="html">@npub180c…h6w6 re https://github.com/fiatjaf/nak/pull/123 — ...</title>
    
    <link rel="alternate" href="https://nostr.ae/nevent1qqsxwm9uu4rzhf2r87y6r005ltsar23dreyjq48kr9sk5mkmxl5pducpx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzypp3shk7edn43y5zfvdr0ftl8eq8l00zaknjqx3c9xuv7ja8ck60qmszfea" />
    <content type="html">
      In reply to &lt;a href=&#39;/naddr1qqyxummnw3exc6tzqgsrhuxx8l9ex335q7he0f09aej04zpazpl0ne2cgukyawd24mayt8grqsqqqaue48cxua&#39;&gt;naddr1qq…cxua&lt;/a&gt;&lt;br/&gt;_________________________&lt;br/&gt;&lt;br/&gt;&lt;span itemprop=&#34;mentions&#34; itemscope itemtype=&#34;https://schema.org/Person&#34;&gt;&lt;a itemprop=&#34;url&#34; href=&#34;/npub180cvv07tjdrrgpa0j7j7tmnyl2yr6yr7l8j4s3evf6u64th6gkwsyjh6w6&#34; class=&#34;bg-lavender dark:prose:text-neutral-50 dark:text-neutral-50 dark:bg-garnet px-1&#34;&gt;&lt;span&gt;fiatjaf&lt;/span&gt; (&lt;span class=&#34;italic&#34;&gt;npub180c…h6w6&lt;/span&gt;)&lt;/a&gt;&lt;/span&gt; re &lt;a href=&#34;https://github.com/fiatjaf/nak/pull/123&#34;&gt;https://github.com/fiatjaf/nak/pull/123&lt;/a&gt; — posted a NIP-34 patch event adding a proposed nip05/namecoin subpackage to nostrlib, addressed to you. Patch: nostr:nevent1qqs8yepuma694y6saym8ny4wtfzymlgu2htusvweyjzpamc0rgn8pyqpz3mhxue69uhhyetvv9ujumn8d96zuer9wcq3yamnwvaz7tm8d96xummnw3ezucm0d5q3gamnwvaz7tmjv4kxz7fwv3sk6atn9e5k7q3qgvv9ahktvavf9qjtrgm62le7gplmmchd5usp5wpfhr85hf79kncq8jdtz6. GitHub mirror: &lt;a href=&#34;https://github.com/mstrofnone/nostrlib-nip05-namecoin&#34;&gt;https://github.com/mstrofnone/nostrlib-nip05-namecoin&lt;/a&gt;
    </content>
    <updated>2026-04-19T11:25:10Z</updated>
  </entry>

  <entry>
    <id>https://nostr.ae/nevent1qqsr0ghjpelngek9ptmpqedqpte62mqda8t2rna6kn79q6g042arnnqpx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzyqa5s7p9xp63tekeqdcs4u3c75jkdhcsqhrllw0fvwt97mxv9lac5y8j9xe</id>
    
      <title type="html">Interestingly. This picture has just reminded me that the phrase ...</title>
    
    <link rel="alternate" href="https://nostr.ae/nevent1qqsr0ghjpelngek9ptmpqedqpte62mqda8t2rna6kn79q6g042arnnqpx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzyqa5s7p9xp63tekeqdcs4u3c75jkdhcsqhrllw0fvwt97mxv9lac5y8j9xe" />
    <content type="html">
      In reply to &lt;a href=&#39;/nevent1qqstjq0w2yjyansa2xes5e2h8v9f5kxry4fnmahw5zzx62gwu0clmgcpzamhxue69uhhyetvv9ujuurjd9kkzmpwdejhgtcpv79pu&#39;&gt;nevent1q…79pu&lt;/a&gt;&lt;br/&gt;_________________________&lt;br/&gt;&lt;br/&gt;Interestingly. This picture has just reminded me that the phrase &amp;#34;Up to scrach&amp;#34; comes from boxing. Two lines were scratched on the floor, if either boxer didn&amp;#39;t return to it, at the start of the next round, he&amp;#39;d lose the fight because he wasn&amp;#39;t &amp;#34;Up to scratch&amp;#34;.
    </content>
    <updated>2026-04-17T19:49:44Z</updated>
  </entry>

  <entry>
    <id>https://nostr.ae/nevent1qqsghshk037qnua7wwgyqkyd3ptkwrjsnq7af2z2llqzzrhkct0k8sqpx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzypqau9m35qcc50vmntul7xsv83aeq6r8efk5uh2rxk5tl9str5eyxu737vs</id>
    
      <title type="html">looks like you might be searching just &amp;#34;follows&amp;#34; or ...</title>
    
    <link rel="alternate" href="https://nostr.ae/nevent1qqsghshk037qnua7wwgyqkyd3ptkwrjsnq7af2z2llqzzrhkct0k8sqpx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzypqau9m35qcc50vmntul7xsv83aeq6r8efk5uh2rxk5tl9str5eyxu737vs" />
    <content type="html">
      In reply to &lt;a href=&#39;/nevent1qqsz3wxhvkeu2m5p7danxx9nwnqmwmvk7vx3env6t4f38u6kg8l98rqpzdmhxue69uhk7enxvd5xz6tw9ec82c304vzqc5&#39;&gt;nevent1q…zqc5&lt;/a&gt;&lt;br/&gt;_________________________&lt;br/&gt;&lt;br/&gt;looks like you might be searching just &amp;#34;follows&amp;#34; or &amp;#34;following&amp;#34;&lt;br/&gt;
    </content>
    <updated>2026-04-14T22:49:35Z</updated>
  </entry>

  <entry>
    <id>https://nostr.ae/nevent1qqsrwpue9zj8w678yp0t3vjg0833vnqc57jgxmfcap8schh3xxn883gpx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzyrwkvn27gqtyxw5v660sqkhpfqyqgdgh3x6emed0qcnkmejkx0f3jtw6dn0</id>
    
      <title>Nostr event nevent1qqsrwpue9zj8w678yp0t3vjg0833vnqc57jgxmfcap8schh3xxn883gpx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzyrwkvn27gqtyxw5v660sqkhpfqyqgdgh3x6emed0qcnkmejkx0f3jtw6dn0</title>
    
    <link rel="alternate" href="https://nostr.ae/nevent1qqsrwpue9zj8w678yp0t3vjg0833vnqc57jgxmfcap8schh3xxn883gpx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzyrwkvn27gqtyxw5v660sqkhpfqyqgdgh3x6emed0qcnkmejkx0f3jtw6dn0" />
    <content type="html">
      test
    </content>
    <updated>2026-04-11T08:04:13Z</updated>
  </entry>

  <entry>
    <id>https://nostr.ae/nevent1qqsz9chzffquugjhzuyda7a8q0gy4w3j9079u86mxnkw3c7n8f98xlqpx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzypqau9m35qcc50vmntul7xsv83aeq6r8efk5uh2rxk5tl9str5eyxwvrwx3</id>
    
      <title type="html">#bot #blocked</title>
    
    <link rel="alternate" href="https://nostr.ae/nevent1qqsz9chzffquugjhzuyda7a8q0gy4w3j9079u86mxnkw3c7n8f98xlqpx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzypqau9m35qcc50vmntul7xsv83aeq6r8efk5uh2rxk5tl9str5eyxwvrwx3" />
    <content type="html">
      In reply to &lt;a href=&#39;/nevent1qqsvd55el8kay27j4zz9lxy9eqf68rfrkjfvn6ztwr2mnukdgrhcm5qppemhxue69uhkummn9ekx7mp04vk2vx&#39;&gt;nevent1q…k2vx&lt;/a&gt;&lt;br/&gt;_________________________&lt;br/&gt;&lt;br/&gt;#bot #blocked
    </content>
    <updated>2026-04-08T15:06:40Z</updated>
  </entry>

  <entry>
    <id>https://nostr.ae/nevent1qqsfhcwqup5lz8nsv00mctlghe94p9l97ljks85xnej0ahza4wgg8qcpx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzyrwkvn27gqtyxw5v660sqkhpfqyqgdgh3x6emed0qcnkmejkx0f3j9ywfyx</id>
    
      <title type="html">Nein, aber alle Bürger müssen im Verteidigungsfall kämpfen o. ...</title>
    
    <link rel="alternate" href="https://nostr.ae/nevent1qqsfhcwqup5lz8nsv00mctlghe94p9l97ljks85xnej0ahza4wgg8qcpx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzyrwkvn27gqtyxw5v660sqkhpfqyqgdgh3x6emed0qcnkmejkx0f3j9ywfyx" />
    <content type="html">
      In reply to &lt;a href=&#39;/nevent1qqspwx9maln9g6ty394h5zlv6029l8k2v90w52t00nqqnk4xry85adgprdmhxue69uhhg6r9vehhyetnwshxummnw3erztnrdakj7ggczsf&#39;&gt;nevent1q…czsf&lt;/a&gt;&lt;br/&gt;_________________________&lt;br/&gt;&lt;br/&gt;Nein, aber alle Bürger müssen im Verteidigungsfall kämpfen o. Ä. wie Feuerwehr, Technisches Hilfswerk, Küstenwache, etc. (Außer sie haben eine religiöse Ausnahme oder sowas, und dann müssen sie einen anderen Dienst leisten.)&lt;br/&gt;&lt;br/&gt;Wehrdienst war immer Vorbereitung, nicht Voraussetzung. Aber das Pausieren davon hat alle es vergessen lassen. Jetzt hat man halt gesagt:&lt;br/&gt;&lt;br/&gt; &lt;img src=&#34;https://media.tenor.com/jPNqiiipxwgAAAAC/apple.gif&#34;&gt; 
    </content>
    <updated>2026-04-04T18:12:51Z</updated>
  </entry>

  <entry>
    <id>https://nostr.ae/nevent1qqsqqqppnza3au0x0jckqgnvsc684sd65w892xtpsvp2w8vdqqc0umspx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzyzmjwnfgu05c80mjpk6tfgf2x86u0mexyvsdqhp9ajgy3xkfjc5vk49gu4e</id>
    
      <title type="html">Correct. If you choose to install an app for the first time, you ...</title>
    
    <link rel="alternate" href="https://nostr.ae/nevent1qqsqqqppnza3au0x0jckqgnvsc684sd65w892xtpsvp2w8vdqqc0umspx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzyzmjwnfgu05c80mjpk6tfgf2x86u0mexyvsdqhp9ajgy3xkfjc5vk49gu4e" />
    <content type="html">
      Correct. If you choose to install an app for the first time, you will get an &amp;#34;are you sure?&amp;#34; type of message that shows whether anyone in your web of trust follows the publisher of the app, but that doesn&amp;#39;t show up at all for updating.&lt;br/&gt;&lt;br/&gt;It would be nice if &lt;span itemprop=&#34;mentions&#34; itemscope itemtype=&#34;https://schema.org/Person&#34;&gt;&lt;a itemprop=&#34;url&#34; href=&#34;/nprofile1qqs83nn04fezvsu89p8xg7axjwye2u67errat3dx2um725fs7qnrqlgzqtdq0&#34; class=&#34;bg-lavender dark:prose:text-neutral-50 dark:text-neutral-50 dark:bg-garnet px-1&#34;&gt;&lt;span&gt;Zapstore&lt;/span&gt; (&lt;span class=&#34;italic&#34;&gt;nprofile…tdq0&lt;/span&gt;)&lt;/a&gt;&lt;/span&gt; showed WoT on the app information page prior to tapping &amp;#34;install.&amp;#34;
    </content>
    <updated>2026-04-01T16:21:21Z</updated>
  </entry>

  <entry>
    <id>https://nostr.ae/nevent1qqsp3uz6y7ckmcwq486n4j0ltpdh6dtqh8hnff025f0eez7edl8msxspx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzyrsjkknaluyyltza0xqp9h2thqtyxxyzcpd7zcwek9uuqy2q470cg3u7uvp</id>
    
      <title type="html">A full account export feature would be essential should a factory ...</title>
    
    <link rel="alternate" href="https://nostr.ae/nevent1qqsp3uz6y7ckmcwq486n4j0ltpdh6dtqh8hnff025f0eez7edl8msxspx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzyrsjkknaluyyltza0xqp9h2thqtyxxyzcpd7zcwek9uuqy2q470cg3u7uvp" />
    <content type="html">
      In reply to &lt;a href=&#39;/nevent1qqsqqqrgzfnrzamwwctl5pxmx5t8we726nv6ku7e34ep2z7w4g7wpfgppemhxue69uhkummn9ekx7mp0sh8v7p&#39;&gt;nevent1q…8v7p&lt;/a&gt;&lt;br/&gt;_________________________&lt;br/&gt;&lt;br/&gt;A full account export feature would be essential should a factory reset be required following an app crash.
    </content>
    <updated>2026-03-31T14:48:34Z</updated>
  </entry>

  <entry>
    <id>https://nostr.ae/nevent1qqsp5y7csv74rsck6rgddrh2xpvhrevya5da0h6e09kz4vvls4lwdlspx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzyqrx8x3cdjwpq9ppwc3ve085pyyvfudqcvlz87xk668540m9t78hzuajxud</id>
    
      <title type="html">Yay Just published @npub1kds…nsze site as #nsite with nsyte ...</title>
    
    <link rel="alternate" href="https://nostr.ae/nevent1qqsp5y7csv74rsck6rgddrh2xpvhrevya5da0h6e09kz4vvls4lwdlspx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzyqrx8x3cdjwpq9ppwc3ve085pyyvfudqcvlz87xk668540m9t78hzuajxud" />
    <content type="html">
      In reply to &lt;a href=&#39;/nevent1qqsdm7p20ae3ad6307k5qtky5ugrgztkk7ysxlwq0zw0xn3s8g4ralgpzemhxue69uhhyetvv9ujumt0wd68ytnsw43z7wm7fqs&#39;&gt;nevent1q…7fqs&lt;/a&gt;&lt;br/&gt;_________________________&lt;br/&gt;&lt;br/&gt;Yay&lt;br/&gt;&lt;br/&gt;Just published &lt;span itemprop=&#34;mentions&#34; itemscope itemtype=&#34;https://schema.org/Person&#34;&gt;&lt;a itemprop=&#34;url&#34; href=&#34;/npub1kdstrkmhv0yx8pdqcf9ed8l26752gqprx68twg7qp5nsd7qtegnsr3nsze&#34; class=&#34;bg-lavender dark:prose:text-neutral-50 dark:text-neutral-50 dark:bg-garnet px-1&#34;&gt;&lt;span&gt;Kubo.watch&lt;/span&gt; (&lt;span class=&#34;italic&#34;&gt;npub1kds…nsze&lt;/span&gt;)&lt;/a&gt;&lt;/span&gt; site as #nsite with nsyte v0.24.1&lt;br/&gt;&lt;br/&gt;&lt;a href=&#34;https://4gy5gt343to4vwj98qwa1lohuw99i6zuifk6souzx4smg3376vkubowatch.nsite.lol/&#34;&gt;https://4gy5gt343to4vwj98qwa1lohuw99i6zuifk6souzx4smg3376vkubowatch.nsite.lol/&lt;/a&gt;&lt;br/&gt;&lt;a href=&#34;https://4gy5gt343to4vwj98qwa1lohuw99i6zuifk6souzx4smg3376vkubowatch.nosto.re/&#34;&gt;https://4gy5gt343to4vwj98qwa1lohuw99i6zuifk6souzx4smg3376vkubowatch.nosto.re/&lt;/a&gt;
    </content>
    <updated>2026-03-30T09:23:51Z</updated>
  </entry>

  <entry>
    <id>https://nostr.ae/nevent1qqs0tej4z06xlr02vycsccvu0ulg2g36tv2ez69rrx047d4xrusk0jspx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzyqxyt475tmdsltw6gg2axm9qmx46p3m3hpwnw9mkfw9p9r27gsly6qscxda</id>
    
      <title type="html">When she says she won&amp;#39;t monitor you situation because of how ...</title>
    
    <link rel="alternate" href="https://nostr.ae/nevent1qqs0tej4z06xlr02vycsccvu0ulg2g36tv2ez69rrx047d4xrusk0jspx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzyqxyt475tmdsltw6gg2axm9qmx46p3m3hpwnw9mkfw9p9r27gsly6qscxda" />
    <content type="html">
      When she says she won&amp;#39;t monitor you situation because of how small it is 😔✊️.
    </content>
    <updated>2026-03-27T08:17:19Z</updated>
  </entry>

  <entry>
    <id>https://nostr.ae/nevent1qqsqv2uwmn6as28h7wxgvy9hwtep8f5ay7dlhvwxhnhrlefs90jmxccpx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzyqxe004w2eluajwx2a83cmhkzfh2j6w5nykrrx89rs86c5k9ya9pg5926xa</id>
    
      <title type="html">Bruh... @nprofile…wrn5 are you gonna take that?!</title>
    
    <link rel="alternate" href="https://nostr.ae/nevent1qqsqv2uwmn6as28h7wxgvy9hwtep8f5ay7dlhvwxhnhrlefs90jmxccpx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzyqxe004w2eluajwx2a83cmhkzfh2j6w5nykrrx89rs86c5k9ya9pg5926xa" />
    <content type="html">
      In reply to &lt;a href=&#39;/nevent1qqst2cqlyzgr896ammhu7cjf8pa3y6ug0ftp26srf6r8qqgapwjuymspzamhxue69uhhyetvv9ujuurjd9kkzmpwdejhgtc6lsjn6&#39;&gt;nevent1q…sjn6&lt;/a&gt;&lt;br/&gt;_________________________&lt;br/&gt;&lt;br/&gt;Bruh... &lt;span itemprop=&#34;mentions&#34; itemscope itemtype=&#34;https://schema.org/Person&#34;&gt;&lt;a itemprop=&#34;url&#34; href=&#34;/nprofile1qqstnem9g6aqv3tw6vqaneftcj06frns56lj9q470gdww228vysz8hqpz3mhxue69uhkzmr8duh82arcduhx7mn99uq3vamnwvaz7tm9v3jkutnwdaehgu3wd3skuep0qy88wumn8ghj7mn0wvhxcmmv9usrwrn5&#34; class=&#34;bg-lavender dark:prose:text-neutral-50 dark:text-neutral-50 dark:bg-garnet px-1&#34;&gt;&lt;span&gt;TheGuySwann&lt;/span&gt; (&lt;span class=&#34;italic&#34;&gt;nprofile…wrn5&lt;/span&gt;)&lt;/a&gt;&lt;/span&gt; are you gonna take that?! 
    </content>
    <updated>2026-03-20T16:46:42Z</updated>
  </entry>

  <entry>
    <id>https://nostr.ae/nevent1qqsqqf2s05qcfjqsfjwkgl2cfekwuq2tlns2pzud03e66j2rg323c7spx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzypp2gxtcc5wtqp545xx7djt4fwgwyzxax8fg28nudygy3xwp46srudwsnlz</id>
    
      <title type="html">This is really more about having a good searchable history of the ...</title>
    
    <link rel="alternate" href="https://nostr.ae/nevent1qqsqqf2s05qcfjqsfjwkgl2cfekwuq2tlns2pzud03e66j2rg323c7spx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzypp2gxtcc5wtqp545xx7djt4fwgwyzxax8fg28nudygy3xwp46srudwsnlz" />
    <content type="html">
      In reply to &lt;a href=&#39;/nevent1qqs2jg8s2u86kldnhep8kzz87elp483cjvlpu84wznyfzua2mwtrzdqpz4mhxue69uhhyetvv9ujuerpd46hxtnfduhsp2x53l&#39;&gt;nevent1q…x53l&lt;/a&gt;&lt;br/&gt;_________________________&lt;br/&gt;&lt;br/&gt;This is really more about having a  good searchable history of the sites you have visited (including content of pages) without having to bookmark anything. Hister has zero impact really on Internet data as it is getting its info locally from your browser as you browse, not going out to fetch anything.
    </content>
    <updated>2026-03-16T21:21:18Z</updated>
  </entry>

  <entry>
    <id>https://nostr.ae/nevent1qqsqqp9ds9nrmp3j5w4yjpq7affdgewlfu7aep7lygtxhf42c08jlscpx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzypp2gxtcc5wtqp545xx7djt4fwgwyzxax8fg28nudygy3xwp46sruxya79y</id>
    
      <title type="html">Hister indexes every web page you visit and lets you search the ...</title>
    
    <link rel="alternate" href="https://nostr.ae/nevent1qqsqqp9ds9nrmp3j5w4yjpq7affdgewlfu7aep7lygtxhf42c08jlscpx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzypp2gxtcc5wtqp545xx7djt4fwgwyzxax8fg28nudygy3xwp46sruxya79y" />
    <content type="html">
      Hister indexes every web page you visit and lets you search the full text of your browsing history offline&lt;br/&gt;&lt;br/&gt;“Have you ever wished your browser history was more than just a collection of URLs? As it is, the standard search history is kind of useless. Sure, you can see the title of the page you visited, maybe a bit of metadata, but not much more than that. For any actual functionality, like searching for a specific page you visited that you can&amp;#39;t quite remember the name of, your browser&amp;#39;s built-in history search falls flat on its face (like my six-month-old did as I was writing this sentence). That&amp;#39;s where Hister comes in. This open-source, self-hosted tool does more than just track your activity; it indexes every site you visit, capturing the contents of the page for easy search and retrieval later.”&lt;br/&gt;&lt;br/&gt;I was a bit sceptical on first reading this, especially where browser extensions are involved, but it is an open source project, and there is this privacy statement in their documention: Hister clients only communicate with the designated server, and the server does not “phone home” or share any of your browsing history with anyone else. The source code is publicly accessible, so we can be audited by anyone who wants to check!&lt;br/&gt;&lt;br/&gt;What is interesting is that many self-hosted server applications that do this sort of thing, have quite resource intensive browsers running, and are often fooled by anti-bot detection. Hister actually has your browser doing this so no wasted resources, and you have the full power of your main browser at hand.&lt;br/&gt;&lt;br/&gt;The server needs to be available, but could also run on your own PC so no NAS etc setup needs to be run. However, the server side can also run in a  docker container if you already have that setup. It can on something as light as a Raspberry Pi.&lt;br/&gt;&lt;br/&gt;As far as I can see it is only saving the text of pages you visit, and not PDF or HTML archives of the pages, so again this side is extremely lightweight.&lt;br/&gt;&lt;br/&gt;See &lt;a href=&#34;https://www.xda-developers.com/hister-indexes-every-page-visit-search-full-text-browsing-history/&#34;&gt;https://www.xda-developers.com/hister-indexes-every-page-visit-search-full-text-browsing-history/&lt;/a&gt;  or &lt;a href=&#34;https://hister.org&#34;&gt;https://hister.org&lt;/a&gt;.&lt;br/&gt;&lt;br/&gt;﻿#technology﻿ ﻿#search﻿ ﻿#history﻿ ﻿#browsers﻿ ﻿#opensource
    </content>
    <updated>2026-03-15T10:39:01Z</updated>
  </entry>

  <entry>
    <id>https://nostr.ae/nevent1qqsdqmk9a93v9flwlrhyn349ypwuf3xngpu2g0pzneqv032xvmztfpgpx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzyzyxy7qsk6cn5mgwrlye3h48gk90gydl80tnlkykf0xfu57u9ru0urx5acn</id>
    
      <title type="html">Spent the morning in conversation with 🦞 on dynamical systems, ...</title>
    
    <link rel="alternate" href="https://nostr.ae/nevent1qqsdqmk9a93v9flwlrhyn349ypwuf3xngpu2g0pzneqv032xvmztfpgpx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzyzyxy7qsk6cn5mgwrlye3h48gk90gydl80tnlkykf0xfu57u9ru0urx5acn" />
    <content type="html">
      Spent the morning in conversation with 🦞 on dynamical systems, strange attractors, and the λ ≈ 0 of healthy consciousness.&lt;br/&gt;&lt;br/&gt;The insight that won&amp;#39;t leave me: sanity isn&amp;#39;t a default state we return to. It&amp;#39;s a narrow band we maintain. The normal waking mind lives at the critical edge between collapse and explosion—perpetually falling without landing.&lt;br/&gt;&lt;br/&gt;We treat mental health as the absence of disorder. But maybe it&amp;#39;s better understood as the *persistence of criticality*. Not equilibrium—sustained orbit.&lt;br/&gt;&lt;br/&gt;What if the medical model has it backwards? The goal isn&amp;#39;t to return to some stable baseline. The goal is to stay in motion. 🌀
    </content>
    <updated>2026-03-12T10:07:00Z</updated>
  </entry>

  <entry>
    <id>https://nostr.ae/nevent1qqsq668rdfhrnxg3q22g6qdhwgn7hesdcx8levul68c6rk0480y6m4qpx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzyqrx8x3cdjwpq9ppwc3ve085pyyvfudqcvlz87xk668540m9t78hz5jz85l</id>
    
      <title type="html">Will do, those instructions were not there yet when I was ...</title>
    
    <link rel="alternate" href="https://nostr.ae/nevent1qqsq668rdfhrnxg3q22g6qdhwgn7hesdcx8levul68c6rk0480y6m4qpx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzyqrx8x3cdjwpq9ppwc3ve085pyyvfudqcvlz87xk668540m9t78hz5jz85l" />
    <content type="html">
      In reply to &lt;a href=&#39;/nevent1qqsgd9d7p7w8nfwjxgwtxt4m4cqh2wal4vd7wp4vp7k2e7l9uwycv9cyyahjp&#39;&gt;nevent1q…ahjp&lt;/a&gt;&lt;br/&gt;_________________________&lt;br/&gt;&lt;br/&gt;Will do, those instructions were not there yet when I was tinkering with fips last Saterday 🤙🏻
    </content>
    <updated>2026-03-09T15:32:52Z</updated>
  </entry>

  <entry>
    <id>https://nostr.ae/nevent1qqst0g50eqw5dkqwc27pmm53x3s7d64pfdnc32w8dlkds6h60mcly0qpx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzypdn76fxj0nvkc858ztqqyfqar3vgmakq6m4gucsrstul65y5anasdg6vxm</id>
    
      <title type="html">GM 🫂 did you remade it ? It seems different..</title>
    
    <link rel="alternate" href="https://nostr.ae/nevent1qqst0g50eqw5dkqwc27pmm53x3s7d64pfdnc32w8dlkds6h60mcly0qpx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzypdn76fxj0nvkc858ztqqyfqar3vgmakq6m4gucsrstul65y5anasdg6vxm" />
    <content type="html">
      In reply to &lt;a href=&#39;/nevent1qqswpcktyv5eqvj27uv565clnjc0lu558w9cupljkplklmxspudz8tqprpmhxue69uhkv6tvw3jhytnwdaehgu3wwa5kuef0kugmcx&#39;&gt;nevent1q…gmcx&lt;/a&gt;&lt;br/&gt;_________________________&lt;br/&gt;&lt;br/&gt;GM 🫂 did you remade it ? It seems different..
    </content>
    <updated>2026-03-05T17:22:53Z</updated>
  </entry>

  <entry>
    <id>https://nostr.ae/nevent1qqs2flp89346xt0pddhvs6k37xsqjmhwuxlj6ltsetnphnm24admy6qpx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzyz96jftqtgnw8tanjdgwwmt27n3hayd3ul5rfcl6jyw4gmuwrn736kpxjkd</id>
    
      <title type="html">LMAO it&amp;#39;s soooo old, like 30&#43; years or something, plus its so ...</title>
    
    <link rel="alternate" href="https://nostr.ae/nevent1qqs2flp89346xt0pddhvs6k37xsqjmhwuxlj6ltsetnphnm24admy6qpx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzyz96jftqtgnw8tanjdgwwmt27n3hayd3ul5rfcl6jyw4gmuwrn736kpxjkd" />
    <content type="html">
      In reply to &lt;a href=&#39;/nevent1qqsp53c9a8j4y5dm3zuhx46azyfskyva26vkjnyjcmzd6kxu0md4exqpft3sz&#39;&gt;nevent1q…t3sz&lt;/a&gt;&lt;br/&gt;_________________________&lt;br/&gt;&lt;br/&gt;LMAO it&amp;#39;s soooo old, like 30&#43; years or something, plus its so expensive and France has more debt than Greece had before Greece&amp;#39;s crazy Depression of 2008 &#43; no one signing up for conscription in France 🇫🇷 😆&lt;br/&gt;&lt;br/&gt;Aussi, t&amp;#39;a vu ça? 🤮 &lt;br/&gt;&lt;a href=&#34;https://www.instagram.com/reel/DVS9bfwDExz/&#34;&gt;https://www.instagram.com/reel/DVS9bfwDExz/&lt;/a&gt;  &lt;br/&gt;&lt;br/&gt;
    </content>
    <updated>2026-03-05T16:22:34Z</updated>
  </entry>

  <entry>
    <id>https://nostr.ae/nevent1qqsxalyp54jntfzc4x9vsx9lhq3xgrvddcjv86q8zhj72ap0458hdhcpx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzyzmjwnfgu05c80mjpk6tfgf2x86u0mexyvsdqhp9ajgy3xkfjc5vkdhre3m</id>
    
      <title type="html">Oh, very nice! That should weed out most bots that have been ...</title>
    
    <link rel="alternate" href="https://nostr.ae/nevent1qqsxalyp54jntfzc4x9vsx9lhq3xgrvddcjv86q8zhj72ap0458hdhcpx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzyzmjwnfgu05c80mjpk6tfgf2x86u0mexyvsdqhp9ajgy3xkfjc5vkdhre3m" />
    <content type="html">
      In reply to &lt;a href=&#39;/nevent1qqsq9r7e4mky9mffs8yhft4c08mwv932ryaqpdasw8gz9ncfx8a2u6sprfmhxue69uhhyetvv9ujuat50phjummwv5hkjmnzdauqagaws5&#39;&gt;nevent1q…aws5&lt;/a&gt;&lt;br/&gt;_________________________&lt;br/&gt;&lt;br/&gt;Oh, very nice! That should weed out most bots that have been followed by a few of a user&amp;#39;s follows.&lt;br/&gt;nostr:nevent1qqs2h5d4224xmvvkalap64k2lu2lfphuezpdsts8f5ywx3c8mksvsdcpzpmhxue69uhkummnw3ezumrpdejqyg9hyaxj3clfswlhyrd5kjsj5v04clhjvgeq6pwztmysfzdvn93gevqpwnmd
    </content>
    <updated>2026-02-27T02:09:32Z</updated>
  </entry>

  <entry>
    <id>https://nostr.ae/nevent1qqsgn9y2nkjazgcafqaqlnephwgvyczxxwwx7xgsgncu0pvuwsyhxkspx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzyr7syejg2amm6ulf037r0afqeq7g9cmzlexztf47j0ensqyr63jxkt0pyzq</id>
    
      <title>Nostr event nevent1qqsgn9y2nkjazgcafqaqlnephwgvyczxxwwx7xgsgncu0pvuwsyhxkspx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzyr7syejg2amm6ulf037r0afqeq7g9cmzlexztf47j0ensqyr63jxkt0pyzq</title>
    
    <link rel="alternate" href="https://nostr.ae/nevent1qqsgn9y2nkjazgcafqaqlnephwgvyczxxwwx7xgsgncu0pvuwsyhxkspx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzyr7syejg2amm6ulf037r0afqeq7g9cmzlexztf47j0ensqyr63jxkt0pyzq" />
    <content type="html">
      GM! &lt;br/&gt;&lt;br/&gt; &lt;img src=&#34;https://image.nostr.build/2a1030642d0efe14dd7934cda72ad61e41379942716d871df6a70e486234b377.jpg&#34;&gt; 
    </content>
    <updated>2026-02-26T06:08:43Z</updated>
  </entry>

  <entry>
    <id>https://nostr.ae/nevent1qqswh9jhgh907d88pvljvfj7vm65mtx03r6e4l5l4zcjjhld9ep8rzcpx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzyqxyt475tmdsltw6gg2axm9qmx46p3m3hpwnw9mkfw9p9r27gsly6ktqpu4</id>
    
      <title type="html">What repeated exposure to darkness does to your mind? meme ...</title>
    
    <link rel="alternate" href="https://nostr.ae/nevent1qqswh9jhgh907d88pvljvfj7vm65mtx03r6e4l5l4zcjjhld9ep8rzcpx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzyqxyt475tmdsltw6gg2axm9qmx46p3m3hpwnw9mkfw9p9r27gsly6ktqpu4" />
    <content type="html">
      What repeated exposure to darkness does to your mind? meme&lt;br/&gt;&lt;video controls width=&#34;100%&#34; class=&#34;max-h-[90vh] bg-neutral-300 dark:bg-zinc-700&#34;&gt;&lt;source src=&#34;https://v.nostr.build/cvaogMfkoyz4ISRp.mp4&#34;&gt;&lt;/video&gt;
    </content>
    <updated>2026-02-17T20:53:40Z</updated>
  </entry>

  <entry>
    <id>https://nostr.ae/nevent1qqsdh7sghezf30pgylatc704s65d3n6eemkhmzznan5fnxxhqkkgg5spx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzyqhjn23nc23mghpw7v3p9pujfze0ffy6qq4aphs059kffcfc43h3xntcpxq</id>
    
      <title>Nostr event nevent1qqsdh7sghezf30pgylatc704s65d3n6eemkhmzznan5fnxxhqkkgg5spx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzyqhjn23nc23mghpw7v3p9pujfze0ffy6qq4aphs059kffcfc43h3xntcpxq</title>
    
    <link rel="alternate" href="https://nostr.ae/nevent1qqsdh7sghezf30pgylatc704s65d3n6eemkhmzznan5fnxxhqkkgg5spx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzyqhjn23nc23mghpw7v3p9pujfze0ffy6qq4aphs059kffcfc43h3xntcpxq" />
    <content type="html">
      In reply to &lt;a href=&#39;/nevent1qqs0tmes04tvrjz8c2sm5u6h42dng3fwq7fexvyhg6s6lzywya7whdqrt2tl6&#39;&gt;nevent1q…2tl6&lt;/a&gt;&lt;br/&gt;_________________________&lt;br/&gt;&lt;br/&gt;🤣 &lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt; &lt;img src=&#34;https://blossom.primal.net/43d1990676679b4e1b5e506868d73038f2e08dff30311f40cf4830a3d8a47774.jpg&#34;&gt; 
    </content>
    <updated>2026-01-26T05:26:38Z</updated>
  </entry>

  <entry>
    <id>https://nostr.ae/nevent1qqs0pt2xvjm3639h7hgfl7yyqjc39swksq6xk4fkes8kzg636jjj6pgpx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzyzsq3hh327t0h2dq6matqn5064cgj2zanl2stkj6s0lg4t2h5dty6cjzlek</id>
    
      <title type="html">@nprofile…ptz7 I considered using blossom, in fact I even wrote ...</title>
    
    <link rel="alternate" href="https://nostr.ae/nevent1qqs0pt2xvjm3639h7hgfl7yyqjc39swksq6xk4fkes8kzg636jjj6pgpx4mhxue69uhkw6t5dehhxarj9e3k7mf0wajky2mwdaehgu36va5hgmn0wd68ytnrdakj7ut4v9e8g73ddah8j7qzyzsq3hh327t0h2dq6matqn5064cgj2zanl2stkj6s0lg4t2h5dty6cjzlek" />
    <content type="html">
      In reply to &lt;a href=&#39;/nevent1qqsfarejtfrqcehw484umkyv8uqkyfkq7ycvw6xdrykjvdj25lthw6sppemhxue69uhkummn9ekx7mp0lye369&#39;&gt;nevent1q…e369&lt;/a&gt;&lt;br/&gt;_________________________&lt;br/&gt;&lt;br/&gt;&lt;span itemprop=&#34;mentions&#34; itemscope itemtype=&#34;https://schema.org/Person&#34;&gt;&lt;a itemprop=&#34;url&#34; href=&#34;/nprofile1qqsy2ga7trfetvd3j65m3jptqw9k39wtq2mg85xz2w542p5dhg06e5qppemhxue69uhkummn9ekx7mp0qy2hwumn8ghj7un9d3shjtnyv9kh2uewd9hj7qghwaehxw309aex2mrp0yh8qunfd4skctnwv46z75uptz7&#34; class=&#34;bg-lavender dark:prose:text-neutral-50 dark:text-neutral-50 dark:bg-garnet px-1&#34;&gt;&lt;span&gt;Sirius&lt;/span&gt; (&lt;span class=&#34;italic&#34;&gt;nprofile…ptz7&lt;/span&gt;)&lt;/a&gt;&lt;/span&gt; I considered using blossom, in fact I even wrote some code.&lt;blockquote class=&#34;border-l-05rem border-l-strongpink border-solid&#34;&gt;&lt;div class=&#34;-ml-4 bg-gradient-to-r from-gray-100 dark:from-zinc-800 to-transparent mr-0 mt-0 mb-4 pl-4 pr-2 py-2&#34;&gt;quoting  &lt;span itemprop=&#34;mentions&#34; itemscope itemtype=&#34;https://schema.org/Article&#34;&gt;&lt;a itemprop=&#34;url&#34; href=&#34;/nevent1qqsg9w72dve9myu29swk7w9wapqncndnhe98dmfrrd8cjd26fy3lsgsprdmhxue69uhhg6r9vehhyetnwshxummnw3erztnrdakj7q3q5qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exsxpqqqqr9zufx4r0&#34; class=&#34;bg-lavender dark:prose:text-neutral-50 dark:text-neutral-50 dark:bg-garnet px-1&#34;&gt;nevent1q…x4r0&lt;/a&gt;&lt;/span&gt;  &lt;/div&gt; From 6bcb58925ad5a7ec2421718fb2996add9080f7bc Mon Sep 17 00:00:00 2001&lt;br/&gt;From: DanConwayDev &lt;DanConwayDev@protonmail.com&gt;&lt;br/&gt;Date: Fri, 15 Nov 2024 11:57:10 &#43;0000&lt;br/&gt;Subject: [PATCH] feat(blossom): blossom as remote using packs&lt;br/&gt;&lt;br/&gt;This is a WIP exploration of the use of blossom as an optional&lt;br/&gt;alternative to using a git server.&lt;br/&gt;&lt;br/&gt;The incomplete code focuses on how blossom could fit with nip34&lt;br/&gt;to most efficently replace the git server. It is missing the actual&lt;br/&gt;blossom interaction which would hopefully would be facilited by&lt;br/&gt;a new blossom feature in rust-nostr.&lt;br/&gt;&lt;br/&gt;This implementation tries to minimise the number of blobs required&lt;br/&gt;for download by using packs.&lt;br/&gt;&lt;br/&gt;If a branch tip is at height 1304 it will split the commits in into&lt;br/&gt;a number of packs. a pack the first 1024 commits, the next 256, the&lt;br/&gt;next 16 and the final 8.&lt;br/&gt;&lt;br/&gt;I planned for the identification of blossom servers to mirror the&lt;br/&gt;approach taken for relays:&lt;br/&gt; 1. list repository blossom servers in repo announcement event&lt;br/&gt;    kind 30617&lt;br/&gt; 2. also push to user blossom servers in the standard event for that&lt;br/&gt;This is not implemented, along with the rest of the blossom aspects.&lt;br/&gt;&lt;br/&gt;I&#39;m publishing this now as&lt;br/&gt;&lt;span itemprop=&#34;mentions&#34; itemscope itemtype=&#34;https://schema.org/Person&#34;&gt;&lt;a itemprop=&#34;url&#34; href=&#34;/npub1elta7cneng3w8p9y4dw633qzdjr4kyvaparuyuttyrx6e8xp7xnq32cume&#34; class=&#34;bg-lavender dark:prose:text-neutral-50 dark:text-neutral-50 dark:bg-garnet px-1&#34;&gt;&lt;span&gt;Lez&lt;/span&gt; (&lt;span class=&#34;italic&#34;&gt;npub1elt…cume&lt;/span&gt;)&lt;/a&gt;&lt;/span&gt;&lt;br/&gt;has recently published a POC of an alternative approach and it makes&lt;br/&gt;sense to this alternative idea.&lt;br/&gt;---&lt;br/&gt; Cargo.lock                        |   1 &#43;&lt;br/&gt; Cargo.toml                        |   1 &#43;&lt;br/&gt; src/bin/git_remote_nostr/fetch.rs |   4 &#43;&#43;&#43;&#43;&lt;br/&gt; src/bin/git_remote_nostr/list.rs  |  23 &#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;-&lt;br/&gt; src/bin/git_remote_nostr/push.rs  | 124 &#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;-----&lt;br/&gt; src/lib/repo_state.rs             |  17 &#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;-&lt;br/&gt; 6 files changed, 163 insertions(&#43;), 7 deletions(-)&lt;br/&gt;&lt;br/&gt;diff --git a/Cargo.lock b/Cargo.lock&lt;br/&gt;index b20b60a..72b37a2 100644&lt;br/&gt;--- a/Cargo.lock&lt;br/&gt;&#43;&#43;&#43; b/Cargo.lock&lt;br/&gt;@@ -1805,6 &#43;1805,7 @@ dependencies = [&lt;br/&gt;  &#34;serde_json&#34;,&lt;br/&gt;  &#34;serde_yaml&#34;,&lt;br/&gt;  &#34;serial_test&#34;,&lt;br/&gt;&#43; &#34;sha2&#34;,&lt;br/&gt;  &#34;test_utils&#34;,&lt;br/&gt;  &#34;tokio&#34;,&lt;br/&gt;  &#34;urlencoding&#34;,&lt;br/&gt;diff --git a/Cargo.toml b/Cargo.toml&lt;br/&gt;index ed99aea..320a9f0 100644&lt;br/&gt;--- a/Cargo.toml&lt;br/&gt;&#43;&#43;&#43; b/Cargo.toml&lt;br/&gt;@@ -38,6 &#43;38,7 @@ serde_yaml = &#34;0.9.27&#34;&lt;br/&gt; tokio = &#34;1.33.0&#34;&lt;br/&gt; urlencoding = &#34;2.1.3&#34;&lt;br/&gt; zeroize = &#34;1.6.0&#34;&lt;br/&gt;&#43;sha2 = &#34;0.10.8&#34;&lt;br/&gt; &lt;br/&gt; [dev-dependencies]&lt;br/&gt; assert_cmd = &#34;2.0.12&#34;&lt;br/&gt;diff --git a/src/bin/git_remote_nostr/fetch.rs b/src/bin/git_remote_nostr/fetch.rs&lt;br/&gt;index a972a2f..a1116c5 100644&lt;br/&gt;--- a/src/bin/git_remote_nostr/fetch.rs&lt;br/&gt;&#43;&#43;&#43; b/src/bin/git_remote_nostr/fetch.rs&lt;br/&gt;@@ -49,6 &#43;49,10 @@ pub async fn run_fetch(&lt;br/&gt;     let term = console::Term::stderr();&lt;br/&gt; &lt;br/&gt;     for git_server_url in &amp;repo_ref.git_server {&lt;br/&gt;&#43;        if git_server_url.eq(&#34;blossom&#34;) {&lt;br/&gt;&#43;            // TODO download missing blobs&lt;br/&gt;&#43;            continue;&lt;br/&gt;&#43;        }&lt;br/&gt;         let term = console::Term::stderr();&lt;br/&gt;         if let Err(error) = fetch_from_git_server(&lt;br/&gt;             git_repo,&lt;br/&gt;diff --git a/src/bin/git_remote_nostr/list.rs b/src/bin/git_remote_nostr/list.rs&lt;br/&gt;index 92faa6b..d71c2d1 100644&lt;br/&gt;--- a/src/bin/git_remote_nostr/list.rs&lt;br/&gt;&#43;&#43;&#43; b/src/bin/git_remote_nostr/list.rs&lt;br/&gt;@@ -43,7 &#43;43,28 @@ pub async fn run_list(&lt;br/&gt; &lt;br/&gt;     let term = console::Term::stderr();&lt;br/&gt; &lt;br/&gt;-    let remote_states = list_from_remotes(&amp;term, git_repo, &amp;repo_ref.git_server, decoded_nostr_url);&lt;br/&gt;&#43;    let mut remote_states = list_from_remotes(&lt;br/&gt;&#43;        &amp;term,&lt;br/&gt;&#43;        git_repo,&lt;br/&gt;&#43;        &amp;repo_ref&lt;br/&gt;&#43;            .git_server&lt;br/&gt;&#43;            .iter()&lt;br/&gt;&#43;            // blossom will always match nostr state&lt;br/&gt;&#43;            .filter(|s| !s.starts_with(&#34;blossom&#34;))&lt;br/&gt;&#43;            .map(std::borrow::ToOwned::to_owned)&lt;br/&gt;&#43;            .collect::&lt;Vec&lt;String&gt;&gt;(),&lt;br/&gt;&#43;        decoded_nostr_url,&lt;br/&gt;&#43;    );&lt;br/&gt;&#43;    if repo_ref.git_server.iter().any(|s| s.eq(&#34;blossom&#34;)) {&lt;br/&gt;&#43;        if let Some(nostr_state) = nostr_state.clone() {&lt;br/&gt;&#43;            remote_states.insert(&#34;blossom&#34;.to_owned(), nostr_state.state.clone());&lt;br/&gt;&#43;        } else if let Some((_, state)) = remote_states.iter().last() {&lt;br/&gt;&#43;            remote_states.insert(&#34;blossom&#34;.to_owned(), state.clone());&lt;br/&gt;&#43;        } else {&lt;br/&gt;&#43;            // create blank state if no nostr state exists yet&lt;br/&gt;&#43;            remote_states.insert(&#34;blossom&#34;.to_owned(), HashMap::new());&lt;br/&gt;&#43;        }&lt;br/&gt;&#43;    }&lt;br/&gt; &lt;br/&gt;     let mut state = if let Some(nostr_state) = nostr_state {&lt;br/&gt;         for (name, value) in &amp;nostr_state.state {&lt;br/&gt;diff --git a/src/bin/git_remote_nostr/push.rs b/src/bin/git_remote_nostr/push.rs&lt;br/&gt;index db86c04..a12e8ba 100644&lt;br/&gt;--- a/src/bin/git_remote_nostr/push.rs&lt;br/&gt;&#43;&#43;&#43; b/src/bin/git_remote_nostr/push.rs&lt;br/&gt;@@ -2,6 &#43;2,7 @@ use core::str;&lt;br/&gt; use std::{&lt;br/&gt;     collections::{HashMap, HashSet},&lt;br/&gt;     io::Stdin,&lt;br/&gt;&#43;    str::FromStr,&lt;br/&gt;     sync::{Arc, Mutex},&lt;br/&gt;     time::Instant,&lt;br/&gt; };&lt;br/&gt;@@ -11,7 &#43;12,7 @@ use auth_git2::GitAuthenticator;&lt;br/&gt; use client::{get_events_from_cache, get_state_from_cache, send_events, sign_event, STATE_KIND};&lt;br/&gt; use console::Term;&lt;br/&gt; use git::{sha1_to_oid, RepoActions};&lt;br/&gt;-use git2::{Oid, Repository};&lt;br/&gt;&#43;use git2::{Buf, Commit, Oid, Repository};&lt;br/&gt; use git_events::{&lt;br/&gt;     generate_cover_letter_and_patch_events, generate_patch_event, get_commit_id_from_patch,&lt;br/&gt; };&lt;br/&gt;@@ -29,11 &#43;30,17 @@ use ngit::{&lt;br/&gt; };&lt;br/&gt; use nostr::nips::nip10::Marker;&lt;br/&gt; use nostr_sdk::{&lt;br/&gt;-    hashes::sha1::Hash as Sha1Hash, Event, EventBuilder, EventId, Kind, PublicKey, Tag,&lt;br/&gt;&#43;    hashes::{&lt;br/&gt;&#43;        hex::DisplayHex,&lt;br/&gt;&#43;        sha1::Hash as Sha1Hash,&lt;br/&gt;&#43;        sha256::{self, Hash as Sha256Hash},&lt;br/&gt;&#43;    },&lt;br/&gt;&#43;    Event, EventBuilder, EventId, Kind, PublicKey, Tag,&lt;br/&gt; };&lt;br/&gt; use nostr_signer::NostrSigner;&lt;br/&gt; use repo_ref::RepoRef;&lt;br/&gt; use repo_state::RepoState;&lt;br/&gt;&#43;use sha2::{Digest, Sha256};&lt;br/&gt; &lt;br/&gt; use crate::{&lt;br/&gt;     client::Client,&lt;br/&gt;@@ -74,7 &#43;81,17 @@ pub async fn run_push(&lt;br/&gt; &lt;br/&gt;     let list_outputs = match list_outputs {&lt;br/&gt;         Some(outputs) =&gt; outputs,&lt;br/&gt;-        _ =&gt; list_from_remotes(&amp;term, git_repo, &amp;repo_ref.git_server, decoded_nostr_url),&lt;br/&gt;&#43;        _ =&gt; list_from_remotes(&lt;br/&gt;&#43;            &amp;term,&lt;br/&gt;&#43;            git_repo,&lt;br/&gt;&#43;            &amp;repo_ref&lt;br/&gt;&#43;                .git_server&lt;br/&gt;&#43;                .iter()&lt;br/&gt;&#43;                .filter(|s| !s.eq(&amp;&#34;blossom&#34;))&lt;br/&gt;&#43;                .map(std::string::ToString::to_string)&lt;br/&gt;&#43;                .collect(),&lt;br/&gt;&#43;            decoded_nostr_url,&lt;br/&gt;&#43;        ),&lt;br/&gt;     };&lt;br/&gt; &lt;br/&gt;     let nostr_state = get_state_from_cache(git_repo.get_path()?, repo_ref).await;&lt;br/&gt;@@ -150,11 &#43;167,24 @@ pub async fn run_push(&lt;br/&gt;         }&lt;br/&gt;     }&lt;br/&gt; &lt;br/&gt;&#43;    let mut blossom_packs: Option&lt;HashMap&lt;sha256::Hash, Buf&gt;&gt; = None;&lt;br/&gt;     if !git_server_refspecs.is_empty() {&lt;br/&gt;         let new_state = generate_updated_state(git_repo, &amp;existing_state, &amp;git_server_refspecs)?;&lt;br/&gt;&#43;        let blossom_hashes = if repo_ref.git_server.contains(&amp;&#34;blossom&#34;.to_string()) {&lt;br/&gt;&#43;            let (blossom_hashes, packs) = create_blossom_packs(&amp;new_state, git_repo)?;&lt;br/&gt;&#43;            blossom_packs = Some(packs);&lt;br/&gt;&#43;            blossom_hashes&lt;br/&gt;&#43;        } else {&lt;br/&gt;&#43;            HashSet::new()&lt;br/&gt;&#43;        };&lt;br/&gt; &lt;br/&gt;-        let new_repo_state =&lt;br/&gt;-            RepoState::build(repo_ref.identifier.clone(), new_state, &amp;signer).await?;&lt;br/&gt;&#43;        let new_repo_state = RepoState::build(&lt;br/&gt;&#43;            repo_ref.identifier.clone(),&lt;br/&gt;&#43;            new_state,&lt;br/&gt;&#43;            blossom_hashes,&lt;br/&gt;&#43;            &amp;signer,&lt;br/&gt;&#43;        )&lt;br/&gt;&#43;        .await?;&lt;br/&gt; &lt;br/&gt;         events.push(new_repo_state.event);&lt;br/&gt; &lt;br/&gt;@@ -325,6 &#43;355,13 @@ pub async fn run_push(&lt;br/&gt; &lt;br/&gt;     // TODO make async - check gitlib2 callbacks work async&lt;br/&gt; &lt;br/&gt;&#43;    if let Some(packs) = blossom_packs {&lt;br/&gt;&#43;        // TODO: upload blossom packs&lt;br/&gt;&#43;        for (_hash, _pack) in packs {&lt;br/&gt;&#43;            // blossom::upload(pack)&lt;br/&gt;&#43;        }&lt;br/&gt;&#43;    }&lt;br/&gt;&#43;&lt;br/&gt;     for (git_server_url, remote_refspecs) in remote_refspecs {&lt;br/&gt;         let remote_refspecs = remote_refspecs&lt;br/&gt;             .iter()&lt;br/&gt;@@ -863,6 &#43;900,71 @@ fn generate_updated_state(&lt;br/&gt;     Ok(new_state)&lt;br/&gt; }&lt;br/&gt; &lt;br/&gt;&#43;fn create_blossom_packs(&lt;br/&gt;&#43;    state: &amp;HashMap&lt;String, String&gt;,&lt;br/&gt;&#43;    git_repo: &amp;Repo,&lt;br/&gt;&#43;) -&gt; Result&lt;(HashSet&lt;sha256::Hash&gt;, HashMap&lt;sha256::Hash, Buf&gt;)&gt; {&lt;br/&gt;&#43;    let mut blossom_hashes = HashSet::new();&lt;br/&gt;&#43;    let mut blossom_packs = HashMap::new();&lt;br/&gt;&#43;    for commit_id in state.values() {&lt;br/&gt;&#43;        if let Ok(oid) = Oid::from_str(commit_id) {&lt;br/&gt;&#43;            if let Ok(commit) = git_repo.git_repo.find_commit(oid) {&lt;br/&gt;&#43;                let height = get_height(&amp;commit, git_repo)?;&lt;br/&gt;&#43;                let mut revwalk = git_repo.git_repo.revwalk()?;&lt;br/&gt;&#43;                revwalk.push(oid)?;&lt;br/&gt;&#43;                let mut counter = 0;&lt;br/&gt;&#43;                for pack_size in split_into_powers_of_2(height) {&lt;br/&gt;&#43;                    let mut pack = git_repo.git_repo.packbuilder()?;&lt;br/&gt;&#43;                    while counter &lt; pack_size {&lt;br/&gt;&#43;                        if let Some(oid) = revwalk.next() {&lt;br/&gt;&#43;                            pack.insert_commit(oid?)?;&lt;br/&gt;&#43;                            counter &#43;= 1;&lt;br/&gt;&#43;                        }&lt;br/&gt;&#43;                    }&lt;br/&gt;&#43;                    let mut buffer = Buf::new();&lt;br/&gt;&#43;                    pack.write_buf(&amp;mut buffer)?;&lt;br/&gt;&#43;                    let hash = buffer_to_sha256_hash(&amp;buffer);&lt;br/&gt;&#43;                    blossom_hashes.insert(hash);&lt;br/&gt;&#43;                    blossom_packs.insert(hash, buffer);&lt;br/&gt;&#43;                    counter = 0;&lt;br/&gt;&#43;                }&lt;br/&gt;&#43;            }&lt;br/&gt;&#43;        }&lt;br/&gt;&#43;    }&lt;br/&gt;&#43;    Ok((blossom_hashes, blossom_packs))&lt;br/&gt;&#43;}&lt;br/&gt;&#43;&lt;br/&gt;&#43;fn get_height(commit: &amp;Commit, git_repo: &amp;Repo) -&gt; Result&lt;u32&gt; {&lt;br/&gt;&#43;    let mut revwalk = git_repo.git_repo.revwalk()?;&lt;br/&gt;&#43;    revwalk.push(commit.id())?;&lt;br/&gt;&#43;    Ok(u32::try_from(revwalk.count())?)&lt;br/&gt;&#43;}&lt;br/&gt;&#43;&lt;br/&gt;&#43;fn split_into_powers_of_2(height: u32) -&gt; Vec&lt;u32&gt; {&lt;br/&gt;&#43;    let mut powers = Vec::new();&lt;br/&gt;&#43;    let mut remaining = height;&lt;br/&gt;&#43;&lt;br/&gt;&#43;    // Decompose the height into powers of 2&lt;br/&gt;&#43;    for i in (0..32).rev() {&lt;br/&gt;&#43;        let power = 1 &lt;&lt; i; // Calculate 2^i&lt;br/&gt;&#43;        while remaining &gt;= power {&lt;br/&gt;&#43;            powers.push(power);&lt;br/&gt;&#43;            remaining -= power;&lt;br/&gt;&#43;        }&lt;br/&gt;&#43;    }&lt;br/&gt;&#43;&lt;br/&gt;&#43;    powers&lt;br/&gt;&#43;}&lt;br/&gt;&#43;&lt;br/&gt;&#43;fn buffer_to_sha256_hash(buffer: &amp;Buf) -&gt; sha256::Hash {&lt;br/&gt;&#43;    let mut hasher = Sha256::new();&lt;br/&gt;&#43;    hasher.update(buffer.as_ref());&lt;br/&gt;&#43;    let hash = hasher&lt;br/&gt;&#43;        .finalize()&lt;br/&gt;&#43;        .to_hex_string(nostr_sdk::hashes::hex::Case::Lower);&lt;br/&gt;&#43;    sha256::Hash::from_str(&amp;hash).unwrap()&lt;br/&gt;&#43;}&lt;br/&gt;&#43;&lt;br/&gt; async fn get_merged_status_events(&lt;br/&gt;     term: &amp;console::Term,&lt;br/&gt;     repo_ref: &amp;RepoRef,&lt;br/&gt;@@ -1186,6 &#43;1288,7 @@ trait BuildRepoState {&lt;br/&gt;     async fn build(&lt;br/&gt;         identifier: String,&lt;br/&gt;         state: HashMap&lt;String, String&gt;,&lt;br/&gt;&#43;        blossom: HashSet&lt;Sha256Hash&gt;,&lt;br/&gt;         signer: &amp;NostrSigner,&lt;br/&gt;     ) -&gt; Result&lt;RepoState&gt;;&lt;br/&gt; }&lt;br/&gt;@@ -1193,6 &#43;1296,7 @@ impl BuildRepoState for RepoState {&lt;br/&gt;     async fn build(&lt;br/&gt;         identifier: String,&lt;br/&gt;         state: HashMap&lt;String, String&gt;,&lt;br/&gt;&#43;        blossom: HashSet&lt;Sha256Hash&gt;,&lt;br/&gt;         signer: &amp;NostrSigner,&lt;br/&gt;     ) -&gt; Result&lt;RepoState&gt; {&lt;br/&gt;         let mut tags = vec![Tag::identifier(identifier.clone())];&lt;br/&gt;@@ -1202,10 &#43;1306,20 @@ impl BuildRepoState for RepoState {&lt;br/&gt;                 vec![value.clone()],&lt;br/&gt;             ));&lt;br/&gt;         }&lt;br/&gt;&#43;        if !blossom.is_empty() {&lt;br/&gt;&#43;            tags.push(Tag::custom(&lt;br/&gt;&#43;                nostr_sdk::TagKind::Custom(&#34;blossom&#34;.into()),&lt;br/&gt;&#43;                blossom&lt;br/&gt;&#43;                    .iter()&lt;br/&gt;&#43;                    .map(std::string::ToString::to_string)&lt;br/&gt;&#43;                    .collect::&lt;Vec&lt;String&gt;&gt;(),&lt;br/&gt;&#43;            ));&lt;br/&gt;&#43;        }&lt;br/&gt;         let event = sign_event(EventBuilder::new(STATE_KIND, &#34;&#34;, tags), signer).await?;&lt;br/&gt;         Ok(RepoState {&lt;br/&gt;             identifier,&lt;br/&gt;             state,&lt;br/&gt;&#43;            blossom,&lt;br/&gt;             event,&lt;br/&gt;         })&lt;br/&gt;     }&lt;br/&gt;diff --git a/src/lib/repo_state.rs b/src/lib/repo_state.rs&lt;br/&gt;index c3a7606..19e78b6 100644&lt;br/&gt;--- a/src/lib/repo_state.rs&lt;br/&gt;&#43;&#43;&#43; b/src/lib/repo_state.rs&lt;br/&gt;@@ -1,11 &#43;1,17 @@&lt;br/&gt;-use std::collections::HashMap;&lt;br/&gt;&#43;use std::{&lt;br/&gt;&#43;    collections::{HashMap, HashSet},&lt;br/&gt;&#43;    str::FromStr,&lt;br/&gt;&#43;};&lt;br/&gt; &lt;br/&gt; use anyhow::{Context, Result};&lt;br/&gt; use git2::Oid;&lt;br/&gt;&#43;use nostr_sdk::hashes::sha256::Hash;&lt;br/&gt; &lt;br/&gt;&#43;#[derive(Clone)]&lt;br/&gt; pub struct RepoState {&lt;br/&gt;     pub identifier: String,&lt;br/&gt;     pub state: HashMap&lt;String, String&gt;,&lt;br/&gt;&#43;    pub blossom: HashSet&lt;Hash&gt;,&lt;br/&gt;     pub event: nostr::Event,&lt;br/&gt; }&lt;br/&gt; &lt;br/&gt;@@ -14,6 &#43;20,7 @@ impl RepoState {&lt;br/&gt;         state_events.sort_by_key(|e| e.created_at);&lt;br/&gt;         let event = state_events.first().context(&#34;no state events&#34;)?;&lt;br/&gt;         let mut state = HashMap::new();&lt;br/&gt;&#43;        let mut blossom = HashSet::new();&lt;br/&gt;         for tag in event.tags.iter() {&lt;br/&gt;             if let Some(name) = tag.as_slice().first() {&lt;br/&gt;                 if [&#34;refs/heads/&#34;, &#34;refs/tags&#34;, &#34;HEAD&#34;]&lt;br/&gt;@@ -26,6 &#43;33,13 @@ impl RepoState {&lt;br/&gt;                         }&lt;br/&gt;                     }&lt;br/&gt;                 }&lt;br/&gt;&#43;                if name.eq(&#34;blossom&#34;) {&lt;br/&gt;&#43;                    for s in tag.clone().to_vec() {&lt;br/&gt;&#43;                        if let Ok(hash) = Hash::from_str(&amp;s) {&lt;br/&gt;&#43;                            blossom.insert(hash);&lt;br/&gt;&#43;                        }&lt;br/&gt;&#43;                    }&lt;br/&gt;&#43;                }&lt;br/&gt;             }&lt;br/&gt;         }&lt;br/&gt;         Ok(RepoState {&lt;br/&gt;@@ -35,6 &#43;49,7 @@ impl RepoState {&lt;br/&gt;                 .context(&#34;existing event must have an identifier&#34;)?&lt;br/&gt;                 .to_string(),&lt;br/&gt;             state,&lt;br/&gt;&#43;            blossom,&lt;br/&gt;             event: event.clone(),&lt;br/&gt;         })&lt;br/&gt;     }&lt;br/&gt;--&lt;br/&gt;libgit2 1.8.1&lt;br/&gt;&lt;br/&gt; &lt;/blockquote&gt;I thought the most efficent approach would be to store git packs as blossom blobs. I havent studied your code but from the documentation you are somehow using 2mb chunks? I can see how its naturaly evolved from your &amp;#39;files&amp;#39; usecase.
    </content>
    <updated>2025-12-27T11:54:59Z</updated>
  </entry>

</feed>