What you'll learn
- Build a portfolio of three projects that shows production skill, not tutorial completion
- Write a README that a hiring manager or client trusts in sixty seconds
- Ship a first small production project for a real user, paid or unpaid
- Present the course's skills in the language jobs and clients use
Concept
A portfolio is evidence. Nobody hires from a certificate; they hire from proof that you can take a problem to a working, maintained result. Three projects are enough if each is complete: it runs from a clean clone, it has tests and CI, it has a README that explains what and why, and it solves a problem someone actually had. Quality over quantity: three finished projects with green checks beat twelve half-built ones, and the capstone from this course is already one of the three.

The README is the page every reviewer reads and most stop at, so it carries the weight. In order: one sentence saying what the project does and for whom; a screenshot or a short terminal transcript; how to install and run it in three commands; the decisions you made and why, in a short paragraph, because that is what separates a developer from a tutorial follower; the status, what works and what does not; and how to run the tests. Green badges for CI and tests, pinned versions, a changelog, and a license signal that you know how software is maintained.
| README section | Answers the reader's question | Signal it sends |
|---|---|---|
| one-line summary + audience | what is this, is it for me? | you can explain a product |
| screenshot / transcript | what does it look like? | it actually runs |
| install + run (3 commands) | can I try it now? | you care about the user's first minute |
| decisions and trade-offs | why is it built this way? | you think like an engineer |
| status and known gaps | can I trust it? what is missing? | honesty; you know what done means |
| tests, CI badge, changelog | is it maintained? | production habits |
The most convincing project is one built for a real person. Find someone with a small, concrete problem: a friend's spreadsheet ritual, a local organization's manual report, a colleague's weekly export. Scope it to two weekends, agree in writing what done means, build it with the production shell from the capstone, deliver it with a README and a five-minute walkthrough, and fix the first two bugs they find. That is a production project: a real user, a real deployment, real feedback. Do it free the first time if you must; the second one can be paid, and the story of the first is what wins it.

Translate the course into the words job posts and clients use. You did not "learn Python"; you can "build, test, package, and deploy Python services and command-line tools". You know "type-annotated code checked with mypy", "pytest with fixtures and mocking", "async HTTP clients", "SQL with sqlite and parameterized queries", "Docker and GitHub Actions CI", "dependency management with uv and lockfiles", and "secure handling of configuration and secrets". Put those phrases in the profile and the README, and let the repositories back them up. For a first role, a portfolio with green CI and a clear README is rarer than you think.
Code
A README checker: it scores a README against the sections reviewers look for and tells you what is missing. Run it on your own before anyone else does.
# readme_check.py
import re
from pathlib import Path
REQUIRED = {
"one-line summary": lambda t: len(t.splitlines()) > 2 and 20 < len(t.splitlines()[2]) < 200,
"install/run commands": lambda t: t.count(" ") >= 3 or t.count("```") >= 2,
"decisions section": lambda t: re.search(r"^##.*(decision|design|why|trade)", t, re.I | re.M) is not None,
"status or roadmap": lambda t: re.search(r"^##.*(status|roadmap|known|limitations)", t, re.I | re.M) is not None,
"tests mentioned": lambda t: "pytest" in t or "tests" in t.lower(),
"CI badge": lambda t: "
Per-category expense reports from CSV files, for anyone who tracks spending in spreadsheets.
pip install expenses-cli
export EXPENSES_DATA_DIR=./data
expenses report sept.csv --format json
## Decisions
A library core with a thin CLI so the same code can back a web API later; sqlite over JSON once
files passed a few thousand rows; `uv` lockfile so every machine installs the same versions.
## Status
Reports and summaries work; budgets and charts are planned. Run `uv run pytest` for the tests.
MIT license.
''', encoding="utf-8")
text = Path("README.md").read_text(encoding="utf-8")
results = {name: check(text) for name, check in REQUIRED.items()}
for name, ok in results.items():
print(f"{'ok ' if ok else '-- '} {name}")
print(f"score {sum(results.values())}/{len(results)}")
ok one-line summary
ok install/run commands
ok decisions section
ok status or roadmap
ok tests mentioned
ok CI badge
ok license
score 7/7A portfolio index: three projects with the evidence each carries, rendered as the table you would put on a personal site or a CV. Fill in yours; the shape is what matters.
# portfolio.py
from dataclasses import dataclass, field
@dataclass
class Project:
name: str
for_whom: str
skills: list[str]
evidence: list[str] = field(default_factory=list)
def row(self):
return f"| {self.name} | {self.for_whom} | {', '.join(self.skills)} | {', '.join(self.evidence)} |"
projects = [
Project("expenses-cli", "anyone tracking spending",
["typing + mypy", "pytest", "packaging", "Docker", "CI"], ["PyPI", "CI badge", "Dockerfile"]),
Project("link-checker", "site owners", ["asyncio", "httpx", "argparse"], ["tests", "README with transcript"]),
Project("club-reports", "a local sports club (real user)",
["sqlite", "csv", "logging", "scheduling"], ["in use weekly", "testimonial"]),
]
print("| Project | For | Skills shown | Evidence |")
print("|---|---|---|---|")
for p in projects:
print(p.row())
real = [p.name for p in projects if "real user" in p.for_whom]
print()
print("projects for a real user:", real, "| skills covered:", len({s for p in projects for s in p.skills}))
| Project | For | Skills shown | Evidence |
|---|---|---|---|
| expenses-cli | anyone tracking spending | typing + mypy, pytest, packaging, Docker, CI | PyPI, CI badge, Dockerfile |
| link-checker | site owners | asyncio, httpx, argparse | tests, README with transcript |
| club-reports | a local sports club (real user) | sqlite, csv, logging, scheduling | in use weekly, testimonial |
projects for a real user: ['club-reports'] | skills covered: 12The scope agreement for a first real project, generated as a one-page document. Agreeing on this before writing code is what makes a small project finish.
# scope.py
from datetime import date, timedelta
start = date(2026, 9, 13)
scope = {
"client": "Riverside Running Club",
"problem": "monthly membership report is assembled by hand from two spreadsheets (3 hours/month)",
"done_when": "one command produces the report as PDF from the two exported CSVs, matching last month's numbers",
"out_of_scope": ["editing memberships", "emailing the report", "a web interface"],
"deliverables": ["the command with README", "a 5-minute walkthrough", "fixes for the first two bugs within two weeks"],
"sessions": 4,
}
end = start + timedelta(weeks=2)
print(f"SCOPE: {scope['client']}")
print(f"Problem: {scope['problem']}")
print(f"Done when: {scope['done_when']}")
print("Not included:", "; ".join(scope["out_of_scope"]))
print("Deliverables:", "; ".join(scope["deliverables"]))
print(f"Timeline: {scope['sessions']} sessions between {start} and {end}")
SCOPE: Riverside Running Club
Problem: monthly membership report is assembled by hand from two spreadsheets (3 hours/month)
Done when: one command produces the report as PDF from the two exported CSVs, matching last month's numbers
Not included: editing memberships; emailing the report; a web interface
Deliverables: the command with README; a 5-minute walkthrough; fixes for the first two bugs within two weeks
Timeline: 4 sessions between 2026-09-13 and 2026-09-27Try it yourself
Run readme_check.py against the capstone's real README and fix every gap it reports. Fill in portfolio.py with your actual three projects, or the two you have and the one you will build, and put the table on a personal page or your profile. Write a scope document for one real person's problem using scope.py as the template, and send it to them this week.
Common mistakes
- Tutorial projects as a portfolio. A to-do app that follows a video shows you can follow a video; a tool for a real person shows you can solve a problem.
- A README that describes the code. Reviewers want what, for whom, how to run it, and why you built it this way; the code describes itself.
- Waiting until you feel qualified. The capstone is production work; the next real project is the qualification.
What's next
- Three complete projects with tests, CI, and honest READMEs are evidence; the capstone is one of them.
- A README leads with what and for whom, then run commands, decisions, status, and how to test.
- Build one project for a real person with a written scope; describe your skills in the words jobs use, and let the repositories prove them.
You can turn this into work. One lesson remains: a look back at the whole road from print("Hello, world!") to a deployed package, and a thank you.