experimental · not production-ready
The reactive template engine for Python.
Build interactive, modern web interfaces with pure Python and HTML. No complex JavaScript stack required.
pip install pyblade
copied
~/code — zsh
Install PyBlade with pip, create a project with pyblade init, then run it with pyblade dev.
Fully supported on Django today. More frameworks on the way.
@syntax
The whole language fits on one screen.
There is no plugin system to learn and no filter library to memorise. Directives start with @, expressions sit in {{ braces }}, and everything else is the HTML you already wrote.
Structure
- @extends
- Inherit a parent layout.
- @block … @endblock
- Fill a named region of that layout.
- @component
- Drop in a reusable, self-contained piece of UI.
Control flow
- @if / @else / @endif
- Branch on any Python expression.
- @for … @endfor
- Loop over a collection.
- @empty
- The fallback when the loop had nothing to show.
{{ comment.body }}
Escaped, always
Every variable is escaped on the way out. A comment containing <script> renders as text, not as a script. You don't opt in to this.
{!! comment.body !!}
Raw, when you say so
The second syntax exists so that trusting input is a decision you write down, visible in review, rather than a default you inherit.
@reactivity
Interactive, and still just Python.
PyBlade Live components render on the server and update only the part of the page that changed. No full page reloads, no build step, no second language for the same feature.
The search box on this page is one. Type in it: each keystroke goes to the Python class below, which filters the list, and the template renders again on the server. Watch the time at the bottom change.
components/home/directive_search/directive_search.py
class DirectiveSearch(LiveComponent): query: str = "" def clear(self): self.query = "" def render(self): words = self.query.lower().split() matches = [d for d in DIRECTIVES if all(w in d.text for w in words)] return self.render_template( context={"matches": matches})
directive_search.html
<input pb:model.live="query"> @for(match in matches) <code>{{ match.name }}</code> @empty <button pb:click="clear">Clear</button> @endfor
Shortened for the page. pyblade make:live writes both files for you.
<pb-home.directive-search />
live
-
@extendsInherit a parent layout. -
@blockFill a named region of the layout. -
@includeRender another template in place. -
@section / @yieldDefine content once, output it elsewhere. -
@push / @stackCollect scripts or styles from anywhere into one place. -
@componentDrop in a reusable piece of UI. -
@propsDeclare what a component takes, with defaults. -
@slotHand a component a named piece of markup.
This is running on the server that sent you this page. Open your browser's network tab to watch the requests go.
@cli
One command to start. One to keep going.
The CLI scaffolds the project, writes the pieces for you, runs the dev server with Tailwind watching alongside, and — when PyBlade Cloud opens — ships it.
- init · new project
- dev · dev server
- make:template · template
- make:component · component
- make:live · Live component
- tw:config · config Tailwind
- make:messages · translations
- deploy · to PyBlade Cloud
$ pyblade make:template blog.index ✔ Created template 'templates/blog/index.html' successfully. $ pyblade make:live like_button ✔ Live component created successfully: - HTML: components/like_button/like_button.html - Python: components/like_button/like_button.py $ pyblade tw:config ✔ TailwindCSS 4 installed successfully.
@quickstart
Three commands to a running app.
-
01
Install
Inside a virtual environment. The PyBlade CLI ships with the package — nothing else to add.
$ pip install pyblade -
02
Create a project
Pick a name, your web framework and a CSS framework. settings.py is wired up for you.
$ pyblade init -
03
Run it
Your app is live at http://127.0.0.1:8000, with hot reload on your templates.
$ pyblade dev
@feedback
Try it this week. Then tell us what broke.
PyBlade is shaped by the people using it. Twenty minutes with it and one honest post on the feedback board does more for it than a star ever could.
-
01
Install it
Into any environment running Python 3.11 or newer.
pip install pybladecopied -
02
Build something small with Django
Start a Django project with
Read the docspyblade init, port one page from a Django app you know, or write a Live component. Where it feels wrong is exactly what we want to hear about. -
03
Tell us how it went
What worked, what confused you, what's missing. Every post is read, and the ones with the most votes go on the roadmap.
@waitlist
Be the second
to know.
Cause I'll be the first :)
PyBlade is still experimental — the API can shift between releases, so it isn't ready to carry a production app yet. Leave your email and I'll write to you once, on the day that changes.