In the previous chapter, we looked at Vlahx as a collection of components: Python, FastAPI, SQLAlchemy, SQLite, Jinja2, Bootstrap, JavaScript, plugins, themes, and the files that hold everything together.
But an application is not really an application while it is sitting on disk.
It becomes an application when the process starts, the code is loaded, the application object is created, and something begins listening for HTTP requests.
This chapter follows that moment.
We will start Vlahx, look at the role of Uvicorn, enter main.py, follow create_app(), and then look at one of the most important pieces in the file: middleware.
Starting Vlahx
The normal entry point is:
python run.py
The important thing here is that run.py is not the Vlahx application itself. It is the launcher.
Its job is to prepare a few runtime options and start Uvicorn.
In reload mode, the relevant call is:
uvicorn.run( "main:app", host="0.0.0.0", port=port, reload=True, reload_dirs=["app"] )
The string main:app is particularly important.
It tells Uvicorn:
- load the Python module named
main; - find the object named
appinside that module; - use that object as the ASGI application.
So the process begins roughly like this:
run.py ↓ Uvicorn ↓ main:app ↓ main.py ↓ app
That small chain is the beginning of the Vlahx runtime.
What Is Uvicorn?
Uvicorn is an ASGI server. Its job is to sit between the outside world and the Python web application.
In practical terms, Uvicorn listens for connections and HTTP requests, then passes those requests to the ASGI application provided by FastAPI.
Vlahx does not implement the low-level network server itself. It builds the application; Uvicorn provides the machinery that actually serves it.
That distinction is useful:
Internet / Browser ↓ Uvicorn ↓ FastAPI ↓ Vlahx
When the terminal eventually reports something like:
INFO: Uvicorn running on http://0.0.0.0:8000 INFO: Application startup complete.
we are seeing the runtime announce that the application has reached the point where it can serve requests.
The source files are still sitting on disk exactly where they were before. What changed is that they are now part of a running process.
Entering main.py
Once Uvicorn loads main:app, Python imports main.py.
The central construction point in that file is:
def create_app() -> FastAPI: app = FastAPI() ... return app
At the bottom of the module, Vlahx creates the actual application:
app = create_app()
This is an important moment.
create_app() is effectively the factory that assembles the Vlahx application. It does not merely create an empty FastAPI object and return it. It prepares the environment in which that object will operate.
The Application Factory
Inside create_app(), several important things happen.
First, Vlahx creates the FastAPI application:
app = FastAPI()
Then it establishes application state and performs initialization work, including database initialization and synchronization of the active theme.
Static files are mounted:
app.mount("/static", StaticFiles(directory="app/static"), name="static")
Session middleware is added so the application can maintain session data across requests.
The template environment is built and stored on the application:
templates = build_templates("app/templates") app.state.templates = templates
Then Vlahx loads its plugins:
load_plugins(app)
This is one of the places where the modular nature of Vlahx becomes visible in the runtime.
The application is not a fixed block of code where every feature has to be hard-coded into main.py. Instead, the core creates the application and gives the plugin system an opportunity to extend it.
Middleware: The Layer Between the Request and the Router
One of the most useful concepts to understand when reading main.py is middleware.
Middleware sits around the request-processing process. It can inspect a request before the request reaches its final route, and it can also inspect or modify the response as it comes back.
A simplified view looks like this:
HTTP request ↓ Middleware ↓ Router ↓ Endpoint ↓ Response ↑ Middleware ↑ HTTP response
Vlahx already has a real example of this in main.py, so there is no need to invent an artificial example.
Vlahx's Installation and Locale Middleware
The application defines an HTTP middleware called install_and_locale_middleware.
@app.middleware("http") async def install_and_locale_middleware(request: Request, call_next): ...
The important object here is request. It represents the incoming HTTP request.
The second important object is call_next. Calling it passes the request further down the application chain.
Conceptually:
request ↓ install_and_locale_middleware ↓ call_next(request) ↓ router / endpoint
But Vlahx does not simply pass every request through without looking at it.
The middleware first examines the request path.
It handles several special cases, including static files, installation, language handling, and other exempt paths.
For normal requests, it checks whether the application has been installed by looking at the user count in the database. If there are no users yet, Vlahx redirects the request to /install.
After that, the middleware deals with locale information.
If the URL already contains a supported locale prefix, Vlahx extracts it and places the information into the request state.
If an old-style query parameter such as ?lang=en is encountered, the middleware can convert that request into the clean locale URL used by the application.
Finally, when the request is ready to continue, the middleware calls:
response = await call_next(request)
At this point the request is handed to the rest of the application.
This is a good example of why middleware is useful. The individual routes do not need to repeat the installation and locale logic themselves. The middleware provides a common layer that all applicable requests pass through.
Then Come the Routers
After the application and middleware are prepared, main.py registers the major routers.
app.include_router(api_router, prefix="/api") app.include_router(build_install_router(templates)) app.include_router(build_admin_router(templates)) app.include_router(build_auth_router(templates)) app.include_router(build_plugin_settings_router(templates)) app.include_router(media.router)
This is another important architectural boundary.
main.py knows which major pieces belong to the application, but it does not need to contain the implementation of every route.
The router modules contain their own route logic. main.py assembles those pieces into the running application.
Again, the distinction between source structure and runtime structure becomes important.
On disk, these components are separate Python modules.
At runtime, they become parts of the same FastAPI application.
The Root Route
Near the end of main.py, Vlahx defines the root-level route:
@app.get("/", response_class=HTMLResponse) @app.get("/{slug}", response_class=HTMLResponse) async def root_level_post(...): ...
This route is more interesting than it may initially appear.
For the root URL, Vlahx checks the configured homepage mode and asks the template hook system to render the appropriate homepage.
For a root-level slug, Vlahx gives the public slug system an opportunity to resolve it.
This means that even a seemingly simple request such as:
GET /
can pass through several layers before HTML is finally returned to the browser.
Putting the Runtime Together
We can now draw a much better picture of what happens when Vlahx starts:
python run.py ↓ Uvicorn ↓ main:app ↓ main.py ↓ create_app() ↓ FastAPI application ↓ database / theme / static files ↓ sessions / templates ↓ plugins ↓ middleware ↓ routers ↓ app ↓ HTTP requests
This is the part that a directory tree cannot show us.
The files tell us where the code lives. The runtime tells us how the pieces actually move.
And that distinction is fundamental when working with a modular framework such as Vlahx.
One File, Many Responsibilities
At first glance, main.py might look like a collection of unrelated configuration statements.
Once we follow the runtime, however, the structure becomes clearer.
main.py is the assembly point.
It creates the application, prepares its infrastructure, loads extensions, installs middleware, registers routers, and finally exposes the app object that Uvicorn serves.
It is not the whole Vlahx engine.
It is the place where many parts of the engine are brought together.
The source code is the pack.
main.py is one of the places where the pack gathers before it starts moving.
Where Do We Go From Here?
This chapter deliberately stays at the runtime level.
We introduced Uvicorn and looked at middleware because both are directly involved in the way the current Vlahx application runs.
There is much more to explore here.
For example, we could follow a single HTTP request through Uvicorn, middleware, routing, plugin hooks, database access, template rendering, and finally back to the browser.
That would take us much deeper into the runtime side of FastAPI and Vlahx.
If there is enough interest in the comments, we will make that a dedicated chapter.
For now, the important thing is to understand the first movement of the engine:
run.py → Uvicorn → main.py → create_app() → app
Once that chain becomes familiar, the rest of Vlahx starts to make considerably more sense.
💬 Comments (0)
💬 Join the Conversation
Log in quickly with Telegram to leave a comment.