I've been writing, presenting, and teaching my entire career, even when it wasn't my primary job. I created tutorials using Microsoft Word and converted them to PDFs, and I used PowerPoint and Keynote when I did slides for conference talks. But those tools always got in the way of the content creation process. And despite my using HTML for ages, it also never felt right. So I looked into text-based methods like DocBook, which I actually like, but that required a lot of XSLT knowledge.
This quote from The Pragmatic Programmer always stuck out to me:
As Pragmatic Programmers, our base material isn't wood or iron, it's knowledge. We gather requirements as knowledge, and then express that knowledge in our designs, implementations, tests, and documents. And we believe that the best format for storing knowledge persistently is plain text.
Plain text is terrific. It's always going to work, but it always seemed so limited compared to what people expect.
But then Markdown came along, and it caught on enough for many other tools and teams to adopt it, making plain text a reality. Today, I use Markdown for nearly everything I create, from articles, conference talks, educational materials, my website, and even this newsletter.
So, in this issue, I'll share the tools and processes I use and how you can use them in your work.
Drafts is a Mac and iOS app I found a few years ago. It's a Markdown-based notes application with tagging and powerful community plugins. Despite its features, Drafts feels fast, and its minimalistic interface keeps you focused on writing.
Everything I do starts in Drafts. I can work seamlessly between my phone and my Mac. I can start a draft by dictating into my phone, and by the time I walk over to my computer, the text is already on the screen in the desktop version.
It's a great tool for sketching out ideas, but it's also good for storing temporary content. I can save a URL or a text snippet into a new Draft from my phone, or I can use automations in Drafts to take my idea and create a social media post.
I mentioned that many community plugins are available, and you can create and share your own automations. For example, I made an automation that sends the current document to an Obsidian vault. We'll get to Obsidian in a bit.
Drafts isn't free, but it's well worth the yearly subscription fee to support a great product.
I use Vim to write my technical content, including books, articles, and conference slides. It's also where I do heavy editing. I use Vim to write code in multiple languages. My Vim environment is heavily customized, and anything else just slows me down when it comes to technical content development. I have built up many custom shortcuts for Markdown, but I often rely on Vim's built-in modal editing tools as I work with text.
Here are a few that I use daily:
ciw
: This is an editing command I learned years ago. It's "change inner word." If you place your cursor anywhere on a word, typing this sequence deletes the word and automatically puts you in Insert mode so you can "punch in" the new word. It's faster than positioning the cursor at the start of the word or deleting it.ci"
or ci(
: Like cil
, but it lets you change all of the content within double quotes or parentheses, respectively. cit
: This variant lets you change the content within an HTML tag. Place your cursor anywhere on the text between the opening and closing tags. `.
: This is a backtick, followed by a period. This combination automatically jumps you back to the last place you inserted text. This is great for long documents. If you scroll up to read something and need to return to where you were editing, use this combo to get back there quickly.I do a lot of work with command-line tools and often use Vim's built-in terminal to run my examples. I can then use Ctrl+W
Ctrl+N
to turn the terminal window into a Vim buffer and capture all of the input and output for the session. I can then write prose and explanations around the sections of the session.
I use the vim-markdown plugin, which properly colors Markdown elements and handles source code highlighting within code fences. I also use Ale, a general-purpose syntax checker for many programming languages. It works with Vale, a prose linter I wrote about in issue 14. With this combo, I see real-time feedback on any style violations.
Vim is free and available everywhere. If you're using macOS, it's already installed. But if you're not ready to make the switch, you can find a VSCode plugin that will make VSCode act like Vim so you can use some of the shortcuts I mentioned here. There's also a Vale plugin for VSCode.
Typora is a WYSIWYG Markdown editor. While you can edit the raw Markdown, the real power of Typora is that you can see what the output will look like while editing. Other Markdown preview tools automatically refresh when you make changes in your editor, but Typora acts like a regular word processor. I often use it for final touches, but I've occasionally used it to write content. It's such a good experience.
It's also good at converting content from other sources. You can copy content from a web page, word processor, or even Notion, and Typora can often convert it to Markdown.
It also has the best support I've seen for working with images in your document. You can set up a folder for your images relative to your document, and when you paste your images into the document, they'll be stored in that folder. The links get inserted into your document with the proper paths.
Typora has a handy table builder like the ones you'd find in other word processors. Markdown tables are a little tricky to create, so this speeds things up. It also has an outline view so you can see your table of contents while you work.
Finally, Typora can export to PDFs, HTML, RTF, and even LaTeX.
Typora isn't free, but the $15 one-time price lets you use it on your desktop and laptop.
Obsidian is a Markdown-powered writing and knowledge management tool that many technical content people love. You can think of it as a personal Wiki.
You might find Obsidian to be a great writing tool. It has many of the same features as Typora. It can export content and work with tables, and it has a more WYSIWYG look. However, there are many plugins and settings you may need to investigate to make it fit how you work.
The best feature, by far, is that your Obsidian vault is just a collection of folders that contain text documents. There's no proprietary format or packaging system like other tools have. It's just a bunch of files on your disk. That makes them easy to back up and import into other processes. Need to do something with a file in your Obsidian vault? Open it up on any other program that supports Markdown. Got existing Markdown documents from another project? Move them right into your Obsidian vault.
I use Obsidian for long-term storage and archival. I store information I need to organize and find later, like text clippings, code samples, teaching notes, research, journals, and much more. I used Evernote for a lot of this but switched to Obsidian after Evernote raised their prices again.
I used VimWiki for a long time to store my work journals and other notes, and I was able to migrate that content by copying my Markdown files right into my Obsidian project. It was a seamless transition. Now I have a single place where my archives live, and it's all plain text with assets in folders instead of a proprietary format that locks me in.
Obsidian is free, but they offer a paid sync service. macOS and iOS users can sync with iCloud, which works well.
I've hinted that I use Markdown for my slide presentations, and while there are many tools for presenting Markdown-based slides, a macOS app called Deckset towers over them all for me.
Deckset lets you focus on the content instead of the visual layout. Here are a few examples:
^
). When you export the slide deck as a PDF, you can have those notes printed, and of course, you'll see them on your screen.With Deckset, you build your entire presentation in a single document using your own text editor. Deckset's desktop application automatically refreshes when you save the presentation file. Use a Markdown horizontal rule to separate each slide, and use headings, paragraphs, and bullets for your content.
There are many times I've been able to turn a written document into a presentation by adding in some line breaks, removing some text, moving some text to presenter notes, and adding some images from Pexels. And Deckset can cache images from the web, so things will still work if you're presenting without Internet access.
I wish Deckset was available on other operating systems because it's a fantastic presentation tool. I used Keynote for many years, but with Deckset, I can version my slides in Git along with my code.
Deckset costs $35, but it's worth the price when you see how much time you'll save.
If you're building technical content aimed at developers, you will have code examples in your content. And those code examples need to be correct and current. Pasting code into Markdown documents may work for a while, but then you have to keep it in sync as you update the code.
When I joined Temporal last year, I learned their documentation team built and released an open-source tool to pull content from Git repositories into their docs. The project is called Snipsync, and it's a great way to ensure that the code you place in your content is correct. Pulling code snippets from real, working demo applications rather than pasting code snippets into your Markdown ensures that your examples work and stay current.
To use Snipsync, you create a snipsync.config.yaml
file in the root of your project that specifies the repositories you'll pull down and where the target files are located:
origins:
- owner: temporalio
repo: go-samples
targets:
- docs
Then, you install Snipsync either globally or as part of your project using npm
.
In your code, you add Snipsync markers around your code:
// @@@SNIPSTART hellouniverse
func HelloUniverse() {
fmt.Println("Hello Universe!")
}
// @@@SNIPEND
Then, in your document, add Snipsync markers where you want the code to go:
The following code sample shows how to write a Hello function in Go:
<!--SNIPSTART hellouniverse-->
<!--SNIPEND-->
Run the snipsync
command-line tool to insert the code into the documents. When the external files change, rerun the command. Remove all of the inserted snippets with snipsync --clear
.
The Snipsync README has more information on configuration and usage. I'm grateful that this tool is available. I use it every day at work, and I use it for a lot of personal content projects as well. I'm using it with Deckset to inject code into my slides.
Hugo is a static site generator that ships as a single binary with no external dependencies. It turns a folder of Markdown files into a set of static HTML files you can publish to any infrastructure you need. I love Hugo. I wrote a book about it which shows you how to build your own personal site using it.
My publishing process is very minimal. Since everything I create is Markdown-based, publishing content means copying the content into the content
folder of my Hugo site and running my deploy script.
There are many other Markdown-powered site builders, but Hugo is my favorite because I don't need to set up a complex toolchain to build the site. I've used other tools and wrestled with dependencies instead of publishing content.
Hugo is free and open-source and runs on Windows, macOS, and various Linux flavors.
Those are the tools I use to build content with Markdown. In fact, this issue started in Drafts, which I dictated from my phone. I then moved the content into Vim, where I wrote most of the content. I then opened it in Typora to insert hyperlinks in a few places I forgot and verified that the visual presentation looked good. Finally, I pasted the Markdown into Buttondown, the newsletter service I use, which supports Markdown.
Because Markdown is plaintext, I occasionally use a handful of command-line tools like sed
and pandoc to do additional processing. It's another advantage of using open formats. For example, I have a script that uses sed
to pull some content out of Obsidian into my Hugo site.
As always, here are some questions for you to think about before the next issue:
Thanks for reading this issue. See you next month.
I'd love to talk with you about this newsletter on Mastodon, Twitter, or LinkedIn. Let's connect!
Please support this newsletter and my work by encouraging others to subscribe or by buying a friend a copy of Exercises for Programmers, Small, Sharp Software Tools, or any of my other books.