Metadata-Version: 2.5
Name: coasti-planner
Version: 0.1.1
Summary: Backend service for the Coasti Planning Framework.
Author-email: "Sebastian B. Mohr" <sebastian@mohrenclan.de>, "F. Paul Spitzner" <paul.spitzner@linkfish.eu>
Requires-Python: >=3.13
Requires-Dist: eyconf[pydantic]>=0.8.0
Requires-Dist: fastapi>=0.115.0
Requires-Dist: ruamel-yaml>=0.19.1
Requires-Dist: sqlalchemy>=2.0.0
Requires-Dist: typer>=0.27.3
Requires-Dist: uvicorn[standard]>=0.34.0
Description-Content-Type: text/markdown

# Coasti Planning Framework — Backend

The backend is a Python 3.13 FastAPI application managed with
[uv](https://docs.astral.sh/uv/). It serves the framework and content-package
assets from local Vite build directories.

## Setup

Run this command from the repository root:

```bash
uv sync --directory backend --locked
```

The repository root also provides a Nix/direnv development shell that installs
the required tools automatically. See the root [README](../README.md).

## Build the frontend distributions

The backend does not build the frontend itself. Build the framework and the
example extension before running the backend in local distribution mode; the
framework build is also bundled into the package when building a wheel (see
[Package the backend](#package-the-backend)).

### Framework distribution

Install the frontend workspace dependencies and build the planner framework:

```bash
pnpm --dir frontend install --frozen-lockfile
pnpm --dir frontend build
```

This creates the framework distribution in `frontend/app/dist`.

### Example extension distribution

Install the extension dependencies and build the example content package:

```bash
pnpm --dir cp_example_extension install --frozen-lockfile
pnpm --dir cp_example_extension build
```

This creates the extension distribution in `cp_example_extension/dist`. The
build includes the generated `manifest.json` and Module Federation entry point.

## Configuration

The server accepts a `server` command and an optional YAML configuration path.
The legacy form with only the configuration path remains supported.

The example configuration is available at
[config.example.yml](../cp_example_extension/config.example.yml):

```yaml
backend:
  host: 127.0.0.1
  port: 8000
framework:
  dist_folder: ../frontend/planner/dist
extension:
  dist_folder: ./dist
```

Configuration is loaded by [EYConf](https://eyconf.readthedocs.io/) using its
Pydantic validation backend. The configuration is represented by three pairs of
schema/runtime types in `coasti_planner.config`:

- `BackendConfigSchema` / `BackendConfig` define the listening host and port.
- `AssetSourceSchema` / `AssetSource` define a local distribution or remote
  development server.
- `ServerConfigSchema` / `ServerConfig` combine the backend, framework, and
  extension settings.

Each asset source defines a local `dist_folder`. Relative paths are resolved
relative to the configuration file, not relative to the current working
directory.

## Run the backend

From the repository root, after building both distributions:

```bash
uv run --directory backend coasti-planner ../cp_example_extension/config.example.yml
```

### Run the full stack in development mode

Development mode does not require either frontend distribution directory. Run
the backend from the backend project directory:

```bash
cd backend
uv run backend server --dev
```

The backend uses Uvicorn autoreload and the example configuration by default.
Run the Vite development servers in separate terminals:

```bash
pnpm --dir frontend dev
pnpm --dir cp_example_extension dev
```

The frontend development server proxies API requests to the autoreloading
backend, while the frontend and extension servers reload their own source files.

## HTTP endpoints

- `/` serves the framework `index.html` and its root-relative assets.
- `/api_v1/framework/{path}` serves framework distribution files.
- `/api_v1/extension/{path}` serves extension distribution files.
- `/api_v1/extension/manifest.json` serves the extension's generated manifest.

The manifest is read from the extension distribution. It is not duplicated in
the backend.

## Package the backend

Building the backend bundles the framework build into the wheel:

```bash
pnpm --dir frontend build        # produces frontend/app/dist
uv build --directory backend     # bundles it into the package
```

The `CustomBuildHook` in `backend/hatch_build.py` copies `frontend/app/dist`
into `src/coasti_planner/assets` before packaging, and hatchling includes that
directory in both the wheel and the sdist through the `artifacts` entries in
`pyproject.toml`. The installed backend serves those bundled assets by default,
so it needs no separate framework distribution. Packaging fails with a clear
error when the framework has not been built yet.
