3 Types of FastSpring Storefronts

Modern FastSpring storefronts come in three standard flavors. On top, you can create your own JavaScript client page that uses the Store Builder Library under the hood. Here they are: Web Storefront Web Storefront landing page with multiple products The most basic storefront is t … | Continue reading


@christiantietze.de | 8 months ago

How to Disallow GPTBot Crawling in robots.txt

To tell OpenAI’s web crawler to skip your site, add these lines to your robots.txt (see docs): User-agent: GPTBot Disallow: / (via Hidde de Vries) The outlook is bleak: There’s no way to win this if you don’t want to be scraped at all, ever, except by not putting things online. … | Continue reading


@christiantietze.de | 8 months ago

Developer Voices on Property-Based Testing Made Me Realize PBT’s Value

I listened to “Automate Your Way to Better Code: Advanced Property Testing (with Oskar Wickström)” and I believe that Property-Based Testing (PBT) clicked for me a bit now. Maybe. It never made sense to me before, but Oskar Wickström has a lot of actually interesting examples. My … | Continue reading


@christiantietze.de | 8 months ago

TableFlip v1.6.0: JSON Support and Font Resizing

TableFlip v1.6.0 got approved to the Mac App Store (direct customers got the update a bit earlier, as usual). The least exciting feature first, so that it doesn’t go unnoticed: you can now scale the font in TableFlip (aka “zoom in and out”). Now the true highlight of this version … | Continue reading


@christiantietze.de | 8 months ago

Portable Every-Day-Carry Paper Kanban

I found this among my notes from 2013, and think it’s a fun little tool for analog productivity – the portable Kanban board! It’s a foldable personal Kanban board, suitable as an Every Day Carry in either A3 or A4 size (or US Letter or whatever). Fold the sheet of paper along t … | Continue reading


@christiantietze.de | 9 months ago

Splitting Large Tasks is not a Mathematical Process

Here’s an anecdote for you: Imagine a dev team that performs task estimates expressed in “story points”, Agile style, and encounters a large estimate. Large, in this team, means “13 or more.” Then in one of these sessions, a specific task initially received an estimation of 13 st … | Continue reading


@christiantietze.de | 9 months ago

SwiftUI Field Guide

Chris Eidhof and team launched the SwiftUI Field Guide website today. I noticed that Chris fiddled with JavaScript animations and layout representations to mimick SwiftUI as close as possible and wondered what kind of e-book could be upcoming, but it turns out it’s a website! Cha … | Continue reading


@christiantietze.de | 9 months ago

Looking for Testers: Typers of Japanese, Chinese, and Korean Characters

I’m looking for testers for my macOS apps TableFlip and WordCounter to get an opinion on how accurately characters and “words” are counted, how text alignment in documents look. Reach out if that’s you! hi@christiantietze.de Hire me for freelance macOS/iOS work and consulting … | Continue reading


@christiantietze.de | 9 months ago

Example of Object Tag vs Topic Tag in Programming Zettelkasten

Went through some old notes this week (I’m doing this AppKit/UIKit stuff for surprisingly many years!) and found a problem with the tags I used in one of my notes. Let’s dive right in with an example: # 201801251531 Copy NSView contents into NSImage #appkit #image #screenshot ... … | Continue reading


@christiantietze.de | 9 months ago

When Actions of NSSegmentedControl in Toolbars Do Not Fire In Their Overflow Menu Item State, Do This

In this fourth and probably still not final part of my series on NSToolbarItems with segmented controls, I just want to share a problem and a quick fix that Nathan Manceaux-Panot brought up today. The series spans 8 years and is this: Original Approach Enabling/Disabling Segme … | Continue reading


@christiantietze.de | 9 months ago

Life Hack: Label Your Trash Bins

I can’t for the life of me remember which trash bin bag size to buy. Once I find a fit, it’ll be months before I buy the next batch. By then, I’ve long forgotten which one I bought. Some more expensive ones have the bag’s size printed all over them. That helps exactly one (1) tim … | Continue reading


@christiantietze.de | 9 months ago

32-Bit Cafe: Personal Website Ideas

Here’s a truly inspirational list of things to do from the 32-Bit Cafe, “a community of like-minded website hobbyists and professionals helping to make the personal web fruitful and bountiful again”. It covers these topics: Page Ideas Potential Website Topics CSS & Page Desig … | Continue reading


@christiantietze.de | 9 months ago

Low App Prices are Preemptive Excuses

Developers see the bugs and problems of their products, and thus they are prone to not charge a high price instinctively. The price of an app signals its value or worth to the prospective customer looking at the price tag. Jordan Morgen shares this from the Spend Stack days: It … | Continue reading


@christiantietze.de | 9 months ago

Have You Ever Sent an Email with a File Attachment that is Located on a Server?

Today was a day of convergence. Our home server/NAS had a lot of SATA-related kernel errors and drive failures in the past weeks that I couldn’t track down. I replaced the drive and the cables and things have quieted down. This means I was SSH’ing into the server quite a bit this … | Continue reading


@christiantietze.de | 10 months ago

Transformative Reading ... 2017 Edition?!

So I found this list of books I read and which I wanted to put on this blog in my inbox. It’s from a migration from OmniFocus to Emacs/org-mode from 2019, and the title is “Transformative Reading 2017”. What were the picks back then? And being 7 (!) years wiser, what do I think a … | Continue reading


@christiantietze.de | 10 months ago

ChatGPT Shell: Confirm Before Closing and Split Compose Buffer

I admit: I’ve been relying heavily on ChatGPT to get to grips with some PHP things. Asking for interpretation, alternatives, and PHP 8-specific stuff was a lot of help. I’ve been using this in a separate floating window (aka ‘frame’) in Emacs next to my editing context, and that … | Continue reading


@christiantietze.de | 10 months ago

Emacs sqlite-mode to Open .sqlite Files Automatically

Normally, you’d associate file path extensions with major modes in Emacs via auto-mode-alist. The associative list contains entries like ("\\.html" . web-mode) so that when you open (aka “visit”) an HTML file, Emacs automatically switches to web-mode, which in turns supplies shor … | Continue reading


@christiantietze.de | 10 months ago

Cold-Blooded vs Warm-Blooded Software

So apparently, baby painted turtles survive being frozen. That’s the start of Patrick Dubroy’s blog post about cold-blooded software. Patrick likens software projects to warm-vs-cold-blooded animals: Cold-blooded: Some projects you can let sit around untouched for years without … | Continue reading


@christiantietze.de | 10 months ago

You Can Choose When You Live in Surplus

I was rummaging through my Zettelkasten today, looking for a reference. I found the note 20190823100132 You can choose when you live in surplus and in the spirit of celebrating a new year, I find it is worth sharing: Seth Godin in Living in Surplus: When you live in surplus, yo … | Continue reading


@christiantietze.de | 10 months ago

Timestamps with Weekdays

I’ve recently created a note in my Zettelkasten with a structure I haven’t used before: a timeline. It’s basically an enumerated list with 40 items and a divider that marks “now”. Things above the divide are in the past; things below the divide are in the future. I’m collecting r … | Continue reading


@christiantietze.de | 10 months ago

Show Organic Traffic in TelemetryDeck the Simple Way with a Values Breakdown Insight

Last time, I shared how to use the TQL Insight in TelemetryDeck to see organic traffic sources. Today, I want to share with you a much, much simpler approach to use TelemetryDeck to analyze website traffic without the need for the TelemetryDeck Query Language. I will guide you th … | Continue reading


@christiantietze.de | 11 months ago

Using Type Markers for 'is' Type Predicates

Maybe you have some old code (you wouldn’t write this nowadays, of course) that uses someValue is SomeType checks. Maybe you need to check if someValue is a generic type, like the following Box: struct Box { } Then your is predicates won’t work: switch someValue { case is Int, … | Continue reading


@christiantietze.de | 11 months ago

Dependency Injection via Protocol Composition

Watching Stephen Celis’ “How to Control the World”, NSSpain 2018 presentation, one of the common Swift/iOS patterns he brings up caught my attention. It’s this piece of code: protocol APIClientProvider { var api: APIClientProtocol { get } } protocol DateProvider { func date() - … | Continue reading


@christiantietze.de | 11 months ago

Update for modus-themes v4 and mlscroll.el Colors

Early this year, I wrote about my upgrade to modus-themes v4.x and how I used a custo mechanism to style the scroll bar indicator I like using, mlscroll.el, so that it looks nice. This week, J.D. Smith, author of mlscroll.el, pointed out that mlscroll.el’s color declarations nowa … | Continue reading


@christiantietze.de | 11 months ago

Ignore Generated Xcode .xcworkspace Files in Git Except Package.resolved

Sven Schmidt alerted me to the fact that you can check in Package.resolved to pin Swift package versions in Xcode-managed projects if you add the file from within the generated project.xcworkspace file in your .xcodeproj bundle: git add *.xcodeproj/project.xcworkspace/xcshareddat … | Continue reading


@christiantietze.de | 11 months ago

Show Referrers in TelemetryDeck for Web with a TopN TQL Query

The current TelemetryDeck for web setup guide (version of 2023-12-01) is quite simple. Insert this into your HTML, and you’re set: From that point onward, you’ll be collecting signals per web site hit. Internally, the signal’s type is "type":"pageview". These signals will inclu … | Continue reading


@christiantietze.de | 11 months ago

TableFlip v1.5.1

TableFlip v1.5.1 just got approved to the Mac App Store (direct customers got the update a bit earlier, as usual). Again: kudos to Marin Todorov for the export improvements on HTML! From the release notes: New: tableflip://preference/ added to URL scheme. It currently handles s … | Continue reading


@christiantietze.de | 11 months ago

Transforming JSON to Tables: the Impedance Problem

This is a note from 2022 I found by accident today. Teaser: It will become relevant again, soon, so I want to share the rough idea with you today. JSON data containing nested object lists within object lists, namely, arrays of objects within other arrays, cannot be mapped direct … | Continue reading


@christiantietze.de | 11 months ago

How Long Does a Disk Preclear in Unraid Take for 12TB of Data?

I’m upgrading my 4TB drives in the NAS to 12TB drives. “Let’s be clever,” I thought (foreshadowing), “and do two things in parallel!” So installing the next drive into the disk array of my Unraid NAS, I let Unraid do these tasks: Replace a 4TB disk in the array with a 12TB disk … | Continue reading


@christiantietze.de | 11 months ago

Embracing the AppKit Ways

Earlier today, I was posting some ad-hoc thoughts about how I prefer SwiftUI layout over programmatic AppKit on Mastodon. I expected this to become a blog post later today. But instead, I find myself thinking along the lines of: “am I holding this wrong?” I’m programmatically set … | Continue reading


@christiantietze.de | 1 year ago

Not Quite 100% SwiftUI – Time Makes Perfect

Marin’s Swift Heroes 2023 talk was just uploaded yesterday. It’s called “A 100% SwiftUI App”, and I believe you should watch it, because it’s not actually about what it says on the tin! Marin Todorov: “A 100% SwiftUI App”, Swift Heroes 2023 talk Marin’s a charismatic presenter an … | Continue reading


@christiantietze.de | 1 year ago

TableFlip v1.5.0 Released

TableFlip v1.5.0 just passed App Store Review. Direct customers got the update already. Thanks to Marin Todorov for helping on this version! The better performance with large tables, HTML export, and overall fixes are of his making ❤️ Here’s what’s new: Improved: Much better pe … | Continue reading


@christiantietze.de | 1 year ago

Sparkle v2.5 Adds Relevant Version Highlighting to Release Notes

Nathan Manceaux-Panot shared his contribution to Sparkle the other day, available in version 2.5. of the updater library: attaching CSS to parts of the release notes that are actually new to the user. Say you ship updates in x.x.1 increments to beta testers, but x.1.x updates on … | Continue reading


@christiantietze.de | 1 year ago

Portable Painter Micro Palette

Maybe you don’t know, but I’m organizing a local Urban Sketchers group in Bielefeld for 6 years. We meet regularly and draw and paint together. And that’s how I met your mother, – I’d say if you were my child. As a birthday present, I got a Portable Painter Micro palette from my … | Continue reading


@christiantietze.de | 1 year ago

UserDefaults.register(defaults:) Is a Bit Like Nil-Coalescing

I suggested the use of UserDefaults.register(defaults:) today. During the conversation, I realized that this behaves very much like the Optional/Nil-Coalescing operator ??. When UserDefaults have a stored value for a key, it’s like .some(...). When UserDefaults don’t have a st … | Continue reading


@christiantietze.de | 1 year ago

Year 36, a Retrospective

I’m usually not doing birthday posts, but a lot has happened, and it feels like more change is about to come. We got married in July. Ok, that’s the biggest change, and I could stop here. But there were other things that do pale in comparison, but which were still important: … | Continue reading


@christiantietze.de | 1 year ago

Kill Unsaved Emacs Buffers UX: Replacing Yes/No/Save with Meaningful Options

Upgrading to Emacs 29.1 worked like a charm. There’ve been a couple of small neat additions next to all the big changes like native tree-sitter support – and there’s one in particular that you could say I almost hate. Kill Anyway? Yes, No, Save and kill?! When I compose email and … | Continue reading


@christiantietze.de | 1 year ago

The Missing Array.appending(contentsOf:)

The Swift standard library has a mutating func append(contentsOf:), but not an immutable variant. Usually, the Array and Collection types offer both. I wonder why that’s not the case here. To be fair, the concatenation operator + does the same trick. Here’s a basic implementation … | Continue reading


@christiantietze.de | 1 year ago

Making Your App Extensible with JavaScriptCore: Annotated Presentation with Full Transcript

Last year, I posted my presentation video and slides for the CocoaHeads Aachen talk “Making Your App Extensible with JavaScriptCore”. Today I read about Simon Willisons’s presentation annotation tool. It’s a simple HTML file where you can put your slides, have Tesseract generate … | Continue reading


@christiantietze.de | 1 year ago

SwiftData: Store Image Data, but Actually Outside the Database

Tunds (@tundsdev@iosdev.space) shared a video tutorial about SwiftData this weekend. I hadn’t looked at SwiftData at all until now. The thumbnail read “Store Images in SwiftData”, and I was immediately worried: I recall it’s a bad idea to store megabyte upon megabyte of binary da … | Continue reading


@christiantietze.de | 1 year ago

Async XCTest Assertion Helpers

SwiftAsyncAssert by Angu (@angu@techhub.social): Instead of writing import XCTest func test_should_succeed() async { do { let isTrue = try await shouldSucceed() XCTAssertTrue(isTrue) } catch { XCFail("Should not throw an error") } } conveniently write imp … | Continue reading


@christiantietze.de | 1 year ago

Cocoa AppKit Responder Chain

The whole responder chain is traversed like the following, via the documentation for NSApplication.sendAction(_:to:from:): Start with firstResponder in the key window Try every nextResponder in the chain Try the key window’s delegate Try the same for main window, if it’s dif … | Continue reading


@christiantietze.de | 1 year ago

SwiftUI.View Is Your ViewModel

Remember when I wrote about MVVM and eventually in 2015 produced this: I learned that the “view model” in the architectural style of MVVM is a “model of the view” instead of a “model for the view”. Let me explain the difference and the benefits of being able to chose between bo … | Continue reading


@christiantietze.de | 1 year ago

Decoupling SwiftUI.View Configuration from Layout and Action Handling

Say you have a view component. You can control which sub-components it displays for maximum reuse. One day, you end up configuring the available effects, or actions, of the view component. Let’s say it’s something like this, a made-up example: enum AvailableAction { case cancel … | Continue reading


@christiantietze.de | 1 year ago

Inverted E-Mail Blockquotes

Is the following a thing in the U.S. of A, or common anywhere else, and I just didn’t notice that? For about a year, some people reply to email questions by interspersing their replies with my questions. That’s good in general to provide context. But what I don’t understand is th … | Continue reading


@christiantietze.de | 1 year ago

Super Saturday Sharefest: Matt Massicotte's XPC Work

Ok ok, I know Super Saturday Sharefest is not a thing, but it’s too late for Follower Friday, alright? I want to give a big shout-out to Matt Massicotte of ChimeHQ for dropping another awesome Swift open source package that makes using XPC Swift-ier. I’m really grateful for all t … | Continue reading


@christiantietze.de | 1 year ago

WordCounter v1.6.6 Released

I have released a maintenance update to my app, WordCounter. Check out the release notes. Some old code went out, some updated components went in. Most notably the date range picker from the statistics: Latest date range picker of your stats Since this update is built on modern m … | Continue reading


@christiantietze.de | 1 year ago

macOS Sonoma Menu Section Headers Look a Bit Off

Screenshot from “What's New in AppKit” (WWDC 2023) In my opinion, the new section headers of NSMenu don’t have enough top margin. In the WWDC 2023 example, there are no “descenders” in the menu title typo of e.g. “Section 2”. (Descenders are e.g. the lower-case g or p going below … | Continue reading


@christiantietze.de | 1 year ago