mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-15 01:01:09 +02:00
Move inactive projects out of active workspace: - bauntown (community website) - maerchenzauber (AI story generation) - memoro (voice memo app) - news (news aggregation) - nutriphi (nutrition tracking) - reader (reading app) - uload (URL shortener) - wisekeep (AI wisdom extraction) Update CLAUDE.md documentation: - Add presi to active projects - Document archived projects section - Update workspace configuration Archived apps can be re-activated by moving back to apps/ 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
12 KiB
12 KiB
Server-Side HTML Cards - Konzept & Analyse
Executive Summary
Die Idee, Cards als reinen HTML/CSS-Code serverseitig zu rendern, bietet maximale Flexibilität für Nutzer und könnte das bestehende modulare System ergänzen oder ersetzen. Dieser Ansatz würde es ermöglichen, dass Nutzer komplett eigene Designs erstellen können, während gleichzeitig die Aspect Ratio und Container-Constraints eingehalten werden.
🎯 Konzept-Übersicht
Grundidee
<!-- Nutzer definiert HTML/CSS -->
<div class="custom-card">
<style>
.custom-card {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
padding: 2rem;
color: white;
}
.custom-card h2 {
font-size: 2rem;
}
</style>
<h2>{{username}}</h2>
<p>{{bio}}</p>
</div>
Server rendert zu:
<div class="card-container" style="aspect-ratio: 16/9;">
<iframe srcdoc="..." sandbox="allow-same-origin" style="width: 100%; height: 100%; border: none;">
<!-- Nutzer HTML/CSS isoliert in iframe -->
</iframe>
</div>
📊 Vergleich der Ansätze
| Aspekt | Modulares System (aktuell) | HTML/CSS System | Hybrid-Ansatz |
|---|---|---|---|
| Flexibilität | Mittel | Sehr hoch | Hoch |
| Sicherheit | Hoch | Niedrig-Mittel | Mittel-Hoch |
| Performance | Sehr gut | Gut | Gut |
| Nutzer-Komplexität | Niedrig | Hoch | Variabel |
| Wartbarkeit | Sehr gut | Schlecht | Mittel |
| Datenbank | Komplex | Einfach | Mittel |
✅ Vorteile Server-Side HTML Cards
1. Maximale Kreativität
- Nutzer können JEDES Design umsetzen
- Keine Einschränkungen durch vordefinierte Module
- Custom Animationen und Effekte möglich
- Einzigartige Layouts
2. Einfachere Datenbank
-- Statt komplexer JSON-Strukturen
CREATE TABLE cards (
id TEXT PRIMARY KEY,
user_id TEXT,
html_content TEXT,
css_content TEXT,
variables JSON, -- Für Template-Variablen
created_at TIMESTAMP
);
3. Portabilität
- HTML/CSS ist universell
- Kann in jede Plattform exportiert werden
- Keine Framework-Abhängigkeiten
4. Learning Opportunity
- Nutzer lernen HTML/CSS
- Community kann Code teilen
- Inspiration durch andere Designs
❌ Nachteile & Risiken
1. Sicherheitsrisiken
// XSS-Gefahr
<script>alert('XSS')</script>
// CSS-Injection
<style>
body { display: none !important; }
</style>
// Clickjacking
<a href="javascript:void(0)" onclick="stealData()">
2. Performance-Probleme
- Unkontrollierte CSS-Animationen
- Große Bilder/Assets
- Ineffiziente Selektoren
- Memory Leaks durch JavaScript
3. Responsive Design
- Nutzer müssen selbst Media Queries schreiben
- Inkonsistente Mobile-Ansichten
- Aspect Ratio schwer zu garantieren
4. Wartbarkeit
- Kein Type-Checking
- Schwer zu debuggen
- Updates kompliziert
- Keine einheitliche Code-Qualität
🔒 Sicherheitskonzept
1. Sandboxing mit iframes
<iframe
srcdoc="{{sanitized_html}}"
sandbox="allow-same-origin"
csp="default-src 'self'; script-src 'none';"
loading="lazy"
/>
2. HTML/CSS Sanitization
import DOMPurify from 'isomorphic-dompurify';
import { sanitizeCSS } from 'css-tree';
function sanitizeCardContent(html, css) {
// HTML säubern
const cleanHTML = DOMPurify.sanitize(html, {
ALLOWED_TAGS: ['div', 'span', 'p', 'h1', 'h2', 'h3', 'img', 'a'],
ALLOWED_ATTR: ['class', 'id', 'href', 'src', 'alt', 'style'],
FORBID_TAGS: ['script', 'iframe', 'object', 'embed', 'form'],
FORBID_ATTR: ['onclick', 'onload', 'onerror']
});
// CSS säubern
const cleanCSS = sanitizeCSS(css, {
removeImports: true,
removeJavaScript: true,
limitSelectors: true,
maxNesting: 3
});
return { html: cleanHTML, css: cleanCSS };
}
3. Content Security Policy
// Server-Header
response.headers.set(
'Content-Security-Policy',
"default-src 'self'; " +
"style-src 'self' 'unsafe-inline'; " +
"script-src 'none'; " +
"img-src 'self' data: https:;"
);
🎨 Hybrid-Ansatz (EMPFEHLUNG)
Konzept: "Progressive Enhancement"
interface CardDefinition {
type: 'modular' | 'template' | 'custom-html';
// Für modulare Cards (wie bisher)
modules?: ModuleConfig[];
// Für Template-basierte Cards
template?: string;
templateVars?: Record<string, any>;
// Für Custom HTML
customHTML?: string;
customCSS?: string;
// Gemeinsame Properties
constraints?: {
aspectRatio?: string;
maxWidth?: string;
minHeight?: string;
};
}
Drei Ebenen der Anpassung:
Level 1: Module Builder (Anfänger)
{
type: 'modular',
modules: [
{ type: 'header', props: { title: 'Meine Karte' } }
]
}
Level 2: Template Editor (Fortgeschritten)
{ type: 'template', template: `
<div class='card-template'>
<h2>{{title}}</h2>
<p>{{description}}</p>
</div>
`, templateVars: { title: 'Titel', description: 'Text' } }
Level 3: Custom HTML/CSS (Experten)
{
type: 'custom-html',
customHTML: '<div class="my-card">...</div>',
customCSS: '.my-card { ... }'
}
💻 Implementierungsplan
Phase 1: Basis-Infrastruktur (Woche 1-2)
1.1 Sanitization Layer
// src/lib/services/cardSanitizer.ts
export class CardSanitizer {
sanitizeHTML(html: string): string;
sanitizeCSS(css: string): string;
validateConstraints(html: string, constraints: Constraints): boolean;
extractVariables(html: string): string[];
}
1.2 Rendering Engine
<!-- src/lib/components/cards/CustomHTMLCard.svelte -->
<script lang="ts">
import { sanitizeCard } from '$lib/services/cardSanitizer';
export let html: string;
export let css: string;
export let variables: Record<string, any> = {};
export let aspectRatio: string = '16/9';
$: sanitized = sanitizeCard(html, css);
$: rendered = replaceVariables(sanitized.html, variables);
</script>
<div class="custom-card-container" style="aspect-ratio: {aspectRatio}">
<iframe
srcdoc={`
<!DOCTYPE html>
<html>
<head>
<style>${sanitized.css}</style>
<style>
body { margin: 0; padding: 0; height: 100vh; display: flex; }
.card-content { flex: 1; }
</style>
</head>
<body>
<div class="card-content">${rendered}</div>
</body>
</html>
`}
sandbox="allow-same-origin"
loading="lazy"
title="Custom Card"
/>
</div>
Phase 2: Editor & Preview (Woche 3-4)
2.1 HTML/CSS Editor
<!-- src/lib/components/builder/HTMLCardEditor.svelte -->
<script>
import CodeMirror from 'codemirror';
import 'codemirror/mode/htmlmixed/htmlmixed';
import 'codemirror/mode/css/css';
export let html = '';
export let css = '';
export let onUpdate;
// Live Preview
$: preview = generatePreview(html, css);
</script>
<div class="editor-container">
<div class="editors">
<div class="html-editor">
<CodeMirror bind:value={html} mode="htmlmixed" />
</div>
<div class="css-editor">
<CodeMirror bind:value={css} mode="css" />
</div>
</div>
<div class="preview">
<CustomHTMLCard {html} {css} />
</div>
</div>
2.2 Template Variables
interface TemplateVariable {
name: string;
type: 'text' | 'number' | 'image' | 'link' | 'list';
default?: any;
required?: boolean;
}
// Variable extraction
function extractVariables(html: string): TemplateVariable[] {
const regex = /\{\{(\w+)(?::(\w+))?\}\}/g;
const variables: TemplateVariable[] = [];
let match;
while ((match = regex.exec(html)) !== null) {
variables.push({
name: match[1],
type: match[2] || 'text',
required: true
});
}
return variables;
}
Phase 3: Datenbank-Migration (Woche 5)
Neue Datenbank-Struktur
-- Erweiterte cards Tabelle
ALTER TABLE cards ADD COLUMN render_type TEXT DEFAULT 'modular';
ALTER TABLE cards ADD COLUMN html_content TEXT;
ALTER TABLE cards ADD COLUMN css_content TEXT;
ALTER TABLE cards ADD COLUMN template_variables JSON;
ALTER TABLE cards ADD COLUMN constraints JSON;
-- Versionierung für Custom Cards
CREATE TABLE card_versions (
id TEXT PRIMARY KEY,
card_id TEXT REFERENCES cards(id),
version INTEGER,
html_content TEXT,
css_content TEXT,
created_at TIMESTAMP,
change_note TEXT
);
Phase 4: Builder Integration (Woche 6)
<!-- Erweiterter Card Builder -->
<script>
let builderMode: 'visual' | 'template' | 'code' = 'visual';
</script>
<div class="builder-modes">
<button class:active={builderMode === 'visual'} on:click={() => (builderMode = 'visual')}>
Visual Builder (Module)
</button>
<button class:active={builderMode === 'template'} on:click={() => (builderMode = 'template')}>
Template Editor
</button>
<button class:active={builderMode === 'code'} on:click={() => (builderMode = 'code')}>
HTML/CSS Code
</button>
</div>
{#if builderMode === 'visual'}
<CardBuilder />
{:else if builderMode === 'template'}
<TemplateEditor />
{:else}
<HTMLCardEditor />
{/if}
🏗️ Technische Architektur
Rendering Pipeline
User Input (HTML/CSS)
↓
Sanitization Layer
↓
Variable Replacement
↓
Constraint Validation
↓
iframe Sandboxing
↓
Final Render
Aspect Ratio Enforcement
/* Container styles */
.card-container {
position: relative;
width: 100%;
aspect-ratio: var(--card-aspect-ratio, 16/9);
overflow: hidden;
}
.card-container iframe {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
border: none;
}
/* Inside iframe */
body {
margin: 0;
padding: 0;
width: 100vw;
height: 100vh;
overflow: auto;
}
📈 Migration Strategy
Schritt 1: Parallel-Betrieb
- Bestehendes System bleibt
- HTML-Cards als "Advanced Mode"
- Opt-in für Power-User
Schritt 2: Feature Parity
- Card Builder unterstützt beide Modi
- Import/Export zwischen Formaten
- Template Converter
Schritt 3: Unified System
// Universeller Card Renderer
function renderCard(card: UnifiedCard): HTMLElement {
switch (card.type) {
case 'modular':
return renderModularCard(card);
case 'template':
return renderTemplateCard(card);
case 'custom-html':
return renderCustomHTMLCard(card);
}
}
🎯 Empfehlung
Hybrid-Ansatz implementieren mit:
- Beibehaltung des modularen Systems für 80% der Nutzer
- Template-System für fortgeschrittene Anpassungen
- HTML/CSS-Editor für Power-User und Entwickler
- Strikte Sandboxing für Sicherheit
- Progressive Enhancement - Nutzer können zwischen Modi wechseln
Vorteile dieses Ansatzes:
- ✅ Backward Compatibility
- ✅ Verschiedene Skill-Level bedient
- ✅ Sicherheit gewährleistet
- ✅ Performance optimiert
- ✅ Wartbarkeit erhalten
Timeline:
- Woche 1-2: Proof of Concept
- Woche 3-4: Editor & Tools
- Woche 5: Datenbank-Migration
- Woche 6: Integration
- Woche 7-8: Testing & Rollout
🚀 Nächste Schritte
- Proof of Concept mit einfachem HTML-Renderer
- Sicherheitsaudit der Sanitization
- Performance-Tests mit komplexen Cards
- User Research - Welcher Ansatz wird bevorzugt?
- Schrittweise Migration beginnen
💡 Zusätzliche Überlegungen
AI-Unterstützung
// KI generiert HTML/CSS basierend auf Beschreibung
async function generateCardFromPrompt(prompt: string): Promise<CardHTML> {
const response = await ai.generate({
prompt: `Create a card with: ${prompt}`,
constraints: ['responsive', 'aspect-ratio: 16/9', 'no-javascript']
});
return sanitizeCard(response);
}
Marketplace Evolution
- Verkauf von HTML/CSS Templates
- Code-Snippets Library
- Community Challenges
- Template Converter Tools
Monitoring & Analytics
// Track welcher Modus am meisten genutzt wird
analytics.track('card_created', {
type: 'modular' | 'template' | 'custom-html',
complexity: calculateComplexity(card),
render_time: measureRenderTime(card)
});