Your README is the first opportunity you have to communicate with people when visit your GitHub repo. Lorna Mitchell covers what it takes to create a README that engages and informs developers, in this talk from DevRelCon London 2019.
Lorna: Hello, good morning. Yeah, Owen is right, we’re in the middle of a rebrand, so my badge says Vonage and my slides say Nexmo. My mouth probably says Nexmo, my GitHub orgs are still branded as Nexmo. So, I am, yeah, if you ever need any advice about rebranding, I am all ears. I’m super excited to be here. I think I would describe myself as an engineer with a writing problem, and I think it’s just super important to welcome engineers who want to be part of the things we’ve made on the internet. But it can be hard to keep a handle on what’s important.
So, you know what GitHub is, but let’s talk about landing pages for a moment. Your landing page is the home page. It’s the front door of your documentation. If you are a technical writer by profession then you’ve spent a lot of time perfecting your landing page. You have designed an information architecture. You have worked extremely hard on understanding the user journey and the users needs when they arrive on that page.
However, your users did not get the memo. They use, at best, a search engine. But very often we see people landing on our GitHub projects, they were looking for code, so they went to the place where the code is. with no context of who you are, what you do, or what this repository is about. So it’s all about giving people some context. When you are parachuted in to an unfamiliar landscape with no context, you need to have a little bit of sign posting, a little bit of information of what is around. But it is all about landmarks, context, you are here, and the directions you might need to find the thing you are looking for.
In pursuit of this at Nexmo we have, for a while, been working on repository standards. So in trying to make sure that doing the right thing when you publish a repo, and we have 300 across our various orgs, doing the right thing needs to become doing the easy thing. We need to to follow this process everyday and try and get it right. Our repo standards, if you are interested, are public. And these contain some guidelines but also just some checklists and some templates. We don’t want to think hard about this. We also don’t want to reinvent the wheel every single time we publish a new repository to any of our company orgs. There are templates for what should be in your read-me. There are templates for a basic contributing file, to get you started. You probably need to edit it for specifics for your event, but it’s there, you can use it, it can give you a starting point. Working on a project like this, our intention is to improve our practice.
To look at how we collect those developers that ended up lost on a GitHub project page somewhere and welcome them in a way that we would want to if they had landed, rung the doorbell, and come in the front door, right. I still want to give them the context, their next steps, and try and help them understand where they are, and where they could go from here. On GitHub project, the readme file is a really good place to start. It’s ideal for lots of reasons. It’s very simple, someone pointed out to me recently that, if I have the repository cloned to my laptop, I will typically read the readme off disk in this format. So I will typically read it in whatever format. Typically it’s marked-down. GitHub actually supports a bunch of mark-up formats, marked-down is not my favorite. We can argue about this later in the bar. I know there are some opinions with a capital O in this room.
So we’ve got this readme, why is this mark-down formatted to look like this? I don’t know and I didn’t fix it just so it was safe to put on this line. This is our truth, this is the readme from our PHP SDK. Developers might read it like this, in plain text, but it’s also rendered. So when you come to the GitHub project page, by default, that readme is rendered on the page. It’s typically the first thing the users see once they scroll past your list of files. Then the readme is rendered in place and it is designed for that. It’s also used in a bunch of other contexts. I think this is what makes the readme such a great place to start. If you’re going to change one thing, make it this. Because the readme is rendered. We use it within the code project, that’s what it’s doing there, GitHub renders it by default. It’s also shown on the package manager’s page.
So, this is a PHP library, so this is the Packagist website, which is the hosting for the composer dependency manager. And the same across all the other dependency managers. They will render your readme, or parts of it, as what the information they show to users browsing the web interface.
So users see this readme in a bunch of different contexts. And they might, you might need to cover more than one base when you create this, because people are coming in different ways. I like to start a readme in the same way every time. Giving your project a title and a short explanation of what this is, is surprisingly rare on the internet. It’s like, I understand that you were excited about this project when you wrote this readme, but do I install it? Is it just for me to look at? What is it that you have made me? Did you just write a blog post and throw the code at me? What do I have here? And I think that’s really important. What’s the purpose of the repo? What’s the scope? Is it supported? Is this something we actively want people to work on? Did we make this once just to show how to do a particular thing? What’s it here for? I have repos that match all of those descriptions and more. And it’s really important to try spell things out, especially where you have similar repos. If there is a documentation for this project, link to it. I also like to include a bit about what Nexmo is. We do communications APIs, so if you need to send any sort of message or make any sort of phone call, video call, different sorts of messages, two-factor authentication, that’s what we do. But a user who just searched for 2FA plugin WordPress, probably doesn’t know what Nexmo does. So it’s good to give that context.
If they are arriving with no context, they probably don’t have a Nexmo account either, and you are going to need that to do this. We do include a signup link and I try and have that in my standard readme template, like, “click here to see what we do, click here to signup.” And that’s pretty low friction and I like that. We do include some query parameters with our signup link, which gets blocked by lots of things, it’s not very accurate. But it gives us some idea of the trends. Are people signing up through the GitHub links? Is this even useful include? Did that new library that we launched at PyCon last week, is it bringing loads of sign ups? It gives us a sense of what’s happening where that data is present, so we find that useful. And you may want to do something similar to try and understand the journeys that your users are taking when they’re on a place like GitHub, that you don’t control and maybe can’t get a lot of stats back from. There are different types of repositories and I think the different types really dictate what different things are needed in the readme, for those different types. I am working on the basis of three different types and that’s what we have in our repo standards.
Library code, this is an install-able thing for you to include in your own applications, that will be helpful. It is intended to be stable enough for you to use it in production, so it needs really good documentation, really good test coverage, generally absolutely first class everything you can imagine, that’s what we have.
A tool or demo app, so this is going to be something that’s standalone, you can spin it up, play with it, maybe use it as a basis for something else that you could move on and adapt it to do.
And supporting code. I wrote a blog post and you don’t want to include the whole code, ever. But sometimes it’s really useful, the snippet is in the blog post, showing the real meat of the thing I’m blogging about. But, sometimes, it can be so useful to see that in the context of its application. I may not know that you’ve never configured this template engine before, and so seeing the full, working copy and how that plugs together can be incredibly helpful. So, that’s supporting code, you can use it if you want but we’re not, it’s not a big flagship project for us, it’s just there to support something else that we’ve done. I think doxers code is probably a fourth category. Our whole developer portal is an open source project, it’s on GitHub. It has a readme and we don’t make a lot of these, so I kind of don’t have that on my radar right now. But that’s something, I know we have documentarians in the room, and that’s something that I would think about if you do have that time.
So for library code, we need: Prerequisites, what version do you need? What programming language is this for? What version do you need to be running? Are there any extra complicated installations? Like any system libraries, or anything that you need? Are there any operating systems that are not supported? Spell it out, because I don’t want to go too far down this list, without understanding if I can meet your requirements. Installation instructions. Again, I’m confused about how often this is missing. I think, as developers, we sometimes make assumptions about things. And my advice to you when you write installation instructions; more is more. Really experienced developers don’t need really detailed instructions. But really experienced developers are really experienced skip-readers. So they’re just going to pull out what they need and it’s no problem. Less experienced developers, who I hope we also want to include in the work that we do. Or people like me who, maybe just , I found the thing I needed, it’s not in the text deck I use every day, I don’t care. Because I don’t think we should reinvent the wheel. And I would like to just know, here it is, it exists. I love technology, but I may not be super familiar with how all the dependencies work in – insert name of scripting language here. More is great for me too, I’m not a beginner developer, but I may not be 100% fluent in Erlang, or whatever you made it in. So just write down what I need to type, make it easy. And that includes everybody, it’s appropriate for everybody. And experienced developers you might think, “Oh no, I find it patronizing”, it’s useful for lots of people and they will not even notice that you’re patronizing them. They will just pull the things they need.
Usage instructions. You’ve installed it. You’ve told me how to run the server, now tell me what port it’s on. Tell me what path to append to the URL. Give me a clue. How do I, yes I have installed it, how do I do the thing? I want to do the thing, I’m ready to do thing, now tell me how to do the thing, please, tell me how to do the thing. Anyone who would like to tell you that an API reference is enough by itself, or the code documents itself, or insert reason here, has no clue. Document it, like, I could be more diplomatic about that, but I wasn’t, so there we go. Every project benefits from every example that you write. And that is, yeah I still want your hello world examples, no disrespect to your hello world. But I also need, how do I do it with a proxy server? How do I do it, I need to change this thing, how do I do it with that plugin that you advertised that you support, right? I need an example and then I need some more examples, as well as straight up library documentation, generated code, whatever is working in your local space. So, there’s a bunch of things here and I think all of them are important for libraries. The usage instructions for the libraries. Ours are either generated code, or in the readme, or mostly both. Should they all be in the readme? Well there’s a separate talk. There’s a really good blog post about this that I’ve linked off the resources page from Stoplight, about good ways to document your open source library. So I’m, going to try not to lose all of the minutes in my talk to that, because Taylor’s post is fantastic and I have a link for you later. All right, so, everything in the install-able sample app, demo app category needs everything I just said.
Requirements, installation instructions, usage instructions. I am expecting a user to take the thing and run it themselves. So I’d run a local development machine. Or if they’re going to deploy it somewhere. So we will typically have, this is how you run it if you’re on your bare metal, if you already have the ruby version installed, or whatever. Here it is with a docker setup, so you don’t need dependencies, you can just, you should type the following things and then use this URL. And that is great for allowing users to quickly try stuff. We also have, we use in a few places, click to deploy. And this is also fantastic. So there’s a few things, we’re a communications company, API traffic goes both ways, you need to be able to hit webhook endpoints. So, having: try this thing, click, deploy it to Heroku, now you have a public URL, use it here, has worked really well for us. And allows users to use tools that we’ve made, or try approaches that we’re, that we’ve put together for them really, really easily.
The deployment instruction, more than just running it locally. For something that is supposed to be a standalone project, I think is really important, this is often completely missing as well. For us, this is proven to be the hardest step, because we’re in dev rel, so we don’t have a lot of our Obs engineers hanging around, so this can be a bit of a challenge. And it’s one that we’re just going to keep on working on. It’s not the easy thing, but it’s the right thing. I very diplomatically called this slide the “Supporting Code Slide.” I normally call it “Over The Hedge Code.” You’ve written it once, you’ve thrown I onto GitHub, boom, it’s opensource, hooray! With this, this is a really tricky thing, because what I don’t want to do is create rules about repositories. You must have an excellent readme or you may not publish. I don’t want that We’re in DevRel, we want to include everybody. If you made a thing, let’s share the thing, right? So I don’t have a lot of rules about what must be in the readme for this. In fact I only have one rule. You need to link to the thing it is for.
So you make the sample code, you write the blog post. We do what we do with blog posts, we actually have a great publishing process, but imagine it’s simple. We do what we do with blog posts and one day your blog post is published. The link to the public log post needs to come back and go in the readme and then we are done. If you want to write other things on here and you are happy to be, “Oh, there’s a blog post and here’s the real Dev friendly, fewer words, type this to install it, have fun.” readme, then great, I want that too. But if you don’t, what’s it for? Good enough, but make sure you link. The linking thing, where you make one thing and then you make another thing and you link to it? It’s really hard to link back to the first thing, but there’s lots of places where it’s really important. We discovered, earlier in the year, that we have, so we do all of our API reference documentation with open API specs. I’m wild about this, so if you want to talk about open API, please, find me. We discovered that if you landed on our reference pages, either rendered on our docs portal, or you just grab the spec because that’s what you do with open API specs. There was no link to the actual documentation for this API. If you were in the API documentation we have guides, and tutorials, and examples, and code snippets, and API reference, you link through to the API reference. But if, for any reason, you were on the API reference originally, not all of them had a link back to the actual documentation about this API, fail. So look out for traps like that, it’s super easy to do between artifacts. Between your blog posts and your repo, or whatever. So, look out for it.
Other things I want you to always consider in your readme: How to get help. How would you like people to ask for help? Should they open and issue on GitHub? Would you like a particular tag to have overflow? Does your organization run an online forum? We have a community slack channel. I have a boiler plate piece in my readme template. Different projects prefer it different ways and that is completely fine. In reality users never read this and usually open tickets on GitHub and with support and onstack overflow. Which at least makes it easy to get through all the support tickets, right? The last thing here is something that I don’t think we do enough of in any context. Giving the next steps. I’ve explained to you where you are, optionally you might have cared to read all this stuff about how to deal with it, if this isn’t where you want to be then you need some links, some next steps, and it might just be straight to the documentation landing page for a Nexmo developer, which will hopefully then get you to where you really needed to go. Or further reading, things that are related to this project, I think all of that is really valuable. Right, let’s talk about things that are not the readme file. I think the readme is really important, it’s a great place to start, but there’s other things that we can do to make our repositories both more welcoming but also more discoverable. The first is getting the metadata right on your repository. Please give your project a clear name. Now I am guilty of the developer thing where where I call my project SMSAPIflaskdemo, but if it’s the project where you can text a text message and get a joke back, like, silly joke service would be a much better name for that project. Because everybody will remember which project it was and pick you out of a list of 10 other results. That said, it’s super important to use the tags, GitHub call them topics, to make sure that the python flask SMS Nexmo elements are covered and people can find them in their search terms. Don’t skimp on the description. It’s shown here and it’ll be shown in search results. So people might not be seeing the whole page. It’s not the bit that goes before the files and people are reading it there and then the readme. A lot of the time people will see it out of context, in search results. So use the description to, like, this is a real test as a writer of, kind of, really and descriptive content. You’ve two sentences, get this right and concentrate. It’s not quite micro copy, it nearly is.
If you want people to interact and use your open source stuff, it needs to have a license. There’s no point in creating a thing without documentation and there’s no point in publishing opensource code without a license. A real one, an OSI approved on, not something you made up. They key is, if GitHub doesn’t recognize it here, you’re doing it wrong. Pick a recognized license, this is the only time that I actually add files to GitHub through the web interface. Like, I learned Git before GitHub was as thing. We’re very dependent on a very proprietary tool, that’s again a different talk. I like to review a merge on the command line and I believe I could use other Git platforms, sometimes I even do. The web interface, right, add new file, start typing the word license and it prompts you, right? Click on the prompt, choose the license you need, boom, it’s correct, good. This is the only time I use the web interface for GitHub and it will mean that it’s right every time. By including a license, you give real users permission to take your code and build on it. And if you’re not publishing open source, in order to empower others and let us stand on the shoulders of each other then why are you there? You must have a license. Giving permission and then actually welcoming use are two different things. I think the code of conduct and the contributing file are two things that really enable users to have confidence in being part of your project as users, as contributors. I may check the license before I install the code, but I’m gonna check both of these files before I open even an issue, nevermind a pull request. Because, I mean I’m pretty prolific, I fix mostly typos in documentation, but it happens a bunch. So, these are super important and if you’re not sure where to start, something like the code manifesto, or contributor covenant are really, really good starting points. Please think about what this means to you and your team. If you have a violation, who’s going to deal with that? Who’s going to support that user? And who’s gonna, like, what’s the outcome? Write that down, make sure that exists. With contributing I think it’s important just to spell out how to run the bleeding edge locally, how to contribute things. If you have rules about branch naming, or whatever, then good for you. Make all of that clear here.
Don’t let users engage with your project and then tell them no thanks. We have a couple where our contributing file just says “We don’t accept patches.” So a really good example is our API standards. That’s agreed in committee between developer experience and engineering. You literally can’t patch our API standards, we do that. So, they’re open source, you’re welcome to use them working on a spectral rule set, but we can’t accept patches. So the contributing file just says, “No, go away.” I mean it’s really polite, but, yeah. Your users will find you all kinds of different ways, they have no idea where they’ve landed, right? GitHub is one of the many places they can land. And I think there’s lots of really easy things we can do to help those users find their way. Perhaps push them back to where we hope they would be, but also just help them understand, “You are here.” Where they are on the map and what their next steps could be. I’m gonna wrap up, so I have some resources for you, you can check out what we’re doing at https://github.com/nexmo. I’m a regular blogger, there should be more of this on https://lornajane.net, that is my winter’s resolution. There’s the stoplight post I mentioned about good ways to document opensource projects, it’s too big for a thing this short. And if you’re looking for a license, this is the place that you should go. I will probably have, or will, tweet a photo of a picture of these things. So check my twitter account and if you want to come and chat during the conference, I would be delighted. Thanks for your attention.
When the pandemic tore apart Neo4j’s plans for a community conference, what did they do next?
In this talk from DevRelCon Earth 2020, Sarah Novotny discussed the role of empathy within your community activities.