How MVC Architecture Is Implemented in MoneyPrinterTurbo: FastAPI Structure Explained

MoneyPrinterTurbo implements a clean MVC architecture using FastAPI, where Pydantic models handle data validation and state management, controller modules manage HTTP routing and orchestration, and FastAPI's response handling combined with static file mounts serve as the view layer for JSON and media delivery.

MoneyPrinterTurbo is an AI-powered video generation application built on FastAPI that leverages a structured MVC (Model-View-Controller) pattern to separate concerns between data management, business logic, and presentation. This architectural approach makes the codebase modular, testable, and extensible for adding new AI-driven media generation features.

MVC Architecture Overview in MoneyPrinterTurbo

The project adapts classic MVC principles to the asynchronous, HTTP-centric world of FastAPI. Each layer has distinct responsibilities and implementation files:

MVC Layer Responsibility Primary Implementation Key Example
Model Defines data structures, validation rules, constants, and state-management logic Pydantic schemas (app/models/schema.py), constants (app/models/const.py), state services (app/services/state.py) VideoParams, TASK_STATE_PROCESSING, MemoryState
View Serializes model data into HTTP responses and serves static files FastAPI response models, utils.get_response, StaticFiles mounts in app/asgi.py utils.get_response(200, data), video file serving
Controller Handles HTTP requests, orchestrates service calls, and maps URLs to functions Router modules in app/controllers/v1/ (video.py, llm.py), root router (app/router.py) @router.post("/videos")create_video

The Model Layer: Data Validation and State Management

The Model layer in MoneyPrinterTurbo is responsible for data integrity, validation, and persistence. It uses Pydantic for schema definition and custom state classes for runtime data storage.

Pydantic Schemas for Request Validation

All request and response bodies are defined using Pydantic models in app/models/schema.py, guaranteeing type safety and automatic OpenAPI documentation generation.


# app/models/schema.py

class VideoParams(BaseModel):
    """Parameters supplied when creating a video task."""
    video_subject: str
    video_script: str = ""          # optional script supplied by the user

    video_aspect: Optional[VideoAspect] = VideoAspect.portrait.value
    # … other fields omitted for brevity

Constants and Enums

Shared constants such as task states and supported file types live in app/models/const.py. These enums are reused across schemas and services to maintain consistency.


# app/models/const.py

TASK_STATE_PROCESSING = 4
FILE_TYPE_VIDEOS = ["mp4", "mov", "mkv", "webm"]

State Management with MemoryState and RedisState

The Model layer also encapsulates runtime task state through the BaseState abstraction. The implementation chooses between in-memory (MemoryState) and Redis (RedisState) based on configuration.


# app/services/state.py

class MemoryState(BaseState):
    def __init__(self):
        self._tasks = {}

    def update_task(self, task_id: str, state: int = const.TASK_STATE_PROCESSING, progress: int = 0, **kwargs):
        self._tasks[task_id] = {"task_id": task_id, "state": state, "progress": progress, **kwargs}

The View Layer: JSON Responses and Static Media

In MoneyPrinterTurbo, the View layer is responsible for serializing Model data into HTTP responses. FastAPI handles much of this automatically, but the project adds standardization through utility functions and static file mounts.

Standardized JSON Response Envelopes

The app/utils/utils.py file provides a helper function to ensure all API responses follow a consistent envelope structure.


# app/utils/utils.py

def get_response(status: int, data: Any = None, message: str = "success"):
    return {"status": status, "message": message, "data": data}

Serving Generated Videos via StaticFiles

The View layer also serves generated media directly. In app/asgi.py, StaticFiles mounts act as the view for video resources, making completed tasks downloadable or streamable.


# app/asgi.py

task_dir = utils.task_dir()
app.mount("/tasks", StaticFiles(directory=task_dir, html=True, follow_symlink=True), name="")
public_dir = utils.public_dir()
app.mount("/", StaticFiles(directory=public_dir, html=True), name="")

The Controller Layer: Routing and Business Logic

Controllers in MoneyPrinterTurbo handle HTTP request validation, orchestrate service calls, and return view responses. They are organized under app/controllers/v1/ and aggregated by a root router.

Video Generation Endpoints

The app/controllers/v1/video.py module defines endpoints for creating and managing video tasks. It validates incoming TaskVideoRequest models and delegates processing to the task manager.


# app/controllers/v1/video.py

@router.post("/videos", response_model=TaskResponse, summary="Generate a short video")
def create_video(background_tasks: BackgroundTasks, request: Request, body: TaskVideoRequest):
    return create_task(request, body, stop_at="video")

The create_task helper function demonstrates the controller's orchestration role:

def create_task(request: Request, body: Union[TaskVideoRequest, SubtitleRequest, AudioRequest], stop_at: str):
    task_id = utils.get_uuid()
    request_id = base.get_task_id(request)
    task = {"task_id": task_id, "request_id": request_id, "params": body.model_dump()}
    sm.state.update_task(task_id)                     # Model update

    task_manager.add_task(tm.start, task_id=task_id, params=body, stop_at=stop_at)   # Service call

    return utils.get_response(200, task)              # View response

LLM Script Generation Endpoints

The app/controllers/v1/llm.py module handles AI-driven content creation, following the same pattern of validating models and returning standardized responses.


# app/controllers/v1/llm.py

@router.post("/scripts", response_model=VideoScriptResponse, summary="Create a script for the video")
def generate_video_script(request: Request, body: VideoScriptRequest):
    video_script = llm.generate_script(
        video_subject=body.video_subject,
        language=body.video_language,
        paragraph_number=body.paragraph_number,
    )
    return utils.get_response(200, {"video_script": video_script})

Router Aggregation

The root router in app/router.py collects all version-specific controllers, forming the complete API surface.


# app/router.py

root_api_router = APIRouter()
root_api_router.include_router(video.router)   # Controller → View

root_api_router.include_router(llm.router)

Wiring the Application Together

The app/asgi.py file serves as the application bootstrap, mounting the root router and initializing the view layer's static file handling. This completes the MVC pipeline by connecting controllers to the FastAPI application instance and configuring the view components for media delivery.

Summary

MoneyPrinterTurbo demonstrates a clean implementation of MVC architecture within the FastAPI ecosystem:

  • Models define data structures using Pydantic schemas, manage constants in const.py, and handle runtime state through MemoryState or RedisState implementations.
  • Views serialize data through standardized JSON envelopes in utils.get_response and serve generated media via StaticFiles mounts in asgi.py.
  • Controllers in app/controllers/v1/ handle HTTP routing, validate incoming models, orchestrate service calls, and return consistent view responses through the root router aggregation.

Frequently Asked Questions

How does MoneyPrinterTurbo handle state management within the MVC pattern?

MoneyPrinterTurbo implements state management in the Model layer through the BaseState abstraction defined in app/services/state.py. The system supports both MemoryState for in-memory storage during development and RedisState for production persistence, allowing controllers to update task progress via sm.state.update_task() while remaining agnostic to the underlying storage mechanism.

What serves as the View layer in this FastAPI implementation?

The View layer consists of two primary components: standardized JSON response envelopes generated by utils.get_response() in app/utils/utils.py, and static file mounts configured in app/asgi.py using FastAPI's StaticFiles. Together, these components handle both API data serialization and direct media delivery for generated video files.

Where are the Controller endpoints defined in the project?

Controller endpoints are organized under app/controllers/v1/, with specific modules like video.py handling video generation routes and llm.py managing AI script creation. These are aggregated into the root API router in app/router.py using root_api_router.include_router(), creating a centralized routing structure that connects to the FastAPI application instance in app/asgi.py.

How does the Model layer validate incoming API requests?

The Model layer uses Pydantic schemas defined in app/models/schema.py to enforce data validation automatically. When a controller receives a request, FastAPI validates the payload against these schemas—such as VideoParams or TaskVideoRequest—ensuring type safety and generating OpenAPI documentation before the controller logic executes.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →