A mix between a todo and calendar app. Creates tasks from todos by inserting them into the calendar while avoiding conflicts with existing entries. A task is scheduled in a predefined timespan.
- DISCLAIMER this project was fully implemented using Claude Code
specification.md: the source of truth for what is being built.
cp .env.example .env
docker compose up --buildThen open http://localhost:8080
packages/
shared/ Zod schemas + types, imported by both client and server
scheduler/ the scheduling engine (a pure package: no DB, no HTTP, no clock)
server/ Hono API + Drizzle
client/ Vue 3 + Tailwind + Reka UI / shadcn-vue
desktop/ the desktop app: Tauri shell, and the server on PGlite in a worker
docker/
node/ dev and multi-stage prod images
nginx/ reverse-proxy config (dev proxies Vite; prod serves the built bundle)
Everything is served through nginx on one origin: /api/* goes to the server, everything else to
the client. There is no cross-origin configuration in either environment.
| Command | What it does |
|---|---|
pnpm dev |
docker compose up --build |
pnpm build |
Build every package |
pnpm typecheck |
Typecheck every package |
pnpm lint |
ESLint, warnings treated as errors |
pnpm format |
Prettier write |
pnpm test |
Vitest across every package |
pnpm db:generate |
Generate a Drizzle migration from the schema |
pnpm db:migrate |
Apply pending migrations |
pnpm desktop:dev |
Run the desktop app with hot reload |
pnpm desktop:bundle |
Build the desktop app (.app and .dmg on macOS) |
Server tests need a real Postgres (docker compose up -d postgres). Override the
connection with TEST_DATABASE_URL if it is not on localhost:5432.
pnpm --filter @ambitime/server test:pglite runs the same suite on PGlite, the
database the desktop app ships; CI runs both.
A build of the same client and server for one person on their own computer, with
PostgreSQL running inside the app (specification.md §2.3):
no account, no server, and a backup file under Settings → Backup to keep a copy or
move to another machine.
Building it needs Rust (rustup) and, on macOS, the Xcode command line tools; Tauri's
prerequisites list what Linux and Windows need.
pnpm desktop:dev # the app, with the client reloading as you edit
pnpm desktop:bundle # packages/desktop/src-tauri/target/release/bundle/On macOS the disk image step asks Finder to arrange its window, which needs your
terminal to be allowed to control Finder (System Settings → Privacy & Security →
Automation). Without that it times out; CI=true pnpm desktop:bundle skips the
arrangement and builds a plain disk image.
The frontend is the client package built a second time with one module swapped
(@/platform), so there is nothing to keep in step by hand: a feature, fix or
migration made for the web app is in the next desktop build. What the desktop package
adds — the worker, the storage, the backup format, the Tauri shell — is described in
packages/desktop/README.md.
docker compose -f docker-compose.prod.yml up --buildRequires POSTGRES_USER, POSTGRES_PASSWORD and POSTGRES_DB in the environment.
- TypeScript strict mode
- Zod schemas live in
packages/sharedand are the single source of both types and validation - Intervals are half-open
[start, end) - Instants are stored as
timestamptz(UTC) packages/scheduleris pure: no DB or HTTP imports, no wall-clock reads, no randomness. Lint rules andpackages/scheduler/test/purity.test.tsboth enforce this.- All writes go through the command layer, nothing else mutates source state.