Building the newsletter Scribbles doesn't send

The assumption

When I saw the Buttondown section in my Scribbles blog settings, I assumed Scribbles would turn my posts into a newsletter on its own. It doesn’t. The integration stores a Buttondown username, a heading and a description, and that’s it: a theme can show a subscribe form wired to my Buttondown list. People can subscribe, and then nothing is ever sent.

I only connected Buttondown to Blips yesterday, and the form didn’t appear on the blog at all until I updated my custom theme to show it. So before anyone could subscribe and wait for an email that would never come, I built the missing piece: a monthly digest of every post, generated by an n8n workflow from the Scribbles API and created in Buttondown through its API.

Why not RSS-to-email

Buttondown’s own answer to this is RSS-to-email, and I ruled it out for two reasons.

  • It’s a paid add-on. My newsletter is on Buttondown’s free plan, which includes the API but not RSS-to-email.
  • The feed is too short. The Scribbles feed only carries the latest 15 posts. In a busy month I post more than that (September had 17), so a monthly digest built from the feed would quietly drop the oldest ones.

The Scribbles JSON API doesn’t have that limit. It takes a date range, pages through results, and returns each post’s full content. That made it the right source.

The workflow

The workflow has six nodes and runs on the 1st of each month at 8:00, Montreal time. It covers the previous calendar month.

  1. Two triggers. A Schedule Trigger fires monthly on the 1st. A Manual Trigger lets me run the same path on demand for testing.
  2. Config (Set node). Every setting lives here: the mode (draft or send), the blog ID, name and URL, the subject prefix, an optional intro note, the maximum text length per post, and whether to show categories. It also computes the month with Luxon: the previous month in the America/Toronto time zone. The date range sent to the API is padded by a day on each side, so posts near midnight UTC aren’t lost.
  3. Fetch (HTTP Request). GET /api/v1/posts on the Scribbles API with blog_id, type=posts, from_date, to_date, include_content=true and limit=100, authenticated with a bearer token. n8n’s built-in pagination increments page until pagination.page reaches pagination.pages. The node retries up to three times.
  4. Build Digest (Code node). Merges the pages, drops duplicates, and keeps only published posts that aren’t hidden or excluded from RSS. It then applies the exact month boundaries in Toronto time, sorts by date and builds the email body. If the month is empty, it returns nothing and the workflow stops there, so no empty email is ever created.
  5. Create email (HTTP Request). POST /v1/emails on the Buttondown API with the subject, the body and a status: draft while testing, about_to_send once it’s live.

Failures go to my shared error workflow, like every other workflow on my n8n instance. A digest that silently doesn’t go out is worse than one that fails loudly.

Designing the email

The first draft was too airy, and the second one fits the same 17 posts in about a third of the scrolling.

Version one gave each post a heading, a full-width photo, a 300-character excerpt and a “Read the blip” link, with a rule between entries. On a phone, a month of blips became a long scroll with little on each screen.

Version two is built for density:

  • Full text. Blips are short, so each one goes in whole, with its own links kept: the trail links, the article I’m pointing to, the YouTube video. Only posts over 700 characters get trimmed, with a “Read more” link.
  • Small photos. When a post has a photo, it becomes a 96-pixel thumbnail on the right of the text.
  • Tighter entries. The title is the link, followed by the date in grey. No separators, no extra links.
  • Short link labels. Long URLs show as glass.photo/…/iphone-18-pro-max instead of the full address.
  • No category line. My titles already carry the category ("📡✨" for blips, “→ Links 🔗” for links), so repeating it was noise. A setting brings it back.

The body is HTML, not Markdown. Buttondown accepts both, but Markdown can’t size an image or place a thumbnail beside text, and that’s what makes the layout compact. The thumbnail rows use a simple table, which is still the most reliable way to lay out two columns across email clients.

Snags along the way

The Scribbles side worked on the first run; Buttondown authentication took several tries.

  • Token, not Bearer. Buttondown expects Authorization: Token <key>. My first credential was n8n’s Bearer Auth type, which sends Bearer <key>, and Buttondown answered 401 with a helpful message saying exactly which header it wanted.
  • Header Auth is the fix, but its fields are literal. In n8n’s Header Auth credential, “Name” is the HTTP header name, not a label for the credential. It must be Authorization. “Value” must be Token, one space, then the key. A stray space or a re-pasted wrong key gives the same 401, so if it keeps failing, copy the key again from Buttondown’s API settings.
  • Embed shortcodes in the text. A post’s plain-text version still contains Scribbles embed codes like {{yt:https://youtu.be/…}}. The builder now turns those into plain links, and YouTube embeds in the HTML become a “Watch on YouTube” link.

The subscribe form

The form lives in my custom Scribbles theme and needs no JavaScript. It’s a Liquid snippet that reads the Buttondown username from the blog settings, so changing it in Scribbles updates the form everywhere. If the username is blank, the form doesn’t render.

The form posts the email address straight to Buttondown’s embed endpoint, https://buttondown.com/api/emails/embed-subscribe/<username>, with embed=1, and opens the confirmation in a new tab. It appears in two places: the left sidebar, and under each individual post, where a reader who just finished a blip is most likely to want more. The heading and description come from the same Scribbles settings, with a default heading when they’re empty.

Where it stands

The workflow is built and tested in draft mode, and the first real issue goes out November 1, covering October.

So far every run has created a draft in Buttondown, which let me review September’s digest as a real email before anything reached subscribers. The remaining steps are small: confirm a fresh signup through the form, flip mode from draft to send in the Config node, and activate the schedule. The send path hasn’t run yet, so the first live issue is also its first real test.

What I like about this setup is that nothing is locked in. If Scribbles adds a native newsletter one day, or I move the list elsewhere, the workflow is five steps I can change or retire in an afternoon.

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. 😎

A workflow diagram illustrates the process of publishing from Craft to Ghost, including steps for fetching content, converting to HTML, handling images, merging content, and responding to webhooks.

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

Solving Broken Images When Exporting Craft Documents

The Problem

When exporting articles from Craft to Ulysses and Micro.blog, images referenced by temporary URLs quickly become broken links. Craft hosts images with public URLs that expire within days, leaving your published posts with missing images. This automation workflow solves that problem by re-hosting all images on Micro.blog before publishing.

How It Works

The workflow is triggered when you request to publish a Craft document to Micro.blog. Here's what happens behind the scenes:

  1. A request is send in Claude with the article title to publish
  2. The n8n automation searches my Craft space and uses a scoring algorithm to find the exact document (preventing false matches from body text mentions)
  3. The document's content is converted from Craft's block format into clean HTML, preserving headings, lists, formatting, quotes, code blocks, and more
  4. The workflow scans for all image URLs pointing to Craft's backend hosting
  5. Each image is downloaded from Craft and immediately re-uploaded to Micro.blog's permanent media storage
  6. All image references in the post are updated to point to the new, stable Micro.blog URLs
  7. The article is published as a draft to Micro.blog for review before going live, which is a manual process
A workflow diagram depicts steps for processing Craft image blocks through downloading, uploading, and merging processes.

Key Technical Features

Smart Document Matching

The search algorithm scores results by how closely the document title matches the request. Exact matches score 100, partial matches score lower, and body-text mentions are heavily penalized. This ensures I get the right document even if multiple articles discuss similar topics. The search is done via Craft API endpoint.

Rich Content Support

The conversion preserves all the formatting: paragraph styles, heading levels (h1–h4), bullet and numbered lists, blockquotes, task checkboxes, strikethrough text, code blocks, horizontal rules, and rich link bookmarks. Consecutive list items are automatically grouped into single lists.

Graceful Image Handling

If an image fails to upload (for example, unsupported formats like AVIF), the system keeps the original Craft URL in your post rather than failing entirely. This ensures the article publishes even if one image has issues.

Manual Review

All posts are created as drafts in Micro.blog. I can review the final result, check that images loaded correctly, and make edits before publishing it live.

Workflow Specifications

  • Trigger: Webhook at craft-to-microblog (available in my n8n instance wirh MCP endpoint enabled)
  • Input: Simple JSON with the article title to publish
  • APIs used: Craft's document search and block retrieval, Micro.blog's Micropub standard API
  • Typical execution: 4–6 seconds (image uploads add ~1.5 seconds)
  • Output: Draft post URL, preview link, and edit URL from Micro.blog

Why This Matters

This automation fills a gap in the content publishing process. I can craft and organize my articles in Craft, a versatile and attractive writing environment, and then publish them to Micro.blog without losing images or manually fixing broken links. I use a similar method to publish new editions of the Ephemeral Scrapbook newsletter, which relies on a separate n8n workflow to handle Ghost CMS-specific requirements.

An interface displays an article titled Solving Broken Images When Exporting Craft Documents ready to be published to Micro.blog.

Now that I manage all my issues and enhancements in GitHub Issues, I just realized that I could automate many manual workflows on issues closure… many interesting ideas here, like updating the README.md file once an issue is closed by Claude Code. 🤓

From now on, I will document and track all bugs in my custom web apps using GitHub, instead of relying on checklists in Craft. Centralizing everything isn’t ideal; organizing issues in their appropriate locations is smarter. Additionally, Claude Code will be able to close issues on my request.

From My RSS Feeds To Day One

Recent readings about n8n and with the help of Claude AI, I finally found a way to replace IFTTT for archiving my RSS feeds content: it won’t be by using an n8n automation but a simple feature that was sitting right in front of my eyes on Micro.blog: cross-posting. The trick is simple: each of my RSS feed is added to the Sources panel in Micro.blog, from there, I configure cross-post the RSS feed article to other places like Day One journal using email-to-dayone. Voilà. I’ll be closing my IFTTT account later today after so many years of service. The only rather big downside: Micro.blog doesn’t copy images from the source into Day One while IFTTT could. 🫤

Update #1: I submitted my issue on the Micro.blog help forum, and a few hours later, a fix was on the way. Thanks @manton

Update #2: And now it is available; photos are now supported, too! Thanks to Manton!

A settings interface shows options for disabling cross-posting to various services like Day One and Flickr.

Using AI For Writing is Lazy? Think Again

Some believe that using AI for writing articles is lazy, not creative, and that you don’t earn the credit for doing it. I disagree. Or, it depends. Here’s a personal experiment.

This week, I shared an article about digital sovereignty with my professional network on LinkedIn. Even if I used ChatGPT to write the article, I spent days on it, or, more specifically, I spent days creating and testing different prompts. The article was written in French, then later translated into English and shared on my blog (see “On Digital Sovereignty and Strategic Realism”).

In this meta blog post, I want to share the final prompt that led to the article. Please note that the final response from ChatGPT was manually modified before being posted. Here’s the prompt below followed with some comments.

I would like you to write an article of no more than 1500 words on the topic of digital sovereignty, a subject that is currently highly relevant both in Québec and around the world. This article will be read by information technology and cybersecurity professionals. It should offer a clear-eyed perspective on the issues and challenges related to the pursuit of digital sovereignty for organizations and governments. The article should not be alarmist, but realistic and critical, with the goal of prompting reflection among readers.

Here is how the article should be structured: an introductory section that provides context, followed by a section explaining why digital sovereignty is essential but not a fully realistic target in absolute terms; we must remain pragmatic. Then, a section offering potential solutions or realistic strategies that large organizations should adopt, especially if they are critical to society.

The article should conclude with open questions inviting readers to reflect and comment in order to spark a constructive conversation. Use the following elements to build the article. Reuse the provided links as references.

  • Over the past five years, a series of international, political, and technological events has forced us to examine the notion of digital sovereignty (a few examples: the rise of the GAFAM giants, the Snowden affair, the U.S. Patriot Act and Cloud Act, recent U.S. elections, mergers and acquisitions in the tech sector, etc.).
  • What exactly is digital sovereignty? “Digital sovereignty refers to the ability of a state, an organization, or an individual to control and manage its data, digital infrastructures, and technologies in order to ensure its strategic autonomy and security in the digital space.”
  • It is the ability to fully exercise one’s rights and choices in the digital domain without being subject to external constraints.
  • Major outages from several cloud service providers have occurred, the most notable being:
  • AWS (October 20, 2025: Revealing the Cascading Impacts of the AWS Outage – Ookla)
  • A Microsoft Azure outage (October 29, 2025: Microsoft Azure Outage: How the World’s Second-Largest Cloud Platform Went Down – ThinkCloudly)
  • And more recently, a Cloudflare outage (November 18, 2025: Cloudflare outage on November 18, 2025)
  • Another outage occurred last year, on July 19, 2024, when a problematic update from CrowdStrike caused widespread service failures (2024 CrowdStrike-related IT outages – Wikipedia)
  • These outages strongly remind us of our deep dependence on cloud services and technology in general, both personally and within organizations.
  • We need to reflect and attempt to find viable answers and strategies to these questions: Are we well prepared? Do mitigation solutions exist? Is digital sovereignty only about data?
  • Is digital sovereignty a mirage? Are we not always dependent on something beyond our control? We must keep in mind that:
  • Complexity and cost: Developing sovereign solutions (cloud, software, artificial intelligence) requires massive investments.
  • Global interdependence: Digital value chains are globalized, making total autonomy difficult, if not impossible.
  • Risk of protectionism: Some fear that digital sovereignty could be used as a pretext for trade barriers.
  • Clearly, digital sovereignty is not merely about using or not using cloud computing, or choosing which cloud to use; it is much broader than that.
  • I really like this quote, and it must be integrated into the article: “Digital sovereignty is neither a luxury nor a technological gimmick. It is a pillar of resilience and democracy.” — Le Devoir: https://www.ledevoir.com/opinion/chroniques/936699/parlons-souverainete
  • I believe we need to accept the fact that we will never have full control over our digital destiny. Therefore, we must adopt mitigation and exit strategies to reduce dependency links.
  • We must maintain a message of independence toward major industry players so that they understand they are not alone, even if they are powerful. We need to be strategic, give ourselves the means to stay agile, and diversify.

As you can see, the prompt is nearly as long as the final product. It took me a dozen tries to see what ChatGPT could create. After each try, I would modify and add instructions to the prompt. Oh, and I searched for references myself. In short, this was a multi-day effort. Am I a lazy guy? You tell me.

Screenflow + Screen Studio

This week, I decided to add Screen Studio to my YouTube recording workflow. Screen Studio brings simplicity for recording more dynamic screen sequences. Everything Screen Studio does can be done in ScreenFlow, but it requires significantly more manual work. But Screen Studio has a severe limitation: we cannot merge recorded sequences. That’s why I’m keeping ScreenFlow.

A video editing interface is shown with a person overlaid on a blurred computer screen and options for background customization.

In summary, my workflow proceeds as follows: individual sequences are recorded in Screen Studio, exported as .mp4 files, and then imported into ScreenFlow to be assembled into a complete video sequence, which includes the intro and outro sequences with background music. Chapter markers are also added in ScreenFlow before final export. Finally, video subtitles are created using Whisper Transcription and exported as an .srt file, which is compatible with YouTube Studio.

A video editing software interface is displayed, featuring a video clip on the timeline, a preview screen, and various editing tools and options.

Overall, I do spend more time on video rendering, but I think it’s worth it. Lastly, disk space consumption is way higher than before, with 2x-3x more space consumed than with ScreenFlow alone. Ouch.

One more thing: Screen Studio is the only app that makes the M4 Mac mini fan run at full speed. I wonder if Screen Studio uses Apple Metal technology?