A README often becomes the first conversation between a project and a person. It cannot anticipate every question. It can tell the right reader, “This project is for you,” lead them to one dependable result, and point them toward the next page for their situation.
By the end of this lesson, you should be able to answer:
What does this reader know before opening the project?
What result are they trying to achieve now?
Does the reader need a tutorial, a how-to guide, explanation, or reference?
Which promises belong in the README, and which should link elsewhere?
What clean evidence makes a quick start trustworthy?
1. Start with a reader and a task
“Developers” is too broad to guide a document. Compare these Midnight Museum visitors:
Reader
Current situation
Immediate question
Useful destination
Curious visitor
Has not installed the package
What does it do, and is it for me?
README opening
New user
Knows basic Python
How do I rank one exhibit successfully?
Tutorial/quick start
Returning user
Already ranked an exhibit
How do I change the ranking inputs?
How-to guide
Maintainer
Understands the API
Why are repeated rankings deterministic?
Explanation
Active caller
Is writing code now
What does rank_exhibit accept, return, and raise?
API reference
A good audience statement includes context and work. “For beginners” only describes presumed experience. “For a learner who has Python 3.10 and wants to rank one exhibit from a local project” gives the author decisions to make: name the required version, identify the project root, show the import, and show the result.
Use a small record before drafting:
reader = {"context": "Python learner at the project root","goal": "rank one exhibit","prerequisites": ["Python 3.10+", "project files downloaded"],"success": "ExhibitScore(name='Moon Dial', score=44)",}for label, value in reader.items():print(f"{label}: {value}")
The dictionary does not become the documentation. It forces an author to name assumptions before they disappear into prose.
NoteName one concrete reader
Write a reader record for someone who already completed the quick start and now needs to rank an exhibit with a different open time. Which fields change? Which page should receive that task?
2. Give each kind of documentation one job
Tutorials, how-to guides, explanation, and reference answer different questions. The distinction is about reader need, not file extensions.
A tutorial creates a successful learning experience. It controls the path, supplies safe choices, and explains only enough to keep the learner oriented.
A how-to guide helps an already-oriented reader achieve a particular result. It begins from stated prerequisites and does not stop to teach the entire system.
Explanation helps a reader understand why the system behaves as it does, which alternatives exist, or which trade-off shaped a decision.
Reference describes the product accurately and consistently: public signatures, parameters, returned values, exceptions, commands, and formats.
The reader’s question selects the document; the framework does not select it for them.
flowchart TD
A[What does the reader need now?] --> B[Learn through a guided path]
A --> C[Complete a known task]
A --> D[Understand a design]
A --> E[Look up exact facts]
B --> F[Tutorial]
C --> G[How-to guide]
D --> H[Explanation]
E --> I[Reference]
Consider this crowded paragraph:
Install the package, then call rank_exhibit(name, votes, minutes_open). The score uses ten points per vote because visitor choices matter most. The function returns ExhibitScore and raises ValueError for negative values. To compare three exhibits, loop over their records and sort the results.
It tries to install, explain policy, state reference facts, and solve a later task at once. Separate the information:
Quick start: install and rank one supplied exhibit.
Explanation: why votes and time contribute different weights.
Reference: signature, result type, and ValueError contract.
How-to: rank and compare several exhibits.
Do not create empty tutorials/, how-to/, explanation/, and reference/ directories merely to appear organized. Create the page that answers an actual reader question, label its purpose, and link it from the places where that question arises.
A useful project README normally answers these questions in a scannable order:
What is this? Name the product and its visible purpose.
Why would I use it? Show the useful result, not internal architecture.
Can I run it? State supported Python and any important platform limit.
How do I install or prepare it? Give one maintained path and its context.
What is the shortest meaningful use? Provide a complete quick start.
What should I see? Show a small expected result.
What should I read next? Link by reader task.
What are the important limits and support path? Do not hide them below a wall of badges or history.
Here is a compact entry point:
# Midnight Museum QuestRank museum exhibits with a small, deterministic Python API.## RequirementsUse Python 3.10 or newer. Run the commands below from the project root.## Quick start```pythonfrom museum_quest import rank_exhibitresult = rank_exhibit("Moon Dial", votes=4, minutes_open=75)print(result)```Expected result:```textExhibitScore(name='Moon Dial', score=44)```Continue with the [guided museum visit](docs/tutorial.qmd "tutorial"), or see the[public API contract](docs/api.qmd "API reference").
The opening tells a visitor what the package does before asking them to install anything. The requirement establishes version and working directory. The code shows every name it needs. The exact result proves more than “it works”: the reader can compare the class name, exhibit name, and score.
Keep installation honest
In a real published package, installation might be:
python-m pip install midnight-museum
In a lesson-sized source checkout that has not been published, claiming that command would be false. Use the path the learner can actually run, such as an editable install from the project root:
python-m pip install -e .
Name the context. A command that succeeds only because the author previously set PYTHONPATH, installed an unpublished wheel, or left a notebook import in memory is not a clean quick start.
When pyproject.toml declares the README, that same entry point can become package metadata:
This connection increases the cost of repository-only relative links or markup that a package index cannot render. Build and inspect the distribution in Unit 10’s workflow when package publication is relevant; Unit 15 concentrates on whether the entry content remains accurate.
4. A quick start needs meaningful evidence
Syntax is only one boundary. This check proves that a text fragment parses:
It does not prove that museum_quest is installed, the exported name still exists, the arguments match the public interface, or the displayed score is current.
A stronger documentation check runs the same public call and compares the promised result:
from museum_quest import ExhibitScore, rank_exhibitresult = rank_exhibit("Moon Dial", votes=4, minutes_open=75)expected = ExhibitScore(name="Moon Dial", score=44)assert result == expectedprint(result)
Expected output:
ExhibitScore(name='Moon Dial', score=44)
The cleanest test executes from the environment and directory the README names. For a full project, record both context and command:
python-m venv .venv# Activate the environment using the command for your shell.python-m pip install -e .python examples/quick_start.py
Avoid shell prompts such as $ inside copyable command blocks. If a placeholder is required, label it:
python -m pip install <path-to-project>
<path-to-project> signals replacement. project without brackets may look like a literal directory name.
A README becomes hard to scan when it contains every advanced task, complete API detail, design discussion, contributor procedure, and release history. Keep the entry path short and use descriptive links:
## Learn more- [Rank your first exhibit](docs/tutorial.qmd "tutorial")- [Change ranking inputs](docs/how-to-rank-exhibits.qmd "ranking how-to")- [Understand deterministic scoring](docs/why-ranking-is-deterministic.qmd "design explanation")- [Look up the public API](docs/api.qmd "API reference")
“Click here” hides the destination when a reader scans links or uses assistive technology to list them. “API” is better, but “Look up the public API” also states why the reader would follow it.
Use paths relative to the file containing the link. From root README.md, docs/api.qmd points into the documentation folder. From docs/tutorial.qmd, api.qmd points to a sibling. A path beginning with a developer’s home directory can never be a portable project link.
This small standard-library check verifies known local targets:
from pathlib import Pathroot = Path(".")targets = [ Path("docs/tutorial.qmd"), Path("docs/how-to-rank-exhibits.qmd"), Path("docs/why-ranking-is-deterministic.qmd"), Path("docs/api.qmd"),]missing = [str(target) for target in targets ifnot (root / target).is_file()]assert missing == [], f"missing README targets: {missing}"
This is stronger than checking hand-written labels in isolation, but it is not a general Markdown link parser. Lesson 5 builds a more honest documentation review: check the source page, target, rendered navigation, and reader meaning.
6. Diagnose a README that works only for its author
Suppose a new learner reports:
ModuleNotFoundError: No module named 'museum_quest'
The README said:
Run `python examples/quick_start.py` to rank an exhibit.
Use the evidence in order:
The failure happens at import, before ranking logic runs.
The README names neither installation nor a project-root requirement.
The author had previously installed the project in an existing environment.
Reproducing in a fresh environment confirms the missing step.
Add the real editable-install command and rerun the whole path.
Do not “repair” this by changing the example to import from src through a machine-specific path. That transfers the hidden assumption into public prose.
WarningThe README must not promise an unpublished command
If the package is not on a package index, do not tell learners to install it by its future package name. Document the source-checkout path that exists now and revise the README when distribution actually changes.
# ToolThis uses our architecture to do rankings. Install it normally. Click[here](file:///home/author/museum/docs/api.html) for more.```pythonprint(rank_exhibit("Moon Dial", 4, 75))```It should work. The implementation has a scorer, validators, dataclasses,private helpers, and other details. Version history follows...
Create a revised README.md that includes:
a specific project name and one-sentence value statement;
Python version and project-root context;
the actual installation path for the project state you have;
a complete import and call;
the exact expected ExhibitScore result;
a limitations statement and support path;
relative, descriptive links to tutorial, how-to, explanation, and API pages;
no private implementation inventory in the entry journey.
Then check it:
Create or reset a clean environment.
Follow only the README.
Record the complete command that produces the first result.
Compare the result with the documented value.
Check that each local target exists.
Ask which reader question each linked page answers.
Introduce one stale expected score, observe the mismatch, and repair the documentation or code according to the actual public contract.
Hint: choose the first visible success
Use one exhibit, one public import, and one returned value. Batch ranking, custom policies, and internal helpers belong after the entry path.
Reveal a representative README after attempting the checks
# Midnight Museum QuestRank museum exhibits with a small, deterministic Python API.## RequirementsUse Python 3.10 or newer. Run commands from the project root.## Installation```textpython -m pip install -e .```## Quick start```pythonfrom museum_quest import rank_exhibitresult = rank_exhibit("Moon Dial", votes=4, minutes_open=75)print(result)```Expected result: `ExhibitScore(name='Moon Dial', score=44)`.## LimitationsThis teaching package stores no rankings between runs.## SupportOpen a project issue with the command, complete error, and Python version.## Learn more- [Follow the guided museum visit](docs/tutorial.qmd "tutorial")- [Change ranking inputs](docs/how-to-rank-exhibits.qmd "ranking how-to")- [Understand deterministic scoring](docs/why-ranking-is-deterministic.qmd "design explanation")- [Look up the public API](docs/api.qmd "API reference")
A different structure is valid if the path remains short, complete, and verified for the named reader.
Key points
Begin with one reader’s context, question, and observable success.
Tutorials, how-to guides, explanation, and reference serve different needs.
A README should establish value and a verified first result, then route readers to deeper pages.
Valid syntax is weaker evidence than a clean installation, public call, exact result, and resolved links.
Document the project state that exists now, not an imagined future release.