- Add security-bootstrap.js for centralized auth token management - Improve login flow with token persistence - Update htmx-app.js auth integration - Fix settings and tasks auth handling
1001 lines
No EOL
24 KiB
Markdown
1001 lines
No EOL
24 KiB
Markdown
# BotUI Development Prompt Guide
|
|
|
|
**Version:** 6.1.0
|
|
**Purpose:** LLM context for BotUI development
|
|
|
|
---
|
|
|
|
## ZERO TOLERANCE POLICY
|
|
|
|
**This project has the strictest code quality requirements possible.**
|
|
|
|
**EVERY SINGLE WARNING MUST BE FIXED. NO EXCEPTIONS.**
|
|
|
|
---
|
|
|
|
## ABSOLUTE PROHIBITIONS
|
|
|
|
```
|
|
❌ NEVER use #![allow()] or #[allow()] in source code to silence warnings
|
|
❌ NEVER use _ prefix for unused variables - DELETE the variable or USE it
|
|
❌ NEVER use .unwrap() - use ? or proper error handling
|
|
❌ NEVER use .expect() - use ? or proper error handling
|
|
❌ NEVER use panic!() or unreachable!() - handle all cases
|
|
❌ NEVER use todo!() or unimplemented!() - write real code
|
|
❌ NEVER leave unused imports - DELETE them
|
|
❌ NEVER leave dead code - DELETE it or IMPLEMENT it
|
|
❌ NEVER use approximate constants (3.14159) - use std::f64::consts::PI
|
|
❌ NEVER silence clippy in code - FIX THE CODE or configure in Cargo.toml
|
|
❌ NEVER add comments explaining what code does - code must be self-documenting
|
|
❌ NEVER use CDN links - all assets must be local
|
|
```
|
|
|
|
---
|
|
|
|
## CARGO.TOML LINT EXCEPTIONS
|
|
|
|
When a clippy lint has **technical false positives** that cannot be fixed in code,
|
|
disable it in `Cargo.toml` with a comment explaining why:
|
|
|
|
```toml
|
|
[lints.clippy]
|
|
# Disabled: has false positives for functions with mut self, heap types (Vec, String)
|
|
missing_const_for_fn = "allow"
|
|
# Disabled: Tauri commands require owned types (Window) that cannot be passed by reference
|
|
needless_pass_by_value = "allow"
|
|
# Disabled: transitive dependencies we cannot control
|
|
multiple_crate_versions = "allow"
|
|
```
|
|
|
|
**Approved exceptions:**
|
|
- `missing_const_for_fn` - false positives for `mut self`, heap types
|
|
- `needless_pass_by_value` - Tauri/framework requirements
|
|
- `multiple_crate_versions` - transitive dependencies
|
|
- `future_not_send` - when async traits require non-Send futures
|
|
|
|
---
|
|
|
|
## MANDATORY CODE PATTERNS
|
|
|
|
### Error Handling - Use `?` Operator
|
|
|
|
```rust
|
|
// ❌ WRONG
|
|
let value = something.unwrap();
|
|
let value = something.expect("msg");
|
|
|
|
// ✅ CORRECT
|
|
let value = something?;
|
|
let value = something.ok_or_else(|| Error::NotFound)?;
|
|
```
|
|
|
|
### Self Usage in Impl Blocks
|
|
|
|
```rust
|
|
// ❌ WRONG
|
|
impl MyStruct {
|
|
fn new() -> MyStruct { MyStruct { } }
|
|
}
|
|
|
|
// ✅ CORRECT
|
|
impl MyStruct {
|
|
fn new() -> Self { Self { } }
|
|
}
|
|
```
|
|
|
|
### Format Strings - Inline Variables
|
|
|
|
```rust
|
|
// ❌ WRONG
|
|
format!("Hello {}", name)
|
|
|
|
// ✅ CORRECT
|
|
format!("Hello {name}")
|
|
```
|
|
|
|
### Display vs ToString
|
|
|
|
```rust
|
|
// ❌ WRONG
|
|
impl ToString for MyType { }
|
|
|
|
// ✅ CORRECT
|
|
impl std::fmt::Display for MyType { }
|
|
```
|
|
|
|
### Derive Eq with PartialEq
|
|
|
|
```rust
|
|
// ❌ WRONG
|
|
#[derive(PartialEq)]
|
|
struct MyStruct { }
|
|
|
|
// ✅ CORRECT
|
|
#[derive(PartialEq, Eq)]
|
|
struct MyStruct { }
|
|
```
|
|
|
|
---
|
|
|
|
## Weekly Maintenance - EVERY MONDAY
|
|
|
|
### Package Review Checklist
|
|
|
|
**Every Monday, review the following:**
|
|
|
|
1. **Dependency Updates**
|
|
```bash
|
|
cargo outdated
|
|
cargo audit
|
|
```
|
|
|
|
2. **Package Consolidation Opportunities**
|
|
- Check if new crates can replace custom code
|
|
- Look for crates that combine multiple dependencies
|
|
- Review `Cargo.toml` for redundant dependencies
|
|
|
|
3. **Code Reduction Candidates**
|
|
- Custom implementations that now have crate equivalents
|
|
- Boilerplate that can be replaced with derive macros
|
|
- Manual serialization that `serde` can handle
|
|
|
|
4. **Frontend Asset Updates**
|
|
```bash
|
|
# Check vendor libs in ui/suite/js/vendor/
|
|
# Compare with latest versions of htmx, gsap, etc.
|
|
```
|
|
|
|
### Packages to Watch
|
|
|
|
| Area | Potential Packages | Purpose |
|
|
|------|-------------------|---------|
|
|
| HTTP Client | `reqwest` | Consolidate HTTP handling |
|
|
| Templates | `askama` | Efficient HTML templates |
|
|
| Animations | `gsap` | Replace CSS animations |
|
|
|
|
---
|
|
|
|
## Version Management - CRITICAL
|
|
|
|
**Current version is 6.1.0 - DO NOT CHANGE without explicit approval!**
|
|
|
|
### Rules
|
|
|
|
1. **Version is 6.1.0 across ALL workspace crates**
|
|
2. **NEVER change version without explicit user approval**
|
|
3. **BotUI does not have migrations - all migrations are in botserver/**
|
|
4. **All workspace crates share version 6.1.0**
|
|
|
|
---
|
|
|
|
## Official Icons - MANDATORY
|
|
|
|
**NEVER generate icons with LLM. ALWAYS use official SVG icons from:**
|
|
|
|
```
|
|
ui/suite/assets/icons/
|
|
├── gb-logo.svg # Main GB logo
|
|
├── gb-bot.svg # Bot/assistant
|
|
├── gb-analytics.svg # Analytics app
|
|
├── gb-calendar.svg # Calendar app
|
|
├── gb-chat.svg # Chat app
|
|
├── gb-compliance.svg # Compliance/security
|
|
├── gb-designer.svg # Workflow designer
|
|
├── gb-drive.svg # File storage
|
|
├── gb-mail.svg # Email
|
|
├── gb-meet.svg # Video meetings
|
|
├── gb-paper.svg # Documents
|
|
├── gb-research.svg # Research/search
|
|
├── gb-sources.svg # Knowledge sources
|
|
└── gb-tasks.svg # Task management
|
|
```
|
|
|
|
### Usage in HTML
|
|
|
|
```html
|
|
<!-- Inline SVG (preferred for styling) -->
|
|
<img src="/assets/icons/gb-chat.svg" alt="Chat" class="icon">
|
|
|
|
<!-- With CSS currentColor -->
|
|
<svg class="icon" style="color: var(--primary);">
|
|
<use href="/assets/icons/gb-chat.svg#icon"></use>
|
|
</svg>
|
|
```
|
|
|
|
### Icon Style Guidelines
|
|
|
|
- All icons use `stroke="currentColor"` for theming
|
|
- ViewBox: `0 0 24 24`
|
|
- Stroke width: `1.5`
|
|
- Rounded caps and joins
|
|
- Consistent with GB brand identity
|
|
|
|
**DO NOT:**
|
|
- Generate new icons with AI/LLM
|
|
- Use emoji or unicode symbols as icons
|
|
- Use external icon libraries (FontAwesome, etc.)
|
|
- Create inline SVG content in templates
|
|
|
|
---
|
|
|
|
## Project Overview
|
|
|
|
BotUI is a **dual-mode UI application** built in Rust that runs as either a desktop app (Tauri) or web server (Axum). All business logic is in **botserver** - BotUI is purely presentation + HTTP bridge.
|
|
|
|
### Workspace Position
|
|
|
|
```
|
|
botui/ # THIS PROJECT - Web/Desktop UI
|
|
botserver/ # Main server (business logic)
|
|
botlib/ # Shared library (consumed here)
|
|
botapp/ # Desktop wrapper (consumes botui)
|
|
botbook/ # Documentation
|
|
```
|
|
|
|
---
|
|
|
|
## LLM Workflow Strategy
|
|
|
|
### Two Types of LLM Work
|
|
|
|
1. **Execution Mode (Fazer)**
|
|
- Pre-annotate phrases and send for execution
|
|
- Focus on automation freedom
|
|
- Less concerned with code details
|
|
- Primary concern: Is the LLM destroying something?
|
|
- Trust but verify output doesn't break existing functionality
|
|
|
|
2. **Review Mode (Conferir)**
|
|
- Read generated code with full attention
|
|
- Line-by-line verification
|
|
- Check for correctness, security, performance
|
|
- Validate against requirements
|
|
|
|
### LLM Fallback Strategy (After 3 attempts / 10 minutes)
|
|
|
|
1. DeepSeek-V3-0324 (good architect, reliable)
|
|
2. gpt-5-chat (slower but thorough)
|
|
3. gpt-oss-120b (final validation)
|
|
4. Claude Web (for complex debugging, unit tests, UI)
|
|
|
|
---
|
|
|
|
## Code Generation Rules
|
|
|
|
### CRITICAL REQUIREMENTS
|
|
|
|
```
|
|
- BotUI = Presentation + HTTP bridge ONLY
|
|
- All business logic goes in botserver
|
|
- No code duplication between layers
|
|
- Feature gates eliminate unused code paths
|
|
- Zero warnings - feature gating prevents dead code
|
|
- NO DEAD CODE - implement real functionality, never use _ for unused
|
|
- All JS/CSS must be local (no CDN)
|
|
```
|
|
|
|
### HTMX-First Frontend
|
|
|
|
```
|
|
- Use HTMX to minimize JavaScript at maximum
|
|
- Delegate ALL logic to Rust server
|
|
- Server returns HTML fragments, not JSON
|
|
- Use hx-get, hx-post, hx-target, hx-swap attributes
|
|
- WebSocket via htmx-ws extension for real-time
|
|
- NO custom JavaScript where HTMX can handle it
|
|
```
|
|
|
|
### JavaScript Usage Guidelines
|
|
|
|
**JS is ONLY acceptable when HTMX cannot handle the requirement:**
|
|
|
|
| Use Case | Solution |
|
|
|----------|----------|
|
|
| Data fetching | HTMX `hx-get`, `hx-post` |
|
|
| Form submission | HTMX `hx-post`, `hx-put` |
|
|
| Real-time updates | HTMX WebSocket extension `hx-ext="ws"` |
|
|
| Content swapping | HTMX `hx-target`, `hx-swap` |
|
|
| Polling | HTMX `hx-trigger="every 5s"` |
|
|
| Loading states | HTMX `hx-indicator` |
|
|
| **Modal show/hide** | **JS required** - DOM manipulation |
|
|
| **Toast notifications** | **JS required** - dynamic element creation |
|
|
| **Clipboard operations** | **JS required** - `navigator.clipboard` API |
|
|
| **Keyboard shortcuts** | **JS required** - `keydown` event handling |
|
|
| **WebSocket state mgmt** | **JS required** - connection lifecycle |
|
|
| **Complex animations** | **JS required** - GSAP or custom |
|
|
| **Client-side validation** | **JS required** - before submission UX |
|
|
|
|
**When writing JS:**
|
|
```
|
|
- Keep it minimal - one function per concern
|
|
- No frameworks (React, Vue, etc.) - vanilla JS only
|
|
- Use vendor libs sparingly (htmx, marked, gsap)
|
|
- All JS must work with HTMX lifecycle (htmx:afterSwap, etc.)
|
|
- Prefer CSS for animations when possible
|
|
```
|
|
|
|
### Local Assets Only
|
|
|
|
All external libraries are bundled locally - NEVER use CDN:
|
|
|
|
```
|
|
ui/suite/js/vendor/
|
|
├── htmx.min.js # HTMX core
|
|
├── htmx-ws.js # WebSocket extension
|
|
├── htmx-json-enc.js # JSON encoding
|
|
├── marked.min.js # Markdown parser
|
|
├── gsap.min.js # Animation (minimal use)
|
|
└── livekit-client.umd.min.js # LiveKit video
|
|
|
|
ui/minimal/js/vendor/
|
|
└── (same structure)
|
|
```
|
|
|
|
```html
|
|
<!-- CORRECT -->
|
|
<script src="js/vendor/htmx.min.js"></script>
|
|
|
|
<!-- WRONG - NEVER DO THIS -->
|
|
<script src="https://unpkg.com/htmx.org@1.9.10"></script>
|
|
```
|
|
|
|
### Dependency Management
|
|
|
|
```
|
|
- Use diesel for any local database needs
|
|
- After adding to Cargo.toml: cargo audit must show 0 warnings
|
|
- If audit fails, find alternative library
|
|
- Minimize redundancy - check existing libs before adding new ones
|
|
```
|
|
|
|
### Documentation Rules
|
|
|
|
```
|
|
- Rust code examples ONLY allowed in architecture/gbapp documentation
|
|
- Scan for ALL_CAPS.md files created at wrong places - delete or integrate
|
|
- Keep only README.md and PROMPT.md at project root level
|
|
```
|
|
|
|
---
|
|
|
|
## Architecture
|
|
|
|
### Dual Modes
|
|
|
|
| Mode | Command | Description |
|
|
|------|---------|-------------|
|
|
| Web | `cargo run` | Axum server on port 3000 |
|
|
| Desktop | `cargo tauri dev` | Tauri native window |
|
|
|
|
### Code Organization
|
|
|
|
```
|
|
src/
|
|
├── main.rs # Entry point - mode detection
|
|
├── lib.rs # Feature-gated module exports
|
|
├── http_client.rs # HTTP wrapper for botserver (web-only)
|
|
├── ui_server/
|
|
│ └── mod.rs # Axum router + UI serving (web-only)
|
|
├── desktop/
|
|
│ ├── mod.rs # Desktop module organization
|
|
│ ├── drive.rs # File operations via Tauri
|
|
│ ├── tray.rs # System tray infrastructure
|
|
│ └── stream.rs # Streaming operations
|
|
└── shared/
|
|
└── state.rs # Shared application state
|
|
|
|
ui/
|
|
├── suite/ # Main UI (HTML/CSS/JS)
|
|
│ ├── js/vendor/ # Local JS libraries
|
|
│ └── css/ # Stylesheets
|
|
└── minimal/ # Minimal chat UI
|
|
└── js/vendor/ # Local JS libraries
|
|
```
|
|
|
|
### Feature Gating
|
|
|
|
```rust
|
|
#[cfg(feature = "desktop")]
|
|
pub mod desktop;
|
|
|
|
#[cfg(not(feature = "desktop"))]
|
|
pub mod http_client;
|
|
```
|
|
|
|
---
|
|
|
|
## Security Architecture - MANDATORY
|
|
|
|
### Centralized Auth Engine
|
|
|
|
All authentication is handled by `security-bootstrap.js` which MUST be loaded immediately after HTMX in the `<head>` section. This provides:
|
|
|
|
1. **Automatic HTMX auth headers** - All `hx-get`, `hx-post`, etc. requests get Authorization header
|
|
2. **Fetch API interception** - All `fetch()` calls automatically get auth headers
|
|
3. **XMLHttpRequest interception** - Legacy XHR calls also get auth headers
|
|
4. **Session management** - Handles token storage, refresh, and expiration
|
|
|
|
### Script Loading Order (CRITICAL)
|
|
|
|
```html
|
|
<head>
|
|
<!-- 1. HTMX must load first -->
|
|
<script src="js/vendor/htmx.min.js"></script>
|
|
<script src="js/vendor/htmx-ws.js"></script>
|
|
|
|
<!-- 2. Security bootstrap IMMEDIATELY after HTMX -->
|
|
<script src="js/security-bootstrap.js"></script>
|
|
|
|
<!-- 3. Other scripts can follow -->
|
|
<script src="js/api-client.js"></script>
|
|
</head>
|
|
```
|
|
|
|
### DO NOT Duplicate Auth Logic
|
|
|
|
```javascript
|
|
// ❌ WRONG - Don't add auth headers manually
|
|
fetch("/api/data", {
|
|
headers: { "Authorization": "Bearer " + token }
|
|
});
|
|
|
|
// ✅ CORRECT - Let security-bootstrap.js handle it
|
|
fetch("/api/data");
|
|
```
|
|
|
|
### DO NOT Register Multiple HTMX Auth Listeners
|
|
|
|
```javascript
|
|
// ❌ WRONG - Don't register duplicate listeners
|
|
document.addEventListener("htmx:configRequest", (e) => {
|
|
e.detail.headers["Authorization"] = "Bearer " + token;
|
|
});
|
|
|
|
// ✅ CORRECT - This is handled by security-bootstrap.js automatically
|
|
```
|
|
|
|
### Auth Events
|
|
|
|
The security engine dispatches these events:
|
|
|
|
- `gb:security:ready` - Security bootstrap initialized
|
|
- `gb:auth:unauthorized` - 401 response received
|
|
- `gb:auth:expired` - Session expired, user should re-login
|
|
- `gb:auth:login` - Dispatch to store tokens after login
|
|
- `gb:auth:logout` - Dispatch to clear tokens
|
|
|
|
### Token Storage Keys
|
|
|
|
All auth data uses these keys (defined in security-bootstrap.js):
|
|
|
|
- `gb-access-token` - JWT access token
|
|
- `gb-refresh-token` - Refresh token
|
|
- `gb-session-id` - Session identifier
|
|
- `gb-token-expires` - Token expiration timestamp
|
|
- `gb-user-data` - Cached user profile
|
|
|
|
---
|
|
|
|
## HTMX Patterns
|
|
|
|
### Server-Side Rendering
|
|
|
|
```html
|
|
<!-- Button triggers server request, response swaps into target -->
|
|
<button hx-get="/api/items"
|
|
hx-target="#items-list"
|
|
hx-swap="innerHTML">
|
|
Load Items
|
|
</button>
|
|
|
|
<div id="items-list">
|
|
<!-- Server returns HTML fragment here -->
|
|
</div>
|
|
```
|
|
|
|
### Form Submission
|
|
|
|
```html
|
|
<form hx-post="/api/items"
|
|
hx-target="#items-list"
|
|
hx-swap="beforeend">
|
|
<input name="title" type="text" required>
|
|
<button type="submit">Add</button>
|
|
</form>
|
|
```
|
|
|
|
### WebSocket Real-time
|
|
|
|
```html
|
|
<div hx-ext="ws" ws-connect="/ws/chat">
|
|
<div id="messages"></div>
|
|
<form ws-send>
|
|
<input name="message" type="text">
|
|
<button type="submit">Send</button>
|
|
</form>
|
|
</div>
|
|
```
|
|
|
|
### Server Response (Rust/Askama)
|
|
|
|
```rust
|
|
#[derive(Template)]
|
|
#[template(path = "partials/item.html")]
|
|
struct ItemTemplate {
|
|
item: Item,
|
|
}
|
|
|
|
async fn create_item(
|
|
State(state): State<Arc<AppState>>,
|
|
Form(input): Form<CreateItem>,
|
|
) -> Html<String> {
|
|
let item = save_item(&state, input).await;
|
|
let template = ItemTemplate { item };
|
|
Html(template.render().unwrap())
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Adding Features
|
|
|
|
### Process
|
|
|
|
1. Add business logic to **botserver** first
|
|
2. Create REST API endpoint in botserver (returns HTML for HTMX)
|
|
3. Add HTTP wrapper in BotUI if needed
|
|
4. Add UI in `ui/suite/` using HTMX attributes
|
|
5. For desktop-specific: Add Tauri command in `src/desktop/`
|
|
|
|
### Desktop Tauri Command
|
|
|
|
```rust
|
|
#[tauri::command]
|
|
pub fn list_files(path: &str) -> Result<Vec<FileItem>, String> {
|
|
let entries = std::fs::read_dir(path)
|
|
.map_err(|e| e.to_string())?;
|
|
|
|
let items: Vec<FileItem> = entries
|
|
.filter_map(|e| e.ok())
|
|
.map(|e| FileItem {
|
|
name: e.file_name().to_string_lossy().to_string(),
|
|
is_dir: e.path().is_dir(),
|
|
})
|
|
.collect();
|
|
|
|
Ok(items)
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Final Steps Before Commit
|
|
|
|
```bash
|
|
# Check for warnings
|
|
cargo check 2>&1 | grep warning
|
|
|
|
# Audit dependencies (must be 0 warnings)
|
|
cargo audit
|
|
|
|
# Build both modes
|
|
cargo build
|
|
cargo build --features desktop
|
|
|
|
# Verify no dead code with _ prefixes
|
|
grep -r "let _" src/ --include="*.rs"
|
|
|
|
# Verify no CDN references
|
|
grep -r "unpkg.com\|cdnjs\|jsdelivr" ui/
|
|
```
|
|
|
|
---
|
|
|
|
## Key Files Reference
|
|
|
|
```
|
|
src/main.rs # Entry point, mode detection
|
|
src/lib.rs # Feature-gated exports
|
|
src/http_client.rs # botserverClient wrapper
|
|
src/ui_server/mod.rs # Axum router, static files
|
|
ui/suite/index.html # Main UI entry
|
|
ui/suite/base.html # Base template
|
|
ui/minimal/index.html # Minimal chat UI
|
|
```
|
|
|
|
---
|
|
|
|
## Dependencies
|
|
|
|
| Library | Version | Purpose |
|
|
|---------|---------|---------|
|
|
| axum | 0.7.5 | Web framework |
|
|
| reqwest | 0.12 | HTTP client |
|
|
| tokio | 1.41 | Async runtime |
|
|
| askama | 0.12 | HTML Templates |
|
|
| diesel | 2.1 | Database (sqlite) |
|
|
|
|
---
|
|
|
|
---
|
|
|
|
## Design System - UI Standards
|
|
|
|
**The `tasks.css` file defines the standard patterns for ALL screens in General Bots.**
|
|
|
|
All themes MUST implement these core components consistently.
|
|
|
|
### Layout Standards
|
|
|
|
```css
|
|
/* Full-height container - no global scroll */
|
|
.app-container {
|
|
display: flex;
|
|
flex-direction: column;
|
|
height: 100vh;
|
|
max-height: 100vh;
|
|
overflow: hidden;
|
|
}
|
|
|
|
/* Two-column layout - list + detail */
|
|
.main-content {
|
|
display: grid;
|
|
grid-template-columns: 320px 1fr;
|
|
flex: 1;
|
|
overflow: hidden;
|
|
height: calc(100vh - 120px);
|
|
}
|
|
|
|
/* Scrollable list panel (LEFT) */
|
|
.list-panel {
|
|
overflow-y: scroll;
|
|
overflow-x: hidden;
|
|
height: 100%;
|
|
scrollbar-width: auto;
|
|
scrollbar-color: var(--border-light) var(--surface);
|
|
}
|
|
|
|
/* Fixed detail panel (RIGHT) - no scroll */
|
|
.detail-panel {
|
|
display: flex;
|
|
flex-direction: column;
|
|
overflow: hidden;
|
|
height: 100%;
|
|
}
|
|
```
|
|
|
|
### Scrollbar Standards
|
|
|
|
```css
|
|
/* Visible scrollbar - 10px width */
|
|
.scrollable::-webkit-scrollbar {
|
|
width: 10px;
|
|
}
|
|
|
|
.scrollable::-webkit-scrollbar-track {
|
|
background: var(--surface);
|
|
border-radius: 5px;
|
|
}
|
|
|
|
.scrollable::-webkit-scrollbar-thumb {
|
|
background: var(--border-light);
|
|
border-radius: 5px;
|
|
border: 2px solid var(--surface);
|
|
}
|
|
|
|
.scrollable::-webkit-scrollbar-thumb:hover {
|
|
background: var(--primary);
|
|
}
|
|
|
|
/* Firefox */
|
|
.scrollable {
|
|
scrollbar-width: auto;
|
|
scrollbar-color: var(--border-light) var(--surface);
|
|
}
|
|
```
|
|
|
|
### Card Standards
|
|
|
|
```css
|
|
/* Base card - used in task lists, items, etc. */
|
|
.card {
|
|
background: var(--surface-hover);
|
|
border: 2px solid var(--border);
|
|
border-radius: 16px;
|
|
padding: 16px 20px;
|
|
cursor: pointer;
|
|
transition: all 0.2s ease;
|
|
position: relative;
|
|
}
|
|
|
|
.card:hover {
|
|
border-color: var(--border-hover);
|
|
background: var(--surface);
|
|
}
|
|
|
|
.card.selected {
|
|
border-color: var(--primary);
|
|
box-shadow: 0 0 0 2px var(--primary);
|
|
}
|
|
|
|
/* Card status indicator (left bar) */
|
|
.card::before {
|
|
content: "";
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
width: 5px;
|
|
height: 100%;
|
|
background: var(--text-secondary);
|
|
transition: background 0.2s ease;
|
|
}
|
|
|
|
.card.status-running::before { background: var(--primary); }
|
|
.card.status-complete::before { background: var(--success); }
|
|
.card.status-error::before { background: var(--error); }
|
|
.card.status-pending::before { background: var(--text-secondary); }
|
|
```
|
|
|
|
### Progress/Tree Indicators
|
|
|
|
```css
|
|
/* Dot indicator - shows status */
|
|
.status-dot {
|
|
width: 8px;
|
|
height: 8px;
|
|
border-radius: 50%;
|
|
flex-shrink: 0;
|
|
background: var(--text-secondary);
|
|
transition: all 0.3s ease;
|
|
}
|
|
|
|
.status-dot.running {
|
|
background: var(--primary);
|
|
box-shadow: 0 0 8px var(--primary-light);
|
|
animation: dot-pulse 1.5s ease-in-out infinite;
|
|
}
|
|
|
|
.status-dot.completed {
|
|
background: var(--primary);
|
|
}
|
|
|
|
.status-dot.pending {
|
|
background: var(--text-secondary);
|
|
}
|
|
|
|
@keyframes dot-pulse {
|
|
0%, 100% {
|
|
opacity: 1;
|
|
box-shadow: 0 0 10px var(--primary-light);
|
|
transform: scale(1);
|
|
}
|
|
50% {
|
|
opacity: 0.7;
|
|
box-shadow: 0 0 4px var(--primary-light);
|
|
transform: scale(0.9);
|
|
}
|
|
}
|
|
|
|
/* Step badge */
|
|
.step-badge {
|
|
padding: 4px 12px;
|
|
background: var(--primary);
|
|
color: var(--bg);
|
|
border-radius: 4px;
|
|
font-size: 11px;
|
|
font-weight: 600;
|
|
}
|
|
|
|
.step-badge.pending {
|
|
background: var(--surface);
|
|
color: var(--text-secondary);
|
|
}
|
|
```
|
|
|
|
### Tree/List with Children
|
|
|
|
```css
|
|
/* Parent-child expandable tree */
|
|
.tree-section {
|
|
border: 1px solid var(--border);
|
|
background: var(--surface);
|
|
border-radius: 8px;
|
|
margin: 8px 16px;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.tree-row {
|
|
display: flex;
|
|
align-items: center;
|
|
padding: 16px 20px;
|
|
cursor: pointer;
|
|
transition: background 0.15s;
|
|
}
|
|
|
|
.tree-row:hover {
|
|
background: var(--surface-hover);
|
|
}
|
|
|
|
.tree-children {
|
|
display: none;
|
|
background: var(--bg);
|
|
}
|
|
|
|
.tree-section.expanded .tree-children {
|
|
display: block;
|
|
}
|
|
|
|
.tree-child {
|
|
border-bottom: 1px solid var(--border);
|
|
padding-left: 24px;
|
|
}
|
|
|
|
.tree-item {
|
|
display: flex;
|
|
align-items: center;
|
|
padding: 8px 20px 8px 40px;
|
|
min-height: 32px;
|
|
}
|
|
```
|
|
|
|
### Fixed Panels (Terminal, Status)
|
|
|
|
```css
|
|
/* Fixed-height panel at bottom */
|
|
.fixed-panel {
|
|
flex: 0 0 120px;
|
|
height: 120px;
|
|
min-height: 120px;
|
|
max-height: 120px;
|
|
display: flex;
|
|
flex-direction: column;
|
|
overflow: hidden;
|
|
border-top: 1px solid var(--border);
|
|
}
|
|
|
|
/* Variable-height panel with scroll */
|
|
.variable-panel {
|
|
flex: 1 1 auto;
|
|
min-height: 150px;
|
|
display: flex;
|
|
flex-direction: column;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.variable-panel-content {
|
|
flex: 1 1 auto;
|
|
min-height: 0;
|
|
overflow-y: scroll;
|
|
}
|
|
```
|
|
|
|
### Status Badges
|
|
|
|
```css
|
|
.status-badge {
|
|
font-size: 11px;
|
|
font-weight: 700;
|
|
padding: 6px 12px;
|
|
border-radius: 6px;
|
|
text-transform: uppercase;
|
|
}
|
|
|
|
.status-badge.running {
|
|
background: rgba(var(--primary-rgb), 0.15);
|
|
color: var(--primary);
|
|
}
|
|
|
|
.status-badge.completed {
|
|
background: rgba(var(--success-rgb), 0.15);
|
|
color: var(--success);
|
|
}
|
|
|
|
.status-badge.error {
|
|
background: rgba(var(--error-rgb), 0.15);
|
|
color: var(--error);
|
|
}
|
|
|
|
.status-badge.pending {
|
|
background: var(--surface);
|
|
color: var(--text-secondary);
|
|
}
|
|
```
|
|
|
|
### Theme Variables Required
|
|
|
|
Every theme MUST define these CSS variables:
|
|
|
|
```css
|
|
[data-theme="your-theme"] {
|
|
/* Backgrounds */
|
|
--bg: #0a0a0a;
|
|
--surface: #161616;
|
|
--surface-hover: #1e1e1e;
|
|
|
|
/* Borders */
|
|
--border: #2a2a2a;
|
|
--border-light: #3a3a3a;
|
|
--border-hover: #4a4a4a;
|
|
|
|
/* Text */
|
|
--text: #ffffff;
|
|
--text-secondary: #888888;
|
|
--text-tertiary: #666666;
|
|
|
|
/* Primary (accent) */
|
|
--primary: #c5f82a;
|
|
--primary-hover: #d4ff3a;
|
|
--primary-light: rgba(197, 248, 42, 0.15);
|
|
|
|
/* Status colors */
|
|
--success: #22c55e;
|
|
--warning: #f59e0b;
|
|
--error: #ef4444;
|
|
--info: #3b82f6;
|
|
}
|
|
```
|
|
|
|
### Component Checklist for New Screens
|
|
|
|
When creating a new screen, ensure it has:
|
|
|
|
- [ ] Full-height container with `overflow: hidden`
|
|
- [ ] No global page scroll
|
|
- [ ] List panel with visible scrollbar (if applicable)
|
|
- [ ] Detail panel with fixed layout
|
|
- [ ] Cards with status indicator bar
|
|
- [ ] Status dots/badges using standard classes
|
|
- [ ] Tree sections if showing parent-child relationships
|
|
- [ ] Fixed terminal/status panels at bottom
|
|
- [ ] Variable content area with internal scroll
|
|
|
|
### Alert Infrastructure (Bell Notifications)
|
|
|
|
Use `window.GBAlerts` for app notifications that appear in the global bell icon:
|
|
|
|
```javascript
|
|
// Task completed (with optional app URL)
|
|
window.GBAlerts.taskCompleted("My App", "/apps/my-app/");
|
|
|
|
// Email notification
|
|
window.GBAlerts.newEmail("john@example.com", "Meeting tomorrow");
|
|
|
|
// Chat message
|
|
window.GBAlerts.newChat("John", "Hey, are you there?");
|
|
|
|
// Drive sync
|
|
window.GBAlerts.driveSync("report.pdf", "uploaded");
|
|
|
|
// Calendar reminder
|
|
window.GBAlerts.calendarReminder("Team Meeting", "15 minutes");
|
|
|
|
// Error
|
|
window.GBAlerts.error("Drive", "Failed to sync file");
|
|
|
|
// Generic notification
|
|
window.GBAlerts.add("Title", "Message", "success", "🎉");
|
|
```
|
|
|
|
All notifications appear in the bell dropdown with sound (if enabled).
|
|
|
|
---
|
|
|
|
## Remember
|
|
|
|
- **ZERO WARNINGS** - Every clippy warning must be fixed
|
|
- **NO ALLOW IN CODE** - Never use #[allow()] in source files
|
|
- **CARGO.TOML EXCEPTIONS OK** - Disable lints with false positives in Cargo.toml with comment
|
|
- **NO DEAD CODE** - Delete unused code, never prefix with _
|
|
- **NO UNWRAP/EXPECT** - Use ? operator or proper error handling
|
|
- **INLINE FORMAT ARGS** - format!("{name}") not format!("{}", name)
|
|
- **USE SELF** - In impl blocks, use Self not the type name
|
|
- **DERIVE EQ** - Always derive Eq with PartialEq
|
|
- **DISPLAY NOT TOSTRING** - Implement Display, not ToString
|
|
- **USE DIAGNOSTICS** - Use IDE diagnostics tool, never call cargo clippy directly
|
|
- **HTMX first**: Minimize JS, delegate to server
|
|
- **Local assets**: No CDN, all vendor files local
|
|
- **No business logic**: All logic in botserver
|
|
- **HTML responses**: Server returns fragments, not JSON
|
|
- **Version**: Always 6.1.0 - do not change without approval
|
|
- **Theme system**: Use data-theme attribute on body, 6 themes available
|
|
- **Session Continuation**: When running out of context, create detailed summary: (1) what was done, (2) what remains, (3) specific files and line numbers, (4) exact next steps. |