# STRUCTURE — document-scanner

_Last updated: 2026-05-21_

## Summary

The project is a monorepo with two top-level service directories (`backend/`, `frontend/`) and Docker Compose at the root. Backend is a Python/FastAPI app; frontend is a Vue 3 SPA built with Vite. All persistent data lives under `backend/data/`.

---

## Top-Level Layout

```
document_scanner/
├── backend/              Python FastAPI service
├── frontend/             Vue 3 SPA
├── docker-compose.yml    Two-service compose (backend + frontend)
├── .env.example          Optional env vars (API keys)
└── .claude/              Claude Code settings
```

---

## Backend

```
backend/
├── main.py               FastAPI app: CORS, lifespan, router registration
├── config.py             Path constants, DEFAULT_SETTINGS, ensure_data_dirs()
├── requirements.txt      Python dependencies
├── pytest.ini            pytest config (asyncio_mode=auto)
├── Dockerfile
│
├── api/                  FastAPI routers (thin HTTP layer)
│   ├── documents.py      Upload, list, get, delete, reclassify endpoints
│   ├── topics.py         Topic CRUD endpoints
│   └── settings.py       AI provider settings endpoints
│
├── ai/                   AI provider abstraction
│   ├── base.py           AIProvider ABC + ClassificationResult dataclass
│   ├── __init__.py       get_provider() factory
│   ├── anthropic_provider.py
│   ├── openai_provider.py
│   ├── ollama_provider.py      extends OpenAIProvider
│   └── lmstudio_provider.py    extends OpenAIProvider
│
├── services/             Business logic (no FastAPI dependency)
│   ├── extractor.py      Text extraction: PDF/DOCX/image/text dispatch
│   ├── classifier.py     Orchestrates AI call + topic auto-creation
│   └── storage.py        Flat-file JSON CRUD + filelock
│
├── data/                 Runtime data (volume-mounted in Docker)
│   ├── uploads/          Uploaded document files
│   ├── metadata/         Per-document JSON metadata files
│   ├── topics.json       Global topic list
│   └── settings.json     Active AI provider + system prompt config
│
└── tests/
    ├── conftest.py       Fixtures: isolated tmp data dir, TestClient, sample files
    ├── test_health.py
    ├── test_documents.py
    ├── test_topics.py
    ├── test_settings.py
    ├── test_extractor.py
    ├── test_classifier.py
    └── test_lmstudio.py
```

---

## Frontend

```
frontend/
├── index.html            Vite entry HTML
├── vite.config.js        Vite config (Vue plugin, /api proxy)
├── tailwind.config.js
├── postcss.config.js
├── package.json          Vue 3, Vue Router 4, Pinia; no test framework
├── Dockerfile
│
└── src/
    ├── main.js           App bootstrap: Vue + Pinia + Router
    ├── App.vue           Root component (sidebar layout wrapper)
    ├── style.css         Global Tailwind imports
    │
    ├── api/
    │   └── client.js     fetch wrapper; all API calls go through here
    │
    ├── stores/           Pinia stores (data + actions layer)
    │   ├── documents.js  Document list, upload, classify state
    │   ├── topics.js     Topic list CRUD state
    │   └── settings.js   AI provider settings state
    │
    ├── router/
    │   └── index.js      Routes: /, /topics, /topics/:name, /document/:id, /settings
    │
    ├── views/            Page-level components (one per route)
    │   ├── HomeView.vue
    │   ├── TopicsView.vue
    │   ├── DocumentView.vue
    │   └── SettingsView.vue
    │
    └── components/       Reusable UI components
        ├── layout/
        │   └── AppSidebar.vue
        ├── documents/
        │   └── DocumentCard.vue
        ├── topics/
        │   ├── TopicBadge.vue
        │   └── TopicManager.vue
        └── upload/
            ├── DropZone.vue
            └── UploadProgress.vue
```

---

## Key Entry Points

| File | Purpose |
|---|---|
| `backend/main.py` | FastAPI app instantiation, middleware, router registration |
| `backend/config.py` | All path constants and default settings — change storage paths here |
| `backend/ai/__init__.py` | Add a new AI provider here |
| `frontend/src/main.js` | Vue app bootstrap |
| `frontend/src/api/client.js` | All HTTP calls originate here |

---

## Where to Add New Code

- **New API endpoint**: add router in `backend/api/`, register in `backend/main.py`
- **New AI provider**: implement `AIProvider` ABC in `backend/ai/`, add case in `get_provider()`
- **New document type**: add extraction branch in `backend/services/extractor.py`
- **New frontend page**: add view in `src/views/`, add route in `src/router/index.js`
- **New shared UI component**: add to relevant `src/components/<category>/` subdirectory

---

## Gaps / Unknowns

- No `src/components/settings/` subdirectory — settings UI is entirely in `SettingsView.vue`
- No migration or schema versioning for `topics.json` / `settings.json` flat files
