{
  "version": "https://jsonfeed.org/version/1.1",
  "title": "wbnns / notes",
  "home_page_url": "https://wbnns.com/notes/",
  "feed_url": "https://wbnns.com/notes/feed.json",
  "description": "Misc. et al.",
  "items": [
    {
      "id": "https://wbnns.com/notes/three-seams-in-a-twelve-second-loop/",
      "url": "https://wbnns.com/notes/three-seams-in-a-twelve-second-loop/",
      "title": "Three seams in a twelve-second loop",
      "summary": "An animated mark that visibly restarted. Every fix exposed the next seam underneath it.",
      "content_text": "An animated mark that visibly restarted. Every fix exposed the next seam underneath it.",
      "date_published": "2026-09-12T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/two-dedupe-windows-and-an-idle-notice-that-arrives-late/",
      "url": "https://wbnns.com/notes/two-dedupe-windows-and-an-idle-notice-that-arrives-late/",
      "title": "Two deduplication windows, because the idle notice arrives late",
      "summary": "A notifier for agent sessions cannot use one dedupe window. A finished turn and a permission prompt do not arrive on the same clock.",
      "content_text": "A notifier for agent sessions cannot use one dedupe window. A finished turn and a permission prompt do not arrive on the same clock.",
      "date_published": "2026-09-11T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/an-undocumented-ceiling-and-the-only-paging-on-offer/",
      "url": "https://wbnns.com/notes/an-undocumented-ceiling-and-the-only-paging-on-offer/",
      "title": "An undocumented ceiling, and the only paging on offer",
      "summary": "One route showed 58 departure dates out of 181, and the board drew the rest as no flight. The answer was truncated, not empty.",
      "content_text": "One route showed 58 departure dates out of 181, and the board drew the rest as no flight. The answer was truncated, not empty.",
      "date_published": "2026-09-10T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/six-weeks-looking-for-a-signal-and-what-was-left/",
      "url": "https://wbnns.com/notes/six-weeks-looking-for-a-signal-and-what-was-left/",
      "title": "Six weeks looking for a signal, and what was left when there wasn't one",
      "summary": "No tradable direction in these pools, and a fee side that nets to nothing. What is left is the emissions.",
      "content_text": "No tradable direction in these pools, and a fee side that nets to nothing. What is left is the emissions.",
      "date_published": "2026-09-09T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/redacting-network-identifiers-from-a-debug-report/",
      "url": "https://wbnns.com/notes/redacting-network-identifiers-from-a-debug-report/",
      "title": "Redacting network identifiers from a debug report",
      "summary": "Stop omarchy-debug output from carrying the reporter's access point, LAN devices and paired hardware into a public issue.",
      "content_text": "Stop omarchy-debug output from carrying the reporter's access point, LAN devices and paired hardware into a public issue.",
      "date_published": "2026-09-07T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/the-two-pointer-merge-that-never-reached-the-chart-file/",
      "url": "https://wbnns.com/notes/the-two-pointer-merge-that-never-reached-the-chart-file/",
      "title": "The two-pointer merge that never reached the chart file",
      "summary": "One page took ten seconds to render. The fix was already written, commented and shipped in a sibling file.",
      "content_text": "One page took ten seconds to render. The fix was already written, commented and shipped in a sibling file.",
      "date_published": "2026-09-07T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/hearwrite-vs-the-hosted-transcribers/",
      "url": "https://wbnns.com/notes/hearwrite-vs-the-hosted-transcribers/",
      "title": "Four sets of vendor claims, and why none of them can be ranked",
      "summary": "One transcription system measured properly against four sets of published numbers, almost none of which compare to each other.",
      "content_text": "One transcription system measured properly against four sets of published numbers, almost none of which compare to each other.",
      "date_published": "2026-09-04T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/streaming-transcription-speaker-labels-endpointing-open/",
      "url": "https://wbnns.com/notes/streaming-transcription-speaker-labels-endpointing-open/",
      "title": "Streaming transcription, speaker labels and endpointing from open weights on a CPU",
      "summary": "Get what Meta's Muse Voice Transcribe does from one closed model, words, speaker labels, endpoints, out of separate open components, on a CPU, with the audio never leaving the machine.",
      "content_text": "Get what Meta's Muse Voice Transcribe does from one closed model, words, speaker labels, endpoints, out of separate open components, on a CPU, with the audio never leaving the machine.",
      "date_published": "2026-09-02T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/forking-the-farcaster-client/",
      "url": "https://wbnns.com/notes/forking-the-farcaster-client/",
      "title": "Forking the Farcaster client: what you actually need",
      "summary": "The client is open source. The API is not. What actually sits between the protocol and a working app.",
      "content_text": "The client is open source. The API is not. What actually sits between the protocol and a working app.",
      "date_published": "2026-08-27T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/mail-configuration-desired-state-credential-free-drift-gate/",
      "url": "https://wbnns.com/notes/mail-configuration-desired-state-credential-free-drift-gate/",
      "title": "Mail configuration as desired state, with a credential-free drift gate",
      "summary": "Put mail configuration under version control, and have something tell me when the live system no longer matches what is committed.",
      "content_text": "Put mail configuration under version control, and have something tell me when the live system no longer matches what is committed.",
      "date_published": "2026-08-27T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/measuring-oracle-staleness-against-market-never-closes/",
      "url": "https://wbnns.com/notes/measuring-oracle-staleness-against-market-never-closes/",
      "title": "Measuring oracle staleness against a market that never closes",
      "summary": "Tokenized stocks trade 24/7 on Base. The Chainlink oracle pricing them updates on a deviation trigger with no off-hours heartbeat. Find out how big that gap actually gets, and publish it.",
      "content_text": "Tokenized stocks trade 24/7 on Base. The Chainlink oracle pricing them updates on a deviation trigger with no off-hours heartbeat. Find out how big that gap actually gets, and publish it.",
      "date_published": "2026-08-24T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/testing-content-corpus-like-code-so-unsourced-fact-fails/",
      "url": "https://wbnns.com/notes/testing-content-corpus-like-code-so-unsourced-fact-fails/",
      "title": "Testing a content corpus like code, so an unsourced fact fails the build",
      "summary": "An independent guide to Pico Island that does two jobs and no others: rank in search, and get cited by answer engines. Everything that served neither came off.",
      "content_text": "An independent guide to Pico Island that does two jobs and no others: rank in search, and get cited by answer engines. Everything that served neither came off.",
      "date_published": "2026-08-23T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/selling-placement-instead-advice-directory-companies-claim/",
      "url": "https://wbnns.com/notes/selling-placement-instead-advice-directory-companies-claim/",
      "title": "Selling placement instead of advice, in a directory companies claim by domain",
      "summary": "Legal and immigration advice is a reserved act in Portugal, so the obvious business is closed. Be the reference people check first instead, and sell placement in a directory rather than advice.",
      "content_text": "Legal and immigration advice is a reserved act in Portugal, so the obvious business is closed. Be the reference people check first instead, and sell placement in a directory rather than advice.",
      "date_published": "2026-08-22T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/one-page-seven-files-two-decide-whether-deploys/",
      "url": "https://wbnns.com/notes/one-page-seven-files-two-decide-whether-deploys/",
      "title": "One page, seven files, and the two that decide whether it deploys",
      "summary": "A single page, no build step, no dependencies.",
      "content_text": "A single page, no build step, no dependencies.",
      "date_published": "2026-08-15T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/custom-domains-github-pages-five-absolute-urls-one-dns/",
      "url": "https://wbnns.com/notes/custom-domains-github-pages-five-absolute-urls-one-dns/",
      "title": "Custom domains on GitHub Pages: five absolute URLs and one DNS setting",
      "summary": "A prototype for Pico: live webcam views, current conditions, and what islanders are reporting right now. Fog on the crossings, caravelas in the pools, whales off Lajes. A *vigia* was the cliff-top tower where a spotter watched for whales and signalled the boats.",
      "content_text": "A prototype for Pico: live webcam views, current conditions, and what islanders are reporting right now. Fog on the crossings, caravelas in the pools, whales off Lajes. A *vigia* was the cliff-top tower where a spotter watched for whales and signalled the boats.",
      "date_published": "2026-08-14T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/a-daily-report-on-a-systemd-timer-instead-of-a-crontab-line/",
      "url": "https://wbnns.com/notes/a-daily-report-on-a-systemd-timer-instead-of-a-crontab-line/",
      "title": "A daily report on a systemd timer instead of a crontab line",
      "summary": "A daily go-to-market report that runs itself and puts the numbers somewhere I will actually see them.",
      "content_text": "A daily go-to-market report that runs itself and puts the numbers somewhere I will actually see them.",
      "date_published": "2026-08-13T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/manifest-v3-never-killed-cosmetic-filtering/",
      "url": "https://wbnns.com/notes/manifest-v3-never-killed-cosmetic-filtering/",
      "title": "Manifest V3 never killed cosmetic filtering",
      "summary": "Chrome's Manifest V2 removal killed uBlock Origin, and with it years of hand-written cosmetic filters people had tuned to their own annoyances. uBlock Origin Lite is declarative by design: no custom filters, no element picker. Get the custom filters back.",
      "content_text": "Chrome's Manifest V2 removal killed uBlock Origin, and with it years of hand-written cosmetic filters people had tuned to their own annoyances. uBlock Origin Lite is declarative by design: no custom filters, no element picker. Get the custom filters back.",
      "date_published": "2026-08-10T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/keeping-the-model-out-of-the-verdict-path/",
      "url": "https://wbnns.com/notes/keeping-the-model-out-of-the-verdict-path/",
      "title": "Keeping the model out of the verdict path",
      "summary": "Measure which online communities actually produce paying customers, and withhold a verdict until the evidence supports one. *Madrugar* is Portuguese for rising before dawn.",
      "content_text": "Measure which online communities actually produce paying customers, and withhold a verdict until the evidence supports one. *Madrugar* is Portuguese for rising before dawn.",
      "date_published": "2026-08-09T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/one-command-that-decides-whether-the-work-is-done/",
      "url": "https://wbnns.com/notes/one-command-that-decides-whether-the-work-is-done/",
      "title": "One command that decides whether the work is done",
      "summary": "A One Shot build where the thing worth recording is not the kit but the gate.",
      "content_text": "A One Shot build where the thing worth recording is not the kit but the gate.",
      "date_published": "2026-07-23T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/rails-starter-whose-stripe-billing-runs-zero-external/",
      "url": "https://wbnns.com/notes/rails-starter-whose-stripe-billing-runs-zero-external/",
      "title": "A Rails starter whose Stripe billing runs with zero external accounts",
      "summary": "Every prototype needs the same six things before it can do the one thing it exists for. Ship those done, so the work is the actual product.",
      "content_text": "Every prototype needs the same six things before it can do the one thing it exists for. Ship those done, so the work is the actual product.",
      "date_published": "2026-07-22T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/hotwire-native-deciding-which-screens-stop-being-web-views/",
      "url": "https://wbnns.com/notes/hotwire-native-deciding-which-screens-stop-being-web-views/",
      "title": "Hotwire Native, and deciding which screens stop being web views",
      "summary": "The working repo for One Shot. Same kit as shiponeshot; the piece specific here is mobile/.",
      "content_text": "The working repo for One Shot. Same kit as shiponeshot; the piece specific here is mobile/.",
      "date_published": "2026-07-12T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/one-stripe-account-and-every-endpoint-gets-every-event/",
      "url": "https://wbnns.com/notes/one-stripe-account-and-every-endpoint-gets-every-event/",
      "title": "One Stripe account, and every endpoint gets every event",
      "summary": "Stripe warned that one product's webhook was failing. The events breaking it belonged to a different product entirely.",
      "content_text": "Stripe warned that one product's webhook was failing. The events breaking it belonged to a different product entirely.",
      "date_published": "2026-07-07T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/the-lever-on-agent-token-cost-is-turns-not-transport/",
      "url": "https://wbnns.com/notes/the-lever-on-agent-token-cost-is-turns-not-transport/",
      "title": "The lever on agent token cost is turns, not transport",
      "summary": "Switching a messaging agent from polling to streaming is supposed to cut cost. Past a certain arrival rate it does the opposite.",
      "content_text": "Switching a messaging agent from polling to streaming is supposed to cut cost. Past a certain arrival rate it does the opposite.",
      "date_published": "2026-06-17T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/assembling-reproducible-exam-bank-cannot-satisfy-every/",
      "url": "https://wbnns.com/notes/assembling-reproducible-exam-bank-cannot-satisfy-every/",
      "title": "Assembling a reproducible exam from a bank that cannot satisfy every constraint",
      "summary": "Train people for the CIPLE, the official A2-level European Portuguese certificate, as a subscription platform. Reading and writing in v1.",
      "content_text": "Train people for the CIPLE, the official A2-level European Portuguese certificate, as a subscription platform. Reading and writing in v1.",
      "date_published": "2026-06-10T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/twenty-lines-shell-sync-notes-repo-never-shout-about/",
      "url": "https://wbnns.com/notes/twenty-lines-shell-sync-notes-repo-never-shout-about/",
      "title": "Twenty lines of shell that sync a notes repo and never shout about it",
      "summary": "Keep a notes repo in sync across machines on a timer, and never interrupt me about it.",
      "content_text": "Keep a notes repo in sync across machines on a timer, and never interrupt me about it.",
      "date_published": "2026-05-10T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/two-operating-systems-one-dotfiles-repo-no-conditionals/",
      "url": "https://wbnns.com/notes/two-operating-systems-one-dotfiles-repo-no-conditionals/",
      "title": "Two operating systems, one dotfiles repo, no conditionals",
      "summary": "One dotfiles repo for macOS workstations and Linux servers, without scattering OS conditionals through twenty files.",
      "content_text": "One dotfiles repo for macOS workstations and Linux servers, without scattering OS conditionals through twenty files.",
      "date_published": "2026-04-30T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/serving-one-documentation-corpus-to-people-and-to-agents/",
      "url": "https://wbnns.com/notes/serving-one-documentation-corpus-to-people-and-to-agents/",
      "title": "Serving one documentation corpus to people and to agents",
      "summary": "Documentation is increasingly read by something that is not a person. Serve that reader properly instead of wrapping content in navigation chrome.",
      "content_text": "Documentation is increasingly read by something that is not a person. Serve that reader properly instead of wrapping content in navigation chrome.",
      "date_published": "2026-04-19T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/a-static-site-with-exactly-one-server-route/",
      "url": "https://wbnns.com/notes/a-static-site-with-exactly-one-server-route/",
      "title": "A static site with exactly one server route",
      "summary": "Find out whether anyone wanted a CIPLE course before building one.",
      "content_text": "Find out whether anyone wanted a CIPLE course before building one.",
      "date_published": "2026-04-11T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/edge-triggered-alerting-registration-window-closes-minutes/",
      "url": "https://wbnns.com/notes/edge-triggered-alerting-registration-window-closes-minutes/",
      "title": "Edge-triggered alerting for a registration window that closes in minutes",
      "summary": "CIPLE A2 registration in Portugal fills within minutes of opening, with no notification, no waitlist and no published time. Get told the moment it opens.",
      "content_text": "CIPLE A2 registration in Portugal fills within minutes of opening, with no notification, no waitlist and no published time. Get told the moment it opens.",
      "date_published": "2026-04-11T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/when-browser-lcp-measures-the-wrong-thing-on-a-feed/",
      "url": "https://wbnns.com/notes/when-browser-lcp-measures-the-wrong-thing-on-a-feed/",
      "title": "When browser LCP measures the wrong thing on a feed",
      "summary": "Largest Contentful Paint was measuring the wrong thing on an image feed, so measure the right one.",
      "content_text": "Largest Contentful Paint was measuring the wrong thing on an image feed, so measure the right one.",
      "date_published": "2026-03-12T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/designing-type-first-building-whole-dashboard-against-mocks/",
      "url": "https://wbnns.com/notes/designing-type-first-building-whole-dashboard-against-mocks/",
      "title": "Designing the type first and building the whole dashboard against mocks",
      "summary": "An operator dashboard for a trading bot that reads and never acts.",
      "content_text": "An operator dashboard for a trading bot that reads and never acts.",
      "date_published": "2026-03-10T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/two-places-astro-site-can-put-image-why-matters/",
      "url": "https://wbnns.com/notes/two-places-astro-site-can-put-image-why-matters/",
      "title": "The two places an Astro site can put an image, and why it matters",
      "summary": "My CV and photography. The repo dates to October 2017; the Astro site in it was written in February 2026, and everything before that was a different site under the same name.",
      "content_text": "My CV and photography. The repo dates to October 2017; the Astro site in it was written in February 2026, and everything before that was a different site under the same name.",
      "date_published": "2026-02-20T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/four-agent-lifecycles-one-markdown-file-format/",
      "url": "https://wbnns.com/notes/four-agent-lifecycles-one-markdown-file-format/",
      "title": "Four agent lifecycles, one markdown file format",
      "summary": "Autonomous agent management for Claude Code, where every agent is a markdown file you can read, grep and edit.",
      "content_text": "Autonomous agent management for Claude Code, where every agent is a markdown file you can read, grep and edit.",
      "date_published": "2026-02-12T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/symlinking-dependencies-so-n-worktrees-do-not-mean-n-node/",
      "url": "https://wbnns.com/notes/symlinking-dependencies-so-n-worktrees-do-not-mean-n-node/",
      "title": "Symlinking dependencies so N worktrees do not mean N node_modules",
      "summary": "Run several Claude Code sessions in parallel without paying for a full checkout each time.",
      "content_text": "Run several Claude Code sessions in parallel without paying for a full checkout each time.",
      "date_published": "2026-02-05T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/hand-written-api-docs-and-the-drift-they-cannot-detect/",
      "url": "https://wbnns.com/notes/hand-written-api-docs-and-the-drift-they-cannot-detect/",
      "title": "Hand-written API docs, and the drift they cannot detect",
      "summary": "Document a small API by writing the docs, rather than generating a reference from a spec.",
      "content_text": "Document a small API by writing the docs, rather than generating a reference from a spec.",
      "date_published": "2025-10-06T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/trailing-stop-whose-distance-function-realized-profit/",
      "url": "https://wbnns.com/notes/trailing-stop-whose-distance-function-realized-profit/",
      "title": "A trailing stop whose distance is a function of realized profit",
      "summary": "A trading bot for Zora markets where the risk management, not the signal, is the product.",
      "content_text": "A trading bot for Zora markets where the risk management, not the signal, is the product.",
      "date_published": "2025-09-28T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/a-weekly-release-digest-that-ran-for-a-year/",
      "url": "https://wbnns.com/notes/a-weekly-release-digest-that-ran-for-a-year/",
      "title": "A weekly release digest that ran for a year",
      "summary": "Framed as an OP Stack consulting site. What actually accumulated is _posts/: a year of weekly OP Stack release digests.",
      "content_text": "Framed as an OP Stack consulting site. What actually accumulated is _posts/: a year of weekly OP Stack release digests.",
      "date_published": "2025-09-10T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/duplicate-detection-without-an-api/",
      "url": "https://wbnns.com/notes/duplicate-detection-without-an-api/",
      "title": "Duplicate detection without an API",
      "summary": "Submit to Hacker News in one keystroke without breaking the guidelines or posting a duplicate.",
      "content_text": "Submit to Hacker News in one keystroke without breaking the guidelines or posting a duplicate.",
      "date_published": "2025-09-06T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/parts-indexer-grows-rate-limiter-verify-queue-wal-safe/",
      "url": "https://wbnns.com/notes/parts-indexer-grows-rate-limiter-verify-queue-wal-safe/",
      "title": "The parts an indexer grows: a rate limiter, a verify queue, and a WAL-safe backup",
      "summary": "Ingest Zora markets into a queryable local database, and keep it correct while it runs.",
      "content_text": "Ingest Zora markets into a queryable local database, and keep it correct while it runs.",
      "date_published": "2025-08-16T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/serving-pwa-manifest-service-worker-through-rails-view-layer/",
      "url": "https://wbnns.com/notes/serving-pwa-manifest-service-worker-through-rails-view-layer/",
      "title": "Serving a PWA manifest and service worker through the Rails view layer",
      "summary": "The app itself. The README is the stock Rails placeholder, so the tree is the record.",
      "content_text": "The app itself. The README is the stock Rails placeholder, so the tree is the record.",
      "date_published": "2025-08-15T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/reader-no-account-post-identity-problem-creates/",
      "url": "https://wbnns.com/notes/reader-no-account-post-identity-problem-creates/",
      "title": "A reader with no account, and the post identity problem that creates",
      "summary": "Only what you follow, nothing else. A reader for public Instagram and Twitter accounts over RSS, with no account and no server.",
      "content_text": "Only what you follow, nothing else. A reader for public Instagram and Twitter accounts over RSS, with no account and no server.",
      "date_published": "2025-06-16T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/magic-link-auth-the-decisions-the-gem-does-not-make-for-you/",
      "url": "https://wbnns.com/notes/magic-link-auth-the-decisions-the-gem-does-not-make-for-you/",
      "title": "Magic-link auth: the decisions the gem does not make for you",
      "summary": "A Rails 8 starting template with the authentication decisions already made rather than left to the gem.",
      "content_text": "A Rails 8 starting template with the authentication decisions already made rather than left to the gem.",
      "date_published": "2025-05-23T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/thread-local-sqlite-connections-write-lock-underneath-them/",
      "url": "https://wbnns.com/notes/thread-local-sqlite-connections-write-lock-underneath-them/",
      "title": "Thread-local SQLite connections, and the write lock underneath them",
      "summary": "Index Base contract deployers and count activity per contract.",
      "content_text": "Index Base contract deployers and count activity per contract.",
      "date_published": "2024-12-31T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/turning-a-week-of-github-activity-into-notion-blocks/",
      "url": "https://wbnns.com/notes/turning-a-week-of-github-activity-into-notion-blocks/",
      "title": "Turning a week of GitHub activity into Notion blocks",
      "summary": "Building in public should not require remembering to write anything down. Pull the week's GitHub activity and post it to Notion automatically.",
      "content_text": "Building in public should not require remembering to write anything down. Pull the week's GitHub activity and post it to Notion automatically.",
      "date_published": "2024-12-26T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/partial-success-as-the-default-outcome-of-a-cross-post/",
      "url": "https://wbnns.com/notes/partial-success-as-the-default-outcome-of-a-cross-post/",
      "title": "Partial success as the default outcome of a cross-post",
      "summary": "The cost of posting is not the typing, it is opening three apps designed to keep you there. Send one Telegram message and have it fan out to Bluesky, Farcaster and X.",
      "content_text": "The cost of posting is not the typing, it is opening three apps designed to keep you there. Send one Telegram message and have it fan out to Bluesky, Farcaster and X.",
      "date_published": "2024-11-21T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/a-frame-image-written-as-jsx-rendered-on-the-response-path/",
      "url": "https://wbnns.com/notes/a-frame-image-written-as-jsx-rendered-on-the-response-path/",
      "title": "A frame image written as JSX, rendered on the response path",
      "summary": "Build a Farcaster frame with Frog, where the frame image is written as JSX rather than drawn.",
      "content_text": "Build a Farcaster frame with Frog, where the frame image is written as JSX rather than drawn.",
      "date_published": "2024-10-05T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/a-todo-list-that-lives-in-contract-storage/",
      "url": "https://wbnns.com/notes/a-todo-list-that-lives-in-contract-storage/",
      "title": "A todo list that lives in contract storage",
      "summary": "A todo list where tasks live in contract storage instead of a database, so people can see what you are working on without you publishing anything.",
      "content_text": "A todo list where tasks live in contract storage instead of a database, so people can see what you are working on without you publishing anything.",
      "date_published": "2024-08-16T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/publishing-a-snapshots-size-without-hosting-the-snapshot/",
      "url": "https://wbnns.com/notes/publishing-a-snapshots-size-without-hosting-the-snapshot/",
      "title": "Publishing a snapshot's size without hosting the snapshot",
      "summary": "Node operators need to know how much disk a Base node takes when restoring from a snapshot, before they provision. The number moves weekly and was published nowhere convenient.",
      "content_text": "Node operators need to know how much disk a Base node takes when restoring from a snapshot, before they provision. The number moves weekly and was published nowhere convenient.",
      "date_published": "2024-08-08T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/reading-a-directory-from-its-own-json-instead-of-its-html/",
      "url": "https://wbnns.com/notes/reading-a-directory-from-its-own-json-instead-of-its-html/",
      "title": "Reading a directory from its own JSON instead of its HTML",
      "summary": "Get every project URL out of base.org/ecosystem in one click.",
      "content_text": "Get every project URL out of base.org/ecosystem in one click.",
      "date_published": "2024-08-06T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/where-ecosystem-ends-headline-number-moves/",
      "url": "https://wbnns.com/notes/where-ecosystem-ends-headline-number-moves/",
      "title": "Where an ecosystem ends, and the headline number that moves with it",
      "summary": "Keep Base's entry current in the dataset behind everyone's developer-count charts.",
      "content_text": "Keep Base's entry current in the dataset behind everyone's developer-count charts.",
      "date_published": "2024-07-05T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/two-block-explorers-one-address-graph-result-cap-truncates/",
      "url": "https://wbnns.com/notes/two-block-explorers-one-address-graph-result-cap-truncates/",
      "title": "Two block explorers, one address graph, and a result cap that truncates silently",
      "summary": "Get every address that sent a transaction to a target address, across Ethereum and Base, as a CSV. Useful for allowlists and for seeing who actually interacted with something.",
      "content_text": "Get every address that sent a transaction to a target address, across Ethereum and Base, as a CSV. Useful for allowlists and for seeing who actually interacted with something.",
      "date_published": "2024-06-02T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/mtproto-not-bot-api-session-file-credential/",
      "url": "https://wbnns.com/notes/mtproto-not-bot-api-session-file-credential/",
      "title": "MTProto is not the Bot API, and the session file is a credential",
      "summary": "Export your Telegram chat titles to CSV so they can go into a spreadsheet.",
      "content_text": "Export your Telegram chat titles to CSV so they can go into a spreadsheet.",
      "date_published": "2024-05-30T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/keeping-the-raw-payload-next-to-the-derived-report/",
      "url": "https://wbnns.com/notes/keeping-the-raw-payload-next-to-the-derived-report/",
      "title": "Keeping the raw payload next to the derived report",
      "summary": "Check a token's security and rug-pull risk, and keep what the check said.",
      "content_text": "Check a token's security and rug-pull risk, and keep what the check said.",
      "date_published": "2024-04-25T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/ci-check-reads-diff-validates-against-another-repo/",
      "url": "https://wbnns.com/notes/ci-check-reads-diff-validates-against-another-repo/",
      "title": "A CI check that reads a diff and validates it against another repo",
      "summary": "Stop a wrong token definition reaching the Base bridge by checking it in CI.",
      "content_text": "Stop a wrong token definition reaching the Base bridge by checking it in CI.",
      "date_published": "2024-02-15T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/a-unique-constraint-as-the-idempotency-mechanism/",
      "url": "https://wbnns.com/notes/a-unique-constraint-as-the-idempotency-mechanism/",
      "title": "A UNIQUE constraint as the idempotency mechanism",
      "summary": "Poll Farcaster casts, extract links, and process each cast exactly once.",
      "content_text": "Poll Farcaster casts, extract links, and process each cast exactly once.",
      "date_published": "2024-02-09T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/one-guild-setting-as-an-anti-scam-control/",
      "url": "https://wbnns.com/notes/one-guild-setting-as-an-anti-scam-control/",
      "title": "One guild setting as an anti-scam control",
      "summary": "New members of a crypto-adjacent Discord get DMed within minutes by someone pretending to be support, and the server's moderation never sees it because it does not happen in the server. Turn member-to-member DMs off, through the API.",
      "content_text": "New members of a crypto-adjacent Discord get DMed within minutes by someone pretending to be support, and the server's moderation never sees it because it does not happen in the server. Turn member-to-member DMs off, through the API.",
      "date_published": "2024-02-07T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/a-farcaster-frame-is-meta-tags-and-a-post-handler/",
      "url": "https://wbnns.com/notes/a-farcaster-frame-is-meta-tags-and-a-post-handler/",
      "title": "A Farcaster frame is meta tags and a POST handler",
      "summary": "Find out how small the Farcaster Frames protocol actually is by building one on plain Flask.",
      "content_text": "Find out how small the Farcaster Frames protocol actually is by building one on plain Flask.",
      "date_published": "2024-01-28T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/minting-button-press-verification-has-sit-behind/",
      "url": "https://wbnns.com/notes/minting-button-press-verification-has-sit-behind/",
      "title": "Minting from a button press, and the verification that has to sit behind it",
      "summary": "Mint an NFT from a button press inside a Farcaster feed.",
      "content_text": "Mint an NFT from a button press inside a Farcaster feed.",
      "date_published": "2024-01-27T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/on-chain-randomness-you-can-read-before-you-guess/",
      "url": "https://wbnns.com/notes/on-chain-randomness-you-can-read-before-you-guess/",
      "title": "On-chain randomness you can read before you guess",
      "summary": "A guess-the-number game with a prize pot, and why the number was never actually hidden.",
      "content_text": "A guess-the-number game with a prize pot, and why the number was never actually hidden.",
      "date_published": "2024-01-25T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/the-block-number-is-the-token-id/",
      "url": "https://wbnns.com/notes/the-block-number-is-the-token-id/",
      "title": "The block number is the token id",
      "summary": "Make the scarce thing the block, not the artwork. Be the first person to mint an NFT in each new Base block.",
      "content_text": "Make the scarce thing the block, not the artwork. Be the first person to mint an NFT in each new Base block.",
      "date_published": "2024-01-23T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/contract-project-caught-halfway-between-truffle-hardhat/",
      "url": "https://wbnns.com/notes/contract-project-caught-halfway-between-truffle-hardhat/",
      "title": "A contract project caught halfway between Truffle and Hardhat",
      "summary": "A contract project caught halfway between Truffle and Hardhat.",
      "content_text": "A contract project caught halfway between Truffle and Hardhat.",
      "date_published": "2024-01-08T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/what-an-indexer-has-to-solve-that-a-node-does-not/",
      "url": "https://wbnns.com/notes/what-an-indexer-has-to-solve-that-a-node-does-not/",
      "title": "What an indexer has to solve that a node does not",
      "summary": "Build a Base indexer from scratch, to understand what an indexer has to solve that a node does not.",
      "content_text": "Build a Base indexer from scratch, to understand what an indexer has to solve that a node does not.",
      "date_published": "2023-11-19T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/two-package-json-files-one-repo-no-workspace/",
      "url": "https://wbnns.com/notes/two-package-json-files-one-repo-no-workspace/",
      "title": "Two package.json files, one repo, no workspace",
      "summary": "Onchain insights and analytics for Base, as an Express backend and a Create React App frontend.",
      "content_text": "Onchain insights and analytics for Base, as an Express backend and a Create React App frontend.",
      "date_published": "2023-09-26T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/a-gateway-websocket-and-a-web-server-in-one-process/",
      "url": "https://wbnns.com/notes/a-gateway-websocket-and-a-web-server-in-one-process/",
      "title": "A gateway websocket and a web server in one process",
      "summary": "Capture Discord server metrics over time and serve them from a small web app in the same process.",
      "content_text": "Capture Discord server metrics over time and serve them from a small web app in the same process.",
      "date_published": "2023-09-02T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/bridging-an-erc-20-to-base-with-cast-and-nothing-else/",
      "url": "https://wbnns.com/notes/bridging-an-erc-20-to-base-with-cast-and-nothing-else/",
      "title": "Bridging an ERC-20 to Base with cast and nothing else",
      "summary": "Write down the handful of Base operations worth doing from the command line, where nothing is hidden.",
      "content_text": "Write down the handful of Base operations worth doing from the command line, where nothing is hidden.",
      "date_published": "2023-08-01T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/adding-a-network-to-a-token-list-that-moves-real-funds/",
      "url": "https://wbnns.com/notes/adding-a-network-to-a-token-list-that-moves-real-funds/",
      "title": "Adding a network to a token list that moves real funds",
      "summary": "Add the Base mainnet definition to the Optimism token list, the file bridges and interfaces read to resolve a token.",
      "content_text": "Add the Base mainnet definition to the Optimism token list, the file bridges and interfaces read to resolve a token.",
      "date_published": "2023-07-19T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/the-nonce-is-not-the-transaction-count/",
      "url": "https://wbnns.com/notes/the-nonce-is-not-the-transaction-count/",
      "title": "The nonce is not the transaction count",
      "summary": "Extract bits of onchain information about Base from the shell.",
      "content_text": "Extract bits of onchain information about Base from the shell.",
      "date_published": "2023-05-30T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/a-faucet-whose-reward-scales-with-what-you-hold/",
      "url": "https://wbnns.com/notes/a-faucet-whose-reward-scales-with-what-you-hold/",
      "title": "A faucet whose reward scales with what you hold",
      "summary": "An ETH faucet that pays by merit rather than a flat drip, and the three places that idea leaks.",
      "content_text": "An ETH faucet that pays by merit rather than a flat drip, and the three places that idea leaks.",
      "date_published": "2023-05-22T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/has-this-person-committed-anything-has-no-correct-answer/",
      "url": "https://wbnns.com/notes/has-this-person-committed-anything-has-no-correct-answer/",
      "title": "\"Has this person committed anything\" has no correct answer",
      "summary": "Answer \"has this GitHub username committed anything, and how much\" as a package.",
      "content_text": "Answer \"has this GitHub username committed anything, and how much\" as a package.",
      "date_published": "2023-05-08T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/queue-front-simulcast-double-post-invites/",
      "url": "https://wbnns.com/notes/queue-front-simulcast-double-post-invites/",
      "title": "A queue in front of a simulcast, and the double-post it invites",
      "summary": "Queue posts and simulcast them to Farcaster and Twitter.",
      "content_text": "Queue posts and simulcast them to Farcaster and Twitter.",
      "date_published": "2023-05-04T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/link-rot-in-a-curated-list/",
      "url": "https://wbnns.com/notes/link-rot-in-a-curated-list/",
      "title": "Link rot in a curated list",
      "summary": "There was no list of Base ecosystem links, so make one.",
      "content_text": "There was no list of Base ecosystem links, so make one.",
      "date_published": "2023-04-28T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/a-security-policy-for-a-repo-that-runs-other-peoples-nodes/",
      "url": "https://wbnns.com/notes/a-security-policy-for-a-repo-that-runs-other-peoples-nodes/",
      "title": "A security policy for a repo that runs other people's nodes",
      "summary": "Give the repository that runs Base nodes a security policy and contribution guidelines.",
      "content_text": "Give the repository that runs Base nodes a security policy and contribution guidelines.",
      "date_published": "2023-02-24T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/setting-public-folder-twice-and-the-silent-404-that-follows/",
      "url": "https://wbnns.com/notes/setting-public-folder-twice-and-the-silent-404-that-follows/",
      "title": "Setting public_folder twice, and the silent 404 that follows",
      "summary": "Two small Sinatra experiments, one of which contains a bug worth keeping.",
      "content_text": "Two small Sinatra experiments, one of which contains a bug worth keeping.",
      "date_published": "2022-04-07T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/trustless-fil-wfil-bridge-liquidity-bound-centre/",
      "url": "https://wbnns.com/notes/trustless-fil-wfil-bridge-liquidity-bound-centre/",
      "title": "A trustless FIL to WFIL bridge, and the liquidity bound at its centre",
      "summary": "Propose a trustless, bidirectional FIL to WFIL bridge, and get Filecoin to fund it.",
      "content_text": "Propose a trustless, bidirectional FIL to WFIL bridge, and get Filecoin to fund it.",
      "date_published": "2021-07-01T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/one-index-html-730-bytes-floor-shipping-web/",
      "url": "https://wbnns.com/notes/one-index-html-730-bytes-floor-shipping-web/",
      "title": "One index.html, 730 bytes, and the floor of shipping on the web",
      "summary": "One index.html, 730 bytes, nothing else.",
      "content_text": "One index.html, 730 bytes, nothing else.",
      "date_published": "2021-06-26T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/talking-ethereum-node-ruby-where-transport-options-api/",
      "url": "https://wbnns.com/notes/talking-ethereum-node-ruby-where-transport-options-api/",
      "title": "Talking to an Ethereum node from Ruby, where the transport options are the API",
      "summary": "Ruby had almost nothing for talking to an Ethereum node, so Rails apps wanting chain state were writing raw JSON-RPC by hand. Fix that.",
      "content_text": "Ruby had almost nothing for talking to an Ethereum node, so Rails apps wanting chain state were writing raw JSON-RPC by hand. Fix that.",
      "date_published": "2021-04-06T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/translating-a-curriculum-made-mostly-of-english-links/",
      "url": "https://wbnns.com/notes/translating-a-curriculum-made-mostly-of-english-links/",
      "title": "Translating a curriculum made mostly of English links",
      "summary": "Everything a person needs to get started or level up as a web developer, free, based on The Odin Project's open curriculum by Erik Trautman, credited throughout. Published as a GitBook and translated: codelibro in Spanish, codelivre in French.",
      "content_text": "Everything a person needs to get started or level up as a web developer, free, based on The Odin Project's open curriculum by Erik Trautman, credited throughout. Published as a GitBook and translated: codelibro in Spanish, codelivre in French.",
      "date_published": "2021-03-30T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/aggregating-price-several-apis-deciding-what-do-when-they/",
      "url": "https://wbnns.com/notes/aggregating-price-several-apis-deciding-what-do-when-they/",
      "title": "Aggregating a price from several APIs, and deciding what to do when they disagree",
      "summary": "Pull the bitcoin price from several APIs at once, so one bad feed cannot mislead an app.",
      "content_text": "Pull the bitcoin price from several APIs at once, so one bad feed cannot mislead an app.",
      "date_published": "2021-03-28T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/mounting-react-inside-rails-and-the-initial-state-seam/",
      "url": "https://wbnns.com/notes/mounting-react-inside-rails-and-the-initial-state-seam/",
      "title": "Mounting React inside Rails, and the initial-state seam",
      "summary": "A cryptocurrency portfolio tracker, built as Rails with React inside it.",
      "content_text": "A cryptocurrency portfolio tracker, built as Rails with React inside it.",
      "date_published": "2021-03-26T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/three-sources-one-nft-listing-why-scraping-worst/",
      "url": "https://wbnns.com/notes/three-sources-one-nft-listing-why-scraping-worst/",
      "title": "Three sources for one NFT listing, and why scraping is the worst",
      "summary": "A proof of concept for scraping an NFT marketplace, which mostly became an argument for not doing it.",
      "content_text": "A proof of concept for scraping an NFT marketplace, which mostly became an argument for not doing it.",
      "date_published": "2021-03-24T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/ethernaut-level-one-fallback-function-public-entry-point/",
      "url": "https://wbnns.com/notes/ethernaut-level-one-fallback-function-public-entry-point/",
      "title": "Ethernaut level one: a fallback function is a public entry point",
      "summary": "Work the Ethernaut levels rather than read the writeups.",
      "content_text": "Work the Ethernaut levels rather than read the writeups.",
      "date_published": "2021-02-21T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/forking-a-jekyll-theme-you-intend-to-keep-editing/",
      "url": "https://wbnns.com/notes/forking-a-jekyll-theme-you-intend-to-keep-editing/",
      "title": "Forking a Jekyll theme you intend to keep editing",
      "summary": "A site for the Congo Developers Club, an online place where developers across Congo and central Africa exchange ideas and opportunities.",
      "content_text": "A site for the Congo Developers Club, an online place where developers across Congo and central Africa exchange ideas and opportunities.",
      "date_published": "2021-01-23T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/reporting-three-change-windows-without-storing-any-history/",
      "url": "https://wbnns.com/notes/reporting-three-change-windows-without-storing-any-history/",
      "title": "Reporting three change windows without storing any history",
      "summary": "Post the WBTC price and its 1-hour, 24-hour and 7-day changes for assets with option markets on Siren.",
      "content_text": "Post the WBTC price and its 1-hour, 24-hour and 7-day changes for assets with option markets on Siren.",
      "date_published": "2020-10-30T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/a-json-schema-as-the-entire-product/",
      "url": "https://wbnns.com/notes/a-json-schema-as-the-entire-product/",
      "title": "A JSON schema as the entire product",
      "summary": "A token list registry for the Superchain, where the product is the JSON schema.",
      "content_text": "A token list registry for the Superchain, where the product is the JSON schema.",
      "date_published": "2020-08-18T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/rails-application-templates-ordering-problem-everyone-hits/",
      "url": "https://wbnns.com/notes/rails-application-templates-ordering-problem-everyone-hits/",
      "title": "Rails application templates, and the ordering problem everyone hits",
      "summary": "Make my Rails defaults one flag instead of a checklist.",
      "content_text": "Make my Rails defaults one flag instead of a checklist.",
      "date_published": "2020-08-13T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/anti-tracking-blocked-signup-form-so-form-moved-house/",
      "url": "https://wbnns.com/notes/anti-tracking-blocked-signup-form-so-form-moved-house/",
      "title": "Anti-tracking blocked the signup form, so the form moved in-house",
      "summary": "Brave and Firefox block MailChimp's embedded signup script under anti-tracking rules, so the Scyberia waiting list silently collected nothing. Replace the embed with a form we own.",
      "content_text": "Brave and Firefox block MailChimp's embedded signup script under anti-tracking rules, so the Scyberia waiting list silently collected nothing. Replace the embed with a form we own.",
      "date_published": "2020-08-03T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/measuring-60-support-desks-hand-publishing-correspondence/",
      "url": "https://wbnns.com/notes/measuring-60-support-desks-hand-publishing-correspondence/",
      "title": "Measuring 60+ support desks by hand, and publishing the correspondence",
      "summary": "Nobody knew which bitcoin exchanges actually answer their support email, so measure it: 60+ exchanges, June 2020.",
      "content_text": "Nobody knew which bitcoin exchanges actually answer their support email, so measure it: 60+ exchanges, June 2020.",
      "date_published": "2020-06-19T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/rendering-mediawiki-format-proposals-as-a-static-site/",
      "url": "https://wbnns.com/notes/rendering-mediawiki-format-proposals-as-a-static-site/",
      "title": "Rendering MediaWiki-format proposals as a static site",
      "summary": "Render the Bitcoin Improvement Proposals as a browsable static site.",
      "content_text": "Render the Bitcoin Improvement Proposals as a browsable static site.",
      "date_published": "2020-06-09T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/storage-number-nobody-warns-you-about-when-you-run-explorer/",
      "url": "https://wbnns.com/notes/storage-number-nobody-warns-you-about-when-you-run-explorer/",
      "title": "The storage number nobody warns you about when you run an explorer",
      "summary": "Stand up a Bitcoin block explorer on Blockstream's Esplora frontend and electrs backend.",
      "content_text": "Stand up a Bitcoin block explorer on Blockstream's Esplora frontend and electrs backend.",
      "date_published": "2020-05-26T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/form-posts-without-leaving-page-gate-actually-enforces/",
      "url": "https://wbnns.com/notes/form-posts-without-leaving-page-gate-actually-enforces/",
      "title": "A form that posts without leaving the page, and the gate that actually enforces",
      "summary": "The Congo Developers Club site before the Jekyll rebuild, with a jQuery signup form and a launch countdown.",
      "content_text": "The Congo Developers Club site before the Jekyll rebuild, with a jQuery signup form and a launch countdown.",
      "date_published": "2020-04-26T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/cache-committed-to-git-and-the-stale-build-it-can-cause/",
      "url": "https://wbnns.com/notes/cache-committed-to-git-and-the-stale-build-it-can-cause/",
      "title": ".cache committed to git, and the stale build it can cause",
      "summary": "A Gatsby site, with .cache/ committed to git.",
      "content_text": "A Gatsby site, with .cache/ committed to git.",
      "date_published": "2020-01-21T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/heading-typography-in-a-long-form-archive/",
      "url": "https://wbnns.com/notes/heading-typography-in-a-long-form-archive/",
      "title": "Heading typography in a long-form archive",
      "summary": "Improve heading typography on the Satoshi index at the Nakamoto Institute.",
      "content_text": "Improve heading typography on the Satoshi index at the Nakamoto Institute.",
      "date_published": "2020-01-05T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/a-build-script-that-renders-php-to-static-html/",
      "url": "https://wbnns.com/notes/a-build-script-that-renders-php-to-static-html/",
      "title": "A build script that renders PHP to static HTML",
      "summary": "A personal site where PHP is the template language and what gets deployed is static HTML.",
      "content_text": "A personal site where PHP is the template language and what gets deployed is static HTML.",
      "date_published": "2019-10-18T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/a-bitcoin-conf-for-a-machine-that-does-not-have-the-ram/",
      "url": "https://wbnns.com/notes/a-bitcoin-conf-for-a-machine-that-does-not-have-the-ram/",
      "title": "A bitcoin.conf for a machine that does not have the RAM",
      "summary": "Run a Bitcoin node on a machine that does not have the RAM, and write down what each setting actually costs.",
      "content_text": "Run a Bitcoin node on a machine that does not have the RAM, and write down what each setting actually costs.",
      "date_published": "2019-06-01T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/eight-community-health-files-and-how-github-resolves-them/",
      "url": "https://wbnns.com/notes/eight-community-health-files-and-how-github-resolves-them/",
      "title": "Eight community health files, and how GitHub resolves them",
      "summary": "Collect the eight community health files a new repository should start with, and learn how GitHub actually resolves them.",
      "content_text": "Collect the eight community health files a new repository should start with, and learn how GitHub actually resolves them.",
      "date_published": "2019-05-31T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/a-sphinx-theme-is-not-a-stylesheet/",
      "url": "https://wbnns.com/notes/a-sphinx-theme-is-not-a-stylesheet/",
      "title": "A Sphinx theme is not a stylesheet",
      "summary": "Change the Sphinx theme on the Bitcoin developer documentation.",
      "content_text": "Change the Sphinx theme on the Bitcoin developer documentation.",
      "date_published": "2019-05-16T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/the-loop-and-the-closed-form/",
      "url": "https://wbnns.com/notes/the-loop-and-the-closed-form/",
      "title": "The loop and the closed form",
      "summary": "Start Project Euler in Ruby.",
      "content_text": "Start Project Euler in Ruby.",
      "date_published": "2019-04-25T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/escrow-is-the-whole-product-in-a-peer-to-peer-exchange/",
      "url": "https://wbnns.com/notes/escrow-is-the-whole-product-in-a-peer-to-peer-exchange/",
      "title": "Escrow is the whole product in a peer-to-peer exchange",
      "summary": "Replicate LocalBitcoins for Latin America, in Spanish. Shipped as BitMae.",
      "content_text": "Replicate LocalBitcoins for Latin America, in Spanish. Shipped as BitMae.",
      "date_published": "2019-03-15T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/volume-floors-why-percent-change-rankings-noise-without-them/",
      "url": "https://wbnns.com/notes/volume-floors-why-percent-change-rankings-noise-without-them/",
      "title": "Volume floors, and why percent-change rankings are noise without them",
      "summary": "Three bots posting CoinMarketCap movers: top ten, biggest gainers, biggest losers.",
      "content_text": "Three bots posting CoinMarketCap movers: top ten, biggest gainers, biggest losers.",
      "date_published": "2018-12-11T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/deriving-a-cross-rate-through-a-base-you-did-not-ask-for/",
      "url": "https://wbnns.com/notes/deriving-a-cross-rate-through-a-base-you-did-not-ask-for/",
      "title": "Deriving a cross rate through a base you did not ask for",
      "summary": "Post the Costa Rican colón to US dollar rate with 7-day, 30-day and 1-year comparisons, in Spanish.",
      "content_text": "Post the Costa Rican colón to US dollar rate with 7-day, 30-day and 1-year comparisons, in Spanish.",
      "date_published": "2018-12-07T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/hmac-request-signing-clock-skew-looks-like-auth-failure/",
      "url": "https://wbnns.com/notes/hmac-request-signing-clock-skew-looks-like-auth-failure/",
      "title": "HMAC request signing, and the clock skew that looks like an auth failure",
      "summary": "Post the average bitcoin price across exchanges, in Spanish. The English-language price bots were everywhere and there were very few for Spanish-speaking audiences.",
      "content_text": "Post the average bitcoin price across exchanges, in Spanish. The English-language price bots were everywhere and there were very few for Spanish-speaking audiences.",
      "date_published": "2018-11-21T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/percent-change-the-sign-convention-and-the-zero-denominator/",
      "url": "https://wbnns.com/notes/percent-change-the-sign-convention-and-the-zero-denominator/",
      "title": "Percent change: the sign convention and the zero denominator",
      "summary": "Two small Ruby utilities, one of which has a bug that outlives beginners.",
      "content_text": "Two small Ruby utilities, one of which has a bug that outlives beginners.",
      "date_published": "2018-11-21T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/gets-chomp-to-i-returns-0-and-beginners-never-find-out/",
      "url": "https://wbnns.com/notes/gets-chomp-to-i-returns-0-and-beginners-never-find-out/",
      "title": "gets.chomp.to_i returns 0, and beginners never find out",
      "summary": "Work through Chris Pine's *Learn to Program* in Ruby.",
      "content_text": "Work through Chris Pine's *Learn to Program* in Ruby.",
      "date_published": "2018-11-13T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/hundreds-of-emoji-pngs-and-the-advice-http-2-reversed/",
      "url": "https://wbnns.com/notes/hundreds-of-emoji-pngs-and-the-advice-http-2-reversed/",
      "title": "Hundreds of emoji PNGs, and the advice HTTP/2 reversed",
      "summary": "VA services for hodlers, as a one-page site carrying hundreds of emoji PNGs.",
      "content_text": "VA services for hodlers, as a one-page site carrying hundreds of emoji PNGs.",
      "date_published": "2018-10-19T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/quoting-a-price-you-are-willing-to-be-held-to/",
      "url": "https://wbnns.com/notes/quoting-a-price-you-are-willing-to-be-held-to/",
      "title": "Quoting a price you are willing to be held to",
      "summary": "An over-the-counter desk that provides quotes and executes trades, in Flask.",
      "content_text": "An over-the-counter desk that provides quotes and executes trades, in Flask.",
      "date_published": "2018-07-22T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/flask-app-costa-rican-market-data-never-written/",
      "url": "https://wbnns.com/notes/flask-app-costa-rican-market-data-never-written/",
      "title": "A Flask app for Costa Rican market data that was never written",
      "summary": "Costa Rican market data as a Flask app.",
      "content_text": "Costa Rican market data as a Flask app.",
      "date_published": "2018-06-02T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/normalize-css-and-the-dependency-nobody-audits/",
      "url": "https://wbnns.com/notes/normalize-css-and-the-dependency-nobody-audits/",
      "title": "normalize.css, and the dependency nobody audits",
      "summary": "An interactive page as a front-end exercise: index.html, app.js, main.css and normalize.css.",
      "content_text": "An interactive page as a front-end exercise: index.html, app.js, main.css and normalize.css.",
      "date_published": "2018-04-15T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/fetch-render-and-send-as-three-modules/",
      "url": "https://wbnns.com/notes/fetch-render-and-send-as-three-modules/",
      "title": "Fetch, render and send as three modules",
      "summary": "Email a weather forecast on a schedule, split into three modules that each do one thing.",
      "content_text": "Email a weather forecast on a schedule, split into three modules that each do one thing.",
      "date_published": "2018-03-31T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/what-adding-one-clause-to-mit-costs-you-downstream/",
      "url": "https://wbnns.com/notes/what-adding-one-clause-to-mit-costs-you-downstream/",
      "title": "What adding one clause to MIT costs you downstream",
      "summary": "Write a licence for software that moves money, so users acknowledge market risk rather than inferring a promise.",
      "content_text": "Write a licence for software that moves money, so users acknowledge market risk rather than inferring a promise.",
      "date_published": "2017-10-01T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/optimising-inside-a-build-environment-that-forbids-plugins/",
      "url": "https://wbnns.com/notes/optimising-inside-a-build-environment-that-forbids-plugins/",
      "title": "Optimising inside a build environment that forbids plugins",
      "summary": "A Jekyll blog for bitcoin development writing, with a Sass tree, a projects data file, and one post reviewing SegWit2x.",
      "content_text": "A Jekyll blog for bitcoin development writing, with a Sass tree, a projects data file, and one post reviewing SegWit2x.",
      "date_published": "2017-07-22T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/one-landing-page-template-eight-sites-eight-years/",
      "url": "https://wbnns.com/notes/one-landing-page-template-eight-sites-eight-years/",
      "title": "One landing-page template, eight sites, eight years",
      "summary": "The Digital Currency Depository & Trust site, and the landing-page template I reused for the next eight years.",
      "content_text": "The Digital Currency Depository & Trust site, and the landing-page template I reused for the next eight years.",
      "date_published": "2017-04-04T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/a-support-matrix-that-has-to-say-what-supports-segwit-means/",
      "url": "https://wbnns.com/notes/a-support-matrix-that-has-to-say-what-supports-segwit-means/",
      "title": "A support matrix that has to say what \"supports SegWit\" means",
      "summary": "Add a Bitcoin Ruby library to the SegWit support list on bitcoincore.org.",
      "content_text": "Add a Bitcoin Ruby library to the SegWit support list on bitcoincore.org.",
      "date_published": "2017-03-28T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/http-402-as-a-working-payment-channel/",
      "url": "https://wbnns.com/notes/http-402-as-a-working-payment-channel/",
      "title": "HTTP 402 as a working payment channel",
      "summary": "Wrap an existing API so that requests pay you bitcoin.",
      "content_text": "Wrap an existing API so that requests pay you bitcoin.",
      "date_published": "2016-11-15T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/reselling-a-metered-api-for-satoshis/",
      "url": "https://wbnns.com/notes/reselling-a-metered-api-for-satoshis/",
      "title": "Reselling a metered API for satoshis",
      "summary": "Resell News API access, priced per request in satoshis, across 43 sources.",
      "content_text": "Resell News API access, priced per request in satoshis, across 43 sources.",
      "date_published": "2016-10-12T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/charging-for-a-public-good-data-feed/",
      "url": "https://wbnns.com/notes/charging-for-a-public-good-data-feed/",
      "title": "Charging for a public-good data feed",
      "summary": "Sell parsed National Hurricane Center data through a bitcoin-paid endpoint.",
      "content_text": "Sell parsed National Hurricane Center data through a bitcoin-paid endpoint.",
      "date_published": "2016-10-04T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/selling-stock-quotes-over-endpoint-google-never-documented/",
      "url": "https://wbnns.com/notes/selling-stock-quotes-over-endpoint-google-never-documented/",
      "title": "Selling stock quotes over an endpoint Google never documented",
      "summary": "Sell NYSE price lookups for 720 satoshis a call.",
      "content_text": "Sell NYSE price lookups for 720 satoshis a call.",
      "date_published": "2016-09-06T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/the-same-service-one-string-different/",
      "url": "https://wbnns.com/notes/the-same-service-one-string-different/",
      "title": "The same service, one string different",
      "summary": "The same service as NYSE-Ticker against a different exchange.",
      "content_text": "The same service as NYSE-Ticker against a different exchange.",
      "date_published": "2016-09-06T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/normalising-free-text-ingredients-and-selling-the-ranking/",
      "url": "https://wbnns.com/notes/normalising-free-text-ingredients-and-selling-the-ranking/",
      "title": "Normalising free-text ingredients, and selling the ranking",
      "summary": "Provide some ingredients, get recipe suggestions, pay in bitcoin.",
      "content_text": "Provide some ingredients, get recipe suggestions, pay in bitcoin.",
      "date_published": "2016-09-05T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/pricing-a-security-answer-by-value-not-by-cost/",
      "url": "https://wbnns.com/notes/pricing-a-security-answer-by-value-not-by-cost/",
      "title": "Pricing a security answer by value, not by cost",
      "summary": "Check whether a link might be malicious, for 2700 satoshis.",
      "content_text": "Check whether a link might be malicious, for 2700 satoshis.",
      "date_published": "2016-09-04T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/payment-taken-extraction-failed/",
      "url": "https://wbnns.com/notes/payment-taken-extraction-failed/",
      "title": "Payment taken, extraction failed",
      "summary": "A paid media extraction endpoint, and the failure mode that made it unworkable.",
      "content_text": "A paid media extraction endpoint, and the failure mode that made it unworkable.",
      "date_published": "2016-08-24T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/selling-a-search-whose-negative-result-means-nothing/",
      "url": "https://wbnns.com/notes/selling-a-search-whose-negative-result-means-nothing/",
      "title": "Selling a search whose negative result means nothing",
      "summary": "Sell trademark lookups through a paid endpoint.",
      "content_text": "Sell trademark lookups through a paid endpoint.",
      "date_published": "2016-08-22T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/account-existence-oracles-sold-by-the-request/",
      "url": "https://wbnns.com/notes/account-existence-oracles-sold-by-the-request/",
      "title": "Account-existence oracles, sold by the request",
      "summary": "Yellow pages are for businesses, white pages for people. Orange pages return the social media accounts associated with an email address, paid in bitcoin.",
      "content_text": "Yellow pages are for businesses, white pages for people. Orange pages return the social media accounts associated with an email address, paid in bitcoin.",
      "date_published": "2016-08-21T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/bitcoin-bounties-for-github-work-escrowed-in-2-of-3-multisig/",
      "url": "https://wbnns.com/notes/bitcoin-bounties-for-github-work-escrowed-in-2-of-3-multisig/",
      "title": "Bitcoin bounties for GitHub work, escrowed in 2-of-3 multisig",
      "summary": "A platform for working from anywhere and getting paid in bitcoin, with 2-of-3 multisig escrow holding the bounties.",
      "content_text": "A platform for working from anywhere and getting paid in bitcoin, with 2-of-3 multisig escrow holding the bounties.",
      "date_published": "2016-02-24T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/five-years-maintaining-bitcoin-org/",
      "url": "https://wbnns.com/notes/five-years-maintaining-bitcoin-org/",
      "title": "Five years maintaining bitcoin.org",
      "summary": "Five years maintaining bitcoin.org, from July 2015 to June 2020.",
      "content_text": "Five years maintaining bitcoin.org, from July 2015 to June 2020.",
      "date_published": "2015-07-06T00:00:00.000Z"
    },
    {
      "id": "https://wbnns.com/notes/maintaining-a-translated-document-corpus-in-opendocument/",
      "url": "https://wbnns.com/notes/maintaining-a-translated-document-corpus-in-opendocument/",
      "title": "Maintaining a translated document corpus in OpenDocument",
      "summary": "Maintain the bitcoin whitepaper in many languages, with each translated PDF matching the layout of the 2008 original.",
      "content_text": "Maintain the bitcoin whitepaper in many languages, with each translated PDF matching the layout of the 2008 original.",
      "date_published": "2014-01-29T00:00:00.000Z"
    }
  ]
}