Technik & AHA-Stack
Wie die Rechenkiste gebaut wurde
Die Rechenkiste ist eine Demo-Anwendung für den AHA-Stack und den @casoon/fragment-renderer. Sie zeigt, wie moderne Web-Anwendungen mit minimalem JavaScript und maximaler Performance gebaut werden können.
Was ist der AHA-Stack?
Der AHA-Stack kombiniert drei leichtgewichtige Technologien:
Astro
Astro - Ein modernes Web-Framework für content-fokussierte Websites mit Zero-JS-Default
HTMX
HTMX - Ermöglicht dynamische Interaktionen durch HTML-Attribute statt JavaScript
Alpine.js
Alpine.js - Leichtgewichtiges JavaScript für reaktive UI-Komponenten
@casoon/fragment-renderer
Der Fragment-Renderer ist eine Bibliothek von casoon, die das serverseitige Rendern von Astro-Komponenten als HTML-Fragmente ermöglicht. Dies ist ideal für HTMX-basierte Anwendungen.
Features:
- Serverseitiges Rendering von Astro-Komponenten
- HTMX-Integration mit automatischen Response-Headers
- Preset für den AHA-Stack
- TypeScript-Support
Beispiel: Feedback-Fragment
So wird in der Rechenkiste das Feedback nach einer Antwort gerendert:
// task-renderer.ts
import { createAstroRuntime } from "@casoon/fragment-renderer";
import { ahaStackPreset } from "@casoon/fragment-renderer/presets/aha-stack";
const runtime = createAstroRuntime({
...ahaStackPreset({ locale, htmxHeaders: true }),
components: [
{ id: "feedback-correct", loader: () => import("./FeedbackCorrect.astro") },
{ id: "feedback-incorrect", loader: () => import("./FeedbackIncorrect.astro") },
],
});
// Render feedback as HTML fragment
const html = await runtime.renderToString({
componentId: result.isCorrect ? "feedback-correct" : "feedback-incorrect",
props: { locale, nextUrl, isComplete },
}); Das Aufgaben-System
Die Rechenkiste verwendet ein modulares Aufgaben-System mit:
- • Einheitliches Interface für alle Aufgabentypen
- • Selbst-validierende Aufgaben mit Hints
- • SVG-Visualisierungen für Geometrie und Brüche
- • Multiple-Choice und Drag-and-Drop Support
- • Adaptive Schwierigkeit und Fehler-Wiederholung
// Unified Task Interface
interface TaskInstance {
id: string;
question: string;
validate(answer: string): ValidationResult;
getHint(): string;
getCorrectAnswer(): string | number;
}
// Self-validating task
const result = task.validate(userAnswer);
if (!result.isCorrect) {
console.log(result.hint); // "Der kleine Zeiger zeigt die Stunde..."
}