-
Notifications
You must be signed in to change notification settings - Fork 0
Description
Problem
monitor-forge ships 6 built-in panel types (news-feed, ai-brief, market-ticker, entity-tracker, instability-index, service-status), but there is no supported way to add custom panels without understanding the internal manifest generation pipeline.
The irony: the architecture was designed for extensibility but the developer-facing tooling was never built:
- Schema already accepts
type: 'custom':PanelSchemainforge/src/config/schema.tsincludes'custom'as a valid panel type - PanelBase has a full abstract API:
render(),update(data),destroy()+ utility helpers (triggerPulse(),showSkeleton(),createElement()) - PanelRegistry has
registerPanelType(): The registration mechanism exists insrc/core/panels/panel-registry.ts - Manifest generator deliberately skips custom panels: Lines 103/110 of
forge/src/generators/manifest-generator.tshave a no-op code path fortype !== 'custom'— the stub exists but does nothing
The result: A developer who wants a "WeatherPanel" or "GitHubActivityPanel" must manually:
- Understand the manifest generation pipeline
- Create a class extending PanelBase in the correct location
- Manually register it in the generated manifest (which gets overwritten on next build)
- Figure out the data flow from SourceManager → Panel
This is the #1 missing piece that would transform monitor-forge from a template into a platform. worldmonitor requires forking and editing core source files. monitor-forge should let you extend without touching core code.
Solution
1. forge panel create <name> Scaffold Command
New command that generates a ready-to-use custom panel:
$ npx forge panel create weather-panel
✓ Created src/custom-panels/WeatherPanel.ts
✓ Updated panel registry for custom panels
✓ Panel "weather-panel" ready for development
Next steps:
1. Edit src/custom-panels/WeatherPanel.ts
2. Add panel to config: forge panel add weather-panel --type custom
3. Run forge dev to see it liveGenerated file (src/custom-panels/WeatherPanel.ts):
import { PanelBase, type PanelConfig } from '@/core/panels/PanelBase';
/**
* Custom panel: weather-panel
*
* PanelBase API:
* render() — Create and return your panel's DOM (called once)
* update(data) — Receive new data from sources (called on each poll)
* destroy() — Cleanup timers, listeners, DOM (called on teardown)
*
* Available helpers (from PanelBase):
* this.triggerPulse() — Flash header on data update
* this.showSkeleton(lines?) — Show loading skeleton
* this.hideSkeleton() — Hide loading skeleton
* this.markDataReceived() — Hide skeleton + trigger pulse
* this.createElement(tag, cls) — Create DOM element helper
*/
export class WeatherPanel extends PanelBase {
render(): HTMLElement {
const container = this.createElement('div', 'weather-panel');
container.innerHTML = '<p>Weather panel — edit this file to customize</p>';
this.showSkeleton();
return container;
}
update(data: unknown): void {
// Process incoming data from connected sources
// Call this.markDataReceived() when rendering is complete
this.markDataReceived();
}
destroy(): void {
this.cleanupTimers();
}
}2. Manifest Generator Update
Update forge/src/generators/manifest-generator.ts to auto-discover and register custom panels:
// Scan src/custom-panels/ for .ts files
// Auto-generate import + registration:
import { WeatherPanel } from '../custom-panels/WeatherPanel';
registerPanelType('weather-panel', WeatherPanel);- Custom panels discovered at build time via filesystem scan of
src/custom-panels/ - Naming convention:
PascalCase.ts→kebab-casepanel type - No manual registration needed —
forge buildhandles it
3. CLI Integration
forge panel create <name>— scaffold new custom panelforge panel list— shows custom panels with[custom]badge alongside built-in panelsforge panel add <name> --type custom— add custom panel to config (existing command, works today)forge panel remove <name>— works for custom panels too (existing command)
4. Hot-Reload Support
Custom panels in src/custom-panels/ are regular TypeScript files in the Vite source tree. Hot module replacement works automatically — edit the file, see changes instantly in the browser.
5. Convention Over Configuration
src/custom-panels/
├── WeatherPanel.ts → type: "weather-panel"
├── GitHubActivityPanel.ts → type: "github-activity-panel"
└── index.ts → auto-generated barrel export
- File name determines panel type (PascalCase → kebab-case)
- No config changes needed beyond
forge panel add - Custom panels are first-class citizens in the panel system
Implementation Notes
Files to modify:
forge/src/commands/panel.ts— addcreatesubcommandforge/src/generators/manifest-generator.ts— custom panel discovery + registration codegenforge/src/config/schema.ts— no changes needed ('custom'already valid)src/core/panels/panel-registry.ts— no changes needed (registration API exists)
Files to create:
forge/src/templates/custom-panel.ts.template— scaffold templatesrc/custom-panels/.gitkeep— directory placeholder
Backward compatibility:
- Zero breaking changes — existing configs without custom panels work identically
- Custom panel directory is optional — if absent, build proceeds as before