Clients
Structure of a client and the options of pankosmia_metadata.json
Table of Contents
What is a client
A client is a web app (React, built with Vite) served by the Pankosmia server at /clients/<name>. The dashboard, the settings and every content handler (core-contenthandler_*) are clients. A product includes a client by listing it in CLIENTn in app_config.env (and so in libClients of buildSpec.json). The build then copies its build/ output, package.json, pankosmia_metadata.json and storage_id.json (when it exists) into lib/clients/<repository name>.
Structure of a client
| Item | What it does |
|---|---|
pankosmia_metadata.json | Declares the client to the server and the other clients (see below). |
package.json | Dependencies and scripts. homepage is /clients/<name>. |
vite.config.js | Vite setup: base is /clients/<name>/, the dev server has its own port, and /api is proxied to the Pankosmia server (port 19119). |
index.html, public/ | Page shell and static files. |
src/index.jsx | Entry point. It wraps the app in the RCL SpSpa component with requireNet, titleKey (pages:<id>:title) and currentId (the metadata id). |
src/App.jsx, src/components/ | The pages and components of the client. |
build/ | Output of vite build, the folder the server actually serves. |
storage_id.json | A generated UUID of the client (written by scripts/write-storage-id.js before start, dev and build), when the client uses it. |
pankosmia_metadata.json
This file is the identity card of a client. The server reads it to list the client (/api/list-clients) and to publish what it can do (/api/client-interfaces), and the translations it contains feed the i18n tree. Fields:
| Field | Type | What it does |
|---|---|---|
id | string | Unique identifier of the client. It is the section name in the i18n tree (pages:<id>:...), the currentId given to SpSpa, and it identifies the client in the menu. |
require.net | boolean | When true, the client needs internet. Its menu entry is disabled while the app is offline, and a page using requireNet shows a “no entry if offline” message. |
require.debug | boolean | When true, the client is a developer tool: it is listed in the Debug section of the menu, which only appears when debug mode is on. When false or absent, the client is in the normal menu. |
minServerVersion | string | Minimum server version (for example 0.20.3). The app does not run if the server is older than the minimum required by a client. |
exclude_from_menu | boolean | When true, the client is not listed in the menu of the header. It is still reachable by its URL and from links of other clients. |
exclude_from_dashboard | boolean | When true, the client is removed from the dashboard, for example its entry in the Create button. |
i18n | object | Translations of the client. Each key is a name with one text per language code. title and summary are conventional. See the i18n page. |
endpoints | object | The actions the client offers to other clients, per document type (see below). |
Examples
The settings client is hidden from both the menu and the dashboard:
{
"id": "core-settings",
"require": { "net": false },
"minServerVersion": "0.20.3",
"exclude_from_menu": true,
"exclude_from_dashboard": true,
"i18n": {
"title": { "en": "Settings", "fr": "Paramètres" }
}
}
A content handler for developers only (require.debug), shown in the Debug section of the menu:
{
"id": "contenthandler-template",
"require": { "net": false, "debug": true },
"i18n": {
"title": { "en": "contenthandler-template" }
}
}
endpoints
Content handlers use endpoints to tell the other clients what they can do with a type of document (a flavor such as textTranslation). Other clients read it from /api/client-interfaces and build their menus from it, so a handler does not need to be known by name. Each action is a list of entries (edit is a single entry) with these fields:
doc: a developer description of the entry.label: an i18n key (for examplepages:core-contenthandler_obs:create_content_obs) shown to the user.url: the page of the client to open, relative to/clients/<id>/.placeHolders: documents the variables used inurl, such as%%REPO_PATH%%, replaced by the path of the repository in<X>/<Y>/<Z>format.subMenu: only forexport, groups the entries by format (usfm,pdf…).
Actions in use:
| Action | Used for |
|---|---|
create_document | Entries of the Create button of the dashboard. |
edit | The client that opens a repository of this document type. |
new_book, import_book, delete_book | Actions on a repository, offered in the Content client. |
export | Export formats of a repository, per format in subMenu. |
about_repo, manager, initDocument, importContent | Other entries read by the dashboard. |
download_resources | Page used to download resources (remote repos client). |
{
"id": "core-contenthandler_obs",
"endpoints": {
"textStories": {
"create_document": [
{
"doc": "Create a document for OBS",
"label": "pages:core-contenthandler_obs:create_content_obs",
"url": "/createDocument/obsContent"
}
],
"edit": {
"doc": "main page for workspace",
"label": "pages:core-client-workspace:main",
"url": "core-local-workspace#"
}
}
}
}