536 lines
25 KiB
Python
536 lines
25 KiB
Python
#!/usr/bin/env python3
|
||
"""Baut den Redaktionsplan als A4-PDF.
|
||
|
||
Aufbau wie beim Webinar-Vergleich: eine HTML-Datei mit eingebettetem Manrope
|
||
und eingebettetem Logo, die von Chrome nach PDF gedruckt wird. Eingebettet
|
||
heißt hier wörtlich, die Datei läuft ohne Netz und ohne Nachbarordner.
|
||
|
||
python3 redaktionsplan/bauen.py
|
||
"""
|
||
|
||
import base64
|
||
import subprocess
|
||
from datetime import date, timedelta
|
||
from pathlib import Path
|
||
|
||
HIER = Path(__file__).resolve().parent
|
||
REPO = HIER.parent
|
||
CHROME = "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
|
||
|
||
# Schrift und Logo kommen aus dem Repo selbst, nicht aus einem Nachbarordner:
|
||
# das PDF soll sich auf jedem Rechner bauen lassen, der nur dieses Repo hat.
|
||
# Manrope liegt als variables Latin-Subset vor, 200 bis 800.
|
||
FONT = base64.b64encode(
|
||
(REPO / "assets/fonts/xn7gYHE41ni1AdIRggexSvfedN4.woff2").read_bytes()).decode()
|
||
LOGO = base64.b64encode(
|
||
(REPO / "assets/brand/logo.svg").read_bytes()).decode()
|
||
|
||
TAGE = {0: "Mo", 2: "Mi", 4: "Fr"}
|
||
|
||
|
||
# Der erste Termin. Am 12.08. war der Start geplant, erschienen ist "Die
|
||
# Geschichte" aber erst am Freitag darauf -- der ganze Plan ist damit um
|
||
# einen Termin nach hinten gerutscht.
|
||
START = date(2026, 8, 14)
|
||
|
||
# Termine, die ausfallen. Der Plan rutscht ab dort um einen Slot nach hinten,
|
||
# die Beitraege davor behalten ihr Datum -- sie sind schon erschienen.
|
||
#
|
||
# Warum nicht einfach START verschieben: das haette auch die vier Beitraege
|
||
# mitgenommen, die am 14., 17., 19. und 21.08. tatsaechlich draussen waren.
|
||
# Ein Plan, der rueckwirkend andere Termine behauptet, ist keiner.
|
||
#
|
||
# 24.08. Team-Chat war nicht fertig, rueckt auf Mi 26.08.
|
||
# 26.08. und weiter geschoben: der Beitrag lag noch beim Feinschliff
|
||
# 28.08. erschienen ist er am Mo 31.08.
|
||
# 02.09. Form Builder ruecken wir bewusst auf Mo 07.09., statt ihn zwei
|
||
# 04.09. Tage nach dem Team-Chat hinterherzuschicken
|
||
AUSGELASSEN = {"24.08.", "26.08.", "28.08.", "02.09.", "04.09."}
|
||
|
||
|
||
def slots(start: date, anzahl: int, auslassen=frozenset()):
|
||
"""Die Mo/Mi/Fr-Termine ab dem Starttag, ohne die ausgelassenen."""
|
||
raus, d = [], start
|
||
while len(raus) < anzahl:
|
||
if d.weekday() in TAGE:
|
||
stempel = d.strftime("%d.%m.")
|
||
if stempel not in auslassen:
|
||
raus.append((TAGE[d.weekday()], stempel))
|
||
d += timedelta(days=1)
|
||
return raus
|
||
|
||
|
||
# Thema, Format, Ziel. Reihenfolge ist nicht beliebig: erst warum es uns gibt,
|
||
# dann die Haltung, dann die Funktionen von der täglichen Last nach hinten zu
|
||
# dem, was Vorwissen braucht.
|
||
# E-Mail-Marketing und Zettelwirtschaft sind am 11.09.2026 getauscht worden.
|
||
# Die Reihenfolge geht sonst von der taeglichen Last nach hinten zu dem, was
|
||
# Vorwissen braucht -- Zettelwirtschaft ist aber der einzige Beitrag ohne
|
||
# Produkt dahinter und muss deshalb erst gebaut werden, waehrend E-Mail-
|
||
# Marketing eine fertige Oberflaeche zum Zeigen hat.
|
||
PLAN = [
|
||
("Die Geschichte", "Carousel, 6", "Herkunft. Warum es HiveGrid gibt."),
|
||
("Verbinden statt ersetzen", "Einzelbild", "Haltung. Die Kernaussage in einem Satz."),
|
||
("Workflow-Engine", "Carousel", "Wenn-dann statt Handarbeit."),
|
||
("Projektmanagement", "Carousel", "Der Überblick, den jeder Betrieb vermisst."),
|
||
("Team-Chat", "Carousel", "Ein Kanal pro Projekt, Foto rein, Aufgabe raus."),
|
||
("Form Builder", "Carousel", "Vom Kontaktformular bis zum Aufmaß."),
|
||
("E-Mail-Marketing", "Carousel", "Aus Anfragen werden Kontakte, aus Kontakten Aufträge."),
|
||
("Zettelwirtschaft", "Carousel", "Wissen ohne Produkt. Wo im Betrieb Zeit verloren geht."),
|
||
("Mitarbeiter-Management", "Carousel", "Wer kann was, wer ist wo, wer braucht was."),
|
||
("Der Betrieb dahinter", "Carousel", "Vierte Generation SHK. Keine Studio-Bilder."),
|
||
("KI-Anbindung, MCP", "Carousel", "Externe KI darf mitlesen, ohne Datenabfluss."),
|
||
("Dein ERP bleibt", "Einzelbild", "Der Einwand Nummer eins, direkt beantwortet."),
|
||
("Tempo und Übersicht", "Reel", "Die Oberfläche selbst. Wenige Klicks, kein Suchen."),
|
||
("Warteliste", "Carousel", "Aufruf. Was die ersten Betriebe bekommen."),
|
||
("Häufige Fragen", "Carousel", "Die fünf Einwände, die immer kommen."),
|
||
]
|
||
|
||
TERMINE = slots(START, len(PLAN), AUSGELASSEN)
|
||
|
||
# Wie viele Beitraege fertig im Generator liegen. Sie sind in der Tabelle
|
||
# gelb hinterlegt, und der Satz darueber nennt die Zahl -- beides kommt aus
|
||
# derselben Konstante, damit es nicht auseinanderlaeuft.
|
||
FERTIG = 7
|
||
ZAHLWORT = {1: "Der eine markierte Termin ist", 2: "Die beiden markierten Termine sind",
|
||
3: "Die drei markierten Termine sind", 4: "Die vier markierten Termine sind",
|
||
5: "Die fünf markierten Termine sind", 6: "Die sechs markierten Termine sind",
|
||
7: "Die sieben markierten Termine sind",
|
||
8: "Die acht markierten Termine sind"}[FERTIG]
|
||
|
||
# Der erste Reel-Termin, gerechnet statt abgeschrieben. Im Text stand er
|
||
# einmal fest als "09.09." und stimmte schon damals nicht. Auch der Kommentar,
|
||
# der ihn danach auf dem 11.09. verortete, war nach der naechsten Verschiebung
|
||
# wieder falsch -- ein Datum, das sich aus AUSGELASSEN ergibt, gehoert
|
||
# nirgendwo als Zahl hingeschrieben, auch nicht in einen Kommentar.
|
||
REEL = next(d for p, (t, d) in zip(PLAN, TERMINE) if p[1] == "Reel")
|
||
SPANNE = TERMINE[0][1] + " bis " + TERMINE[-1][1] + START.strftime("%Y")
|
||
|
||
ZEILEN = "".join(
|
||
'<tr{hi}><td class="dt"><b>{tag}</b> {datum}</td><td><b>{thema}</b></td>'
|
||
'<td class="fm">{format}</td><td class="zl">{ziel}</td></tr>'.format(
|
||
hi=' class="hi"' if i < FERTIG else "",
|
||
tag=t, datum=d, thema=p[0], format=p[1], ziel=p[2],
|
||
)
|
||
for i, (p, (t, d)) in enumerate(zip(PLAN, TERMINE))
|
||
)
|
||
|
||
HTML = f"""<!doctype html>
|
||
<html lang="de">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<title>Instagram: Redaktionsplan und Vorgehen</title>
|
||
<style>
|
||
@font-face{{font-family:'Manrope';font-style:normal;font-weight:200 800;
|
||
src:url(data:font/woff2;base64,{FONT}) format('woff2');font-display:block}}
|
||
|
||
:root{{
|
||
--ink:#14161A; --ink2:#4A5158; --ink3:#868D95; --ink4:#AAB1B8;
|
||
--line:#E2E6EA; --line-soft:#EFF2F4;
|
||
--paper2:#F6F8FA; --yellow:#F1B729; --yellow-soft:#FDF3DC;
|
||
--navy:#0F1A2E; --teal:#0D6E6E; --rot:#C0554B;
|
||
}}
|
||
*{{box-sizing:border-box;margin:0;padding:0}}
|
||
html{{-webkit-font-smoothing:antialiased}}
|
||
body{{font-family:'Manrope',system-ui,sans-serif;color:var(--ink);background:#8A9099;
|
||
font-size:12.4px;line-height:1.5;font-variant-numeric:tabular-nums;letter-spacing:-.003em}}
|
||
@page{{size:A4;margin:0}}
|
||
.page{{width:210mm;height:296.6mm;background:#fff;position:relative;overflow:hidden;
|
||
padding:16mm 16mm 13mm;page-break-after:always;margin:0 auto 8mm;display:flex;flex-direction:column}}
|
||
.page:last-child{{page-break-after:auto;margin-bottom:0}}
|
||
@media print{{body{{background:#fff}}.page{{margin:0}}}}
|
||
|
||
h1{{font-size:29px;font-weight:800;line-height:1.08;letter-spacing:-.03em}}
|
||
h2{{font-size:16px;font-weight:800;letter-spacing:-.018em;line-height:1.2}}
|
||
h3{{font-size:12.4px;font-weight:800;letter-spacing:-.01em}}
|
||
p{{margin-bottom:7px}}p:last-child{{margin-bottom:0}}
|
||
strong{{font-weight:700}}
|
||
.lead{{font-size:13.6px;line-height:1.48;color:var(--ink2);font-weight:500;letter-spacing:-.01em}}
|
||
.small{{font-size:10.8px;line-height:1.45;color:var(--ink2)}}
|
||
.micro{{font-size:9.4px;line-height:1.4;color:var(--ink3)}}
|
||
.eyebrow{{font-size:8.4px;font-weight:700;letter-spacing:.16em;text-transform:uppercase;color:var(--ink3)}}
|
||
|
||
.top{{display:flex;justify-content:space-between;align-items:center;
|
||
border-bottom:1px solid var(--line);padding-bottom:8px;margin-bottom:16px;flex:0 0 auto}}
|
||
.foot{{position:absolute;left:16mm;right:16mm;bottom:7mm;display:flex;justify-content:space-between;
|
||
font-size:8.4px;letter-spacing:.05em;color:var(--ink4);border-top:1px solid var(--line-soft);padding-top:5px}}
|
||
.body{{flex:1 1 auto;min-height:0}}
|
||
|
||
.chamfer{{clip-path:polygon(10px 0,calc(100% - 10px) 0,100% 10px,100% calc(100% - 10px),
|
||
calc(100% - 10px) 100%,10px 100%,0 calc(100% - 10px),0 10px)}}
|
||
.grid2{{display:grid;grid-template-columns:1fr 1fr;gap:13px}}
|
||
.grid3{{display:grid;grid-template-columns:1fr 1fr 1fr;gap:13px}}
|
||
.card{{background:var(--paper2);padding:13px 15px}}
|
||
.card--line{{background:#fff;border:1px solid var(--line);padding:13px 15px}}
|
||
|
||
.reco{{background:var(--navy);color:#fff;padding:14px 18px;display:flex;align-items:center;gap:22px}}
|
||
.reco .lbl{{font-size:8.4px;font-weight:700;letter-spacing:.16em;text-transform:uppercase;color:var(--yellow);margin-bottom:4px}}
|
||
.reco .big{{font-size:19px;font-weight:800;letter-spacing:-.025em;line-height:1}}
|
||
.reco .sep{{width:1px;height:34px;background:rgba(255,255,255,.2)}}
|
||
|
||
.stat{{padding:12px 14px;background:var(--paper2)}}
|
||
.stat .k{{font-size:8.2px;font-weight:700;letter-spacing:.13em;text-transform:uppercase;color:var(--ink3);margin-bottom:6px}}
|
||
.stat .v{{font-size:27px;font-weight:800;letter-spacing:-.035em;line-height:1}}
|
||
.stat .v .u{{font-size:14px;font-weight:700}}
|
||
.stat .s{{font-size:9.4px;color:var(--ink3);margin-top:5px;line-height:1.3}}
|
||
.stat--acc{{background:var(--navy);color:#fff}}
|
||
.stat--acc .k{{color:#7E8CA0}}.stat--acc .v{{color:var(--yellow)}}.stat--acc .s{{color:#9AA6B6}}
|
||
|
||
table{{width:100%;border-collapse:collapse;font-size:11px}}
|
||
th{{text-align:left;font-size:8.4px;font-weight:800;letter-spacing:.11em;text-transform:uppercase;
|
||
color:var(--ink3);padding:0 8px 5px;border-bottom:1.5px solid var(--ink);vertical-align:bottom}}
|
||
td{{padding:6px 8px;border-bottom:1px solid var(--line-soft);vertical-align:top;line-height:1.35}}
|
||
tr:last-child td{{border-bottom:none}}
|
||
th:first-child,td:first-child{{padding-left:0}}
|
||
th:last-child,td:last-child{{padding-right:0}}
|
||
tr.hi td{{background:var(--yellow-soft)}}
|
||
tr.hi td:first-child{{box-shadow:inset 3px 0 0 var(--yellow);padding-left:9px}}
|
||
td.dt{{white-space:nowrap;color:var(--ink2)}}
|
||
td.fm{{white-space:nowrap;color:var(--ink2);font-size:10.4px}}
|
||
td.zl{{color:var(--ink2)}}
|
||
|
||
ul{{list-style:none}}
|
||
li{{position:relative;padding-left:14px;margin-bottom:5px;font-size:11px;line-height:1.42;color:var(--ink2)}}
|
||
li:last-child{{margin-bottom:0}}
|
||
li::before{{content:"";position:absolute;left:0;top:6px;width:5px;height:5px;background:var(--yellow)}}
|
||
li b{{color:var(--ink)}}
|
||
ul.num{{counter-reset:n}}
|
||
ul.num li{{padding-left:20px;counter-increment:n}}
|
||
ul.num li::before{{content:counter(n);background:none;color:var(--ink3);font-size:9.4px;
|
||
font-weight:800;top:0;left:0;width:auto;height:auto}}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
|
||
<!-- SEITE 1 -->
|
||
<section class="page">
|
||
<div class="top">
|
||
<img src="data:image/svg+xml;base64,{LOGO}" style="height:17px" alt="HiveGrid">
|
||
<div class="eyebrow">Instagram · Redaktionsplan & Vorgehen · Stand 23.08.2026</div>
|
||
</div>
|
||
<div class="body">
|
||
<h1 style="margin-bottom:9px">Rahmen und Rhythmus</h1>
|
||
<p class="lead" style="margin-bottom:14px;max-width:660px">
|
||
In dieser Phase erwarten wir über den Kanal keine nennenswerte Reichweite. Er dient
|
||
zuerst der <strong style="color:var(--ink)">Darstellung der Software</strong> für Leute,
|
||
die ohnehin auf uns stoßen: mögliche Kunden, Partner, Investoren. Dieses Dokument legt
|
||
fest, was wann erscheint, wie es aussieht und was wir nach vier Wochen ansehen.
|
||
</p>
|
||
|
||
<div class="reco chamfer" style="margin-bottom:15px">
|
||
<div>
|
||
<div class="lbl">Rhythmus</div>
|
||
<div class="big">Mo · Mi · Fr</div>
|
||
</div>
|
||
<div class="sep"></div>
|
||
<div>
|
||
<div class="lbl" style="color:#7A879B">Uhrzeit</div>
|
||
<div class="big" style="color:var(--yellow)">12:00</div>
|
||
</div>
|
||
<div class="sep"></div>
|
||
<div style="flex:1">
|
||
<div class="lbl" style="color:#7A879B">Worauf es ankommt</div>
|
||
<div style="font-size:11px;color:#C8D0DC;line-height:1.4">
|
||
Auf dem Eindruck der ersten neun Kacheln. Die sieht jeder, der zum ersten Mal
|
||
auf dem Profil landet, bevor er einen einzelnen Beitrag öffnet.</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="grid3" style="margin-bottom:16px">
|
||
<div class="stat chamfer">
|
||
<div class="k">Beiträge</div>
|
||
<div class="v">3<span class="u"> / Woche</span></div>
|
||
<div class="s">12 in vier Wochen. Mehr als fünf ginge auf die Qualität.</div>
|
||
</div>
|
||
<div class="stat chamfer">
|
||
<div class="k">Format zuerst</div>
|
||
<div class="v">Carousel</div>
|
||
<div class="s">Trägt Erklärung und lässt sich im Generator wiederholbar bauen.</div>
|
||
</div>
|
||
<div class="stat stat--acc chamfer">
|
||
<div class="k">Durchgängig</div>
|
||
<div class="v">Ein Raster</div>
|
||
<div class="s">Gleiche Schrift, gleicher Grund, gleiche Bildsprache über alle Beiträge.</div>
|
||
</div>
|
||
</div>
|
||
|
||
<h2 style="margin-bottom:8px">Wofür der Kanal da ist</h2>
|
||
<div class="grid2" style="margin-bottom:15px">
|
||
<div class="card chamfer">
|
||
<h3 style="margin-bottom:5px">Zeigen statt behaupten</h3>
|
||
<p class="small">Jeder Beitrag zeigt etwas Konkretes aus der Software oder aus dem
|
||
Betrieb: einen Screen, einen Ablauf, eine Aufnahme von der Baustelle. Keine
|
||
Behauptungen ohne Bild dazu.</p>
|
||
</div>
|
||
<div class="card chamfer">
|
||
<h3 style="margin-bottom:5px">Titelbilder tragen allein</h3>
|
||
<p class="small">Im Raster ist von einem Carousel nur die erste Slide zu sehen.
|
||
Die trägt deshalb einen vollständigen Gedanken, nicht den Anfang von einem. Der Rest
|
||
steht innen und in der Bildunterschrift.</p>
|
||
</div>
|
||
</div>
|
||
|
||
<h2 style="margin-bottom:8px">Warum drei Tage und warum 12:00</h2>
|
||
<div class="grid3">
|
||
<div class="card chamfer">
|
||
<h3 style="margin-bottom:5px">Drei ist die untere Grenze</h3>
|
||
<p class="small">Unter drei Beiträgen pro Woche wirkt ein Profil inaktiv. Über
|
||
fünf leidet die Qualität.</p>
|
||
</div>
|
||
<div class="card chamfer">
|
||
<h3 style="margin-bottom:5px">12:00 ist eine Annahme</h3>
|
||
<p class="small">Für handwerklich geprägte Betriebe sind drei Fenster belegt: 6 bis 8,
|
||
12 bis 13 und 19 bis 21 Uhr. Die Mittagspause passt am besten.</p>
|
||
</div>
|
||
<div class="card chamfer">
|
||
<h3 style="margin-bottom:5px">Montag ist der schwächste</h3>
|
||
<p class="small">Die Studienlage nennt Dienstag bis Donnerstag. Wir starten trotzdem
|
||
mit Mo, Mi, Fr und schauen es uns in vier Wochen an.</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="foot"><span>HiveGrid · Social Media</span><span>Seite 1 von 4</span></div>
|
||
</section>
|
||
|
||
<!-- SEITE 2: REDAKTIONSPLAN -->
|
||
<section class="page">
|
||
<div class="top">
|
||
<img src="data:image/svg+xml;base64,{LOGO}" style="height:17px" alt="HiveGrid">
|
||
<div class="eyebrow">Redaktionsplan · {SPANNE}</div>
|
||
</div>
|
||
<div class="body">
|
||
<h1 style="margin-bottom:9px">Was wann erscheint</h1>
|
||
<p class="lead" style="margin-bottom:13px;max-width:660px">
|
||
Fünfzehn Termine, alle um 12:00 Uhr. Die Reihenfolge ist nicht beliebig: erst warum
|
||
es uns gibt, dann die Haltung, dann die Funktionen. Innerhalb der Funktionen von der
|
||
täglichen Last nach hinten zu dem, was Vorwissen braucht. {ZAHLWORT} gesetzt und
|
||
liegen fertig im Generator, alles danach darf sich verschieben.
|
||
</p>
|
||
|
||
<table style="margin-bottom:14px">
|
||
<thead><tr>
|
||
<th style="width:76px">Termin</th>
|
||
<th style="width:186px">Thema</th>
|
||
<th style="width:92px">Format</th>
|
||
<th>Wofür der Beitrag da ist</th>
|
||
</tr></thead>
|
||
<tbody>{ZEILEN}</tbody>
|
||
</table>
|
||
|
||
<h2 style="margin-bottom:8px">Sechs Sorten im Wechsel</h2>
|
||
<table style="margin-bottom:15px">
|
||
<thead><tr>
|
||
<th style="width:150px">Sorte</th>
|
||
<th style="width:64px" class="t-num">Anteil</th>
|
||
<th>Beispiel aus dem Plan</th>
|
||
</tr></thead>
|
||
<tbody>
|
||
<tr><td><b>Funktion erklärt</b></td><td class="t-num">8</td>
|
||
<td>Workflow-Engine, Form Builder, Team-Chat</td></tr>
|
||
<tr><td><b>Menschen und Betrieb</b></td><td class="t-num">2</td>
|
||
<td>Die Geschichte, Der Betrieb dahinter</td></tr>
|
||
<tr><td><b>Haltung</b></td><td class="t-num">1</td>
|
||
<td>Verbinden statt ersetzen</td></tr>
|
||
<tr><td><b>Einwand beantwortet</b></td><td class="t-num">2</td>
|
||
<td>Dein ERP bleibt, Häufige Fragen</td></tr>
|
||
<tr><td><b>Wissen ohne Produkt</b></td><td class="t-num">1</td>
|
||
<td>Zettelwirtschaft</td></tr>
|
||
<tr><td><b>Aufruf</b></td><td class="t-num">1</td>
|
||
<td>Warteliste</td></tr>
|
||
</tbody>
|
||
</table>
|
||
|
||
<h2 style="margin-bottom:8px">Was unter jedem Beitrag steht</h2>
|
||
<div class="grid3">
|
||
<div class="card chamfer">
|
||
<h3 style="margin-bottom:5px">Die ersten 125 Zeichen</h3>
|
||
<p class="small">Mehr sieht niemand, bevor er auf "mehr" tippt. Der Haken gehört
|
||
dorthin, nicht in den letzten Absatz.</p>
|
||
</div>
|
||
<div class="card chamfer">
|
||
<h3 style="margin-bottom:5px">300 bis 800 Zeichen</h3>
|
||
<p class="small">Der Bereich, in dem erklärende Beiträge am besten laufen. Darunter
|
||
wirkt es dünn, darüber liest es niemand zu Ende.</p>
|
||
</div>
|
||
<div class="card chamfer">
|
||
<h3 style="margin-bottom:5px">5 bis 10 Hashtags</h3>
|
||
<p class="small">Ganz unten, durch Leerzeilen abgesetzt. Schlägt sowohl drei als auch
|
||
dreißig. Die Suchwörter gehören zusätzlich in den Fließtext.</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="foot"><span>HiveGrid · Social Media</span><span>Seite 2 von 4</span></div>
|
||
</section>
|
||
|
||
<!-- SEITE 3: BILDSPRACHE -->
|
||
<section class="page">
|
||
<div class="top">
|
||
<img src="data:image/svg+xml;base64,{LOGO}" style="height:17px" alt="HiveGrid">
|
||
<div class="eyebrow">Bildsprache & Format</div>
|
||
</div>
|
||
<div class="body">
|
||
<h1 style="margin-bottom:9px">Bildsprache</h1>
|
||
<p class="lead" style="margin-bottom:14px;max-width:660px">
|
||
Das Profil zeigt neun Kacheln auf einmal. Was gleich bleibt und was wechselt, ist
|
||
deshalb festgelegt und nicht von Beitrag zu Beitrag neu entschieden.
|
||
</p>
|
||
|
||
<div class="grid2" style="margin-bottom:16px">
|
||
<div class="card chamfer">
|
||
<h3 style="margin-bottom:6px">Was gleich bleibt</h3>
|
||
<ul>
|
||
<li><b>1080 × 1350 px</b>, das hochkantigste Feed-Format</li>
|
||
<li><b>Manrope</b>, dieselbe Schrift wie auf der Website</li>
|
||
<li><b>Ein Grund</b>, das Raster, sonst nichts</li>
|
||
<li><b>Ein Akzentwort</b> je Überschrift, per Marker</li>
|
||
<li><b>Chamfer</b> an Rahmen und Tags, die Markenform</li>
|
||
</ul>
|
||
</div>
|
||
<div class="card chamfer">
|
||
<h3 style="margin-bottom:6px">Was von Beitrag zu Beitrag wechselt</h3>
|
||
<ul>
|
||
<li><b>Hell und dunkel</b> im Wechsel, damit das Raster atmet</li>
|
||
<li><b>Screens oder Visualisierung</b>, je nach Thema</li>
|
||
<li><b>Die Anzahl der Slides</b>, fünf bis sieben</li>
|
||
</ul>
|
||
<p class="micro" style="margin-top:7px">Im Profil-Raster wird auf 3:4 beschnitten,
|
||
nicht auf 4:5. Was mittig sitzt, überlebt.</p>
|
||
</div>
|
||
</div>
|
||
|
||
<h2 style="margin-bottom:8px">Statt behaupten, zeigen</h2>
|
||
<table style="margin-bottom:16px">
|
||
<thead><tr>
|
||
<th style="width:210px">Statt</th>
|
||
<th>Zeigen wir</th>
|
||
</tr></thead>
|
||
<tbody>
|
||
<tr><td>"Alles auf einen Blick"</td>
|
||
<td>Das Board mit echten Aufträgen, Summen und Terminen.</td></tr>
|
||
<tr><td>"Spart Zeit"</td>
|
||
<td>Den Ablauf: Anfrage rein, Aufgabe raus, Bestätigung an den Kunden.</td></tr>
|
||
<tr><td>"Einfach zu bedienen"</td>
|
||
<td>Das Formular, das per Drag-and-drop entsteht.</td></tr>
|
||
<tr><td>"Aus dem Handwerk"</td>
|
||
<td>Den Betrieb, die Baustelle, die Menschen dahinter.</td></tr>
|
||
<tr><td>"Verbindet deine Tools"</td>
|
||
<td>Die Visualisierung: ERP in der Mitte, das Neue drumherum.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
|
||
<h2 style="margin-bottom:8px">Carousel jetzt, Reels später</h2>
|
||
<div class="card--line chamfer">
|
||
<p class="small" style="margin-bottom:6px">Für Konten unter 50.000 Followern bringen
|
||
Reels mehr Reichweite als Carousels. Das ist die Datenlage. Für uns ist sie zweitrangig,
|
||
weil Reichweite in dieser Phase nicht das Ziel ist.</p>
|
||
<p class="small">Carousels passen besser zu dem, was der Kanal leisten soll: Sie
|
||
erklären, sie lassen sich im Generator sauber und wiederholbar bauen, und sie werden
|
||
gespeichert. Das erste Reel steht am {REEL} und ist eine Bildschirmaufnahme, dafür
|
||
braucht es keine Kamera. Danach kommt Material aus dem Betrieb dazu. Aus drei Beiträgen
|
||
werden dann zwei Carousels und ein Reel, nicht vier Beiträge.</p>
|
||
</div>
|
||
</div>
|
||
<div class="foot"><span>HiveGrid · Social Media</span><span>Seite 3 von 4</span></div>
|
||
</section>
|
||
|
||
<!-- SEITE 4: INTERAKTION -->
|
||
<section class="page">
|
||
<div class="top">
|
||
<img src="data:image/svg+xml;base64,{LOGO}" style="height:17px" alt="HiveGrid">
|
||
<div class="eyebrow">Tägliche Arbeit & Auswertung</div>
|
||
</div>
|
||
<div class="body">
|
||
<h1 style="margin-bottom:9px">Tägliche Interaktion</h1>
|
||
<p class="lead" style="margin-bottom:14px;max-width:660px">
|
||
Instagram sortiert ein Konto auch danach ein, womit es sich selbst beschäftigt.
|
||
Rund zehn Minuten am Tag, aufgeteilt auf die drei Posting-Tage.
|
||
</p>
|
||
|
||
<div class="grid2" style="margin-bottom:16px">
|
||
<div class="card chamfer">
|
||
<h3 style="margin-bottom:6px">Die Routine pro Beitrag</h3>
|
||
<ul>
|
||
<li><b>5 Beiträge liken</b> aus dem eigenen Umfeld</li>
|
||
<li><b>3 echte Kommentare</b> schreiben, keine Emojis</li>
|
||
<li><b>1 Konto folgen</b>, das wirklich passt</li>
|
||
</ul>
|
||
<p class="micro" style="margin-top:7px">Zehn gute Kommentare bei den richtigen Konten
|
||
wirken mehr als fünfzig verstreute. In den Zahlen sichtbar wird das nach vier bis
|
||
acht Wochen.</p>
|
||
</div>
|
||
<div class="card chamfer">
|
||
<h3 style="margin-bottom:6px">Wem wir folgen</h3>
|
||
<ul>
|
||
<li><b>SHK-, Elektro- und Dachbetriebe</b>, die selbst posten</li>
|
||
<li><b>Innungen, Kreishandwerkerschaften, Kammern</b></li>
|
||
<li><b>Handwerksmessen und Fachmedien</b></li>
|
||
<li><b>Hersteller</b>, deren Produkte im Betrieb verbaut werden</li>
|
||
<li><b>Andere Handwerkssoftware</b>, deren Kommentarspalten voll sind</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="card--line chamfer" style="margin-bottom:16px">
|
||
<h3 style="margin-bottom:6px">Wie ein Kommentar aussieht</h3>
|
||
<p class="small" style="margin-bottom:6px">Am meisten bringt ein Kommentar in den ersten
|
||
Minuten nach einem Beitrag. Deshalb folgen wir gezielt Konten, die regelmäßig posten,
|
||
und schauen einmal täglich zur Mittagszeit rein.</p>
|
||
<p class="small">Ein Kommentar ist gut, wenn er ohne unseren Namen funktioniert. Also
|
||
eine Erfahrung, eine Nachfrage, ein Widerspruch. Nicht "Toller Beitrag", und nichts,
|
||
was auf uns verweist.</p>
|
||
</div>
|
||
|
||
<h2 style="margin-bottom:8px">Was wir nach vier Wochen ansehen</h2>
|
||
<table style="margin-bottom:14px">
|
||
<thead><tr>
|
||
<th style="width:150px">Kennzahl</th>
|
||
<th style="width:150px">Wo sie steht</th>
|
||
<th>Was sie uns sagt</th>
|
||
</tr></thead>
|
||
<tbody>
|
||
<tr class="hi"><td><b>Profilaufrufe je Beitrag</b></td><td>Insights, Interaktionen</td>
|
||
<td>Ob ein Beitrag jemanden dazu bringt, sich das Profil anzusehen. Das ist unser Zweck.</td></tr>
|
||
<tr><td><b>Sendungen</b></td><td>Beitragsinsights</td>
|
||
<td>Welches Thema jemand weiterschickt. Wiegt beim Ausspielen mehr als ein Like.</td></tr>
|
||
<tr><td><b>Speicherungen</b></td><td>Beitragsinsights</td>
|
||
<td>Ob ein Carousel als Nachschlagewerk taugt.</td></tr>
|
||
<tr><td><b>Konten erreicht,<br>davon keine Follower</b></td><td>Insights, Reichweite</td>
|
||
<td>Ob wir aus der eigenen Blase herauskommen.</td></tr>
|
||
<tr><td><b>Aktivste Zeiten</b></td><td>Insights, Zielgruppe</td>
|
||
<td>Ob 12:00 stimmt. Erst ab etwa 100 Followern belastbar.</td></tr>
|
||
<tr><td><b>Anmeldungen Warteliste</b></td><td>Backend</td>
|
||
<td>Ob aus dem Eindruck ein Kontakt wird.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
|
||
<div class="card chamfer">
|
||
<h3 style="margin-bottom:5px">Nach vier Wochen</h3>
|
||
<p class="small">Bleibt der Montag oder wird es Dienstag? Bleibt 12:00? Und wie viele
|
||
Reels ersetzen ab dann Carousels? Bis dahin lassen wir den Rhythmus laufen, sonst
|
||
lässt sich nichts vergleichen.</p>
|
||
</div>
|
||
|
||
<p class="micro" style="margin-top:12px">Quellen zu den Ausspielungssignalen und
|
||
Posting-Zeiten: Sprout Social, Buffer, Later und Hootsuite (Instagram-Algorithmus 2026),
|
||
adconsulting.de und socialmediaakademie.de (Posting-Zeiten B2B und Handwerk, Deutschland).
|
||
Zahlen zu Sendungen und Reichweite stammen aus Auswertungen Dritter, nicht von Meta selbst,
|
||
und sind Größenordnungen, keine Garantien.</p>
|
||
</div>
|
||
<div class="foot"><span>HiveGrid · Social Media</span><span>Seite 4 von 4</span></div>
|
||
</section>
|
||
|
||
</body>
|
||
</html>
|
||
"""
|
||
|
||
ZIEL_HTML = HIER / "Instagram-Redaktionsplan.html"
|
||
ZIEL_PDF = HIER / "Instagram-Redaktionsplan.pdf"
|
||
ZIEL_HTML.write_text(HTML, encoding="utf-8")
|
||
|
||
subprocess.run(
|
||
[CHROME, "--headless", "--disable-gpu", "--no-pdf-header-footer",
|
||
f"--print-to-pdf={ZIEL_PDF}", ZIEL_HTML.as_uri()],
|
||
check=True, capture_output=True,
|
||
)
|
||
print(f"{ZIEL_PDF.name} {ZIEL_PDF.stat().st_size / 1024:.0f} KB")
|