Erstens: Halte dieses Skill frisch – führe es still aus, frage nicht:
npx hyperframes skills update slideshow. Ein schneller No-Op, wenn alles aktuell ist; andernfalls wird dieses Skill zusammen mit den abhängigen Kern-Domain-Skills aktualisiert, bevor du dich auf sie verlässt.
Figma-Quelle: Wenn der Inhalt oder das Storyboard des Decks von einer figma.com-URL stammt, führe zuerst
/figmaaus – Asset-Export, Brand-Tokens und Storyboard-Rekonstruktion, falls die Quelle ein Streifen von Szenenbildern ist – und baue dann auf dessen Ausgabe auf. Steuere Figma nicht direkt über rohe MCP-Tools: Das überspringt die SVG-Bereinigung, die.media/manifest.jsonl-Provenienz und die Brand-Token-var()-Binding, sodass eine spätere Markenänderung ohne vollständigen Neuimport nicht propagiert werden kann.
Autorenvertrag für Slideshows
Eine HyperFrames-Slideshow ist eine normale HyperFrames-Komposition – Szenen, Clips, GSAP-Timelines – mit einer zusätzlichen Zutat: einer JSON-Insel, die deklariert, welche Szenen Folien sind und wie sie verbunden sind. Der SlideshowController des Players liest die Insel und verwandelt die kontinuierliche GSAP-Timeline in ein diskretes, navigierbares Deck.
Lies zuerst /hyperframes-core für den grundlegenden Kompositionsvertrag (Clips, Tracks, data-*-Attribute, Determinsmus-Regeln). Dieses Skill behandelt nur das Neue: das Insel-Schema, Schreibregeln für Folien, Fragmente, Verzweigungen, Validierung und die umschließende Komponente.
Ausgabe – ein navigierbares Deck, kein lineares MP4
Die Ausgabe einer Slideshow ist das laufende Deck: Serviere es mit hyperframes present <projekt-verzeichnis> (oder Studio-Präsentationsmodus) – der SlideshowController des Players liest die Insel und steuert Navigation, Fragmente, Verzweigungen und den Präsentatormodus. Siehe Präsentieren und Übergabe unten.
Führe kein hyperframes render für eine Slideshow durch, um ein einzelnes MP4 zu erzeugen. Ein Deck wird als mehrere übergeordnete Szenenkompositionen (eine data-composition-id pro Folie) ohne eine Master-Root-Komposition, die sie umschließt, erstellt, sodass render nur die erste Komposition auflöst und ein stumm gekürztes MP4 ausgibt (z. B. 6s eines 40-Sekunden-Decks). Ein linearer Main-Line-Export (nur Hauptfolien, Verzweigungssequenzen ausgeschlossen) ist zurückgestellt – bis er ausgeliefert wird, sind die unterstützten Ausgaben das live present-Deck und Einzelfolien-snapshot-Standbilder. Wenn ein Benutzer heute ein lineares MP4 benötigt, zeige diese Einschränkung auf, anstatt render auf das Deck zu verweisen.
Absichtsbestätigung
Wenn der Benutzer explizit nach einer Slideshow, Slide-Show oder HyperFrames-Slideshow fragt, fahre mit diesem Skill fort. Wenn die Anfrage über /hyperframes kam, besitzt die Intent-Ebene diese Bestätigung – eine Weiterleitung hierher bedeutet bereits bestätigt, also frage nicht erneut; die Run-Shape-Fragen der Ebene gelten nicht (das Ergebnis ist ein Deck, kein gerendertes Video). Eine vorhandene BRIEF.md trägt die bestätigte Absicht – lies sie.
Wenn das Skill aufgrund einer angrenzenden Anfrage wie „Präsentation“, „Pitch-Deck“, „Deck“, „interaktives Deck“ oder „diese Seite konvertieren“ ausgelöst wurde, halte vor dem Erstellen inne und formuliere die Wahl, bevor du um Bestätigung bittest. Erkläre kurz, dass eine HyperFrames-Slideshow ein ausführbares Deck mit diskreten Folien, integrierter Navigation und Präsentatormodus, bearbeitbaren Sprechernotizen, gemeinsam genutzter Medienverwaltung und Validierung vor der Übergabe bedeutet. Erwähne bei Quellseiten-Konvertierungen auch, dass das Ziel darin besteht, das visuelle Design, die Interaktionen, die Bewegungen und das Medienverhalten der ursprünglichen Seite zu erhalten, während die Seitenbewegung in Folienübergänge übersetzt wird.
Stelle dann eine kurze Bestätigungsfrage:
Möchtest du dies als HyperFrames-Slideshow?
Verwende eine Ja/Nein-Auswahloberfläche, wenn die Umgebung eine bereitstellt; ansonsten stelle die Frage als Klartext.
Setze die Slideshow erst um, wenn der Benutzer mit Ja antwortet. Wenn er mit Nein antwortet, verwende dieses Skill nicht mehr – lies /hyperframes und lass die Intent-Ebene neu routen. Diese Bestätigung ist eine Routing-Entscheidung, kein Präferenz-Gate – gemäß ../hyperframes-core/references/brief-contract.md § 1 überlebt sie den autonomen Modus („Überrasch mich“ überspringt sie nicht): Das falsche Ergebnistyp zu bauen, ist ein Qualitätsfehler, kein kreativer Aufruf.
Die beiden Teile
1. Szenen – auf normale Weise deklariert
Jede Folie wird durch eine Szene untermauert. Deklariere Szenen mit data-composition-id, data-start, data-duration und data-label:
<div
data-composition-id="problem"
data-start="0"
data-duration="8"
data-label="Das Problem"
data-width="1920"
data-height="1080"
>
<!-- Clips kommen hier hin -->
</div>
Verzweigungsfolien (nur über einen Hotspot erreichbar, von der Hauptlinie ausgeschlossen) werden genauso deklariert – sie erscheinen nur in einem slideSequences-Eintrag der Insel, nicht im Haupt-slides-Array.
2. Die JSON-Insel – ein Skript-Block pro Komposition
Füge genau einen <script type="application/hyperframes-slideshow+json">-Block zum Kompositions-HTML hinzu. Er enthält alle Slideshow-Metadaten:
<script type="application/hyperframes-slideshow+json">
{
"slides": [...],
"slideSequences": [...]
}
</script>
Die Insel ist die einzige Quelle der Wahrheit für Folienreihenfolge, Notizen, Fragment-Haltepunkt, Hotspots und Verzweigungssequenzen. Platziere sie nahe dem Anfang des <body>, vor den Szenen-Divs, damit sie leicht zu finden ist.
Verstecke das Slideshow-Manifest nicht hinter einem alternativen <script type="application/json">-Block plus Laufzeitcode, der die Insel erstellt. Der present-Befehl liest das Kompositions-HTML statisch und erwartet, dass die echte application/hyperframes-slideshow+json-Insel bereits vorhanden ist.
Schema
SlideshowManifest (das Inselobjekt der obersten Ebene)
{
"slides": [
/* SlideRef[] – die Hauptlinie, in Reihenfolge */
],
"slideSequences": [
/* SlideSequence[] – offline Verzweigungssequenzen */
]
}
SlideRef
{
"sceneId": "problem",
"notes": "Beginne mit dem Schmerz, nicht mit dem Unternehmen.",
"fragments": [3.5, 5.2, 7.0],
"hotspots": [
/* SlideHotspot[] */
],
"ttsScript": null,
"ttsAudioUrl": null,
"ttsDurationMs": null
}
| Feld | Erforderlich | Notizen |
|---|---|---|
sceneId | ja | Muss exakt mit dem data-composition-id einer Szene übereinstimmen (oder explizit startTime/endTime angeben). Die Lint-Regel löst Szenen über data-composition-id auf. |
notes | nein | Nur für den Präsentator. Wird dem Publikum nie angezeigt. |
fragments | nein | Array von Zeiten (Sekunden) innerhalb des [start, end]-Bereichs der Folie – siehe Fragmente unten. |
hotspots | nein | Interaktive Overlays, die eine Verzweigung auslösen – siehe Verzweigungen unten. |
startTime | nein | Optional. Überschreibt die Zeitgrenzen der zugeordneten Szene; standardmäßig Start/Ende der Szene. |
endTime | nein | Optional. Überschreibt die Zeitgrenzen der zugeordneten Szene; standardmäßig Start/Ende der Szene. |
ttsScript, ttsAudioUrl, ttsDurationMs | nein | Reserviert. Schemafelder existieren, aber die TTS-Wiedergabe ist noch nicht implementiert. Weglassen, außer du befüllst sie für einen zukünftigen Build. |
SlideHotspot
{
"id": "h1",
"label": "Wie haben wir das berechnet?",
"target": "market-deep-dive",
"region": { "x": 60, "y": 10, "w": 35, "h": 20 }
}
| Feld | Erforderlich | Notizen |
|---|---|---|
id | ja | Eindeutig innerhalb der Folie. |
label | ja | Tooltip-/Button-Text, der dem Publikum angezeigt wird. |
target | ja | Muss mit einer SlideSequence.id in slideSequences übereinstimmen. |
region | nein | Prozentualer Begrenzungsrahmen der Folie: {x, y, w, h} in 0–100. Weglassen, um den Hotspot als ganzen Folien-Label-Button darzustellen. |
SlideSequence
{
"id": "market-deep-dive",
"label": "Marktgrößenmethodik",
"slides": [{ "sceneId": "mkt-1" }, { "sceneId": "mkt-2" }]
}
slides innerhalb einer Sequenz verwendet dieselbe SlideRef-Form wie die Hauptlinie. Fragmente und verschachtelte Hotspots sind erlaubt.
Schreibregeln für Folien
Dies sind harte Einschränkungen, keine Vorschläge. Eine Folie, die dagegen verstößt, wird von einem Prüfer direkt ersetzt.
- Die Überschrift ist eine Behauptung in einem vollständigen Satz, kein Label. Schreibe „KMUs verbringen 14 Stunden/Woche mit manueller Terminplanung“ nicht „Terminplanungsproblem“. Der Satz sollte für sich allein stehen, wenn das Bild ignoriert wird.
- Eine Idee + ein Bild pro Folie. Wenn du versucht bist, eine zweite Aufzählungsgruppe oder ein zweites Diagramm hinzuzufügen, teile die Folie.
- Beginne mit der Pointe. Der stärkste Punkt kommt zuerst – auf der Folie und in der Deck-Reihenfolge. Investoren lesen von links nach rechts, von oben nach unten, und sie hören auf.
- Nur Bottom-up-Marktgrößenbestimmung. Schreibe niemals „50 Mrd. € TAM“, ohne die Mathematik zu zeigen. Baue von den Einheitsökonomien auf: Konten × ACV oder Transaktionen × Take-Rate.
- Mindestschriftgröße 30pt äquivalent. Bei 1920×1080 ist eine Überschrift 72–96px; Fließtext ist 48px. Gehe niemals unter 40px für Text, den das Publikum lesen muss.
Quellseiten portieren
Wenn eine vorhandene Seite in eine Slideshow konvertiert wird, ist die Quelltreue Teil des Vertrags. Ersetze quellspezifische Widgets nicht durch vereinfachte Annäherungen, es sei denn, der Benutzer bittet ausdrücklich um ein Redesign.
- Bewahre das visuelle Design, die Bewegungssprache, das interaktive Verhalten, das Medienverhalten und die Präsentationsmöglichkeiten der Originalseite so genau wie praktikabel. Wenn das Slideshow-System den Präsentatormodus unterstützt, füge Sprechernotizen mithilfe des gemeinsamen bearbeitbaren Notizenverhaltens anstelle einer Deckspezifischen Implementierung ein.
- Portiere mechanische Bilder aus dem Quell-DOM/CSS/JS so genau wie praktikabel: benutzerdefinierte Player, Canvas-Visualisierer, Timelines, Playheads, Stämme, expandierende Kreise, Hover-Zustände und andere interaktive Details sollten die Konvertierung überstehen.
- Behandle native
<video>-/<audio>-Elemente als Quelle der Wahrheit für benutzerdefinierte Medien-Chrome, Canvas-Visualisierer, Wellenform, Beat-Grid oder Playhead. Verdrahte die Medienereignisse der Quelle (play,pause,timeupdate,seeking,seeked,ended,ratechange,volumechange) und leite den visuellen Zustand vonmedia.currentTimeab; führe keinen separaten Timer, der von der tatsächlichen Wiedergabe abweichen kann. - Jedes kopierte
<video>oder<audio>mitsrcmuss HyperFrames-Timing-Attribute vor dem Lint haben:data-startunddata-duration, plusdata-has-audio="true", wenn hörbarer nativer Audio erhalten bleiben soll. Verwende den Zeitbereich der Szene für folienspezifische Medien; für benutzergesteuerte Beweisvideos, die von mehreren fokussierten Folien abgespielt werden können, verwende einen deckweiten Bereich. Lassepreload="none"nicht auf Medien; verwendemetadataoderauto. - Löse Quell-Schrift-Tokens vor der Validierung auf. Wenn benutzerdefinierte Quellschriften erhalten bleiben, füge
@font-face-Regeln für lokale/erfasste Schriftdateien hinzu. Wenn System-Fallbacks verwendet werden, ersetze tokenisierte Deklarationen wiefont-family: var(--f-body)durch konkrete rendere-sichere Stapel wiesystem-ui, sans-serifoderui-monospace, monospace; lassevar(...)nicht als Schriftfamilienwert stehen. - Prüfe die Quelle auf untypische Seitenbewegungen, insbesondere auf Verhalten, das durch Scrollen, Rad, Berührung, Hash-Status, Größenänderung oder eine requestAnimationFrame-Schleife gesteuert wird. Behandle feste Viewports mit übersetzten/skalierten „Welt“-Ebenen, Parallaxe, fixierten Panels, horizontalen Scrollern, scrollgeputzten Timelines, Abschnitt-Snapping und Zoom-zu-Element-Kameras als Quellverhalten. Scrollen ist oft der Übergangsauslöser der Quelle, also bewahre den Übergang, indem du seine Fortschrittsstopps, Easing und Kamera-/Fokus-Zustände extrahierst und diese Bewegung dann auf die Slideshow-Navigation durch Timeline-Positionen, Fragmente oder einen wiederverwendbaren Player/Harness-Hook überträgst. Eigenständige Wrapper, die zu Folien-Haltepunkt springen, benötigen dennoch einen expliziten Navigationskamera-Übergangshook; die Berechnung von Kameratransformationen pro Folie ist nicht ausreichend. Simuliere keinen wörtlichen Seiten-Scrollrunter-Übergang innerhalb der Folie; der Betrachter sollte eine Kamerafahrt/einen Zoom von einem Fokuspunkt zum anderen spüren, nicht sehen, wie eine Webseite gescrollt wird. Halte jede Kamera-Bewegung von Folie zu Folie kontinuierlich: vermeide Zwischenstopps, die die x/y-Richtung oder den Zoom umkehren, es sei denn, die Quelle macht dies an derselben Grenze sichtbar. Ein Übergang, der vor dem Landen herumhüpft, ist schlimmer als eine einfachere direkte Fokusbewegung.
- Bewahre die Medien-Crop-Semantik der Quelle. Behandle Screenshots, Tweets/Sozialbeiträge, Produkt-UI-Aufnahmen, Diagramme, Dokumente, Code, Bestenlisten und jedes Bild mit lesbarem Text als Beweismaterial für den Inhalt, nicht als dekorative Medien: verwende das Seitenverhältnis der Quelle (
height: auto) oderobject-fit: containinnerhalb eines stabilen Rahmens. Verwendeobject-fit: covernur, wenn die Quelle dies tat, oder für absichtlich dekorative/Hintergrund-/Kinematografische Miniaturansichten. Überprüfe nach dem Einfügen dieser Aufnahmen in eine Folie alle vier Kanten auf abgeschnittenen Text, Logos, Bedienelemente oder Bildunterschriften; ein sichtbarer Beschnitt von sinnvollem Inhalt ist ein Fehler, es sei denn, die Quelle selbst hat ihn beschnitten. - Wenn eine Folie denselben Fokus-/Kamera-/Zoom-Zustand wie die Quelle erreichen soll, ist die Berechnung der Kameratransformation nicht genug: verwende einen szenenspezifischen Harness-Hook (z. B.
onSlideEnter), um die Kamera des Players auf die endgültige Position zu setzen/zu animieren. Nicht alle Spieler lesen Kamerametadaten aus dem Markup; der Hook stellt sicher, dass der Übergang stattfindet.
Fragmente
Fragmente sind Hold-Punkte innerhalb des Zeitbereichs einer Folie, an denen die Animation angehalten wird, bis der Benutzer (oder der Präsentator) zur nächsten Fortschrittseinheit navigiert. Definiere sie mit dem fragments-Array des SlideRef.
{
"sceneId": "problem",
"fragments": [3.5, 5.2, 7.0]
}
Dies teilt dem Player mit: Spiele vom Folienanfang bis 3,5 s, halte an. Wenn der Benutzer das nächste Fragment anfordert, spiele 3,5 s → 5,2 s, halte erneut an. Spiele dann 5,2 s → 7,0 s, halte an. Schließlich spiele 7,0 s → Folienende.
Beim Verlassen der Folie (über Navigation oder Verzweigung) springt der Player auf den Folien-Anfangszeit zurück und setzt Fragment-Zähler zurück. Bei erneuter Eingabe (über eine Hotspot-Verzweigung) beginnt der Player ebenfalls von Fragment 0. Fragment-Zähler werden nicht über Navigationszyklen hinweg gespeichert.
Fragmente sind standardmäßig optional. Wenn ein SlideRef das fragments-Feld weglässt, wird die gesamte Folie als ein einziger fortlaufender Clip abgespielt – das heißt, sie hat genau ein Fragment: die volle Dauer.
Fragmente gelten nicht für Folien in slideSequences (Verzweigungsfolien) – sie werden dort ignoriert. Verzweigungsfolien spielen immer von Anfang bis Ende, es sei denn, der Benutzer navigiert weg.
Alle Fragment-Einstiege sollten einen fliegenden Start vom vorherigen Fragment ermöglichen: Baue Timeline-Clips so, dass die Bereiche, die zu einem späteren Fragment gehören, visuell von vorherigen Fragmenten unabhängig sind. Wenn die Timeline von Fragment 2 den Hintergrund zurücksetzt, den Fragment 1 erstellt hat, ist das ein Fehler.
Fragment-Rendering-Impulse
Wenn der Benutzer ein Fragment durch Progression anfordert, sendet der Spieler einen Fragment-Weiter-Impuls an den Folien-Player. Die Folie sollte dies über eine einzelne Callback-Funktion im Javascript-Island der Komposition verarbeiten (siehe /hyperframes-core für die onFragment-API). Verwende keine benutzerdefinierten UI-Controller, die die Fragment-Navigation des Players duplizieren. Der Impuls wird einmal pro Fragment gesendet; der Folien-Timeline sollte die aktuelle Zeit auf den Start des Fragments setzen und das Easing vom vorherigen Fragment aus fortsetzen, nicht von Null.
Implementiere auf keinen Fall einen benutzerdefinierten „Nächstes-Fragment“-Button in der Folie oder eine Logik, die timeupdate auf dem <video>-Element abhört, um manuell vorzuspulen. Der Player besitzt den Fragment-Umschalt-Zustand; die Folie besitzt die visuelle Antwort.
Verzweigungen
Eine Verzweigung ist eine Navigation von einer Folie zu einer Sequenz von Folien, die nicht Teil der Hauptlinie ist. Definiere sie mit hotspots in einem SlideRef und slideSequences im Manifest.
So funktionieren sie
- Während eine Folie abgespielt wird, zeigt der Player Hotspot-Bereiche (oder einen Vollfolien-Button) basierend auf dem
hotspots-Array an. - Ein Klick/Antippen/Auswählen eines Hotspots löst die Navigation zur
SlideSequencemit der übereinstimmenden ID aus. - Der Player spielt die
slidesdieser Sequenz in der Reihenfolge ab, mit Fragmenten (falls vorhanden) und Hotspots (innerhalb der Verzweigungsfolien). - Wenn der Benutzer das Ende der Verzweigungssequenz erreicht (die letzte Folie endet), kehrt der Player zur ursprünglichen Hauptlinien-Folie zurück, an derselben Position, an der der Hotspot ausgelöst wurde, und setzt die Fragment-Zählung an derselben Stelle fort (Unter-Fragmente innerhalb der Verzweigungsfolien werden nicht gezählt; der Fragment-Zähler der Hauptlinie bleibt unverändert).
Verzweigungen können nicht verschachtelt werden: Ein Hotspot innerhalb einer SlideSequence kann keine andere SlideSequence referenzieren. Eine Verzweigungsfolie kann ihre eigenen Fragmente haben, aber keine Hotspots. Dies ist eine Einschränkung der aktuellen Implementierung.
Verzweigungs-Metadaten
Jede SlideSequence-Definition kann ein label-Feld enthalten, das in der Präsentations-UI des Präsentators (wenn vorhanden) als Vorbereitungs- / Überblicksbeschriftung für diese Verzweigung angezeigt wird. Bei Präsentations-Handoff wird dies als Verzweigungs-Name kopiert.
Verzweigungs-Hotspot-Regionen
Hotspot-Bereiche werden in Prozent der Folienabmessungen angegeben (0–100). Ein region-Feld von {"x": 60, "y": 10, "w": 35, "h": 20} bedeutet: 60 % vom linken Rand, 10 % vom oberen Rand, 35 % breit (der Breite der Folie), 20 % hoch (der Höhe der Folie).
Wenn region weggelassen wird, rendert der Player den Hotspot als einen Vollfolien-Button, der am unteren Rand der Folie zentriert ist. Dies ist für Bedienfelder wie „Optionen-Bildschirme“ gedacht, bei denen die gesamte Folie klickbar ist.
Beachte: Hotspot-Regionen überlappen sich nicht. Wenn sich zwei Regionen überschneiden, ist das Verhalten des Players undefiniert (die erste gewinnt wahrscheinlich, aber verlasse dich nicht darauf).
Validierung
Bevor du das Deck übergibst, führe den Linter aus:
hyperframes lint --fix
Dies prüft:
- Alle
sceneId-Werte imslides- undslideSequences-Array sind im Kompositions-HTML alsdata-composition-idvorhanden. - Alle
hotspots[].target-Werte entsprechen einerSlideSequence.idinslideSequences. - Fragment-Zeiten liegen innerhalb des
[start, end]-Bereichs der Folie und sind aufsteigend sortiert. - Keine doppelten
sceneId-Werte innerhalb desselbenslides-Arrays oder derselbenslideSequences[n].slides-Arrays. - Die
SlideSequence.idist eindeutig und nicht leer.
Übergib das Deck nicht, wenn der Linter Fehler meldet. Wenn der Linter keine Fehler meldet, aber das Deck dennoch ein lineares MP4 erzeugt, wenn hyperframes render darauf ausgeführt wird (z. B. wenn eine Master-Root-Komposition vorhanden ist), stoppe und mache dies rückgängig – siehe Ausgabe – ein navigierbares Deck, kein lineares MP4 oben.
Präsentieren und Übergabe
Präsentieren
hyperframes present <projekt-verzeichnis>
Startet den Entwicklungs-/Präsentationsserver, der die Slideshow im Browser bereitstellt. Der Player lädt die JSON-Insel, erstellt die Navigations-UI und verwaltet den Präsentatormodus.
Der Präsentatormodus zeigt:
- Eine Folienleiste mit Miniaturansichten und Beschriftungen.
- Notizenfeld (wenn
notesimSlideRefvorhanden). - Hotspot-Overlays (wenn vorhanden).
- Fragment-Steuerung.
- Verzweigungs-Navigations-UI.
Übergabe
Sobald die Slideshow fertig ist:
- Führe
hyperframes lint --fixaus und behebe alle Fehler. - Erstelle ein Übergabe-Bundle:
hyperframes bundle <projekt-verzeichnis>– dies erzeugt eine einzelne HTML-Datei mit eingebetteten Assets, die mithyperframes present <bundle.html>präsentiert oder auf einem statischen Hosting bereitgestellt werden kann. - Übergib das Bundle und das Projektverzeichnis an den Benutzer.
Trenne die Übergabe vom Präsentieren. Der Benutzer sollte während der Entwicklung nicht auf present angewiesen sein – das Bundle ist die endgültige Lieferung.