Skip to content

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

  • @extends Inherit a parent layout.
  • @block Fill a named region of the layout.
  • @include Render another template in place.
  • @section / @yield Define content once, output it elsewhere.
  • @push / @stack Collect scripts or styles from anywhere into one place.
  • @component Drop in a reusable piece of UI.
  • @props Declare what a component takes, with defaults.
  • @slot Hand a component a named piece of markup.
33 of 33 directives · first 8 shown rendered by Python at 01:13:52.487 · filtered in 0.15 ms

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.

  1. 01

    Install

    Inside a virtual environment. The PyBlade CLI ships with the package — nothing else to add.

    $ pip install pyblade
  2. 02

    Create a project

    Pick a name, your web framework and a CSS framework. settings.py is wired up for you.

    $ pyblade init
  3. 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.

  1. 01

    Install it

    Into any environment running Python 3.11 or newer.

    pip install pyblade copied
  2. 02

    Build something small with Django

    Start a Django project with pyblade 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.

    Read the docs
  3. 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.

One email. No newsletter, no digest, no drip campaign.