Backend Module
The backend half of a module is a Python package that exposes a FastAPI sub-application. Ocelescope discovers it through a Python entry point and mounts it under a versioned path.
Creating a backend module
Section titled “Creating a backend module”The module template includes scripts that generate new modules from templates. To create a backend module, run the following from the repository root:
pnpm run add:backend ocel-statsocel-stats is the name of the folder the module is created in. To create a backend and a frontend module together, use pnpm run add:module instead.
The script uses Copier to generate the module from the backend module template. It asks for the module’s name, a short description and an author. All other names are derived from the module name:
| Module name | Python package | Module key | Class |
|---|---|---|---|
OCEL Stats | ocelescope-module-ocel-stats | ocelStats | OCELStats |
3D Viewer | ocelescope-module-3d-viewer | module3dViewer | Module3DViewer |
The module is created in backend-modules/<folder>:
backend-modules/ocel-stats/├── src/ocelescope_module_ocel_stats/│ ├── __init__.py│ ├── module.py # The Module class│ └── routes.py # The module's API endpoints├── .copier-answers.yml # Your answers, used to update the module later├── pyproject.toml└── README.mdThe script then adds the module to the root pyproject.toml, so it is installed as part of the backend.
Install it and start the development servers:
pnpm run syncpnpm run devThe backend loads the module on startup and serves it under /modules/<key>/v1.
The generated module contains a single example endpoint, which you can open at http://localhost:8000/modules/ocelStats/v1/hello.
The following sections explain the generated files and how to extend them.
The Module class
Section titled “The Module class”module.py defines the module itself: a class that inherits from Module (from ocelescope_backend.app.modules). It declares its identity through meta and builds its FastAPI app in create_app.
from fastapi import FastAPIfrom ocelescope_backend.app.modules import Module, ModuleMetafrom packaging.version import Version
from ocelescope_module_ocel_stats.routes import router
class OCELStats(Module): meta = ModuleMeta(key="ocelStats", version=Version("1.0"))
def create_app(self) -> FastAPI: app = FastAPI(title="OCEL Stats", version=str(self.meta.version)) app.include_router(router) return appmeta.keyis the module’s unique identifier andmeta.versionits version. The module is mounted at/modules/<key>/v<major>, so the major version is part of the URL and you can run multiple major versions side by side.create_appreturns a fully independent FastAPI app. Include your routers on it and return it.
Defining routes
Section titled “Defining routes”routes.py contains the module’s endpoints on an APIRouter. The generated module comes with a single example endpoint:
from fastapi import APIRouterfrom pydantic import BaseModel
router = APIRouter()
class HelloResponse(BaseModel): message: str
@router.get("/hello", operation_id="hello", response_model=HelloResponse)def hello() -> HelloResponse: return HelloResponse(message="Hello from the OCEL Stats backend module")Give every endpoint a stable operation_id, because it becomes the name of the generated frontend hook.
Declaring the response as a Pydantic model gives the generated frontend client fully typed responses.
Accessing the session and OCELs
Section titled “Accessing the session and OCELs”Two dependencies from ocelescope_backend.app.dependencies give you access to the current session and its logs:
ApiSessioninjects the activeSession, which holds the uploaded OCELs and resources.ApiOcelinjects anOCELdirectly, resolved from theocel_idpath parameter.
from ocelescope_backend.app.dependencies import ApiOcel
@router.get("/{ocel_id}/object-types", operation_id="getObjectTypes")def get_object_types(ocel: ApiOcel) -> list[str]: return ocel.objects.typesThe injected OCEL is the same ocelescope library class used everywhere else, so its managers (objects, events, e2o, o2o, …) are available.
Registering the entry point
Section titled “Registering the entry point”Ocelescope finds modules through the ocelescope_backend.modules entry point group. The generated pyproject.toml already declares the module under its key:
[project]name = "ocelescope-module-ocel-stats"version = "0.1.0"readme = "README.md"description = "An Ocelescope module"authors = [{ name = "Your Name" }]requires-python = ">=3.11"dependencies = [ "ocelescope-backend>=0.10.1",]
[project.entry-points."ocelescope_backend.modules"]ocelStats = "ocelescope_module_ocel_stats.module:OCELStats"When the backend starts, it loads every entry point in that group, checks each is a Module subclass, and mounts it. Duplicate key and major-version pairs are skipped, so install only one package per major version.
Add further Python dependencies of your module from its folder with uv add <package>.
Once the backend is in place, build the Frontend Module that consumes it.