@skyglide.com/catalog
Web components for Skyglide's web surfaces: the member portal, the operator console and later the venue owner portal. Built with Lit on @design.estate/dees-catalog and its theme tokens, in English and German.
The elements are presentational. The host brings dees-catalog's app shell, the data and the I/O: it passes view models and handles events. No element fetches, stores or authorizes anything, and none decides what the controller decides.
Issue Reporting and Security
For reporting bugs, issues, or security vulnerabilities, please visit community.foss.global/. This is the central community hub for all issue reporting. Developers who sign and comply with our contribution agreement and go through identification can also get a code.foss.global/ account to submit Pull Requests directly.
Install
pnpm add @skyglide.com/catalog @design.estate/dees-catalog @design.estate/dees-element @design.estate/dees-domtools
The dees packages are peer dependencies: the host provides them, so a page holds one copy of each and every element registers once.
import '@skyglide.com/catalog';
import { html } from '@design.estate/dees-element';
html`<sky-ops-site-table
.sites=${sites}
@sky-site-open=${(event) => openRouter(event.detail.siteId)}
></sky-ops-site-table>`;
Elements
Every view model is exported from the package root, with the detail type of every event. Times are epoch milliseconds, rates bits per second and money whole minor units; the elements write them in the reader's language. Text a router or the controller wrote (a model, a release, a check's value and reason) is shown as passed. A value the host does not have shows as a dash, said as "Not available" to assistive technology. Events bubble and are composed.
Elements that show relative times take now (epoch milliseconds), the moment they count from: the time of rendering when unset.
| Element | What it shows |
|---|---|
sky-mark |
The brand mark, optionally with the wordmark. |
sky-router-check |
What a router agent reported, with a summary chip. |
sky-ops-site-table |
The operator console's table of venue sites. |
sky-ops-home-router-table |
The operator console's table of members' home routers. |
sky-ops-router-decision |
The "What the controller sends" card of a venue router. |
sky-device-list |
The member's devices, with rename and remove. |
sky-wifi-password |
The member's Wi-Fi password, with reveal, copy and a WIFI: QR code. |
sky-device-approval |
Approving a device's sign-in by its user code. |
sky-exit-picker |
The choice of the internet exit. |
sky-membership-card |
Where a membership stands, and the next step. |
sky-mark
| Property | Type | Meaning |
|---|---|---|
size |
number |
The mark's side in CSS pixels, 28 by default. |
wordmark |
boolean |
The lowercase wordmark follows the mark. |
decorative |
boolean |
Hidden from assistive technology, for a mark beside the product's name. |
The mark is an image asset with its own fixed colours, the one place the Skyglide cyan appears. It is named "Skyglide"; with wordmark the visible word names it.
sky-router-check
| Property | Type | Meaning |
|---|---|---|
items |
ISkyCheckItem[] |
The agent's items: id, status (ok, limited, missing), value?, reason?, in the agent's order. |
outcome |
TSkyCheckOutcome |
The controller's verdict, in the operator API's names. |
checkedAt, reportedAt |
number |
When the router checked and when the controller got the report. |
chip |
boolean |
Draws the summary chip alone, for a table row or a page heading. |
interactive |
boolean |
Makes the chip a button. |
routerId |
string |
What the button reports. |
The labels come from the catalogue and match the agents' LuCI pages: OpenWrt release, Firewall, Kernel WireGuard, Wi-Fi (hostapd), Per-member Wi-Fi passwords, Encrypted guest network (OWE), Radios, Wired venue networks, Memory, Flash, Captive portal (openNDS). An id the catalogue does not know shows as it is.
outcome |
Router | Chip |
|---|---|---|
allowed_owe |
venue | Ready |
allowed_open |
venue | Open guest network |
refused |
venue | Refused: the items with status missing |
unchecked |
venue, home | Not reported yet |
ready |
home | Ready |
limited |
home | Limited: the items with status limited or missing, with their values |
missing |
home | Missing: the items with status missing |
The element decides nothing: the controller's rule (any missing item refuses the venue role, the guest network uses OWE only where owe is ok, a home router's check is never enforced) stays with the controller. Where the host has only the refusal's missing item ids, it passes them as { id, status: 'missing' }.
Event: sky-router-open (ISkyRouterOpenDetail: routerId), from an interactive chip.
sky-ops-site-table
| Property | Type | Meaning |
|---|---|---|
sites |
ISkySite[] |
The rows, in the host's order. |
heading |
string |
The table's title; the catalogue's "Sites" while unset, none when empty. |
ISkySite: id, name, routerModel?, openwrt? (as reported, OpenWrt 24.10.8), target?, keyRegisteredAt? (shown while no model is reported), state (healthy, pending, refused, unchecked), checkOutcome, checkItems?, members?, guests?, trafficInBps?, trafficOutBps?, configuration? (ISkyConfigVersion: desired?, acked?, withheld?), heartbeatAt?.
Columns: site, state, router check, members and guests, traffic, configuration, heartbeat. Below 1140px of its own width the heartbeat folds under the state; below 900px everything stacks in one column. The chip, a click on the row and its context menu action report sky-site-open (ISkySiteOpenDetail: siteId).
sky-ops-home-router-table
| Property | Type | Meaning |
|---|---|---|
routers |
ISkyHomeRouter[] |
The rows, in the host's order. |
heading |
string |
The table's title; the catalogue's "Home routers" while unset, none when empty. |
ISkyHomeRouter: id, member, name, routerModel?, openwrt?, target?, checkOutcome, checkItems?, tunnel? (up, down, connecting, unpaired, none), lanPrefix?, lanShared?, lastReportAt?.
The table's info button says that a home router's check is shown, never enforced. Below 1140px of its own width the last report folds under the tunnel; below 900px everything stacks in one column. The chip, a click on the row and its context menu action report sky-home-router-open (ISkyHomeRouterOpenDetail: routerId).
sky-ops-router-decision
| Property | Type | Meaning |
|---|---|---|
decision |
ISkyRouterDecision |
role (allowed, refused, waiting), memberNetworks?, guestNetwork (owe, open, none), configuration?, tunnel, handshakeAt?. |
Shows what the host passes. How the controller decides stands behind the card's info button. No events.
sky-device-list
| Property | Type | Meaning |
|---|---|---|
devices |
ISkyDevice[] |
The rows, in the host's order. |
ISkyDevice: id, name, platform (mainapp's TPlatform), dnsName? (absent where no domain is configured), address?, presence (mainapp's TPresence, passed through; at a location it shows site_name, else site), lastSeenAt? (milliseconds; mainapp's last_seen_at is in seconds), thisDevice?.
A device at a location or away is seen now; an offline one shows when it was last seen. Below 760px of its own width everything stacks in one column. Rename and remove are row actions the host answers: sky-device-rename and sky-device-remove (ISkyDeviceActionDetail: deviceId). The list changes nothing itself.
sky-wifi-password
| Property | Type | Meaning |
|---|---|---|
ssid |
string |
The network, skyglide.com by default. |
password |
string |
The member's password. A secret: it has no attribute. |
The password stays hidden until revealed; the mask does not show its length. The QR code is drawn by dees-qrcode from skyWifiQrPayload(ssid, password), exported from the package root. Events: sky-wifi-reveal (ISkyWifiRevealDetail: revealed) and sky-wifi-copy (ISkyWifiCopyDetail: copied, false when the clipboard refused).
sky-device-approval
| Property | Type | Meaning |
|---|---|---|
deviceName, platform, client |
Which device asks, and with which client (service, cli, app). |
|
userCode |
string |
The code the device shows. |
place |
string |
Where it asks from, in the host's words. |
network |
string |
The name of the member's network. |
askedAt, expiresAt |
number |
When it asked and when the code stops working. |
state |
TSkySignInState |
pending, approved, denied or expired; the host sets it from the controller's answer. |
errorText |
string |
Why the host's request failed, in the host's words. |
Confirm and Deny report sky-signin-approve and sky-signin-deny (ISkySignInDecisionDetail: userCode). The pressed button stays busy until the host sets state or errorText.
sky-exit-picker
| Property | Type | Meaning |
|---|---|---|
choices |
ISkyExitChoice[] |
key, kind (cloud, home_router, computer), name? (the cloud exit is named by the catalogue), applied. |
selected |
string |
The key of the chosen exit. |
Each exit says what it means and whether it is applied or "Recorded, not routed yet". The choice is the host's: a press reports sky-exit-change (ISkyExitChangeDetail: key), and the picker shows selected until the host changes it.
sky-membership-card
| Property | Type | Meaning |
|---|---|---|
status |
TSkyMembershipStatus |
active, grace, restricted, cancelled or released. |
paidUntil |
number |
The next renewal while active, the last day while cancelled. |
graceUntil |
number |
While in grace: when access is restricted unless PayPal collects. |
releaseAt |
number |
While restricted: when the network is released. |
price |
ISkyMoney |
The monthly price, VAT included: { minor, currency }. |
status |
Next step (sky-membership-action, ISkyMembershipActionDetail: action) |
|---|---|
active |
cancel |
grace |
update-payment |
restricted, cancelled, released |
renew |
Languages
Every word comes from one typed @push.rocks/smarti18n catalogue, skyMessages (namespace @skyglide.com/catalog). English is the source and German is complete. The German says "du" to the reader, as Skyglide's signup pages do. A page provides its language once, and every element renders again when it changes:
import { createI18n } from '@push.rocks/smarti18n';
import { provideI18n } from '@design.estate/dees-element';
import { skyMessages } from '@skyglide.com/catalog';
const i18n = createI18n({ locale: 'de-DE' });
provideI18n(document.documentElement, i18n, { reflect: true });
// a word of your own, for one language
i18n.override(skyMessages, 'de', { 'wifi.heading': 'Dein Skyglide-WLAN' });
Without a provider the elements speak English.
Design tokens
Styling uses dees-catalog's tokens only (themeDefaultStyles, --dees-*). No element declares its own colour, type size, spacing, radius or shadow, calls cssManager.bdTheme() or redefines a --dees-* token. Status uses TTone and dees badges, always with a glyph and words.
dees-catalog's colours take no overrides, so the accent stays its blue. The one exception is the brand mark's fixed colours, named with their reason in scripts/design-token-allowlist.json.
scripts/check-design-tokens.cjs holds the elements to this, and scripts/check-literal-ratchet.cjs holds them to no English literals. pnpm test runs both.
Develop
pnpm install
pnpm run watch # the workbench: every element's demo and the demo pages
pnpm test # build, guards, then the browser tests
The demo pages in the workbench show the operator console's Sites and Router pages and the member portal's Overview and Devices pages in dees-catalog's app shell, on sample data.
License and Legal Information
This repository contains open-source code that is licensed under the MIT License. A copy of the MIT License can be found in the license file within this repository.
Please note: The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file.
Trademarks
This project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH and are not included within the scope of the MIT license granted herein. Use of these trademarks must comply with Task Venture Capital GmbH's Trademark Guidelines, and any usage must be approved in writing by Task Venture Capital GmbH.
Company Information
Task Venture Capital GmbH Registered at District court Bremen HRB 35230 HB, Germany
For any legal inquiries or if you require further information, please contact us via email at hello@task.vc.
By using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.