Repository navigation
symbion: a keyboard-first NiceGUI PWA over a coding agent's tickets, and what we tripped over #6436
Replies: 1 comment 2 replies
|
Thanks for this write-up, @phreakocious! It's rare to get such a careful list of rough edges, each with the workaround already worked out. Funny coincidence, too: we're building a very similar app in-house right now, a NiceGUI dashboard where a person and their coding agents share tickets, drafts and decisions. It's closed source for now, so it's great to see someone else arrive at much the same shape in the open. Going through your list:
Points 2, 3 and 6 are each a small, self-contained change. Would you like to open pull requests for them? You've already found the problems and the fixes, so they'd make nice first contributions. If you'd rather not, just say so and we'll take care of them. About your open question: when a page has a thousand or more elements, the cost is in having that many server-side elements at all. Each one is created, serialized and mounted separately. What has worked for us:
|
Uh oh!
There was an error while loading. Please reload this page.
Hi all. symbion is a notebook and ticket registry that a person shares with their coding agents (Claude Code, Codex): bugs, tasks, questions and test results, kept as dated entries in a git repo beside the project. The agent works it through a CLI.
symbion serveis the NiceGUI app where the person reads it and answers.src/symbion/gui/.pipx install 'symbion[gui]'What the app does
j/kpeek at entries in a drawer beside the page;xresolves,aanswers,eedits.nwrites a new entry from any page.⌘Kopens a palette that also searches every other store aserveruns on.ui.timerchecks the store file's mtime and size, and a button counts the entries an agent wrote since the page was drawn. Installed as an app, the icon's badge counts them (navigator.setAppBadge).@app.getroute serves the manifest, which registers aweb+symbion:protocol handler, so a URL router can send links from a terminal into the app.--read-onlyserves a public demo: every control answers with a notice.Things we tripped over
1.
#esm-fallback ~ *made every style pass quadratic. The page template hides what follows its ES-module notice with that rule, and the rule stays after the notice is gone, so every element is tested against each of its earlier siblings. A 200 KB source file in our file viewer (27,000 spans in one<code>) took 4.5 s per style pass and 24 s to first paint in headless Chrome. With the rule deleted, a pass took 90 ms and the paint 2.2 s. Reported in #6411 and fixed in #6426 within four days; thank you. Until a release carries the fix, we delete the rule at load:2. A script blocker reads "Your browser does not support ES modules." That notice shows whenever scripts do not run, including when a blocker turned them off. A
<noscript>says what is really missing. The template styles the notice afterui.add_body_html's HTML, so only!importanthides it:3.
ui.on('a-b', …)registers asaB. NiceGUI camelCases a global event's type. In a browser, Vue maps an emitteda-bto the same handler, so only theuserfixture'strigger('a-b')misses it. We name page events in camelCase everywhere.4.
ui.notifybeforeui.navigate.reload()never shows. It dies with the page. A notice before a refreshable's redraw lives. Theuserfixture shows both, so only a browser catches it. We put the text inapp.storage.taband show it on the next load.5. A
ui.timerin a shared page shell wantsimmediate=False. With an immediate first tick that ranrun.io_bound, every test's teardown waited for it, and our GUI suite went from 16 s to 115 s.6. The
userfixture without amain.py. By default it runs./main.pyto find the pages. Our pages are registered by a function against a store, somain_file = ""under[tool.pytest.ini_options]turns that off, and each test registers the pages it needs.7. On macOS,
setAppBadgecan go quiet. Once Chrome attributes the PWA's notifications to the app, the dock badge needs notification permission, and without it nothing shows and nothing fails.An open question
A card is about 25 NiceGUI elements, built on the server and mounted by Vue, so a page of a hundred cards is a couple of thousand elements. On the demo's one vCPU that costs seconds to render, and more seconds to mount in the browser. We have not cut elements per card yet. If you have kept a page of a thousand-plus elements fast without paginating, I'd like to hear how.
All reactions