PANELITH DOCS Open the interactive docs ↗

Reference · Panelith 0.1.0 · plain HTML edition; the interactive edition has search and live examples

Schema

On this page 4 sections
  1. The shell (the manifest)
  2. AppInfo
  3. Brand
  4. Theme
  5. Canvas
  6. PaneHeader
  7. Glyph
  8. KindSpec
  9. HotkeySpec
  10. CommandSpec
  11. ListColumn
  12. ListStatus
  13. ListSpec
  14. TopBar
  15. Manifest
  16. Actions
  17. OpenPane
  18. SetPaneState
  19. PatchPaneState
  20. Subtab
  21. SetSubtabs
  22. ClosePane
  23. FocusPane
  24. RenameTab
  25. SetTitle
  26. Notify
  27. RefreshList
  28. OpenCommandBar
  29. RunBuiltin
  30. SpotStep
  31. Spotlight
  32. SetRoute
  33. OpenUrl
  34. SendEvent
  35. ActionList
  36. LayoutRecord
  37. EmptyCall
  38. Requests
  39. TabRef
  40. Viewport
  41. ClientContext
  42. RegisterPane
  43. PaneEvent
  44. CommandCall
  45. RouteCall
  46. ListRows
  47. UIAction

The pydantic models in panelith.schema: the contract between the Python side and the shell. The manifest describes the shell; actions are what handlers return; requests are what the shell sends.

The shell (the manifest)#

AppInfo#

Field Type Default Description
id str required the app id: [a-z][a-z0-9_-]*; names the session cookie and the local-storage namespace
title str required the window title
version str '0.1' the app's version string

Brand#

The top-left mark. text renders the title in a monoline wordmark style, svg inlines markup verbatim, image points at a URL (served by the app or external).

Field Type Default Description
text str | None None the wordmark text for a text brand; each word may take a colour
colors list[str] [] per-word colors for text brands
svg str | None None inline SVG markup for an svg brand
src str | None None the image URL for an image brand
alt str '' alt text for svg and image brands
height int 28 the mark's height in pixels
short str | None None compact form shown on phones in place of the mark; a text brand defaults to its initials

Theme#

CSS custom-property overrides. Keys are token names without the --pl- prefix (accent, pane-bg, …); families maps a family id to its color, emitted as --pl-family-<id>.

Field Type Default Description
scheme str 'dark' the colour scheme the shell starts in; auto follows the OS; the visitor's own toggle (the app.theme built-in) is remembered per app — Options: dark · light · auto
tokens dict[str, str] {} --pl-* overrides by name without the prefix (accent, pane-bg, …) — Options:
45 options
accent assessment author-purple backdrop bad bg cmdbar-top cmdbar-trigger-h cmdbar-width code-bar code-bg code-class code-comment code-decorator code-function code-keyword code-number code-operator code-punct code-string collapsed-px collected danger divider divider-hover drop family-assessment family-author family-independent family-problem focus focus-outline mono ok pane-bg pane-border pane-gap sans shadow-rgb text text-dim topbar-h warn wash-rgb white
as keys; values and defaults in Tokens
families dict[str, str] {'independent': '#4f8cff', 'problem': '#e8a33d', 'author'... family id → colour, emitted as --pl-family-<id>

Canvas#

Field Type Default Description
max_columns int 2 how many columns the canvas may split into (1–4)
max_rows int 3 how many rows per column (1–6)
initial str 'launcher' what the first pane shows: the launcher tiles, nothing, or a kind — Options: launcher · empty · kind
initial_kind str | None None the kind opened at start when initial='kind'
bottom bool False allow one full-width pane across the bottom of every column (the pane.splitBottom built-in); it holds one pane, resizes against the grid, and is off by default

PaneHeader#

Field Type Default Description
visible bool True False renders the body only: no tab strip, no icons
glyph bool True show the kind's glyph on the tab
rename bool True double-click renames the tab
close bool True a × on the tab
chain bool True the tether icon when the pane has tethered partners
cycler bool True the ‹ › buttons of a kind with a cycler
maximize bool True the maximize / restore icon
collapse bool True the collapse icon

Glyph#

A custom tab/launcher glyph: SVG path d strings drawn in a 24×24 box with the family stroke (the built-in glyphs are referenced by name instead).

Field Type Default Description
paths list[str] required SVG path d strings in a 24×24 box
fill bool False fill the paths with the family colour instead of stroking them

KindSpec#

Field Type Default Description
id str required the kind id
label str required the tab name and launcher caption
glyph str | Glyph 'ring' a built-in glyph name or a custom Glyph — Options:
49 options
ring square table list grid form file gear bolt star home info bell calendar database globe image play book user chat flask dollar key cube math code prompt terminal output graph chart plot solve steps puzzle puzzle-left puzzle-right text document pen author checklist report timer clipboard folder search commands
or a Glyph; pictured in Glyphs
family str 'independent' the colour family of the glyph, tile and tethers — Options: independent · problem · author · assessment or any key of Theme.families
widget str 'markdown' the widget that renders the body — Options: markdown · html · table · keyvalue · output · form · text · blocks or a plugin's id
widget_options dict[str, Any] {} passed to the widget unchanged
persist list[str] [] state keys a saved layout carries for this kind; the rest is rebuilt by restore_state
subtabs bool False a sub-tab strip inside the pane
closable bool True a × on the tab and a close command
launcher bool True a launcher tile and a generated <kind>.new opener
launcher_group str | None None a heading the launcher groups this kind's tile under; None keeps it in the first, unnamed group
tip str '' the launcher tile's tooltip
cycler str | None None a list id: ‹ › buttons that send a cycle event
header PaneHeader | None None this kind's header flags; None inherits the app's
single bool False at most one pane of this kind is open at a time

HotkeySpec#

A chord under the app's modifier namespace. code is a KeyboardEvent.code (KeyK, Quote, Enter); label is what the help overlay prints.

Field Type Default Description
code str required the KeyboardEvent.code the shell matches
ctrl bool False the chord also needs control
label str required what the help overlay prints

CommandSpec#

Field Type Default Description
id str required the command id
title str required the entry in the bar
keywords str '' extra text the bar's search matches
hotkey HotkeySpec | None None the parsed chord, if any
scope str 'global' 'global' or 'kind:' (shown only when such a pane is focused) — Options: global · kind:<kind id>
server bool True False: the shell runs it itself (the built-in pane commands)
launcher bool False the launcher shows a tile for this command
launcher_label str | None None the tile's caption
launcher_glyph str | Glyph | None None the tile's icon — Options:
49 options
ring square table list grid form file gear bolt star home info bell calendar database globe image play book user chat flask dollar key cube math code prompt terminal output graph chart plot solve steps puzzle puzzle-left puzzle-right text document pen author checklist report timer clipboard folder search commands
or a Glyph; pictured in Glyphs
launcher_color str | None None the tile's colour
launcher_tip str | None None the tile's tooltip
launcher_group str | None None a heading the launcher groups the tile under

ListColumn#

Field Type Default Description
key str required the row key
label str | None None the header text; the key when omitted
width int | None None a fixed width in pixels
grow bool False take the spare width
mono bool False monospace, for ids and figures

ListStatus#

Field Type Default Description
key str required the row key the marks and tones read
marks dict[str, str] {} value -> glyph, e.g. {'solved': '✓'}
tones dict[str, str] {} value -> 'ok' | 'half' | 'dim'

ListSpec#

Field Type Default Description
id str required the list id
title str required the drawer heading and the bar's section name
sigil str | None None one character that lists this source in the command bar — Options: any single character other than the command sigil
drawer bool True whether the list has a drawer
columns list[ListColumn] required the columns a row shows
search list[str] [] row keys the search box matches
facets list[str] [] row keys that get a filter button each
status ListStatus | None None a mark and tone per row from one key
row_action str | None None command id run with {row} when a row is chosen
empty_text str 'Nothing here yet' what an empty list says
live bool False the server searches: every keystroke fetches /api/lists/?q=… and the shell keeps the order it gets back
snippet str | None None a row key shown dim under the row's columns (a search excerpt)
tree str | None None a row key holding an indent level (0, 1, 2): level 0 rows read as headings, deeper rows sit indented beneath them
chips list[str] [] facets (from facets) shown as a row of toggle chips above the rows instead of a filter button

TopBar#

Field Type Default Description
buttons list[str] ['hotkeys'] right-side buttons in order: 'hotkeys', 'commands', 'layouts' (save and restore the canvas), or 'list:' — Options: hotkeys · commands · layouts · list:<list id>
placeholder str 'Search commands…' the text in the idle bar
trigger_sigil str | None None the sigil the top-bar trigger opens the bar with (default: the command sigil); a docs app opens straight into its search list

Manifest#

Field Type Default Description
app AppInfo required id, title, version
brand Brand required the top-left mark
theme Theme required scheme, tokens, families
canvas Canvas required grid limits and the start mode
pane_header PaneHeader required the default header flags
topbar TopBar required buttons, placeholder, trigger sigil
command_sigil str '>' the character that lists commands in the bar
hotkey_modifiers list[str] ['alt', 'shift'] the chord every hotkey lives under — Options: alt · shift · ctrl · meta
kinds list[KindSpec] required every kind
commands list[CommandSpec] required the built-ins first, then the app's commands and generated openers
lists list[ListSpec] required every list source
features dict[str, bool] {'sse': True} sse (push is on), routes (the app handles the URL hash), on_empty (the app wants to hear when the canvas is emptied) and layouts_server (saved layouts go to the app's LayoutStore instead of the browser)
plugins list[str] [] URLs of ES modules the shell imports before first render (custom widgets)

Actions#

OpenPane#

Field Type Default Description
kind str required the kind to open
name str | None None the tab name; the kind's label when omitted
state dict[str, Any] | None None the pane's first state; skips initial_state
parent str | None None cid of the tab this one is tethered to
placement str 'focused' where a child goes relative to its parent; 'tab' = the parent's own pane — Options: focused · below · beside · new · tab
focus bool True focus the new tab
cid str | None None reuse: surface this cid instead of opening a new tab if it exists
size float | None None fraction of the parent's row/column a new below/beside pane takes

SetPaneState#

Field Type Default Description
cid str required the pane
state dict[str, Any] required the whole new state

PatchPaneState#

Field Type Default Description
cid str required the pane
patch dict[str, Any] required fields merged into the state

Subtab#

Field Type Default Description
id str required the sub-tab id
name str required the sub-tab name

SetSubtabs#

Field Type Default Description
cid str required the pane
subtabs list[Subtab] required the strip, in order
active str | None None the selected id

ClosePane#

Field Type Default Description
cid str required the tab to close

FocusPane#

Field Type Default Description
cid str required the tab to focus

RenameTab#

Field Type Default Description
cid str required the tab
name str required its new name

SetTitle#

Field Type Default Description
text str | None required the top bar's centre text; None restores the placeholder

Notify#

Field Type Default Description
text str required the toast text
tone str 'info' its colour — Options: info · ok · warn · error
ms int 2600 how long it stays

RefreshList#

Field Type Default Description
list_id str required the list to fetch again

OpenCommandBar#

Field Type Default Description
sigil str '>' the sigil to open with
query str '' text typed after the sigil

RunBuiltin#

Field Type Default Description
id str required a built-in command id, or list:<id>

SpotStep#

One stop of a spotlight: the shell element to ring (a data-pl hook such as topbar.brand, cmdbar, drawer, launcher, help, pane:<cid>, tab:<cid>, header:<cid>, body:<cid>, subtabs:<cid>, divider:<col>, divider:<col>:<row>, cmdbar.row:<command id>, launcher.tile:<command id>, topbar.list:<id>, topbar.hotkeys, topbar.commands, toast), a caption, an optional auto-advance after ms, and a family name for the ring colour.

Field Type Default Description
target str required the data-pl hook of the element to ring
text str | None None caption shown beside the ring
ms int | None None advance (or dismiss) after this many milliseconds; None waits for a click
tone str | None None a theme family name for the ring colour, or preview (the yellow warn colour); None uses the accent
patch dict[str, Any] | None None a preview: a partial manifest (brand, theme, command_sigil, topbar, pane_header) the shell applies while this step shows and reverts when the spotlight ends

Spotlight#

Ring a shell element with a caption, or walk the user through several (a tour). An empty steps list clears any spotlight showing.

Field Type Default Description
steps list[SpotStep] [] the stops, in order; empty clears the spotlight
dismiss str 'click' click: any click outside the caption dismisses; auto: only the caption buttons, Escape or ms do

SetRoute#

Put path in the address bar's hash (#/guide/panes) without reloading or adding history, so the visitor can share or bookmark where they are. The shell posts the hash back to App.on_route on load and whenever it changes by hand.

Field Type Default Description
path str required the hash to write, without the #
push bool False add a history entry, so the browser's Back returns to the previous hash (the default replaces the current entry)

OpenUrl#

Open a URL: a new tab by default (the browser allows it right after the user's click that produced this action), or navigate the current one.

Field Type Default Description
url str required the URL
new_tab bool True open a new tab rather than navigating

SendEvent#

Have the shell post an event back to a pane (lets a command delegate to the pane's own handler, e.g. code.run -> the editor's run event).

Field Type Default Description
cid str required the pane
name str required the event name
payload dict[str, Any] {} the event payload

ActionList#

Field Type Default Description
actions list[Union[OpenPane, SetPaneState, PatchPaneState, SetSubtabs, ClosePane, FocusPane, RenameTab, SetTitle, Notify, RefreshList, OpenCommandBar, RunBuiltin, SendEvent, Spotlight, OpenUrl, SetRoute]] [] the actions, applied in order

LayoutRecord#

A saved canvas layout as the shell stores it: the split geometry and, per tab, the kind and the keys it persists. The shell builds and reads data; a LayoutStore only keeps records by profile.

Field Type Default Description
id str required stable id (the shell derives it from the name)
name str required the name the visitor gave it
saved_at float required epoch seconds
summary str '' one line: pane count and what is open
data dict[str, Any] {} the layout: columns, rows, tabs with their seeds

EmptyCall#

The shell's report that the canvas has no tabs left (App.on_empty).

Field Type Default Description
context ClientContext ClientContext(...) the client context

Requests#

TabRef#

Field Type Default Description
cid str required the tab's content id
kind str required its kind
name str | None None its name
parent str | None None the cid it is tethered to

Viewport#

Field Type Default Description
width int 0 window width in CSS pixels
height int 0 window height in CSS pixels

ClientContext#

What the shell knows that a handler may want: the focused tab, every open tab (cid, kind, parent) in reading order, and the window size.

Field Type Default Description
focused TabRef | None None the focused tab
tabs list[TabRef] [] every open tab in reading order
columns int 1 how many columns the canvas has
viewport Viewport | None None the window size

RegisterPane#

Field Type Default Description
cid str required the new tab's cid
kind str required its kind
parent str | None None the cid it is tethered to
state dict[str, Any] | None None state carried by the open_pane action, or the browser's persisted copy on a restore
restore bool False the browser is re-registering a pane it restored from local storage
seed dict[str, Any] | None None a saved layout is being restored: the keys the kind persists (Pane.persist); the state comes from restore_state and the kind's children are not re-opened (the layout holds them)
context ClientContext ClientContext(...) the client context

PaneEvent#

Field Type Default Description
name str required the event name
payload dict[str, Any] {} the payload
context ClientContext ClientContext(...) the client context

CommandCall#

Field Type Default Description
args dict[str, Any] {} arguments for ctx.args (a list row under row)
context ClientContext ClientContext(...) the client context

RouteCall#

Field Type Default Description
path str required the URL hash without #
context ClientContext ClientContext(...) the client context

ListRows#

Field Type Default Description
rows list[dict[str, Any]] required the rows
total int | None None how many rows in all

UIAction#

UIAction is the discriminated union of every action model (on type); ActionList is {"actions": [UIAction, ...]}, the shape of every reply and every pushed event.