How it works¶
Astro 7 in SSR mode (@astrojs/node, standalone) with React 19 islands, Tailwind 4, a
node:sqlite cache and a JSON config file. No database server, no auth. Consumers run
landschaft dev straight after installing; production needs landschaft build before
landschaft start.
bin/landschaft.js— the CLI. Points Astro'srootat the installed package, so the bundledastro.config.mjsandsrc/are used while config and cache come from the directory the command runs in.src/lib/schema.ts— zod schemas shared by server and client: config, filters, move and sync requests. The types are inferred from them.src/lib/server/config.ts— load and atomic save oflandschaft.config.json.src/lib/server/db.ts— SQLite schema and queries (issues, blockers, labels, sync state).src/lib/server/github.ts— GraphQL sync queries and REST label writes; token fromGITHUB_TOKENorgh auth token.src/lib/server/sync.ts— theSyncer(sequential, incremental and full passes) and the scheduler that followsrefreshMinutes.src/lib/server/board.ts— the pure board builder andlabelDiffForMove. Everything about placement lives here and is unit-tested against fixtures.src/lib/server/app.ts— one DB handle, GitHub client and scheduler per process, booted bysrc/middleware.tson the first request and surviving Vite HMR.src/pages/api/**— thin JSON endpoints wrapped inroute()fromapi.ts.src/lib/client/— fetch wrappers,useBoard(polling plus optimistic move), URL filters, drag and drop.src/components/board/,src/components/settings/— React islands mounted withclient:only="react"fromsrc/pages/d/[id].astroandsrc/pages/settings.astro.
Why these shapes:
- Labels as the only state on GitHub. No Projects board, no custom fields: a dashboard is a view over labels any repo already has, and works for repositories you do not own.
- Diff, never replace. A move removes and adds specific labels by name, so concurrent edits elsewhere survive.
- Sequential sync. GitHub's GraphQL budget is per token; running repositories one after another keeps the board usable instead of fast-then-throttled.
- Cache in SQLite, truth on GitHub. The database is disposable; deleting it costs one full sync.