Flapi - FastAPI Low-Code Framework
Flapi is a low-code framework for building web applications that serve both human-facing webpages and JSON APIs. It supports Flask and FastAPI backends.
Installation
pip install ionbus_flapi
Quick Start
1. Create a Config File
Create config/windows.yaml (or linux.yaml):
app_type: fastapi # or "flask"
host: 0.0.0.0
port: 5080
proxy_prefix: MyApp
title: My Application
shutdown_code: "secret123" # Optional: enables /shutdown endpoint
2. Create an Endpoint Module
Create MyEndpoints/endpoints.py:
from __future__ import annotations
from ionbus_flapi import FlapiPage, HtmlComponent, register_endpoint
MODULE_NAME = "MyEndpoints"
HTML_DESCRIPTION = "<li>My custom endpoints.</li>"
def initialize() -> None:
"""Initialize endpoints in this module."""
register_endpoint(
MODULE_NAME,
"HelloWorld",
hello_world_endpoint,
ep_description="A simple hello world example.",
)
def hello_world_endpoint() -> FlapiPage:
"""Display a hello world page."""
return FlapiPage(
title="Hello World",
objects=[
HtmlComponent(html="<h2>Hello, World!</h2>"),
"<p>This is my first Flapi endpoint.</p>", # strings work too
],
)
3. Create the Main App
Create app.py:
from __future__ import annotations
import sys
from ionbus_flapi import initialize, register_endpoint_group, serve
if __name__ == "__main__":
if len(sys.argv) < 2:
raise RuntimeError("Must provide .yaml config file")
initialize(sys.argv[1])
import MyEndpoints.endpoints
register_endpoint_group(
MyEndpoints.endpoints.initialize,
MyEndpoints.endpoints.MODULE_NAME,
MyEndpoints.endpoints.HTML_DESCRIPTION,
)
serve()
4. Run
python app.py config/windows.yaml
Visit http://localhost:5080/MyApp/ to see your endpoints.
Core Concepts
FlapiPage
The main container for building HTML pages:
from ionbus_flapi import FlapiPage
page = FlapiPage(
title="My Page",
objects=[...], # List of components or strings
theme_toggle=True, # Show theme toggle button
refresh_in_seconds=30, # Auto-refresh interval
)
Components
Components are objects that render to HTML. Available components:
| Component | Description | Example |
|---|---|---|
HtmlComponent |
Raw HTML | HtmlComponent(html="<h1>Title</h1>") |
FrameComponent |
JQX Data Grid | FrameComponent(frame=df) |
PlotlyComponent |
Plotly Chart | PlotlyComponent(plotly_obj=fig) |
ImageComponent |
Base64 Image | ImageComponent(encoded_image=b64) |
MarkdownComponent |
Markdown Text | MarkdownComponent(text="# Hello") |
FormComponent |
HTML Forms | See Forms section |
ColumnsContainer |
Grid Layout | ColumnsContainer(obj1, obj2) |
Container |
Vertical Stack | Container([obj1, obj2]) |
Automatic Type Conversion
FlapiPage automatically converts common types to components:
str->HtmlComponentlist/tuple->Containerpd.DataFrame->FrameComponentgo.Figure(Plotly) ->PlotlyComponent
# These are equivalent:
FlapiPage(objects=[HtmlComponent(html="<p>Hello</p>")])
FlapiPage(objects=["<p>Hello</p>"])
Layouts with ColumnsContainer
Place components side-by-side:
from ionbus_flapi import ColumnsContainer
# Two equal columns
ColumnsContainer(chart1, chart2)
# Custom column widths
ColumnsContainer(
chart1, chart2, chart3,
column_desc="1fr 2fr 1fr" # Middle column is 2x wider
)
DataFrames with FrameComponent
Display pandas DataFrames as sortable, filterable grids:
from ionbus_flapi import FrameComponent
frame = FrameComponent(
frame=df,
sortable=True,
filterable=True,
)
# Configure columns
frame.format_dict = {
"price": {"width": 100, "cellsformat": "D2"},
"name": {"width": 200},
}
# Add sum row
frame.sum_columns = ["price", "quantity"]
Forms
Create interactive forms:
from ionbus_flapi import FormComponent, FormElement
form = FormComponent(
elements=[
FormElement(name="username", box=True, label="Username"),
FormElement(name="role", values=["Admin", "User"]),
FormElement(name="active", checkbox=True, default=True),
],
submit="Save",
)
API Endpoints
Register JSON API endpoints:
from ionbus_flapi import register_api_endpoint
def my_api() -> dict:
"""Returns user data."""
return {"users": [...], "count": 10}
register_api_endpoint(MODULE_NAME, "users", my_api, methods="GET")
Request Context
Access request data within endpoints:
from ionbus_flapi import get_request_context
def my_endpoint():
ctx = get_request_context()
user = ctx.username
params = ctx.args
theme = ctx.theme
# ...
Cookies
Set cookies for persistence:
from ionbus_flapi import set_cookie
set_cookie("my_preference", "value")
Themes
Flapi supports three themes: system, light, and dark.
The theme toggle button cycles through themes when clicked. To add it:
FlapiPage(title="My Page", objects=[...], theme_toggle=True)
Directory Structure
Recommended project structure:
my_project/
├── app.py
├── config/
│ ├── windows.yaml
│ └── linux.yaml
├── static/
│ ├── base.css
│ ├── themes/
│ │ ├── system.css
│ │ ├── light.css
│ │ └── dark.css
│ └── assets/
├── sampleData/
└── MyEndpoints/
├── __init__.py
└── endpoints.py
Dash Integration
Embed interactive Dash apps within Flapi pages:
from ionbus_flapi import register_dash_endpoint, DashComponent, FlapiPage
from dash import dcc, html
def initialize():
# Register a standalone Dash app
dash_app = register_dash_endpoint(
MODULE_NAME,
"my_dash_app",
ep_description="Interactive Dash application",
show_in_dir=True,
)
# Configure Dash layout
dash_app.layout = html.Div([
dcc.Dropdown(id="dropdown", options=[...]),
dcc.Graph(id="graph"),
])
# Add callbacks
@dash_app.callback(...)
def update_graph(...):
...
def my_page() -> FlapiPage:
# Embed Dash app in a FlapiPage
return FlapiPage(
title="Page with Dash",
objects=[
DashComponent("my_dash_app", height="600px"),
],
)
Server Shutdown
Configure graceful server shutdown with callbacks.
Config
Add shutdown_code to your YAML config:
app_type: fastapi
port: 5080
proxy_prefix: MyApp
shutdown_code: "my_secret_code" # Required to enable shutdown endpoint
Shutdown Endpoint
Once configured, access /MyApp/shutdown?code=my_secret_code to shut down the
server.
Shutdown Callbacks
Register functions to run before shutdown (cleanup resources, save state, etc.):
from ionbus_flapi import register_shutdown_callback
def cleanup_resources():
"""Called when server shuts down."""
print("Cleaning up...")
# Close database connections, save state, etc.
# Register during initialization
register_shutdown_callback(cleanup_resources)
Real-Time Data Streaming
Use EventStreamManager for Server-Sent Events (SSE) to push live data updates:
from ionbus_flapi import (
EventStreamManager,
EventStreamTypes,
FlapiPage,
HtmlComponent,
get_flapi,
)
import threading
# Create manager supporting grid and div updates
esm = EventStreamManager(
"MyStream",
modes=EventStreamTypes.GRID | EventStreamTypes.DIV,
include_pause=True,
)
def initialize():
# Register with FlapiApp (after initialize(), before serve())
esm.register(get_flapi())
# Start data thread
threading.Thread(target=data_thread, daemon=True).start()
def data_thread():
while True:
if esm.has_subscriptions():
# Update a div
esm.broadcast_event("ticker", {
"MessageType": "div",
"DivId": "myDiv",
"Html": "Updated content",
})
# Update a grid
esm.broadcast_event("ticker", {
"MessageType": "grid",
"GridName": "MyGrid",
"UpdateId": "id", # Column to match rows
"Rows": [{"id": 1, "value": 42}],
})
time.sleep(0.5)
def live_page() -> FlapiPage:
stream_addr = esm.get_stream_address("ticker")
js = esm.javascript(stream_addr)
html = esm.html() # Pause button
return FlapiPage(
title="Live Data",
objects=[HtmlComponent(html=f'''
<div id="myDiv">Loading...</div>
{html}
<script>$(document).ready(function() {{ {js} }});</script>
''')],
)
EventStreamTypes
| Type | Description |
|---|---|
GRID |
Update JQX Grid rows |
DIV |
Update div innerHTML |
LINE_PLOT |
Extend Plotly line chart |
OHLC_PLOT |
Extend Plotly OHLC chart |
Combine types with |: EventStreamTypes.GRID | EventStreamTypes.DIV
URL Utilities
extract_variables_from_address
Parse query parameters from URL strings (useful in Dash callbacks):
from ionbus_flapi import extract_variables_from_address
url = "/MyApp/page?foo=bar&baz=123"
params = extract_variables_from_address(url)
# {'foo': 'bar', 'baz': '123'}
Setup Script
Use the setup script to create a new project:
python -m ionbus_flapi.setup_project my_new_project
This creates the full directory structure with a sample endpoint.
Metadata
Release files for ionbus-flapi 0.1.2.4
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| ionbus_flapi-0.1.2.4.tar.gz | 72.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| ionbus_flapi-0.1.2.4-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 141.7 kB
Release files / ionbus_flapi-0.1.2.4.tar.gz
| Download URL | ionbus_flapi-0.1.2.4.tar.gz |
|---|---|
| Size | 72.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
9d7ac964780f067eedac227d6e47a6046ae7e5b7158f3572688d584c91ba8ba5
|
|
BLAKE2b-256 checksum How to use checksums |
645bc3d664ba0c77a48929344befedf53e6aeb2d6e88997cfd8536661200ff22
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.13
|
Release files / ionbus_flapi-0.1.2.4-py3-none-any.whl
| Download URL | ionbus_flapi-0.1.2.4-py3-none-any.whl |
|---|---|
| Size | 69.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
aaf624f10fee4de258ef4b5ec1382bca306281449b6c8d39ce5fdc2581816e8e
|
|
BLAKE2b-256 checksum How to use checksums |
a531c3798dcecc609da80473babbcb014d70b2bc690077e5f3c3410da83ecd2a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.13
|