Skip to main content

Revolutionary Full-Stack Python Web Framework - Write React-like components in pure Python

Project description

PyFrame Logo

PyFrame - Full-Stack Python Web Framework

A modern, reactive web framework that allows developers to write both frontend and backend entirely in Python, with automatic compilation to efficient JavaScript for the browser.

Python 3.8+ License: MIT

๐Ÿš€ What Makes PyFrame Special

PyFrame revolutionizes web development by eliminating the traditional frontend/backend divide. Write your entire application in Python - from reactive UI components to database models - and PyFrame handles the rest.

from pyframe import PyFrameApp, Component, Model, Field, FieldType

# Define your data model
class User(Model):
    name: str = Field(FieldType.STRING, max_length=100)
    email: str = Field(FieldType.EMAIL, unique=True)
    # โ†ณ Automatically generates database tables, migrations, and REST APIs!

# Create reactive UI components in Python
class UserProfile(Component):
    def render(self):
        user = self.props.get("user")
        return f"""
        <div class="profile">
            <h1>Welcome, {user.name}!</h1>
            <p>Email: {user.email}</p>
        </div>
        """
        # โ†ณ Automatically compiles to JavaScript for the browser!

# Set up your app
app = PyFrameApp()

@app.component_route("/profile/<user_id>")
class ProfilePage(UserProfile):
    pass

app.run()  # ๐ŸŽ‰ Full-stack app running!

โœจ Key Features

๐Ÿ Unified Python Development

  • Write frontend UI components entirely in Python
  • Automatic compilation to optimized JavaScript
  • Reactive state management with Python syntax
  • No JavaScript, TypeScript, or build tools required

๐Ÿ”„ Real-Time by Default

  • Built-in WebSocket and Server-Sent Events support
  • Automatic data synchronization between server and clients
  • Optimistic UI updates with conflict resolution
  • Live component updates without page refreshes

๐Ÿ“Š Zero-Boilerplate Data Layer

  • Define models with Python classes and type hints
  • Automatic database schema generation and migrations
  • Auto-generated REST and GraphQL APIs
  • Built-in validation and form generation

๐Ÿ“ฑ Context-Aware Adaptivity

  • Automatic device type and network speed detection
  • Adaptive content delivery and optimization
  • User preference detection (dark mode, reduced motion)
  • Progressive enhancement for accessibility

๐Ÿ”Œ Plugin-Based Architecture

  • Lightweight core (~10-20KB) with optional plugins
  • Built-in plugins for auth, caching, analytics
  • Easy custom plugin development
  • Hook system for extending functionality

โšก Modern Development Experience

  • Hot module replacement with file watching
  • Zero-config development server
  • Detailed error reporting and debugging
  • AI-assisted code suggestions (optional)

๐Ÿ—๏ธ Architecture Overview

PyFrame uses a layered architecture where each component can be used independently:

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  ๐ŸŽจ Frontend (Python โ†’ JavaScript)                         โ”‚
โ”‚  โ€ข Reactive components written in Python                   โ”‚
โ”‚  โ€ข Automatic compilation to efficient JavaScript           โ”‚
โ”‚  โ€ข Client-side hydration and state management              โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  โš™๏ธ  Core Runtime                                          โ”‚
โ”‚  โ€ข Component lifecycle management                          โ”‚
โ”‚  โ€ข Routing and navigation                                  โ”‚
โ”‚  โ€ข Server-side rendering (SSR)                            โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  ๐Ÿ—„๏ธ  Data Layer                                           โ”‚
โ”‚  โ€ข Model definitions with automatic migrations             โ”‚
โ”‚  โ€ข Auto-generated REST/GraphQL APIs                       โ”‚
โ”‚  โ€ข Built-in validation and relationships                   โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  ๐Ÿ”Œ Plugin System                                          โ”‚
โ”‚  โ€ข Authentication and authorization                        โ”‚
โ”‚  โ€ข Caching and performance optimization                    โ”‚
โ”‚  โ€ข Analytics and monitoring                               โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  ๐ŸŒ Server & Deployment                                    โ”‚
โ”‚  โ€ข Context-aware adaptive rendering                        โ”‚
โ”‚  โ€ข Multiple deployment targets (serverless, edge, VPS)     โ”‚
โ”‚  โ€ข Development server with hot reload                      โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

๐Ÿš€ Quick Start

Installation

pip install pyframe-web

Using the CLI (Recommended)

PyFrame includes a command-line tool to help you get started quickly:

# Create a new project
pyframe-web create my-awesome-app
cd my-awesome-app

# Install dependencies
pip install -r requirements.txt

# Run the development server
python main.py
# or
pyframe-web run

Your app will be available at http://localhost:3000 with hot reload enabled!

Create Your First App Manually

# app.py
from pyframe import PyFrameApp, Component, StatefulComponent

class Counter(StatefulComponent):
    def __init__(self, props=None, children=None):
        super().__init__(props, children)
        self.set_state("count", 0)
    
    def increment(self):
        count = self.get_state("count", 0)
        self.set_state("count", count + 1)
    
    def render(self):
        count = self.get_state("count", 0)
        return f"""
        <div>
            <h1>Count: {count}</h1>
            <button onclick="this.component.increment()">
                Click me!
            </button>
        </div>
        """

app = PyFrameApp()

@app.component_route("/")
class HomePage(Counter):
    pass

if __name__ == "__main__":
    app.run()

Run Your App

python app.py

Visit http://localhost:3000 to see your reactive counter in action! ๐ŸŽ‰

๐Ÿ“– Learn by Example

Reactive Components

class TodoList(StatefulComponent):
    def __init__(self, props=None, children=None):
        super().__init__(props, children)
        self.set_state("todos", [])
        self.set_state("input_value", "")
    
    def add_todo(self):
        input_value = self.get_state("input_value", "")
        if input_value.strip():
            todos = self.get_state("todos", [])
            todos.append({"id": len(todos), "text": input_value, "done": False})
            self.set_state("todos", todos)
            self.set_state("input_value", "")
    
    def toggle_todo(self, todo_id):
        todos = self.get_state("todos", [])
        for todo in todos:
            if todo["id"] == todo_id:
                todo["done"] = not todo["done"]
        self.set_state("todos", todos)
    
    def render(self):
        todos = self.get_state("todos", [])
        input_value = self.get_state("input_value", "")
        
        todo_items = ""
        for todo in todos:
            checked = "checked" if todo["done"] else ""
            todo_items += f"""
            <li>
                <input type="checkbox" {checked} 
                       onchange="this.component.toggle_todo({todo['id']})">
                <span class="{'done' if todo['done'] else ''}">{todo['text']}</span>
            </li>
            """
        
        return f"""
        <div class="todo-app">
            <h1>Todo List</h1>
            <div class="add-todo">
                <input type="text" value="{input_value}" 
                       placeholder="Add a todo..."
                       onchange="this.component.set_state('input_value', this.value)">
                <button onclick="this.component.add_todo()">Add</button>
            </div>
            <ul class="todo-list">{todo_items}</ul>
        </div>
        """

Data Models with Auto-Generated APIs

from pyframe.data.models import Model, Field, FieldType
from datetime import datetime

class User(Model):
    username: str = Field(FieldType.STRING, unique=True, max_length=50)
    email: str = Field(FieldType.EMAIL, unique=True)
    first_name: str = Field(FieldType.STRING, max_length=50, required=False)
    last_name: str = Field(FieldType.STRING, max_length=50, required=False)
    is_active: bool = Field(FieldType.BOOLEAN, default=True)
    created_at: datetime = Field(FieldType.DATETIME, auto_now_add=True)

class Post(Model):
    title: str = Field(FieldType.STRING, max_length=200)
    content: str = Field(FieldType.TEXT)
    author_id: str = Field(FieldType.UUID, foreign_key="User")
    published: bool = Field(FieldType.BOOLEAN, default=False)
    tags: list = Field(FieldType.JSON, default=list)

# Automatically generates:
# GET /api/users - List users
# POST /api/users - Create user  
# GET /api/users/:id - Get user
# PUT /api/users/:id - Update user
# DELETE /api/users/:id - Delete user
# (Same for posts)

# Use in Python:
user = User.create(username="john", email="john@example.com")
post = Post.create(title="Hello World", content="...", author_id=user.id)

Real-Time Live Updates

class ChatRoom(StatefulComponent):
    def __init__(self, props=None, children=None):
        super().__init__(props, children)
        self.set_state("messages", [])
        self.set_state("input_value", "")
        
        # Subscribe to real-time updates
        room_id = props.get("room_id", "general")
        live_sync_manager.subscribe_to_channel(f"chat:{room_id}")
    
    def send_message(self):
        input_value = self.get_state("input_value", "")
        if input_value.strip():
            message = ChatMessage.create(
                content=input_value,
                room_id=self.props.get("room_id"),
                user_id=self.props.get("user_id")
            )
            # โ†ณ Automatically broadcasts to all connected clients!
            self.set_state("input_value", "")
    
    def render(self):
        messages = self.get_state("messages", [])
        input_value = self.get_state("input_value", "")
        
        message_list = ""
        for msg in messages:
            message_list += f"""
            <div class="message">
                <strong>{msg['username']}:</strong> {msg['content']}
            </div>
            """
        
        return f"""
        <div class="chat-room">
            <div class="messages">{message_list}</div>
            <div class="input-area">
                <input type="text" value="{input_value}"
                       onchange="this.component.set_state('input_value', this.value)"
                       onkeypress="if(event.key==='Enter') this.component.send_message()">
                <button onclick="this.component.send_message()">Send</button>
            </div>
        </div>
        """

Plugins and Authentication

from pyframe.plugins.auth_plugin import AuthPlugin, require_auth

# Configure authentication
app.register_plugin(AuthPlugin({
    "jwt_secret": "your-secret-key",
    "password_min_length": 8
}))

# Protected routes
@app.component_route("/dashboard")
@require_auth
class Dashboard(Component):
    def render(self):
        user = self.props.get("user")
        return f"""
        <div class="dashboard">
            <h1>Welcome, {user.username}!</h1>
            <p>This is your private dashboard.</p>
        </div>
        """

# Login component
class LoginForm(StatefulComponent):
    def __init__(self, props=None, children=None):
        super().__init__(props, children)
        self.set_state("username", "")
        self.set_state("password", "")
        self.set_state("loading", False)
    
    async def handle_login(self):
        self.set_state("loading", True)
        
        username = self.get_state("username", "")
        password = self.get_state("password", "")
        
        # Make API call to login endpoint
        response = await fetch("/auth/login", {
            "method": "POST",
            "headers": {"Content-Type": "application/json"},
            "body": json.dumps({"username": username, "password": password})
        })
        
        if response.ok:
            # Redirect to dashboard
            window.location.href = "/dashboard"
        else:
            self.set_state("loading", False)
            # Show error message
    
    def render(self):
        username = self.get_state("username", "")
        password = self.get_state("password", "")
        loading = self.get_state("loading", False)
        
        return f"""
        <form class="login-form" onsubmit="this.component.handle_login(); return false;">
            <h2>Login</h2>
            <input type="text" placeholder="Username" value="{username}"
                   onchange="this.component.set_state('username', this.value)">
            <input type="password" placeholder="Password" value="{password}"
                   onchange="this.component.set_state('password', this.value)">
            <button type="submit" {'disabled' if loading else ''}>
                {'Logging in...' if loading else 'Login'}
            </button>
        </form>
        """

๐ŸŒŸ Live Demo

Explore a complete blog application built with PyFrame:

git clone https://github.com/pyframe/pyframe.git
cd pyframe/examples/blog_app
pip install -r requirements.txt
python main.py

Visit http://localhost:3000 to see:

  • Reactive Python components
  • Real-time comments
  • Auto-generated APIs
  • Adaptive rendering
  • Authentication system
  • Hot reload in action

๐Ÿ“š Documentation

Core Concepts

Advanced Topics

API Reference

๐Ÿ”ง Development

Requirements

  • Python 3.8+
  • Modern web browser with JavaScript enabled

Dependencies

  • asyncio - Asynchronous programming
  • websockets - Real-time communication
  • watchdog - File system monitoring
  • PyJWT - JSON Web Tokens

Development Setup

# Clone the repository
git clone https://github.com/pyframe/pyframe.git
cd pyframe

# Install dependencies
pip install -r requirements.txt

# Run tests
python -m pytest

# Run the example app
cd examples/blog_app
python main.py

๐Ÿšข Deployment

PyFrame applications can be deployed anywhere Python runs:

Traditional Servers

from pyframe.deployment.wsgi import create_wsgi_app

# WSGI for Apache, Gunicorn, uWSGI
application = create_wsgi_app(app)

ASGI Servers

from pyframe.deployment.asgi import create_asgi_app

# ASGI for Uvicorn, Daphne, Hypercorn
application = create_asgi_app(app)

Serverless Functions

# AWS Lambda, Vercel, Netlify Functions
def lambda_handler(event, context):
    return app.handle_serverless_request(event, context)

Edge Computing

# Cloudflare Workers, Deno Deploy
app.configure_for_edge_deployment()

๐Ÿค Contributing

We welcome contributions! Please see our Contributing Guide for details.

Development Philosophy

  • Python-First: Everything should be writable in Python
  • Zero Config: Sensible defaults with optional customization
  • Performance: Fast development, fast runtime
  • Accessibility: Progressive enhancement and WCAG compliance
  • Developer Experience: Great error messages and debugging tools

๐Ÿ“„ License

MIT License - see the LICENSE file for details.

๐Ÿ™ Acknowledgments

PyFrame is inspired by:

  • React - Component-based architecture
  • Django - Batteries-included philosophy
  • FastAPI - Modern Python web framework design
  • Next.js - Full-stack development experience
  • Phoenix LiveView - Real-time server-rendered UI

๐Ÿ’ฌ Community


Ready to build the future of web development with Python? ๐Ÿโœจ

pip install pyframe-web

Get Started | Examples | API Docs

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pyframe_web-0.1.0.tar.gz (122.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pyframe_web-0.1.0-py3-none-any.whl (98.5 kB view details)

Uploaded Python 3

File details

Details for the file pyframe_web-0.1.0.tar.gz.

File metadata

  • Download URL: pyframe_web-0.1.0.tar.gz
  • Upload date:
  • Size: 122.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.10.11

File hashes

Hashes for pyframe_web-0.1.0.tar.gz
Algorithm Hash digest
SHA256 55e884f1fd49b7c493938d17b12ef10fe7dd2e43647e9f0e2568ed124afc7f21
MD5 6b02da287d86c7c4bd398a1d41c1c027
BLAKE2b-256 14bc1683bbd4a445f3ee748df88a96c81b459fb84a313ed7c2e93706e7249fe2

See more details on using hashes here.

File details

Details for the file pyframe_web-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: pyframe_web-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 98.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.10.11

File hashes

Hashes for pyframe_web-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 fda2dc83809479ddd93f0bd264aa8513c4ae27205d6831563e1e36f52dcea993
MD5 c417f8bd2d5f8c949ff569ffe01c6872
BLAKE2b-256 d2a6a7e8282a589ab6707f8dd3c3f6b91be940af4563cce62132187816b717fb

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page