Each project is a sequence of short lessons that ends in a working program. Pick one that you've always wanted to understand from the inside.
Build an in-memory search index you add documents to and query, with your own inverted index and ranking.
Take source text all the way to a working interpreter: tokenize, parse into a syntax tree, then evaluate it into real results.
Emulate the CPU, memory map, and pixels of real handheld hardware.
Read a line, run a program, and wire up pipes the way your terminal does.
Speak HTTP over a raw socket: parse requests, serve files, handle many clients.
Grow a regex library from a thirty-line matcher into a Thompson NFA that matches in linear time.
Turn SQL text into answers: tokenize, parse, and execute real queries over tables you build yourself.
Build a crash-safe, ordered key-value store on a log-structured merge tree: a fsync'd write-ahead log, immutable SSTables, merged reads, compaction, and recovery that loses nothing committed.
Build a real spell checker from first principles: a case-insensitive dictionary, a tokenizer, Levenshtein edit distance, Norvig-style candidate generation, frequency ranking, and a BK-tree index that makes lookups fast - ending in a tool that flags misspellings in a document and suggests ranked corrections.
Build an fzf-style fuzzy finder from scratch: subsequence matching, a boundary- and consecutive-aware scoring model, an optimal best-match found with dynamic programming, ranking, highlighting, incremental filtering, and an interactive finder over a real corpus.
Build a real type checker for a small functional language from first principles: a type representation and expression AST, an explicitly-typed checker with environments, let-bindings, functions and conditionals, then the inference core - type variables, unification with the occurs check, substitutions, and Hindley-Milner (Algorithm W) let-polymorphism - finishing with tuples, lists, records, located diagnostics, and a capstone that infers the principal type of a program or reports its type error.
Build a WebAssembly runtime from scratch: decode the binary format (magic, LEB128, sections), build a value stack and a decode-and-execute loop, implement the i32/i64/f32/f64 numeric core, structured control flow with the label and branch-arity model, function calls and call_indirect over a table, linear memory with bounds traps, and globals - then run a real compiled module.
Build a real HTTP/1.1 client from the bytes up: parse a URL into its parts, serialize a request to exact raw bytes ending in a blank line, parse a status line and headers back, decode chunked and Content-Length bodies, read multiple responses off one keep-alive stream, follow redirects, carry cookies, and send Basic auth and form-encoded posts - ending in a runnable client that performs a live GET over TCP and prints the response.
Build a 2D rigid-body physics engine from first principles: a Vec2 math kit, semi-implicit Euler integration under gravity and forces, rigid bodies with mass and inverse mass, circle/AABB/convex-polygon shapes, collision detection that returns an exact contact normal and penetration depth (including SAT), impulse-based resolution with restitution and Coulomb friction, rotation with moment of inertia and contact-point impulses, and a world step that ends in a stable settling simulation.
Build a real terminal text editor from first principles: a piece-table buffer with exact inserts and deletes, a cursor model with clamped movement and word motions, editing operations that split and join lines, a scrolling viewport that renders a frame with tab expansion, file load and save with a dirty flag, incremental search and replace, and piece-table undo/redo with coalesced typing - ending in an editor driven by a scripted keystroke session.
Build a real JSON library from first principles: a scanner that turns text into tokens, string and number scanning with every escape and grammar edge, a recursive-descent parser that builds a value tree with arbitrary nesting, positioned error reporting, a compact serializer plus a pretty-printer proven by round-trip, and a JSON Pointer query layer - ending in a jq-lite tool that validates and pretty-prints any document.
Build a real CSV library from first principles: a finite-state machine that splits a plain comma-and-newline table into records and fields, a quoting state machine that handles embedded delimiters, newlines, and doubled-quote escapes with positioned errors, line-ending and BOM handling, a configurable dialect, a streaming reader that yields one record at a time, a header mode, and a writer that quotes exactly what needs it, proven by round-trip and ending in a normalizer for messy real-world CSV.
Build a real PNG codec from the bytes up: parse the signature and chunk stream, validate every chunk with a table-driven CRC32, inflate the zlib/DEFLATE stream by hand (stored, fixed-Huffman, and dynamic-Huffman blocks with canonical Huffman decoding and LZ77 back-references), reverse the five scanline filters, assemble pixels across every color type and bit depth, and then run the pipeline backward to write valid PNG files other decoders can read.
Build a real baseline JPEG codec from the bytes up: walk the marker and segment container, parse the quantization and Huffman tables and the SOF0 frame, read the entropy-coded scan by hand (an MSB-first bit reader with byte-stuffing, the receive-and-extend magnitude decode, DC differentials, run-length AC with EOB and ZRL, and restart markers), dequantize and run an inverse DCT, upsample chroma and convert YCbCr to RGB, then reverse the whole pipeline to write valid baseline JPEG files other decoders can read.
Build a real memory allocator from first principles over a simulated arena - a single backing byte buffer where every allocation returns a deterministic offset. Start with a bump allocator, add block headers and boundary tags, an explicit free list with splitting and coalescing, first-fit and best-fit policies, realloc and calloc, segregated size-class bins, and a heap-integrity checker - ending in an allocator that runs a scripted workload and reports the exact final heap layout with no corruption, leaks, or overlap.
Build a real general-purpose compressor from first principles, organised around one invariant: decompress(compress(x)) must equal x, byte for byte. Start with an MSB-first bit writer and reader that pack codes across byte boundaries, add run-length encoding, canonical Huffman coding, and an LZ77/LZSS sliding-window matcher, then combine the last two into a DEFLATE-lite pipeline with a self-describing container. End with a Compress and Decompress library that round-trips real multi-line text byte-identically, falls back to storing incompressible input without expanding it, and reports the compression ratio.
Build a real audio toolkit from first principles - a library that reads and writes WAV files and transforms raw PCM samples, plus a CLI on top. Start by walking the RIFF/WAVE container chunk by chunk and parsing the fmt fields, decode 8/16/24-bit and 32-bit-float samples into exact integers, de-interleave channels, then write valid files proven by round-trip equality. Add the sample math - gain with clipping, mixing with clamping, normalization, fades, reversing, and channel ops - then synthesize sine, square, and sawtooth tones, an ADSR-lite envelope, and a delay effect, ending with a capstone that synthesizes a stereo signal, shapes it, writes a 16-bit WAV, and reads back the exact samples.
Build a real DNS resolver from first principles, one exact byte at a time. Start with the 12-byte header and its packed flag bits, encode and decode domain names as length-prefixed labels, handle the classic 0xC0 compression pointers with a loop guard, parse every common record type (A, AAAA, NS, CNAME, MX, TXT, SOA), then drive the resolution algorithm through an injectable transport - build a query, parse a response, follow a CNAME chain, and walk root to TLD to authoritative using referrals and glue - ending in a resolver that resolves www.example.com end to end against scripted nameserver responses with no network at all.
Build a real MP4 / ISO Base Media File Format parser from first principles by walking exact bytes. Every box is a 4-byte big-endian size plus a 4-byte type, so the whole file is a tree you can parse to exact values with no guesswork. Start with a box header, add the 64-bit largesize and size-to-end-of-file cases, build the recursive box tree with FullBox and unknown-box handling, decode the movie and track headers, parse every sample table, and end with a library that turns an MP4 into a box tree and a per-track media summary - the honest core of a tiny mp4box or ffprobe.
Build a real autocomplete engine from first principles as an importable library: a trie of terms with shared-prefix branching, prefix traversal that collects every completion in a subtree, weighted top-K ranking with a deterministic lexicographic tie-break, a per-node cached top list that turns a query into O(prefix length + K), learning from selections that re-ranks terms as they are chosen, case-insensitive folding that preserves display form, phrase terms, and an optional single-typo prefix fallback - ending in an engine that loads a weighted term list and serves exact ranked completions as you type.
Build a real load balancer from first principles over an injectable transport - a function that maps a chosen backend to a response - so the whole thing is deterministic and testable offline with no real network. Start with a backend pool you add to and remove from, then build every selection algorithm one at a time (round-robin, weighted round-robin, seeded random, least-connections, power-of-two-choices, and sticky sessions), track active connections through dispatch, and drive a passive-and-active health-check state machine with rise and fall thresholds - ending in a balancer that routes a scripted request stream across flapping and draining backends and reports the exact backend chosen for every request.
Build a real process supervisor from first principles - the service-management core inside runit, supervisord, and systemd. Model each managed service as a state machine over a fake, injectable process runtime and a virtual clock so every transition, restart decision, and backoff interval is exact and offline-testable. Start with the six-state lifecycle, add start, readiness, stop, and reap over the fake runtime, then restart policies, exponential backoff, crash-loop protection, a dependency graph with topological start order and reverse-order shutdown, and a reconcile loop with graceful shutdown - ending in a supervisor that runs a scripted set of services and asserts the exact state timeline and final states.
Build a real Standard MIDI File parser from first principles: read the MThd header and MTrk track chunks, decode variable-length delta-times, parse every channel voice message with running status, handle meta events and system-exclusive data, then assemble tracks of timed events into a song model - absolute ticks, a tempo map, note-on paired with note-off into notes, and ticks converted to seconds. It ends in a library that turns raw SMF bytes into a song of tracks, tempo, time signature, and notes, plus a midinfo-style inspector. This is a parser, not a player: there is no audio synthesis or real-time playback.
Build a working CHIP-8 interpreter from first principles - the classic 1970s virtual machine that runs games like Pong and Space Invaders as tiny two-byte opcodes. Start with the machine itself (4KB memory, sixteen registers, the index register, program counter, call stack, timers, a 64x32 monochrome framebuffer, and the built-in hex font), build a fetch-decode-execute cycle, then implement the full opcode set one instruction at a time with every carry, borrow, and shift quirk pinned to an exact value, ending in an emulator that loads a real ROM and runs it to completion.
Build a real tracing garbage collector from first principles over a simulated heap - a table of objects addressed by an integer object id (a Ref), each holding a small set of reference fields, with an explicit root set. Start with the object model and reachability by tracing, build a full tri-color mark-sweep collector with a free list and allocation that triggers collection, then a copying semispace collector using Cheney's algorithm with forwarding pointers and compaction, and finish with write barriers and a capstone that collects a graph with a shared node, a reachable cycle, and an unreachable cycle - asserting the exact set of surviving and reclaimed ids.
Build an on-disk, crash-safe B+Tree index from first principles: fixed-size pages, a pager, serialized leaf and internal nodes, search, splits, deletes with rebalancing, ordered range scans, a file-backed pager, and copy-on-write commits with a double meta page that survive a crash mid-write.
Build a cooperative green-thread scheduler from first principles - a single-threaded, deterministic user-space runtime over a virtual clock. Model a green thread as a resumable task that steps and returns a status (Ready, Blocked, or Done), then build a FIFO run queue, yielding and round-robin interleaving, wait queues for blocking and waking, a virtual-clock timer heap, and synchronization primitives (a semaphore, a mutex, buffered and unbuffered channels, a wait group) all built on block and wake - ending in a runtime that runs a set of cooperating green threads and reports their exact interleaved step order and virtual timeline.
Build a real line-based diff library from first principles - the same engine that powers git diff and patch. Start with the edit model (diffing two sequences as a shortest edit script, equivalently a longest common subsequence) and a correct dynamic-programming baseline, then implement Eugene Myers' greedy O(ND) algorithm over the edit graph - diagonals, snakes, and the furthest-reaching V array - and backtrack its trace into a concrete edit script. Turn that script into real unified-diff output with hunks, context lines, and @@ headers, then close the loop with a patch applier that reconstructs the target and proves apply(a, diff(a, b)) == b.
Build a real big-integer library from first principles, storing every number as a little-endian array of base-1000000000 limbs plus a sign - never leaning on a language built-in like Go math/big. Start with the limb array, normalization, and exact decimal parse and render, then magnitude comparison, schoolbook addition and subtraction with carry and borrow, signed dispatch, schoolbook and Karatsuba multiplication, single-limb and full long division producing quotient and remainder, and finish with bit shifts, fast exponentiation, modular exponentiation, GCD, and hexadecimal - ending in a library that computes 100 factorial and 2 to the 1000th power to the exact decimal digit.
Build the SHA-256 hash function from first principles on fixed-width 32-bit words - no crypto library, every intermediate a fixed number you check against the standard. Start with the word primitives (modular addition, ROTR, SHR, Ch, Maj, and the four sigma functions), pin the eight initial hash values and 64 round constants, pad and block a message, expand the 64-word message schedule, run the 64-round compression function, and drive multiple blocks to a 32-byte digest - ending in a library that reproduces the official FIPS 180-4 and RFC 6234 test vectors exactly, plus an HMAC-SHA256 bonus.
Build a real Sudoku solver from first principles, following Peter Norvig's approach of constraint propagation plus backtracking search, as an importable library. Start with the board - an 81-cell grid, an 81-character puzzle string, the 27 units and each cell's 20 peers, and a validity check - then compute per-cell candidate sets, write a correct backtracking solver, speed it up with the most-constrained-cell heuristic, add naked-single and hidden-single propagation to a fixpoint with contradiction detection, and finish with solution counting for uniqueness, a seeded puzzle generator, and a difficulty rating. Every step is one concrete spec with exact grids, candidate sets, and counts, and the whole thing is deterministic so every value reproduces in any language.
Build a real QR code encoder from first principles, anchored to a fully worked example (the string HELLO WORLD as a Version 1, error-correction level Q symbol) so every value is checkable. Start with arithmetic in the finite field GF(256), build Reed-Solomon error correction as polynomial division over that field, encode text into a bitstream with modes and padding, split it into codewords with error correction, lay out the 21x21 module grid with its finder, timing, and format patterns, then mask and score the result - ending in a library that turns a string into a boolean module grid a real scanner reads.
Build a pathfinding and maze library from first principles over a deterministic grid, where every path, cost, node count, and generated maze is exactly reproducible. Start with a grid of walkable and wall cells and a fixed neighbor order, add breadth-first search with path reconstruction, a hand-built binary min-heap and Dijkstra over weighted terrain, then A* with admissible heuristics that finds the same optimal path while expanding fewer nodes. Finish by generating perfect mazes from a seeded random number generator with two classic algorithms and solving one with A*, overlaying the exact optimal path on the maze.
Build an ordered map backed by a skip list from first principles - a tower of forward pointers per node, express lanes that give expected O(log n) search, and a seeded level generator that makes every tower height reproducible. Start with a sorted level-0 skeleton, add the drop-down search, a self-seeded coin-flip level generator, insert with the classic update array, delete that lowers the list level, in-order iteration and range queries, and spans for O(log n) rank and select - ending in a deterministic ordered set you can search, mutate, iterate, and index by position.
Build a library of probabilistic data structures from first principles - the sketches that answer "have I seen this?", "how often?", and "how many distinct?" in a fraction of the memory an exact answer would need. Start with a deterministic hash pair and a bit array, build a Bloom filter with tunable false positives and no false negatives, add a counting Bloom filter with delete, a Count-Min sketch for frequency estimation, and a HyperLogLog for distinct counting - ending in one library that runs a real stream through all three with exact, reproducible bit, counter, and register states.
Build two fixed-capacity caches from first principles - an LRU cache and an LFU cache - each with O(1) Get and Put. Start with the cache contract on a plain map, add a doubly-linked list with sentinel head and tail so recency moves are O(1), make a hit promote its entry to the front and eviction remove the tail, then build an LFU cache with a per-frequency list and a minFreq pointer. Add per-entry TTL, runtime resize, and hit/miss stats, and finish by running one scripted workload through both caches to show exactly where least-recently-used and least-frequently-used diverge.
Build a rate-limiting library from first principles, driven by an injected virtual clock so every allow and deny decision is exact and reproducible. Start with the Allow contract and a fixed quota, then implement the classic algorithms in turn: a fixed-window counter and its boundary-burst flaw, a precise sliding-window log, the sliding-window-counter approximation, and a token bucket with fractional refill and a leaky-bucket variant. Add per-key isolation and a retry-after hint, and finish by running one scripted request stream through three limiters at once to see exactly where they agree and where they diverge at a window boundary.
Build a Merkle tree library from first principles - a tamper-evident data structure where one small root hash fingerprints a whole dataset. Start with a simple deterministic hash and leaf-versus-internal domain separation, build a tree by pairing and hashing hashes up to a single root, detect tampering by comparing roots, generate and verify inclusion (audit) proofs that prove one item belongs without revealing the rest, and finish with append-only consistency proofs and a subtree-walking diff that reports exactly which leaves changed.
Build a consistent hash ring from first principles - a library that maps keys to nodes so that adding or removing a node reshuffles only a small fraction of keys instead of almost all of them. Start by showing why naive modulo hashing remaps nearly every key when the node count changes, then place both nodes and keys on a circular hash space, find each key's owner as the first node clockwise, make lookups fast with a sorted array and binary search, prove that adding or removing a node moves only about 1/N of the keys, spread load with virtual nodes, weight nodes by giving them more virtual positions, and compute a replica set of R distinct nodes for each key - ending in a ring that survives node churn with minimal, exactly-predictable remapping.
Build a real Protocol Buffers codec from the wire format up, decoding raw protobuf bytes into structured fields and encoding them back, with no generated code and no .proto compiler. Start with base-128 varints, then tags and the four wire types, the scalar family (varint ints, zigzag sints, little-endian fixed32 and fixed64, length-delimited strings and bytes), nested messages, repeated and packed fields, and finally a schema-aware decode into named fields with proto3 defaults and preserved unknown fields, ending in a library that round-trips a real message byte for byte.
Build a real TOML library from first principles: a line reader that turns key = value lines and # comments into a flat table, every string flavor (basic, literal, and both multiline forms with their trim rules), the full number and date grammar (underscores, hex and octal and binary, inf and nan, and RFC 3339 datetimes), table headers and dotted keys that build a nested document, inline arrays and inline tables and arrays of tables, and positioned errors - ending in a parser that turns a realistic config into an exact nested value tree.
Build a real URL/URI parser from first principles, straight out of RFC 3986: split any URI into its five components (scheme, authority, path, query, fragment) with the generic-syntax algorithm, break the authority into userinfo, host - reg-name, IPv4, or bracketed IPv6 - and port, percent-decode and percent-encode components against the unreserved and reserved sets, run the remove_dot_segments algorithm and syntax-based normalization, parse a query string into key/value pairs, and implement the Section 5 reference-resolution algorithm that turns a relative reference against a base into an absolute URI - ending in a library that reproduces the exact RFC 3986 Appendix C examples.
Build a real glob and gitignore matcher from first principles as an importable library. Start with a literal name match, add the single-char and star wildcards (first a correct backtracking matcher, then the classic two-pointer linear scan that will not blow up on adversarial input), character classes with ranges and negation, backslash escaping, path-aware matching where the star stops at a slash and the double-star spans directories, then the full gitignore rule engine - anchored and floating patterns, directory-only rules, negation that re-includes, and last-match-wins precedence - ending in a matcher that decides the exact ignore-or-keep verdict for every path against a realistic .gitignore.
Build a real cron expression parser and scheduler from first principles as an importable library. Split a cron line into its five fields, compile each field to the exact set of values it allows (wildcards, single numbers, lists, ranges, and steps), decode three-letter month and day names, and handle the quirk that both 0 and 7 mean Sunday. Then test whether an explicit timestamp matches an expression - including the classic day-of-month / day-of-week OR rule - and compute the next fire time from a given instant, handling hour and day rollover, end-of-month skipping, and a leap-day February. Every value is deterministic: time is driven by fixed timestamps you pass in, never the wall clock.
Build the library behind every package manager: a parser and range matcher for Semantic Versioning 2.0.0. Parse a version string into its major, minor, patch, prerelease, and build parts and reject malformed ones; order any two versions by the exact SemVer precedence rules, including the tricky prerelease chain; parse npm-style ranges (comparators, hyphen, tilde, caret, and x-ranges combined with AND and OR); and answer the two questions a resolver actually asks - does this version satisfy this range, and which installed version is the best match.
Build an arithmetic expression evaluator from first principles, centered on Pratt parsing (top-down operator precedence). Start with a tokenizer that scans numbers, operators, and parentheses; write a Pratt parser whose prefix handlers cover numbers, grouping, and unary minus and whose infix handlers give left-associative plus, minus, times, divide, and modulo and a right-associative power; walk the resulting tree to an exact float64 result; add an environment for variables and built-in functions like sqrt, abs, and max with comma-separated arguments; finish with clear, positioned error messages and a capstone that evaluates a batch of real expressions to their exact results.
Build the calculation engine behind a spreadsheet from first principles - a library where you set cells and formulas, recalculate, and read the computed values. Start with A1-style addressing and a grid of cells, add a formula tokenizer and a precedence-aware parser that turns "=A1+B1*2" into an AST with cell references and ranges, evaluate arithmetic and a starter function set (SUM, AVERAGE, MIN, MAX, COUNT, IF), then build the real core: a dependency graph, a topological recalculation order via Kahn's algorithm, incremental recalculation of only a changed cell's dependents, circular-reference detection, and error values that propagate downstream - ending in an engine that recalculates a real sheet, updates exactly the right cells on an edit, and flags a cycle instead of looping forever.
Build the core of Git from first principles as a content-addressable object database. Start with the loose object format and blobs whose SHA-1 ids match real Git exactly, then build tree objects for directories, a staging index with write-tree, commit objects with parents and a fixed identity, refs and a symbolic HEAD with log, and a simplified status - ending in a working mini-git library whose objects real git cat-file can read.