# openOii turns a story idea into storyboards, then pins itself to one worker

> openOii chains planning, character and storyboard generation, and video compositing into a single LangGraph run drawn on an infinite canvas. It is a learning project, and its compose file holds the backend to one worker on purpose.

**xeronsh/openOii** — From story idea to multi-agent collaboration to a finished comic film: an AI motion-comic generation platform based on LangGraph.

- Repository: https://github.com/xeronsh/openOii
- Stars: 403 · Forks: 99
- Language: Python
- License: not declared
- Published: 2026-09-10 · Updated: 2026-09-10 · Language: en
- Canonical page: https://hysenlabs.com/projects/xeronsh-openoii

## Four LangGraph stages drawn on one infinite canvas

The pipeline takes a story idea and runs it through planning, then character and storyboard generation, then video generation and compositing, with a tldraw infinite canvas showing the process and the results as they land. The run flow is resumable, cancellable and takes feedback, and progress arrives over WebSocket rather than at the end of a request. On the stack side the front end is React 18 with TypeScript and tldraw, the back end is FastAPI with SQLModel and LangGraph, and the infrastructure is PostgreSQL, Redis and a /static mount. A warning block sits directly under the description: this is a LangGraph learning and demo project aimed at validating multi-stage orchestration, resumable execution, live progress and frontend/backend cooperation, and it is not suited to direct industrial production use. Above that description the README carries a sponsor block for Bloome, a hosted service that puts Claude, ChatGPT and DeepSeek into one conversation to question and cross-check each other.

## task_manager and confirm keep state in the process, so workers stay at one

The most consequential line in docker-compose.yml is not a port. It is WEB_CONCURRENCY: "1" on the backend service, with a comment saying that task_manager and confirm depend on in-process state and the current implementation is only safe with a single worker by default. Resumable, cancellable, feedback-capable runs are exactly the features that need shared state, and here that state stays inside one process. The same service already waits for healthy PostgreSQL and Redis before it starts, so the persistent stores are available; they are simply not where run state lives. Reading the compose file as a deployment template, anyone who copies it into a scaled environment inherits a single backend process until that state moves out.

## Compose replaces the database and Redis URLs that backend/.env sets

The backend service loads env_file ./backend/.env and then overrides two keys with an environment block, so anything you put in that file for the database or Redis is ignored while compose is driving the stack. DATABASE_URL becomes postgresql+asyncpg://openoii:openoii_dev@postgres:5432/openoii and REDIS_URL becomes redis://redis:6379/0, because inside the compose network the hosts are service names rather than localhost. Two more keys, IMAGE_BASE_URL and VIDEO_BASE_URL, are present but commented out, waiting for you to name real containers and ports if the image and video services also move into Docker. A commented networks block at the bottom covers the other case: joining an external Docker network that already hosts those services.

## The two line quick start pulls :latest images instead of your checkout

The documented fast path is two commands. They do not build the Python or TypeScript in this repository; they fetch ghcr.io/xeronsh/openoii-backend:latest and ghcr.io/xeronsh/openoii-frontend:latest, which is why the copy step for backend/.env.example matters, since the compose file reads that file as its env_file and the backend service will not start without it. The front end is published on 15173 and the API docs on 18765. Both services carry restart: unless-stopped, so a container that crashes comes back on its own. With no GitHub releases published, :latest is the only handle anyone has on the image contents, and the compose file pins no digest, so two people running these commands on different days are not guaranteed the same build.

## The other route runs uvicorn on 18765 and a pnpm dev server beside it

Dropping the containers means running both halves on the host instead.

```bash
# backend
cd backend
uv sync
uv run uvicorn app.main:app --reload --host 0.0.0.0 --port 18765

# frontend
cd frontend
pnpm install
pnpm dev
```

Port 18765 is the same number the compose file publishes, so the documented API port does not move between the two routes. What this route adds is two dependency installs and two toolchains, uv for Python and pnpm for the front end, plus a reload watcher on the backend. The daily commands are split the same way, with pytest and ruff check app tests on the Python side and pnpm test and pnpm build on the TypeScript side, so a contributor ends up running two toolchains for every change.

## Postgres and Redis publish development ports with their credentials in the file

Both stores are fully specified and both are exposed to the host. Postgres runs postgres:16-alpine with POSTGRES_USER, POSTGRES_DB and POSTGRES_PASSWORD set in the tracked compose file, published on 5432 and backed by a named postgres_data volume. Redis runs redis:7-alpine on 6379 with a redis_data volume. Each waits on its own health check, pg_isready -U openoii for Postgres and redis-cli ping for Redis, both on a 5 s interval with a 5 s timeout and 5 retries, and the backend declares condition: service_healthy on both. Publishing 5432 and 6379 alongside a development password in a committed file is a laptop arrangement. It collides with anything already listening on those ports, and it is the first thing to change before this runs anywhere shared.

## Two documentation directories, four briefs, and a licence with no file

The repository root carries more planning documents than most projects of this size: AGENTS.md, CONTEXT.md, DESIGN.md, PRODUCT.md, a .impeccable/ directory and a .run/ directory, alongside both doc/ and docs/. Two extra compose files, docker-compose.dev.yml and docker-compose.override.yml, sit next to the docker-compose.yml the quick start actually uses, and pyrightconfig.json at the root holds type checking configuration even though the documented Python commands stop at pytest and ruff check app tests. The README closes with a License section reading MIT, and no LICENSE file appears among the top-level entries, so anyone reusing the code has the README line and nothing else to go on. The repository is not archived, the last push landed on 27 September 2026, three issues are open, and no releases exist.

## Conclusion

Use openOii if you are studying multi-stage LangGraph orchestration and want a run you can pause, cancel and resume while watching progress over WebSocket. Do not adopt it as a production service yet: the project says so itself, the licence is asserted in the README rather than shipped in a file, and moving the task and confirm state out of process is the work that has to happen before the backend can run more than one worker. Verify first that the ghcr.io :latest images match the commit you intend to read, since no releases are published.

## FAQ

### What is openOii built on?

The back end is FastAPI with SQLModel and LangGraph, the front end is React 18 with TypeScript and tldraw, and the infrastructure is PostgreSQL, Redis and a /static mount. A story idea runs through planning, character and storyboard generation, then video generation and compositing.

### Is openOii ready for production use?

No, and the project says so. A warning in the README calls it a LangGraph learning and demo project focused on validating multi-stage orchestration, resumable execution, live progress and frontend/backend cooperation, and not suited to direct industrial production use.

### How do I start openOii quickly?

Copy backend/.env.example to backend/.env, then run docker-compose up -d. That pulls the prebuilt backend and frontend images from ghcr.io rather than building the checkout. The front end is on http://localhost:15173 and the API docs on http://localhost:18765/docs.

### Can the openOii backend run more than one worker?

Not with the current implementation. docker-compose.yml sets WEB_CONCURRENCY to "1" on the backend service, with a comment saying task_manager and confirm depend on in-process state and the current code is only safe with a single worker by default.

### What licence is openOii under?

The README ends with a License section reading MIT. No LICENSE file appears among the repository's top-level entries, so that line in the README is the only statement of terms.

## Sources

- [Issues](https://github.com/xeronsh/openOii/issues)
- [README](https://github.com/xeronsh/openOii/blob/main/README.md)
- [xeronsh/openOii on GitHub](https://github.com/xeronsh/openOii)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/xeronsh-openoii
