Development setup
Node 22+.
Server — needs a token and a writable database path:
cd servernpm installYARUKOTO_TOKEN=devtoken DATABASE_PATH=./data/dev.db MIGRATIONS_DIR=./migrations npm run devClient — in a second terminal:
cd clientnpm installnpm run webnpm run ios and npm run android compile the native app instead, which needs the platform
toolchain installed — see Building the iOS app.
The Expo dev server runs on a different port than the API, so the first-run screen will ask for
both the server URL (http://localhost:8080) and the token. That’s expected — the
URL field is skipped only when the page is served by the API server itself.
Stop the container before running a dev server on the same port. Docker binds
8080on IPv6 and a localnodeprocess binds it on IPv4, so both can hold it at once without either erroring.localhostthen resolves to whichever the client prefers — meaning your browser and yourcurlcan silently talk to different servers. If something on8080looks stale or wrong,lsof -i :8080 -sTCP:LISTENis the first thing to check; a second listener is invisible todocker compose ps.
Type checking (there is no test runner yet):
cd client && npx tsc --noEmitcd server && npx tsc --noEmitInspecting the database
Section titled “Inspecting the database”Don’t point
sqlite3at the database while the server is running. The database lives on a Docker bind mount, and SQLite’s WAL mode coordinates readers through a shared-memory file that bind mounts don’t support. A second process therefore reads only the main file — showing stale results that silently omit recent writes — and a checkpoint from that process can discard committed transactions the server hasn’t merged down yet. This is not theoretical; it cost us two rows while writing this README.
Query the API instead, which always reflects live state:
curl -s localhost:8080/api/v1/sync -H "Authorization: Bearer $YARUKOTO_TOKEN"For real SQL, stop the server first so nothing else holds the file:
docker compose stopsqlite3 data/yarukoto.db 'select id, title, updated_at from tasks;'docker compose start