DEV Community

Cover image for Build Full-Stack Web Apps in Pure Python with Reflex
Developer Service
Developer Service

Posted on • Originally published at developer-service.blog

Build Full-Stack Web Apps in Pure Python with Reflex

Introduction

For years, web developers have been juggling the infamous frontend/backend divide. You write your backend in Python, maybe with Django or FastAPI, and then switch gears entirely to build the frontend with JavaScript frameworks like React, Vue, or Next.js. It’s a constant context switch between two ecosystems, two dependency managers, and two mental models. Even simple features like syncing state between backend and UI can become an exercise in boilerplate and glue code.

Wouldn’t it be simpler if you could just build everything, frontend and backend alike, in Python?

That’s the promise of Reflex, an open-source framework designed to let you create full-stack web applications in pure Python. With Reflex, you write your components, state management, and event handlers all in the same language you already use for APIs, data processing, and AI integrations. Under the hood, it compiles your Python UI code into a modern React/Next.js frontend and runs a Python backend that handles state and communication seamlessly via WebSockets.

In this article, we’ll take a deep dive into what Reflex is, how it works, and why it’s generating buzz in the Python community. You’ll learn about its architecture, core features, and how to get started with a simple app (source code at the end of the article).


What is Reflex?

Reflex is an open-source framework for building interactive web applications entirely in Python. It aims to eliminate the traditional separation between frontend and backend development by allowing you to define your UI, state, and logic in one unified Python codebase.

Reflex automatically handles the translation of your Python code into a modern React/Next.js frontend, while managing communication and state synchronization with a Python backend under the hood.

At its core, Reflex is built around three simple but powerful goals:

  • Pure Python: Build full-stack web apps using only Python, no need to learn or write JavaScript, TypeScript, or React.
  • Easy to learn: Start building interactive applications quickly with an intuitive, Pythonic API.
  • Fully flexible: Scale from simple prototypes to production-grade applications with ease.

Originally launched under the name Pynecone, the project rebranded to Reflex to better reflect its mission of providing a more “reflexive” development experience, where changes in code and state seamlessly reflect in the user interface.

Despite being a relatively new entrant in the Python ecosystem, Reflex has gained significant traction, attracting a large and enthusiastic community. On GitHub, the project has amassed over 27,000 stars, reflecting the growing interest among Python developers looking for a modern, unified approach to web development.

Reflex isn’t just another Python web framework, it’s an attempt to redefine what building web apps in Python can look like: no JavaScript, no separate front-end stack, and no friction.


Architecture & How It Works

At a high level, Reflex unifies your frontend and backend into a single Python codebase. Unlike traditional web development where the frontend (React, Vue, etc.) and backend (Django, Flask, FastAPI) are separate systems communicating through REST or GraphQL APIs, Reflex merges them into one coherent framework.

Here’s how the architecture breaks down:

Reflex Architecture

Frontend: Python Components → React/Next.js

Reflex lets you define your user interface using Python components, which are then compiled into a modern React/Next.js frontend under the hood. You never have to touch JavaScript, Reflex automatically generates the necessary HTML, CSS, and JS from your Python code.

Backend: FastAPI-Powered State Management

Behind the scenes, Reflex runs a Python backend (based on FastAPI) that handles state management, event handling, and real-time communication between the UI and server via WebSockets.

Every interaction on the frontend, a button click, text input, or dropdown change, triggers an event that is sent back to the Python backend. The backend updates the application’s state, and Reflex automatically syncs the updated state back to the frontend UI.

State & Event Handling

Central to Reflex’s design is the concept of a State class.

You define reactive variables and methods (event handlers) inside a subclass of rx.State. When a state variable changes, Reflex automatically updates all UI components that depend on it, no manual DOM manipulation or client-side JavaScript required.

Implications

This unified approach means:

  • You’re writing UI, logic, and state all in Python, no context switching to JavaScript.
  • You get real-time interactivity out of the box via WebSockets.
  • Your app is fully reactive, much like React or Vue, but powered by Python instead of JavaScript.

However, this also introduces trade-offs. Because the frontend depends on a live connection to the Python backend, performance and scalability can vary for very large real-time workloads.

How Reflex Differs from Django, Streamlit, and Dash

While Django focuses on traditional server-rendered web pages and APIs, and frameworks like Streamlit or Dash cater primarily to data apps and dashboards, Reflex occupies a middle ground:

  • Compared to Django + React: Reflex removes the need to manage two separate codebases and build pipelines.
  • Compared to Streamlit/Dash: Reflex gives you more flexibility, you can build full-featured web applications, not just dashboards, with complete control over routing, components, and state.

Reflex delivers a modern, Pythonic alternative to full-stack web development, one that feels as intuitive as writing a Flask app, but produces dynamic, React-grade user experiences.


While you explore Reflex and build your first Python-powered web app, don’t forget to grab the “Master Python One-Liners” cheat sheet from my site.

It’s absolutely free and packed with clean, efficient Python snippets that’ll boost your productivity across everything you build, from Reflex apps to Django backends.

Grab it here: Free Cheat Sheet


Key Features & Benefits

Below are the core features that make Reflex a compelling framework for modern developers.

Pure Python Full-Stack

Reflex lets you write both your frontend and backend entirely in Python. You define components, routes, state, and event handlers all in the same language and project structure. Under the hood, Reflex compiles your Python UI into a modern React/Next.js app, but you never have to deal with the JavaScript ecosystem directly.

This makes it ideal for Python developers who want to build dynamic, interactive web apps without learning a whole new frontend stack.

Built-in UI Components

Reflex ships with a large library of ready-to-use UI components — everything from buttons, grids, and forms to modals and navigation bars.

Each component follows a Pythonic syntax and can be combined to create rich, responsive layouts.

Beyond the built-ins, Reflex also supports wrapping React components, meaning you can import and use virtually any third-party React library without writing JavaScript yourself.

Integrations

Because Reflex apps run entirely in Python, they have direct access to the Python ecosystem, including APIs, databases, file formats, and data libraries like pandas, sqlalchemy, or requests.

You can build dashboards that query databases, call machine learning models, or visualize analytics, all in one codebase.

Deployment & Hosting Support

Deploying a Reflex app is straightforward. With a single command, you can build and deploy your app using Reflex’s built-in hosting or export it to deploy anywhere (e.g., Vercel, AWS, or your own server).

This streamlined deployment process lowers the barrier from prototype to production — especially useful for small teams and indie developers.

Themes & UI Customization

Reflex includes a theming system that lets you easily define color palettes, typography, spacing, and global styles.

Apps built with Reflex are responsive by default, adapting automatically to different screen sizes and devices, an essential feature for modern web experiences.

Rapid Prototyping & AI Builder Support

Reflex is especially useful for rapid prototyping, you can go from idea to functional web interface in minutes. For developers working in AI or data-driven projects, this means you can build interfaces for models, visualization tools, or automation dashboards directly from your Python environment, no need for a frontend developer.


Getting Started - A Quick Walk-through

All you need is Python ≥ 3.8. Install Reflex with pip:

pip install reflex
Enter fullscreen mode Exit fullscreen mode

Then initialize a new project:

reflex init --name my_todo_app
Enter fullscreen mode Exit fullscreen mode

Choosing '1' for the option of a blank Reflex app:

─────────────────────────────────────────────────────────────────────── Initializing my_todo_app ───────────────────────────────────────────────────────────────────────
[10:53:51] Initializing the web directory.                                                                                                                console.py:231

Get started with a template:
(0) Try our free AI builder.
(1) A blank Reflex app.
(2) Premade templates built by the Reflex team.
Which template would you like to use? (0): 1
[10:54:05] Initializing the app directory.                                                                                                                console.py:231
Success: Initialized my_todo_app using the blank template.
Enter fullscreen mode Exit fullscreen mode

This command creates a minimal Reflex project scaffold, clean, readable, and ready to run.

Structure of an App

After initialization, you’ll see something like this:

├── .web/                # Auto-generated frontend (React)
├── assets/              # Static files
├── my_todo_app/         # Your main Python package
│   └── my_todo_app.py   # Entry point: state + UI
├── rxconfig.py          # Reflex configuration
└── requirements.txt
Enter fullscreen mode Exit fullscreen mode

Everything happens inside my_todo_app.py, that’s where your state (data) and UI (frontend) live together.

A Simple To-Do App

Every Reflex app has two key parts:

  • State class – defines your app’s data and logic.
  • UI function(s) – define how the interface should look.

Here’s a complete working example that you can copy into my_todo_app.py:

import reflex as rx

# --- Reactive State ---
class State(rx.State):
    todos: list[str] = []
    new_todo: str = ""

    def add_todo(self):
        if self.new_todo.strip():
            self.todos.append(self.new_todo.strip())
            self.new_todo = ""

    def remove_todo(self, index: int):
        self.todos.pop(index)


# --- UI Definition ---
def index() -> rx.Component:
    return rx.center(
        rx.vstack(
            rx.heading("📝 To-Do List", size="6"),
            rx.hstack(
                rx.input(
                    placeholder="Add a task...",
                    value=State.new_todo,
                    on_change=State.set_new_todo,
                    width="70%",
                ),
                rx.button("Add", on_click=State.add_todo),
            ),
            rx.divider(),
            rx.foreach(
                State.todos,
                lambda todo, i: rx.hstack(
                    rx.text(todo, flex="1"),
                    rx.button("", color_scheme="red", on_click=lambda: State.remove_todo(i)),
                ),
            ),
            width="400px",
            spacing="4",
        ),
        height="100vh",
    )


# --- App Setup ---
app = rx.App()
app.add_page(index)
Enter fullscreen mode Exit fullscreen mode

This app lets you type a task, click “Add,” and remove items with the ❌ button, all powered by Python state and React’s reactivity under the hood.

Running Locally

To start the app, simply run:

reflex run
Enter fullscreen mode Exit fullscreen mode

Reflex will automatically spin up both backend and frontend servers.

───────────────────────────────────────────────────────────────────────── Starting Reflex App ──────────────────────────────────────────────────────────────────────────
[10:59:32] Compiling: ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━   0%  0/21 
[10:59:32] Compiling: ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100% 21/21 0:00:00
───────────────────────────────────────────────────────────────────────────── App Running ──────────────────────────────────────────────────────────────────────────────
App running at: http://localhost:3000/
Backend running at: http://0.0.0.0:8000
Enter fullscreen mode Exit fullscreen mode

Then open http://localhost:3000 in your browser, you’ll see your To-Do List live and interactive.

Let's see the example in action:

Full Source Code at: https://github.com/nunombispo/Reflex-Article


Conclusion

Reflex represents a refreshing shift in how Python developers can approach full-stack web development. Instead of juggling separate ecosystems for frontend and backend, Reflex allows you to build fully interactive web applications using only Python, seamlessly integrating UI, logic, and state in a single, unified framework.

For developers coming from Django, FastAPI, or AI tooling, this approach means less boilerplate, faster iteration, and the ability to leverage your existing Python expertise without having to dive into the complexities of JavaScript frameworks.

If you’re curious, the best way to understand Reflex’s potential is to experiment, start with the classic counter app or prototype a small tool from one of your existing Python projects. You’ll quickly see how natural it feels to design interfaces, manage state, and deploy apps, all from a single language.

As part of my broader focus on Python, Django, and AI development, Reflex fits naturally into the growing ecosystem of tools that let you build smarter, faster, and more maintainable applications.


Follow me on Twitter: https://twitter.com/DevAsService

Follow me on Instagram: https://www.instagram.com/devasservice/

Follow me on TikTok: https://www.tiktok.com/@devasservice

Follow me on YouTube: https://www.youtube.com/@DevAsService

Top comments (0)