Architecture¶
This page describes the high-level architecture of panelini, how its modules relate to each other, and how data flows through the system.
Package Structure¶
graph TB
subgraph core [" Core "]
direction TB
init(["__init__.py"])
main(["Panelini"])
css(["main.css"])
end
subgraph panels [" Panels "]
direction TB
je(["JsonEditor"])
vn(["VisNetwork"])
gdt(["GraphDetailTool"])
utils(["utils"])
end
subgraph components [" Components "]
direction TB
planned(["planned"])
end
init --> main
gdt --> vn
gdt -.-> je
classDef coreNode fill:#1e293b,stroke:#334155,color:#f8fafc
classDef panelNode fill:#0d7377,stroke:#095c5f,color:#ffffff
classDef plannedNode fill:#94a3b8,stroke:#64748b,color:#ffffff
class init,main,css coreNode
class je,vn,gdt,utils panelNode
class planned plannedNode
The panelini package has two layers:
Core (
main.py): ThePaneliniclass provides the application layout frameworkPanels (
panels/): Independent, reusable components that work with or without PaneliniComponents (
components/): Panelini-dependent components (planned for future development)
Panels are designed to be standalone – they can be used directly in any Panel application without importing the Panelini framework.
Dashboard Layout¶
The Panelini class composes a responsive dashboard layout from distinct sections:
graph TB
subgraph layout [" Panelini Dashboard "]
direction TB
subgraph header [" Header / Navbar "]
direction LR
logo(["Logo"])
title(["Title"])
nav(["Nav Buttons"])
end
subgraph content [" Content Area "]
direction LR
sidebar_left(["Left Sidebar"])
main_area(["Main Content"])
sidebar_right(["Right Sidebar"])
end
subgraph footer [" Footer "]
footer_content(["Footer Content"])
end
end
header --> content
content --> footer
classDef headerNode fill:#1e293b,stroke:#334155,color:#f8fafc
classDef contentNode fill:#0d7377,stroke:#095c5f,color:#ffffff
classDef sidebarNode fill:#6366f1,stroke:#4f46e5,color:#ffffff
classDef footerNode fill:#94a3b8,stroke:#475569,color:#ffffff
class logo,title,nav headerNode
class main_area contentNode
class sidebar_left,sidebar_right sidebarNode
class footer_content footerNode
Each section accepts any Panel component:
Header: Logo image, title text, and navigation button bar
Left/Right Sidebars: Toggleable sidebars with configurable max width
Main Content: The primary content area managed via
main_set(),main_add(), etc.Footer: Optional footer section
All sections support custom CSS classes and background images.
Panel Component Architecture¶
Both JsonEditor and VisNetwork follow the same architecture pattern – they are AnyWidgetComponent subclasses that bridge Python and JavaScript via Vue.js:
graph LR
subgraph python [" Python Server "]
props(["Param Properties"])
callbacks(["Event Callbacks"])
end
subgraph bridge [" AnyWidget Bridge "]
sync(["Bi-directional Sync"])
end
subgraph browser [" JavaScript Browser "]
vue(["Vue.js Wrapper"])
lib(["JS Library"])
dom(["DOM"])
end
props <--> sync
sync <--> vue
vue --> lib --> dom
dom -- "events" --> vue
vue -- "_event_data" --> sync
sync -- "callback" --> callbacks
classDef pyNode fill:#1e293b,stroke:#334155,color:#f8fafc
classDef bridgeNode fill:#6366f1,stroke:#4f46e5,color:#ffffff
classDef jsNode fill:#0d7377,stroke:#095c5f,color:#ffffff
class props,callbacks pyNode
class sync bridgeNode
class vue,lib,dom jsNode
Key points:
Python-side properties (nodes, edges, options) are synced to JavaScript automatically
JavaScript events (clicks, drags, file drops) are sent back via
_event_dataparamPython callbacks process these events and can update properties reactively
The Vue.js wrapper handles initialization, cleanup, and library-specific API calls
Data Flow¶
This diagram shows how a user interaction flows through the system:
sequenceDiagram
participant User as User
participant JS as Vue.js
participant Bridge as AnyWidget
participant Py as Component
participant App as App Code
User->>JS: Interact
JS->>JS: Process event
JS->>Bridge: _event_data
Bridge->>Py: Sync property
Py->>Py: @param.depends
Py->>App: Callback
App->>Py: Update props
Py->>Bridge: Sync update
Bridge->>JS: Apply changes
JS->>User: Re-render
GraphDetailTool Composition¶
The GraphDetailTool composes VisNetwork and JsonEditor into a complete graph editing UI:
graph TB
subgraph gdt [" GraphDetailTool "]
direction TB
subgraph controls [" Edit Controls "]
direction LR
disable(["Disable Edit"])
add_node(["Add Node"])
add_edge(["Add Edge"])
end
subgraph workspace [" Workspace "]
direction LR
vn(["VisNetwork"])
subgraph detail [" Detail Panel "]
direction TB
viz(["Visualization"])
editor(["JsonEditor"])
end
end
end
controls --> vn
vn -- "node click" --> detail
editor -- "value change" --> vn
classDef controlNode fill:#8b7355,stroke:#6b5840,color:#ffffff
classDef graphNode fill:#0d7377,stroke:#095c5f,color:#ffffff
classDef detailNode fill:#6366f1,stroke:#4f46e5,color:#ffffff
class disable,add_node,add_edge controlNode
class vn graphNode
class viz,editor detailNode
Features:
Single node click: Shows node details and content visualization
Multi-node selection: Comparison table with bulk editing
CSV data: Rendered as interactive table with optional Plotly charts
Drag events: Automatically update node positions