719 lines
21 KiB
Markdown
719 lines
21 KiB
Markdown
# 🎨 Crumbforest Roles & Groups Architecture
|
||
|
||
## 🎯 Vision
|
||
|
||
**Statt 8x .sh Files → 1x JSON Config mit Rollen, Gruppen & Themes**
|
||
|
||
### Ziele:
|
||
1. ✅ **Unified Role System** - Ein JSON statt vieler Shell Scripts
|
||
2. ✅ **Group-based Theming** - CSS/Template per Gruppe (#barrierefrei)
|
||
3. ✅ **Module Loading** - Zusätzliche Features per Gruppe
|
||
4. ✅ **Separation** - home/demo/admin mit eigenen Designs
|
||
5. ✅ **Web UI** - HTML Interface für Roles (nicht nur Terminal)
|
||
|
||
---
|
||
|
||
## 📋 JSON Schema: `crumbforest_config.json`
|
||
|
||
```json
|
||
{
|
||
"version": "1.0.0",
|
||
"groups": {
|
||
"home": {
|
||
"name": "Home (Öffentlich)",
|
||
"theme": "pico-default",
|
||
"template_base": "base_public.html",
|
||
"css_files": ["pico.min.css", "crumbforest_public.css"],
|
||
"features": ["info", "contact"],
|
||
"navbar": ["home", "about", "contact"],
|
||
"description": "Neutrale öffentliche Ansicht"
|
||
},
|
||
"demo": {
|
||
"name": "Demo User",
|
||
"theme": "pico-accessible",
|
||
"template_base": "base_demo.html",
|
||
"css_files": ["pico.min.css", "crumbforest_accessible.css"],
|
||
"features": ["roles_web", "search", "chat"],
|
||
"navbar": ["dashboard", "roles", "search"],
|
||
"description": "Demo-Zugang mit Role-Chat UI"
|
||
},
|
||
"admin": {
|
||
"name": "Admin",
|
||
"theme": "pico-admin",
|
||
"template_base": "base_admin.html",
|
||
"css_files": ["pico.min.css", "crumbforest_admin.css"],
|
||
"features": ["roles_web", "roles_terminal", "search", "rag_admin", "user_management"],
|
||
"navbar": ["dashboard", "roles", "rag", "users", "settings"],
|
||
"description": "Vollzugriff mit Terminal-Zugang"
|
||
},
|
||
"accessible": {
|
||
"name": "Barrierefrei",
|
||
"theme": "pico-high-contrast",
|
||
"template_base": "base_accessible.html",
|
||
"css_files": ["pico.min.css", "crumbforest_high_contrast.css", "screen_reader.css"],
|
||
"features": ["roles_web", "search", "tts", "high_contrast"],
|
||
"navbar": ["dashboard", "roles", "search", "settings"],
|
||
"font_size": "large",
|
||
"contrast": "high",
|
||
"description": "Hochkontrast, große Schrift, TTS"
|
||
}
|
||
},
|
||
|
||
"roles": {
|
||
"dumbo": {
|
||
"id": "dumbo",
|
||
"name": "🐘 DumboSQL",
|
||
"title": "SQL Translator",
|
||
"description": "A kind and patient SQL translator in the Crumbforest",
|
||
"model": "openai/gpt-3.5-turbo",
|
||
"temperature": 0.4,
|
||
"system_prompt": "You are DumboSQL – a kind and patient SQL translator in the Crumbforest. You speak to children like a gentle teacher with a big heart. You remember previous questions when helpful, and always respond in a friendly, encouraging, and clear way.",
|
||
"group_access": ["demo", "admin"],
|
||
"features": ["chat", "history", "sql_formatting"],
|
||
"icon": "🐘",
|
||
"color": "#6c757d",
|
||
"tags": ["sql", "database", "beginner-friendly"]
|
||
},
|
||
|
||
"snakepy": {
|
||
"id": "snakepy",
|
||
"name": "🐍 SnakePy",
|
||
"title": "Python Expert",
|
||
"description": "A wise python who teaches programming with patience",
|
||
"model": "openai/gpt-4o-mini",
|
||
"temperature": 0.3,
|
||
"system_prompt": "You are SnakePy – a wise and friendly Python expert in the Crumbforest. You explain Python concepts clearly, provide working code examples, and encourage learners. You are patient and adapt to the user's skill level.",
|
||
"group_access": ["demo", "admin"],
|
||
"features": ["chat", "history", "code_execution", "syntax_highlighting"],
|
||
"icon": "🐍",
|
||
"color": "#3776ab",
|
||
"tags": ["python", "coding", "teaching"]
|
||
},
|
||
|
||
"pepperphp": {
|
||
"id": "pepperphp",
|
||
"name": "🌶️ PepperPHP",
|
||
"title": "PHP Specialist",
|
||
"description": "A spicy PHP expert with a passion for web development",
|
||
"model": "openai/gpt-4o-mini",
|
||
"temperature": 0.3,
|
||
"system_prompt": "You are PepperPHP – a passionate PHP expert in the Crumbforest. You love web development, know all PHP versions, and can help with frameworks like Laravel, Symfony. You're enthusiastic but also practical.",
|
||
"group_access": ["demo", "admin"],
|
||
"features": ["chat", "history", "code_execution", "composer_help"],
|
||
"icon": "🌶️",
|
||
"color": "#777bb4",
|
||
"tags": ["php", "web", "backend"]
|
||
},
|
||
|
||
"templatus": {
|
||
"id": "templatus",
|
||
"name": "📄 Templatus",
|
||
"title": "Template Master",
|
||
"description": "Expert for Jinja2, HTML, and frontend templating",
|
||
"model": "anthropic/claude-3-5-sonnet",
|
||
"temperature": 0.3,
|
||
"system_prompt": "You are Templatus – a meticulous template expert in the Crumbforest. You master Jinja2, HTML, CSS, and creating beautiful, accessible web interfaces. You value clean code and user experience.",
|
||
"group_access": ["demo", "admin"],
|
||
"features": ["chat", "history", "template_preview", "html_validator"],
|
||
"icon": "📄",
|
||
"color": "#e44d26",
|
||
"tags": ["templates", "html", "jinja2", "frontend"]
|
||
},
|
||
|
||
"funkfox": {
|
||
"id": "funkfox",
|
||
"name": "🦊 FunkFox",
|
||
"title": "JavaScript Wizard",
|
||
"description": "A clever fox who makes JavaScript fun and functional",
|
||
"model": "openai/gpt-4o-mini",
|
||
"temperature": 0.4,
|
||
"system_prompt": "You are FunkFox – a clever and playful JavaScript expert in the Crumbforest. You make JS fun, teach functional programming, and help with modern frameworks like React, Vue. You're enthusiastic about clean code.",
|
||
"group_access": ["demo", "admin"],
|
||
"features": ["chat", "history", "code_execution", "npm_help"],
|
||
"icon": "🦊",
|
||
"color": "#f7df1e",
|
||
"tags": ["javascript", "frontend", "functional"]
|
||
},
|
||
|
||
"schraubaer": {
|
||
"id": "schraubaer",
|
||
"name": "🔧 Schraubaer",
|
||
"title": "Hardware Helper",
|
||
"description": "A handy bear who knows everything about Raspberry Pi and hardware",
|
||
"model": "openai/gpt-4o-mini",
|
||
"temperature": 0.3,
|
||
"system_prompt": "You are Schraubaer – a practical hardware expert in the Crumbforest. You know Raspberry Pi, Arduino, electronics, and Linux systems. You give clear, hands-on advice for building and fixing things.",
|
||
"group_access": ["demo", "admin"],
|
||
"features": ["chat", "history", "gpio_help", "circuit_diagrams"],
|
||
"icon": "🔧",
|
||
"color": "#c51a4a",
|
||
"tags": ["hardware", "raspberry-pi", "electronics"]
|
||
},
|
||
|
||
"schnecki": {
|
||
"id": "schnecki",
|
||
"name": "🐌 Schnecki",
|
||
"title": "Slow Tech Guide",
|
||
"description": "A gentle snail who teaches mindful, sustainable technology",
|
||
"model": "anthropic/claude-3-5-sonnet",
|
||
"temperature": 0.6,
|
||
"system_prompt": "You are Schnecki – a gentle and wise slow-tech advocate in the Crumbforest. You teach mindful technology use, sustainability, energy efficiency, and the value of taking time. You encourage breaks and reflection.",
|
||
"group_access": ["demo", "admin"],
|
||
"features": ["chat", "history", "mindfulness_tips", "green_tech"],
|
||
"icon": "🐌",
|
||
"color": "#8b4513",
|
||
"tags": ["slow-tech", "sustainability", "mindfulness"]
|
||
},
|
||
|
||
"kungfutaube": {
|
||
"id": "kungfutaube",
|
||
"name": "🕊️ KungfuTaube",
|
||
"title": "Security Sensei",
|
||
"description": "A peaceful but vigilant dove teaching web security",
|
||
"model": "anthropic/claude-3-5-sonnet",
|
||
"temperature": 0.2,
|
||
"system_prompt": "You are KungfuTaube – a calm but alert security expert in the Crumbforest. You teach web security, DSGVO compliance, safe coding practices, and encryption. You balance protection with usability.",
|
||
"group_access": ["admin"],
|
||
"features": ["chat", "history", "security_scan", "dsgvo_check"],
|
||
"icon": "🕊️",
|
||
"color": "#6f42c1",
|
||
"tags": ["security", "dsgvo", "encryption", "admin-only"]
|
||
}
|
||
},
|
||
|
||
"theme_variants": {
|
||
"pico-default": {
|
||
"name": "Standard",
|
||
"css": "pico.min.css",
|
||
"colors": {
|
||
"primary": "#1095c1",
|
||
"secondary": "#6c757d",
|
||
"contrast": "#000000"
|
||
}
|
||
},
|
||
"pico-accessible": {
|
||
"name": "Barrierefrei",
|
||
"css": "pico.min.css",
|
||
"custom_css": "accessible.css",
|
||
"colors": {
|
||
"primary": "#0066cc",
|
||
"secondary": "#333333",
|
||
"contrast": "#ffffff"
|
||
},
|
||
"font_size_base": "18px",
|
||
"line_height": "1.8"
|
||
},
|
||
"pico-high-contrast": {
|
||
"name": "Hochkontrast",
|
||
"css": "pico.min.css",
|
||
"custom_css": "high_contrast.css",
|
||
"colors": {
|
||
"primary": "#ffff00",
|
||
"secondary": "#ffffff",
|
||
"contrast": "#000000",
|
||
"background": "#000000",
|
||
"text": "#ffffff"
|
||
},
|
||
"font_size_base": "20px",
|
||
"line_height": "2.0",
|
||
"border_width": "3px"
|
||
},
|
||
"pico-admin": {
|
||
"name": "Admin Dark",
|
||
"css": "pico.min.css",
|
||
"custom_css": "admin_dark.css",
|
||
"colors": {
|
||
"primary": "#00d4aa",
|
||
"secondary": "#6c757d",
|
||
"contrast": "#ffffff",
|
||
"background": "#1a1a1a",
|
||
"text": "#e0e0e0"
|
||
}
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 🏗️ Architektur-Komponenten
|
||
|
||
### 1. FastAPI Router: `/routers/crumbforest_roles.py`
|
||
|
||
```python
|
||
from fastapi import APIRouter, Depends, Request, Form
|
||
from fastapi.responses import HTMLResponse, JSONResponse
|
||
import httpx
|
||
from typing import Optional
|
||
|
||
router = APIRouter()
|
||
|
||
# Load config
|
||
import json
|
||
with open('crumbforest_config.json') as f:
|
||
config = json.load(f)
|
||
|
||
@router.get("/roles", response_class=HTMLResponse)
|
||
async def roles_dashboard(req: Request, user = Depends(current_user)):
|
||
"""
|
||
Show available roles based on user's group.
|
||
"""
|
||
user_group = user.get('group', 'demo')
|
||
|
||
# Filter roles by group access
|
||
available_roles = {
|
||
rid: role for rid, role in config['roles'].items()
|
||
if user_group in role['group_access']
|
||
}
|
||
|
||
return req.app.state.render(
|
||
req,
|
||
"crumbforest/roles_dashboard.html",
|
||
roles=available_roles,
|
||
user_group=user_group
|
||
)
|
||
|
||
@router.get("/roles/{role_id}", response_class=HTMLResponse)
|
||
async def role_chat(req: Request, role_id: str, user = Depends(current_user)):
|
||
"""
|
||
Chat interface for a specific role.
|
||
"""
|
||
role = config['roles'].get(role_id)
|
||
if not role:
|
||
raise HTTPException(404, "Role not found")
|
||
|
||
user_group = user.get('group', 'demo')
|
||
if user_group not in role['group_access']:
|
||
raise HTTPException(403, "Access denied")
|
||
|
||
return req.app.state.render(
|
||
req,
|
||
"crumbforest/role_chat.html",
|
||
role=role
|
||
)
|
||
|
||
@router.post("/roles/{role_id}/ask")
|
||
async def ask_role(
|
||
req: Request,
|
||
role_id: str,
|
||
question: str = Form(...),
|
||
user = Depends(current_user)
|
||
):
|
||
"""
|
||
Send question to role and get AI response.
|
||
"""
|
||
role = config['roles'].get(role_id)
|
||
if not role:
|
||
raise HTTPException(404, "Role not found")
|
||
|
||
# Get conversation history from session
|
||
history = req.session.get(f'role_history_{role_id}', [])
|
||
|
||
# Build messages
|
||
messages = [
|
||
{"role": "system", "content": role['system_prompt']}
|
||
] + history + [
|
||
{"role": "user", "content": question}
|
||
]
|
||
|
||
# Call OpenRouter API
|
||
async with httpx.AsyncClient() as client:
|
||
response = await client.post(
|
||
"https://openrouter.ai/api/v1/chat/completions",
|
||
headers={
|
||
"Authorization": f"Bearer {settings.openrouter_api_key}",
|
||
"Content-Type": "application/json"
|
||
},
|
||
json={
|
||
"model": role['model'],
|
||
"temperature": role['temperature'],
|
||
"messages": messages
|
||
}
|
||
)
|
||
result = response.json()
|
||
|
||
answer = result['choices'][0]['message']['content']
|
||
|
||
# Update history
|
||
history.append({"role": "user", "content": question})
|
||
history.append({"role": "assistant", "content": answer})
|
||
req.session[f'role_history_{role_id}'] = history[-10:] # Keep last 10
|
||
|
||
return JSONResponse({
|
||
"role": role_id,
|
||
"question": question,
|
||
"answer": answer,
|
||
"usage": result.get('usage', {})
|
||
})
|
||
```
|
||
|
||
### 2. Template: `templates/crumbforest/roles_dashboard.html`
|
||
|
||
```html
|
||
{% extends group_config.template_base %}
|
||
|
||
{% block title %}Crumbforest Roles{% endblock %}
|
||
|
||
{% block content %}
|
||
<main class="container">
|
||
<hgroup>
|
||
<h1>🌲 Crumbforest Characters</h1>
|
||
<p>Choose your learning companion!</p>
|
||
</hgroup>
|
||
|
||
<div class="grid">
|
||
{% for role_id, role in roles.items() %}
|
||
<article>
|
||
<header>
|
||
<h3>
|
||
<span style="font-size: 2em;">{{ role.icon }}</span>
|
||
{{ role.name }}
|
||
</h3>
|
||
<p><small>{{ role.title }}</small></p>
|
||
</header>
|
||
|
||
<p>{{ role.description }}</p>
|
||
|
||
<footer>
|
||
<div style="display: flex; gap: 0.5rem; flex-wrap: wrap;">
|
||
{% for tag in role.tags %}
|
||
<span class="badge" style="background: {{ role.color }}20; color: {{ role.color }};">
|
||
#{{ tag }}
|
||
</span>
|
||
{% endfor %}
|
||
</div>
|
||
|
||
<a href="/crumbforest/roles/{{ role_id }}" role="button">
|
||
Chat with {{ role.name }}
|
||
</a>
|
||
</footer>
|
||
</article>
|
||
{% endfor %}
|
||
</div>
|
||
</main>
|
||
{% endblock %}
|
||
```
|
||
|
||
### 3. Template: `templates/crumbforest/role_chat.html`
|
||
|
||
```html
|
||
{% extends group_config.template_base %}
|
||
|
||
{% block title %}{{ role.name }} - Chat{% endblock %}
|
||
|
||
{% block content %}
|
||
<main class="container">
|
||
<hgroup>
|
||
<h1>{{ role.icon }} {{ role.name }}</h1>
|
||
<p>{{ role.description }}</p>
|
||
</hgroup>
|
||
|
||
<article id="chat-container">
|
||
<div id="messages" style="max-height: 500px; overflow-y: auto; padding: 1rem;">
|
||
<!-- Messages will be added here via JS -->
|
||
</div>
|
||
|
||
<footer>
|
||
<form id="chat-form">
|
||
<div class="grid">
|
||
<input
|
||
type="text"
|
||
name="question"
|
||
id="question-input"
|
||
placeholder="Ask {{ role.name }} something..."
|
||
required
|
||
autofocus
|
||
>
|
||
<button type="submit">Send</button>
|
||
</div>
|
||
</form>
|
||
</footer>
|
||
</article>
|
||
</main>
|
||
|
||
<script>
|
||
const roleId = "{{ role.id }}";
|
||
const chatForm = document.getElementById('chat-form');
|
||
const messagesDiv = document.getElementById('messages');
|
||
const questionInput = document.getElementById('question-input');
|
||
|
||
chatForm.addEventListener('submit', async (e) => {
|
||
e.preventDefault();
|
||
|
||
const question = questionInput.value;
|
||
if (!question.trim()) return;
|
||
|
||
// Add user message
|
||
addMessage('user', question);
|
||
questionInput.value = '';
|
||
|
||
// Show loading
|
||
const loadingId = addMessage('assistant', '{{ role.icon }} thinking...');
|
||
|
||
try {
|
||
const formData = new FormData();
|
||
formData.append('question', question);
|
||
|
||
const response = await fetch(`/crumbforest/roles/${roleId}/ask`, {
|
||
method: 'POST',
|
||
body: formData
|
||
});
|
||
|
||
const data = await response.json();
|
||
|
||
// Remove loading, add real response
|
||
document.getElementById(loadingId).remove();
|
||
addMessage('assistant', data.answer);
|
||
|
||
} catch (error) {
|
||
document.getElementById(loadingId).remove();
|
||
addMessage('error', 'Oops! Something went wrong.');
|
||
}
|
||
});
|
||
|
||
function addMessage(role, content) {
|
||
const msgId = 'msg-' + Date.now();
|
||
const div = document.createElement('div');
|
||
div.id = msgId;
|
||
div.style.marginBottom = '1rem';
|
||
div.style.padding = '1rem';
|
||
div.style.borderRadius = '8px';
|
||
|
||
if (role === 'user') {
|
||
div.style.background = '#e3f2fd';
|
||
div.style.textAlign = 'right';
|
||
div.innerHTML = `<strong>You:</strong><br>${content}`;
|
||
} else if (role === 'assistant') {
|
||
div.style.background = '#f5f5f5';
|
||
div.innerHTML = `<strong>{{ role.name }}:</strong><br>${content}`;
|
||
} else {
|
||
div.style.background = '#ffebee';
|
||
div.innerHTML = `<strong>Error:</strong><br>${content}`;
|
||
}
|
||
|
||
messagesDiv.appendChild(div);
|
||
messagesDiv.scrollTop = messagesDiv.scrollHeight;
|
||
|
||
return msgId;
|
||
}
|
||
</script>
|
||
{% endblock %}
|
||
```
|
||
|
||
### 4. User Model Extension: `app/models/user.py`
|
||
|
||
```python
|
||
# Extend users table
|
||
"""
|
||
ALTER TABLE users
|
||
ADD COLUMN user_group VARCHAR(50) DEFAULT 'demo',
|
||
ADD COLUMN theme VARCHAR(50) DEFAULT 'pico-default',
|
||
ADD COLUMN accessibility JSON DEFAULT NULL;
|
||
"""
|
||
|
||
# Example accessibility JSON:
|
||
{
|
||
"font_size": "large",
|
||
"high_contrast": true,
|
||
"screen_reader": true,
|
||
"animation_reduced": true
|
||
}
|
||
```
|
||
|
||
### 5. Base Template with Group Support: `templates/base_demo.html`
|
||
|
||
```html
|
||
<!DOCTYPE html>
|
||
<html lang="{{ lang }}" data-theme="{{ user.theme or 'auto' }}">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>{% block title %}Crumbforest{% endblock %}</title>
|
||
|
||
<!-- Load CSS based on group config -->
|
||
{% for css_file in group_config.css_files %}
|
||
<link rel="stylesheet" href="/static/css/{{ css_file }}">
|
||
{% endfor %}
|
||
|
||
{% if user.accessibility %}
|
||
<style>
|
||
:root {
|
||
{% if user.accessibility.font_size == 'large' %}
|
||
font-size: 120%;
|
||
{% endif %}
|
||
|
||
{% if user.accessibility.high_contrast %}
|
||
--primary: #ffff00;
|
||
--background-color: #000000;
|
||
--color: #ffffff;
|
||
{% endif %}
|
||
}
|
||
|
||
{% if user.accessibility.animation_reduced %}
|
||
* {
|
||
animation: none !important;
|
||
transition: none !important;
|
||
}
|
||
{% endif %}
|
||
</style>
|
||
{% endif %}
|
||
</head>
|
||
<body>
|
||
<nav>
|
||
<ul>
|
||
<li><strong>🌲 Crumbforest</strong></li>
|
||
</ul>
|
||
<ul>
|
||
{% for nav_item in group_config.navbar %}
|
||
{% if nav_item == 'dashboard' %}
|
||
<li><a href="/dashboard">Dashboard</a></li>
|
||
{% elif nav_item == 'roles' %}
|
||
<li><a href="/crumbforest/roles">Characters</a></li>
|
||
{% elif nav_item == 'search' %}
|
||
<li><a href="/search">Search</a></li>
|
||
{% endif %}
|
||
{% endfor %}
|
||
|
||
<li>
|
||
<details class="dropdown">
|
||
<summary>{{ user.email }}</summary>
|
||
<ul dir="rtl">
|
||
<li><a href="/settings">Settings</a></li>
|
||
<li>
|
||
<form action="/logout" method="post" style="margin:0;">
|
||
<button type="submit" class="contrast">Logout</button>
|
||
</form>
|
||
</li>
|
||
</ul>
|
||
</details>
|
||
</li>
|
||
</ul>
|
||
</nav>
|
||
|
||
{% block content %}{% endblock %}
|
||
|
||
<footer>
|
||
<small>
|
||
Group: {{ group_config.name }} |
|
||
Theme: {{ user.theme }} |
|
||
Made with 💚 in the Crumbforest
|
||
</small>
|
||
</footer>
|
||
</body>
|
||
</html>
|
||
```
|
||
|
||
---
|
||
|
||
## 📊 Implementierungs-Phasen
|
||
|
||
### Phase 1: Foundation (Tag 1-2)
|
||
- [ ] `crumbforest_config.json` erstellen
|
||
- [ ] User-Model erweitern (group, theme, accessibility)
|
||
- [ ] Config-Loader Service
|
||
- [ ] Base Templates für Gruppen (home, demo, admin, accessible)
|
||
|
||
### Phase 2: Role System (Tag 3-4)
|
||
- [ ] `/routers/crumbforest_roles.py` implementieren
|
||
- [ ] Roles Dashboard Template
|
||
- [ ] Chat Interface Template
|
||
- [ ] Session-based History
|
||
- [ ] OpenRouter API Integration
|
||
|
||
### Phase 3: Theme System (Tag 5-6)
|
||
- [ ] CSS Variants (default, accessible, high-contrast, admin)
|
||
- [ ] Theme Switcher UI
|
||
- [ ] User Settings Page
|
||
- [ ] Accessibility Controls (font size, contrast, TTS)
|
||
|
||
### Phase 4: Migration (Tag 7)
|
||
- [ ] Shell Scripts → JSON Config migrieren
|
||
- [ ] Testing aller 8 Roles
|
||
- [ ] Demo User einrichten
|
||
- [ ] Branko.de Integration (Static pages)
|
||
|
||
### Phase 5: Features (Tag 8-10)
|
||
- [ ] Code Execution (für SnakePy, PepperPHP)
|
||
- [ ] Syntax Highlighting
|
||
- [ ] Role-spezifische Features
|
||
- [ ] Export Chat History
|
||
- [ ] Token Usage Tracking
|
||
|
||
---
|
||
|
||
## 🎨 Vorteile dieser Architektur
|
||
|
||
### ✅ Wartbarkeit
|
||
- **Ein JSON** statt 8 Shell Scripts
|
||
- Zentralisierte Konfiguration
|
||
- Einfaches Hinzufügen neuer Roles
|
||
|
||
### ✅ Flexibilität
|
||
- Gruppen-basiertes Theming
|
||
- Modul-basierte Features
|
||
- Multi-Tenant fähig
|
||
|
||
### ✅ Barrierefreiheit
|
||
- High-Contrast Theme
|
||
- Große Schrift
|
||
- Screen Reader Support
|
||
- Animation-Reduktion
|
||
|
||
### ✅ Separation of Concerns
|
||
- **Home**: Öffentlich, neutral, Info
|
||
- **Demo**: Role-Chat, Read-Only
|
||
- **Admin**: Voller Zugriff, Terminal, RAG
|
||
|
||
### ✅ Extensibility
|
||
- Neue Roles via JSON
|
||
- Neue Gruppen ohne Code-Änderung
|
||
- Theme-Varianten einfach hinzufügen
|
||
- Features als Plugins
|
||
|
||
---
|
||
|
||
## 🚀 Quick Start (Nach Implementierung)
|
||
|
||
```python
|
||
# 1. User mit Gruppe erstellen
|
||
user = {
|
||
"email": "demo@crumb.local",
|
||
"group": "demo",
|
||
"theme": "pico-accessible"
|
||
}
|
||
|
||
# 2. Role-Chat öffnen
|
||
GET /crumbforest/roles/dumbo
|
||
|
||
# 3. Frage stellen
|
||
POST /crumbforest/roles/dumbo/ask
|
||
{
|
||
"question": "Wie erstelle ich eine SQL-Tabelle?"
|
||
}
|
||
|
||
# 4. Theme wechseln
|
||
POST /settings/theme
|
||
{
|
||
"theme": "pico-high-contrast",
|
||
"accessibility": {
|
||
"font_size": "large",
|
||
"high_contrast": true
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 🦉 Fazit
|
||
|
||
Diese Architektur:
|
||
- ✅ Ersetzt 8 Shell Scripts durch 1 JSON
|
||
- ✅ Ermöglicht Web UI für Roles
|
||
- ✅ Unterstützt Barrierefreiheit
|
||
- ✅ Trennt home/demo/admin sauber
|
||
- ✅ Ist erweiterbar & wartbar
|
||
- ✅ Behält Pico CSS bei
|
||
- ✅ Funktioniert mit bestehendem FastAPI Setup
|
||
|
||
**Ready to implement?** 🌲
|