One process, one file. Express serves the API under /api, protected uploads under /uploads, and the built SPA for everything else. SQLite runs in WAL mode with foreign keys on.
Access control in one place. Every route loads its record through access.js, which resolves the pet and the user’s role. Records you can’t see answer 404, so their existence isn’t leaked.
Migrations are an ordered list in db.js. Each one runs once inside a transaction, and PRAGMA user_version records the current version.
Reminders have a single source (reminders.js) used by the dashboard API, the email digest and the calendar feed.
i18n: all UI text lives in translations.js (es and en objects with the same keys). Server log messages are in Spanish.