-
Notifications
You must be signed in to change notification settings - Fork 68
Technical Writing Guidelines
Our goal for these Technical Writing Guideliens is that they will assist Chainguard's employees, customers, and users with with producing and maintain technical educational content that shares a consistent voice and meets the level of detail and technical accuracy expected of our documentation and educational resources.
Our goal for these writing guidelines is that they provide a single source of truth for the most common questions that come up when drafting and revising technical educational resources. There is no singular “correct” approach to writing; our hope is that these practices and techniques will help you achieve a high level of clarity and teaching effectiveness.
We expect these guidelines to evolve over time, so feedback is welcome!
All of Chainguard’s documentation, tutorials, and other educational resources should have the following characteristics:
- Explains why someone would find value in reading the given content
- Communicates technical knowledge that is useful and relevant to users
- Any assumptions regarding the reader’s technical level are communicated at the top to set expectations
- Ideally, we want to educate the broadest audience possible, but this is not always possible in practice
- Well-scoped
- Provides enough detail of information for a given topic
- Not overwhelming to read
- Complex topics should be broken down into accessible, digestible pieces
- Encourages readers to put knowledge into practice
- Providing concrete examples and opportunities to “play” (through something like the terminal, for instance) helps with getting information to stick
- Provides guidance for further learning
- Community-centric
- Supports open source
- Supports developer collaboration
- Supports growing the technical community
- Should align with Chainguard’s company values
- We are customer obsessed
- We have a bias for intentional action
- We don’t take ourselves too seriously (but we do serious work)
- We trust each other and assume good intentions
- Correct, accurate, and without copy errors or bugs
- Follows software security recommended practices
- Up to date with the latest version, or tied to a specific version
- Explains code thoroughly
- Readers should not be asked to run commands or code that they do not fully understand
- Links to further reading if not everything can be covered in one document
- Compelling, realistic examples
- If possible, use concrete examples from open source projects
- Avoid using placeholder names that are meaningless, like foo and bar
- Code and writing is logically structured and helps the reader follow a procedure or understand a concept from beginning to end
- Original and well researched
- Resources are original and not syndicated from elsewhere
- They can be syndicated elsewhere where Chainguard has the canonical link
- When quoting a source, it is linked to
- Plagiarized text is unacceptable
- All written text is licensed under CC BY-NC-SA 4.0
- Any future syndication must maintain the license
- The license enables language translations
- Others may build off of our resources
- Creative Commons is in the spirit of open source
- Authentic developer voice that is welcoming and inclusive
- Conversational but formal
- Prioritizes objectivity
- Avoids making value judgements (for example, “This tool is great!“)
- Can make substantiated recommendations Language
- Use American English spellings
- Clear language
- No idiomatic expressions
- Avoid jokes or puns that detract from the meaning or educational value of the resource (Note that there is more room for humor in content types like videos or presentations)
- Accessible to many readers
- Aim towards machine translatability
- Grammatically correct
- No errors in copy
- Punctuation that helps with readability
- Be mindful of readers who use accessibility tools
- Avoid terms like “look,” “see,” and “view”. For example, you could use “this command will return output like the following” instead of “you’ll see the following output”
- Avoid directional language. Use terms like “following” and “previous” instead of “below” and “above”
- Ensure that images always include descriptive alt text, and are descriptively named
- Avoid colloquialisms and region-centric analogies
- Use inclusive language
- Google’s developer documentation style guide has in-depth guidelines on using inclusive language in a technical document
These principles guide authors to create conceptual articles, tutorials, and other learning resources that help our readers better understand how Chainguard’s products work.
Chainguard’s written documentation and resources should follow a consistent structure. Generally, procedural tutorials should follow the following format:
- Introductory paragraphs, no heading: Should explain in 1-3 paragraphs why the reader may find this tutorial valuable, and what to expect to have completed by the end of the tutorial
- Prerequisites, H2 heading: This section outlines every step that a reader must take in order to complete the tutorial before they proceed with it. In order to keep this section short and clear, it should include links to other Chainguard Academy resources
- Steps, H2 headings: Often following a Step 1 — Do something format, this is the body of the tutorial and where most of the procedure that the reader is following is documented
- Secondary steps, H3 headings: Nested headings should only be used when needed, and may refer to the same step on a different operating system, or closely related and more granular steps of a procedure
- Concluding section, H2 heading: Can be Next Steps or Further Resources — here is an opportunity to reiterate what the reader has accomplished and provide them with additional links to learn more
How to Use Chainguard Images is a great example of a procedural tutorial that follows this structure.
Our documentation involves many code examples throughout learning resources. While we may need to make some assumptions of readers’ knowledge at times, it is important to explain code relevant to the tasks within a given tutorial as much as possible. We do not want to encourage readers to run code that they do not understand well.
We prefer code that we expect readers to execute to be written in blocks so that it is readable. Code should be introduced before the block, and summarized after. Ideally, executed code will have a corresponding output.
For example, if we were to explain the “Hello, World!” program in Python, we may do so in a way similar to the following:
We will be creating a small “Hello, World!” program in Python. Here, we will be using the `print()` function to output a string that we pass onto our screen. We’ll be passing the string `'Hello, World!'`, which we can tell is a string by the single quotes on either side of it. If you prefer, in Python you can use double quotes (`"`) instead.
Type the following in your Python interpreter:
---sh
print('Hello, World!')
---
Once you press `ENTER` to run the program, you’ll receive the following output:
---
Hello, World!
---
At this point, the program was executed and you received the output expected from the `print()` statement. You can continue to practice by passing other strings to the function.
In this sample, the print()
function is briefly explained as well as the concept of the string data type. It presents the full code snippet that the writer expects the reader to run, and also provides the expected output so that the reader can ensure that they executed the code correctly. Finally, there is a concluding sentence that explains what has happened and what the reader may like to do next given their new knowledge of this command.
We prefer our documentation to be declarative, meaning that readers can follow a given procedure or instruction by copying and pasting the given commands and keeping interaction with the command line to a minimum.
To maintain this declarative approach when a piece of technical content requires readers to create a new file, we default to using the cat command to write text to a file as in this example:
cat > sample-policy.yaml <<EOF
apiVersion: policy.sigstore.dev/v1beta1
kind: ClusterImagePolicy
metadata:
name: sample-policy
spec:
images:
- glob: "ghcr.io/chainguard-dev/*/*"
- glob: "ghcr.io/chainguard-dev/*"
- glob: "index.docker.io/*"
- glob: "index.docker.io/*/*"
- glob: "cgr.dev/chainguard/**"
authorities:
- keyless:
url: https://fulcio.sigstore.dev
identities:
- issuer: "*"
subject: "*"
EOF
In the first line of this example, the cat
command redirects all of the remaining lines into a file named sample-policy.yaml
until the content reaches the string EOF
. Using this approach instead of manually creating a file with a text editor like vim
or nano
can help our readers integrate Chainguard’s products with their existing automation systems.
With that said, if a procedure requires you to use a text editor to change an existing file, we default to using nano
in examples due to its wide install base and beginner-friendly interface.
Edit the `sample-policy.yaml` file with your preferred text editor. This example uses `nano`.
---sh
nano sample-policy.yaml
---
After making your changes, save and close the file. If you used `nano` to edit the file, do so by pressing `CTRL + O` and then `CTRL + X`.
Notice that this example doesn’t tell the reader to use nano
directly. Instead, it presents the text editor as a valid option. It also provides clear instructions for how to save and close a file after editing it with nano
, which is crucial information for readers who aren’t already familiar with the tool.
Videos are one of our official Academy content types and, in order to keep our resources inclusive, we aim to include a transcript with each video we publish.
Our videos are hosted on YouTube which generates video transcripts automatically. However, there isn’t an easy way to copy the transcript of a video while retaining the timestamp URLs.
We were stuck doing this manually until Adrian kindly assembled the following Python script which does this for us.
import sys
import re
def is_time_format(line):
return re.match(r"^\d+:\d{2}$", line.strip())
def time_to_seconds(time_str):
minutes, seconds = time_str.split(":")
return int(minutes) * 60 + int(seconds)
def convert_line(line, code):
if is_time_format(line): # Check if it's a time line
time_str = line.strip()
seconds = time_to_seconds(time_str)
return f'<a href="https://youtu.be/{code}?t={seconds}" target="_blank">{time_str}</a> '
else:
return line
def main():
if len(sys.argv) < 3:
print("Usage: python script_name.py <input_file> <youtube_code>")
sys.exit(1)
input_file = sys.argv[1]
code = sys.argv[2]
output_file = "output.txt"
with open(input_file, 'r') as fin, open(output_file, 'w') as fout:
lines = fin.readlines()
for i, line in enumerate(lines):
fout.write(convert_line(line, code))
if __name__ == "__main__":
main()
Copy this script to a file (in the following example, convert.py
). Then, go to the Youtube video and copy the transcript to an input file (input.txt
). Then, retrieve the video’s code. This is an 11-digit string at the end of a YouTube video URL. For example, the code for a YouTube video with the URL https://www.youtube.com/watch?v=rqIcDrg1XOs
is rqIcDrg1XOs
.
After this, run a command like the following to run the script and add hyperlinks to the plaintext transcript:
python3 convert.py input.txt rqIcDrg1XOs
This will output the updated transcript (including hyperlinks) to an output file named output.txt
.
Be sure to review the final transcript for any errors before publishing. Although YouTube generally does a fair job with generating transcription data, it isn’t always perfect.
H2s should follow the Title case, meaning every word other than minor words (such as articles, short prepositions, or conjunctions in certain cases) should be capitalized.
H3s should follow the Sentence case, meaning that only the first word is capitalized.
Although we do make certain exceptions, please avoid using H4s. We never use H1s or anything smaller than an H4.
Chainguard Academy runs as a static Hugo site. As such, each page of content on the site must begin with what's called Hugo front matter. Front matter allows you to add special metadata about a given page.
A typical front matter section looks like this:
---
title: "How to Use Chainguard Images"
linktitle: "How to Use"
type: "article"
description: "A primer on how to migrate to Chainguard Images"
lead: "A primer on how to migrate to Chainguard Images"
date: 2022-09-01T08:49:31+00:00
lastmod: 2024-03-29T19:42:31+00:00
draft: false
tags: ["Chainguard Images", "Procedural", "Product"]
images: []
menu:
docs:
parent: "chainguard-images"
weight: 020
terminalImage: academy/chainguard-images:latest
toc: true
---
The following should be in every page's front matter:
-
title
: The title of the given doc. The value should be in quotes and written in Title case. -
linktitle
: The "short title" of a given doc that appears in the left-hand navigation menu. If no linktitle is given, Hugo will default to using the full title in places where the linktitle would appear. -
type
: We only have one "content type" defined for Chainguard Academy. This field should always be set toarticle
. -
description
: A brief, one- or two-sentence description of the resource. -
date
: A timestamp showing the date of initial publication. -
lastmod
: A timestamp of the most recent edit to the page.
Note: You should only update the
lastmod
field of a resource's front matter when it has been fully reviewed and tech tested. Otherwise, it can mess with our automated maintenance reporting.
-
draft
: If sent totrue
, the resource will be hidden from view when published to Academy. This should generally be set tofalse
. -
tags
: The tags with which to associate the given resource. In general, there should be at least three tags on each resource. Also, tags should always be written in all caps. -
menu
: If set, Hugo adds the page to the given menu or menus. See the menus page for details. -
weight
: This is the "weight" of content pages in the lefthand nav, higher weights appear lower in lists. -
toc
: This should almost always be set totrue
- this will allow a table of contents to appear at the right side of the resource.
Chainguard Academy resources are organized based on their location within the Hugo filesystem in the content/
directory. Each piece of content should reside in what we refer to as "buckets"
You can organize resources within the same bucket by assigning them a weight
value in the Hugo front matter. Docs with higher weights will appear lower in, say, the left-hand navigation menu.
It often makes sense to organize docs in Alphabetical order (as in the case of our Vulnerability Comparison docs) but other times we may want to sort docs for different purposes. For example, docs in the Working with Images bucket are sorted by what we think readers will want to know first.
When it comes to punctuation, we've elected to strictly enforce use of the Oxford comma in resources on Chainguard Academy. This is a comma placed before the coordinating conjunction ("and" or "or") preceding the final element in a series of three or more terms. For example, between the following two examples, only example A would be allowed on Chainguard Academy:
Example A | Example B |
---|---|
"My heroes are my parents, Superman, and Wonder Woman." | "My heroes are my parents, Superman and Wonder Woman." |
Our Academy resources adhere to a "friendly but formal" tone in our documentation. This means our docs aim to be conversational and informative, but generally lack overly expressive language. Avoid exclamation marks, jokes, puns, or strong opinions (unless those opinions are relevant to the case of the resource, as in security best practices).
Generally, the sentence preceding a code block, command, or command output should end in a colon, rather than a period. We haven't always been consistent about this as a team, so if you are editing an older doc and see a period that could be replaced with a colon, do it!
- One of the most important parts of any written resource is its title. The title (which is housed in the given tutorial’s front matter), should be specific, reasonably succinct, and make it immediately clear to readers what the tutorial is about. Titles often follow the How to … format, but this isn’t always necessary
- Never end a section of a tutorial with a code block. There should be introductory and concluding lines in each section to ensure that the reader knows what to expect and understands whether or not they have achieved relevant goals
- Before publishing or submitting a draft for review, always run through each command within the tutorial in order to ensure that everything works as written
If you have any questions or suggestions regarding our Style Guide, please create an issue and we will follow up accordingly.