Code

Build the project — four files

Your app has finally outgrown one file. The capstone splits it into four — use the tabs above the code to move between them. Build them top to bottom; each depends on the one before.

item.go — the record type. A struct bundles the fields your list needs (here a title, a priority, a status). The json:"..." tags name the fields on disk, so saving works.

storage.go — save and load. Data must survive a restart, so it lives in a file. saveItems turns the whole []Item into readable JSON and writes items.json; loadItems reads it back at startup — and treats a missing file as a normal first run, not an error, via errors.Is(err, fs.ErrNotExist).

actions.go — the operations. All the logic lives in small functions with clear jobs (the checklist wants at least four; here there are six): addItem (append), listItems, markDone (takes a pointer *Item — the only way to change the original, not a copy), searchItems (case-insensitive filter), indexByTitle (the map from lesson 9, for exact lookup), and summary (the "X of Y done" stat).

main.go — the menu loop. It loads the data, then spins in for + switch until q. Every branch checks the Atoi error and the bounds, prints a message and continues — the program never crashes. On quit, the list is saved.

Verifygo run ., add items, quit, run again: your data comes back. Before submitting, gofmt -l . must print nothing and go vet ./... must be silent.

Tip. Your project has different fields (a movie's Year int, Rating float64…) — what matters is the shape: a record type, storage, actions, and a menu, split into four files that each do one job. This is the one place a multi-file split is earned — the program is genuinely too big for a single file now.