ai-assisted-todolist

ai-assisted-todolist

A browser-based todo list: tasks with due dates, importance and workflow state, private to whoever signed in. Quarkus backend, React + TypeScript frontend, PostgreSQL persistence, OpenID Connect sign-in.

DocumentationWhy the project exists, how it fits together, and every decision taken, with the rejected alternatives. Instructions to ClaudeThe working agreement this repository is built under, published because it is the method rather than a description of it. API referenceThe REST contract as OpenAPI 3.1, with one JSON Schema per type beside it. SourceThe repository, the pull requests, and the checks that gate them.

Backend CI Frontend CI CodeQL Quality gate

The todo list is not really the point — this repository exists to build up experience with AI-assisted software development. See doc/purpose.md.

How the application fits together#

The browser talks only to httpd, which serves the app and proxies /api to the Quarkus backend. The backend is the OIDC client: it exchanges the code with the identity provider itself and returns an encrypted session cookie, so the browser never holds a token.

The backend is a backend-for-frontend: it is the OIDC client, it performs the code exchange itself, and what reaches the browser is an encrypted session cookie rather than a token. One origin, so the SPA needs no CORS handling and no API base URL. architecture.md has the deployment shape and authentication.md the sign-in flow in full.

How a change reaches main#

Every change starts from a question rather than a guess, then a failing test, then the change and its documentation in one commit. A pull request must pass Checkstyle, the tests and coverage gate, CodeQL, and the browser end-to-end run before it is squashed onto main. SonarCloud then analyses main, and a failed quality gate becomes a GitHub issue. PIT mutation testing reports but does not block.

Anything that can be checked by a machine is, so that a convention does not depend on somebody remembering it. The one deliberate exception is mutation testing, which reports rather than blocks — testing.md says why, and decisions.md records that and every other choice with its reasoning.

Both diagrams are generated: edit doc/images/generate.py and re-run it rather than touching the SVGs, which exist in a light and a dark variant that must stay in step.

Getting it running#

cd backend && ./mvnw quarkus:dev      # starts PostgreSQL and Keycloak for you
cd frontend && npm install && npm run dev

Open http://localhost:5173 and sign in as gunnar / gunnar. Nothing else to install and no credentials to obtain — doc/local-development.md has the details, the second local account, the container stacks and the troubleshooting.

Documentation#

doc/ is the source of truth; this page is the entry point. Each page answers one question, so start from the question rather than the filename.

Understanding it

purpose.md Why does this repository exist, and why is it built the way it is?
architecture.md What are the pieces, how does a request travel, how is it deployed?
domain-model.md What is a Task, and where is each invariant enforced?
authentication.md How does sign-in work, and why is the backend the OIDC client?

Working on it

local-development.md How do I run it, and what do I do when it misbehaves?
testing.md What is tested where, and which checks can fail my build?
releasing.md How do I cut a release, and what does it publish?
deployment.md Where will this run on AWS, who may change it, and what does it cost?
decisions.md Why is it like this — and what was tried and rejected?

decisions.md is the one worth reading before changing anything structural: several settings in this repository look removable and are not, and it says which and why.

Code-level documentation lives in the code, as Javadoc and TSDoc. The conventions are in backend/CLAUDE.md and frontend/CLAUDE.md, and the backend build enforces them.

Repository layout#

API#

All endpoints require a session except /api/auth/providers.

Method Path
GET /api/tasks the caller's tasks, by due date
POST /api/tasks create
PUT /api/tasks/{id} replace
DELETE /api/tasks/{id} delete
GET /api/auth/providers sign-in options
GET /api/auth/login /logout /me session

A task has a description, a due date, an importance (LOW, MEDIUM, HIGH) and a state (TODO, WORKING, DONE). OpenAPI is at /q/openapi, Swagger UI at /q/swagger-ui, Prometheus metrics at /q/metrics.

CI/CD#

Image publication needs these repository secrets:

Production Google credentials are supplied through environment variables and never checked in; .env.example lists them.

Releases#

git tag v1.0.0 && git push origin v1.0.0

That is the whole procedure. No version is written down anywhere else: the backend's pom.xml carries ${revision}, which the release build overrides from the tag, and the frontend package is private and never published. release.yml then refuses SNAPSHOT and pre-release dependencies, runs both suites, publishes quay.io/ghilling/todo-backend:1.0.0 and todo-frontend:1.0.0, and opens a GitHub Release. Details, including why latest is not moved, are in doc/releasing.md.

Dependencies#

Renovate opens the update pull requests, configured in .github/renovate.json. Patch and minor updates merge themselves once every check on the pull request is green; major updates wait for a human. The dependency dashboard issue lists everything outstanding.

License#

Apache License 2.0 — see LICENSE.

Copyright 2026 Gunnar Hilling.