# Web Page Split And Root Source Cleanup > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. **Goal:** Restructure the `web/` directory into `core/` + `feeder/` + `ops/` subdirectories, delete the obsolete root `src/` files, and update README to reflect the new workspace layout. **Architecture:** Web pages split into a shared `web/core/` (platform HTML partials and CSS) and per-app directories (`web/feeder/`, `web/ops/`). Each app's Axum router uses `ServeDir` with fallback: try app-specific dir first, then core. This means no URL changes in HTML/JS — the fallback chain resolves transparently. The root `src/` contains stale copies of files already migrated to crates and must be removed. **Tech Stack:** Rust (Axum, tower-http ServeDir), HTML/CSS/JS (vanilla, ES modules), Cargo workspace --- ## File Map ### Web core (shared platform pages) - Move: `web/styles.css` → `web/core/styles.css` - Move: `web/html/source-panel.html` → `web/core/html/source-panel.html` - Move: `web/html/points-panel.html` → `web/core/html/points-panel.html` - Move: `web/html/equipment-panel.html` → `web/core/html/equipment-panel.html` - Move: `web/html/chart-panel.html` → `web/core/html/chart-panel.html` - Move: `web/html/log-stream-panel.html` → `web/core/html/log-stream-panel.html` - Move: `web/html/logs-panel.html` → `web/core/html/logs-panel.html` - Move: `web/html/api-doc-drawer.html` → `web/core/html/api-doc-drawer.html` - Create: `web/core/html/modals.html` (core modals only — equipment, source, point, binding; unit modal removed) ### Web feeder (feeder-specific pages + all JS) - Move: `web/index.html` → `web/feeder/index.html` (add unit-modal partial reference) - Move: `web/html/topbar.html` → `web/feeder/html/topbar.html` - Move: `web/html/ops-panel.html` → `web/feeder/html/ops-panel.html` - Create: `web/feeder/html/unit-modal.html` (extracted from old modals.html) - Move: `web/js/*.js` → `web/feeder/js/*.js` (all 15 JS files stay together as interconnected module graph) ### Web ops (operation-system pages) - Move: `crates/app_operation_system/web/index.html` → `web/ops/index.html` (updated content) - Create: `web/ops/html/topbar.html` - Create: `web/ops/js/index.js` - Create: `web/ops/js/app.js` ### Rust router changes - Modify: `crates/app_feeder_distributor/src/router.rs` (update ServeDir to use fallback) - Modify: `crates/app_operation_system/src/router.rs` (update ServeDir to use fallback) ### Root src cleanup - Delete: all 19 files under `src/` (stale duplicates of files in crates) ### Documentation - Modify: `README.md` --- ## Task 1: Split modals.html And Create Unit Modal Partial **Files:** - Create: `web/core/html/modals.html` - Create: `web/feeder/html/unit-modal.html` - [ ] **Step 1: Create core modals (without unit modal)** Extract everything except the unit modal div from `web/html/modals.html` into a new file: `web/core/html/modals.html`: ```html
``` - [ ] **Step 2: Create feeder unit modal partial** Extract the unit modal into its own file: `web/feeder/html/unit-modal.html`: ```html ``` - [ ] **Step 3: Verify both files contain all original modal content** Check that the combined line count of the two new files matches the original `web/html/modals.html` (188 lines total, minus blank lines between sections). - [ ] **Step 4: Commit** ```bash git add web/core/html/modals.html web/feeder/html/unit-modal.html git commit -m "refactor(web): split modals into core and feeder unit-modal" ``` ## Task 2: Move Core HTML And CSS Into web/core **Files:** - Move: `web/styles.css` → `web/core/styles.css` - Move: `web/html/source-panel.html` → `web/core/html/source-panel.html` - Move: `web/html/points-panel.html` → `web/core/html/points-panel.html` - Move: `web/html/equipment-panel.html` → `web/core/html/equipment-panel.html` - Move: `web/html/chart-panel.html` → `web/core/html/chart-panel.html` - Move: `web/html/log-stream-panel.html` → `web/core/html/log-stream-panel.html` - Move: `web/html/logs-panel.html` → `web/core/html/logs-panel.html` - Move: `web/html/api-doc-drawer.html` → `web/core/html/api-doc-drawer.html` - [ ] **Step 1: Create core directories and move files** ```bash mkdir -p web/core/html git mv web/styles.css web/core/styles.css git mv web/html/source-panel.html web/core/html/source-panel.html git mv web/html/points-panel.html web/core/html/points-panel.html git mv web/html/equipment-panel.html web/core/html/equipment-panel.html git mv web/html/chart-panel.html web/core/html/chart-panel.html git mv web/html/log-stream-panel.html web/core/html/log-stream-panel.html git mv web/html/logs-panel.html web/core/html/logs-panel.html git mv web/html/api-doc-drawer.html web/core/html/api-doc-drawer.html ``` - [ ] **Step 2: Commit** ```bash git add web/core git commit -m "refactor(web): move shared HTML partials and CSS into web/core" ``` ## Task 3: Move Feeder-Specific HTML And All JS Into web/feeder **Files:** - Move: `web/index.html` → `web/feeder/index.html` - Move: `web/html/topbar.html` → `web/feeder/html/topbar.html` - Move: `web/html/ops-panel.html` → `web/feeder/html/ops-panel.html` - Move: `web/js/*.js` → `web/feeder/js/*.js` - Delete: `web/html/modals.html` (replaced by split files in Task 1) - [ ] **Step 1: Create feeder directories and move files** ```bash mkdir -p web/feeder/html web/feeder/js git mv web/html/topbar.html web/feeder/html/topbar.html git mv web/html/ops-panel.html web/feeder/html/ops-panel.html git mv web/js/api.js web/feeder/js/api.js git mv web/js/app.js web/feeder/js/app.js git mv web/js/chart.js web/feeder/js/chart.js git mv web/js/docs.js web/feeder/js/docs.js git mv web/js/dom.js web/feeder/js/dom.js git mv web/js/equipment.js web/feeder/js/equipment.js git mv web/js/events.js web/feeder/js/events.js git mv web/js/index.js web/feeder/js/index.js git mv web/js/logs.js web/feeder/js/logs.js git mv web/js/ops.js web/feeder/js/ops.js git mv web/js/points.js web/feeder/js/points.js git mv web/js/roles.js web/feeder/js/roles.js git mv web/js/sources.js web/feeder/js/sources.js git mv web/js/state.js web/feeder/js/state.js git mv web/js/units.js web/feeder/js/units.js ``` - [ ] **Step 2: Move index.html and delete old modals** ```bash git mv web/index.html web/feeder/index.html git rm web/html/modals.html ``` - [ ] **Step 3: Update feeder index.html to add unit-modal partial** In `web/feeder/index.html`, change the modals partial line and add a unit-modal partial: Before: ```html ``` After: ```html ``` - [ ] **Step 4: Verify no files remain in old web/html and web/js directories** ```bash ls web/html/ 2>/dev/null && echo "ERROR: web/html still has files" || echo "OK: web/html is clean" ls web/js/ 2>/dev/null && echo "ERROR: web/js still has files" || echo "OK: web/js is clean" ``` Expected: both directories are empty or deleted. - [ ] **Step 5: Commit** ```bash git add web/feeder git commit -m "refactor(web): move feeder HTML, JS, and index into web/feeder" ``` ## Task 4: Update Feeder Router To Use Fallback ServeDir **Files:** - Modify: `crates/app_feeder_distributor/src/router.rs` - [ ] **Step 1: Update the static file serving to use fallback chain** In `crates/app_feeder_distributor/src/router.rs`, replace the current `/ui` nest: Before: ```rust .nest( "/ui", Router::new() .fallback_service(ServeDir::new("web").append_index_html_on_directories(true)) .layer(axum::middleware::from_fn(no_cache)), ) ``` After: ```rust .nest( "/ui", Router::new() .fallback_service( ServeDir::new("web/feeder") .append_index_html_on_directories(true) .fallback(ServeDir::new("web/core")), ) .layer(axum::middleware::from_fn(no_cache)), ) ``` - [ ] **Step 2: Verify feeder crate compiles** Run: ```bash cargo check -p app_feeder_distributor ``` Expected: PASS - [ ] **Step 3: Commit** ```bash git add crates/app_feeder_distributor/src/router.rs git commit -m "refactor(feeder): update static file serving for split web dirs" ``` ## Task 5: Create Operation-System Web Pages And Update Router **Files:** - Create: `web/ops/index.html` - Create: `web/ops/html/topbar.html` - Create: `web/ops/js/index.js` - Create: `web/ops/js/app.js` - Modify: `crates/app_operation_system/src/router.rs` - Delete: `crates/app_operation_system/web/index.html` - [ ] **Step 1: Create ops web scaffold** `web/ops/index.html`: ```html${error.message || String(error)}`;
});
```
`web/ops/js/app.js`:
```javascript
function bootstrap() {
console.log("Operation system app initialized");
}
bootstrap();
```
- [ ] **Step 2: Update ops router to use split web dirs**
Replace `crates/app_operation_system/src/router.rs`:
```rust
use axum::{extract::State, routing::get, Router};
use tower_http::services::ServeDir;
use crate::app::AppState;
async fn no_cache(req: axum::extract::Request, next: axum::middleware::Next) -> axum::response::Response {
let mut response = next.run(req).await;
response.headers_mut().insert(
axum::http::header::CACHE_CONTROL,
axum::http::HeaderValue::from_static("no-store"),
);
response
}
pub fn build_router(state: AppState) -> Router {
Router::new()
.route("/api/health", get(health_check))
.nest(
"/ui",
Router::new()
.fallback_service(
ServeDir::new("web/ops")
.append_index_html_on_directories(true)
.fallback(ServeDir::new("web/core")),
)
.layer(axum::middleware::from_fn(no_cache)),
)
.with_state(state)
}
async fn health_check(State(state): State