PANELITH DOCS Open the interactive docs ↗

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

App

On this page 6 sections
  1. Attributes
  2. Hooks and methods
  3. on_start
  4. on_route
  5. profile
  6. extend_server
  7. push
  8. broadcast
  9. after_reply
  10. bind
  11. manifest
  12. run
  13. kind
  14. command
  15. list_source
  16. context
  17. session
  18. panes
  19. sessions
  20. LayoutStore
  21. Methods to implement
  22. list
  23. save
  24. delete
  25. MemoryLayoutStore
  26. Brand
  27. text
  28. svg
  29. svg_file
  30. image
  31. Also exported

App is the base class an application subclasses. Its class attributes are the shell defaults; override what differs and list the kinds, commands and lists the app ships. One instance serves every visitor (Sessions).

Attributes#

Attribute Type Default What it changes
id str 'app' the app id: the session cookie (panelith_<id>) and the local-storage namespace
title str 'App' the window title and the default text brand
version str '0.1' shown in the manifest
description str ''
brand Brand | None None the top-left mark: Brand.text(...), Brand.svg(...), Brand.svg_file(...), Brand.image(...); defaults to the title as text
theme Theme Theme(...) Theme(scheme=, tokens=, families=)
canvas Canvas Canvas(...) Canvas(max_columns=, max_rows=, initial=, initial_kind=)
pane_header PaneHeader PaneHeader(...) PaneHeader(...): the header controls of every kind that does not set its own
topbar TopBar TopBar(...) TopBar(buttons=, placeholder=, trigger_sigil=)
command_sigil str '>' the character the bar treats as 'commands' — Options: any single character the bar does not already use (? and . are typical list sigils)
hotkey_modifiers list[str] ['alt', 'shift'] the chord every hotkey lives under: any of alt, shift, ctrl, meta
builtin_commands list[dict[str, Any]] [21 entries] the shell's own commands to offer (a filtered copy of BUILTIN_PANE_COMMANDS) — Options:
21 options
pane.splitVertical pane.splitHorizontal pane.splitBottom pane.close pane.collapse pane.maximize pane.focusLeft pane.focusRight pane.focusUp pane.focusDown pane.moveContentPrev pane.moveContentNext pane.cyclePrev pane.cycleNext pane.subtabPrev pane.subtabNext pane.rename app.commandBar app.help app.theme app.layouts
by id
builtin_hotkeys dict[str, str | None] {} {id: key} re-maps a built-in's key; None disables it — Options:
21 options
pane.splitVertical pane.splitHorizontal pane.splitBottom pane.close pane.collapse pane.maximize pane.focusLeft pane.focusRight pane.focusUp pane.focusDown pane.moveContentPrev pane.moveContentNext pane.cyclePrev pane.cycleNext pane.subtabPrev pane.subtabNext pane.rename app.commandBar app.help app.theme app.layouts
as keys
kinds list[type[Pane]] [] the Pane subclasses the app ships (plus any defined in the class body)
commands list[type[Command]] [] the Command subclasses
lists list[type[ListSource]] [] the ListSource subclasses
plugins list[str | pathlib.Path] [] ES modules with custom widgets, paths relative to the file defining the app; served at /plugins/<name>
session_ttl float 7200 seconds an idle, disconnected visitor's session is kept
max_sessions int 1000 how many sessions are kept at most; the idlest go first
launcher_kinds list[str] | None None
layouts LayoutStore | None None None: saved layouts stay in the browser; a LayoutStore keeps them on the server per profile(ctx) (Saved layouts)
max_layouts int 50

Hooks and methods#

on_start#

on_start(self) -> None

Called once when the server starts (start background threads here).

on_route#

on_route(self, ctx: Context, path: str) -> Any

Override to open what path (the URL hash without #, e.g. /guide/panes#events) names. Returning actions that include set_route is fine. Only when overridden does the shell send routes at all.

profile#

profile(self, ctx: Context) -> str | None

Who the visitor is, for a server-side LayoutStore (and anything else an app keeps per person). The default returns ctx.user, which is None until an app sets it, so every visitor shares one profile; an app with accounts returns the username it resolves from the session (self.session().data) or a cookie.

Argument Meaning
ctx a context for the current session (no pane).

extend_server#

extend_server(self, api: Any) -> None

Hook: add routes to the FastAPI app that serves this App, before the shell's catch-all is registered. The docs app uses it for its crawlable HTML pages and sitemap; a plain app needs nothing here.

Argument Meaning
api the FastAPI application for this App (one per mount).

push#

push(self, *actions: Any) -> None

Send actions to the current visitor's open tabs (needs the running server). Outside a request there is no current visitor, so this reaches every session, like broadcast.

broadcast#

broadcast(self, *actions: Any) -> None

Send actions to every connected visitor. State actions are mirrored into each session separately, so a cid only has an effect where it exists.

after_reply#

after_reply(self, fn: Callable[[], Any]) -> None

Run fn once the current request's reply has been applied (start a worker thread here so its pushes cannot be overwritten by the reply's own state actions). Outside a request it runs at once.

bind#

bind(self, session: Session) -> Iterator[Session]

Serve the enclosed code as session (what the server wraps each request in). Callbacks queued with after_reply run when the block exits, i.e. after the handler's actions have been mirrored into the session.

manifest#

manifest(self) -> s.Manifest

run#

run(self, host: str = '127.0.0.1', port: int = 8000, open_browser: bool = False, log_level: str = 'info', forwarded_allow_ips: str | None = None) -> None

Serve the app with uvicorn. Behind a reverse proxy pass forwarded_allow_ips (the proxy's address, or "*") so X-Forwarded-Proto is trusted and the session cookie is marked Secure on https.

kind#

kind(self, kind_id: str) -> Pane | None

command#

command(self, command_id: str) -> Command | None

list_source#

list_source(self, list_id: str) -> ListSource | None

context#

context(self, client: s.ClientContext, pane: PaneRef | None = None, args: dict[str, Any] | None = None) -> Context

session#

A property. The visitor whose request is being served (a shared default otherwise).

panes#

A property. The current session's pane table: cid -> live record with its state.

sessions#

A property.

LayoutStore#

Where saved layouts live when an app keeps them on the server instead of in the browser (App.layouts = MyStore()). Records are schema.LayoutRecord dicts, kept per profile: App.profile(ctx) names the visitor (a username once accounts exist); None is the shared default. Subclass and implement the three methods over any storage; MemoryLayoutStore is the in-process reference.

Set App.layouts to an instance to keep saved layouts on the server (Saved layouts); the shell then uses /api/layouts.

Methods to implement#

list#

list(self, profile: str | None) -> list[dict[str, Any]]

Every saved layout of profile, newest first.

save#

save(self, profile: str | None, record: dict[str, Any]) -> None

Store record (replacing one with the same id).

delete#

delete(self, profile: str | None, layout_id: str) -> None

Remove the layout layout_id; a missing id is not an error.

MemoryLayoutStore#

Layouts kept in this process, per profile: the reference implementation and what tests use. They vanish with the process.

Brand#

Factories for the top-left mark; each returns a schema.Brand.

text#

text(text: str, colors: Iterable[str] = (), height: int = 28, short: str | None = None) -> s.Brand

short is the phone form (default: the initials, in the same colors).

svg#

svg(markup: str, height: int = 28, alt: str = '', short: str | None = None) -> s.Brand

short, if given, replaces the mark on phones (a monogram as text).

svg_file#

svg_file(path: str | os.PathLike[str], height: int = 28, alt: str = '', short: str | None = None) -> s.Brand

image#

image(src: str, height: int = 28, alt: str = '', short: str | None = None) -> s.Brand

Also exported#

Theme, Canvas, PaneHeader, TopBar and Glyph are the schema models of the same names, re-exported for app code; see the schema.