Erscheinungsbild
project.config.ts
Die zentrale Projektkonfiguration. Alles hier ist öffentlich und wird versioniert — Geheimnisse gehören nicht in diese Datei.
ts
import { defineProject } from './src/lib/config';
export default defineProject({
site: {/* … */},
company: {/* … */},
localization: {/* … */},
navigation: {/* … */},
features: {/* … */},
seo: {/* … */},
tracking: {/* … */},
consent: {/* … */},
forms: {/* … */},
deployment: {/* … */},
});site
| Feld | Pflicht | Regel |
|---|---|---|
name | ja | nicht leer |
url | ja | vollständige URL, https://, ohne abschließenden Schrägstrich |
locale | ja | Sprachkennzeichen wie de-DE |
titleTemplate | ja | muss den Platzhalter %s enthalten |
description | ja | nicht leer |
company
Quelle für die Schemata Organization und LocalBusiness.
| Feld | Pflicht | Regel |
|---|---|---|
legalName | ja | nicht leer |
address | bedingt | erforderlich, wenn seo.schemas.localBusiness aktiv ist |
email | nein | gültige E-Mail-Adresse |
phone | nein | — |
sameAs | nein | Liste von URLs, Vorgabe [] |
localization
| Feld | Pflicht | Regel |
|---|---|---|
defaultLocale | ja | muss in locales enthalten sein |
locales | ja | mindestens ein Eintrag |
Bei mehr als einer Sprache muss site.locale dem defaultLocale entsprechen.
Mehrere Sprachen erzeugen für sich genommen kein hreflang: Alternates entstehen erst, wenn eine Seite ihre Übersetzungen selbst nennt — siehe Metadaten.
navigation
Quelle für Kopf- und Fußnavigation. Ein Eintrag besteht aus label und href.
| Feld | Pflicht | Regel |
|---|---|---|
main | nein | Hauptnavigation im Kopf; Vorgabe [], keine doppelten Ziele |
legal.imprint | ja | Impressumslink |
legal.privacy | ja | Datenschutzlink |
legal.additional | nein | weitere Rechtslinks wie AGB; Vorgabe [] |
href muss ein absoluter Pfad (/kontakt) oder eine absolute https-URL sein. Relative Pfade sind ausgeschlossen: Sie hingen davon ab, auf welcher Seite die Navigation gerade gerendert wird, und ergeben in einem global eingebundenen Kopf keinen verlässlichen Sinn.
Impressum und Datenschutz sind Pflichtfelder
Beide sind für geschäftsmäßige Websites in Deutschland vorgeschrieben und müssen von jeder Seite aus erreichbar sein. Sie stehen deshalb als Pflichtfelder im Schema und nicht als zwei Einträge in einer Liste — fehlt eines, ist das ein Typfehler im Editor und nicht erst ein Build-Abbruch.
Externe Ziele erkennt die Navigation an der https-URL und ergänzt für Screenreader den Hinweis „(externe Website)". Ein target="_blank" setzt sie bewusst nicht: Ein erzwungener Tabwechsel nimmt der bedienenden Person eine Entscheidung ab, die ihr zusteht.
features
Alle Werte sind boolesch.
| Flag | Vorgabe | Wirkung |
|---|---|---|
sitemap | true | erzeugt sitemap.xml und den Verweis in robots.txt |
structuredData | true | Hauptschalter der JSON-LD-Ausgabe |
cookieConsent | true | Consent-Schicht (M5) |
vue | false | Vue als Astro Island; verlangt installiertes @astrojs/vue |
webMcp | false | experimentell; verlangt zusätzlich das Objekt webMcp |
seo
| Feld | Pflicht | Regel |
|---|---|---|
defaultOgImage | nein | Schlüssel im Asset-Manifest, kein freier Pfad |
logo | nein | Schlüssel im Asset-Manifest; JSON-LD-Logo |
twitterSite | nein | muss mit @ beginnen |
schemas.organization | ja | boolesch |
schemas.localBusiness | ja | boolesch; verlangt company.address |
schemas.website | ja | boolesch |
defaultOgImage und logo verweisen absichtlich auf Manifest-Schlüssel statt auf Pfade. Im Referenzprojekt zeigten OG-Bild-Angaben auf Dateien, die nie existierten; ein unbekannter Schlüssel bricht dagegen den Build ab.
schemas.localBusiness ersetzt den Typ des Organisationsknotens, es entsteht kein zweiter Knoten. Details unter Structured Data.
tracking
| Feld | Vorgabe | Regel |
|---|---|---|
enabled | false | verlangt features.cookieConsent: true |
provider | 'gtm' | derzeit nur GTM |
containerId | — | Format GTM-XXXXXXX; Pflicht, wenn enabled |
gtmServerUrl | — | optionaler First-Party-Endpunkt für serverseitiges GTM |
consentMode | 'basic' | basic lädt GTM erst nach der Entscheidung |
ga4 | false | verlangt Consent-Kategorie analytics |
googleAds | false | verlangt Consent-Kategorie marketing |
ga4 und googleAds bauen keinen Code ein
Beide Flags dokumentieren, was im GTM-Container konfiguriert sein soll, und steuern Consent-Kategorien sowie Tests. Ein direkter Einbau von GA4 oder Google Ads neben GTM findet nicht statt und ist ausdrücklich unerwünscht.
consent
| Feld | Regel |
|---|---|
categories | mindestens ein Eintrag, muss necessary enthalten |
revision | ganze Zahl ab 1; Erhöhen fragt bestehende Zustimmungen erneut ab |
forms
| Feld | Vorgabe | Regel |
|---|---|---|
provider | 'none' | none, standalone-php oder joomla |
endpoint | — | Pflicht, sobald ein Provider gewählt ist |
captcha | 'none' | none oder turnstile |
Der Endpunkt muss zum Provider passen: standalone-php verlangt einen same-origin Pfad beginnend mit /, joomla eine absolute https-URL des Backends.
deployment
| Feld | Regel |
|---|---|
target | mittwald-static oder github-pages |
apache.canonicalHost | optional; nur für Apache-Ziele relevant |
apache.redirects | Liste aus from (absoluter Pfad), to, status (301 oder 302) |
webMcp und meta
webMcp ist optional und erzwingt mit acknowledgeExperimental: true eine bewusste Aktivierung. meta.starterVersion wird ab M9 von starter:init gesetzt und dient als Ankerpunkt für spätere Starter-Upgrades.