Production-minded Python apps with a small, class-oriented API.
Dashboards · Internal tools · CRUD · Data workflows · No separate frontend
Quickstart · Showcase · User guide · API by task · Deployment
Edron is the batteries-included authoring layer for Hedron. You write pages, fragments, actions, forms, data views, and workflows with ordinary Python classes. Edron lowers them into one FastAPI-native application that renders accessible HTML on the server and progressively enhances requests with HTMX.
There is no generated frontend project, Node.js build, callback graph, whole-script rerun model, second router, or second state store. Built-in styling provides responsive layouts and coordinated light/dark modes without requiring application CSS.
Explore the interactive showcase → · View the Edron-only source
Package maturity: Stable · Version line documented:
1.0.xEvery command and example below targets the Edron 1.0 API. Supported Python versions are 3.10–3.14; applications should require the
>=1.0.0stable compatibility floor shown below.
Start in under a minute
Create a project with uv:
uvx --from "edron>=1.0.0" edron new my-app --template dashboard
cd my-app
uv sync
uv run edron run app:app --reload
Open http://127.0.0.1:8000. The scaffold is ordinary Python with a responsive application shell, built-in theme, page routes, and production-oriented configuration.
Adding Edron to an existing project is just as direct:
uv add "edron>=1.0.0"
# or: python -m pip install "edron>=1.0.0"
Your first page
Create app.py:
import edron as ed
app = ed.App(title="Sales", security="standard")
@app.page("/", title="Sales dashboard")
class Home(ed.Page):
def render(self) -> None:
self.heading("Sales dashboard")
self.metric("Orders", 128, delta="+12")
self.text("Useful HTML from a small, explicit Python application.")
Run it with either command:
edron run app:app --reload
# or: uvicorn app:app --reload
The app object is a normal ASGI application. Your existing server, reverse proxy, observability,
and deployment stack remain usable.
The programming model
Edron has four primary ideas:
| Idea | Responsibility |
|---|---|
App |
Own routes, resources, packages, diagnostics, and deployment facts |
Page |
Build one request-local component tree through concise methods |
@fragment |
Define an independently addressable, refreshable read surface |
@action |
Process an unsafe request and return a bounded outcome |
Page instances are request-local controllers, never session state. Durable data belongs in
databases and services; authenticated principals and request facts belong in explicit
dependencies; application resources belong on App.
Partial-page interaction
from datetime import datetime, timezone
import edron as ed
app = ed.App(title="Operations", security="standard")
@app.page("/", title="Operations")
class Operations(ed.Page):
def render(self) -> None:
self.status()
self.button("Refresh status", action=self.refresh_status)
@ed.fragment
def status(self) -> None:
stamp = datetime.now(timezone.utc).strftime("%H:%M:%S UTC")
self.text(f"All systems operational · {stamp}")
@ed.action
def refresh_status(self) -> ed.Outcome:
return ed.refresh(self.status)
The initial request renders a complete page. The button sends a declared action request and only
the status fragment is replaced. Edron preserves CSRF policy, target allowlists, escaping, and
ordinary HTTP fallbacks through the entire flow.
Layout with normal Python
@app.page("/customers", title="Customers")
class Customers(ed.Page):
def render(self) -> None:
left, right = self.columns(2)
left.heading("Customers", level=2)
left.text("Request-local containers compose like any other Python value.")
right.metric("Active", 412, delta="+18")
right.metric("At risk", 7, delta="-2")
The built-in layout recipes collapse cleanly for narrow screens. Theme tokens coordinate light and dark modes across forms, data, charts, maps, navigation, and status surfaces.
A focused application vocabulary
Common page methods include:
heading text markdown code
metric table card container
layout columns tabs expander
text_input number_input selectbox multiselect
slider checkbox date_input form
button download_button chart map
image audio video
The stable root API is deliberately small. Package internals, private native objects, and experimental adapters are outside the compatibility promise.
What you get
| Concern | Built-in capability |
|---|---|
| Application structure | Class-oriented pages, fragments, actions, navigation targets, inheritance, and feature packages |
| UI and layout | Responsive shells, cards, columns, tabs, forms, dialogs, status, media, and light/dark themes |
| Data applications | DataSource, DataWorkspace, explicit columns, bounded queries, typed edit intents, and CSV export |
| Charts and maps | Stable first-party chart/map lowering with accessible fallbacks and bounded payloads |
| Services | Typed dependencies, lazy app/request resources, scoped caches, health metadata, and secret references |
| Long-running work | JobFlow, pluggable backends, bounded results, polling, cancellation, and status events |
| Delivery | Static source checks, application explanations, capability diagnostics, deployment profiles, manifests, and conformance reports |
| Migration | Review-first Streamlit analysis, generated project structure, source maps, and explicit TODOs |
Edron includes Hedron, data, chart, map, Markdown, sanitization, and Uvicorn foundations. Optional extras install only the third-party libraries your application actually uses:
uv add "edron[pandas,plotly,sqlalchemy]>=1.0.0"
Available extras are pandas, polars, pyarrow, plotly, altair, matplotlib, and
sqlalchemy.
Data boundaries stay visible
Data editing is deny-by-default. Applications declare keys, columns, allowed query operations, writable fields, validation, authorization, concurrency policy, and audit behavior instead of shipping an unbounded object to the browser.
import edron as ed
source = ed.DataSource.in_memory(
[
{"id": "1", "name": "Northwind", "status": "open"},
{"id": "2", "name": "Contoso", "status": "closed"},
],
key_field="id",
columns=(
ed.Column("id", read_only=True, sortable=True),
ed.Column("name", sortable=True, filterable=True),
ed.Column("status", sortable=True, filterable=True),
),
sort_fields=("id", "name", "status"),
filter_fields=("name", "status"),
)
DataWorkspace adds bounded paging, filtering, sorting, search, selection, export, and typed edit
intents. The application still owns row authorization, database sessions, transactions,
persistence, and durable audit records.
Resources, caching, and jobs are explicit
Register lazy resources at the application boundary and expose secret names—not secret values—in diagnostic metadata:
import os
import edron as ed
app = ed.App(title="Orders", security="standard")
def open_database() -> object:
return make_database(os.environ["DATABASE_URL"])
database = app.resource(
"database",
open_database,
kind="sqlalchemy",
secret_refs={"dsn": "DATABASE_URL"},
)
@app.page("/", title="Orders")
class Orders(ed.Page):
db = database
def render(self) -> None:
self.metric("Open orders", count_open_orders(self.db))
@ed.cache_data(ttl=60, scope="tenant", vary_on=("tenant_id",))
def load_summary(tenant_id: str) -> dict[str, int]:
return query_summary(tenant_id)
Use JobFlow when work must outlive a request. Configure shared cache and job backends before
running multiple workers; deployment diagnostics report process-local backends explicitly.
Inspect before you ship
# Parse and check source without executing it
edron check app.py
# Inspect a trusted application's pages, fragments, and actions
edron explain app:app
# Diagnose capabilities and topology-specific deployment facts
edron doctor app:app --profile container
edron deploy-check --profile reverse-proxy --format json
edron check --format sarif emits CI-friendly findings. app.manifest() and
app.conformance() return deterministic, bounded reports for promotion and release gates.
Moving from Streamlit
Edron offers familiar page, input, metric, data, and chart vocabulary without emulating Streamlit's global rerun runtime or mutable session dictionary.
edron migrate streamlit streamlit_app.py --out migrated-app
Migration is static and review-first: source is not executed or overwritten. The output includes a fresh project, deterministic findings, a source map, and explicit TODOs for behavior that needs human judgment.
One runtime, one authority
Edron page / fragment / action / resource
|
v
Hedron page / view / action / dependency
|
v
FastAPI + server-rendered HTML + HTMX
Edron is an authoring facade, not a parallel web framework. It preserves Hedron's renderer, request lifecycle, security policy, assets, and deployment model while presenting a smaller application-facing API.
Choose Hedron directly when you prefer explicit component trees, FastAPI-native function routes, custom host integration, or framework extension points.
Production checklist
Edron provides secure defaults and inspectable boundaries. Before deployment:
- Set a strong application-specific session secret and deliberate security profile.
- Authenticate and authorize in trusted dependencies and action boundaries.
- Use shared state, cache, and job backends for multi-worker deployments.
- Keep transactions, retries, idempotency, tenancy, and audit persistence in application services.
- Treat user, database, upload, and generated content as untrusted input.
- Validate proxy trust, root paths, HTTPS, cookies, artifacts, and health behavior against the actual deployment topology.
- Prefer polling for durable job status unless SSE/WebSocket buffering, timeouts, and backpressure have been verified.
Edron is not an ORM, identity provider, database, durable job broker, hosted platform, or browser SPA runtime.
See the complete application
The Edron Showcase is a responsive, light/dark operations workspace with pages, layouts, fragments, actions, metrics, tables, charts, tabs, and outcomes. The documentation links the same runnable source represented by the simulation. Every application surface is authored through public Edron APIs, with no custom application CSS or Hedron escape hatches.
Learn more
- Five-minute quickstart
- Edron user guide
- API by task
- Edron API
- Example catalog
- Cookbook
- Deployment
- Source
- Changelog
- Issues
License
Edron is available under the MIT License.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file edron-1.0.2.tar.gz.
File metadata
- Download URL: edron-1.0.2.tar.gz
- Upload date:
- Size: 72.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
uv/0.12.1 {"installer":{"name":"uv","version":"0.12.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d609c76c580933e450a3099629d7318ef4163cb66856edf63fe7c8c6cee2258e
|
|
| MD5 |
d522921debbdde621f390a5464e069f3
|
|
| BLAKE2b-256 |
a6acd10aba9159ac29bd488c50947d5952c5563916b46e51e0c7a5c84794f8fe
|
File details
Details for the file edron-1.0.2-py3-none-any.whl.
File metadata
- Download URL: edron-1.0.2-py3-none-any.whl
- Upload date:
- Size: 85.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
uv/0.12.1 {"installer":{"name":"uv","version":"0.12.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c54553bfb45c914a64d014c803a67aecbc5b705919a39aba9e0f11f5588cf409
|
|
| MD5 |
276a9760ba91141a038fe54ff5651a8a
|
|
| BLAKE2b-256 |
be37e637888ca8ccbf782d6b068fb32f9ad532e181828e47e8bfafd1f041b253
|