I published The Brain That Grew — Then Shrunk: What I Just Discovered, a long-form note that starts from a Cleo Abram YouTube Short and then follows the research on human brain evolution, the unexpected Holocene shrinkage, and the idea that culture may have taken over part of the cognitive load. It is the kind of rabbit hole post I like writing here: one short video, a lot of reading, and a sharper takeaway than I expected.
I’ve been working on ProjectSpire’s iOS app (codename: Neow’s Cafe) in NicholasClooney/ProjectSpire as a 1:1 Slay the Spire 2 card library, and the useful part is not just the filtering UI and refactor cleanup, but the way I’m trying to work with AI.
I get better results when I lay down the foundations myself first, especially around quality, guard rails, and how the data is modeled, and then let AI work inside that framework instead of asking it to define the framework for me. It also helps a lot when I have AI propose higher-level API or contract changes before it starts making edits.
Here's a snapshot of the visual changes. There is also quite a bit of non-visual work too, like reorganizing the source files into clearer areas such as App, Components, Models, Views, Logic, and Dependencies, splitting the banner text into its own component, moving the app toward injected dependencies instead of hardcoded wiring, and a few other things.
The useful part is not just the snippets themselves, but that AI agents researched the best practices, produced the example code, organized the project, and left me with a runnable playground where I can compare equal-width stacks, GeometryReader, PreferenceKey, and some surprisingly similar results against my actual needs.
I published The Confident Lie: What AI Got Wrong About @ViewBuilder, a SwiftUI debugging note that came out of the ProjectSpire card view work. It captures a small but useful lesson: body gets @ViewBuilder from the View protocol, but a custom computed some View property needs the annotation explicitly if I want an if without an else. The compiler was right, the AI was overconfident, and now the mistake is written down somewhere I can find again.
I’ve moved the SwiftUI card view forward by adding a real Card model, so even though the screen does not look dramatically different yet, the app is much closer to rendering cards from extracted data instead of hardcoded values. There is even a small visual regression in the golden text compared with the previous screenshot, but the important change is underneath: I can now refine the card parser and JSON output models, bring those records and required images directly into the app, and aim to emulate any card regardless of rarity, type, or data shape. The relevant work is in the ProjectSpire compare for the card view changes and the new card model.
New Card model version.Previous visual pass for comparison.
I’m really happy that I built the timeline feature into my blog, because it gives me an easy way to write about little moments and keep them somewhere permanent, platform agnostic, and accessible without any kind of paywall or login wall. The ProjectSpire SwiftUI card view WIP entry is exactly the kind of thing I wanted this for: a small progress record I can send to friends and family without needing it to be a full post or trapped inside a social feed.
I’m recreating the Slay the Spire 2 card view in SwiftUI with assets extracted from the game, and I’m very happy with how close the first pass feels. The current work is captured in ProjectSpire snapshot/2026-04-28, especially CardView.swift; most of it is still hardcoded, but the visual foundation is there. Next I want to generalize it so the view can take a card data object and dynamically reload the text, colors, and assets, which might eventually turn into a Slay the Spire wiki app for the phone.
I published Why You Feel More Tired During the Day Than at Night, a practical explanation of the afternoon slump, the evening second wind, and the push-pull between sleep pressure and circadian alerting. The useful takeaway is simple: protect sleep quality, get morning light, move during the day, and be deliberate about caffeine timing.
I published Localization Formatters - Slay The Spire 2 Research Note, a ProjectSpire note on how card localization formatter functions such as diff() are resolved and applied. GPT-5.5 researched and wrote the note, and I am honestly amazed by how well and how quickly it produced a detailed explanation from decompiled sources in minutes. This is exactly the kind of agent-assisted research loop that makes ProjectSpire feel much more possible.
I published Three ways to pass an @Observable object in SwiftUI, a short SwiftUI reference for choosing between environment injection, direct initializer passing, and @Binding. It keeps the distinction focused on ownership and coupling: whole-object reference sharing when the child is allowed to know the model, or a projected binding when the child should only see one value.
I pushed 1263f2d to SwiftyBites as a Friday-night AsyncDebounceDemo for playing with Swift's async and sync edges. The demo compares a view-owned async .task flow with a synchronous button action that cancels and restarts a stored Task, which makes the debounce mechanics feel a lot more concrete than just reading the pattern.
I updated SwiftUI in the Wild: Memory, Concurrency, and the Gaps in the Docs with a clearer explanation of using .task(id:) for debounced work. The change moves that pattern into the debounce section, where SwiftUI's automatic cancellation model fits naturally, and keeps the button-action section focused on manual task ownership tradeoffs.
I published Godot + .NET Internals: PCK Files, Dual Runtimes, and Why Decompiled C# Looks Terrible as a note for Slay the Spire 2 modding work. The useful distinction is that Godot mounts the .pck for its own virtual filesystem while CoreCLR loads the .dll from disk, which also explains why source recovered from the .pck reads cleaner than reconstructed C# from a decompiler.
I published SwiftUI in the Wild: Memory, Concurrency, and the Gaps in the Docs, a field guide to the parts of modern SwiftUI + concurrency that look clean in isolation but get messy in real apps. The post covers @State + @Observable lifetime bugs, debouncing with async/await, task ownership in views and buttons, closure capture cycles, and why @Observable and actor pull in different architectural directions.
I’ve been working since last night and today with agents to document how Slay the Spire 2 works, prototype a Spire API and a REST API on top of it, and shape a WIP card parser that turns C# into JSON structures. That work is captured in ProjectSpire snapshot/2026-04-19, which gives me a concrete snapshot of the game model and tooling so far.
I shipped dedicated archive index pages in v1.30.0 of 11ty-subspace-builder, including a timeline months index alongside the earlier weeks index. It also tightens up the shared archive navigation, which makes the timeline's growing set of month and week views feel more connected instead of like isolated pages.
I shipped a dedicated /timeline/weeks/ index in v1.29.0 of 11ty-subspace-builder. It groups both month-banded weeks and ISO calendar weeks by month, includes entry counts on each link, and makes the older week archive pages easier to browse without already knowing the exact week key.
I shipped timeline topic archive pages under /timeline/:topic/ in v1.28.0 of 11ty-subspace-builder. Topic tags on timeline entries now link into that namespace, which makes it easier to follow one thread of work across time without losing the main chronological feed.
I’m thinking about a timeline-specific tags page at /timeline/tags/<tag>/ so I can group related entries together and follow one topic across time without losing the chronological context. It would make the timeline feel a little more like a long-running notebook for a single idea instead of only a straight feed.
Shipped a fix for the timeline entry detail view in v1.27.1 of 11ty-subspace-builder. Earlier in thread now includes older siblings from the same branch and keeps the nearest prior entry closest to the current one instead of flipping the thread upside down.
Shipped GitHub-style collapse and expand controls for long Markdown code blocks in v1.27.0 of 11ty-subspace-builder. The release also reuses that shared copy-and-collapse behavior for regular fenced code blocks, which keeps the interaction consistent instead of treating Markdown blocks as a separate case.
I shipped month archive pages for timeline entries, month-banded week archive pages under /timeline/weeks/, and ISO calendar week archives in v1.26.0 of 11ty-subspace-builder. That gives the timeline a few more ways to browse older entries without flattening the chronological flow.
Published The Accelerated Speed of Creation, a reflection on how much faster the path from thought to shipped artifact has become with coding agents handling the translation layer around writing, blog workflow, and routine Git operations. I also kept the earlier Encoding My Blog Workflow for Coding Agents draft as a note rather than a post, because it was useful and concrete but still did not meet my standard for what the real piece needed to be.
Shipped theme mode control and delayed previews in v1.25.0 of 11ty-subspace-builder. The new theme switch adds explicit auto, light, and dark modes instead of treating the site theme as a hidden implementation detail, and delayed previews make hover previews configurable so they feel less jumpy when moving around a page.
rtc-bridge — TCP tunneling from a browser, explained is up. I wrote down the WebRTC signaling path, the node/coordinator/browser split, and the auth gap I think matters most before anyone uses it for sensitive services. I also compared it to my Tailscale + Caddy setup so the trade-offs stay concrete.
I split the blog editing rules into repo-local skills in 22c4d7d. post-and-note-workflow now makes the timeline-entry rule explicit, while frontmatter-editing routes posts/, notes/, and timeline/ to canonical front matter docs instead of burying that guidance in CLAUDE.blog.md. I also cleaned up timeline-entry so its tag guidance matches the repo defaults.
I published WebRTC — How it actually works as a note on how signaling, STUN/TURN, ICE, DTLS, and SRTP fit together. The useful framing here is that WebRTC is not just "peer-to-peer"; it is a browser-owned transport stack wrapped around signaling and fallback infrastructure you still have to run.
I published Smart AI Token Consumption as a note on matching model choice to task complexity instead of defaulting to the biggest model. It captures the split I keep using in practice: light models for mechanical work, stronger reasoning only when the problem actually needs it.
I published Getting Pulled Into the Ethereum Ecosystem (From a Digital Garden Perspective) after a 3am rabbit hole with Andrew about Ethereum, trust models, and what a markdown blog can borrow from a ledger. It is less a crypto post than a thinking-out-loud piece about verification, shared state, and the difference between controlling a history and publishing into one. I’m treating it as the first step toward a small on-chain/off-chain experiment rather than a full web3 shift.
Published the first follow-up entry in the new threaded timeline model.
Timeline entries can now point back to earlier entries, which turns the feed into more of a build log than a flat list. This update continues from the original timeline launch and marks the point where parent and follow-up relationships became part of the feature.
I’ve set up ProjectSpire Lab so I can run a script that pulls a decompiled copy of Slay the Spire 2 for local experimentation; the game code itself stays out of Git because I do not have a license to commit it. The setup lives in NicholasClooney/ProjectSpire. It gives me a clean foundation to build mod tooling from.
This grows out of Cloudflare Build Notifications via Email Routing and Email Worker, but I’m now moving the Email Worker out of the Cloudflare dashboard editor and into Git in NicholasClooney/cloudflare-email-to-webhook-worker. The goal is to keep the worker version controlled, review changes before deploys, test locally, and configure it with Wrangler instead of only editing it in the Cloudflare web UI. Right now it is still mostly Wrangler init plus the example email worker, but that is a solid foundation to build from.
I created git-activity in a631c98 so I can quickly answer "what have I been working on?" It walks a directory tree, finds the Git repos underneath it, and shows the latest log entries from each one in a single pass. It also supports a few filters, which is handy when I only want to review a slice of recent work; for example, from my projects folder I can run:
git-activity -r blog -m feat -x chore
That recursively scans repos, focuses on feature work, and leaves chores out of the list.
I moved the timeline-entry workflow into a repo-local skill in f7fceef. It now sits at .claude/skills/timeline-entry/SKILL.md, with the date/time quoting rules, status tags, and commit-based workflow close to the files it writes.
I published The Limits of AI and Where Humans Shine — a devlog about a tiny timeline sorting bug that turned into a useful comparison between AI confidence, runtime verification, and human judgement. It follows the fix from plausible-but-wrong timestamp changes to a quoted-date guard that keeps the timeline honest.
I added a /release skill to 11ty-subspace-builder in f1cb3a3. It captures the release ritual in one place: choose the semver bump, update package.json, commit chore: release vX.Y.Z, push, and create the GitHub release with the right title, body, and compare link.
I’m recording the ProjectSpire ideas now even though they’ve been rattling around for a while: an unofficial SpireAPI for mods, a REST layer on top of it, and a voice-command/accessibility layer that could eventually add Whisper-backed recognition and text-to-speech. Writing them down gives me one place to grow the monorepo instead of leaving the ideas scattered in my head.
Published What's Worth Keeping: On Humanness in the Age of AI — a post on what I've been thinking about since attending a thought experiment session on AI and skill erosion. It's about the parts of humanness I think are genuinely worth protecting — junior skill-building, critical thinking, forming a view before outsourcing it — and what I actually try to do in my own daily use of AI tools.
Added a personal timeline feed to the site. Markdown files in timeline/, same front matter as posts. Color is tag-driven: shipped goes green, published goes blue, thinking goes amber — no extra fields needed.
Added random month navigation in v1.3.0 of project-etho — a button that jumps to a random month's content rather than always landing on the latest. Good for surfacing older stuff without having to browse manually.
Published A Small Digital Garden That Feels Like Home — a reflective post on what it means to tend a personal site: slow accumulation, things planted for yourself rather than an audience, and why that feels different from posting anywhere else.
Fixed OG image generation for Chinese text in v1.21.1 of 11ty-subspace-builder — social cards were silently dropping CJK characters, now they render correctly.
Published a note on homemade hash browns, two ways — the kind of thing I keep wanting to look up and never find written the way I remember it, so I wrote it down myself.
Added copy buttons to long fenced code blocks in v1.21.0 of 11ty-subspace-builder. Short snippets don't get one — only blocks long enough that scrolling to copy is annoying.
Code blocks and GitHub embeds now follow the runtime theme in v1.19.0 of 11ty-subspace-builder. If a visitor switches between light and dark, the embeds switch with them rather than staying hardcoded.
Shipped a lightweight notes section in v1.19.0 of 11ty-subspace-builder — short-form content separate from posts, with its own collection and OG image support so each note gets a proper social card.
Starting a captain's log. Shipped things, published writing, half-formed thoughts — all in one place, in order, no categories needed. Let's see how it goes.