Christian Heilmann

You are currently browsing the archives for the General category.

Archive for the ‘General’ Category

Hemingway is now Hemingw-AI! My favourite writing tool just got an AI upgrade and it’s great.

Friday, August 25th, 2023

Disclaimer: I got no affiliation with Hemingway other than paying for it. I am just genuinely excited about this.

Hemingway is an app I use almost daily. It is a text editor that shows you when your language gets too hard to read. It advises you to keep shorter sentences and avoid complex language. It also tells you the reading grade level your readers need for your texts.

Hemingway editor showing a text with a lot of complex sentences coloured in different ways to indicate that I should edit it.

What I like most about it is how unobtrusive the editor is. It is very bare-bones but does what you expect of a text editor. I’ve seen a lot of “smart” writing suites that fail at the first hurdle by not providing a simple editor to start with.

Hemingway colours problematic parts of your text as you type it. This is an interaction that’s pretty common – think of spellcheckers in any editing suite. You have a legend on the right hand side explaining you what each background colour means.

You get the amount of words and a readability grade for the whole document. You can also see the Sentence count, paragraphs and expected reading time.

In the latest beta, Hemingway, much like any other tool these days, got an “AI” upgrade. The editor now not only tells you that something is wrong, but you can also ask it to fix the issues for you. Here’s how that looks:

Hemingway Editor fixing a complex sentence by offering a simpler one

This is nothing groundbreaking. Almost any editing suite I work with has an AI feature. But what I like here is how unobtrusive it is. AI becomes and editorial step, not a creation step. You can also hit ‘/’ to ask the editor to continue writing, as shown in this recording:

Other editors I tried that touted AI capabilities does this in a much more intrusive manner. Instead of a “let me help you write more”, they shouted “become a great writer at the push of a button”. It is especially annoying when they then to fail to provide content in a format akin to my writing style. If you ever see a text by me that uses the word “utilize” or “finding synergies”, rest assured that I’ve been kidnapped. And check the text for a cypher with information how to help me.

Ironically, it seems that AI created text by Hemingway fails to adhere to its simplicity rules as shown in this recording.

Generated text content of Hemingway fails to adhere to its own simplicity rules

Something to fix soon, I suppose.

Check the following YouTube video for a quick walkthrough where I edited one of my last blog posts.

All in all, this is a great example how to add AI to aid the writing process. Not to replace it with automated text optimised for machines or SEO. I like it and look forward to see more of what’s coming next.

Quick tip: Getting all links from any web site into a spreadsheet using browser developer tools

Thursday, August 24th, 2023

As part of taking over the editorial job of the WeAreDevelopers newsletter, I needed to get all the links from older editions and import them into a spreadsheet. Eventually I will write a scraping script, but there is a much simpler way to get all the links from a web site into a spreadsheet: browser developer tools. You can follow how that’s done in this video:

The step-by-step instructions:

  • Go to the web site you want the links from
  • Open Developer Tools (press F12)
  • Go to the Console tool
  • Enter (or copy and paste) the following: console.table($$('a'),['innerHTML','href'])
  • Highlight the table with your mouse
  • Copy and paste into your spreadsheet, making sure to only copy the values

This works in Microsoft Edge, Google Chrome, Firefox but for some reason not in Safari

Another issue is that long links and link texts get shortened with a … in Chrome and Edge, to work around that you need to shorten the links first. In my case, I removed the `utm_source=` tracking info. To this end, I had to write another short script in the console to run first.

Using $$('a').forEach(l => {l.href = l.href.replace(/?utm_source=.*$/,'')}) replaces all the utm_source tracking info on each link before calling the console.table.

Adding GitHub repository info, pages links and latest commits to any page using github-include

Tuesday, August 22nd, 2023

GitHub is where code lives. You make your updates there, and in the case of frontend work, you can even host it in GitHub pages.

When I publish something, I write a blog post and often I put some of the code in the post. When feedback comes in about new features I update the code and then I dread to also update the blog post. So, instead, I wanted to find a way to offer a link to the GitHub repo that shows the main link, a link to the GitHub pages, and show the latest commits. This allows people to see what changed in the code without me changing the post.

To make this happen, I wrote github-include, a web component that allows you to add a link to a repo to your blog post. It then converts it to a card showing the main repo link, a link to the GitHub Pages demo and the last x commits.

For example, the following HTML code gets converted to the card shown as an image here:

<github-include commits="5" pages="&#x1f30d;" links="true">
    <a href="">
       Mastodon Share

Recording of the web component in action

By default, it detects the setting of your OS and displays either as a dark or a light theme. If you don’t want any styling at all, you can also use plain HTML instead of the web component:

<div class="github-include" 
  <a href="">
  Mastodon Share

You can see it in action on the demo page .

You can customise all the functionality and labels of the component using attributes. These are all documented in the README .

Adding a “share to mastodon” link to any web site – and here

Friday, August 18th, 2023

I just added a “share to mastodon” link to this bloh. Ages ago I added a “share to Twitter” link, as there is a URL you can send Tweet content to that works:{URL}&text={TEXT}?&via={TWITTER_HANDLE}

With Mastodon, it wasn’t as easy as it is a federated service and there is not one URL. So I had to find a way to ask people for their service URL, and then store it somehow.

I’ve seen quite a few solutions for this, but I really wanted a bare-bones one that you can style any way you want. So here’s mastodon-share for you.

Mastodon Share

In order to add a “share to mastodon” link, all you need to do is to add a link with the class “.mastodon-share” and include the script:

<a href="#" target="mastodon" class="mastodon-share" rel="noopener">
Share to Mastodon
<script src="mastodon-share.js"></script>

The script is ridiculously simple, if you check it out:

// Grab link from the DOM
const button = document.querySelector('.mastodon-share');
// When a user clicks the link
button.addEventListener('click', (e) => {
// If the user has already entered their instance and it is in localstorage
// write out the link href with the instance and the current page title and URL
if(localStorage.getItem('mastodon-instance')) {
  button.href = `
// otherwise, prompt the user for their instance and save it to localstorage
} else {
    let instance = window.prompt(
      'Please tell me your Mastodon instance'
    localStorage.setItem('mastodon-instance', instance);

(yes, the comments were generated by GitHub CoPilot).

You can try it out on GitHub .

On my blog, I use WordPress and thus wanted to make the links also work when JavaScript fails for some reason, so I am using a slightly different approach. The PHP is:

<p class="mastodonshare">
  <a class="tootshare" 
            echo get_the_title().' '.
     ?>" target="blank" rel="noreferrer noopener">
       Share on Mastodon <span>(needs instance)</span>

In the JavaScript, I also remove the span once the instance is stored in LocalStorage:

const button = document.querySelector('.tootshare');
    let key = 'mastodon-instance';
    let prompt = 'Please tell me your Mastodon instance';
    if(localStorage.getItem(key)) {
    button.addEventListener('click', (e) => {
    if(localStorage.getItem(key)) {
    button.href = button.href.replace(
    } else {
        let instance = window.prompt(prompt);
        localStorage.setItem(key, instance);

Hope that helps!

I also came across the mastodon-share button by grayleonard that uses an input field on the button to allow you to specify the instance, but doesn’t store it. It looks nicer, though.

You can also use to avoid having to request the mastodon instance people want to use, but I didn’t want to rely on another service.

What’s my job in my new role as Director of DevRel at WeAreDevelopers?

Wednesday, August 16th, 2023

Now, with the World Congress out of the way, it is time to focus on my new role as Director of Developer Relations at WeAreDevelopers.
It feels great that what I do anyways because of personal interest is part of my role. This was the case when I worked for Yahoo and Mozilla and the first few years in Microsoft, but pivoting to Technical Product Management, I was missing this part. I had to take vacation days to present at events and there was no budget for any DevRel activitives.

Now, what am I going to do for WeAreDevelopers? I will be leading and coaching a team of DevRel people and whilst this is small for now, there is growth in the near future.

For now, I will be:

  • Content editor of the DevDigest newsletter and blog and see what else we can do with that.
  • Recording interviews and fireside chats with interesting people in the Coffee with Developers series.
  • On the advirsory board for the WeAreDevelopers World Congress and plan the content of this 12,000 people event.
  • Keep evolving the Code100 competition and how we can make this easier to run, so that other events can also take part.
  • Working on some event strategy that goes beyond the big congress, with Bits and Bites meetups and a the WeAreDevelopers Live series.
  • Presenting at events, doing training courses and coach and mentor people inside and outside on public speaking, video creation, writing and presenting.

As WeAreDevelopers is also a job board, I also want to work closely with our recruiters and content editors to ensure that developers and those trying to hire developers speak the same language.

For all of this, I’d love input from you. You can:

  • Propose content items to write about and include in the newsletter
  • Propose people to interview
  • Tell me what a unique product like WeAreDevelopers can do to become your go-to resource for all things developer

Ping me on any of the channels I am on, or send content ideas to

I’m looking forward to what comes next!