• VMWare Fusion 10 on macOS Catalina

    This post is for those of us running an older version of VMWare Fusion on macOS Catalina. VMWare Fusion 11.5 supports macOS 10.15 out of the box.

    I use VMWare Fusion 10 to test my apps on previous and future versions of macOS. Since this fall, that’s become problematic. The screen remains blank when I start one of my virtuals on Catalina. Oddly enough the preview in the virtual machine overview works fine.

    Catalina requires apps to request permission for various tasks. Recording the screen is one of them. Apparently Fusion uses this feature, but neglects to ask for permission. Thus the screen stays black.

    Some people found a way to get around this by granting permission manually. Here’s how that works.

    ⚠️ Note that this requires running Terminal commands in Recovery Mode. Make sure you’re comfortable with these steps. I don’t offer any support and am not responsible if things don’t go as planned. ⚠️

    Create the script

    Create a new script file where you can easily access it. I recommend /tmp/ Paste in the following:

    # Change the following to fit your system
    root="/Volumes/Macintosh HD"
    "$root/usr/bin/sqlite3" "${root}/Library/Application Support/" 'insert into access values ("kTCCServiceScreenCapture", "com.vmware.fusion", 0, 1, 1, "", "", "", "UNUSED", "", 0,1565595574)'

    Enter Recovery Mode

    Enter Recovery Mode by restarting your Mac and holding down + R while it boots.

    Start a Terminal window by selecting UtilitiesTerminal from the menu bar when you’ve reached Recovery Mode.

    Unlock your disk if necessary

    If your primary drive is encrypted using FileVault (it should be), unlock it first by running the following command:

    diskutil apfs unlock "Macintosh HD"

    (Again, adjust the command if your disk isn’t called “Macintosh HD”.)

    Enter your passphrase when it asks for it.

    Run the script

    You can now run the script you created earlier:

    sh "/Volumes/Machintosh HD/tmp/"

    It’s supposed to not show any output. If there’s no error, it worked.


    Check System PreferencesSecurity & PrivacyPrivacyScreen Recording and you’ll notice VMWare Fusion has the permission it needs.

    A screenshot of System Preferences showing permission for VMWare Fusion to record the screen

    That’s it. Your virtual machines should properly work again. 🥳

  • Sponsor me on GitHub

    GitHub entered me into their sponsored developers program!

    This means you can easily support me through my repos or the projects I contribute to. 👯‍♂️

    I made a page where I feature the generous people who sponsor me:

  • Migrating away from DevMate: redirecting Sparkle updates

    Originally appeared on

    DevMate is the service I use to gather download and install statistics for most of my apps. It also serves the update feeds for all non-Mac App Store apps. Earlier this year DevMate announced its retiring the platform in December.

    A screenshot of my DevMate dashboard, showing about 50 downloads and 30 installs for Timeless in the past 30 days and 100 downloads and 60 installs for Pipvid

    In this post I’ll outline how I’m preparing my apps to migrate to a new update feed. Christian Tietze mentions asking DevMate to point the Sparkle update feed to a new location. He also recommends to not rely on DevMate’s redirect to work forever. That’s where my approach comes in.

    I urge you to take control over the feed URL entirely and redirect it yourself. DevMateKit uses Sparkle under the hood. This means a custom update URL can be specified by implementing a Sparkle delegate method.

    Setting the URL

    class ApplicationCoordinator: NSObject, Coordinator {
      private func configureUpdates() {
        DM_SUUpdater.shared().delegate = self
    extension ApplicationCoordinator: DM_SUUpdaterDelegate_DevMateInteraction {
        func feedURLString(for updater: DM_SUUpdater) -> String? {
            if Defaults.shared.isEnabled(setting: .betaUpdates) {
                return .appcastBetaURLString
            } else {
                return .appcastURLString
    extension String {
        static let appcastURLString = "\(Bundle.main.bundleIdentifier!)/appcast.xml"
        static let appcastBetaURLString = "\(Bundle.main.bundleIdentifier!)/beta-appcast.xml"

    After this change Timeless will check for updates at The domain is mine and I can set redirects for it however I want.


    I use Netlify to handle the redirects. Here’s what that looks like:

    com.dangercove.Timeless.Mac/appcast.xml*       301
    com.dangercove.Timeless.Mac/beta-appcast.xml*  301

    As you can see I currently redirect to the feed at DevMate, but I can redirect it anywhere else whenever I want. This allows me to use DevMate for as long as possible and switch to any other service that uses Sparkle. I’m keeping a close eye on App Center by Microsoft. They put Sparkle feeds for macOS on the roadmap for September.

  • Fix "mapped file has no Team ID and is not a platform binary" in Xcode 11

    After applying the preferred project settings in Xcode 11 you might be confronted with the following error while loading a Library at runtime:

    dyld: Library not loaded: @rpath/DCOAboutWindow.framework/Versions/A/DCOAboutWindow
      Referenced from: /Users/username/Library/Developer/Xcode/DerivedData/Pipvid-adwfbkaurzovizgaarwkmugeihce/Build/Products/Debug/
      Reason: no suitable image found.  Did find:
    	/Users/username/Library/Developer/Xcode/DerivedData/Pipvid-adwfbkaurzovizgaarwkmugeihce/Build/Products/Debug/ code signature in (/Users/username/Library/Developer/Xcode/DerivedData/Pipvid-adwfbkaurzovizgaarwkmugeihce/Build/Products/Debug/ not valid for use in process using Library Validation: mapped file has no Team ID and is not a platform binary (signed with custom identity or adhoc?)

    The issue is caused by a new entry in your project.pbxproj that specifies the signing identity: CODE_SIGN_IDENTITY = "-";. It’s set to Sign to Run Locally by default.

    Changing Signing Certificate to Development under Signing Capabilities in the project settings resolves the issue. You could also manually update the entry to CODE_SIGN_IDENTITY = "Apple Development";.

    A screenshot showing that you should set 'Signing Certificate' to 'Development'

  • Related content with Jekyll and other Liquid tricks

    This article originally appeared on

    As promised, in this second part of the website redesign story I’ll go over the technical details of the changes I made to

    Stack & frameworks

    To get a sense of how the website’s built, here’s an overview of what I use to layout and serve its content.

    It’s a simple setup. The entire site is statically generated by Jekyll and then served by Netlify. Bulma is a CSS framework that allows me to style templates quickly.


    Let’s take a look at the homepage first. The list of apps is generated by including the app/overview.html template and assigning it a set of apps pages.

    {% assign live = site.pages | where: 'layout', 'app/live' %}
    {% assign announced = site.pages | where: 'layout', 'app/announced' %}
    {% assign apps = announced | concat: live %}
    {% include app/overview.html apps=apps %}

    I fetch the apps to display by querying site.pages for pages that use the app/live and app/announced layout. Then I concatenate both arrays into a single apps variable and pass that to the includable app/overview.html template.

    A screenshot of the homepage after the changes. It shows a compact row of boxes that represent all the apps.

    Overview template

    The app/overview.html template checks if it’s on the homepage (if page.layout == "home") and adds the Danger Cove logo accordingly.

    {% if page.layout == "home" %}
    <div class="column is-4-widescreen is-half-desktop is-full-tablet is-full-mobile">
      <div class="box is-shadowless has-text-centered">
        {% include logo/retro.html %}
        <h1 class="title is-size-2-mobile is-1 is-spaced">{{ page.title }}</h1>
        <h2 class="subtitle is-size-5-mobile is-4">{{ page.subtitle }}</h2>
    {% endif %}

    Then it loops over the provided apps and includes app/introduction.html for each. This is the actual visual representation of the app, in the form of a card. Pulling it out into a separate include makes it trivial to display the app card anywhere else. I’ll use it again when showing related apps with blog posts. More on that a little further down.

    {% for app in apps %}
    <div class="column is-4-widescreen is-half-desktop is-full-tablet is-full-mobile">
      {% include app/introduction.html app=app %}
    {% endfor %}

    Notice the convenient column CSS classes that Bulma provides. It’s trivial to scale the layout from mobile to widescreen devices.

    Front matter

    The app/introduction.html template pulls the title, subtitle, description and colors from the app’s front matter. This is what the front matter for Timeless looks like:

    layout: app/announced
    site_title: Don't get distracted by time
    title: Timeless
    subtitle: Reduce time anxiety
    description: >-
      Get a more subtle sense of what time it is. Reducing time pressure and distraction.
    date: 2018-07-18
    icon: timeless-clock_512.png
      icon: timeless-clock_512.png
        r: 200
        g: 200
        b: 200
      - Specify several, customizable 'time segments'.
      - Indicates the current segment in the menu bar.
      - Display the actual time and date with a single click.
      - macOS
      - Productivity
    topic: timeless
      interests: [2]
    permalink: /timeless/

    Every card shows a specific rainbow of colors in its bottom right corner. Storing this information in the page’s front matter allows me to pull it out in the template and apply per-app design details.

    {% assign color = app.hero.dominant_color %}
    <div class="box" style="background-image: linear-gradient(135deg,
    transparent 80%,
    rgba({{ color.r }}, {{ color.g }}, {{ color.b }}, 0.25) 80%,
    rgba({{ color.r }}, {{ color.g }}, {{ color.b }}, 0.25) 85%,
    rgba({{ color.r }}, {{ color.g }}, {{ color.b }}, 0.5) 85%,
    rgba({{ color.r }}, {{ color.g }}, {{ color.b }}, 0.5) 90%,
    rgba({{ color.r }}, {{ color.g }}, {{ color.b }}, 0.75) 90%,
    rgba({{ color.r }}, {{ color.g }}, {{ color.b }}, 0.75) 95%,
    transparent 95%)

    It’s hard to get around using style="" for this loop. On the app’s landing pages I apply the colors to a generic CSS class that I can use in the template.

    {% if page.hero.dominant_color %}
    {% assign color = page.hero.dominant_color %}
      .hero-app {
        background: linear-gradient(35deg,
        transparent 60%,
        rgba({{ color.r }}, {{ color.g }}, {{ color.b }}, 0.25) 60%,
        rgba({{ color.r }}, {{ color.g }}, {{ color.b }}, 0.25) 70%,
        rgba({{ color.r }}, {{ color.g }}, {{ color.b }}, 0.5) 70%,
        rgba({{ color.r }}, {{ color.g }}, {{ color.b }}, 0.5) 80%,
        rgba({{ color.r }}, {{ color.g }}, {{ color.b }}, 1) 80%,
        rgba({{ color.r }}, {{ color.g }}, {{ color.b }}, 1) 90%,
        transparent 90%);

    Setting class="hero-app" atomatically applies the rainbow background for each app.

    News overview

    Before: A screenshot of the news overview before the changes. It showed an endless list of post titles. After: A screenshot of the news overview after the changes. It's a paginated list of full articles. Ready to read.


    Loading all posts on the /news page would be madness. The first step I took was to implement the jekyll-paginate-v2 plugin:

    1. Add gem "jekyll-paginate-v2" to Gemfile:
       group :jekyll_plugins do
         gem "jekyll-paginate-v2"
    2. Activate the plugin in _config.yml:
          - jekyll-paginate-v2
         enabled: true
         sort_reverse: true # Required in my setup to order posts from new to old 
         permalink: "/page/:num/"
    3. Add pagination settings to the news.markdown front matter:
         enabled: true
         per_page: 5

    The pagination plugin is ready to be implemented in _layouts/news/home.html at this point. It comes down to two things:

    1. Replacing {% for post in site.posts %} with {% for post in paginator.posts %} in the template.
    2. Including the paginator controls somewhere on the page.

    Full post content

    I updated _includes/post/preview.html to show the entire post instead of just a preview. That’s it.

    A screenshot of the Timeless 'card' shown under an article about Timeless.

    This new feature uses some front matter magic to allow me to pull in related content with a blog post. Consider the _includes/post/related.html template:

    {% assign tags = include.tags %}
    {% for tag in tags %}
    {% assign app = site.pages | where: 'topic', tag | first %}
    {% if app %}
    {% include app/introduction.html app=app %}
    {% endif %}
    {% endfor %}

    Usage: {% include post/related.html tags=post.tags %}

    It loops through all tags assigned to a post and then searches site.pages for a page that has a topic that matches the tag.

    Imagine I write a post about Timeless and tag it like this:

    tags: [updates, timeless]

    If you look in the front matter for Timeless above, you’ll notice its topic:

    topic: timeless

    The app variable gets assigned and the app/introduction.html card template gets included. If the tags include multiple apps, each is shown.


    The full source code for is available on GitHub. For a comprehensive list of all changes made for this redesign, take a look at this diff: 3493aae..4518428

    I hope you enjoyed this in-depth look at how I keep up-to-date. If you have any feedback, questions or comments let me know on Twitter.