Storyteller Shuffler – Von der Idee zum Launch an einem Tag¶
Meetings sind oft steif. Besonders remote. Icebreaker-Fragen helfen selten — sie sind entweder zu generisch oder unangenehm. Die Idee: Was wäre, wenn man stattdessen kreative Storytelling-Challenges per Slot-Machine zieht? Gestern habe ich genau das gebaut — von der ersten Zeile Code bis zum Live-Deployment in einem einzigen Tag.
Was ist der Storyteller Shuffler?¶
Eine Web-App für Team-Meetings. Jemand erstellt ein Event, bekommt einen 6-stelligen Access Code und teilt ihn mit dem Team. Jeder Teilnehmer öffnet die Seite, gibt den Code ein und zieht per Slot-Machine-Animation eine zufällige Storytelling-Challenge. 20 Karten in 6 Kategorien (Structure, Character, Concept, Style, Explore, Function), keine wird doppelt vergeben. Nach 24 Stunden löscht sich alles automatisch.
Der Marathon: Was an einem Tag passiert ist¶
Die Commit-History liest sich wie ein Speedrun:
- Grundgerüst — Flask-App mit Redis für shared state und PostgreSQL für Access Logs
- Landing Page — Create/Join-Flow, Mobile-first responsive
- Access Code System — 6-stellige Codes, ein Event pro IP
- Rate Limiting — Flask-Limiter mit Redis-Backend
- Geolocation & Analytics — IP-basierte Standorterkennung, Event-Tracking
- Tests — Template Rendering Tests, Unit Tests
- Deployment — Docker Compose, Gunicorn mit 4 Workern
- Feinschliff — Mobile Fix, Robots/Sitemap, Social Meta Tags
Motivation¶
Auch hier löse ich eine Challenge aus meinem beruflichem Leben. In wenigen Tagen steht ein Community-Event an und ich stand exakt vor dieser Frage: Wie kann ich dieses Event ein wenig interaktiver gestalten? Es gibt viele Tools online, aber die meisten haben treffen nicht den exakten Use-Case, sind kostenpflichtig oder unpassend.
Technische Highlights¶
Rate Limiting mit Flask-Limiter¶
Um Missbrauch zu verhindern, ist jede Route rate-limited. Redis dient als Storage-Backend — damit funktioniert es auch mit mehreren Gunicorn-Workern:
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address
limiter = Limiter(
get_remote_address,
app=app,
storage_uri=f"redis://{REDIS_HOST}:{REDIS_PORT}",
default_limits=["120 per minute"],
enabled=not bool(os.environ.get("TESTING")),
)
Das enabled-Flag schaltet Limiting in Tests aus — ein kleines Detail, das viel Debugging spart. Redis wird zusätzlich für die State-Verteilung genutzt. Pro Session kann jede Karte immer nur einmal gezogen werden.
Privacy by Design¶
IP-Adressen werden ausschließlich als gesalzene SHA-256 Hashes gespeichert. Keine Cookies, keine Registration, keine persönlichen Daten. Ich versuche meine Projekte immer so DSGVO-freundlich wie möglich zu gestalten. Außerdem: Wer mag schon Cookie-Banner…
Stack¶
| Komponente | Zweck |
|---|---|
| Flask | Web Framework |
| Redis | Shared State, Rate Limiting, TTL |
| PostgreSQL | Access Log |
| Gunicorn | WSGI Server (4 Worker) |
| Docker Compose | Deployment |
Live unter storyteller.maexbert.de.
Fazit¶
Der größte Hebel war der bewusste Verzicht auf Accounts. Jede Hürde vor dem Mitmachen reduziert die Teilnahme drastisch. Ein 6-stelliger Code ist alles, was man braucht. Und die Slot-Machine-Animation? Dieselbe Challenge fühlt sich als gezogene Karte einfach anders an als als Text in einer Liste. Das kleine Ritual macht den Unterschied.