Ein Template ist eine gewöhnliche statische Website (HTML + CSS + Bilder, kein JavaScript). ProntoSite übernimmt sie beim Import bytetreu und leitet alles aus Struktur, Wiederholung und Position ab. Es gibt keine ProntoSite-Spezialattribute, die du setzen musst oder darfst. Ein gutes Template ist eines, das ProntoSite ohne "nicht erkannt"-Meldungen versteht: Bereiche, Wiederholungsgruppen, Navigation, Formulare und Interaktionsmuster sind dann alle sauber bearbeitbar.
Diese Seite beschreibt, wie du dein HTML baust, damit das gelingt, und warum die jeweilige Regel fürs Ergebnis wichtig ist.
1. Semantische Struktur #
Regel: Gliedere Seiten mit den fünf Bereichs-Tags <header>, <nav>, <main>, <aside>, <footer> (plus <article>). Baue innerhalb von <main> jede Sektion als <section> mit eigener Überschrift (h1–h6), die Überschriften-Hierarchie absteigend.
Warum: ProntoSite kennt genau diese Bereiche und bildet daraus die Gliederung (Inhaltsverzeichnis und Breadcrumb): Kopfbereich, Navigation, Inhalt, Seitenleiste, Fußbereich. Überschriften eröffnen die Blöcke der Gliederung und geben jedem Container ein sprechendes Label (die erste Überschrift im Abschnitt; fehlt sie, greift das System auf Bild-Alt oder einen Kurztext zurück). Sektionen ohne erkennbare Rolle tauchen in der Prüfansicht als "Bereich ohne Rolle" auf.
Text-Elemente: Bearbeitbarer Text muss in einem echten Text-Element stehen: h1–h6, p, li, button, label, td, th, figcaption, blockquote, dt, dd, caption, summary, legend, span (auch ein div, das NUR Inline-Kinder enthält, zählt). Text, der direkt in einem Layout-div zwischen Block-Kindern liegt, wird NICHT editierbar.
<!-- RICHTIG: Bereichs-Tags, Sektion mit Überschrift, Text in <p> -->
<main>
<section class="leistungen">
<h2>Unsere Leistungen</h2>
<p>Wir begleiten Sie von der Planung bis zur Übergabe.</p>
</section>
</main>
<!-- FALSCH: div-Suppe ohne Überschrift, nackter Text im Layout-Container -->
<div class="wrapper">
<div class="box">
Wir begleiten Sie von der Planung bis zur Übergabe.
<div class="deco"></div>
</div>
</div>
2. Wiederholungsgruppen (Karten, Listen, Team-Grids) #
Regel: Baue gleichartige Einträge als direkte Geschwister mit demselben Tag und derselben Kind-Tag-Struktur — und liefere mindestens 3 Einträge.
Warum: ProntoSite gruppiert Geschwister, wenn ihr Tag gleich ist und ihre direkten Kind-Tags weitgehend übereinstimmen. Ab 3 Einträgen gilt eine Gruppe als sicher erkannt; bei nur 2 Einträgen bleibt sie unsicher (löst beim Duplizieren eine Rückfrage aus und erscheint in der Prüfansicht unter "nicht erkannt"). Nur auf sicheren Gruppen funktionieren Duplizieren, Entfernen und Umsortieren reibungslos.
Listen: <ul>/<ol> mit <li> bilden IMMER eine vollständige Gruppe — auch bei innerer Abweichung. Verwende für Aufzählungen also echte Listen.
Footer-Spalten: Ein Container im <footer>, dessen direkte Kinder überwiegend "spaltenartig" sind, wird als Spalten-Gruppe geführt. Spaltenartig heißt: div/section/nav/li mit eigener Überschrift. Gib jeder Footer-Spalte deshalb eine h4/h5-Überschrift.
<!-- RICHTIG: 3 Karten, identische Kind-Struktur (img+h3+p+a) -->
<div class="grid">
<article class="card"><img src="img/a.jpg" alt="…"><h3>Planung</h3><p>…</p><a class="btn" href="kontakt.html">Mehr</a></article>
<article class="card"><img src="img/b.jpg" alt="…"><h3>Umsetzung</h3><p>…</p><a class="btn" href="kontakt.html">Mehr</a></article>
<article class="card"><img src="img/c.jpg" alt="…"><h3>Übergabe</h3><p>…</p><a class="btn" href="kontakt.html">Mehr</a></article>
</div>
<!-- FALSCH: nur 2 Einträge (unsichere Gruppe) und abweichende Struktur
(Karte 2 ohne Bild, zusätzlicher Wrapper) -->
<div class="grid">
<article class="card"><img src="a.jpg" alt=""><h3>Planung</h3><p>…</p></article>
<div class="card special"><div class="inner"><h3>Umsetzung</h3></div></div>
</div>
3. ARIA-Konventionen #
ProntoSite wertet genau diese Attribute aus — mehr nicht:
| Attribut | Wirkung |
|---|---|
aria-controls (am Menü-Button) |
stärkstes Mobile-Menü-Signal |
aria-expanded |
Mobile-Menü-Signal |
aria-haspopup="true|menu|listbox" |
Untermenü-Kandidat (Dropdown NUR mit echter verschachtelter Linkliste) |
aria-hidden="true", role="presentation|none" |
Element gilt als Dekoration → gesperrt (nicht editierbar) |
aria-label |
editierbares Attribut-Feld; an Slider-Pfeilen zusätzlich Erkennungssignal (prev/next/…) |
alt, title, placeholder |
editierbare Attribut-Knoten |
label[for] / umschließendes <label> |
Feld-Beschriftung der Formular-Erkennung |
Achtung — häufigster Fehler: aria-hidden="true" auf INHALT (z. B. einem dekorativ animierten Titel) sperrt ihn für jede Bearbeitung. Verwende es nur für echte Dekoration (Icon-Glyphen, Zier-Elemente).
<!-- RICHTIG: dekoratives Icon versteckt, Inhalt frei -->
<i class="icon icon-star" aria-hidden="true"></i><h3>Bewertungen</h3>
<!-- FALSCH: die Überschrift ist damit gesperrt -->
<h3 aria-hidden="true">Bewertungen</h3>
4. CSS: Variablen-Token und Sanitisierung #
Regel Token: Definiere im Stylesheet :root-Variablen mit accent, primary oder brand im Namen; baue Buttons über eine Klasse mit btn, button oder cta; gib Hintergrundfarben von body/.hero/section als Hex-Wert an.
Warum: ProntoSite liest daraus die Optik der Website aus: die Akzentfarbe (--*accent|primary|brand*), border-radius, border, font-family, font-size (bevorzugt an body/p), die :focus-Outline, die häufigste btn/button/cta-Klasse an <a>/<button> und die background-color von body/.hero/section für die Hell/Dunkel-Einstufung. Aus diesen Werten entsteht die Optik neu eingefügter Formulare — sie fügen sich dann automatisch ins Design ein.
Regel Sanitisierung: Kein externes @import, kein expression(), kein behavior:, kein url(javascript:…) — diese werden beim Import entfernt (in .css-Dateien UND <style>-Blöcken). Alles andere CSS bleibt unangetastet. Liefere alle Styles lokal aus (Abschnitt 6).
/* RICHTIG */
:root { --primary: #1d4ed8; --accent: #f59e0b; }
body { font-family: "Inter", system-ui, sans-serif; font-size: 16px; background-color: #ffffff; }
.btn { background: var(--primary); border-radius: 6px; }
.btn:focus-visible { outline: 2px solid var(--accent); }
/* FALSCH: externes @import wird beim Import ENTFERNT → Optik bricht */
@import url("https://fonts.googleapis.com/css2?family=Inter");
5. Interaktionsmuster (Mobile-Menü, Dropdown, Slider, Akkordeon) #
Grundsatz: Du setzt keine data-ps-*-Attribute. ProntoSite erkennt die Muster rein strukturell und richtet die Interaktivität bei der Auslieferung selbst ein. So baust du die Muster, damit die Erkennung greift:
Mobile-Menü (Punktesystem: aria-controls wiegt am stärksten, dann Hamburger-Icon, aria-expanded, <button>; das Ziel muss auflösbar sein, sonst bleibt das Menü statisch):
<header>
<button class="burger" aria-controls="mainnav" aria-expanded="false">
<span></span><span></span><span></span> <!-- 3 gleiche leere Kinder = Hamburger -->
</button>
<nav id="mainnav">
<ul>
<li><a href="index.html">Start</a></li>
<li><a href="leistungen.html">Leistungen</a></li> <!-- ≥2 interne Links = Navigation -->
</ul>
</nav>
</header>
Dropdown (ein Menüpunkt mit ECHTER verschachtelter Linkliste; aria-haspopup allein reicht nicht):
<li><a href="leistungen.html">Leistungen</a>
<ul class="sub"><li><a href="malerarbeiten.html">Malerarbeiten</a></li>
<li><a href="bodenbelaege.html">Bodenbeläge</a></li></ul></li>
Slider/Karussell — die Signale müssen OHNE CSS erkennbar sein, denn Klassen-CSS wird für die Slider-Erkennung NICHT ausgewertet. Eines von drei Signalen genügt:
overflow:hiddenals Inline-Style am Container + mindestens 3 gleichartige Folien, ODER- Folien mit
position:absoluteals Inline-Style, ODER - Steuerungen als Geschwister der Folien: mindestens 2 Pfeile (
button/amitaria-label/Klasseprev/next/arrow/… oder Textzeichen‹ ›) oder ein Punkte-Container (mehrere kleine, textarme klickbare Kinder).
<!-- RICHTIG: Inline-overflow + 3 Folien + Pfeile -->
<div class="hero-slider" style="overflow:hidden">
<div class="slide"><img src="img/s1.jpg" alt="…"></div>
<div class="slide"><img src="img/s2.jpg" alt="…"></div>
<div class="slide"><img src="img/s3.jpg" alt="…"></div>
<button aria-label="Voriges">‹</button><button aria-label="Nächstes">›</button>
</div>
<!-- FALSCH: overflow nur im Stylesheet (.hero-slider{overflow:hidden}) → für die
Erkennung unsichtbar, ohne Pfeile/Punkte KEIN Slider → Folien stehen statisch untereinander -->
Akkordeon (mindestens 2 direkte Kind-Paare aus klickbarem Kopf — h1–h6, button, summary, a, dt — gefolgt von einem Inhaltscontainer div/section/dd/ul mit Inhalt):
<div class="faq">
<h3>Was kostet ein Anstrich?</h3><div><p>…</p></div>
<h3>Wie lange dauert es?</h3><div><p>…</p></div>
</div>
Ehrlichkeits-Netz: Klassen wie slider/carousel/accordion/tab/dropdown/collapse/menu/toggle oder data-toggle-artige Attribute OHNE erkennbares Muster erzeugen eine "konnte nicht sicher übernommen werden"-Meldung im Import-Bericht. Verwende solche Klassen also nur dort, wo das Muster wirklich erkennbar gebaut ist.
6. Assets: lokal, relativ, Favicon, Bildgrößen #
- Alles lokal, relative Pfade. Externe
https://…-Verweise (Bilder, CSS, Fonts,srcset,url()in<style>/style=) werden beim Import zwar best-effort lokalisiert (mit Grenze, Fehlschläge im Bericht) — ein Template sollte aber ab Werk null externe Verweise enthalten. - Favicon:
<link rel="icon" href="img/favicon.png">im<head>der Startseite, als lokale, mitgelieferte Datei.data:-URIs und externe URLs werden ignoriert. - Icons vs. Fotos: Als Icon gelten inline
<svg>, Icon-Font-Glyphen (<i class="fa-…">, leer) und<img>mit.svg-Quelle oderwidth/height≤ 64 — sie sind über die Icon-Bibliothek tauschbar. Größere Raster-Bilder gelten als Foto. Zeichne Fotos deshalb IMMER mitwidth/height> 64 bzw. ohne Icon-Klasse aus, Icons klein bzw. als Inline-SVG (siehe Abschnitt 10). - Hintergrundbilder:
style="background-image:url(img/…)"(inline) wird als Bild-Knoten erkannt und ist tauschbar; Hintergrundbilder, die NUR im Stylesheet stehen, sind nicht adressierbar. - Formate: übliche Web-Formate (jpg/png/webp/svg/avif); baue SVG-Dateien ohne
<script>/foreignObject.
7. Formulare #
ProntoSite erkennt Formulare vollständig: je input/select/textarea den Feldnamen (name, ersatzweise id), die Beschriftung (label[for] → umschließendes <label> → placeholder → aria-label), required, pattern und eine Consent-Checkbox (deren Label/Name datenschutz/einwillig/consent/agb/privacy enthält). Ein vorhandenes Formular dient außerdem als Stil-Vorlage für die ganze Website.
Konventionen fürs Template:
- Jedes Feld mit
name-Attribut (nurA–Z,a–z,0–9,_,-, max. 40 Zeichen) und echter<label for="…">-Beschriftung. - Pflichtfelder mit
required; eine Datenschutz-Checkbox mit sprechendem Namen (z. B.name="datenschutz") — sie wird als Consent erkannt. - Reserviert:
name="website"— das ist ein Honeypot-Feld zur Spam-Abwehr; Einsendungen mit gefülltemwebsite-Feld werden still verworfen. Nie als echtes Feld verwenden. - Submit als
<button type="submit">(Submit/Reset/Button werden nicht als Felder geführt).
Erfolgs-Weiterleitung (optional, empfohlen): Das <form> darf ein data-ps-redirect-Attribut mit site-internem Ziel tragen, z. B. data-ps-redirect="/beratung?gesendet=1". Nach erfolgreichem Versand leitet die Plattform dorthin weiter. Dein Template zeigt bei ?gesendet=1 seine Danke-Ansicht (per JS den Query-Parameter lesen und das Formular gegen eine Erfolgs-Box tauschen). Nur interne Pfade — externe URLs, javascript:/data: u. Ä. werden ignoriert (dann greift die eingebaute Erfolgsmeldung). Alternativen zum Attribut: ein verstecktes <input type="hidden" name="_redirect" value="/beratung?gesendet=1">; oder eine Query-only-action="?gesendet=1". Der Fehlerfall leitet nicht weiter, sondern zeigt die feldgenaue Fehlanzeige. Ohne Deklaration bleibt es bei der eingebauten Erfolgsmeldung.
<form action="" method="post" data-ps-redirect="/beratung?gesendet=1">
… Felder …
<button type="submit" class="btn">Absenden</button>
</form>
<!-- Danke-Ansicht des Templates (liest ?gesendet=1 und blendet die Erfolgs-Box ein): -->
<script>
if (new URLSearchParams(location.search).get("gesendet") === "1") {
document.querySelector("[data-form-danke]")?.removeAttribute("hidden");
document.querySelector("form")?.setAttribute("hidden", "");
}
</script>
Setze für die action zunächst action="" (oder #) — der Import lässt das unverändert; die Anbindung an den Mailweg erfolgt später über die Formular-Registrierung und wird nicht im Template hartkodiert (die Kunden-Zuordnung ist zur Template-Zeit unbekannt).
<form action="" method="post">
<label for="f-name">Ihr Name</label>
<input id="f-name" name="name" type="text" required>
<label for="f-mail">E-Mail</label>
<input id="f-mail" name="email" type="email" required>
<label><input type="checkbox" name="datenschutz" required> Ich habe die Datenschutzerklärung gelesen.</label>
<button type="submit" class="btn">Absenden</button>
</form>
8. Verbotenes #
Alles hier wird beim Import entfernt oder führt zu Berichts-Warnungen:
- Eigenes JavaScript — jedes
<script>(inline und extern) wird entfernt;on*-Handler undjavascript:-URLs werden gestrippt..js-Dateien im ZIP werden gar nicht übernommen, ebenso.php/.asp/… - Nicht-gewhitelistete iframes — erlaubt sind NUR YouTube (wird zu youtube-nocookie gehärtet), Vimeo, Google Maps, Calendly (je als iframe, mit Sandbox) und ProvenExpert (nur statisches Siegel). Alles andere — inkl. JEDES
<object>/<embed>— wird entfernt und durch einen Kommentar-Platzhalter ersetzt. - JS-abhängige Dritt-Widgets — externe URLs in
data-*-Attributen erzeugen eine "bleibt statisch leer"-Warnung. Keine Lazy-Load-data-src-Muster, keinedata-settings-Widgets: Bilder direkt insrc. data-ps-*-Attribute selbst setzen — dieser Namensraum gehört der Plattform (siehe Abschnitt 5); eigene Werte kollidieren mit der automatischen Auszeichnung.- Keine Bootstrap-
data-bs-toggle-Mechanik erwarten: Ohne JavaScript zählt allein die statische Struktur aus Abschnitt 5. - Rechtstext-Formulierungen in normalen Seiten — Slugs/Dateinamen/Titel wie
impressum/datenschutz/agb/… und massierte §-Formulierungen im Hauptinhalt sperren die GANZE Seite für die Bearbeitung. Das ist für echte Rechtsseiten gewollt (ein Platzhalter-Impressum ins Template zu legen ist richtig) — verwende solche Begriffe aber niemals in Marketing-Slugs.
9. Abnahme-Test (je Template, vor Aufnahme in die Galerie) #
- ZIP bauen (ein gemeinsamer Wurzelordner wird erkannt):
cd template-x && zip -r ../template-x.zip . - Import ausführen: "Meine Websites" → "+ Neue Website" → ZIP-Import.
- Import-Bericht lesen — für ein sauberes Template erwartet: keine entfernten Skripte (oder bewusst, dann prüfen was fehlt), keine entfernten Embeds, keine dynamischen Widgets, keine fehlgeschlagenen Lokalisierungen, korrekte Sprachen, alle Seiten vorhanden.
- Prüfansicht je Seite prüfen: Navigation erkannt, erwartete Anzahl Gruppen, Interaktionen (mobile-menu/dropdown/slider/accordion) wie gebaut, Formulare erkannt; unter "nicht erkannt" nur bewusste Sonder-Sektionen, keine unsicheren Gruppen (sonst 3. Eintrag ergänzen), keine unerkannten Muster.
- Vorschau bedienen: Mobile-Menü öffnen/schließen (Tastatur: Enter/Escape), Dropdown, Slider-Pfeile, Akkordeon — die Muster müssen in der Vorschau funktionieren (identisch im veröffentlichten Stand).
- Editor-Durchstich: eine Überschrift ändern, eine Karte duplizieren, ein Icon tauschen, ein Bild tauschen, Undo.
- Bausteine-Tab öffnen: die erwarteten Karten/Boxen erscheinen als Bausteine mit echter Miniatur (Abschnitt 10); einen Baustein testweise auf einer anderen Seite einfügen.
- Publish prüfen: Veröffentlichen; die veröffentlichte Fassung enthält das Original bytetreu.
10. Bausteine-Tauglichkeit (Bibliothek + kontextfreie Optik) #
Regel A — als Baustein qualifizieren: Ein Eintrag einer Wiederholungsgruppe wird nur dann Bibliotheks-Baustein, wenn er inhaltlich eigenständig ist: Bild ODER Überschrift plus mindestens ein weiterer Inhaltstyp (bzw. mindestens 3 Elemente); Icon+Text; Formular; oder eine mehrteilige Textbox (mindestens 3 Elemente, mindestens 40 Zeichen). Reine Text-/Link-Listenpunkte werden bewusst NICHT aufgenommen. Außerdem darf der Eintrag kein Seitenbereich direkt unter body/main sein (ein section/header/footer/… auf oberster Ebene wird kein Baustein) — lege Karten also immer in einen Container (div.grid o. ä.).
Regel B — Optik an der EIGENEN Klasse: Der komplette Stil einer Karte muss an ihrer eigenen Klasse hängen (.card { … }), nie an Eltern-Selektoren (.grid > div { … }). Beim Einfügen an fremder Stelle warnt ProntoSite zwar, wenn die neue Umgebung Layout-Klassen trägt — aber das ERGEBNIS stimmt nur, wenn die Karte sich selbst trägt.
Regel C — identischer Inhalt = konstanter Baustein: Sind die Einträge einer Gruppe site-weit wortgleich (z. B. eine Kontaktbox auf mehreren Seiten), wird der Baustein mit Inhalt übernommen; sonst bekommen Klone Platzhalter. Schreibe Kontaktboxen deshalb überall byte-gleich (siehe Abschnitt 11).
Regel D — Icons als Inline-SVG: Bette Icons in Karten/Icon-Listen als <svg …> inline ein (oder als leeres Icon-Font-<i>): So werden sie als Icon erkannt und sind gegen die Bibliothek tauschbar (Inline-SVG wird 1:1 ersetzt, Größe/Klassen bleiben). Ein Foto-<img> lässt sich zwar auch tauschen, aber die Icon-Erkennung und die Rollen-Benennung ("Icon-Karte") greifen nur bei echten Icon-Elementen.
<!-- RICHTIG: eigenständige Icon-Karte, Stil an .icard, Inline-SVG -->
<div class="icards">
<div class="icard">
<svg class="icon" width="32" height="32" viewBox="0 0 24 24" aria-hidden="true"><path d="…"/></svg>
<h3>Beratung</h3><p>Persönlich und vor Ort.</p>
</div>
<!-- … 2 weitere gleich gebaute … -->
</div>
/* RICHTIG: die Karte trägt sich selbst */
.icard { background:#fff; border-radius:8px; padding:24px; box-shadow:0 2px 8px rgba(0,0,0,.08); }
/* FALSCH: Optik hängt am Eltern-Kontext – eingefügt anderswo bricht sie */
.icards > div { background:#fff; border-radius:8px; }
11. Reichweiten-Freundlichkeit (wiederholte Inhalte) #
Regel: Führe Telefonnummer, Öffnungszeiten, Adresse und ähnliche site-weite Angaben auf ALLEN Seiten in identischer Schreibweise — inklusive der tel:-/mailto:-Links (sichtbarer Text UND href konsistent).
Warum: ProntoSite erkennt wiederkehrende Inhalte über einen normalisierten Vergleich. Toleriert werden daher nur Unterschiede in Interpunktion und Leerraum ("0175-999 88 77" ≡ "0175 – 999 88 77"); abweichende Ziffern-Gruppierung oder Wortlaut zerreißen den Inhalt in getrennte Fundstellen ("0175 9998877" ≠ "0175 999 88 77"; "Mo–Fr 8–17 Uhr" ≠ "Montag bis Freitag 8 bis 17 Uhr"). Dann bietet das System nicht mehr "überall ändern?" an, sondern sieht verschiedene Inhalte. tel:-Links werden bei "überall" nur dann konsistent nachgezogen, wenn das href bereits mit tel: beginnt.
<!-- RICHTIG: überall exakt gleich, tel:-Link konsistent (alle Seiten!) -->
<div class="topbar"><span>Mo.–Fr. 8–17 Uhr</span>
<a href="tel:+4922855544">0228 555 44</a></div>
…
<footer><p>Mo.–Fr. 8–17 Uhr · <a href="tel:+4922855544">0228 555 44</a></p></footer>
<!-- FALSCH: drei Schreibweisen derselben Nummer → drei getrennte „Inhalte" -->
<span>0228/55544</span> … <span>0228 555 44</span> … <a href="tel:022855544">Ruf an!</a>
12. Marker & Shortcodes #
Mit Markern (HTML-Kommentaren bzw. dem einen erlaubten data-ps-Attribut) platzierst du an gewünschter Stelle Plattform-Elemente wie ein Kontaktformular, das Google-Bewertungs-Widget oder generierte Rechtstexte (Impressum, Datenschutz) sowie deren Links. Sie verletzen die data-ps-*-Regel aus Abschnitt 8 nicht.
Details und die vollständige Marker-Liste unter Marker & Shortcodes.