The case for boring data structures
A small, explicit model is often the most useful abstraction.
Name the thing
Before choosing a database or adding a framework, describe the object your system is responsible for. What does it mean? What makes it valid? What changes over time?
A reading shelf can start with a title, an author, a reading status, and a note. That simple structure carries the intent without asking a future reader to decipher a flexible but ambiguous schema.
Make states explicit
A handful of named states is easier to reason about than several independent flags. Two booleans can accidentally describe a book as both unfinished and completed. A single status avoids that particular ambiguity.
type ReadingStatus = 'to-read' | 'reading' | 'finished';
type Book = {
slug: string;
title: string;
author: string;
status: ReadingStatus;
takeaway: string;
};
Change with evidence
Explicit does not mean permanent. Add fields when a concrete use case needs them, and give a migration the same care you give the new feature.
A good small model leaves a trail of decisions. It should help someone understand what the system cares about, even when that someone is you, six months later.