Reflex 7.11 Cursor/Cline Rules & Best Practices
Note: These rules are based on the latest available Reflex documentation and best practices. For version-specific details, always refer to the official Reflex docs.
Core Structure
- Always import Reflex as
rx
: Getting Startedimport reflex as rx
State Management
- Define state classes inheriting from
rx.State
. - All mutable variables must be defined as state vars with type hints.
- Event handlers must be methods within state classes.
- Only modify state vars through event handlers.
Example:
class State(rx.State):
count: int = 0 # Define vars with type hints
def increment(self):
self.count += 1 # Event handler
Component Rules
- Only use Reflex components for UI building.
- Use
rx.cond
andrx.foreach
for dynamic UI elements. - Components must reference state vars for dynamic content.
- Bind event triggers (like
on_click
) to state event handlers.
Frontend Guidelines
- Keep UI logic in component definitions.
- Complex logic belongs in the State class (backend).
- Use layout components like
rx.hstack
,rx.vstack
, etc., for structure.
App Configuration
- Create app instance with
rx.App()
. - Add pages using
app.add_page()
.
Best Practices
- Use Python type hints for all state vars.
- Keep event handlers focused and single-purpose.
- Use proper component composition for complex UIs.
- Leverage Reflex’s built-in state management.
Essential Reference Example
import reflex as rx
class AppState(rx.State):
value: str = ""
def update(self, new_val: str):
self.value = new_val
def index():
return rx.hstack(
rx.input(
value=AppState.value,
on_change=AppState.update
),
rx.text(AppState.value)
)
app = rx.App()
app.add_page(index)
Frontend Architecture Rules
Components
- Components compile to React components under the hood.
- Use Reflex components like
rx.hstack
,rx.avatar
, andrx.input
for UI. - Components can have props that affect appearance and functionality.
- Bind event triggers like
on_blur
to state event handlers.
Layout Components
Common layout components:
- AspectRatio
- Box
- Card
- Center
- Container
- Flex
- Fragment
- Grid
- Inset
- Section
- Separator
- Spacer
- Stack
Pages
- Pages must be defined as Python functions.
- Decorate page functions with
@rx.page()
to add as routes. - Pages can have their own substate defined in the same module.
- Use templates to maintain consistent layout across pages.
Backend Architecture Rules
State Management
See above; all state is managed via classes inheriting from rx.State
.
Database Integration
Reflex integrates with SQLAlchemy:
- Supports SQLite, Postgres, MySQL.
FastAPI Backend
Reflex compiles to a FastAPI backend:
- Runs on port 8000 by default.
- Connects to frontend via WebSocket.
- State manager maps client tokens to state.
Event Processing
Events contain:
- Client token
- Event handler name
- Arguments
Events are queued and processed one at a time; state updates are sent back to frontend.
Project Structure Example
example-app/
├─ assets/
├─ example_app/
│ ├─ components/
│ │ ├─ __init__.py
│ │ ├─ auth.py
│ │ ├─ footer.py
│ │ ├─ menu.py
│ │ ├─ navbar.py
│ ├─ pages/
│ │ ├─ __init__.py
│ │ ├─ index.py
│ ├─ __init__.py
│ ├─ example_app.py
│ ├─ models.py
│ ├─ state.py
├─ requirements.txt
├─ rxconfig.py
Authentication & Security
Reflex supports:
- Local Auth, Google Auth, Captcha, Magic Link Auth, Clerk Auth.
For RBAC (Role-Based Access Control), implement role checks in your State/event handler logic.
Security Tips:
- Never store sensitive data in client-accessible state.
- Use server-side validation for all critical actions.
- Integrate authentication providers securely.
Database Connections
Reflex uses SQLAlchemy under the hood; you can use standard SQLAlchemy patterns for models and queries.
For external backends (e.g., Supabase), use their Python SDKs within your State/event handler methods.
Testing Best Practices
- Write unit tests for all State methods (event handlers).
- Test component rendering using Reflex’s test utilities or snapshot testing.
- Validate that all routes/pages load without errors.
- Mock external dependencies (e.g., database calls) in tests.
Example: Minimal Working App Structure
rxconfig.py
import reflex as rx
config = rx.Config(
app_name="example_app",
theme=rx.theme(radius="full", accent_color="grass"),
)
example_app/example_app.py
import reflex as rx
from . import state, models
from .pages import index, login, profile
app = rx.App()
app.add_page(index)
app.add_page(login)
app.add_page(profile)
example_app/state.py
import reflex as rx
class AuthState(rx.State):
"""Base state for authentication."""
logged_in: bool = False
username: str = ""
example_app/models.py
import reflex as rx
class User(rx.Base):
"""The user model."""
username: str
email: str
role: str = "user"
example_app/template.py
from typing import Callable
import reflex as rx
from .components.navbar import navbar
from .components.menu import menu
def template(page: Callable[[], rx.Component]) -> rx.Component:
"""Base template for all pages."""
return rx.vstack(
navbar(),
rx.hstack(
menu(),
rx.container(page()),
),
width="100%",
)
example_app/components/navbar.py
import reflex as rx
from ..state import AuthState
class NavbarState(rx.State):
show_menu: bool = False
def toggle_menu(self):
self.show_menu = not self.show_menu
def navbar() -> rx.Component:
return rx.hstack(
rx.heading("Example App"),
rx.spacer(),
rx.text(AuthState.username),
rx.button(
"Menu",
on_click=NavbarState.toggle_menu,
),
width="100%",
padding="1em",
)
example_app/components/menu.py
import reflex as rx
from ..state import AuthState
def menu() -> rx.Component:
return rx.box(
rx.vstack(
rx.link("Home", href="/"),
rx.link("Profile", href="/profile"),
rx.button(
"Logout",
on_click=AuthState.logout,
) if AuthState.logged_in else rx.link(
"Login",
href="/login"
),
padding="1em",
),
width="200px",
)
example_app/pages/index.py
import reflex as rx
from ..template import template
from ..state import AuthState
@rx.page(route="/")
@template
def index() -> rx.Component:
return rx.vstack(
rx.heading("Welcome to Example App"),
rx.text(
f"Hello {AuthState.username}" if AuthState.logged_in else "Please login"
),
width="100%",
padding="2em",
)
example_app/pages/login.py
import reflex as rx
from ..state import AuthState
from ..template import template
class LoginState(AuthState):
"""Login page state."""
def handle_submit(self, form_data: dict):
"""Handle login form submission."""
self.username = form_data["username"]
self.logged_in = True
@rx.page(route="/login")
@template
def login() -> rx.Component:
return rx.vstack(
rx.heading("Login"),
rx.form(
rx.vstack(
rx.input(
placeholder="Username",
name="username",
),
rx.button("Login", type="submit"),
width="100%",
spacing="4",
),
on_submit=LoginState.handle_submit,
),
width="100%",
padding="2em",
)
example_app/pages/profile.py
import reflex as rx
from ..state import AuthState
from ..template import template
from ..models import User
class ProfileState(AuthState):
"""Profile page state."""
user: User = User(username="", email="", role="user")
def update_profile(self, form_data: dict):
"""Update user profile."""
self.user = User(**form_data)
@rx.page(route="/profile")
@template
def profile() -> rx.Component:
return rx.vstack(
rx.heading("Profile"),
rx.form(
rx.vstack(
rx.input(
placeholder="Username",
name="username",
value=ProfileState.user.username,
),
rx.input(
placeholder="Email",
name="email",
value=ProfileState.user.email,
),
rx.button("Update", type="submit"),
width="100%",
spacing="4",
),
on_submit=ProfileState.update_profile,
),
width="100%",
padding="2em",
)
References & Further Reading:
- Getting Started
- Reflex Architecture Blog
- How Reflex Works
- Layout Components
- Code Structure
- Tutorial: Data Dashboard
- Base Vars
Feel free to build upon this structure and refer back to these rules when generating or reviewing Reflex code!