The constraint is the teacher

A project teaches when it forces a decision you have not made before. Building another to-do app in a familiar stack teaches nothing; building a small tool with one hard constraint — no framework, offline-first, must run in CI — forces you to understand a layer you previously delegated.

One new thing per project is enough. Two new things means debugging two unknowns at once, which teaches frustration more than skill.

Example scenario: a documentation linter

Example scenario: you want to learn how static analysis works. Instead of reading about it, you build a small tool that checks Markdown files for broken relative links. The constraint — parse the files yourself, no heavyweight dependencies — forces you to understand file graphs, edge cases in path resolution and exit-code design. The tool is small; the learning is not.

This mirrors the motivation behind real projects like DeadLinkFinder, described here as an illustrative example.

Finished small beats abandoned big

An abandoned ambitious project teaches mostly scoping failure — a real lesson, but an expensive one to repeat. A small project that ships, with a README and a defined finish line, teaches the full cycle including the unglamorous last ten percent where most of the craft lives.

A short project checklist

Pick exactly one new thing to learn; define the finish line before starting; keep the first version embarrassingly small; write the README as if someone else will use it; and publish even if the audience is just your future self.

Source: DeadLinkFinder case study

Source: Related guide: a real CLI example, EnvDoctor