Coding standards¶
How we write code in Docling Studio. Linters and tests check most of these rules. Reviewers check the rest.
Backend (Python, document-parser/)¶
Tools¶
| Tool | Role | Config |
|---|---|---|
| Ruff | Lint and format | [tool.ruff] in document-parser/pyproject.toml |
| pytest | Tests | document-parser/pytest.ini |
| pytestarch | Layer rules, run as a test | document-parser/tests/test_architecture.py |
The commands to run are in CONTRIBUTING.
Naming¶
| Element | Convention | Example |
|---|---|---|
| Modules | snake_case |
analysis_repo.py |
| Classes | PascalCase |
AnalysisJob, DocumentConverter |
| Functions and methods | snake_case |
find_by_document() |
| Constants | UPPER_SNAKE_CASE |
DEFAULT_PAGE_HEIGHT |
| Private names | _leading_underscore |
_build_chunker() |
Style¶
- Keep functions to 30 lines at most. A longer one needs a reason.
- Keep files to 300 lines at most. Split a file that grows past it.
- Order imports: standard library, third-party, local. Ruff sorts them.
- Add type hints to every public function.
- Write a docstring only when the code is not obvious.
Layers¶
The backend uses ports and adapters. The ports are Protocol classes, all in domain/ports.py. infra/ and persistence/ implement them. bootstrap/ builds the adapters and passes them to the services.
tests/test_architecture.py fails when a layer imports something it must not:
| Layer | Must not import |
|---|---|
domain/ |
api, services, infra, persistence, and the fastapi, sqlalchemy, httpx and opensearchpy libraries |
services/ |
api, infra, persistence, and fastapi |
api/ |
infra, persistence |
infra/ |
api, services |
persistence/ |
api, services, infra |
In practice: routes call services, and services reach adapters only through ports.
API contract¶
- JSON uses camelCase. API models extend
_CamelModelinapi/schemas.py, which generates camelCase aliases. Python code stays snake_case. - One exception: an analysis's
pagesJsonis a JSON string whose keys stay snake_case (page_number,self_ref), because the backend builds it withdataclasses.asdict(). - Route design rules are in Architecture.
Frontend (TypeScript and Vue, frontend/src/)¶
Tools¶
| Tool | Role | Config |
|---|---|---|
| ESLint | Lint | frontend/eslint.config.js (flat config) |
| Prettier | Format | frontend/.prettierrc |
| vue-tsc | Type check | frontend/tsconfig.json |
| Vitest | Tests | frontend/vite.config.js (Vitest reads the Vite config) |
Naming¶
| Element | Convention | Example |
|---|---|---|
| Components | PascalCase.vue |
BboxCanvas.vue |
| Composables | useCamelCase.ts |
usePagination.ts |
| Stores | store.ts in the feature folder |
features/analysis/store.ts, which exports useAnalysisStore |
| Types and interfaces | PascalCase |
Analysis, PageElement |
| Constants | UPPER_SNAKE_CASE |
PREVIEW_DPI |
| CSS classes | kebab-case |
.bbox-canvas |
data-e2e attributes |
kebab-case |
data-e2e="upload-zone" |
Style¶
- Use the Composition API:
<script setup lang="ts">. No Options API. - Put one component in each file.
- Type props and emits:
defineProps<T>(),defineEmits<T>(). - A feature has one Pinia store at most, in
store.ts. Shared state lives in stores. The only exception isshared/appConfig.ts. - Put HTTP calls in the feature's
api.ts, built onapiFetchfromshared/api/http.ts. Components and stores call those functions. - Put unit tests next to the code:
store.test.tsbesidestore.ts. Tests that span features go insrc/__tests__/integration/.
Feature boundaries¶
Each feature lives in src/features/<name>/. Its index.ts lists what other features may use. A feature imports another feature only through @/features/<name>, or uses @/shared. It never reaches into another feature's store, api or ui.
ESLint enforces this with the no-restricted-imports rule in frontend/eslint.config.js. Test files are exempt.
End-to-end tests (Karate, e2e/)¶
The full rules are in e2e/CONVENTIONS.md. The essentials:
- Select elements with
data-e2e, never with CSS classes. - Wait with
waitFor()orwaitUntil(), never withThread.sleep()ordelay(). - Set up through the API, check through the UI, clean up through the API.
- Tag tests:
@critical,@ui,@smoke,@regressionor@e2e.