[{"data":1,"prerenderedAt":1572},["Reactive",2],{"posts-de-cms":3},[4,926],{"_path":5,"_dir":6,"_draft":7,"_partial":7,"_locale":8,"title":9,"description":10,"locale":11,"draft":7,"date":12,"image":13,"tags":16,"imageLogo":19,"imageLogo2":24,"seoImage":28,"body":30,"_type":921,"_id":922,"_source":923,"_file":924,"_extension":925},"/blog/payload","blog",false,"","Payload CMS – Erfahrungen aus Hostcraft","Code-First-CMS auf Next.js-Basis: moderne Oberfläche, Anpassungsfähigkeit und KI-Kompatibilität – aber auch Serveranforderungen, Deploy und die Abhängigkeit von Next.js","de","2026-09-25T00:00:00.000Z",{"src":14,"alt":15},"/background/background-7.svg","background",[17,18],"tools","cms",{"src":20,"alt":21,"width":22,"left":23},"/logo/payload.svg","payload-logo","45%","10%",{"src":25,"alt":26,"width":27,"right":23},"/logo/payload-icon.svg","payload-icon","20%",{"src":29},"/payload.jpg",{"type":31,"children":32,"toc":905},"root",[33,70,77,82,87,96,102,109,123,128,134,139,202,207,476,497,502,508,513,534,548,554,559,565,571,576,620,633,639,644,756,761,767,788,821,826,832,855,860,878,883,889,894,899],{"type":34,"tag":35,"props":36,"children":37},"element","p",{},[38,41,51,53,60,62,68],{"type":39,"value":40},"text","Ich habe ",{"type":34,"tag":42,"props":43,"children":48},"a",{"href":44,":target":45,"rel":46},"https://payloadcms.com/","\\_blank",[47],"nofollow",[49],{"type":39,"value":50},"Payload",{"type":39,"value":52}," für ",{"type":34,"tag":42,"props":54,"children":57},{"href":55,":target":45,"rel":56},"https://hostcraft.rentals",[47],[58],{"type":39,"value":59},"Hostcraft",{"type":39,"value":61}," verwendet, eine SaaS-App, mit der Gastgeber von Ferienunterkünften eine eigene Buchungsseite bekommen (mehr dazu in der ",{"type":34,"tag":42,"props":63,"children":65},{"href":64},"/hostcraft",[66],{"type":39,"value":67},"Fallstudie",{"type":39,"value":69},"). Payload 3 läuft dort zusammen mit Next.js 16 und Postgres. Zeit für ein ehrliches Fazit.",{"type":34,"tag":71,"props":72,"children":74},"h2",{"id":73},"was-ist-payload",[75],{"type":39,"value":76},"Was ist Payload?",{"type":34,"tag":35,"props":78,"children":79},{},[80],{"type":39,"value":81},"Payload ist ein Open-Source-CMS (MIT-Lizenz), das komplett in TypeScript konfiguriert wird. Collections, Felder, Zugriffsrechte und Hooks werden nicht im Backend zusammengeklickt, sondern als Code im Projekt definiert. Aus dieser Konfiguration erzeugt Payload automatisch das Admin-Panel, eine REST- und GraphQL-API und eine typisierte Local API für den direkten Zugriff vom Server aus.",{"type":34,"tag":35,"props":83,"children":84},{},[85],{"type":39,"value":86},"Seit Version 3 ist Payload kein eigener Server mehr, sondern wird direkt in eine Next.js-App installiert. Admin-Panel, API und Frontend laufen im selben Projekt und im selben Prozess. Als Datenbank stehen Postgres, MongoDB und SQLite zur Verfügung, bei Hostcraft ist es Postgres.",{"type":34,"tag":35,"props":88,"children":89},{},[90],{"type":34,"tag":91,"props":92,"children":95},"img",{"alt":93,"src":94},"Das Payload Admin-Panel in Hostcraft","/images/blog/payload.webp",[],{"type":34,"tag":71,"props":97,"children":99},{"id":98},"vorteile",[100],{"type":39,"value":101},"Vorteile",{"type":34,"tag":103,"props":104,"children":106},"h3",{"id":105},"moderne-oberfläche",[107],{"type":39,"value":108},"Moderne Oberfläche",{"type":34,"tag":35,"props":110,"children":111},{},[112,114,121],{"type":39,"value":113},"Das Admin-Panel ist schnell, aufgeräumt und bringt Dark Mode, Tabs, Relationship-Felder, Medien-Bibliothek, Versionen und Mehrsprachigkeit mit. Bei Hostcraft sind viele Texte pro Sprache (Deutsch, Englisch, Kroatisch) pflegbar, dafür reicht ein ",{"type":34,"tag":115,"props":116,"children":118},"code",{"className":117},[],[119],{"type":39,"value":120},"localized: true",{"type":39,"value":122}," am Feld, und im Backend erscheint automatisch der Sprachumschalter.",{"type":34,"tag":35,"props":124,"children":125},{},[126],{"type":39,"value":127},"Die Oberfläche stammt aus der Konfiguration, es gibt also keinen separaten Admin-Code, der gepflegt werden muss. Neue Felder erscheinen sofort im Backend.",{"type":34,"tag":103,"props":129,"children":131},{"id":130},"anpassungsfähigkeit",[132],{"type":39,"value":133},"Anpassungsfähigkeit",{"type":34,"tag":35,"props":135,"children":136},{},[137],{"type":39,"value":138},"Payload gibt kaum Struktur vor. Man baut die Inhaltsmodelle selbst, und alles lässt sich erweitern:",{"type":34,"tag":140,"props":141,"children":142},"ul",{},[143,162,172,182,192],{"type":34,"tag":144,"props":145,"children":146},"li",{},[147,153,155,160],{"type":34,"tag":148,"props":149,"children":150},"strong",{},[151],{"type":39,"value":152},"Collections",{"type":39,"value":154}," und ",{"type":34,"tag":148,"props":156,"children":157},{},[158],{"type":39,"value":159},"Felder",{"type":39,"value":161}," (Gruppen, Tabs, Relationen, Selects, Uploads …)",{"type":34,"tag":144,"props":163,"children":164},{},[165,170],{"type":34,"tag":148,"props":166,"children":167},{},[168],{"type":39,"value":169},"Access Control",{"type":39,"value":171}," auf Collection- und Feld-Ebene, auch mit Filtern pro Benutzer",{"type":34,"tag":144,"props":173,"children":174},{},[175,180],{"type":34,"tag":148,"props":176,"children":177},{},[178],{"type":39,"value":179},"Hooks",{"type":39,"value":181},", die vor und nach dem Speichern laufen",{"type":34,"tag":144,"props":183,"children":184},{},[185,190],{"type":34,"tag":148,"props":186,"children":187},{},[188],{"type":39,"value":189},"Eigene React-Komponenten",{"type":39,"value":191}," im Admin-Panel, zum Beispiel Dashboards oder komplett eigene Views",{"type":34,"tag":144,"props":193,"children":194},{},[195,200],{"type":34,"tag":148,"props":196,"children":197},{},[198],{"type":39,"value":199},"Auth",{"type":39,"value":201}," mit Rollen, Sperre nach Fehlversuchen und Passwort-Reset, bereits eingebaut",{"type":34,"tag":35,"props":203,"children":204},{},[205],{"type":39,"value":206},"Bei Hostcraft hat jeder Gastgeber nur Zugriff auf seine eigenen Unterkünfte, Webseiten und Buchungen. Das ist keine eigene Berechtigungslogik, sondern ein paar Zeilen Access Control:",{"type":34,"tag":208,"props":209,"children":213},"pre",{"className":210,"code":211,"language":212,"meta":8,"style":8},"language-ts shiki shiki-themes dracula","export const ownSiteOrOperator: Access = ({ req: { user } }) => {\n  if (!user) return false\n  if (isOperator(user)) return true\n\n  const hostId = getUserHostId(user)\n  if (!hostId) return false\n\n  // Hosts only see sites that belong to them\n  return { host: { equals: hostId } }\n}\n","ts",[214],{"type":34,"tag":115,"props":215,"children":216},{"__ignoreMap":8},[217,283,318,349,359,388,417,425,435,467],{"type":34,"tag":218,"props":219,"children":222},"span",{"class":220,"line":221},"line",1,[223,229,234,240,245,251,256,262,268,273,278],{"type":34,"tag":218,"props":224,"children":226},{"style":225},"--shiki-default:#FF79C6",[227],{"type":39,"value":228},"export",{"type":34,"tag":218,"props":230,"children":231},{"style":225},[232],{"type":39,"value":233}," const",{"type":34,"tag":218,"props":235,"children":237},{"style":236},"--shiki-default:#50FA7B",[238],{"type":39,"value":239}," ownSiteOrOperator",{"type":34,"tag":218,"props":241,"children":242},{"style":225},[243],{"type":39,"value":244},":",{"type":34,"tag":218,"props":246,"children":248},{"style":247},"--shiki-default:#8BE9FD;--shiki-default-font-style:italic",[249],{"type":39,"value":250}," Access",{"type":34,"tag":218,"props":252,"children":253},{"style":225},[254],{"type":39,"value":255}," =",{"type":34,"tag":218,"props":257,"children":259},{"style":258},"--shiki-default:#F8F8F2",[260],{"type":39,"value":261}," ({ req: { ",{"type":34,"tag":218,"props":263,"children":265},{"style":264},"--shiki-default:#FFB86C;--shiki-default-font-style:italic",[266],{"type":39,"value":267},"user",{"type":34,"tag":218,"props":269,"children":270},{"style":258},[271],{"type":39,"value":272}," } }) ",{"type":34,"tag":218,"props":274,"children":275},{"style":225},[276],{"type":39,"value":277},"=>",{"type":34,"tag":218,"props":279,"children":280},{"style":258},[281],{"type":39,"value":282}," {\n",{"type":34,"tag":218,"props":284,"children":286},{"class":220,"line":285},2,[287,292,297,302,307,312],{"type":34,"tag":218,"props":288,"children":289},{"style":225},[290],{"type":39,"value":291},"  if",{"type":34,"tag":218,"props":293,"children":294},{"style":258},[295],{"type":39,"value":296}," (",{"type":34,"tag":218,"props":298,"children":299},{"style":225},[300],{"type":39,"value":301},"!",{"type":34,"tag":218,"props":303,"children":304},{"style":258},[305],{"type":39,"value":306},"user) ",{"type":34,"tag":218,"props":308,"children":309},{"style":225},[310],{"type":39,"value":311},"return",{"type":34,"tag":218,"props":313,"children":315},{"style":314},"--shiki-default:#BD93F9",[316],{"type":39,"value":317}," false\n",{"type":34,"tag":218,"props":319,"children":321},{"class":220,"line":320},3,[322,326,330,335,340,344],{"type":34,"tag":218,"props":323,"children":324},{"style":225},[325],{"type":39,"value":291},{"type":34,"tag":218,"props":327,"children":328},{"style":258},[329],{"type":39,"value":296},{"type":34,"tag":218,"props":331,"children":332},{"style":236},[333],{"type":39,"value":334},"isOperator",{"type":34,"tag":218,"props":336,"children":337},{"style":258},[338],{"type":39,"value":339},"(user)) ",{"type":34,"tag":218,"props":341,"children":342},{"style":225},[343],{"type":39,"value":311},{"type":34,"tag":218,"props":345,"children":346},{"style":314},[347],{"type":39,"value":348}," true\n",{"type":34,"tag":218,"props":350,"children":352},{"class":220,"line":351},4,[353],{"type":34,"tag":218,"props":354,"children":356},{"emptyLinePlaceholder":355},true,[357],{"type":39,"value":358},"\n",{"type":34,"tag":218,"props":360,"children":362},{"class":220,"line":361},5,[363,368,373,378,383],{"type":34,"tag":218,"props":364,"children":365},{"style":225},[366],{"type":39,"value":367},"  const",{"type":34,"tag":218,"props":369,"children":370},{"style":258},[371],{"type":39,"value":372}," hostId ",{"type":34,"tag":218,"props":374,"children":375},{"style":225},[376],{"type":39,"value":377},"=",{"type":34,"tag":218,"props":379,"children":380},{"style":236},[381],{"type":39,"value":382}," getUserHostId",{"type":34,"tag":218,"props":384,"children":385},{"style":258},[386],{"type":39,"value":387},"(user)\n",{"type":34,"tag":218,"props":389,"children":391},{"class":220,"line":390},6,[392,396,400,404,409,413],{"type":34,"tag":218,"props":393,"children":394},{"style":225},[395],{"type":39,"value":291},{"type":34,"tag":218,"props":397,"children":398},{"style":258},[399],{"type":39,"value":296},{"type":34,"tag":218,"props":401,"children":402},{"style":225},[403],{"type":39,"value":301},{"type":34,"tag":218,"props":405,"children":406},{"style":258},[407],{"type":39,"value":408},"hostId) ",{"type":34,"tag":218,"props":410,"children":411},{"style":225},[412],{"type":39,"value":311},{"type":34,"tag":218,"props":414,"children":415},{"style":314},[416],{"type":39,"value":317},{"type":34,"tag":218,"props":418,"children":420},{"class":220,"line":419},7,[421],{"type":34,"tag":218,"props":422,"children":423},{"emptyLinePlaceholder":355},[424],{"type":39,"value":358},{"type":34,"tag":218,"props":426,"children":428},{"class":220,"line":427},8,[429],{"type":34,"tag":218,"props":430,"children":432},{"style":431},"--shiki-default:#6272A4",[433],{"type":39,"value":434},"  // Hosts only see sites that belong to them\n",{"type":34,"tag":218,"props":436,"children":438},{"class":220,"line":437},9,[439,444,449,453,458,462],{"type":34,"tag":218,"props":440,"children":441},{"style":225},[442],{"type":39,"value":443},"  return",{"type":34,"tag":218,"props":445,"children":446},{"style":258},[447],{"type":39,"value":448}," { host",{"type":34,"tag":218,"props":450,"children":451},{"style":225},[452],{"type":39,"value":244},{"type":34,"tag":218,"props":454,"children":455},{"style":258},[456],{"type":39,"value":457}," { equals",{"type":34,"tag":218,"props":459,"children":460},{"style":225},[461],{"type":39,"value":244},{"type":34,"tag":218,"props":463,"children":464},{"style":258},[465],{"type":39,"value":466}," hostId } }\n",{"type":34,"tag":218,"props":468,"children":470},{"class":220,"line":469},10,[471],{"type":34,"tag":218,"props":472,"children":473},{"style":258},[474],{"type":39,"value":475},"}\n",{"type":34,"tag":35,"props":477,"children":478},{},[479,481,487,489,495],{"type":39,"value":480},"Die Funktion gibt entweder ",{"type":34,"tag":115,"props":482,"children":484},{"className":483},[],[485],{"type":39,"value":486},"true",{"type":39,"value":488},"/",{"type":34,"tag":115,"props":490,"children":492},{"className":491},[],[493],{"type":39,"value":494},"false",{"type":39,"value":496}," oder einen Filter zurück, den Payload direkt in die Datenbankabfrage übernimmt. Für ein Multi-Tenant-System wie Hostcraft ist das sehr praktisch.",{"type":34,"tag":35,"props":498,"children":499},{},[500],{"type":39,"value":501},"Weil man die Local API auch außerhalb des Admin-Panels nutzen kann, sind Payload und die eigene App nicht getrennt. Das öffentliche Frontend, das Gastgeber-Dashboard und die Buchungslogik lesen und schreiben direkt in dieselben Collections. Das Admin-Panel selbst nutze ich nur als Betreiber. Die Gastgeber bekommen ein eigenes, einfacheres Dashboard, das ich selbst gebaut habe.",{"type":34,"tag":103,"props":503,"children":505},{"id":504},"ki-kompatibilität",[506],{"type":39,"value":507},"KI-Kompatibilität",{"type":34,"tag":35,"props":509,"children":510},{},[511],{"type":39,"value":512},"Auch hier hat mich der Code-First-Ansatz überzeugt. Das ganze Datenmodell steht in TypeScript-Dateien im Repository. Ein KI-Assistent im Editor sieht Collections, Felder, Access Control und Hooks, ohne dass er ein Backend bedienen oder eine Datenbank untersuchen muss. Neue Felder, Collections oder Berechtigungen lassen sich per Prompt ergänzen, und alles ist als Git-Diff nachvollziehbar.",{"type":34,"tag":35,"props":514,"children":515},{},[516,518,524,526,532],{"type":39,"value":517},"Dazu kommt ",{"type":34,"tag":115,"props":519,"children":521},{"className":520},[],[522],{"type":39,"value":523},"payload generate:types",{"type":39,"value":525},": Aus der Konfiguration entsteht eine ",{"type":34,"tag":115,"props":527,"children":529},{"className":528},[],[530],{"type":39,"value":531},"payload-types.ts",{"type":39,"value":533}," mit allen Typen. Der Assistent bekommt damit präzises Feedback vom TypeScript-Compiler, wenn er ein Feld falsch benutzt. Das ist ein großer Unterschied zu CMS-Systemen, bei denen das Schema irgendwo in der Datenbank steckt.",{"type":34,"tag":35,"props":535,"children":536},{},[537,539,546],{"type":39,"value":538},"Außerdem gibt es ein offizielles ",{"type":34,"tag":42,"props":540,"children":543},{"href":541,":target":45,"rel":542},"https://payloadcms.com/docs/plugins/mcp",[47],[544],{"type":39,"value":545},"MCP-Plugin",{"type":39,"value":547},", über das KI-Clients Inhalte lesen und anlegen können, natürlich unter Beachtung der Access Control. Das habe ich bisher nicht ausprobiert, es ist aber ein gutes Zeichen, dass Payload den Weg ernsthaft weitergeht.",{"type":34,"tag":103,"props":549,"children":551},{"id":550},"kostenlos-ohne-lizenzmodell",[552],{"type":39,"value":553},"Kostenlos, ohne Lizenzmodell",{"type":34,"tag":35,"props":555,"children":556},{},[557],{"type":39,"value":558},"Payload ist MIT-lizenziert. Es gibt keine Pro-Version, keine Preise pro Site und keine Einschränkung auf einen Benutzer. Für ein SaaS-Produkt, bei dem viele Gastgeber auf derselben Installation arbeiten, ist das ein echtes Argument.",{"type":34,"tag":71,"props":560,"children":562},{"id":561},"nachteile",[563],{"type":39,"value":564},"Nachteile",{"type":34,"tag":103,"props":566,"children":568},{"id":567},"serveranforderungen",[569],{"type":39,"value":570},"Serveranforderungen",{"type":34,"tag":35,"props":572,"children":573},{},[574],{"type":39,"value":575},"Payload ist keine statische Seite und kein klassisches PHP-CMS. Es braucht einen dauerhaft laufenden Node.js-Prozess und eine Datenbank. Billiges Shared Hosting ist damit raus, ein VPS (bei Hostcraft ein Server bei Hetzner) ist das Minimum.",{"type":34,"tag":140,"props":577,"children":578},{},[579,584,589,594,607],{"type":34,"tag":144,"props":580,"children":581},{},[582],{"type":39,"value":583},"Node.js 22, bei mir mit pm2 als Prozess-Manager",{"type":34,"tag":144,"props":585,"children":586},{},[587],{"type":39,"value":588},"Postgres (oder MongoDB bzw. SQLite)",{"type":34,"tag":144,"props":590,"children":591},{},[592],{"type":39,"value":593},"Ein Reverse Proxy, der SSL übernimmt",{"type":34,"tag":144,"props":595,"children":596},{},[597,599,605],{"type":39,"value":598},"Genug Arbeitsspeicher für ",{"type":34,"tag":115,"props":600,"children":602},{"className":601},[],[603],{"type":39,"value":604},"next build",{"type":39,"value":606},", denn bei mir wird auf dem Server gebaut und das Admin-Panel kommt zum Build noch dazu",{"type":34,"tag":144,"props":608,"children":609},{},[610,612,618],{"type":39,"value":611},"Persistenter Speicher für hochgeladene Dateien (bei mir ein ",{"type":34,"tag":115,"props":613,"children":615},{"className":614},[],[616],{"type":39,"value":617},"media/",{"type":39,"value":619},"-Ordner), solange man keinen S3-Speicher anbindet",{"type":34,"tag":35,"props":621,"children":622},{},[623,625,631],{"type":39,"value":624},"Auch lokal ist der Aufwand höher als bei einer Markdown-basierten Seite. Ich starte Postgres per Container, und allein die ",{"type":34,"tag":115,"props":626,"children":628},{"className":627},[],[629],{"type":39,"value":630},"node_modules",{"type":39,"value":632}," sind rund 2 GB groß. Für eine kleine Visitenkarten-Seite ist Payload deshalb überdimensioniert.",{"type":34,"tag":103,"props":634,"children":636},{"id":635},"deploy-ein-bedingter-nachteil",[637],{"type":39,"value":638},"Deploy – ein bedingter Nachteil",{"type":34,"tag":35,"props":640,"children":641},{},[642],{"type":39,"value":643},"Im Alltag läuft das Deployment bei mir per GitHub Actions: Code holen, Abhängigkeiten installieren, Datenbank sichern, Migrationen ausführen, bauen, Prozess neu laden. Das ist kein Payload-spezifisches Problem, sondern normaler Alltag bei einer Node-App mit Datenbank. Trotzdem gab es Punkte, die man kennen sollte:",{"type":34,"tag":140,"props":645,"children":646},{},[647,672,705,730],{"type":34,"tag":144,"props":648,"children":649},{},[650,655,657,663,664,670],{"type":34,"tag":148,"props":651,"children":652},{},[653],{"type":39,"value":654},"Schema-Push vs. Migrationen:",{"type":39,"value":656}," Im Entwicklungsmodus gleicht Payload die Datenbank automatisch an die Konfiguration an. Produktion braucht dagegen echte Migrationen (",{"type":34,"tag":115,"props":658,"children":660},{"className":659},[],[661],{"type":39,"value":662},"payload migrate:create",{"type":39,"value":154},{"type":34,"tag":115,"props":665,"children":667},{"className":666},[],[668],{"type":39,"value":669},"payload migrate",{"type":39,"value":671},"). Wer das vergisst, merkt es erst beim Deploy.",{"type":34,"tag":144,"props":673,"children":674},{},[675,680,682,688,690,696,698,703],{"type":34,"tag":148,"props":676,"children":677},{},[678],{"type":39,"value":679},"Der Marker aus dem Dev-Push:",{"type":39,"value":681}," Der lokale Push hinterlässt einen Eintrag in ",{"type":34,"tag":115,"props":683,"children":685},{"className":684},[],[686],{"type":39,"value":687},"payload_migrations",{"type":39,"value":689}," (mit ",{"type":34,"tag":115,"props":691,"children":693},{"className":692},[],[694],{"type":39,"value":695},"batch = -1",{"type":39,"value":697},"). Danach fragt ",{"type":34,"tag":115,"props":699,"children":701},{"className":700},[],[702],{"type":39,"value":669},{"type":39,"value":704}," interaktiv nach einer Bestätigung und hängt im SSH-Deploy, bis der Timeout greift. Bei mir entfernt das Deploy-Skript diesen Eintrag vor der Migration.",{"type":34,"tag":144,"props":706,"children":707},{},[708,713,715,720,722,728],{"type":34,"tag":148,"props":709,"children":710},{},[711],{"type":39,"value":712},"Inhalte gehören zur Datenbank:",{"type":39,"value":714}," Anders als bei einem Flat-File-CMS lassen sich Inhalte nicht per Git verschieben. Für den Start habe ich ein Skript, das Datenbank und ",{"type":34,"tag":115,"props":716,"children":718},{"className":717},[],[719],{"type":39,"value":617},{"type":39,"value":721},"-Ordner lokal sichert und auf den Server überträgt. Dafür müssen Git-Revision und ",{"type":34,"tag":115,"props":723,"children":725},{"className":724},[],[726],{"type":39,"value":727},"PAYLOAD_SECRET",{"type":39,"value":729}," zusammenpassen.",{"type":34,"tag":144,"props":731,"children":732},{},[733,738,740,746,748,754],{"type":34,"tag":148,"props":734,"children":735},{},[736],{"type":39,"value":737},"Content Security Policy:",{"type":39,"value":739}," Das Admin-Panel braucht in Produktion ",{"type":34,"tag":115,"props":741,"children":743},{"className":742},[],[744],{"type":39,"value":745},"unsafe-eval",{"type":39,"value":747},". Die strenge CSP für die öffentliche Seite muss man für ",{"type":34,"tag":115,"props":749,"children":751},{"className":750},[],[752],{"type":39,"value":753},"/admin",{"type":39,"value":755}," deshalb getrennt konfigurieren.",{"type":34,"tag":35,"props":757,"children":758},{},[759],{"type":39,"value":760},"Hat man das einmal sauber aufgesetzt, läuft es zuverlässig. Neue Projekte sollten Migrationen aber von Anfang an einplanen und nicht erst vor dem ersten Release.",{"type":34,"tag":103,"props":762,"children":764},{"id":763},"abhängigkeit-von-nextjs",[765],{"type":39,"value":766},"Abhängigkeit von Next.js",{"type":34,"tag":35,"props":768,"children":769},{},[770,772,778,780,786],{"type":39,"value":771},"Payload 3 ist eng mit Next.js verzahnt. Das Admin-Panel ist eine Next-App, die Konfiguration wird über ",{"type":34,"tag":115,"props":773,"children":775},{"className":774},[],[776],{"type":39,"value":777},"withPayload",{"type":39,"value":779}," in ",{"type":34,"tag":115,"props":781,"children":783},{"className":782},[],[784],{"type":39,"value":785},"next.config.ts",{"type":39,"value":787}," eingebunden, und die Versionen von Payload und Next müssen zusammenpassen. Dadurch gilt:",{"type":34,"tag":140,"props":789,"children":790},{},[791,801,811],{"type":34,"tag":144,"props":792,"children":793},{},[794,799],{"type":34,"tag":148,"props":795,"children":796},{},[797],{"type":39,"value":798},"Next-Updates und Payload-Updates müssen zusammenpassen.",{"type":39,"value":800}," Next bringt regelmäßig Breaking Changes mit, und Payload veröffentlicht sehr häufig neue Versionen. Updates sollte man deshalb bewusst einplanen.",{"type":34,"tag":144,"props":802,"children":803},{},[804,809],{"type":34,"tag":148,"props":805,"children":806},{},[807],{"type":39,"value":808},"React ist Pflicht.",{"type":39,"value":810}," Wer sonst Vue und Nuxt nutzt, so wie ich bei den meisten Projekten, kann Payload zwar headless verwenden, betreibt dann aber trotzdem eine Next-App nur für das Backend.",{"type":34,"tag":144,"props":812,"children":813},{},[814,819],{"type":34,"tag":148,"props":815,"children":816},{},[817],{"type":39,"value":818},"Der Lock-in ist spürbar.",{"type":39,"value":820}," Die Local API und die Admin-Komponenten sind eng mit der Next-App verzahnt. Ein späterer Wechsel des Frontends ist möglich, aber nicht trivial.",{"type":34,"tag":35,"props":822,"children":823},{},[824],{"type":39,"value":825},"Wer ohnehin mit Next.js arbeitet, hat davon dagegen fast nur Vorteile: ein Repository, ein Deployment, geteilte Typen.",{"type":34,"tag":103,"props":827,"children":829},{"id":828},"unsicherheit-durch-die-übernahme-von-figma",[830],{"type":39,"value":831},"Unsicherheit durch die Übernahme von Figma",{"type":34,"tag":35,"props":833,"children":834},{},[835,837,844,846,853],{"type":39,"value":836},"Im Juni 2025 hat Figma das Payload-Team übernommen (",{"type":34,"tag":42,"props":838,"children":841},{"href":839,":target":45,"rel":840},"https://www.figma.com/blog/payload-joins-figma/",[47],[842],{"type":39,"value":843},"Ankündigung von Figma",{"type":39,"value":845},", ",{"type":34,"tag":42,"props":847,"children":850},{"href":848,":target":45,"rel":849},"https://payloadcms.com/posts/blog/payload-is-joining-figma",[47],[851],{"type":39,"value":852},"Ankündigung von Payload",{"type":39,"value":854},"). Beide Seiten versprechen, dass Payload Open Source und selbst hostbar bleibt, dass das Team weiter an Payload arbeitet und dass sich für bestehende Nutzer zunächst nichts ändert.",{"type":34,"tag":35,"props":856,"children":857},{},[858],{"type":39,"value":859},"Das ist beruhigend, aber „zunächst“ ist das entscheidende Wort. Figma entwickelt ein eigenes CMS, und Payload soll dafür die Grundlage liefern. Die Roadmap von Payload hängt damit künftig auch von den Interessen eines großen Unternehmens ab, und das lässt sich von außen nicht einschätzen:",{"type":34,"tag":140,"props":861,"children":862},{},[863,868,873],{"type":34,"tag":144,"props":864,"children":865},{},[866],{"type":39,"value":867},"Entwickelt Figma den Open-Source-Kern weiter oder wandert der Fokus in kommerzielle Produkte?",{"type":34,"tag":144,"props":869,"children":870},{},[871],{"type":39,"value":872},"Bleibt die MIT-Lizenz auf Dauer bestehen?",{"type":34,"tag":144,"props":874,"children":875},{},[876],{"type":39,"value":877},"Wie lange werden Funktionen, die ich heute nutze, im Kern weiterentwickelt?",{"type":34,"tag":35,"props":879,"children":880},{},[881],{"type":39,"value":882},"Bisher gibt es keinen Grund zur Panik, denn der Kern ist weiterhin MIT-lizenziert und wird aktiv gepflegt. Trotzdem sollte man diese Unsicherheit bei der Wahl für ein langlebiges Projekt mit einkalkulieren. Das Risiko ist überschaubar, weil Daten in Postgres und die Konfiguration in TypeScript liegen und sich im Zweifel auch ohne Payload weiterverwenden lassen. Aufwand wäre ein Wechsel trotzdem.",{"type":34,"tag":71,"props":884,"children":886},{"id":885},"fazit",[887],{"type":39,"value":888},"Fazit",{"type":34,"tag":35,"props":890,"children":891},{},[892],{"type":39,"value":893},"Payload ist für mich das CMS, das am besten zu Next.js-Projekten passt und das ich für Web-Apps mit echter Logik, Benutzerrollen und mehreren Mandanten wieder einsetzen würde. Das Admin-Panel ist modern, das Datenmodell lässt sich beliebig anpassen, und weil alles in TypeScript liegt, arbeitet man hervorragend mit KI-Assistenten.",{"type":34,"tag":35,"props":895,"children":896},{},[897],{"type":39,"value":898},"Die Nachteile sind überschaubar, aber real: ein eigener Server mit Node.js und Datenbank, ein Deployment mit sauberen Migrationen, die enge Bindung an Next.js und die offene Frage, wohin sich Payload unter Figma entwickelt. Für einfache Seiten, bei denen die Redaktion nur ein paar Texte ändert, gibt es leichtere Lösungen. Für ein Produkt wie Hostcraft war Payload die richtige Wahl.",{"type":34,"tag":900,"props":901,"children":902},"style",{},[903],{"type":39,"value":904},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":8,"searchDepth":285,"depth":285,"links":906},[907,908,914,920],{"id":73,"depth":285,"text":76},{"id":98,"depth":285,"text":101,"children":909},[910,911,912,913],{"id":105,"depth":320,"text":108},{"id":130,"depth":320,"text":133},{"id":504,"depth":320,"text":507},{"id":550,"depth":320,"text":553},{"id":561,"depth":285,"text":564,"children":915},[916,917,918,919],{"id":567,"depth":320,"text":570},{"id":635,"depth":320,"text":638},{"id":763,"depth":320,"text":766},{"id":828,"depth":320,"text":831},{"id":885,"depth":285,"text":888},"markdown","content:blog:payload.md","content","blog/payload.md","md",{"_path":927,"_dir":6,"_draft":7,"_partial":7,"_locale":8,"title":928,"description":929,"locale":11,"draft":7,"date":930,"image":931,"tags":933,"imageLogo":934,"imageLogo2":938,"seoImage":942,"body":944,"_type":921,"_id":1570,"_source":923,"_file":1571,"_extension":925},"/blog/statamic","Statamic CMS – Erfahrungen aus zwei Projekten","Flat-File-CMS auf Laravel-Basis: Git-Integration, moderne Oberfläche und KI-Kompatibilität – aber auch Preis, Cache und Serveranforderungen","2026-10-09T00:00:00.000Z",{"src":932,"alt":15},"/background/background-5.svg",[17,18],{"src":935,"alt":936,"width":937,"left":23},"/logo/statamic.svg","statamic-logo","30%",{"src":939,"alt":940,"width":941,"right":23},"/logo/git.svg","git-logo","15%",{"src":943},"/images/blog/statamic.webp",{"type":31,"children":945,"toc":1553},[946,959,965,970,975,982,986,992,1005,1010,1014,1027,1032,1036,1041,1099,1104,1110,1115,1227,1247,1251,1263,1267,1273,1292,1297,1303,1315,1342,1346,1351,1397,1426,1430,1443,1530,1535,1539,1544,1549],{"type":34,"tag":35,"props":947,"children":948},{},[949,950,957],{"type":39,"value":40},{"type":34,"tag":42,"props":951,"children":954},{":target":45,"href":952,"rel":953},"https://statamic.com/",[47],[955],{"type":39,"value":956},"Statamic",{"type":39,"value":958}," inzwischen in zwei Kundenprojekten eingesetzt: einer Konferenz-Website mit Programm, Referenten und Ausstellern sowie der Seite eines Netzwerks mit Veranstaltungen, Orten und Artikeln. Beide laufen mit Statamic 6 auf Laravel 13. Zeit für ein ehrliches Zwischenfazit.",{"type":34,"tag":71,"props":960,"children":962},{"id":961},"was-ist-statamic",[963],{"type":39,"value":964},"Was ist Statamic?",{"type":34,"tag":35,"props":966,"children":967},{},[968],{"type":39,"value":969},"Statamic ist ein Content-Management-System auf Basis von Laravel. Der Kern ist ein sogenanntes Flat-File-CMS: Inhalte landen nicht in einer Datenbank, sondern als Markdown- und YAML-Dateien direkt im Projektverzeichnis. Dazu kommt ein Control Panel (das Backend), in dem Redakteure Inhalte pflegen, ohne mit Dateien in Berührung zu kommen.",{"type":34,"tag":35,"props":971,"children":972},{},[973],{"type":39,"value":974},"Das Frontend wird mit der Template-Sprache Antlers oder mit Blade gebaut. Statamic kann aber auch headless betrieben werden.",{"type":34,"tag":35,"props":976,"children":977},{},[978],{"type":34,"tag":91,"props":979,"children":981},{"alt":980,"src":943},"Das Statamic Control Panel",[],{"type":34,"tag":71,"props":983,"children":984},{"id":98},[985],{"type":39,"value":101},{"type":34,"tag":103,"props":987,"children":989},{"id":988},"git-integration",[990],{"type":39,"value":991},"Git-Integration",{"type":34,"tag":35,"props":993,"children":994},{},[995,997,1003],{"type":39,"value":996},"Da alle Inhalte Dateien sind, lässt sich das gesamte Projekt in Git versionieren – Code, Templates, Feld-Definitionen ",{"type":34,"tag":998,"props":999,"children":1000},"em",{},[1001],{"type":39,"value":1002},"und",{"type":39,"value":1004}," Inhalte. Das ist ein echter Unterschied zu WordPress & Co., wo der Inhalt in der Datenbank liegt und zwischen lokaler Umgebung und Server mühsam synchronisiert werden muss.",{"type":34,"tag":35,"props":1006,"children":1007},{},[1008],{"type":39,"value":1009},"In der Pro-Version kann Statamic Änderungen aus dem Backend sogar automatisch committen und pushen. Eine Redakteurin speichert einen Eintrag, und kurz darauf steht der Commit im Repository. Jede Änderung ist nachvollziehbar und lässt sich bei Bedarf zurückdrehen.",{"type":34,"tag":103,"props":1011,"children":1012},{"id":105},[1013],{"type":39,"value":108},{"type":34,"tag":35,"props":1015,"children":1016},{},[1017,1019,1025],{"type":39,"value":1018},"Das Control Panel ist seit Version 6 komplett überarbeitet und fühlt sich sehr modern an: schnell, aufgeräumt, mit Dark Mode, Live Preview und einer globalen Suche (",{"type":34,"tag":115,"props":1020,"children":1022},{"className":1021},[],[1023],{"type":39,"value":1024},"Strg + K",{"type":39,"value":1026},"). Felder werden in Blueprints definiert und in Tabs und Sektionen gegliedert. Dadurch sieht das Backend für jeden Inhaltstyp genau so aus, wie es das Projekt braucht – nicht mehr und nicht weniger.",{"type":34,"tag":35,"props":1028,"children":1029},{},[1030],{"type":39,"value":1031},"Für Kunden war das ein großer Pluspunkt. Die Einarbeitung war deutlich kürzer, als ich es von anderen Systemen kenne.",{"type":34,"tag":103,"props":1033,"children":1034},{"id":130},[1035],{"type":39,"value":133},{"type":34,"tag":35,"props":1037,"children":1038},{},[1039],{"type":39,"value":1040},"Statamic zwingt dir keine Struktur auf. Du baust deine Inhaltsmodelle selbst:",{"type":34,"tag":140,"props":1042,"children":1043},{},[1044,1053,1069,1089],{"type":34,"tag":144,"props":1045,"children":1046},{},[1047,1051],{"type":34,"tag":148,"props":1048,"children":1049},{},[1050],{"type":39,"value":152},{"type":39,"value":1052}," für Seiten, News, Veranstaltungen, Referenten …",{"type":34,"tag":144,"props":1054,"children":1055},{},[1056,1061,1062,1067],{"type":34,"tag":148,"props":1057,"children":1058},{},[1059],{"type":39,"value":1060},"Blueprints",{"type":39,"value":154},{"type":34,"tag":148,"props":1063,"children":1064},{},[1065],{"type":39,"value":1066},"Fieldsets",{"type":39,"value":1068}," für die Felder, inklusive Replicator/Bard für flexible Seitenbausteine",{"type":34,"tag":144,"props":1070,"children":1071},{},[1072,1077,1078,1083,1084],{"type":34,"tag":148,"props":1073,"children":1074},{},[1075],{"type":39,"value":1076},"Taxonomien",{"type":39,"value":845},{"type":34,"tag":148,"props":1079,"children":1080},{},[1081],{"type":39,"value":1082},"Globals",{"type":39,"value":154},{"type":34,"tag":148,"props":1085,"children":1086},{},[1087],{"type":39,"value":1088},"Navigationen",{"type":34,"tag":144,"props":1090,"children":1091},{},[1092,1097],{"type":34,"tag":148,"props":1093,"children":1094},{},[1095],{"type":39,"value":1096},"Rollen und Rechte",{"type":39,"value":1098},", zum Beispiel „Content Editor“ und „Site Manager“ mit genau definierten Berechtigungen",{"type":34,"tag":35,"props":1100,"children":1101},{},[1102],{"type":39,"value":1103},"Weil es Laravel ist, kann man alles erweitern: eigene Controller, Commands, Scheduler (bei uns für den Import externer API-Daten), Queues und Addons. Fehlt etwas, schreibt man es einfach in PHP.",{"type":34,"tag":103,"props":1105,"children":1107},{"id":1106},"flat-file-cms",[1108],{"type":39,"value":1109},"Flat-File-CMS",{"type":34,"tag":35,"props":1111,"children":1112},{},[1113],{"type":39,"value":1114},"Keine Datenbank bedeutet: kein Datenbank-Server, keine Dumps, kein Migrationsproblem zwischen Staging und Produktion. Ein Eintrag sieht so aus:",{"type":34,"tag":208,"props":1116,"children":1120},{"className":1117,"code":1118,"language":1119,"meta":8,"style":8},"language-yaml shiki shiki-themes dracula","---\nid: 6f0c4a1e-0000-0000-0000-000000000000\ntitle: Eröffnungsvortrag\npublished: true\nstart: '2026-10-09 10:00'\n---\nHier steht der Inhalt als ganz normales **Markdown**.\n","yaml",[1121],{"type":34,"tag":115,"props":1122,"children":1123},{"__ignoreMap":8},[1124,1132,1151,1168,1184,1212,1219],{"type":34,"tag":218,"props":1125,"children":1126},{"class":220,"line":221},[1127],{"type":34,"tag":218,"props":1128,"children":1129},{"style":258},[1130],{"type":39,"value":1131},"---\n",{"type":34,"tag":218,"props":1133,"children":1134},{"class":220,"line":285},[1135,1141,1145],{"type":34,"tag":218,"props":1136,"children":1138},{"style":1137},"--shiki-default:#8BE9FD",[1139],{"type":39,"value":1140},"id",{"type":34,"tag":218,"props":1142,"children":1143},{"style":225},[1144],{"type":39,"value":244},{"type":34,"tag":218,"props":1146,"children":1148},{"style":1147},"--shiki-default:#F1FA8C",[1149],{"type":39,"value":1150}," 6f0c4a1e-0000-0000-0000-000000000000\n",{"type":34,"tag":218,"props":1152,"children":1153},{"class":220,"line":320},[1154,1159,1163],{"type":34,"tag":218,"props":1155,"children":1156},{"style":1137},[1157],{"type":39,"value":1158},"title",{"type":34,"tag":218,"props":1160,"children":1161},{"style":225},[1162],{"type":39,"value":244},{"type":34,"tag":218,"props":1164,"children":1165},{"style":1147},[1166],{"type":39,"value":1167}," Eröffnungsvortrag\n",{"type":34,"tag":218,"props":1169,"children":1170},{"class":220,"line":351},[1171,1176,1180],{"type":34,"tag":218,"props":1172,"children":1173},{"style":1137},[1174],{"type":39,"value":1175},"published",{"type":34,"tag":218,"props":1177,"children":1178},{"style":225},[1179],{"type":39,"value":244},{"type":34,"tag":218,"props":1181,"children":1182},{"style":314},[1183],{"type":39,"value":348},{"type":34,"tag":218,"props":1185,"children":1186},{"class":220,"line":361},[1187,1192,1196,1202,1207],{"type":34,"tag":218,"props":1188,"children":1189},{"style":1137},[1190],{"type":39,"value":1191},"start",{"type":34,"tag":218,"props":1193,"children":1194},{"style":225},[1195],{"type":39,"value":244},{"type":34,"tag":218,"props":1197,"children":1199},{"style":1198},"--shiki-default:#E9F284",[1200],{"type":39,"value":1201}," '",{"type":34,"tag":218,"props":1203,"children":1204},{"style":1147},[1205],{"type":39,"value":1206},"2026-10-09 10:00",{"type":34,"tag":218,"props":1208,"children":1209},{"style":1198},[1210],{"type":39,"value":1211},"'\n",{"type":34,"tag":218,"props":1213,"children":1214},{"class":220,"line":390},[1215],{"type":34,"tag":218,"props":1216,"children":1217},{"style":258},[1218],{"type":39,"value":1131},{"type":34,"tag":218,"props":1220,"children":1221},{"class":220,"line":419},[1222],{"type":34,"tag":218,"props":1223,"children":1224},{"style":1147},[1225],{"type":39,"value":1226},"Hier steht der Inhalt als ganz normales **Markdown**.\n",{"type":34,"tag":35,"props":1228,"children":1229},{},[1230,1232,1238,1239,1245],{"type":39,"value":1231},"Das ist leicht lesbar, leicht zu sichern und leicht zu verschieben. Ein Projekt zu klonen heißt ",{"type":34,"tag":115,"props":1233,"children":1235},{"className":1234},[],[1236],{"type":39,"value":1237},"git clone",{"type":39,"value":845},{"type":34,"tag":115,"props":1240,"children":1242},{"className":1241},[],[1243],{"type":39,"value":1244},"composer install",{"type":39,"value":1246}," – fertig. Auch Benutzer und Rollen liegen als Dateien im Projekt. Nur für Laravel-Interna braucht es bei Bedarf eine Datenbank – bei uns reicht dafür eine kleine SQLite-Datei.",{"type":34,"tag":103,"props":1248,"children":1249},{"id":504},[1250],{"type":39,"value":507},{"type":34,"tag":35,"props":1252,"children":1253},{},[1254,1256,1261],{"type":39,"value":1255},"Weil bei Statamic wirklich ",{"type":34,"tag":998,"props":1257,"children":1258},{},[1259],{"type":39,"value":1260},"alles",{"type":39,"value":1262}," in Dateien liegt, kann ein KI-Assistent im Editor das gesamte Projekt lesen und verstehen: Templates, Blueprints, Inhalte, Konfiguration. Er kann neue Collections anlegen, Felder ergänzen, Einträge anpassen oder Templates refactoren, ohne dass man ihm erst Zugriff auf eine Datenbank oder eine API geben muss. Alles ist außerdem im Git-Diff sichtbar und damit gut zu prüfen.",{"type":34,"tag":71,"props":1264,"children":1265},{"id":561},[1266],{"type":39,"value":564},{"type":34,"tag":103,"props":1268,"children":1270},{"id":1269},"preis",[1271],{"type":39,"value":1272},"Preis",{"type":34,"tag":35,"props":1274,"children":1275},{},[1276,1278,1283,1285,1290],{"type":39,"value":1277},"Statamic Core ist kostenlos, hat aber Einschränkungen, vor allem nur einen Benutzer-Account. Sobald es mehrere Redakteure, Rollen, Revisionen, mehrere Sprachen/Sites oder die Git-Integration braucht, ist Pro nötig. Und das kostet seit Mai 2026 ",{"type":34,"tag":148,"props":1279,"children":1280},{},[1281],{"type":39,"value":1282},"349 $ pro Site",{"type":39,"value":1284}," (einmalig, ein Jahr Updates inklusive), danach ",{"type":34,"tag":148,"props":1286,"children":1287},{},[1288],{"type":39,"value":1289},"99 $ pro Jahr",{"type":39,"value":1291}," für Updates und Support. Vorher waren es 275 $ und 65 $.",{"type":34,"tag":35,"props":1293,"children":1294},{},[1295],{"type":39,"value":1296},"Für ein Kundenprojekt ist das gut zu stemmen. Für Hobbyprojekte, kleine Vereinsseiten oder wenn man viele kleine Sites betreibt, ist es ein spürbarer Posten gegenüber WordPress. Man sollte den Preis also von Anfang an im Angebot einkalkulieren. Im Gegenzug sind Formulare, Static Caching oder ein Navigations-Builder bereits enthalten, wofür man bei anderen Systemen oft Plugins kaufen muss.",{"type":34,"tag":103,"props":1298,"children":1300},{"id":1299},"cache",[1301],{"type":39,"value":1302},"Cache",{"type":34,"tag":35,"props":1304,"children":1305},{},[1306,1308,1313],{"type":39,"value":1307},"Damit ein dateibasiertes System schnell bleibt, nutzt Statamic den ",{"type":34,"tag":148,"props":1309,"children":1310},{},[1311],{"type":39,"value":1312},"Stache",{"type":39,"value":1314},", einen Cache-Index über alle Inhalte. Dazu kommen die normalen Laravel-Caches (Config, Routes, Views) und optional Static Caching.",{"type":34,"tag":35,"props":1316,"children":1317},{},[1318,1320,1326,1327,1333,1334,1340],{"type":39,"value":1319},"In der Praxis heißt das: Wenn nach einem Deployment etwas „komisch“ aussieht, ist es fast immer der Cache. Bei uns gab es zum Beispiel einen Config-Cache mit falschen absoluten Pfaden, der zu einem 500er-Fehler geführt hat. Nach jedem Deploy gehört deshalb ein ",{"type":34,"tag":115,"props":1321,"children":1323},{"className":1322},[],[1324],{"type":39,"value":1325},"cache:clear",{"type":39,"value":845},{"type":34,"tag":115,"props":1328,"children":1330},{"className":1329},[],[1331],{"type":39,"value":1332},"config:clear",{"type":39,"value":154},{"type":34,"tag":115,"props":1335,"children":1337},{"className":1336},[],[1338],{"type":39,"value":1339},"statamic:stache:clear",{"type":39,"value":1341}," fest dazu. Wer Static Caching einsetzt, muss sich außerdem Gedanken über die Invalidierung machen.",{"type":34,"tag":103,"props":1343,"children":1344},{"id":567},[1345],{"type":39,"value":570},{"type":34,"tag":35,"props":1347,"children":1348},{},[1349],{"type":39,"value":1350},"Statamic ist eine Laravel-Anwendung und braucht entsprechende Umgebung:",{"type":34,"tag":140,"props":1352,"children":1353},{},[1354,1364,1369,1387,1392],{"type":34,"tag":144,"props":1355,"children":1356},{},[1357,1362],{"type":34,"tag":148,"props":1358,"children":1359},{},[1360],{"type":39,"value":1361},"PHP 8.3+",{"type":39,"value":1363}," (bei uns teils 8.4)",{"type":34,"tag":144,"props":1365,"children":1366},{},[1367],{"type":39,"value":1368},"Composer und idealerweise SSH-Zugang",{"type":34,"tag":144,"props":1370,"children":1371},{},[1372,1374,1380,1381],{"type":39,"value":1373},"Schreibrechte für ",{"type":34,"tag":115,"props":1375,"children":1377},{"className":1376},[],[1378],{"type":39,"value":1379},"storage/",{"type":39,"value":154},{"type":34,"tag":115,"props":1382,"children":1384},{"className":1383},[],[1385],{"type":39,"value":1386},"bootstrap/cache",{"type":34,"tag":144,"props":1388,"children":1389},{},[1390],{"type":39,"value":1391},"GD oder Imagick für die Bildverarbeitung (Glide)",{"type":34,"tag":144,"props":1393,"children":1394},{},[1395],{"type":39,"value":1396},"Cron für den Laravel-Scheduler",{"type":34,"tag":35,"props":1398,"children":1399},{},[1400,1402,1408,1410,1416,1418,1424],{"type":39,"value":1401},"Günstiges Shared Hosting mit alter PHP-Version ist damit raus. Bei einem Hoster war die Standard-PHP-Version im Account noch 7.4, sodass die PHP-Version erst explizit per ",{"type":34,"tag":115,"props":1403,"children":1405},{"className":1404},[],[1406],{"type":39,"value":1407},".htaccess",{"type":39,"value":1409}," umgestellt und auf der CLI immer ",{"type":34,"tag":115,"props":1411,"children":1413},{"className":1412},[],[1414],{"type":39,"value":1415},"php84",{"type":39,"value":1417}," statt ",{"type":34,"tag":115,"props":1419,"children":1421},{"className":1420},[],[1422],{"type":39,"value":1423},"php",{"type":39,"value":1425}," verwendet werden musste. Gegenüber einer statischen Nuxt-Seite auf Netlify oder einem simplen WordPress-Hosting ist das deutlich mehr Aufwand.",{"type":34,"tag":103,"props":1427,"children":1428},{"id":635},[1429],{"type":39,"value":638},{"type":34,"tag":35,"props":1431,"children":1432},{},[1433,1435,1441],{"type":39,"value":1434},"Eigentlich ist das Deployment unproblematisch: Per GitHub Actions werden ",{"type":34,"tag":115,"props":1436,"children":1438},{"className":1437},[],[1439],{"type":39,"value":1440},"vendor/",{"type":39,"value":1442}," und die Assets gebaut und auf den Server übertragen, ein paar Artisan-Befehle laufen hinterher. Das ist kein Statamic-spezifisches Problem, sondern Laravel-Alltag. Trotzdem gab es Stolpersteine:",{"type":34,"tag":140,"props":1444,"children":1445},{},[1446,1480,1494,1512],{"type":34,"tag":144,"props":1447,"children":1448},{},[1449,1454,1456,1462,1464,1470,1472,1478],{"type":34,"tag":148,"props":1450,"children":1451},{},[1452],{"type":39,"value":1453},"nginx und Glide:",{"type":39,"value":1455}," Bildvarianten (",{"type":34,"tag":115,"props":1457,"children":1459},{"className":1458},[],[1460],{"type":39,"value":1461},"/img/...",{"type":39,"value":1463},") gaben 404, weil die Standard-Konfiguration statische Dateiendungen wie ",{"type":34,"tag":115,"props":1465,"children":1467},{"className":1466},[],[1468],{"type":39,"value":1469},".webp",{"type":39,"value":1471}," abfängt, bevor PHP sie erreicht. Es braucht eine eigene ",{"type":34,"tag":115,"props":1473,"children":1475},{"className":1474},[],[1476],{"type":39,"value":1477},"location",{"type":39,"value":1479},"-Regel.",{"type":34,"tag":144,"props":1481,"children":1482},{},[1483,1492],{"type":34,"tag":148,"props":1484,"children":1485},{},[1486],{"type":34,"tag":115,"props":1487,"children":1489},{"className":1488},[],[1490],{"type":39,"value":1491},"open_basedir",{"type":39,"value":1493}," war bei Plesk zu restriktiv eingestellt.",{"type":34,"tag":144,"props":1495,"children":1496},{},[1497,1502,1504,1510],{"type":34,"tag":148,"props":1498,"children":1499},{},[1500],{"type":39,"value":1501},"Rechte und Verzeichnisse:",{"type":39,"value":1503}," ",{"type":34,"tag":115,"props":1505,"children":1507},{"className":1506},[],[1508],{"type":39,"value":1509},"storage/logs",{"type":39,"value":1511}," fehlte nach dem Deploy, weil das Verzeichnis nicht im Repository war.",{"type":34,"tag":144,"props":1513,"children":1514},{},[1515,1520,1522,1528],{"type":34,"tag":148,"props":1516,"children":1517},{},[1518],{"type":39,"value":1519},"Inhalte vs. Code:",{"type":39,"value":1521}," Das ist der eigentliche Knackpunkt. Wenn Redakteure auf dem Server Inhalte ändern und ein Code-Deploy diese Dateien danach wieder aus dem Repository überschreibt, sind Änderungen weg. Entweder man schließt ",{"type":34,"tag":115,"props":1523,"children":1525},{"className":1524},[],[1526],{"type":39,"value":1527},"content/",{"type":39,"value":1529}," vom Deploy aus oder setzt auf die Git-Integration – die dann sauber mit dem Deploy zusammenspielen muss, damit Pushes nicht an einem „non-fast-forward“ scheitern.",{"type":34,"tag":35,"props":1531,"children":1532},{},[1533],{"type":39,"value":1534},"Hat man das einmal sauber aufgesetzt, läuft es zuverlässig. Wer neu startet, sollte diese Punkte aber von Anfang an einplanen.",{"type":34,"tag":71,"props":1536,"children":1537},{"id":885},[1538],{"type":39,"value":888},{"type":34,"tag":35,"props":1540,"children":1541},{},[1542],{"type":39,"value":1543},"Statamic ist für mich eines der angenehmsten CMS, mit denen ich bisher gearbeitet habe. Die Kombination aus Git-Workflow, modernem Backend und voller Anpassbarkeit passt hervorragend zu Projekten, bei denen Redakteure eine komfortable Oberfläche brauchen und Entwickler trotzdem die volle Kontrolle über Code und Struktur behalten wollen. Dass alles in Dateien liegt, macht die Arbeit mit KI-Assistenten außerdem deutlich einfacher.",{"type":34,"tag":35,"props":1545,"children":1546},{},[1547],{"type":39,"value":1548},"Die Nachteile sind überschaubar, aber real: Der Preis für Pro, ein Server mit aktuellem PHP und ein bisschen Disziplin bei Cache und Deployment. Für einfache, kleine Seiten ohne Redaktion oder mit knappem Budget gibt es andere Optionen, die evtl. besser passen. Für Kundenprojekte mit echten Anforderungen würde ich Statamic jederzeit wieder einsetzen.",{"type":34,"tag":900,"props":1550,"children":1551},{},[1552],{"type":39,"value":904},{"title":8,"searchDepth":285,"depth":285,"links":1554},[1555,1556,1563,1569],{"id":961,"depth":285,"text":964},{"id":98,"depth":285,"text":101,"children":1557},[1558,1559,1560,1561,1562],{"id":988,"depth":320,"text":991},{"id":105,"depth":320,"text":108},{"id":130,"depth":320,"text":133},{"id":1106,"depth":320,"text":1109},{"id":504,"depth":320,"text":507},{"id":561,"depth":285,"text":564,"children":1564},[1565,1566,1567,1568],{"id":1269,"depth":320,"text":1272},{"id":1299,"depth":320,"text":1302},{"id":567,"depth":320,"text":570},{"id":635,"depth":320,"text":638},{"id":885,"depth":285,"text":888},"content:blog:statamic.md","blog/statamic.md",1791545016474]