Aug 26, 2026
How to Be the Best Tutorial Writer in the Room
Ten habits that separate a tutorial that actually works from one that just looks like it does -- from defining the requirement and the audience to rebuilding the app three separate times before you hit publish.

There's a special kind of pain reserved for people who follow a tutorial at 11 PM and hit a wall on step 4 because the author renamed a variable between step 3 and step 5 and never told you. You stare at your terminal. The error makes no sense. You check the code four times. Eventually you realize the tutorial was never run, start to finish, by a human being — it was assembled from memory, vibes, and whatever the author thought they did six months ago.
I don't want to be that person, and after enough tutorials spanning across clients like Docker, Auth0, JetBrains, and others, I've settled on a short list of things that actually separate a tutorial that works from one that just looks like it does. None of this is exotic. It's mostly discipline, applied at the right moments, and a healthy suspicion of your own memory.
I'm not going to talk about the same old boring advices like "Improve your English, use your own language." I myself am not a native English speaker, and I write very simple sentences -- no flowery language, no complicated prose -- and I can tell you that no client has ever questioned me about that. I'm going to give you some real advice, battle tested with real clients.
Disclaimer: All of the points below are my own advice, learned from my experience with Draft.dev. These aren't absolute gospels, and you shouldn't take them as such.
1. Clearly Define the Article Requirement
Before you write a single sentence, know what the article is actually supposed to deliver. Not the topic — the shape. Is this a 500-word "here's a neat trick" post, or a 3,000-word soup-to-nuts build? Does it stand alone, or does it assume the reader already has your last three articles' worth of setup done? Is the deliverable a working demo app, or is the demo just scaffolding to explain one specific concept?
I cannot stress enough the advantages of creating an outline before you start writing. I prefer to collect all the information I can from my clients, including details about their company, their product, and the topic, and create an outline with it. An outline gives you the basic shape of the article and tells you what to do, and what not to do.
You can download a copy of the "content plan" template I use with my clients here.
2. Create a Compelling Scenario
Once you know the requirement and before you touch the audience question, decide what the demo app is actually about. This is where a lot of otherwise-solid tutorials go flat, because the author reaches for the most generic possible container for the feature they're demonstrating.
Say you're writing a tutorial about authentication and authorization. The lazy version of the prompt to yourself is "let's create a basic app and add authn and authz." Technically accurate, and it produces exactly what it promises: a to-do list or a "hello, dashboard" page with a login screen bolted onto it, and a role check somewhere that simply prints your roles on an HTML page. Nobody remembers that tutorial a week later, because there was nothing to remember.
Compare that to: "let's build a CMS where anyone can sign up, write and publish articles, but can't delete someone else's article." Same underlying feature -- authn and authz -- but now it's a scenario, not a checklist item, and the scenario does several things the generic version can't:
- It forces you to define real roles before you write any code, because "someone else's article" only means something once you've decided who owns what. That's authorization design, not authorization theater.
- It gives you a built-in negative test case for free. "User B tries to delete User A's article and gets blocked" is a genuinely satisfying moment to demonstrate -- readers get to see the authorization actually stop something, instead of trusting your word that the middleware is wired up correctly. A generic "protected route" demo never gets to prove a negative like that.
- It reads well in a title and in a search result. "How to Build a CMS with Role-Based Permissions" gets clicked. "How to Add Authn and Authz to a Basic App" reads like a boring text.
- It gives your screenshots something to be of. A login form looks like every other login form ever screenshotted. An article list with a greyed-out delete button next to someone else's post is an image that actually explains the feature at a glance.
A compelling scenario is really the requirement and the audience decisions from the last two points, made concrete enough to build. If your scenario is interesting enough, half of your outline writes itself, because the scenario itself implies the steps: sign-up, write a post, publish it, try to break it as someone else. Boring scenarios don't do that work for you -- you end up having to invent steps to pad the tutorial out, and padding is always the first thing a reader notices.
Note: A compelling scenario doesn't have to be elaborate. It just has to be specific enough that a stranger, reading only the title, already has a rough guess of what the finished thing does. Don't get carried away and try to make it too complex.
3. Clearly Define the Audience
This ties to the previous point as this is part of the outline for me, but it's so important that this requires its own paragraph. This is the single biggest lever on how much detail you show, and it's the one people skip because they think they already know. "Developers" is not an audience. "Someone who's shipped a REST API before but has never touched OAuth" is an audience.
Audience determines everything downstream: whether you explain what a JWT is or just link to a reference, whether you spell out npm install or assume it, whether you show the full error message or just say "if you see an auth error, check your redirect URI." Undershoot the audience and you lose beginners on page one. Overshoot it and your expert reader skims past three paragraphs of npm install ceremony looking for the one paragraph that matters, and maybe doesn't find your article again next time.
I write a one-line audience note to myself before drafting — something like "assumes React familiarity, zero assumption of Next.js server actions" — and I keep it visible while writing. Every time I'm about to explain (or skip explaining) something, I check it against that line instead of against my own head, because my own head thinks everything is obvious by the third read-through.
Here's a concrete example of how audience shapes the article details for me. Imagine I am teaching how to create a Next.js app. If my audience is a beginner who has zero to minimal Next.js experience, I'll start with:
Run the following command to create a Next.js app:
npx create-next-app@latest my-app --yes
Now move into the directory by running "cd my app" and start the dev server by running "npm run dev"But if my audience is an intermediate or expert in Next.js, I'll write:
Create a Next.js app and start it.Note: There is one situation where I'll spell out the details irrespective of the audinece. That is, if I'm doing something that is not the default. For example, I'm using a different version of a tool, or passing a non-default option to the command.
4. Build the App First, to Know It Works
This should not need saying, and yet. Before you write a word of prose, build the actual thing, end to end, on your machine, from a clean slate if you can manage it. Not "I did something like this six months ago and it's basically the same." Build it now, with the versions of the tools that exist now.
The reason this matters isn't pride — it's that software drifts under you while you're not looking. An SDK bumps a major version and renames a constructor argument. A framework moves from pages to app router. A CLI flag gets deprecated with a warning nobody reads. If your mental model of "how this works" is even a few months stale, you will confidently write down something that used to be true.
This happened to me on my own side project, actually — not an article, but close enough to sting the same way. I stubbed an external client in my tests, the tests passed, and I moved on trusting that green checkmark. Then I ran the app for real and discovered the library had changed its constructor from keyword arguments to positional ones between the version I remembered and the version installed. My stub accepted anything, so nothing caught it. The lesson transfers directly to writing: a test (or an article) that was never run against the real thing isn't verification, it's a nice story you're telling yourself.
This is also useful when you're writing about a client's product. Many clients -- typically young startups -- don't pay as much attention to their documentations that they do to their marketing. Often their docs will say "do X to get Y," but when you actually try to do it, you'll discover it doesn't work. Either the feature doesn't exist, but the Sales team got excited and claimed boldly that it's available, or that the docs were hallucinated by an AI, or maybe it worked at some point, but something changed and nobody updated the docs.
That's why build it first. Confirm it works. Then start writing about it. As you are building the app, try to build a mental model of what steps you are going to show in the article in what order. Building the app will tell you what all you need to do in order to get an app working. You can write it down, or memorize. Either way, you now have a solid foundation of what works and what doesn't.
5. Build the App Once More as You Write
Here's the part people skip because they just did step 4, so surely they remember what happened. You don't, not precisely enough. The gap between "I built this and it worked" and "I wrote down, in order, the exact commands and code that make it work" is wider than it feels.
As you write each step, actually perform that step again, right then, and paste in what genuinely happened — not what you remember happening. This catches the stuff that ruins tutorials: the config value you tweaked halfway through and forgot to write down, the folder you created out of order, the environment variable you set in one terminal tab and never mentioned. Writing and rebuilding in lockstep turns your article into a transcript of something real, instead of a summary of something remembered.
Building the app as you're writing the article will also allow you to capture screenshots and outputs immediately, which will make the article feel more alive. More on this later.
6. Build the App One More Time as You Go Through the Final Copy
By the time you're proofreading, you're reading your own writing, and your own writing is exactly the thing you're least equipped to catch errors in — you know what you meant, so your eyes helpfully autocorrect what you wrote. A missing cd into the right directory, a code block that's missing the import you added at the last minute, a step that got reordered when you moved a paragraph for flow and never noticed the code above it now depends on something that hasn't happened yet.
The fix is unglamorous: go through the final copy one more time, but instead of just reading it, execute it, literally, in a fresh terminal, following your own instructions exactly as written rather than as intended. Not "run something like this" — copy the actual commands out of your own article and run those. This is the pass that catches the copy-paste artifact from an earlier draft, the snippet that references a variable you renamed three sections ago, the step you accidentally deleted while editing for length.
Three build passes sounds like a lot until you consider that each one is catching a completely different class of mistake: the first confirms the thing is possible, the second confirms your narration of it is accurate, the third confirms your edited, final narration is still accurate after you've been moving paragraphs around for an hour.
The next few tips are "cosmetic." They don't improve the correctness of your article, but they make it better by a huge margin.
7. Show Full File Paths in Code Snippets
A code block that starts with export default function Page() { and nothing else creates more questions than it answers. Where does this go? Is it a new file? Does it replace something? Which folder, at what level, relative to what?
Show the actual path, every time, even when it feels repetitive: frontend/src/app/api/quote/route.ts, not route.ts. Especially in a monorepo, or anything with more than one plausible src/, guessing the path is exactly the kind of low-value puzzle that makes a reader feel dumb for a reason that has nothing to do with their skill and everything to do with your laziness. Full paths cost you only a few extra words per snippet and save the reader a headache and a moment of quiet resentment toward you specifically.
Here you might argue that if the audience is an expert, surely they can figure out where to put the code if I say "the quote route" insted of frontend/src/app/api/quote/route.ts, and that's a valid argument. I prefer to reduce confusion as much as possible, so I almost always mention the full path, regardless of the audience. Better safe than sorry.
8. Clearly Indicate Where to Put the Code
Adjacent to the path problem, but distinct: a snippet with a correct path can still land in the wrong place inside that file. "Add this" is not an instruction. "Add this snippet at the top of frontend/src/lib/strapi.ts, right after the existing imports" is. "Replace the return statement at the bottom of the handler function with the following" is. Say whether it's a new file, an insertion, or a replacement, and say exactly where the insertion point is relative to something the reader can already see in their own editor.
This matters more, not less, as snippets get shorter. A ten-line code block dropped with no context in the middle of a paragraph is the single most common way I've seen a technically correct tutorial become a frustrating one — not because the code was wrong, but because the reader had to guess what to do with it, and guessed wrong.
Don't refer to code by line number, like "Paste this code after line 15." Even if a reader has been following your article and has been copy pasting the exact codes from your article, they may end up having different line numbers. The most common reason is IDE auto-formatting that automatically formats the code as they paste. The reader themselves may decide to format the code in a different way. Always indicate lines via some sort of marker, like "Paste this after the closing </script> tag."
9. Provide Screenshots, Outputs and a Repo
Three different deliverables, all necessary in my opinion.
The screenshot has two jobs. One, it is proof, aimed at the reader following along: "here's what it should look like when you get this right," so they can check their own result against something concrete instead of just trusting that the code compiled. It's also aimed at people skimming to decide whether the article is worth their time at all — a screenshot of a real, working thing does more convincing in half a second than three paragraphs of description.
It's second purpose is to give the reader a visual cue. A screenshot of the web page with the button circled in red is easier and faster to understand than "Click the small + button in the top right corner of the page."
Note: Two things you must never forget with screenshots: Point out the interesting things (for example, circle the button you want the reader to click, or put an arrow next to it) and include an alt text and caption.
The code outputs have a similar responsibility as the screenshots. They provide a visual indicator. If the user gets the same output as you, they will know they are on the right path. To switch things up a bit (or to save yourself for pasting a huge output), you can also indicate what to look for. For example, "If the status command shows Running, you're good to go.
The repo is the escape hatch, aimed at the reader who's stuck. Tutorials are read out of order, skimmed, half-followed, interrupted by lunch. A linked repo at the final commit state means "I did something slightly wrong three steps back" doesn't have to become "I give up" — it becomes "let me diff my folder against theirs." Also, a repo is a better proof of "It works" than a screenshot. Someone can simply check out the repo and test whether the app works or not before deciding to read your article. I link a repo on effectively everything now, and it's the single piece of feedback I get thanked for most often, more than any clever explanation in the prose itself.
I link the repo twice. The first link is before starting the tutorial section, saying something like "All the code I am using in this article can be found in this repo." This gives the reader the escape hatch mentioned earlier before they actually start investing into the tutorial. The second link is after the tutorial is over, with something like "You can check out the full app in this repo." This works as a "tie everything together" moment. If they didn't check out the repo earlier, they can do so now, and compare their app with mine.
A couple of principles I follow when creating a repo for my tutorials:
- The repo should be the exact same as what my article produces. I basically use the repo I got from following step 6. This makes sure someone who is reading the article gets the exact same app as someone who simply checked out the repo. I don't do any "final touches" or improvements over what the article has. If I must, I make sure it's not an extensive functionality change. For example, I used basic CSS in the article, but that looks ugly, so I added some CSS styles in the final app. This is ok. But using SQLite in the article because it's easy, but changing it to PostGreSQL in the repo is too big of a change. Not cool.
- Sometimes I may provide a starter version of an app. In case the initial setup is too long, I provide a small prebuilt app that I want the reader to use as a starting point for the article. In that case, I provide the starter version and the final version in different branches of the same repo. Starter version in
starterand final version inmain, or starter version inmainand final version infinal-- choose whatever suits you.
10. Provide a List of Prerequisites
How many times have you started reading a tutorial and halfway through you realized, "Looks like I need an AWS account for this. No one made that clear!" You don't want to be the person who leaves their readers in the dark about what they need for the tutorial. That's why I add a prerequisites section before the tutorial actually starts. There, I list:
- The tools that are needed, e. g. Docker, Node.js
- The versions of the tools, where to install them, and which versions I used.
- If any third-party tools or services are needed, and where to sign up for them.
- If the tools behave sufficiently differently based on OS.
Here's one example prerequisite section:
To follow along with this tutorial, you will need:
* An Auth0 account. You can sign up for free [here](link-to-auth0-registration).
* The latest version of Node.js. This article uses version 22.0.1. You can download Node from [here](link-to-node-website).Be the Tutorial Nobody Has to Debug
None of the ten points above are secret techniques picked up from some technical writing seminar. Every one of them is really the same instinct wearing a different hat: don't trust what you think you know, trust what actually happened five minutes ago on your own machine. Every "vibes" tutorial I've ever gotten burned by skipped some of these -- usually not out of laziness, but because it felt done already, and the deadline was in three hours.
That's the trap, and it's the same trap every time. A tutorial reads as finished to its author long before it's finished for the reader, because the author already knows what everything means. The reader doesn't. Every point above is just a way of closing that gap -- one more rebuild, one more real file path, one more screenshot, one more line telling them what account to go create before they get 60% of the way in and hit a wall you knew was coming.
I've written these for clients and the ones that got read, bookmarked, and pasted into someone's internal wiki were never the ones with the cleverest explanation of why something works. They were the ones that just worked, on the first try, for a total stranger, with no help from me sitting next to them. That's the whole job. Everything else is decoration on top of that one requirement.
So if you want to be the best tutorial writer in the room, here's the short version: be the one whose tutorial nobody has to debug.