@betterportal/theme-bootstrap1 10.1.46 → 10.1.48
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bp-resources/SKILL.md +1 -1
- package/bp-resources/page-template.tsx +3 -3
- package/bp-resources/ui-guide.md +1 -1
- package/lib/bp-contracts/org.betterportal.theme.bootstrap1.json +4 -4
- package/lib/schemas/service-betterportal-theme-bootstrap1.json +1 -1
- package/lib/schemas/service-betterportal-theme-bootstrap1.plugin.json +1 -1
- package/package.json +4 -4
- package/lib/plugins/service-betterportal-theme-bootstrap1/assets.cleanup.md +0 -9
package/bp-resources/SKILL.md
CHANGED
|
@@ -8,7 +8,7 @@ description: Build BetterPortal service UI that fits the active Bootstrap1 shell
|
|
|
8
8
|
1. Read the active app's `/llms-api.txt` and this theme's UI guide.
|
|
9
9
|
2. Identify the service view, methods, schemas, required permissions and stable `viewId`.
|
|
10
10
|
3. Render server-side JSX/HTMX for the `bootstrap1` theme. Return only service content, never the shell.
|
|
11
|
-
4.
|
|
11
|
+
4. In renderers, use `ctx.url.route()` for service requests and `ctx.url.uiRoute()` only for GET page navigation. Pass a declared dependency alias as `serviceId` for another service.
|
|
12
12
|
5. Use the framework `BPElement` JSX helper with `ctx` for cross-service or active-shell fragments. Reference the dependency alias/key declared in `betterportal.json`, never a title, service UUID, hostname, or absolute URL. Omit `bp-ok` for direct success insertion; an explicit wrapping `bp-ok` must have exactly one `<template />`.
|
|
13
13
|
6. Prefer Bootstrap components and native HTML controls. Add custom CSS or JavaScript only when the theme and platform primitives cannot express the behavior.
|
|
14
14
|
7. Include loading, empty, validation, forbidden and service-unavailable states.
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
/** @jsxImportSource jsx-htmx */
|
|
2
|
-
import type {
|
|
2
|
+
import type { RegisteredViewRenderer } from "@betterportal/framework";
|
|
3
3
|
|
|
4
|
-
export const render:
|
|
4
|
+
export const render: RegisteredViewRenderer["render"] = (data, ctx) => (
|
|
5
5
|
<section class="container-fluid py-3">
|
|
6
6
|
<div class="d-flex flex-wrap justify-content-between align-items-center gap-2 mb-3">
|
|
7
7
|
<div>
|
|
8
8
|
<h1 class="h3 mb-1">Page title</h1>
|
|
9
9
|
<p class="text-body-secondary mb-0">Explain the task in one sentence.</p>
|
|
10
10
|
</div>
|
|
11
|
-
<a class="btn btn-primary" href={ctx.
|
|
11
|
+
<a class="btn btn-primary" href={ctx.url.uiRoute("example.create") ?? "#"}>Create</a>
|
|
12
12
|
</div>
|
|
13
13
|
<div class="card shadow-sm">
|
|
14
14
|
<div class="card-body">{JSON.stringify(data)}</div>
|
package/bp-resources/ui-guide.md
CHANGED
|
@@ -13,7 +13,7 @@ Use Bootstrap 5 classes and server-rendered JSX/HTMX. BetterPortal service rende
|
|
|
13
13
|
## Forms and mutations
|
|
14
14
|
|
|
15
15
|
- Use real `<form>` elements and labelled controls. Validation text uses `.invalid-feedback` or `.form-text`.
|
|
16
|
-
-
|
|
16
|
+
- In renderers, use `ctx.url.route()` for form actions, HTMX calls, downloads and SSE. `ctx.url.uiRoute()` is only for GET navigation through a mounted page route. For another service, pass its declared dependency alias as `serviceId`; both helpers resolve the active app-mounted provider. Handler equivalents are `ctx.routeUrl()` and `ctx.uiRouteUrl()`.
|
|
17
17
|
- Use `<BPElement ctx={ctx} service="dependency-alias" path="/contract/path" fragment="location.id">` for cross-service UI fragments. `service` is the dependency alias/key declared in `betterportal.json`; never put service titles, UUIDs, hostnames, or absolute URLs in renderer code. The server consumes `ctx` and resolves the active app-mounted provider.
|
|
18
18
|
- Use `service="shell"` and a singular shell fragment id to reuse active-shell UI such as `theme-selector`. Add `bp-loading`, status-specific `bp-status`, and `bp-nok` states as needed. Omit `bp-ok` to insert successful content directly; add it only to wrap success content, with exactly one `<template />`.
|
|
19
19
|
- The renderer's second argument is `ViewRenderContext`. Use its limited `tenant`/`app` presentation projections and `ctx.url` helpers; keep authorization and business data in the handler. Auth navigation fields are view IDs and must be resolved with `ctx.url.uiRoute()`.
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"pluginId": "org.betterportal.theme.bootstrap1",
|
|
5
5
|
"title": "Bootstrap1 Theme",
|
|
6
6
|
"description": "Bootstrap 5 + htmx theme that renders BetterPortal app shells.",
|
|
7
|
-
"version": "10.1.
|
|
7
|
+
"version": "10.1.48",
|
|
8
8
|
"category": "theme",
|
|
9
9
|
"deploymentModes": [
|
|
10
10
|
"self-hosted"
|
|
@@ -249,7 +249,7 @@
|
|
|
249
249
|
"title": "Bootstrap1 UI guide",
|
|
250
250
|
"description": "Layout, component, HTMX, responsive and accessibility rules.",
|
|
251
251
|
"mediaType": "text/markdown; charset=utf-8",
|
|
252
|
-
"content": "# Bootstrap1 UI guide\n\nUse Bootstrap 5 classes and server-rendered JSX/HTMX. BetterPortal service renderers return fragments; the theme owns the shell, navigation, visible URL and global assets.\n\n## Layout\n\n- Render primary content for the `main` slot. Never emit another page shell, `<html>`, `<head>`, sidebar navigation or top bar.\n- Start pages with a semantic heading and a short action row when actions exist.\n- Use `.container-fluid`, Bootstrap grid classes and responsive gaps. Avoid fixed widths except a declared `data-bp-sidebar-width`.\n- Use cards for grouped settings, tables for comparable records and list groups for short navigation or status collections.\n- Keep primary actions on the right of desktop action rows and allow them to wrap on small screens.\n\n## Forms and mutations\n\n- Use real `<form>` elements and labelled controls. Validation text uses `.invalid-feedback` or `.form-text`.\n-
|
|
252
|
+
"content": "# Bootstrap1 UI guide\n\nUse Bootstrap 5 classes and server-rendered JSX/HTMX. BetterPortal service renderers return fragments; the theme owns the shell, navigation, visible URL and global assets.\n\n## Layout\n\n- Render primary content for the `main` slot. Never emit another page shell, `<html>`, `<head>`, sidebar navigation or top bar.\n- Start pages with a semantic heading and a short action row when actions exist.\n- Use `.container-fluid`, Bootstrap grid classes and responsive gaps. Avoid fixed widths except a declared `data-bp-sidebar-width`.\n- Use cards for grouped settings, tables for comparable records and list groups for short navigation or status collections.\n- Keep primary actions on the right of desktop action rows and allow them to wrap on small screens.\n\n## Forms and mutations\n\n- Use real `<form>` elements and labelled controls. Validation text uses `.invalid-feedback` or `.form-text`.\n- In renderers, use `ctx.url.route()` for form actions, HTMX calls, downloads and SSE. `ctx.url.uiRoute()` is only for GET navigation through a mounted page route. For another service, pass its declared dependency alias as `serviceId`; both helpers resolve the active app-mounted provider. Handler equivalents are `ctx.routeUrl()` and `ctx.uiRouteUrl()`.\n- Use `<BPElement ctx={ctx} service=\"dependency-alias\" path=\"/contract/path\" fragment=\"location.id\">` for cross-service UI fragments. `service` is the dependency alias/key declared in `betterportal.json`; never put service titles, UUIDs, hostnames, or absolute URLs in renderer code. The server consumes `ctx` and resolves the active app-mounted provider.\n- Use `service=\"shell\"` and a singular shell fragment id to reuse active-shell UI such as `theme-selector`. Add `bp-loading`, status-specific `bp-status`, and `bp-nok` states as needed. Omit `bp-ok` to insert successful content directly; add it only to wrap success content, with exactly one `<template />`.\n- The renderer's second argument is `ViewRenderContext`. Use its limited `tenant`/`app` presentation projections and `ctx.url` helpers; keep authorization and business data in the handler. Auth navigation fields are view IDs and must be resolved with `ctx.url.uiRoute()`.\n- Mutations should return a useful fragment and emit an `HX-Trigger` event for passive regions that need to reload.\n- Disable buttons only while their own request is active. Keep a visible loading indicator and an error fragment.\n\n## Components\n\n- Buttons: `.btn`, with one obvious `.btn-primary` action per group.\n- Status: Bootstrap badges with text; never communicate state by colour alone.\n- Destructive actions: `.btn-outline-danger` or `.btn-danger`, with confirmation proportional to impact.\n- Side panels: wrap content in `data-bp-sidebar`, add `data-bp-sidebar-title`, and open it with `data-bp-sidebar-open`. The theme converts it to an offcanvas.\n- Modals and offcanvas content may be teleported by the shell. Do not depend on a specific DOM parent after activation.\n\n## Accessibility\n\n- Preserve heading order, visible labels, keyboard focus and native controls.\n- Every icon-only action needs an accessible name.\n- Tables need headers; use a responsive wrapper instead of shrinking text.\n- Focus the first meaningful control when opening a task panel and return focus to its trigger when it closes.\n\n## Avoid\n\n- No SPA framework, client router, iframe, client state store or hardcoded service hostname.\n- No inline copy of Bootstrap or shell JavaScript.\n- No theme-origin mutation URL. Service requests go to service URLs.\n- No custom colour that bypasses the app palette when a Bootstrap semantic token exists.\n"
|
|
253
253
|
},
|
|
254
254
|
{
|
|
255
255
|
"id": "bootstrap1.skill",
|
|
@@ -257,7 +257,7 @@
|
|
|
257
257
|
"title": "Bootstrap1 UI skill",
|
|
258
258
|
"description": "Agent workflow for producing theme-compatible service UI.",
|
|
259
259
|
"mediaType": "text/markdown; charset=utf-8",
|
|
260
|
-
"content": "---\nname: betterportal-bootstrap1-ui\ndescription: Build BetterPortal service UI that fits the active Bootstrap1 shell.\n---\n\n# BetterPortal Bootstrap1 UI\n\n1. Read the active app's `/llms-api.txt` and this theme's UI guide.\n2. Identify the service view, methods, schemas, required permissions and stable `viewId`.\n3. Render server-side JSX/HTMX for the `bootstrap1` theme. Return only service content, never the shell.\n4.
|
|
260
|
+
"content": "---\nname: betterportal-bootstrap1-ui\ndescription: Build BetterPortal service UI that fits the active Bootstrap1 shell.\n---\n\n# BetterPortal Bootstrap1 UI\n\n1. Read the active app's `/llms-api.txt` and this theme's UI guide.\n2. Identify the service view, methods, schemas, required permissions and stable `viewId`.\n3. Render server-side JSX/HTMX for the `bootstrap1` theme. Return only service content, never the shell.\n4. In renderers, use `ctx.url.route()` for service requests and `ctx.url.uiRoute()` only for GET page navigation. Pass a declared dependency alias as `serviceId` for another service.\n5. Use the framework `BPElement` JSX helper with `ctx` for cross-service or active-shell fragments. Reference the dependency alias/key declared in `betterportal.json`, never a title, service UUID, hostname, or absolute URL. Omit `bp-ok` for direct success insertion; an explicit wrapping `bp-ok` must have exactly one `<template />`.\n6. Prefer Bootstrap components and native HTML controls. Add custom CSS or JavaScript only when the theme and platform primitives cannot express the behavior.\n7. Include loading, empty, validation, forbidden and service-unavailable states.\n8. Check keyboard operation, visible labels, heading order and responsive wrapping.\n9. Verify JSON and HTML representations against the published schemas.\n\nFor side tasks, use `data-bp-sidebar` and `data-bp-sidebar-open`. For authenticated downloads, use `hx-download`. For live refresh, emit an `HX-Trigger` event and subscribe with `hx-trigger=\"event from:body\"`.\n"
|
|
261
261
|
},
|
|
262
262
|
{
|
|
263
263
|
"id": "bootstrap1.page-template",
|
|
@@ -266,7 +266,7 @@
|
|
|
266
266
|
"description": "Minimal server-rendered JSX page structure.",
|
|
267
267
|
"mediaType": "text/plain; charset=utf-8",
|
|
268
268
|
"language": "typescript",
|
|
269
|
-
"content": "/** @jsxImportSource jsx-htmx */\nimport type {
|
|
269
|
+
"content": "/** @jsxImportSource jsx-htmx */\nimport type { RegisteredViewRenderer } from \"@betterportal/framework\";\n\nexport const render: RegisteredViewRenderer[\"render\"] = (data, ctx) => (\n <section class=\"container-fluid py-3\">\n <div class=\"d-flex flex-wrap justify-content-between align-items-center gap-2 mb-3\">\n <div>\n <h1 class=\"h3 mb-1\">Page title</h1>\n <p class=\"text-body-secondary mb-0\">Explain the task in one sentence.</p>\n </div>\n <a class=\"btn btn-primary\" href={ctx.url.uiRoute(\"example.create\") ?? \"#\"}>Create</a>\n </div>\n <div class=\"card shadow-sm\">\n <div class=\"card-body\">{JSON.stringify(data)}</div>\n </div>\n </section>\n);\n"
|
|
270
270
|
}
|
|
271
271
|
],
|
|
272
272
|
"shell": {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@betterportal/theme-bootstrap1",
|
|
3
|
-
"version": "10.1.
|
|
3
|
+
"version": "10.1.48",
|
|
4
4
|
"description": "BetterPortal v10 Bootstrap1 theme plugin for Node.js",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "src/index.ts",
|
|
@@ -33,9 +33,9 @@
|
|
|
33
33
|
"typescript": "^6.0.3"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@betterportal/framework": "10.1.
|
|
37
|
-
"@betterportal/plugin-bsb": "10.1.
|
|
38
|
-
"@betterportal/theme-runtime": "10.1.
|
|
36
|
+
"@betterportal/framework": "10.1.48",
|
|
37
|
+
"@betterportal/plugin-bsb": "10.1.48",
|
|
38
|
+
"@betterportal/theme-runtime": "10.1.48",
|
|
39
39
|
"@bsb/base": "^9.6.60",
|
|
40
40
|
"anyvali": "^1.0.6",
|
|
41
41
|
"bootstrap": "^5.3.8",
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
# Bootstrap1 Asset Ownership
|
|
2
|
-
|
|
3
|
-
The browser-runtime migration is complete.
|
|
4
|
-
|
|
5
|
-
- `@betterportal/theme-runtime` owns HTMX, service URL rewriting, BP headers, preload, request lifecycle, route chrome state, history, SSE, downloads, auth failures, and background fragments.
|
|
6
|
-
- `Bootstrap1AdapterSource` is typed TSX produced by `js()` and contains presentation hooks only.
|
|
7
|
-
- Bootstrap1 owns Bootstrap assets, modal/offcanvas lifecycle, component initialization, error/loading presentation, and CSS for `data-bp-chrome-*`.
|
|
8
|
-
- Route chrome is generic presentation state. It never implies authentication.
|
|
9
|
-
- Theme adapters must not register duplicate HTMX lifecycle listeners.
|