About csLineInvoker Web User Interface
A unified dashboard orchestrating multiple command-line and infrastructure services through an iframe-based architecture. Provides seamless integration between csLineInvoker (command execution), Airflow (workflow orchestration), and Grafana (metrics visualization) through a centralized Gatsby-based dashboard.
Built with Gatsby 5, React 18, Tailwind CSS 3.4.17, PostMessage API, and a Pub/Sub event system for cross-service communication.
- Project Overview
- Configuration
- Development Setup and Usage
- Architecture
- Orchestration Layer
- Service Integration
- Implementation Status
- Development Guide
- UI Enhancements
- Deployment Considerations
- Appendix
The BISOS Command Service CLI Web UI is a unified dashboard for managing, monitoring, and orchestrating multiple command-line services and infrastructure tools. It provides a single point of access to:
- csLineInvoker (WebCliGui): Execute and monitor command-line tasks across servers
- Airflow: Schedule and orchestrate complex workflows
- Grafana: Visualize and monitor system metrics
The vision is to create a cohesive ecosystem where these independent services work together seamlessly through an orchestration layer.
Instead of merging multiple frontend projects, we take a modular iframe orchestration approach:
- Independent Services: Each service (csLineInvoker, Airflow, Grafana) remains independent
- Maintains its own codebase, dependencies, technology stack
- Runs on separate ports (25002, 8080, 3000)
- Can be updated/deployed independently
- Orchestration Host: Gatsby-based dashboard (csLineInvoker-webUi) serves as the orchestrator
- Runs on port 25001
- Embeds each service in its own iframe
- Manages cross-service communication via PostMessage API
- Trusted Ecosystem: All services are internal, under user control
- No signature validation needed
- Simplified PostMessage security model
- Focus on functional communication, not security perimeter
- Gatsby 5.x: Static site generator for dashboard
- React 18.x: Component framework
- Tailwind CSS 3.4.17: Utility-first styling
- PostMessage API: Cross-iframe communication
- Pub/Sub Pattern: Message bus for event routing
- Node.js 22.21.1: Runtime environment
- Environment Variables: Runtime configuration via .env files
Port numbers and domains for this application are assigned through bisos.banna (BISOS Assigned Names and Numbers Authority).
To obation the relevant port numbers:
pip install bisos.banna
pipx install bisos.banna
bannaInfo.cs -i bannaTcpPortsList | pyLiteralToBash.cs -i stdinToBlackRelevant assigned port numbers are:
{
"csPlayerPerf_dev": TcpPortNuInfo(
portNu=23501,
portName="csPlayerPerf_dev",
portDescription="Backend API performer service (development)",
),
"csPlayerUi_dev": TcpPortNuInfo(
portNu=25001,
portName="csPlayerUi_dev",
portDescription="Reveal Gatsby site wrapping csLineInvoker and others (development)",
),
"csLineInvoker_dev": TcpPortNuInfo(
portNu=25002,
portName="csLineInvoker_dev",
portDescription="Line invoker service (development)",
),
}Relevant assigned .here domains as they apear in /etc/hosts are:
127.0.0.100 csPlayerPerf.here 127.0.0.101 csLineInvoker.here 127.0.0.102 csPlayerUi.here
Service URLs are configured via environment variables using Gatsby’s built-in dotenv support. This allows different URLs for development and production without code changes.
Gatsby automatically loads environment-specific files:
.env.development- Used by `npm run develop` (development mode).env.production- Used by `npm run build` (production mode).env- Fallback if environment-specific file not found
All service URL variables use the GATSBY_ prefix (required by Gatsby to expose variables to the browser):
GATSBY_CSLINE_INV_URL=http://csLineInvoker.here # Invoker: Command submission UI
GATSBY_CSPLAYER_PERF_URL=http://csLineInvokerPerf.here # Performer: Command execution engine
GATSBY_AIRFLOW_URL=http://localhost:8080 # Workflow orchestration
GATSBY_GRAFANA_URL=http://localhost:3000 # Metrics visualization**Development (.env.development):**
GATSBY_CSLINE_INV_URL=http://localhost:25002
GATSBY_CSPLAYER_PERF_URL=http://localhost:23501
GATSBY_AIRFLOW_URL=http://localhost:8080
GATSBY_GRAFANA_URL=http://localhost:3000**Production (.env.production):**
GATSBY_CSLINE_INV_URL=http://csLineInvoker.here
GATSBY_CSPLAYER_PERF_URL=http://csPlayerPerf.here
GATSBY_AIRFLOW_URL=http://localhost:8080
GATSBY_GRAFANA_URL=http://localhost:3000Location: src/utils/serviceConfig.js
The configuration utility centralizes URL management and provides fallback defaults:
import { getServiceUrl } from "../utils/serviceConfig"
// Get specific service URL
const cslineInvokerUrl = getServiceUrl('cslineInvoker')
const csplayerPerformerUrl = getServiceUrl('csplayerPerformer')
const airflowUrl = getServiceUrl('airflow')
const grafanaUrl = getServiceUrl('grafana')
// Debug: view all URLs in browser console
window.__serviceUrls()All iframe pages now use the service configuration utility:
src/pages/csPlayer.js- Invoker UI (cslineInvoker)src/pages/csLineInvokerBackEnd.js- Performer API (csplayerPerformer)src/pages/modPlayerFacter.js- Invoker variant (cslineInvoker)src/pages/modPlayerSoncli.js- Invoker variant (cslineInvoker)src/pages/airflow.js- Airflow servicesrc/pages/grafana.js- Grafana service
The csLineInvoker ecosystem uses the Invoker/Performer abstraction pattern from RPC and Web Services architecture:
- CSLINE_INV (Invoker): Client-facing UI that builds and invokes commands
- Narrow scope: command-line focused
- User interface for command building and submission
- Multiple instances possible (modPlayerFacter, modPlayerSoncli, csLineInvoker)
- CSPLAYER_PERF (Performer): Execution engine with broader scope
- Server-side command executor
- Serves multiple invokers and clients
- Single point of command execution
- Can be scaled independently from invokers
┌──────────────────────────────────────────────────────────────┐
│ CSPLAYER_PERF (Performer) │
│ Single execution engine with broader scope │
│ │
│ Executes commands for: │
│ - CSLINE_INV (current invoker) │
│ - Other invokers (potential) │
│ - Direct API calls │
│ - Batch operations │
└──────────────────────────────────────────────────────────────┘
▲ ▲
│ │
┌────┴──────────┐ ┌─────────┴────────┐
│ CSLINE_INV │ │ Other Invokers │
│ (narrow │ │ (potential) │
│ scope) │ │ │
└───────────────┘ └──────────────────┘
mkdir -p /bisos/git/bxRepos/cliGui
git clone git@github:cliGui/webCliGui.git
cd /bisos/git/bxRepos/cliGui/webCliGui/server
# Set things up and enable the libraries
python manage.py runserver 23001
# visit http://localhost:23501/admincd /bisos/git/bxRepos/cliGui/webCliGui
npm run watch
# visit http://localhost:25002mkdir -p /bisos/git/bxRepos/bisos-web
git clone git@github:bisos-web/csPlayer-webUi
cd /bisos/git/bxRepos/bisos-web/csPlayer-webUi
# Set things up
npm run develop
# visit http://localhost:25001From within the csPlayer app you should now be able to navigate to csLineInvoker and csPlayerPerf.
┌──────────────────────────────────────────────────────────────┐
│ BISOS Dashboard (Gatsby) │
│ localhost:25001 │
│ │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ Orchestration Layer │ │
│ │ │ │
│ │ ┌──────────────────────────────────────────────────┐ │ │
│ │ │ Message Bus (messageBus.js) │ │ │
│ │ │ - Central Pub/Sub system │ │ │
│ │ │ - Routes events between services │ │ │
│ │ │ - Maintains event history │ │ │
│ │ │ - Exposed via window.__messageBus │ │ │
│ │ └──────────────────────────────────────────────────┘ │ │
│ │ ▲ ▲ ▲ │ │
│ │ ┌────────┴──────────┼──────────┴────────────────────┐ │ │
│ │ │ Iframe Adapter (iframeAdapter.js) │ │ │
│ │ │ - PostMessage API handler │ │ │
│ │ │ - Iframe registration & lifecycle │ │ │
│ │ │ - Message routing to bus │ │ │
│ │ │ - Exposed via window.__iframeAdapter │ │ │
│ │ └────────┬──────────┬──────────┬────────────────────┘ │ │
│ └───────────┼──────────┼──────────┼────────────────────────┘ │
│ │ │ │ │
└──────────────┼──────────┼──────────┼──────────────────────────┘
│ │ │
┌──────▼──┐ ┌──────▼──┐ ┌──▼──────┐
│csLineInvoker │ │ Airflow │ │ Grafana │
│ iframe │ │ iframe │ │ iframe │
│ :25002 │ │ :8080 │ │ :3000 │
└─────────┘ └─────────┘ └─────────┘
| Service | Port | Role | Technology |
|---|---|---|---|
| csLineInvoker | 25002 | Command execution & monitoring | React + Django |
| Airflow | 8080 | Workflow orchestration | Python + Flask |
| Grafana | 3000 | Metrics & visualization | Go + Node |
Dashboard sends commands to embedded services:
Parent Action → messageBus.publish() → iframeAdapter → PostMessage → Service iframe
Services report events back to dashboard:
Service iframe → window.parent.postMessage() → iframeAdapter → messageBus → Dashboard subscribers
Standard browser API for cross-origin, cross-frame communication. Used because:
- Works across iframe boundaries
- Doesn’t require shared origin
- Native browser support (no dependencies)
- Trusted ecosystem model (no validation needed)
src/utils/messageBus.js (130 lines)
messageBus.subscribe(eventName, callback, service)- Register listener for an event
- Returns unsubscribe function
messageBus.publish(eventName, data, sender)- Broadcast event to all subscribers
- Logs to event history
messageBus.getSubscribers()- Debug: view all listeners
messageBus.getEventLog()- Debug: view recent events (last 100)
window.__messageBus: Direct message bus accesswindow.__messageBusDebug.subscribers(): View listenerswindow.__messageBusDebug.log(): View event historywindow.__messageBusDebug.print(): Pretty-print log
src/utils/iframeAdapter.js (180 lines)
registerIframe(serviceName, element)- Register an iframe with the orchestration system
- Starts listening for PostMessage events from that iframe
sendToIframe(serviceName, eventName, data)- Send message to specific iframe via PostMessage
getIframeStatus()- Debug: check connection status of all iframes
window.__iframeAdapter: Direct adapter accesswindow.__iframeAdapter.status(): Check iframe connectionswindow.__iframeAdapter.registry(): View registered iframeswindow.__iframeAdapter.send(service, event, data): Send test messages
src/utils/orchestrationEvents.js (40 lines)
Central registry of all events the system supports. Ensures consistency across parent and child implementations.
Parent → csLineInvoker Commands:
csLineInvoker:filterChanged- User changed filterscsLineInvoker:refreshTasks- Refresh task listcsLineInvoker:executeCommand- Execute command
csLineInvoker → Parent Events:
csLineInvoker:taskExecuted- Task completed successfullycsLineInvoker:taskFailed- Task failed with errorcsLineInvoker:statusUpdated- Status changed (idle → executing)
Parent → Airflow Commands:
airflow:triggerDag- Trigger workflowairflow:pauseDag- Pause workflow
Airflow → Parent Events:
airflow:dagTriggered- Workflow triggeredairflow:dagStatusChanged- Workflow status changed
Parent → Grafana Commands:
grafana:updateDashboard- Switch dashboardgrafana:updateTimeRange- Change time range
Grafana → Parent Events:
grafana:panelDataLoaded- Panel data ready
The parent (Gatsby dashboard) is fully set up to communicate with csLineInvoker. The csLineInvoker iframe needs to be integrated.
Location: src/pages/csPlayer.js
Location: src/templates/csLineInvokerClient.template.js (Ready to copy to webCliGui)
Key functions to implement in csLineInvoker/webCliGui:
initializeOrchestration()- Call on app startupsendToParent(eventName, data)- Send events to parentonMessageFromParent(eventName, callback)- Listen for commands
- [ ] Copy
csLineInvokerClient.template.jsto webCliGui - [ ] Import
initializeOrchestration()in main app component - [ ] Call
initializeOrchestration()in useEffect on app load - [ ] Replace task completion handlers to use
sendToParent() - [ ] Test: Parent should show
ready: trueinwindow.__iframeAdapter.status()
The infrastructure supports Airflow integration with identical pattern to csLineInvoker.
Similar to csLineInvoker:
- Create or enhance
src/pages/airflow.js - Register iframe:
registerIframe('airflow', iframeElement) - Subscribe to events:
messageBus.subscribe(ORCHESTRATION_EVENTS.AIRFLOW_*)
Airflow will use same pattern as csLineInvoker:
- Copy
csLineInvokerClient.template.jspattern to Airflow UI - Call
initializeOrchestration()on startup - Send events when workflows trigger/complete
Like Airflow, Grafana follows the same integration pattern.
- Grafana UI is read-heavy (monitoring focus)
- Communication primarily Parent → Grafana (dashboard switching, time range changes)
- Events from Grafana less frequent than csLineInvoker/Airflow
- [x] Message bus system (
messageBus.js) - [x] Iframe adapter (
iframeAdapter.js) - [x] Event registry (
orchestrationEvents.js) - [x] csLineInvoker page integrated (
src/pages/csPlayer.js) - [x] Airflow page created (
src/pages/airflow.js) - [x] Grafana page created (
src/pages/grafana.js) - [x] Explore landing page (
src/pages/explore.js)
- [x] API reference (ORCHESTRATION.md)
- [x] Setup guide (ORCHESTRATION_SETUP.md)
- [x] Testing guide (TESTING_GUIDE.md)
- [x] File manifest (FILE_MANIFEST.md)
- [x] Design document (README.org)
- [x] Zero compilation errors
- [x] Zero JavaScript errors
- [x] Gatsby dev server running stable
- [ ] Integrate csLineInvokerClient code into webCliGui
- [ ] Call
initializeOrchestration()on app startup - [ ] Update task handlers to send events via
sendToParent() - [ ] Test full parent-child communication
- [ ] Create parent-side integration in Airflow page
- [ ] Develop Airflow iframe client code
- [ ] Implement workflow trigger communication
- [ ] Integrate Grafana iframe with orchestration
- [ ] Implement dashboard/time range synchronization
csLineInvoker-webUi/ ├── src/ │ ├── pages/ │ │ ├── index.js # Homepage with service overview │ │ ├── csPlayer.js # csLineInvoker iframe page (invoker, with config) │ │ ├── csLineInvokerBackEnd.js # Django performer API admin page (with config) │ │ ├── modPlayerFacter.js # Alternative invoker variant (with config) │ │ ├── modPlayerSoncli.js # Alternative invoker variant (with config) │ │ ├── airflow.js # Airflow iframe page (with config) │ │ ├── grafana.js # Grafana iframe page (with config) │ │ ├── explore.js # Resource hub page │ │ └── explore/ │ │ ├── help.js │ │ ├── search.js │ │ ├── accessibility.js │ │ └── sitemap.js │ ├── components/ │ │ ├── Header.js # App header │ │ ├── Footer.js # App footer (Libre-Halaal branding) │ │ ├── Layout.js # Root layout component │ │ ├── Sidebar.js # Navigation sidebar │ │ └── SearchBox.js # Search component │ ├── data/ │ │ └── menuData.js # Sidebar navigation structure │ ├── utils/ │ │ ├── orchestrationEvents.js # Event registry │ │ ├── messageBus.js # Pub/Sub system │ │ ├── iframeAdapter.js # PostMessage bridge │ │ └── serviceConfig.js # Service URLs configuration (NEW) │ └── templates/ │ └── csLineInvokerClient.template.js # csLineInvoker integration template ├── .env.development # Development environment variables (NEW) ├── .env.production # Production environment variables (NEW) ├── ORCHESTRATION.md # API reference ├── ORCHESTRATION_SETUP.md # Setup guide ├── TESTING_GUIDE.md # Testing procedures ├── FILE_MANIFEST.md # File breakdown └── README.org # This design document
- Node.js 22.21.1+
- npm 10.9.4+
cd /bisos/git/auth/bxRepos/bisos-web/csLineInvoker-webUi
npm install
npm run developServer starts on http://localhost:25001
npm run build
npm run serveAll debug tools exposed via window object:
// Message Bus debugging
window.__messageBusDebug.subscribers() // View all listeners
window.__messageBusDebug.log() // View event history
window.__messageBusDebug.print() // Pretty-print events
// Iframe Adapter debugging
window.__iframeAdapter.status() // Check iframe connections
window.__iframeAdapter.registry() // View registered iframes
window.__iframeAdapter.send(service, event, data) // Send test messageEvery iframe page now displays its configured URL in the header for:
- **Debugging**: Developers can immediately see which URL is loaded
- **Transparency**: Users know where the content comes from
- **Configuration visibility**: Shows which environment (dev/prod) is active
- **Quick access**: Clickable to open in new tab if iframe fails
All iframe pages now include a URL badge in the page header:
- **Location**: Right-aligned in header, below description text
- **Style**: Small, monospace font, blue color
- **Interactivity**: Clickable link (opens in new tab), hover effect
- **Icon**: Arrow (↗) indicates external link
✓ src/pages/csPlayer.js - Shows cslineInvoker URL
✓ src/pages/csLineInvokerBackEnd.js - Shows csplayerPerformer URL
✓ src/pages/modPlayerFacter.js - Shows cslineInvoker URL
✓ src/pages/modPlayerSoncli.js - Shows cslineInvoker URL
✓ src/pages/airflow.js - Shows airflow URL
✓ src/pages/grafana.js - Shows grafana URL
┌────────────────────────────────────────────────────────────────┐
│ 🖥️ Build and Execute CSXU Command Lines │
│ Build, execute and monitor... http://csLineInvoker... ↗ │
└────────────────────────────────────────────────────────────────┘
```
The URL is right-aligned on the same line as the description text, in blue, and clickable.
* Deployment Considerations
:PROPERTIES:
:CUSTOM_ID: deployment-considerations
:END:
** Security
:PROPERTIES:
:CUSTOM_ID: security
:END:
*** Trust Model
This architecture assumes a *trusted internal ecosystem*:
- All services are controlled by the same organization
- Services are on the same network
- PostMessage uses =*= origin (intentionally simple for internal use)
*** Security NOT Included (By Design)
- Message signing/validation
- Message encryption
- Rate limiting
* Appendix
:PROPERTIES:
:CUSTOM_ID: appendix
:END:
** File Reference
:PROPERTIES:
:CUSTOM_ID: file-reference
:END:
*** Core Orchestration Files
| File | Lines | Purpose | Status |
|-----------------------------------------------+-------+------------------------------------+------------|
| =src/utils/orchestrationEvents.js= | 40 | Event registry | ✓ Complete |
| =src/utils/messageBus.js= | 130 | Pub/Sub system | ✓ Complete |
| =src/utils/iframeAdapter.js= | 180 | PostMessage bridge | ✓ Complete |
| =src/utils/serviceConfig.js= | 35 | Service URLs configuration | ✓ Complete |
| =src/templates/csLineInvokerClient.template.js= | 150 | csLineInvoker integration template | ✓ Complete |
*** Configuration Files
| File | Purpose | Status |
|------------------+--------------------------+------------|
| =.env.development= | Development service URLs | ✓ Complete |
| =.env.production= | Production service URLs | ✓ Complete |
*** Page Components
| File | Purpose | Status |
|-----------------------------------+---------------------------------------------------+------------|
| =src/pages/index.js= | Homepage with service overview | ✓ Complete |
| =src/pages/csPlayer.js= | csLineInvoker/invoker iframe (config + URL badge) | ✓ Complete |
| =src/pages/csLineInvokerBackEnd.js= | Performer API admin (config + URL badge) | ✓ Complete |
| =src/pages/modPlayerFacter.js= | Alternative invoker (config + URL badge) | ✓ Complete |
| =src/pages/modPlayerSoncli.js= | Alternative invoker (config + URL badge) | ✓ Complete |
| =src/pages/airflow.js= | Airflow iframe (config + URL badge) | ✓ Complete |
| =src/pages/grafana.js= | Grafana iframe (config + URL badge) | ✓ Complete |
| =src/pages/testStubs.js= | Test stubs iframe (config + URL badge) | ✓ Complete |
| =src/pages/explore.js= | Resource hub | ✓ Complete |
** Event Registry
:PROPERTIES:
:CUSTOM_ID: event-registry
:END:
*** csLineInvoker Events
| Event | Direction | Payload | Purpose |
|-----------------------------+----------------+-----------------------------+----------------------|
| =csLineInvoker:filterChanged= | Parent → Child | ={environment, server, user}= | User changed filters |
| =csLineInvoker:taskExecuted= | Child → Parent | ={taskId, output, duration}= | Task completed |
| =csLineInvoker:taskFailed= | Child → Parent | ={taskId, errorMessage}= | Task failed |
---
Document Status: LIVING DESIGN DOCUMENT
Last Updated: January 24, 2026
Version: 1.0 (Phase 1 Complete)