Datalumina

The backend

Environment setup

Clone the starter, install the backend with uv, point your editor at the right interpreter, and fill in the environment file.

By the end of this stage the project runs on your machine. The starter repo is cloned, the backend environment is installed with uv, your editor resolves imports from the right virtual environment, and the .env file carries the four Azure values from the setup stages.

daveebbelaar/invoice-review0:10:58

Clone and orient

Start from the main branch. It is deliberately minimal. It holds the brief, the sample corpus, environment templates, and pinned dependencies, and the application code is intentionally absent.

git clone https://github.com/daveebbelaar/e2e-invoice-review.git
cd e2e-invoice-review

The repo is a monorepo, one repository holding both halves of the app plus everything around them:

pyproject.toml
.env.example

backend/app starts almost empty. Building it up, folder by folder, is the rest of this tutorial.

Install the backend

The backend uses uv for dependency management. One command creates the virtual environment and installs everything:

cd backend
uv sync

The dependencies are already declared in backend/pyproject.toml, pinned to exact versions so your install matches the video:

backend/pyproject.toml
[project]
name = "invoice-review-backend"
requires-python = ">=3.12"
dependencies = [
  "azure-ai-documentintelligence==1.0.2",
  "fastapi==0.139.0",
  "openai==2.45.0",
  "pydantic==2.13.4",
  "pydantic-ai-slim[openai]==2.11.0",
  "python-stdnum==2.2",
  "sqlalchemy==2.0.51",
  "uvicorn[standard]==0.51.0",
]

[tool.uv]
add-bounds = "exact"
exclude-newer = "7 days"

add-bounds = "exact" pins every future uv add to an exact version, and exclude-newer = "7 days" ignores packages published in the last week, so a freshly broken release cannot slip into your environment.

The interpreter gotcha

In a monorepo your editor opens at the repo root, but the virtual environment lives one level down at backend/.venv. Cursor and VS Code only auto-detect environments in the project root, so imports show as unresolved even though uv sync just worked.

The fix is manual. Open the interpreter picker (Cmd+Shift+P, then "Python: Select Interpreter"), choose "Enter interpreter path", and point it at backend/.venv/bin/python. Dave hits this exact wall in the video, and it is worth knowing the shape of the problem because every monorepo does this to you.

Prove the imports work

A quick throwaway file confirms the environment and the interpreter agree:

backend/test.py
import pydantic

print(pydantic.VERSION)
# 2.13.4

Run it with uv run python test.py. If the version prints and the editor shows no unresolved import, the environment is wired. The file itself is scaffolding, it does not survive into the finished project. The playground/ folder takes over that experimentation job in the next stage.

Fill in the environment file

Copy the template and fill in the values you collected during the Azure setup stages:

cp .env.example .env
backend/.env.example
AZURE_DOCUMENT_INTELLIGENCE_ENDPOINT=https://your-resource.cognitiveservices.azure.com/
AZURE_DOCUMENT_INTELLIGENCE_KEY=replace-with-your-local-key

AZURE_OPENAI_ENDPOINT=https://your-resource.openai.azure.com/openai/v1/
AZURE_OPENAI_DEPLOYMENT=gpt-5.6-terra
AZURE_OPENAI_API_KEY=replace-with-your-local-key

The Document Intelligence pair comes from the Document Intelligence stage, where the CLI commands to fetch endpoint and key are listed. The Azure OpenAI pair comes from the Foundry stage, and the deployment name must match the model deployment you created there.

The .env file stays local

.env is gitignored and never committed. Only .env.example, with placeholders, lives in version control.

Checkpoint

  • uv sync completes and backend/.venv exists
  • Your editor uses backend/.venv/bin/python and shows no unresolved imports
  • uv run python test.py prints the Pydantic version
  • backend/.env holds all four Azure values plus the deployment name

On this page