S

Knowledge Pack Files

SideButton Dashboard Knowledge Pack Files

Browse the source files that power the SideButton Dashboard MCP server knowledge pack.

Available free v0.4.0 Browser
$ sidebutton install sidebutton.local
Download ZIP
library/_skill.md
14.2 KB

What This Is

The Library page is the skill pack discovery and installation interface. It shows installed packs from external publishers, lets users connect to skill pack registries (publishers), browse available packs from those registries, and install/update packs. It's the entry point for adding new skill packs to SideButton.

URL Patterns

ViewURLNotes
Library/librarySingle page β€” all state is component-local

Legacy redirect: /workflows β†’ /library, /workflows/{id} β†’ /library

Page Structure

+--[Header: "Library" + Refresh button]--------------------+
|                                                           |
|  [Publisher Selector Bar]                                 |
|    Registry <select> "Publisher:" + Search input          |
|                                                           |
|  === Available Skill Packs ===                            |
|  [Pack Card: πŸ“¦ icon + title + domainΒ·version + desc]    |
|    Install / Installed+Manage / Update+Manage buttons     |
|                                                           |
|  [Empty: "No skill packs found..."] (when none match)    |
|                                                           |
|  === INSTALLED (OTHER PUBLISHERS) ===                     |
|  [Pack Card: πŸ“¦ icon + title + domainΒ·version]            |
|    "Installed" badge + "Manage" button                    |
|                                                           |
|  === PUBLISHERS ===                                       |
|  [Publisher Row: name + type badge + status]              |
|    "Remove" button                                        |
|  [+ Add Publisher] button                                 |
|    [Expanded: URL input + Name input + Add/Cancel]        |
|                                                           |
|  [Empty State: "No Publishers Connected"] (no registries) |
|    description + "+ Add Publisher" button                 |
+-----------------------------------------------------------+

Key Elements

Header

ElementSelectorNotes
Page titleh1 / heading "Library"H1 in header bar
Refresh button.btn.btn-ghost in headerIcon-only SVG button. Calls loadData() β€” reloads registries + catalog

Publisher Selector Bar (.publisher-bar)

ElementSelectorNotes
Publisher label + dropdownlabel:has-text("Publisher:") selectNative <select>. Options show "{name} ({packCount} packs)". Auto-selects first on load
Search input.search-box input[type="text"]Placeholder: "Search skill packs...". Filters by name, title, description, domain (case-insensitive)

Catalog Section β€” Available Packs

ElementSelectorNotes
Section headingh2:has-text("Available Skill Packs")Uppercase via CSS
Pack card.catalog-cardOne per pack in filtered results
Pack icon.catalog-iconAlways πŸ“¦ emoji
Pack title.catalog-header h3pack.title or falls back to pack.name
Pack meta.catalog-metaFormat: "{domain} Β· v{version}"
Pack description.catalog-descOptional β€” only shown if pack.description is set
Install buttonbutton:has-text("Install") / .btn.btn-primary.btn-smShown when pack.installed is false. Disabled while installing
Installing statesame button, text "Installing..."Shown when installingDomain === pack.domain. Button is disabled
Installed badge.installed-badgeGreen pill badge, text "Installed". Shown when installed and version matches
Update buttonbutton:has-text("Update to v") / .btn.btn-secondary.btn-smShown when pack.installed && pack.installedVersion !== pack.version. Disabled while installing
Manage buttonbutton:has-text("Manage") / .btn.btn-ghost.btn-smShown alongside Installed badge or Update button. Navigates to Skills page
Empty catalog.empty-card p"No skill packs found matching "{query}"." or "No skill packs found in this registry."

Loading States

ElementSelectorNotes
Page loading.loading:has-text("Loading library...")Shown while initial loadData() runs. Replaces all content
Catalog loading.loading:has-text("Loading catalog...")Shown inside catalog area while loadCatalog() runs after registry switch

Installed (Other Publishers) Section

ElementSelectorNotes
Section headingh2:has-text("Installed (Other Publishers)")Uppercase via CSS
Pack card.catalog-cardSame card style as catalog. Has icon, title, meta line
Installed badge.installed-badgeGreen pill, "Installed"
Manage buttonbutton:has-text("Manage") / .btn.btn-ghost.btn-smNavigates to Skills page

Publishers Section

ElementSelectorNotes
Section headingh2:has-text("Publishers")Uppercase via CSS. Always visible (even when no registries)
Publisher row.publisher-rowOne per registry
Publisher name.pub-nameRegistry display name
Type badge.pub-typeRegistry type string, pill style
Status.pub-status"Connected" or "Disabled" (driven by reg.enabled)
Remove buttonbutton:has-text("Remove") / .btn.btn-ghost.btn-smTriggers confirm() dialog before removal
Add Publisher buttonbutton:has-text("+ Add Publisher") / .btn.btn-secondary.btn-sm.add-pub-btnShown when form is hidden
URL input.add-pub-form input[placeholder="Registry URL or path"]First input in add form
Name input.add-pub-form input[placeholder="Name (optional)"]Second input in add form
Add button.add-pub-actions button:has-text("Add") / .btn.btn-primary.btn-smSubmits new publisher
Cancel button.add-pub-actions button:has-text("Cancel") / .btn.btn-ghost.btn-smCollapses add form without saving

Empty State (No Publishers)

ElementSelectorNotes
Heading.empty-card h3:has-text("No Publishers Connected")Shown only when registries.length === 0
Description.empty-card p"Add a skill pack registry to browse and install skill packs."
Add Publisher button.empty-card button:has-text("+ Add Publisher") / .btn.btn-primarySets showAddPublisher = true, scrolls to Publishers section

Data Model

Registry (Publisher)

FieldTypeNotes
namestringRegistry display name. Also used as the identifier for selectedRegistry state
urlstringRegistry URL
typestringRegistry type label
enabledbooleantrue β†’ "Connected", false β†’ "Disabled"
packCountnumberOptional. Shown in dropdown option as "({packCount} packs)". Defaults to 0 if missing

Catalog Pack (CatalogPack)

FieldTypeNotes
namestringPack identifier
titlestringDisplay name (falls back to name in UI)
domainstringDomain pattern. Used as keyed identifier in lists
versionstringSemver β€” current version in registry
descriptionstringOptional. Shown as catalog-desc when present
pathstringPath passed to installSkillPack(pack.path) for install/update
installedbooleanWhether this pack is currently installed
installedVersionstringInstalled version. Compared to version to determine if update is available

Installed Pack (InstalledPack)

Used for the "Installed (Other Publishers)" section β€” packs in $skillPacks store that are not in the current registry catalog.

FieldTypeNotes
namestringPack identifier
titlestringDisplay name
domainstringDomain pattern
versionstringInstalled version

Component State

State VariableTypeInitialDescription
isLoadingbooleantruePage-level loading β€” true during initial loadData()
registriesPublisher[][]All connected registries from fetchRegistries()
selectedRegistrystring''Name of the currently selected registry
catalogPacksCatalogPack[][]Packs from the selected registry's catalog
catalogNamestring''Display name of the current catalog
searchQuerystring''Current search filter text
isLoadingCatalogbooleanfalseTrue while fetchRegistryCatalog() is running
showAddPublisherbooleanfalseWhether the add-publisher form is expanded
newPublisherUrlstring''URL input value in add-publisher form
newPublisherNamestring''Name input value in add-publisher form
installingDomainstring|nullnullDomain of the pack currently being installed. Only one at a time

Derived State

DerivedSourceNotes
filteredPackscatalogPacks + searchQueryCase-insensitive filter across name, title, description, domain
installedPacks$skillPacks store + catalogPacksPacks in store whose domain is NOT present in current catalog β€” shown in "Other Publishers" section

UI States

StateTriggerVisual
Page loadingInitial mount.loading "Loading library..." covers content area
Catalog loadingRegistry selection change.loading "Loading catalog..." in catalog area
Default β€” publishers existLoad complete, registries presentPublisher bar + catalog visible
No publishersregistries.length === 0.empty-card "No Publishers Connected" shown below Publishers section
Search filteredNon-empty searchQueryCatalog filtered; empty card shown if no matches with query in message
Empty registryRegistry has 0 packs.empty-card "No skill packs found in this registry."
InstallinginstallingDomain setInstall button text β†’ "Installing...", button disabled
Update availablepack.installed && installedVersion !== versionbtn-secondary "Update to v{version}" replaces "Installed" badge
Add publisher formshowAddPublisher = trueURL + Name inputs replace "+ Add Publisher" button
Error (toast)loadCatalog, install, add/remove publisher failshowToast(message, "error") β€” transient toast, no persistent banner

API Calls

ActionAPIPayload / Notes
Load registriesfetchRegistries()GET /api/registries
Load catalogfetchRegistryCatalog(registryName)GET /api/registries/{name}/catalog. Returns { name, packs }
Load installed packsfetchSkillPacks()GET /api/skills
Install / UpdateinstallSkillPack(pack.path)POST /api/skills/install with pack path. Same endpoint for both install and update
Add publisheraddRegistry(url, name?)POST /api/registries
Remove publisherremoveRegistry(name)Uses registry name as identifier

Common Tasks

  1. Browse available packs: Select registry from dropdown β†’ catalog loads β†’ browse pack cards
  2. Search packs: Type in search input β†’ filters by name/title/description/domain (case-insensitive)
  3. Install skill pack: Find pack β†’ click "Install" β†’ button shows "Installing..." β†’ toast on success
  4. Update skill pack: Find pack with "Update to v{version}" button β†’ click it β†’ same install flow
  5. Manage installed pack: Click "Manage" β†’ navigates to Skills page
  6. Add publisher: Click "+ Add Publisher" β†’ enter "Registry URL or path" (+ optional "Name (optional)") β†’ click "Add" β†’ page reloads with new registry
  7. Remove publisher: Click "Remove" next to publisher β†’ native confirm() dialog β†’ removed on confirm, reinstall on cancel

Gotchas

  • Search placeholder is "Search skill packs..." β€” not "Search packs...". Use this exact string for placeholder assertions.
  • Registry dropdown option format includes pack count: "{name} ({packCount} packs)" β€” packCount may be 0 if missing.
  • selectedRegistry is a name string, not an object: The <select> value is reg.name. Catalog is fetched by name, not URL.
  • Install uses pack.path, not pack.source: The field passed to installSkillPack() is pack.path.
  • Update and Install use the same handler: handleInstall(pack) handles both. Install button is btn-primary, Update button is btn-secondary.
  • installingDomain blocks only matching domain: The disabled check is installingDomain === pack.domain. Other packs remain clickable.
  • No persistent error banner: Errors use showToast() β€” transient, no static .error element in DOM. The original error string state documented elsewhere does not exist in this component.
  • Remove uses browser confirm(): Native dialog with exact text Remove publisher "{name}"? This will also uninstall its packs. β€” automation must handle native confirms.
  • Publishers section always renders: The <section class="publishers"> is always shown (even with 0 registries), with the empty-card appearing below it when registries.length === 0.
  • "Other Publishers" logic is derived: A pack appears in this section if its domain is not in the current catalogPacks. Switching registries changes which packs appear here.
  • No explicit error state in component: Unlike prior assumption, there is no error string or error banner. All errors surface via the global showToast store.
  • Add form URL input placeholder: "Registry URL or path" β€” accepts both HTTP URLs and local filesystem paths.
  • Page reload after add/remove: Both handleAddPublisher and handleRemovePublisher call loadData() on success, re-fetching all registries and resetting catalog to first registry.
  • SPA 404 on direct navigation: /library returns 404 JSON if accessed directly β€” must navigate via the SideButton shell.