Getting Started
This guide walks you through scaffolding your first WebFluid project, wiring up a
minimal route, and adding a touch of frontend. By the end you will have a running
app and a feel for how the pieces fit together.
Keep in mind that WebFluid has opinions and so it ships with conventions which we
will explain in detail later on.
Installation
Install the webfluid package from PyPI. The CLI wf ships
alongside it and is what you will use for every project task from here on.
Since this is an alpha version, you will need to pin it to install it.
pip install webfluid==1.0.0a1
mkdir -p myapp/fluid/templates
cd myapp
mkdir fluid/static
mkdir app_configs
This is the minimum required structure for this version to spin up your first minimal fullstack application. For now, we did not use the frameworks CLI to keep this introduction minimalistic and simple.
Python 3.14 or newer is required. WebFluid is built using the latest standards.
Your first app
Fluid is a child of FastAPI. So setting up routes works exactly the same way. The snippet below is a minimal service that serves a static HTML page and a health check.
from webfluid import Fluid
from fastapi.responses import HTMLResponse
fluid = Fluid(__name__)
@fluid.get("/", response_class=HTMLResponse)
async def home():
return await fluid.render(
"index.html",
title="Hello World!",
name="my friend"
)
@fluid.get("/health")
async def health():
return {"status": "ok"}
if __name__ == "__main__":
fluid.mix()
What you see
The snippet is looking like a mixture of Flask and FastAPI. But with one major difference:
Flask and FastAPI are designed to be minimalistic. Fluid is a fullstack runtime, and so there
is a lot of magic happening behind the scenes.
Nevertheless, it comes with a broad but optioned stack which allows you to decide how much
of the magic you really need.
Anyway, for now we won't go into detail about what is really happening here. We just want to get
you started. So let's continue setting up your app.
Adding a sprinkle of frontend
Now we have created a minimalistic app, which should render an index.html
template. Like Flask, Fluid is also using the Jinja2 templating engine. It has its
own jinja_env, and the major difference is the async environment as well as the
rendering utility that sits inside the class.
Another slight difference is the location of the app templates. Fluid is designed to
be abstracted and modular. So they are (as you may have already guessed looking at
the setup command chain) located inside the fluid directory:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{{ title }}</title>
<script>
function healthCheck() {
const result = document.getElementById('result')
fetch('/health').then(res => {
if (res.ok) result.style.color = 'green'
else result.style.color = 'red'
return res.json()
}).then(data => {
result.innerText = JSON.stringify(data)
setTimeout(() => result.innerText = '', 2000)
})
}
</script>
</head>
<body>
<p>Hello <b>{{ name }}</b>!</p>
<button onclick="healthCheck()">Health Check</button>
<p id="result"></p>
</body>
</html>
Set up your application
Now everything is set in place. But before you can run your application,
you will need to create an app config first. This is because WebFluid is
able to serve multiple apps with different configs and setups in just
one project directory.
Fluid requires only one config variable to run. And this is SECRET_KEY.
So creating your app is as simple as:
cat <<'EOF' > app_configs/app.ini
[general]
SECRET_KEY = supersecret
EOF
Running your app
This is it. You can now run your app with the wf run command.
It just takes the name of your app config (which should be equal to the name
of your app) and parses your configuration as the apps' environment.
user@host:~/myapp: wf run app
Starting application...
[WF] [2026-05-28 18:04:29 +0200] [INFO] Mixing your WebFluid application.
[WF] [2026-05-28 18:04:29 +0200] [WARNING] Session cookies are not secure. Consider setting SESSION_COOKIE_SECURE=True.
[WF] [2026-05-28 18:04:29 +0200] [INFO] Running startup hooks...
[WF] [2026-05-28 18:04:29 +0200] [INFO] Server is listening on 127.0.0.1:8000.
Now you can access your app by opening http://localhost:8000 in your browser.
You may notice the warning inside your log / the console output. This is because Fluid sets up a SessionMiddleware
when it gets initialized. It is configured as insecure per default. We will take a closer look at configuring your
app in the next chapter.
For now if you would like to supress this warning, you need to run your app in debug mode using the
-d flag.
Next steps
With the basics in place, we can now dive below the surface of your fluid:
- Read the configuration guide to learn how to configure your apps.
- Explore our extension system and the built-in batteries.
- Discover the integrated frontend tooling to release the full potential of your fluid.
- Build portable modules using our Additive battery.
- Skim the CLI reference for everything the
wfcommand can do.