Week 33 Summary (Aug 09 - Aug 15, 2026)

This is my first week summary. It is built automatically with AI by consuming my manually-written notes Craft Daily notes where I document most of my activities. Then, I do some touch ups before publishing here.

A week centered on the Quick Reads read-later service, which threaded through nearly every day — from drafting a review and appreciation piece to extracting text highlights, weighing data portability, and wiring a Quick Reads section into the personal Dashboard. Automation was the second big theme: the newly discovered Brrr push-notification app went from curiosity on Tuesday to being integrated into four n8n workflows by Saturday, while Claude Code helped tidy the bookmarking app’s documentation and fix its code. Two blog posts shipped — ‘The digital toxicity’ on the return to the web for app development, and ‘It’s fun to go back’ reflecting on past writing. Reading and watching leaned heavily on AI and industry shifts, spanning antirez on lab risks, the OpenAI/Hugging Face incident timeline, the end of Google Search, and self-hosting LLMs to control token costs. The week opened with continued research for an upcoming iPhone review, focused on the camera control button.

Experimenting with a new visitor card design

I’m currently working on an updated visitor card for my digital space. The following is an updated version, the same design as before but with updated information. It’s done in Keynote. The second is an AI-generated concept for a refreshed design. I’m kind of liking the new structure (my wife, too). I might try to reproduce this in Keynote, but I see a few challenges. Keynote is limited for things like this, and I’m not sure I want to switch to another app.

Numeric Citizen Digital Space visitor card previous designNumeric Citizen Digital Space visitor card new concept design built using AI

I went looking for a reason to use Ollama

I tried to find a place for Ollama in my automation stack. I wanted two things: a lower Anthropic bill, and Ollama running somewhere in my workflows. The first reason didn’t survive contact with the data.

The number

I have a workflow that pulls my Anthropic cost report every morning and posts it to Discord and my Craft daily note. So I checked it.

Thirty days, 56 workflows, every LLM call I make: $7.48. Twenty-five cents a day, already down 60% over that window.

Moving everything off Claude would save about $90 a year. Keeping Claude for work where quality matters brings that closer to thirty.

I standardized most of my stack on Haiku months ago. That’s where the savings already went. I went looking to cut a bill that was already at its floor, because reducing API costs sounds like good engineering whether or not the number supports it.

Ollama Cloud costs more than I spend

Two things I had confused: open-weight models and locally-hosted models are separate choices. I don’t want models running on my Mac. That’s not an argument against open models — Ollama Cloud runs them on their hardware behind a normal API. I’d even set up the credentials back in December and forgotten.

But Ollama Cloud doesn’t bill per token. It’s a flat subscription metered by GPU time, with session limits every five hours and weekly limits every seven days. Pro is $20 a month — nearly three times my current bill, for smaller models.

The free tier might cover my volume. I can’t confirm that, because Ollama has no account usage endpoint. Checking your quota means logging into the web dashboard. Several open feature requests ask for an API; none have shipped. You find out you’re near the ceiling when they email you at 90%.

I went looking to reduce a cost I track with a daily automated report, and the alternative can’t be tracked with one.

The reason that holds up

Cost is out. Privacy doesn’t apply — I’m summarizing my own RSS feeds and my own billing data.

What’s left: I don’t know which of my workflows actually need a frontier model.

I have a dozen-plus workflows making LLM calls. Some summarize articles or pull signal out of a week of notes. Others do arithmetic and pattern-matching dressed up as reasoning. I’ve never tested the difference. Everything points at the same model because at twenty-five cents a day there was no reason to check.

An open model is a cheap way to test that. Not to replace Claude — to find out where the line is. Any task where a small open model matches Haiku is a task I’ve been over-provisioning.

The experiment

I picked the most mechanical node I have: the one that asks four questions about thirty numbers. Trend, spikes, projection. 570 tokens in, no nuance required.

Both models now run in parallel from the same prompt, joined by a merge node so the message builder doesn’t fire twice and double-post. Both answers print back to back, labelled with their model. The Ollama arm fails soft — a rate limit on the test shouldn’t break the report.

One thing I nearly got wrong: I reached for the largest open model first, because it was the name I recognized from the docs. Wrong instrument. A big model will obviously handle a trend summary, and confirming that tells me nothing. If you’re looking for the floor, start at the floor.

If you’re considering the same thing

Spending real money on inference? Do the migration. The math works.

Bill is a rounding error? Then cost isn’t your reason and privacy probably isn’t either. The useful question is which of your automations need a frontier model and which ones you’re over-provisioning out of habit.

I’ll report back either way.

AI made me replace another subscription: Ulysses

I finally cancelled my subscription to Ulysses. Why? I was using Ulysses because it supported Craft’s export document so that I could then publish either to Ghost or Micro.blog. Since the beginning of this year, I’ve created two n8n automation workflows to publish directly from Craft to Ghost or Micro.blog.

Publishing from Craft to Micro.blog with a Single n8n Workflow

This is a technical write-up of an n8n automation that takes a document written in Craft, converts it to clean HTML, rehosts its images, and publishes it to Micro.blog as a draft — all from a single webhook call. It’s a companion to an earlier Craft → Ghost publisher and reuses the same document-fetching approach, but targets Micro.blog’s Micropub API instead of a proprietary CMS.

The goal is to write in one place (Craft) and let automation handle the tedious, error-prone part: block conversion and image migration.

What it does

An AI assistant (via n8n’s MCP integration) or any HTTP client sends a webhook request naming a Craft document by title. The workflow then:

  1. Searches the Craft space for that title.
  2. Scores the search results to pick the actual matching document.
  3. Fetches the document’s full block tree.
  4. Converts Craft blocks into Micropub-ready HTML.
  5. Extracts every Craft-hosted image, downloads it, and re-uploads it to Micro.blog’s media endpoint.
  6. Swaps the original image URLs for their new Micro.blog-hosted equivalents.
  7. Publishes the result as a draft for manual review before it goes live.

The whole run typically completes in about 4–6 seconds, with image uploads accounting for most of the overhead.

Trigger and input

The workflow is triggered by an HTTP POST webhook that waits for the full run to complete before responding (a “response node” pattern), so the caller gets the final published URL back synchronously. It’s also exposed through n8n’s MCP server, which is what lets an assistant invoke it conversationally.

The input payload is minimal:

{ "targetTitle": "My Article Title" }

Flow overview

Webhook
  → Search Document in Craft
  → Find Best Matching Document
  → Fetch Document Content
  → Convert Craft Blocks to HTML
  → Set Micro.blog Token
  → Extract Craft Image URLs
  → Has Images?
       ├─ true  → Split by Image URL → Download from Craft → Fix Filename
       │          → Upload to Micro.blog Media → Merge Upload Result
       │          → Reassemble HTML → Merge Before Publish
       └─ false → Format No-Image Post → Merge Before Publish
  → Publish to Micro.blog
  → Respond to Webhook

The interesting problems

Most of the engineering effort went into three areas that aren’t obvious until you hit them.

Craft’s search API does full-text search, not title-only. That means a document that merely mentions the target title somewhere in its body can rank above the document actually named that. Publishing the wrong document is a nasty failure mode.

The fix is a small scoring node that runs after the search and ranks each candidate:

  • Exact title match: 100
  • Title starts with the query: 80
  • Title contains the query: under 50, penalized by how much longer the title is than the query

Before comparing, it strips Markdown noise — bold markers, italics, and heading prefixes — so formatting in a title doesn’t throw off the match. If nothing scores above zero, the node throws a descriptive error that lists every candidate it saw, which makes debugging a missed title trivial. The node emits the single best match in the same shape as the search results, so the downstream “fetch content” step doesn’t need to know any scoring happened.

2. Converting Craft blocks to HTML

Craft stores documents as a nested tree of typed blocks, not as HTML. A dedicated conversion node walks that tree and emits Micropub-ready markup. It covers:

  • Paragraphs and headings (h1–h4)
  • Blockquotes and horizontal rules
  • Unordered and ordered lists — consecutive list-item blocks are grouped into a single <ul> or <ol> rather than emitting one list per item
  • Task checkboxes (rendered as ✅ / ☐)
  • Images, wrapped in <figure>
  • Rich-link bookmarks, rendered as a styled bookmark block
  • Code blocks (<pre><code>)
  • Inline formatting: bold, italic, strikethrough, inline code, links, and proper HTML-entity escaping

It also handles two different document shapes — a notebook with sub-pages and a flat single document — with a fallback lookup, so it doesn’t matter how the source is organized.

3. Rehosting images across services

Craft images live on Craft’s own CDN. If you publish those URLs directly, your post depends on Craft continuing to serve them — not acceptable for a permanent blog post. So every Craft image has to be pulled down and re-uploaded to Micro.blog.

The image branch:

  1. Regex-scans the generated HTML for Craft image URLs.
  2. Splits into one item per image.
  3. Downloads each image’s binary from Craft.
  4. Fixes the filename extension based on the response’s MIME type (Craft URLs don’t always carry a usable extension).
  5. Uploads each image to Micro.blog’s media endpoint as multipart/form-data.

A subtle detail: Micro.blog’s media endpoint returns 202 Accepted and puts the new image URL in the HTTP Location response header, not in the body. To capture a header you have to ask the HTTP node for the full response rather than just the parsed body. A later node maps each uploaded image’s Location back to its original Craft URL by index, and the HTML is reassembled with every Craft URL replaced by its Micro.blog equivalent.

Image failures are handled gracefully: the upload node continues on error, so if one image fails (AVIF, for instance, tends to be rejected), the post still publishes — that image just keeps its original URL instead of breaking the whole run.

Why Micropub

The most reusable idea here is that Micro.blog speaks Micropub, a W3C standard, rather than a proprietary publishing API. The final payload is a standard h-entry:

{
  "type": ["h-entry"],
  "properties": {
    "name": ["My Article Title"],
    "content": ["<h2>...</h2><p>...</p>"],
    "post-status": ["draft"]
  }
}

Any Micropub-compatible endpoint would accept the same shape, so the publishing half of this workflow isn’t locked to one host. The post-status: draft field is deliberate — every post lands as a draft so it can be reviewed in the editor before going public. The endpoint responds with the new post’s URL, a preview link, and an edit link, which the workflow passes straight back to the webhook caller.

Error handling

  • A shared error-handler workflow catches failures across the automation.
  • The webhook always responds, even on failure, so a caller never hangs.
  • Image-upload failures are non-fatal (see above).
  • A missing title produces an explicit, descriptive error listing what was searched.
  • Full-text false positives are neutralized by the scoring node rather than by hoping the search ranks correctly.

Credentials and configuration (redacted)

For obvious reasons, the specifics below are not published:

  • Craft Connect REST link — a private access link used to search Craft and fetch block content.
  • Micro.blog app token — a Bearer token generated in Micro.blog account settings, stored in a dedicated “Set Token” node so it can be rotated in one place.
  • n8n instance URL, webhook path, and internal workflow IDs — infrastructure details specific to a self-hosted deployment.

If you rebuild something like this, you’d supply your own Craft access link and your own Micro.blog token, and point the workflow at your own n8n instance.

Takeaways

  • Treat a full-text search as untrusted input and score its results before acting on them.
  • When migrating content between hosts, migrate the assets too — don’t hotlink another service’s CDN.
  • Watch where an API returns the data you need; a Location header is easy to miss if you only read response bodies.
  • Prefer open standards (Micropub) over proprietary APIs where you can — it keeps the integration portable.
  • Publish to draft first. Automation should hand you a reviewable result, not a live surprise.

Manton Reece on WordPress blogs in Micro.blog:

Several months ago I blogged that we wanted to have more integration with WordPress and Ghost in Micro.blog. I’ve now rolled out the first part of that, with an option to add a WordPress blog to Micro.blog’s web interface. New posts and edits sync back and forth between Micro.blog and WordPress.

I no longer use WordPress; I use Ghost since I moved out a few years ago. I’m really looking forward to seeing how this new integration enables new workflows or simply tweaks existing ones. Some posts are rather complex, and I’m curious to see how Micro.blog would handle these.

Reach is the right word

I was exploring the GitHub website, my profile page to be exact. Here’s my GitHub activity panel for 2026 so far. Apart from the commits from the Micro.blog auto-archiving process, this is what it shows, with everything beginning on January 1st: the contributions coming from my vibe activities. This represents nearly 8 commits per day, every day, resulting in seven custom-built web applications.

Looking back on the past six months, I cannot believe how far I’ve come with all this. If I could choose one word to summarize what generative AI and vibe coding have done for me, it would be “reach”. I have achieved goals that would otherwise have required years of coding experience. The only thing I had was years of end-user experience and a clear idea of what would be fulfilling.

Excited to see what the next six months of 2026 have in store.

Here and There

If it’s a very short thought, it goes here. If it’s a great link, I share it there, too. Any in-the-moment thing is here, too. When I explain why I do this and how I do that, it’s right here. Long-form articles or a new edition of my newsletter, well, that’s over there. Other written tidbits, not too short, not too long, well, it goes here, of course. I wish I could make this post stick to the main page.

From Craft to Ghost (images included)

I finally have a Claude skill that works end-to-end for publishing a document (with images) in draft mode from Craft to Ghost. Two important things happen with this workflow: Claude invokes an n8n workflow that first creates the article in Ghost and performs a full image rehosting from the Craft backend to Ghost. Without this rehosting, images in the Ghost article would still refer to resources hosted on the Craft backend, which I don’t want. 😎

Of course, none of this would be required if there were a way to publish directly to Ghost from within Craft. 🤷🏻‍♂️

The Numeric Citizen Analytics Dashboard Experiment

This morning, I delved into integrating Craft with Claude Cowork. Using the Craft MCP connector, I built a dashboard that sources data directly from Craft tables. This setup generates a Live Artifact in Claude Cowork, which dynamically updates as more data is added. Although Lovable could have been used to achieve this, the absence of custom domain support in its free tier led me to choose Claude Cowork, which offers more flexibility for my needs.