Der Export legte die Datei nur unter animation/ im Repo ab. Die Bilder gehen seit jeher nach ~/Downloads, und von dort laedt man hoch -- ein Video an einem anderen Ort ist eine Inkonsequenz, die man erst merkt, wenn man es sucht. Jetzt beides: Downloads zum Hochladen, animation/ zum Versionieren. Wie beim Bildexport wird in Downloads nichts ueberschrieben, eine zweite Ausgabe heisst "-1" -- eine Datei, die vielleicht schon hochgeladen wurde, gehoert nicht ersetzt. Der Weg ueber die Kommandozeile schreibt weiterhin nur ins Repo. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
529 lines
26 KiB
Markdown
529 lines
26 KiB
Markdown
# HiveGrid Social — Design-Library & Post-Generator
|
||
|
||
Eigenständige Werkbank für HiveGrid-Social-Grafiken. Slides werden im Browser
|
||
als HTML gebaut, im Canvas bearbeitet und pixelgenau als Instagram-taugliche
|
||
PNGs exportiert.
|
||
|
||
**Das Repo ist bewusst autark.** Keine CDN-Verweise, keine Google-Fonts zur
|
||
Laufzeit, keine Pfade in andere Repos. Alles, was ein Post braucht — Schrift,
|
||
Logos, Mockups, Screenshots, Bibliotheken — liegt hier.
|
||
|
||
## Starten
|
||
|
||
```sh
|
||
./serve.sh # http://127.0.0.1:4321
|
||
```
|
||
|
||
Downloads landen direkt in `~/Downloads`, ohne Browser-Dialog.
|
||
|
||
## Projekte
|
||
|
||
| Projekt | Datei | Inhalt | Übergabe |
|
||
|---|---|---|---|
|
||
| Post 1 · Lösung | `post1.html` | Carousel, Anzahl frei | |
|
||
| Post 2 · Die Geschichte | `post2.html` | Carousel, 6 Slides, erscheint 12.08. | [`POST-2.md`](./POST-2.md) |
|
||
| Post 2 · Alternative | `post2-alt.html` | Derselbe Beitrag im Theme `modern` | |
|
||
| Post 3 · Verbinden statt ersetzen | `post3.html` | Einzelbild, Theme `modern`, erscheint 17.08. | |
|
||
| Post 4 · Workflow-Engine | `post4.html` | Carousel, 4 Slides, Theme `modern`, erscheint 19.08. | [`POST-4.md`](./POST-4.md) |
|
||
| Post 5 · Projektmanagement | `post5.html` | Carousel, 5 Slides, Theme `modern`, erscheint 21.08. | [`POST-5.md`](./POST-5.md) |
|
||
| Post 6 · Team-Chat | `post6.html` | Carousel, 5 Slides, Theme `modern`, erscheint 26.08. | [`POST-6.md`](./POST-6.md) |
|
||
|
||
**Alle Streifen nebeneinander** zeigt `uebersicht.html`, erreichbar über
|
||
*Projekt → Alle Projekte im Streifen*. Die Seite baut die Slides nicht selbst
|
||
nach: jedes Projekt kommt als `iframe` mit `?nur=streifen`, und in diesem Modus
|
||
blendet die Post-Seite ihre Bedienoberfläche aus, zeigt den Streifen in
|
||
natürlicher Größe und **speichert nichts** — drei Kacheln, die beim Schließen
|
||
ihren Stand zurückschreiben, wären genau die Falle aus [`POST-2.md`](./POST-2.md) §6.
|
||
Jeder Streifen ist auf die Fensterbreite eingepasst, gescrollt wird nur
|
||
hoch und runter — kein Zoom, weder außen noch im Streifen.
|
||
|
||
**Post 2 gibt es zweimal, in zwei Themes.** Projekt und Theme sind zwei
|
||
verschiedene Dinge: das Projekt sagt, welcher Beitrag, das Theme, wie er
|
||
aussieht. `notebook` ist die Zeichenblock-Optik mit Raster und Marker,
|
||
`modern` der ruhige Grund mit farbigem Akzentwort und schwebenden Karten.
|
||
Beide zeigen denselben Beitrag mit denselben Texten.
|
||
|
||
Die Themes stehen in [`rules.md`](./rules.md) §1a mit ihren Unterschieden.
|
||
Wer eine Visualisierung ändert, muss an beide Dateien denken.
|
||
|
||
**Post 3 ist ein Einzelbild**, keine Slidefolge: eine Haltung, die man
|
||
durchwischen muss, ist keine. Sein Bild ist das **Wabenfeld der Startseite**,
|
||
nachgebaut aus `HoneycombSection.tsx` — dieselbe Achsrechnung, dieselben
|
||
Zellnummern, dieselbe Belegung, damit es wiedererkennbar bleibt und keine
|
||
Anmutung davon ist. Die vier Waben „In Arbeit" fehlen: auf der Startseite sind
|
||
sie ein Versprechen, im Beitrag wären sie ein Eingeständnis.
|
||
|
||
**Post 4 zeigt einen einzigen echten Ablauf**, nicht sechs Behauptungen über
|
||
Automatisierung: den Vorgang aus `assets/screens/workflow.png`. Die Bausteine
|
||
sind nachgebaut aus `NodeWorkflowEngine` und `WorkflowEngineClickDummy` des
|
||
Pitch-Pakets, in Markenfarben statt in den UI-Farben des Produkts — Teal trägt
|
||
die Arbeit, Gelb den einen Akzent, Anthrazit die Entscheidung.
|
||
|
||
**Vier Slides.** Der Redaktionsplan nennt fünf bis sieben, aber das ist eine
|
||
Spanne und kein Soll: eine Slide, die nichts hinzufügt, kostet einen Wisch und
|
||
gibt nichts zurück.
|
||
|
||
| Slide | Was sie leistet | Ansicht | Quelle der Texte |
|
||
|---|---|---|---|
|
||
| 1 | was es ist | ein Ablauf auf dem Canvas | Knoten aus `assets/screens/workflow.png`, Notiz aus `WORKFLOW_PRESETS`, Anordnung eigen |
|
||
| 2 | was ihn startet | Auslöser-Auswahl | `assets/screens/workflow-bausteine.png` |
|
||
| 3 | was dann passiert | Aktionen-Auswahl | `NodeWorkflowEngine`, Rubriken des `Katalog` |
|
||
| 4 | dass man nicht bei null anfängt | drei Vorlagen | `GENERAL_WORKFLOW_PRESETS` |
|
||
|
||
Slide 2 und 3 sind **eine Funktion mit zwei Rubriken**, weil es im Produkt eine
|
||
Auswahl ist: „Auslöser" und „Aktionen" stehen dort untereinander im selben
|
||
Feld. Getrennt gezeichnet wären es zwei Bilder, die zufällig gleich aussehen.
|
||
Die Kachelfarbe kommt dabei aus der **Kategorie**, nicht aus dem Knotentyp —
|
||
im Screenshot tragen alle Auslöser eine gelbe Kachel und die Aktion eine
|
||
blaue, samt Punkt vor der Rubrik. Auf dem Canvas ist es anders, dort färbt die
|
||
Wurzelkomponente je Art. Beides stimmt, es sind zwei Ansichten.
|
||
|
||
**Das Farbsystem stammt aus der Wurzelkomponente** und ist keine Dekoration:
|
||
grün fängt an, rot ändert Daten, blau meldet, amber macht eine Aufgabe daraus,
|
||
violett entscheidet, grau ist ein Fremdsystem. Deshalb sind auf Slide 3 alle
|
||
Kacheln grün — jede Vorlage startet mit einem Auslöser.
|
||
|
||
> **Die Kartenform auf Slide 3 ist nicht aus dem Projekt.** Im Werkzeug werden
|
||
> Vorlagen nur geladen, nicht als Galerie gezeigt; es gibt dort keine Ansicht,
|
||
> an die man sich halten könnte. Wörtlich sind die Namen, Beschreibungen und
|
||
> Startbausteine, gebaut ist die Form. Der Unterschied gehört benannt.
|
||
|
||
**Text mittig, Titel ohne Fließtext.** Die Visualisierungen sitzen 896 px breit
|
||
bei x 92, also links wie rechts 92 px Rand — ein linksbündiger Textblock
|
||
darüber steht sichtbar aus der Achse. Die Titel-Slide trägt nur die
|
||
Überschrift: der Ablauf darunter sagt, was gemeint ist, und ein Fließtext
|
||
wiederholte es in Prosa. Dafür fiel hier dieselbe Korrektur an wie in
|
||
`post3.html` — ein leerer Fließtext darf keinen leeren Absatz erzeugen, sonst
|
||
schiebt sein Zeilenabstand die Zeichnung nach unten.
|
||
|
||
> **Die Gabel auf Slide 1 kommt früher als im Screenshot, und ein Schritt
|
||
> fehlt.** Alle drei echten Abläufe verzweigen erst an Position 3 oder 4 —
|
||
> das füllt ein hochkantes Format schlecht, weil über und unter dem Stamm
|
||
> nichts steht, solange er läuft. Hier gabelt es nach dem zweiten Knoten, und
|
||
> zwischen „Formular eingegangen" und „Passender Lead?" fehlt dadurch „Daten
|
||
> vereinheitlichen". Alle sechs Knoten heißen wörtlich wie in `workflow.png`
|
||
> und tragen dessen Farben, aber diese eine Kante ist zusammengezogen: ein
|
||
> Ablauf, den es genau so gibt, ist es nicht mehr — einer, den es geben
|
||
> könnte, schon. Die Anordnung ist ohnehin eigen, im Werkzeug zieht man
|
||
> Knoten mit der Maus.
|
||
|
||
**Kein PDS im Beitrag.** Von den sechs Vorlagen nennen drei das
|
||
Branchenprogramm — zwei im Namen, eine in der Beschreibung. Der Beitrag
|
||
richtet sich an Betriebe allgemein, nicht an die, die zufällig dieses eine
|
||
Programm fahren. Übrig bleibt genau die Gruppe `GENERAL_WORKFLOW_PRESETS`, in
|
||
der das Wort kein einziges Mal vorkommt — also keine Auswahl nach Geschmack,
|
||
sondern die vollständige zweite Gruppe. Gekürzt wurde nichts: aus „Offene
|
||
Angebote aus PDS erkennen" ein „Offene Angebote erkennen" zu machen wäre die
|
||
bequeme Lösung und kein Zitat mehr. Lieber eine Karte weniger.
|
||
|
||
**Alle Produkttexte auf den Slides sind wortgleich aus der Quelle**, Titel wie
|
||
Beschreibungen. Wo ein Name nicht in eine Zeile passte, steht er zweizeilig —
|
||
gekürzt wird nicht, denn aus „Daten vereinheitlichen" ein „Prüfen" zu machen
|
||
ist keine Kürzung, sondern ein anderer Name.
|
||
|
||
**Der Knoten ist die echte Komponente.** `NodeItem` aus
|
||
`NodeWorkflowEngine.tsx` des Pitch-Pakets: quadratisch 128 × 128, `rounded-lg`,
|
||
6 px Rand, Titel und Beschreibung **unter** dem Feld, beim Auslöser die linke
|
||
Flanke voll gerundet. Genau so rendert es auch `assets/screens/workflow.png`.
|
||
Ein Zwischenstand zeichnete stattdessen breite Karten mit farbiger Kante links
|
||
und einem Block „BESCHREIBUNG" — abgemalt vom Pitch-Bild `02_Präsentation/03`.
|
||
Im Code des Projekts gibt es das nirgends, und der Kommentar behauptete
|
||
trotzdem, es sei ein Nachbau der Komponente.
|
||
|
||
**Die Farben sind die des Produkts**, nicht die der Marke. Aufgelöst aus
|
||
`ui/theme.css` über die ganze Token-Kette (`surface-ui-subtle-green-default`
|
||
→ `--color-ui-green-100` → `--color-green-100`), nicht aus dem Bild geschätzt:
|
||
|
||
| Rolle | Fläche | Zeichen |
|
||
|---|---|---|
|
||
| Auslöser | `#DCFCE4` | `#148134` |
|
||
| Daten | `#FEE2E2` | `#C52020` |
|
||
| Entscheidung | `#F0E7FF` | `#691CD4` |
|
||
| Meldung | `#D5EFFF` | `#003BEB` |
|
||
| Abschluss | `#FCF6C5` | `#9B5E0D` |
|
||
|
||
Ein Zwischenstand hatte sie durch Markenfarben ersetzt, weil `rules.md` §2 diese
|
||
Töne nicht kennt. Das ist zurückgenommen: der Beitrag zeigt die Oberfläche, und
|
||
ihre Farbe trägt Bedeutung — grün fängt an, rot arbeitet an Daten, violett
|
||
entscheidet, blau meldet, gelb schließt ab. Umgefärbt wäre es eine
|
||
Nacherzählung. Der Rand ist `border-default` `#E5E5E5`, also der Wert, vor dem
|
||
`rules.md` §5 warnt; hier trägt er, weil die Felder farbig gefüllt sind.
|
||
|
||
**Der Notizzettel auf Slide 1** ist `StickyNote.tsx` aus dem Pitch-Paket
|
||
(`rounded-md`, Kopfleiste `h-8`, Text `#424242`, sechs Farbpaare) mit dem
|
||
grünen Zettel aus dem Preset `form-to-pds`, Text unverändert. Zettel sind das,
|
||
was einen Ablauf im Werkzeug von einem Diagramm unterscheidet.
|
||
|
||
**Was hier bewusst nicht steht: ein erfundener Vorgang.** Ein Zwischenstand
|
||
hatte eine Slide mit einem Aktivitätenverlauf samt Uhrzeiten. Nichts davon war
|
||
gemessen. Bei einem Produkt vor dem Start ist eine erfundene Uhrzeit keine
|
||
Veranschaulichung, sondern ein Beleg, den es nicht gibt.
|
||
|
||
**Slide 1 trägt einen Ablauf, kein Stichwort.** Im Profilraster ist sie eine
|
||
Kachel von rund 150 px, auf 3:4 beschnitten — dort ist kein Wort lesbar. Was
|
||
ankommt, ist die Form: eine Kette, die sich gabelt.
|
||
|
||
Was über die 1080 px einer Seite hinausragt, landet auf der Nachbarslide — das
|
||
durchgehende Blatt aus `rules.md` §5 liegt in jeder Slide. Ein Prüfskript misst
|
||
das nach; alle sechs Zeichnungen bleiben auf der Sicherheitszone.
|
||
|
||
Sein Grund ist **gepunktet statt leer**: die Arbeitsfläche des Workflow-Editors,
|
||
mit den Werten aus `WorkflowEditor.tsx` der Website. Der Punktgrund steht als
|
||
dritte Stellung unter *Versuch → Punkte* und ist die Voreinstellung dieses
|
||
Projekts. Warum das Theme `modern` hier von seinem ruhigen Grund abweicht, steht
|
||
im CSS bei `.layer-raster`.
|
||
|
||
**Post 5 zeigt die Pipeline von vier Seiten.** Das Demo-Projekt hat dafür vier
|
||
Bildschirme — Schablone, Board, Liste, Detail — und jeder bekommt eine Slide,
|
||
dazu die Karte aus der Nähe. Anders als bei Post 4 wird **nichts umgefärbt**:
|
||
eine Pipeline lebt davon, dass man das Gewerk an der Farbe erkennt, ohne zu
|
||
lesen, und dass der Fuß einer Karte sich mit ihrer Priorität färbt. Die
|
||
Zuordnung Gewerk zu Ton ist `CATEGORY_TONES`, die Plättchenfarben sind
|
||
`ui/theme.css`.
|
||
|
||
| Slide | Screen | Was sie leistet |
|
||
|---|---|---|
|
||
| 1 | 4A | das Board selbst, drei Phasen mit Anzahl, Summe und Karten |
|
||
| 2 | 4A | eine Karte groß |
|
||
| 3 | 4B | „Vom Verkauf in die Abwicklung": dasselbe Projekt in `Auftragsabwicklung SHK`, mit dem Knopf für den Pipelinewechsel |
|
||
| 4 | 4C | dieselben Projekte als Tabelle |
|
||
| 5 | 3 | der Feldeditor, offen auf „Aufmaß erledigt" |
|
||
|
||
**Es sind zwei Pipelines, nicht eine.** Das Board gehört zu
|
||
`Vertrieb: Anlagen-Verkauf`, das Projekt in der Detailansicht liegt in
|
||
`Auftragsabwicklung SHK`, und ein Knopf schiebt es von der einen in die andere.
|
||
Das ist der Unterschied zwischen Vertriebs- und Abwicklungs-Projektmanagement,
|
||
und Slide 3 ist deshalb die Pointe des Beitrags. Möglich ist beides in einer
|
||
Software, weil die Felder an der Pipeline hängen und nicht am Programm — das
|
||
zeigt Slide 5.
|
||
|
||
**Alle Zahlen sind gerechnet, keine ist gesetzt.** Anzahl und Summe je Spalte
|
||
kommen aus denselben Datensätzen wie die Karten.
|
||
|
||
**Die Karte ist aus dem Code nachgebaut, nicht aus dem Screenshot.** Der erste
|
||
Anlauf war von `assets/screens/pipelines.png` abgemalt und lag an drei Stellen
|
||
daneben, die im Bild nicht zu erkennen waren. Der Rest steht in
|
||
[`POST-5.md`](./POST-5.md) §7.
|
||
|
||
> **Eine Richtigstellung.** Ein früherer Stand behauptete hier, die
|
||
> Detailansicht sei nur ein Entwurfs-PNG. Falsch: geprüft worden waren die
|
||
> Beschriftungen des Bildes `07_Screen-4b_Karten-Detail.png`, und die kommen im
|
||
> Code wirklich nicht vor — den Bildschirm gibt es trotzdem, unter
|
||
> `app/(screens)/4b/`, nur anders beschriftet. Die Abwesenheit einer
|
||
> Zeichenkette beweist die Abwesenheit eines Bildschirms nicht.
|
||
|
||
**Post 6 zeigt den Team-Chat**, nachgebaut aus `GeneralTeamChatPage` des
|
||
Pitch-Pakets. Anders als die Pipeline mit ihren vier eigenen Bildschirmen gibt
|
||
es vom Chat nur eine Fassung, unter `/allgemein/team-chat`. Die Inhalte darin
|
||
sind trotzdem aus dem Gewerk: Wärmepumpe Müller, Montagetermin,
|
||
Baustellenfotos.
|
||
|
||
| Slide | Was sie leistet |
|
||
|---|---|
|
||
| 1 | Kanalliste und Verlauf nebeneinander, mit Filterzeile und Eingabefeld |
|
||
| 2 | links das Durcheinander als Zeichnung, rechts die Kanalliste |
|
||
| 3 | Fotos, die Aufgabe daraus, die Bestätigung im Projekt |
|
||
| 4 | das Menü hinter dem Plus im Eingabefeld |
|
||
| 5 | zwei Ausschnitte der Oberfläche, versetzt übereinander, mit Absperrband |
|
||
|
||
**Slide 3 ist der Kern**, und sie ist keine Konstruktion: im Werkzeug folgen
|
||
die drei Nachrichten genau so aufeinander. Tobias schickt die Baustellenfotos,
|
||
darauf eine Nachricht mit angehängter Aufgabe, darauf die Systemzeile
|
||
„Aufgabe „Materialliste prüfen" im Projekt erstellt". Die letzte Zeile macht
|
||
den Unterschied: die Aufgabe liegt danach im Projekt, nicht nur im Verlauf.
|
||
|
||
**Slide 5 zeigt zwei Ausschnitte statt eines Geräts.** Die Machart ist die,
|
||
die Signal für solche Slides benutzt: zwei Teile der Oberfläche,
|
||
versetzt übereinander, jeder mit eigenem Schatten. Ein Zwischenstand hatte hier
|
||
ein nachgebautes Handy samt Insel und Tasten; das kostet viel Platz für etwas,
|
||
das nichts über das Produkt sagt, und der Rahmen war frei erfunden.
|
||
|
||
**Slide 2 stellt gegenüber statt zu zeigen:** links das Durcheinander als
|
||
Zeichnung, rechts die Oberfläche als Ausschnitt. Die linke Hälfte gibt es in
|
||
diesem Repo schon, in `post2.html` auf Slide 2 (`visProzesse`) — dort im
|
||
Zeichenblock-Stil, hier glatt. Die Plättchen sind Redaktionstext und keine
|
||
Produktstrings; sie beschreiben die Wirklichkeit im Betrieb.
|
||
|
||
**Die Leitung läuft über den Wisch hinweg:** sie beginnt links außerhalb der
|
||
Slide, und mit `visLeft: -102` landet dieses Stück auf Slide 1. Das ist der
|
||
Überstand, vor dem `rules.md` §5 sonst warnt — `.page` hat kein `overflow` —
|
||
hier aber gewollt. `pruef.mjs` liest einen negativen `--vis-left` als Ansage
|
||
und meldet ihn nicht mehr als Fehler.
|
||
|
||
Beide Ausschnitte auf Slide 5 sind leicht verwischt: erkennbar, aber nicht zu lesen.
|
||
Scharf bleibt allein das Band. Von Slack kommt ein zweites Mittel, das auf
|
||
Slide 3 sitzt: **ein dicker gelber Rahmen, der seitlich aus der Blase
|
||
ausbricht** und auf die Anhangkarte der Aufgabe zeigt, weil die den Satz der
|
||
Slide trägt.
|
||
|
||
Dass die App noch nicht da ist, sagt das **Absperrband** von der Website:
|
||
`ChatDemoSection.tsx` hat es unter der Fahne `comingSoon`, -13° gedreht, in
|
||
`#F1B729` mit Kanten in `#171106`, darauf Schutzhelm und „BALD VERFÜGBAR". Auch
|
||
Überschrift und Fließtext sind die der Website; der Inhalt der Ausschnitte
|
||
kommt aus dem Pitch-Paket wie auf allen anderen Slides.
|
||
|
||
**Die Tiefe kommt aus dem Stapel und gestaffelten Schatten, nicht aus
|
||
Flächen.** Ein Zwischenstand legte graue Flächen hinter die Elemente; das nimmt
|
||
den Zeichnungen ihre Durchsichtigkeit und setzt einen Kasten auf den
|
||
Punktgrund. Stattdessen zweierlei: die echten Schatten aus `ui/theme.css`, die
|
||
dort **gestaffelt** sind (enge dunkle Kante plus weite helle, in SVG zwei
|
||
`feDropShadow` im selben Filter), und der **Stapel** aus `post1.html`, in SVG
|
||
nachgebaut mit denselben Winkeln, die dort im CSS stehen. Die hinteren Blätter
|
||
sind leer: Andeutung, keine Kopie. Auf Slide 1 und 2, wo ein Bildschirm zu
|
||
sehen ist; nicht auf Slide 3, wo ein Ausschnitt einer Unterhaltung steht.
|
||
|
||
Dazu die Datumsmarke und die Zeile „Maike Berger schreibt gerade …" aus der
|
||
Quelle, die der Unterhaltung Struktur geben, ohne eine Fläche zu behaupten.
|
||
|
||
**Die Bildergalerie ist eine Anhangkarte, kein Bild.** Im Werkzeug lädt
|
||
`GalleryPreview` zwei Fotos von Unsplash. Fremde Fotos in einen Beitrag zu
|
||
setzen, der von der eigenen Baustelle spricht, wäre eine Behauptung über
|
||
Material, das wir nicht haben.
|
||
|
||
Die vierzehn Partner-Marken liegen unter `assets/partner/` und sind, wie alles
|
||
andere hier, aus der Website **gespiegelt statt verlinkt**. Sechs davon sind
|
||
PNG und damit dieselbe Wette wie ein Screenshot (§7 in `rules.md`), deshalb
|
||
prüft der Export sie einzeln nach — `wabenZonen()` in `post3.html`.
|
||
|
||
Der Redaktionsplan für alle weiteren Beiträge liegt in
|
||
[`redaktionsplan/`](./redaktionsplan/), gebaut mit `python3 redaktionsplan/bauen.py`.
|
||
|
||
### Slides anlegen und wegnehmen
|
||
|
||
Wie viele Slides ein Post hat, steht nicht fest. Unter der Slide-Auswahl:
|
||
|
||
| Knopf | Wirkung |
|
||
|---|---|
|
||
| `+ Neu` | leere Slide dahinter einfügen |
|
||
| `Kopie` | die gewählte Slide samt Text, Bild und Verschiebungen verdoppeln |
|
||
| `Löschen` | die gewählte Slide wegnehmen (die letzte bleibt stehen) |
|
||
| `←` `→` | eine Position nach vorn oder hinten |
|
||
|
||
Bei einer einzigen Slide ist der Post ein **Einzelbild** — die Kopfzeile sagt
|
||
es, und der ZIP-Knopf verschwindet.
|
||
|
||
Unter **Inhalt (nur diese Slide)** stehen Tag, Überschrift, Fließtext und die
|
||
Auswahl des Screenshots. Getippt wird Text, keine Auszeichnung: `*Wort*` setzt
|
||
den Akzent, ein Zeilenumbruch bricht die Zeile um. Das Rahmenformat folgt beim
|
||
Wechsel automatisch dem Seitenverhältnis der gewählten Aufnahme.
|
||
|
||
> Die Tags sind gestalterisch ausgeblendet (`visibility: hidden` auf `.badge`).
|
||
> Der eingetippte Tag beschriftet deshalb vorerst nur den Slide-Knopf im
|
||
> Bedienfeld.
|
||
|
||
### Eigene Bilder importieren
|
||
|
||
Unter **Eigene Bilder** wählst du Dateien aus dem Finder, oder du ziehst sie
|
||
direkt auf eine Slide. Beim Ablegen wird das Bild dort zum **zweiten Bild** und
|
||
lässt sich im Bearbeiten-Modus frei schieben und in der Größe ändern; über den
|
||
Knopf importierst du nur und ordnest danach unter *Inhalt* zu.
|
||
|
||
Die Datei geht **byteweise unverändert** an den Server und liegt danach unter
|
||
`assets/eigene/`. Nichts wird neu kodiert, skaliert oder umbenannt — nur
|
||
Zeichen, die in einem Dateinamen nichts zu suchen haben, weichen einem
|
||
Bindestrich.
|
||
|
||
```
|
||
assets/eigene/ importierte Bilder, gehören mit in den Commit
|
||
```
|
||
|
||
> Der Umweg über den Server ist Absicht. Ein Foto als Base64 im Projektstand
|
||
> wäre größer als der gesamte übrige Stand und machte jeden Diff unlesbar. So
|
||
> steht dort nur der Pfad.
|
||
|
||
Die Auswahllisten unter *Inhalt* holt der Generator beim Start vom Server
|
||
(`/bilder`), importierte Bilder stehen deshalb sofort darin — mit `★`
|
||
gekennzeichnet.
|
||
|
||
**Mitgelieferte Slides bleiben Vorlagen.** Der Stand speichert für sie nur
|
||
einen Verweis und die Felder, die du überschrieben hast — eine Änderung an der
|
||
Vorlage im Code kommt dadurch weiterhin bei allen an, die sie nicht angefasst
|
||
haben. Selbst angelegte Slides stehen vollständig im Stand.
|
||
|
||
**Das Projekt speichert seinen Stand** — Einstellungen, Layouts, Muster und
|
||
alle Verschiebungen aus dem Canvas überleben einen Reload. „Projekt
|
||
zurücksetzen" wirft ihn weg.
|
||
|
||
### Der Stand liegt im Repo
|
||
|
||
Nicht nur im Browser: jede Änderung landet auch in `state/<projekt>.json`.
|
||
**Diese Dateien gehören mit in den Commit.** Nur so hat die andere Maschine
|
||
nach `git pull` denselben Stand.
|
||
|
||
```
|
||
state/post1.json Post 1 · Lösung
|
||
state/post1-merk.json Rückfallpunkt
|
||
```
|
||
|
||
Beim Laden gewinnt die Datei, der localStorage ist nur der Rückfall, wenn der
|
||
Server nicht läuft. Wer den Stand ändert, muss also committen und pushen —
|
||
sonst sieht ihn niemand sonst. Gibt es die Datei noch nicht, wird der Stand
|
||
aus dem Browser einmalig hineingeschrieben.
|
||
|
||
|
||
## Animation
|
||
|
||
Unter dem Canvas liegt in **jedem** Projekt, im selben Fenster, ein Bereich
|
||
„Animation". Er zeigt jede Animation als eigenes Blatt in Vorschau, mit
|
||
Zeitregler, `Abspielen` und `MP4 exportieren`.
|
||
|
||
**Eine Animation ist keine Slide.** Sie steht in `ANIMS` und nicht in
|
||
`SLIDES`, liegt also nicht im Streifen, taucht in der Slide-Auswahl nicht auf
|
||
und wird vom Bildexport nicht angefasst. Das ist der ganze Punkt: im Carousel
|
||
ist sie ein eigenes Element, und ob sie mitkommt, entscheidest du beim Posten.
|
||
|
||
```js
|
||
const ANIMS = [
|
||
{ key: "animChat", type: "feature", dauer: 5,
|
||
eyebrow: "Bewegtbild",
|
||
head: 'Getippt,<br><span class="a">und schon im Projekt.</span>',
|
||
body: "Eine Nachricht, ein Klick, und die Aufgabe hängt am richtigen Projekt.",
|
||
vis: "animChat", visW: 700, visLeft: 190, visBottom: 120 },
|
||
];
|
||
```
|
||
|
||
Dieselben Felder wie bei einer Slide, dazu `dauer` in Sekunden. Die
|
||
Zeichenfunktion aus `VIS` bekommt einen zweiten Wert `t` zwischen 0 und 1 und
|
||
zeichnet daraus den Stand zu diesem Zeitpunkt. Blatt, Überschrift,
|
||
Punktgrund und Schutzzone sind dieselben wie überall.
|
||
|
||
### Exportieren
|
||
|
||
**`MP4 exportieren`** im Bereich unter dem Canvas. Der Browser kann kein MP4
|
||
schreiben, also stößt die Seite den Bau auf dem Server an (`POST /anim`) und
|
||
fragt den Stand ab; die Zeile unter den Knöpfen zeigt den Fortschritt und am
|
||
Ende den Pfad. Getrennt vom Bildexport, in beide Richtungen: „Alle Slides als
|
||
ZIP" enthält kein Video, und dieser Knopf rendert kein Bild.
|
||
|
||
**Die Datei landet zweimal.** In `~/Downloads`, wie die Bilder, zum Hochladen.
|
||
Und in `animation/` im Repo, wo sie versioniert ist und nach einem Pull auf
|
||
der anderen Maschine liegt. In Downloads wird nichts überschrieben: eine
|
||
zweite Ausgabe heißt `…-1.mp4`, genau wie beim Bildexport.
|
||
|
||
Auf der Kommandozeile geht dasselbe:
|
||
|
||
```sh
|
||
./serve.sh # muss laufen
|
||
node animation.mjs post6.html # alle Animationen des Projekts
|
||
node animation.mjs post6.html animChat # nur diese
|
||
```
|
||
|
||
Heraus kommt `animation/post6-animChat.mp4` (auf der Kommandozeile nur dort,
|
||
ohne die Kopie in Downloads). Angesprochen wird die Animation
|
||
über ihren Schlüssel, nicht über eine Nummer: sie hat keine Position im
|
||
Streifen, die sich verschieben könnte.
|
||
|
||
Für die Aufnahme lädt das Skript die Seite als `?nur=anim&k=<key>`. In diesem
|
||
Modus zeigt sie allein das Blatt der Animation, in natürlicher Größe an 0,0 —
|
||
damit entfällt jede Ausschnittsrechnung.
|
||
|
||
### Was Instagram bei so einem Beitrag tatsächlich annimmt
|
||
|
||
Kurz: **ein MP4, kein GIF.**
|
||
|
||
| | |
|
||
|---|---|
|
||
| Format | MP4, H.264 High, `yuv420p`, `+faststart` |
|
||
| Maße | 1080 × 1350 (4:5), wie die Standbilder |
|
||
| Bildrate | 30 fps, Schlüsselbild jede Sekunde |
|
||
| Datenrate | rund 12 Mbit/s |
|
||
| Länge | mindestens 3 s, höchstens 60 s je Carousel-Element |
|
||
| Ton | eine stumme AAC-Spur |
|
||
|
||
Vier Dinge, die den Aufbau bestimmen:
|
||
|
||
- **GIF geht nicht.** Instagram nimmt keine GIF-Uploads an; die Datei landet
|
||
als Standbild. Was in der App wie ein animierter Beitrag aussieht, ist ein
|
||
kurzes Video.
|
||
- **Ein Video im Carousel wird kein Reel.** Seit 2022 wandert nur ein
|
||
*einzeln* geposteter Video-Beitrag automatisch in die Reels. Liegt das Video
|
||
in einem Carousel, bleibt der Beitrag ein Beitrag.
|
||
- **Der erste Beitrag im Carousel bestimmt den Ausschnitt für alle.** Ein
|
||
Element in einem anderen Seitenverhältnis wird beschnitten, nicht
|
||
eingepasst. Deshalb rendert die Animation in genau denselben 1080 × 1350 wie
|
||
jedes Standbild.
|
||
- **Eine stumme Tonspur muss mit.** Manche Upload-Wege lehnen ein Video ohne
|
||
Audiostrom ab. Die Spur kostet 128 kbit/s und erspart die Fehlersuche.
|
||
|
||
Die Bewegung läuft in Schleife. Das letzte Bild ist deshalb **nicht** dasselbe
|
||
wie das erste (`t = n / anzahl`, nicht `n / (anzahl − 1)`) — sonst steht der
|
||
Stoß eine Dreißigstelsekunde still.
|
||
|
||
|
||
## Bedienung
|
||
|
||
| Taste | Wirkung |
|
||
|---|---|
|
||
| `←` `→` | Slide wechseln (im Bearbeiten-Modus: Element verschieben) |
|
||
| `E` | Bearbeiten an/aus |
|
||
| `W` | Streifen ⇄ Einzelansicht |
|
||
| `V` | Variante hell/dunkel |
|
||
| `L` `M` `I` | Layout · Muster · Intensität |
|
||
| `C` `G` `T` | Durchgehend · Tag-Ausrückung · Perspektive |
|
||
| `D` `A` | Slide laden · alle als ZIP |
|
||
|
||
Im Bearbeiten-Modus lassen sich Elemente ziehen und mit den Pfeiltasten
|
||
pixelweise schieben (`⇧` = 10 px).
|
||
|
||
**Ein angeklicktes Element öffnet sein eigenes Feld rechts.** Damit ist die
|
||
Oberfläche geteilt: links die Slide und alles Allgemeine, rechts das eine
|
||
Element.
|
||
|
||
| Im Element-Feld | Wirkung |
|
||
|---|---|
|
||
| `Text` | Beschriftung des Elements, `*Wort*` setzt den Akzent |
|
||
| `Schrift` / `Breite`, `A−` `A+` | Größe |
|
||
| `X` `Y` | Stelle auf der Slide, gezählt ab der Mitte, bezogen auf die obere linke Ecke |
|
||
| `Ebene` | wie `z-index` — höher liegt weiter vorn. Leer heißt Standard |
|
||
| `Links` `Mitte` `Rechts`, `Oben` `Mitte` `Unten` | an der Slide ausrichten, 92 px Rand |
|
||
| `Position` / `Größe angleichen` | denselben Wert auf allen Slides |
|
||
| `Löschen` | nimmt es aus der Slide. Es taucht darunter als „… zurück" wieder auf |
|
||
|
||
**Der Streifen ist eine durchgehende Fläche.** Jede Slide trägt das gesamte
|
||
Blatt, ein Element lässt sich also über den ganzen Post schieben und nicht nur
|
||
in die Nachbar-Slide.
|
||
|
||
### Auf der Fläche bewegen
|
||
|
||
| Maus | Wirkung |
|
||
|---|---|
|
||
| Ziehen | Ausschnitt schieben |
|
||
| Rad | Zoomen, auf den Zeiger zu |
|
||
| `⇧` + Rad | Waagerecht schieben |
|
||
| Leertaste-Ziehen, mittlere Taste | Schieben, auch im Bearbeiten-Modus |
|
||
|
||
Ein gewöhnliches Mausrad genügt, ohne Zusatztaste. Im Bearbeiten-Modus zieht
|
||
die linke Taste das Element unter dem Zeiger — die Fläche schiebt man dort mit
|
||
gedrückter Leertaste oder der mittleren Taste. `Fit` unten rechts setzt den
|
||
Maßstab zurück.
|
||
|
||
## Aufbau
|
||
|
||
```
|
||
assets/
|
||
├── brand/ Wortmarke hell/dunkel, G-Marke (SVG + PNG), Wabe, Geerkens
|
||
├── partner/ die 14 Marken des Wabenfelds (DATEV, KWP, pds, Bauhow, Aircall,
|
||
│ Onepage, PandaDoc, Hallo Petra, Claude, OpenAI, Google Drive,
|
||
│ Google Calendar, MS Outlook, MS Teams)
|
||
├── mockups/ Geräte-Mockups (Displays ausgeknockt, Screenshot liegt dahinter)
|
||
├── screens/ Software-Screenshots
|
||
├── eigene/ selbst importierte Bilder
|
||
└── fonts/ Manrope 400–800, lokal
|
||
vendor/ html-to-image, JSZip
|
||
state/ Projektstände, gehören ins Repo
|
||
animation.mjs baut aus einem ANIMS-Eintrag ein MP4 (braucht ffmpeg)
|
||
animation/ die fertigen MP4s, ein Carousel-Element je Datei
|
||
serve.py Statischer Server + /save, /state, /upload, /bilder, /anim
|
||
rules.md Gestaltungsregeln, Farbwerte, Export-Wissen
|
||
```
|
||
|
||
## Regeln
|
||
|
||
**`rules.md` ist die Arbeitsgrundlage.** Farbwerte, Geometrie, Typografie,
|
||
Layout-Template, Instagram-Export und die Liste der Fallen, in die wir schon
|
||
getappt sind. Vor jeder Änderung an der Gestaltung dort nachsehen.
|
||
|
||
Marken-Werte stammen aus der Website (`HiveGrid-Website`) und sind hier
|
||
**gespiegelt**, nicht verlinkt. Ändert sich dort etwas, muss es hier
|
||
nachgezogen werden.
|