Agentic AI with Java: Live Cohort
Claude CodeFull-Stack Integration with Claude Code

Integration Requirements and Flow

The plan for building the backend in small feature branches, the target architecture, and how the frontend, FastAPI and SQLite fit together.

We have done the groundwork. The frontend is ready, our CLAUDE.md describes the project and its rules, and the sub-agents produced two specs: api-contract.md and seed-data.json. Now we connect everything.

We could vibe code the backend in one shot. But the whole point is control: building in small, verifiable steps that we understand and can roll back.

The target architecture

Content Tracker architecture: frontend, FastAPI layers, SQLite
LayerResponsibility
Browser + frontendThe Kanban UI. Calls api.getTasks(), api.createTask() and so on
Routes (api/v1/tasks.py)Receive HTTP requests, validate input, call the service, return responses. No database code
Schemas (schemas/task.py)Pydantic v2 models for requests and responses, with camelCase on the wire
Service (services/task_service.py)Business logic. No HTTP code
Models (models/task.py)SQLAlchemy 2.0 table definitions
DatabaseSQLite through the async aiosqlite driver, as decided in the worktree experiment
Alembic + seedCreate tables from models, and load the sample data

The plan: five feature branches

Professional teams never build a whole backend directly on main. main is what gets deployed. Every change happens on a feature branch, is tested, then merged. Once merged, the branch is deleted.

We follow the same discipline with Claude Code:

Five feature branches merged into main
#BranchWhat we build
1feature/backend-setupThe skeleton: folder structure, uv project, dependencies. No business code yet
2feature/task-modelSQLAlchemy Task model, Pydantic schemas, async database engine, first Alembic migration
3feature/crud-endpointsThe four API endpoints and the service layer. Test with Swagger
4feature/seed-dataAn idempotent seed script that loads specs/seed-data.json
5feature/frontend-wiringReplace the failing mockFetch with a real fetch to the backend

For every branch the loop is the same:

  1. Create the branch
  2. Start a fresh session (or /clear)
  3. Give Claude a precise prompt that points at the specs
  4. Review the changes with /diff
  5. Test it
  6. Commit, merge into main, delete the branch

Git commands for every branch

You will repeat this cycle five times, so it is worth knowing by heart:

git checkout -b feature/<name>    # 1. start the feature
# ... work with Claude, review with /diff ...
git add .                         # 2. stage
git commit -m "feat: ..."         # 3. commit (or let Claude write the message)
git checkout main                 # 4. go back to main
git merge feature/<name>          # 5. bring the feature in
git branch -d feature/<name>      # 6. delete the merged branch

Inside Claude Code you can run each line with the ! prefix, for example !git status, so it does not go through the model.

Definition of done for each branch

Before you merge a branch, every box should be ticked:

  • The prompt referenced the spec files instead of describing things from memory
  • You read the full /diff, not just Claude's summary
  • The code follows CLAUDE.md: service layer, schemas and models in their folders, snake_case, type hints
  • You ran it yourself (Swagger, curl or the browser), not only Claude's own checks
  • Nothing outside the feature changed (no surprise edits in frontend/ or specs/)
  • The commit message explains what and why

A note on uv

While planning, we realised something was missing: we want uv as the Python package manager, not plain pip. uv is much faster, manages Python versions, and keeps dependencies locked in pyproject.toml and uv.lock.

This should have been in CLAUDE.md from day one. It is never too late. We add it as the very first step of the backend setup.

Lesson learned

Decide your tooling (package manager, Python version, formatter, test runner) before Claude writes the first file, and put it in CLAUDE.md. Changing tools later is always more work.

The request flow we are aiming for

Browser (http://localhost:8080)
   │
   ▼
frontend/app.js  ── api.getTasks() ──►  fetch("http://localhost:8000/api/tasks")
                                              │
                                              ▼
                                FastAPI route  (api/v1/tasks.py)
                                              │
                                              ▼
                                Service layer  (services/task_service.py)
                                              │
                                              ▼
                                SQLAlchemy  ──►  SQLite (telusko.db)

When this works end to end, clicking Move Forward on a card updates the database, and the board shows the new state after a refresh.

Official references


Written By: Shramik Masti

How is this guide?

Last updated on