Lively UI

Lively Component System is a real-time UI engine built directly into the framework. It enables dynamic updates over WebSockets without full page reloads — while keeping your architecture clean and predictable.

No React. No Vue. No JavaScript framework at all. Just Python-driven components communicating efficiently using msgpack — making Duck a true full-stack Python alternative to Django and Flask.

✅ Real-time updates — Components update instantly over WebSockets.
✅ Virtual DOM diffing — Only what changes gets patched.
✅ Seamless navigation — Navigate URLs without full reloads.
✅ Unified stack — Backend and dynamic UI in one system.

Here's how the Counter App below is built

components/counterapp.py
from duck.html.components.container import FlexContainer
from duck.html.components.button import Button
from duck.html.components.label import Label


class CounterApp(FlexContainer):
    def on_create(self):
        super().on_create()
        self.style["gap"] = "5px"
        self.style["flex-direction"] = "column"
        self.style["align-items"] = "center"
        self.style["padding"] = "20px"

        # Initialize counter
        self.counter = 0

        def on_btn_click(btn, *_):
            if btn == self.increment_btn:
                self.counter += 1
            else:
                if self.counter > 0:
                    self.counter -= 1

            # Real-time update over WebSocket — no JavaScript
            self.label.text = self.counter

        # Live counter label
        self.label = Label(text=self.counter)
        self.label.style["font-size"] = "1.5rem"
        self.add_child(self.label)

        # Increment button
        self.increment_btn = Button(text="Increment")
        self.increment_btn.bind(
            "click",
            on_btn_click,
            update_targets=[self],
            update_self=False,
        )

        # Decrement button
        self.decrement_btn = Button(text="Decrement")
        self.decrement_btn.bind(
            "click",
            on_btn_click,
            update_targets=[self],
            update_self=False,
        )

        self.add_child(
            FlexContainer(
                children=[self.increment_btn, self.decrement_btn],
                flex_direction="row",
                style={"gap": "5px"},
            )
        )

Try It Yourself

▶ Open another Counter App version in full page

Get Started in Seconds

Install Duck and scaffold a full project with a single command. No boilerplate hunting, no config files to set up manually.

terminal
pip install duckframework
duck makeproject myproject
cd myproject
duck runserver # Starts server on http://localhost:8000

Read the full documentation

Sponsors

Do you want your logo to appear here?