Adventures in Technical Writing
I’ve been reflecting lately on the important role of writing in open source and tech in general. With its focus on clarity, precision, and conciseness, technical writing calls for all the skills of the creative while bringing a full range of challenges and rewards. Here are selected highlights from my two decades of contributing to open source software, throughout which writing has been a key focus and source of engagement.
Interpreting specs: decentralized social networks
ActivityPub is a technical specification aimed at enabling decentralized social media platforms. When users began fleeing Twitter (now X) in droves for alternatives like Mastodon, it was ActivityPub that lay behind the decentralization they sought. For better or for worse, as of March, 2024, Meta’s Threads app also supports ActivityPub.
When I first started working with ActivityPub in late 2019, I found there was a notable lack of introductory information about the spec and how to use it. Engaging with the then-small ActivityPub community, I decided to fill this documentation gap. As well as a brief Introduction to ActivityPub and Guide for ActivityPub users, I produced a detailed Guide for new ActivityPub implementers to help newcomers get up to speed with the spec and how to build projects with ActivityPub support. As an added perk, I converted the entire ActivityPub spec into handy checkboxes for copying into ticketing systems.
Though the ActivityPub project I was part of didn’t go forward, years later the documentation I contributed - now collaboratively maintained - is prominently linked on the ActivityPub Rocks website, has had more than 90,000 views (not bad for a technical guide), and remains a premiere source of guidance for new ActivityPub developers.
Drupal documentation: then and now
From 2003 through 2023, I was a contributor to the open source software project Drupal, used for hundreds of thousands of websites worldwide. At 25 per page, my posts to the flagship project website Drupal.org span 248 pages, meaning I posted to over 6,000 distinct conversations or pages. Gulp!
Then: the first user guide and foundational documentation
When I first joined the Drupal project, what documentation existed was focused on the needs of developers. What about users of the software?
To address that need, in 2004 I wrote the first Drupal user documentation. On an archived 2004 version of the Drupal.org site, the resulting guide is certainly modest in retrospect. Nonetheless, it played a small part in helping move the software from a developer-centric ethos to one alive to the abilities, priorities, and perspectives of adopters and users.
In those early years, much that was key to the project was implicitly understood among a small group of nerdy contributors but nowhere written down. As a newcomer, I had found certain processes particularly opaque. How could you get started as a contributor? How were proposed changes evaluated? I recognized an information gap I could fill. I drafted and shared a proposed set of foundational documentation. Drupal founder Dries Buytaert commented of my documentation:
It is well-written, well-structured and complete but maybe a little long-winded. I’d remove some details and focus on the practical tips. Good job.
I took his astute advice and produced more succinct versions that he approved for public posting. Early archives of Drupal.org show key pages that I wrote and that helped guide the project and orient new contributors for many years:
- Mission
- Principles
- Decision-making structure
- Usability aims
- Criteria for evaluating proposed changes
- Contributing to Drupal
- Tips for contributing to core
That last link - Tips for contributing to core - encapsulates values and approaches I still hold and strive to live up to. Much has changed in the more than two decades since I wrote that documentation, but on Drupal.org today, for example, the Criteria for evaluating proposed changes survive in much their original form.
Now: Drupal Recipes and Config Actions
In 2024, the Drupal project is reinventing itself as “Drupal CMS” through the “Starshot Initiative”. Central to this initiative are two new Drupal core APIs: Recipes and Config Actions.
In the initiative that produced both new APIs, as I had throughout twenty years of project contributions, I played a quiet but necessary background role: that of documenter. Yes, it takes insight and technical chops to wade into an emerging code base and discover what it does and how it works. But to translate that discovery into something others can learn from and build on takes something more: a flair for language and expression.
I wrote the documentation in Markdown, my favourite markup format. When he merged my documentation into the project codebase (see that merge for the documentation itself), leading Drupal core maintainer Alex Pott commented:
I’ve merged this into our docs branch as it is a wonderful starter and I think will form the basis of further docs.
Thanks for this @nedjo.
Software products
Throughout my time in Drupal, I served as a primary maintainer of dozens of plugins, both “modules” (providing functionality) and “themes” (providing the look and feel of a website). Being an open source project maintainer often means taking on multiple documentation roles in addition to development. While less flashy and often undervalued compared with development, documentation is critical to success and calls for facility in a range of forms and formats.
Handbooks
A guide or handbook provides adopters and contributors the guidance they need to understand, use, and develop for an open source project.
Together with other contributors, I rewrote a popular Drupal plugin, the Features module, from scratch for a new Drupal version. As part of the effort, I wrote the handbook for the Features module in Drupal 8+. Covering topics ranging from changes in the new version to usage and how to develop for and extend the code base, the handbook provided a solid grounding in the project for everyone from new users to seasoned developers.
Release notes
Well written release notes accomplish a range of goals: to detail changes, to note any special deployment considerations, to credit contributors.
Occasionally, a particular software release involves complex considerations that need to be carefully explained to users so they have the full information needed before attempting an update. This was the case when a critical bug was inadvertently introduced in a release of the Features module for Drupal. While I was not a maintainer of the affected software version (branch), I jumped in to help diagnose and address the regression and collaborated closely with the maintainer to draft, revise, and publish comprehensive release notes.
More typical are these release notes I posted for a routine Features module update.
In-code documentation
When used well, comments can form an integral part of a code base. In the Drupal project, API documentation and comments standards provide a consistent basis for code documentation. They’re the source, for instance, of the API documentation site for Drupal core, generated programmatically from the comments embedded in code.
In many cases, code comments are appropriately spare. One of the many Drupal modules I wrote and contributed is Configuration Synchronizer, used to safely merge in configuration updates without losing customizations done on a particular site. Here’s me in a class in Configuration Synchronizer documenting a simple method by giving a summary of its usage while defining the name and type of a parameter and specifying the return value:
/**
* Sets the target storage used to discover configuration changes.
*
* @param \Drupal\Core\Config\StorageInterface $storage
* The storage to set as the target.
*
* @return $this
*/
From the same module, here’s an example from another file where I’ve provided more explanation as needed:
/**
* Takes a snapshot of configuration from specified modules or themes.
*
* Two modes are supported: install and import. Install mode is invoked when
* an extension is initially installed, while import mode is invoked on
* subsequent import of configuration updates.
*
* The distinction between install and import modes has implications for the
* handling of extension-provided configuration alters. Alters are considered
* to be "owned" by the extension that provides them. On install, existing
* snapshots should be altered only the newly-installed module or modules.
* This approach ensures the snapshot mirrors the installed state of the
* extension-provided configuration. In contrast, on import, alters should be
* applied from all installed modules.
*
* @param string $type
* The type of extension to snapshot.
* @param array $names
* An array of extension names.
* @param string $mode
* The snapshot mode. Valid values are:
* - ConfigSyncSnapshotterInterface::SNAPSHOT_MODE_INSTALL
* - ConfigSyncSnapshotterInterface::SNAPSHOT_MODE_IMPORT.
*/
Effective documentation isn’t needlessly verbose but provides sufficient detail in succinct and accessible language.
Issues
A key nexus in most open source communities is the issue queue. This is an arena where clear communication can make the difference between divergence and consensus. In my years in Drupal, I myself filed over 2,000 issues (the list of those issues may require being logged into a user account on Drupal.org), in addition to many others I commented on and updated.
Carrying out your work as part of an open community puts a particular stress on effective communication. A large open source community like Drupal’s may include many thousands of contributors, all of whom should feel welcomed and empowered to participate.
Clarity is particularly needed when a problem is hard to spot or seems tangential. This was the case, for example, with a subtle bug I noticed in Drupal core. Before posting a proposed solution, I made sure to concisely explain exactly what was wrong and how the issue could be addressed. Sure, to anyone outside the software project, the issue I filed - Editor module fails to track usage of files embedded in non-core fields - might appear obscure. But to my audience of developers, it gave just the right level of detail. Like many others, this subtle bug fix took several years to wend its way through the review process. But when it resurfaced, the cogent summary helped ensure it got attention and action.
In-app help
Finally, documentation tasks as a software maintainer include the tried and true approach of providing in-app help.
For example, in the Configuration Synchronizer module, I wrote help documentation to both summarize what the extension did and provide contextual help on specific pages where the interface might be non-obvious. In the issue I posted explaining the changes, I included screenshots of the resulting help as it appeared in the application.
Engaging an open source community
Working with an open source community calls for a particular flair with welcoming and involving participants and contributors. Through many stages of my career in open source, I’ve cultivated the inclusive approaches that encourage contribution and involvement.
2008-2009: Revolutionizing internationalization support in Drupal
In 2009, I led an impactful open source project sponsored by Sony Music to fundamentally overhaul support for internationalization (i18n) and localization (l12n) in Drupal. While the main work of the project was undertaken by my team at CivicActions, as tech lead I wanted to ensure we reached out to welcome, involve, and support the broader community. I reached out to the community to invite participation in a virtual code sprint. After the sprint, I reported back to the community, highlighting progress, recognizing contributions, and documenting learnings.
The project complete, I made sure to spread the word. My post to Drupal.org garnered comments like
This is an extremely well written and thought out article/explanation of a really fantastic project. Great work!
And the inevitable quips:
This is music to my ears! :)
2011-2012: Drupal Association at-large director elections
In 2011, the Drupal Association, the non-profit organization focused on accelerating Drupal, introduced a new category of board members: at-large directors who would represent the Drupal community. As a member of the Association’s Advisory Board, I was appointed to lead a committee tasked with designing an election system.
Doing so was no small task. With literally hundreds of thousands of community members, how could we cultivate a genuinely participatory process?
Working with the collaboration and guidance of Angie Byron (known in the Drupal community as webchick) and Donna Benjamin (kattekrab), I put out a call for participation and started a community-edited wiki page to gather ideas before convening and facilitating a series of international virtual community meetings to hammer out the nitty-gritty of a new participatory voting system. To give participants necessary grounding, I wrote a detailed backgrounder on Drupal Association governance and board elections, posting it as a wiki page others could add to and enhance. An emerging community consensus coalesced into a concrete proposal presented to and approved by the Drupal Association board of directors. It was time to celebrate. Through an inclusive and participatory process, we had a solid, community-designed system for electing community representatives.
As follow-up, I posted a series of updates throughout the first elections held under the new voting system, promoting visibility and transparency for both candidates and community members. Successful community engagement calls for both thoughtful planning and conscientious follow-through.
2016 - 2021: Drutopia
Beginning in 2016, I co-led Drutopia, a collaborative initiative that produced a Drupal distribution for use by diverse communities.
As well as a dedicated project website where I and others blogged about our work, we maintained a project documentation site, writing in Markdown format using the Read the Docs documentation platform. As a co-maintainer of the documentation site, I both wrote documentation myself and reviewed and merged documentation contributions from others through over 50 commits.
Tech journalism and blogging
For several years, Drupal had a print publication: Drupal Watchdog. As seen on my profile page for the journal, I was a frequent contributor. Being a paid writer gave me welcome scope to delve more deeply into intriguing questions. One of the articles I learned the most from writing was Drupal in the Age of Surveillance, for which I interviewed several experts in the field.
In the same period, I wrote a comprehensive and accessible technical article for Linux Journal, “Tips for Writing Interoperable Drupal Distributions”.
On the website of Chocolate Lily, the web agency I co-ran from 2010-2023, I used my blog to explore technical themes and queries. A sample post: Multiple version compatibility in Drupal–managing the tradeoffs.
Occasionally, a technical challenge is complex enough that it calls for detailed explication. This was true of a solution for updating Drupal configuration centring on the Configuration Synchronizer module. I’d done the development myself, but to make it easier for others to understand and contribute I wrote what grew into an eight-part series, starting with Managing Shared Configuration Part 1: Configuration Providers. Along the way, when using specialized terminology, I took time to explain terms like visibility and software classes, methods, and interfaces.
To my gratified surprise, more than one Drupal community member who reached out to thank me for the series explained they were eagerly following it despite no particular interest in the problems of configuration management. The fact I’d taken the time to introduce topics and provide grounding meant these readers could use the series as a primer on general topics like object oriented development and software design patterns. Who knew?
Years later, when I was moving on from Drupal development and successfully recruited qualified developers from the University of Arizona to take over as maintainers of the module set, I didn’t need to give them extensive orientation to the code base—the blog series pretty much covered the case.
Code poetry
Perhaps it was inevitable that, as both an IT worker and a poet, I’d eventually be drawn to mix the two—advisedly or otherwise ;) Selected results:
Closing thoughts
Particularly in open source, effective documentation in all its forms is key to socializing the code.