[{"data":1,"prerenderedAt":931},["ShallowReactive",2],{"blog-nuxt-security-module-de":3},{"slug":4,"published":5,"minutes":6,"category":7,"tags":8,"keywords":14,"about":25,"sources":34,"cover":71,"og":72,"expertise":73,"locales":74,"lang":76,"title":78,"description":79,"coverAlt":80,"metaTitle":81,"takeaways":82,"faq":88,"toc":104,"blocks":135,"others":660},"nuxt-security-module","2026-10-02",11,"web",[9,10,11,12,13],"Nuxt","Content Security Policy","HTTP security headers","Rate limiting","Nitro",[15,16,17,18,19,20,21,22,23,24],"nuxt security module","nuxt content security policy nonce","nuxt security headers","nitro route rules security","nuxt rate limiter","nuxt cors server routes","csp report-uri nuxt","nuxt csrf protection","secure nuxt app checklist","nuxt csp strict-dynamic breakage",[26,28,31],{"name":10,"url":27},"https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FContent_Security_Policy",{"name":29,"url":30},"Cross-site scripting","https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FCross-site_scripting",{"name":32,"url":33},"Cross-origin resource sharing","https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FCross-origin_resource_sharing",[35,38,41,44,47,50,53,56,59,62,65,68],{"title":36,"url":37},"Nuxt Security README (main branch)","https:\u002F\u002Fgithub.com\u002FBaroshem\u002Fnuxt-security\u002Fblob\u002Fmain\u002FREADME.md",{"title":39,"url":40},"Nuxt Security default configuration (src\u002FdefaultConfig.ts)","https:\u002F\u002Fraw.githubusercontent.com\u002FBaroshem\u002Fnuxt-security\u002Fmain\u002Fsrc\u002FdefaultConfig.ts",{"title":42,"url":43},"Nuxt Security docs: Content Security Policy","https:\u002F\u002Fraw.githubusercontent.com\u002FBaroshem\u002Fnuxt-security\u002Fmain\u002Fdocs\u002Fcontent\u002F2.headers\u002F1.csp.md",{"title":45,"url":46},"Nuxt Security docs: rate limiter","https:\u002F\u002Fraw.githubusercontent.com\u002FBaroshem\u002Fnuxt-security\u002Fmain\u002Fdocs\u002Fcontent\u002F3.middleware\u002F1.rate-limiter.md",{"title":48,"url":49},"Nuxt Security docs: CORS handler","https:\u002F\u002Fraw.githubusercontent.com\u002FBaroshem\u002Fnuxt-security\u002Fmain\u002Fdocs\u002Fcontent\u002F3.middleware\u002F4.cors-handler.md",{"title":51,"url":52},"Nuxt Security docs: CSRF","https:\u002F\u002Fraw.githubusercontent.com\u002FBaroshem\u002Fnuxt-security\u002Fmain\u002Fdocs\u002Fcontent\u002F3.middleware\u002F7.csrf.md",{"title":54,"url":55},"Nuxt Security docs: hooks","https:\u002F\u002Fraw.githubusercontent.com\u002FBaroshem\u002Fnuxt-security\u002Fmain\u002Fdocs\u002Fcontent\u002F5.advanced\u002F4.hooks.md",{"title":57,"url":58},"Nuxt Security docs: security headers","https:\u002F\u002Fraw.githubusercontent.com\u002FBaroshem\u002Fnuxt-security\u002Fmain\u002Fdocs\u002Fcontent\u002F5.advanced\u002F5.security-headers.md",{"title":60,"url":61},"Nuxt Security docs: improving security","https:\u002F\u002Fraw.githubusercontent.com\u002FBaroshem\u002Fnuxt-security\u002Fmain\u002Fdocs\u002Fcontent\u002F5.advanced\u002F7.improve-security.md",{"title":63,"url":64},"Nuxt Security release v2.6.0 (12 May 2026)","https:\u002F\u002Fgithub.com\u002FBaroshem\u002Fnuxt-security\u002Freleases\u002Ftag\u002Fv2.6.0",{"title":66,"url":67},"MDN: HTTP Observatory","https:\u002F\u002Fdeveloper.mozilla.org\u002Fen-US\u002Fobservatory",{"title":69,"url":70},"Playwright: Response class","https:\u002F\u002Fplaywright.dev\u002Fdocs\u002Fapi\u002Fclass-response","\u002Fimages\u002Fblog\u002Fnuxt-security-module\u002Fcover.webp","\u002Fimages\u002Fblog\u002Fnuxt-security-module\u002Fog.jpg","vue-nuxt-developer",[75,76,77],"en","de","hu","Eine Nuxt-App absichern: CSP, Header und Limits mit Nuxt Security","Wie das Modul Nuxt Security in der Praxis wirkt: sichere Standardwerte, Kompromisse des Strict-Modus, Nonce-CSP in SSR und SSG, Routenregeln und Limits.","Ein Schild mit drei Schlössern schützt ein Browserfenster.","Nuxt Security: CSP, Header und Limits · Balázs Csorba",[83,84,85,86,87],"Nuxt Security ist eine nützliche Standardschicht für Header und Anfragelimits, doch der dokumentierte Funktionsumfang enthält keine Authentifizierung, keine Autorisierung, keinen SSRF-Schutz und keine Web Application Firewall.","Die Standardwerte halten eine typische App funktionsfähig. Der Strict-Modus ist eine andere Richtlinie; beheben Sie deshalb die Brüche im Report-Only-Modus, bevor Sie erzwingen.","Nonce-CSP setzt Server-Rendering voraus. Statische Builds nutzen Hashes aus dem Build in einem Meta-Tag, deshalb testen Sie jede Seitenart getrennt.","Der eingebaute Rate Limiter ist eine Bremse auf Anwendungsebene. Schutz vor Brute-Force-Angriffen gehört auf die Infrastrukturebene.","Rollen Sie in den Report-Only-Modus aus, prüfen Sie die echten Header in End-to-End-Tests und formulieren Sie Ausnahmen pro Route, statt die ganze Seite zu lockern.",[89,92,95,98,101],{"q":90,"a":91},"Schützt Nuxt Security vor SSRF?","Der dokumentierte Funktionsumfang enthält keinen SSRF-Schutz, und das Modul ergänzt auch keine Authentifizierung oder Autorisierung. Prüfen Sie ausgehende Adressen in Ihrem eigenen Code und lesen Sie die Release-Notizen, bevor Sie sich auf eine Aussage zu einer bestimmten Version verlassen.",{"q":93,"a":94},"Reicht die Standard-CSP von Nuxt Security für den Produktivbetrieb?","Die Standardwerte sind so angelegt, dass eine typische App nicht bricht, aber sie sind ein Ausgangspunkt. Sie behalten unsafe-inline als Rückfall und erlauben https:-Quellen für Skripte. Prüfen Sie die Richtlinie im fertigen Build, beheben Sie die Brüche und wechseln Sie dann in den Strict-Modus oder zu einer engeren eigenen Richtlinie.",{"q":96,"a":97},"Warum funktioniert Nonce-CSP auf einer statischen Seite nicht?","Ein Nonce wird pro Antwort erzeugt, eine statische Datei ist für jeden Besucher gleich. Nuxt Security ignoriert die Option nonce bei nuxi generate und verwendet stattdessen Hashes aus dem Build, die in einem Meta-Tag ausgeliefert werden.",{"q":99,"a":100},"Stoppt der Rate Limiter Denial-of-Service-Angriffe?","Nein. Die Dokumentation beschreibt ihn als Werkzeug für einfachere Anwendungen und empfiehlt für Brute-Force-Schutz Lösungen auf Infrastrukturebene. Setzen Sie für das Traffic-Volumen ein CDN, einen Load Balancer oder eine Web Application Firewall davor und behalten Sie den Limiter der Anwendung als zweite Schicht.",{"q":102,"a":103},"Wie prüfe ich, dass die Header nach einem Deployment noch da sind?","Schreiben Sie einen End-to-End-Test, der die Antwort-Header einer serverseitig gerenderten und einer vorgerenderten Seite liest und fehlschlägt, wenn Content-Security-Policy oder Strict-Transport-Security fehlt.",[105,108,111,114,117,120,123,126,129,132],{"id":106,"title":107},"what-nuxt-security-covers","Was deckt Nuxt Security ab, und was lässt es offen?",{"id":109,"title":110},"defaults-versus-strict-mode","Was garantieren die Standardwerte, und was ändert der Strict-Modus?",{"id":112,"title":113},"nonce-csp-ssr-ssg-hybrid","Wie funktioniert Nonce-CSP bei SSR, SSG und Hybrid-Apps?",{"id":115,"title":116},"per-route-hardening","Wie härten Sie einzelne Routen ab?",{"id":118,"title":119},"rate-limits-request-size","Was schützen die Limits für Größe und Häufigkeit tatsächlich?",{"id":121,"title":122},"cors-csrf-api-routes","Wie verhalten sich CORS und CSRF bei API-Routen?",{"id":124,"title":125},"observing-and-testing","Wie rollen Sie die Header-Schicht aus und testen sie?",{"id":127,"title":128},"when-to-hand-roll","Wann ist handgeschriebene Nitro-Middleware die bessere Wahl?",{"id":130,"title":131},"production-checklist","Wie sieht eine Checkliste für den Produktivbetrieb aus?",{"id":133,"title":134},"sources","Quellen",[136,144,147,150,158,161,162,190,221,308,315,321,322,341,345,352,354,357,368,369,380,382,404,423,424,435,443,458,459,486,512,513,531,542,544,552,553,560,566,569,570,573,613,621,622],{"type":137,"content":138},"paragraph",[139,143],{"tag":140,"children":141},"strong",[142],"Nuxt Security"," ist ein Modul, das eine Nuxt-Anwendung um eine Härtungsschicht erweitert. Es setzt Sicherheits-Header der Antwort, darunter eine Content Security Policy (CSP), ergänzt Limits für Größe und Häufigkeit von Anfragen, prüft Eingaben auf Cross-Site-Scripting, übernimmt CORS und entfernt einige Spuren des Frameworks. Stand Oktober 2026 ist die neueste Version 2.6.0 vom 12. Mai 2026, und das Modul funktioniert mit Nuxt 3.x und neueren Versionen einschließlich 4.x. Die Standardwerte sollen eine typische App sicher halten, ohne sie zu brechen. Das ist nützlich, aber nicht die ganze Geschichte: Manche Schutzmaßnahmen hängen davon ab, ob eine Seite auf dem Server gerendert oder als statische Datei erzeugt wird, manche brechen Drittanbieter-Widgets, und der Rate Limiter ist ausdrücklich nicht für komplexe Produktionsanwendungen gedacht.",{"type":137,"content":145},[146],"Dieser Artikel behandelt das Modul als Betriebsschicht und nicht als Funktionsliste. Er erklärt, was die Standardwerte garantieren und was der Strict-Modus ändert, wie sich Nonce-basierte CSP zwischen Server-Rendering und statischer Generierung unterscheidet, wie Regeln pro Route überschrieben werden, warum der eingebaute Rate Limiter eine Bremse und kein Schutz vor Denial of Service ist und wann handgeschriebene Nitro-Middleware die bessere Wahl ist. Alle Zahlen stammen aus der Dokumentation oder dem Quellcode des Moduls, Stand Oktober 2026.",{"type":148,"level":149,"id":106,"text":107},"heading",2,{"type":137,"content":151},[152,153,157],"Nuxt Security deckt die HTTP-Schicht ab: Sicherheits-Header der Antwort, darunter CSP für statische Seiten, Limits für Anfragegröße und Häufigkeit, XSS-Prüfung für GET- und POST-Anfragen, CORS, das Ausblenden des Headers X-Powered-By und das Entfernen der Hilfsfunktionen für Console-Logger. Erlaubte HTTP-Methoden, Basic Auth und CSRF-Schutz sind optional. Die ",{"tag":154,"href":37,"children":155},"a",[156],"README des Moduls"," führt diesen Funktionsumfang auf und nennt Nuxt 3.x und neuer, einschließlich 4.x, als unterstützt.",{"type":137,"content":159},[160],"Die Lücken sind genauso wichtig wie die Liste. Der dokumentierte Funktionsumfang enthält keinen SSRF-Schutz, keine Authentifizierung oder Autorisierung und keine Web Application Firewall. Wenn Ihre App Adressen abruft, die Nutzer angeben, oder private Daten hinter einer Anmeldung bereitstellt, übernimmt das Modul diese Arbeit nicht. Betrachten Sie den XSS-Validator als einen Filter für eingehende Anfragedaten, der auf js-xss basiert. Die Maskierung der Ausgabe in Ihren Komponenten bleibt Ihre Aufgabe.",{"type":148,"level":149,"id":109,"text":110},{"type":137,"content":163},[164,165,169,170,173,174,177,178,181,182,185,186,189],"Die Standardwerte ergeben eine Richtlinie, die mit einer typischen App funktioniert. Skripte dürfen von der eigenen Herkunft und aus https:-Quellen kommen, Styles dürfen Inline-CSS verwenden, und die Skriptrichtlinie nennt einen Nonce zusammen mit ",{"tag":166,"children":167},"code",[168],"'strict-dynamic'",". Browser, die Nonces verstehen, ignorieren den Rückfall unsafe-inline, sobald ein Nonce vorhanden ist. Die übrigen Standardwerte sind ",{"tag":166,"children":171},[172],"nonce: true",", ",{"tag":166,"children":175},[176],"sri: true",", ein Cross-Origin-Embedder-Policy-Wert ",{"tag":166,"children":179},[180],"credentialless"," in Produktion, HSTS mit einer max-age von 15.552.000 Sekunden und includeSubdomains, ",{"tag":166,"children":183},[184],"no-referrer"," als Referrer-Policy und ",{"tag":166,"children":187},[188],"SAMEORIGIN"," für X-Frame-Options. Rate Limits, Größenbegrenzungen und CORS sind aktiv, Basic Auth und CSRF sind aus.",{"type":137,"content":191},[192,193,196,197,200,201,204,205,208,209,212,213,216,217,220],"Der Strict-Modus ist eine andere Richtlinie und keine strengere Fassung derselben Werte. ",{"tag":166,"children":194},[195],"strict: true"," setzt ",{"tag":166,"children":198},[199],"default-src"," auf ",{"tag":166,"children":202},[203],"'none'",", entfernt ",{"tag":166,"children":206},[207],"unsafe-inline"," für Skripte, erlaubt Styles nur mit dem Nonce, begrenzt Frames und Worker auf ",{"tag":166,"children":210},[211],"'self'",", stellt COEP auf ",{"tag":166,"children":214},[215],"require-corp"," um, hebt HSTS auf ein Jahr mit Preload an, setzt X-Frame-Options auf ",{"tag":166,"children":218},[219],"DENY"," und verweigert standardmäßig jede Permissions-Policy-Funktion. Die Dokumentation beschreibt einen schrittweisen Weg: mit den Standardwerten beginnen, die Brüche beheben und dann auf Strict umstellen.",{"type":222,"head":223,"rows":232},"table",[224,226,228,230],[225],"Funktion",[227],"Standard",[229],"Pro Route",[231],"Vorbehalt, der zuerst auftritt",[233,242,251,259,267,275,283,292,300],[234,236,238,240],[235],"CSP für SSR",[237],"Nonce plus strict-dynamic",[239],"ja, unter security",[241],"Nonce wird bei statischen Builds ignoriert",[243,245,247,249],[244],"CSP für SSG",[246],"Hashes aus dem Build in einem Meta-Tag",[248],"pro Route nicht dokumentiert",[250],"Inline-Code muss gehasht werden",[252,254,256,257],[253],"Rate Limiter",[255],"150 requests per 300,000 ms per IP",[239],[258],"LRU-Zustand liegt in jedem Prozess",[260,262,264,265],[261],"Anfragegröße",[263],"2,000,000 bytes, 8,000,000 for uploads",[239],[266],"413 bei zu großen Anfragen",[268,270,272,273],[269],"XSS-Validator",[271],"aktiv für GET und POST",[239],[274],"400, wenn unsicherer Code vorkommt",[276,278,280,281],[277],"CORS",[279],"Ursprung ist die Server-URL",[239],[282],"useRegExp behandelt Ursprünge als Muster",[284,286,288,290],[285],"CSRF",[287],"aus",[289],"Ausnahme über csurf: false",[291],"Aktivierung über nuxt-csurf",[293,295,297,298],[294],"Subresource Integrity",[296],"an, Hashes beim Build",[248],[299],"Host-seitige Änderungen brechen die Hashes",[301,303,305,306],[302],"COEP",[304],"credentialless in Produktion",[239],[307],"Popup-Anmeldungen brauchen Lockerung",{"type":309,"variant":310,"title":311,"body":312},"callout","warn","Strict-Modus ist eine Migration, kein Schalter",[313],[314],"Wenn Sie eine laufende App auf Strict umstellen, brechen Drittanbieter-Widgets, Inline-Handler und Skripte für Bildfehler. Betreiben Sie die Richtlinie zuerst im Report-Only-Modus, beheben Sie jede Verletzung und erzwingen Sie sie erst dann.",{"type":316,"src":317,"alt":318,"wide":319,"caption":320},"image","\u002Fimages\u002Fblog\u002Fnuxt-security-module\u002Fdiagram-10.webp","Drei Stufen der Skriptrichtlinie Drei Kästen von links nach rechts: inline Code erlauben, ein Nonce oder einen Hash verlangen und strict-dynamic hinzufügen. Jede Stufe bricht mehr Code und gibt mehr Kontrolle.",true,"Drei Stufen der Skriptrichtlinie. Stufe 1 erlaubt Inline-Code und bricht am wenigsten. Stufe 2 verlangt einen Nonce oder Hash, was unsafe-inline außer Kraft setzt, sodass Inline-Ereignishandler und Inline-Styles zu scheitern beginnen. Stufe 3 ergänzt strict-dynamic: Dann laufen nur Skripte mit Nonce, und die Skripte, die sie laden, gelten als vertrauenswürdig; Code, der mit beliebigen Script-Tags rechnet, bricht.",{"type":148,"level":149,"id":112,"text":113},{"type":137,"content":323},[324,325,328,329,332,333,336,337,340],"Beim Server-Rendering erzeugt das Modul für jede Antwort einen Nonce, trägt ihn in den CSP-Header ein und ergänzt ihn an den Script-, Link- und Style-Elementen des gerenderten HTML. Bei statischer Generierung funktioniert das nicht, weil eine Datei alle Besucher bedient. Das Modul berechnet Hashes beim Build und liefert die Richtlinie in einem ",{"tag":166,"children":326},[327],"\u003Cmeta http-equiv>","-Tag aus. Die Dokumentation stellt klar, dass die Option ",{"tag":166,"children":330},[331],"nonce"," und die Platzhalter ",{"tag":166,"children":334},[335],"'nonce-{{nonce}}'"," ignoriert werden, wenn Sie mit ",{"tag":166,"children":338},[339],"nuxi generate"," für SSG bauen.",{"type":316,"src":342,"alt":343,"wide":319,"caption":344},"\u002Fimages\u002Fblog\u002Fnuxt-security-module\u002Fdiagram-13.webp","Anfragepfad durch Nuxt Security Sechs Kästen von links nach rechts: Routenregeln, Middleware, das serverseitige Rendering, das Einfügen des Nonce, das Zusammensetzen des HTML und die Header der Antwort.","Auf dem Serverpfad durchläuft die Anfrage Routenregeln und Middleware, die Seite wird gerendert, der Nonce wird in Script-, Link- und Style-Tags eingefügt, das HTML wird neu montiert und die Header werden gesetzt. Statische Builds umgehen den Server und liefern eine gehashte Richtlinie in einem Meta-Tag aus.",{"type":137,"content":346},[347,348,351],"Das Umschreiben passiert in der Render-Pipeline, deshalb muss Anwendungscode selten etwas über Nonces wissen. Das Modul verarbeitet Inline-Elemente ebenso wie externe Ressourcen. Braucht Ihr eigener Code einen Nonce, etwa für ein Inline-Skript, das er erzeugt, liefert ",{"tag":166,"children":349},[350],"useNonce()"," den Wert aus dem Serverkontext:",{"type":166,"code":353},"\u003Cscript setup lang=\"ts\">\nconst nonce = useNonce() \u002F\u002F set during SSR; empty on a static build\nuseHead({\n  script: [{ children: 'window.dataLayer = window.dataLayer || []', nonce }],\n})\n\u003C\u002Fscript>",{"type":137,"content":355},[356],"Ein statischer Build hat keine Anfrage, deshalb ist der Wert dort leer, und Inline-Code, der auf einer vorgerenderten Seite laufen muss, braucht stattdessen einen Hash. Der Hybridfall sorgt für die meiste Verwirrung. Eine Hybrid-App mischt serverseitig gerenderte und vorgerenderte Routen, daher können beide Antwortarten unterschiedliche Richtlinien tragen, und eine Header-Prüfung auf einem Pfad sagt nichts über den anderen. Prüfen Sie beide Seitenarten.",{"type":137,"content":358},[359,360,363,364,367],"Drei Brüche kehren immer wieder. Drittanbieter-Code, der zur Laufzeit Script-Tags erzeugt, liefert oft Elemente, die die Richtlinie nicht kennt. Die FAQ des Moduls sagt, dass die Inline-Fehlerbehandlung von ",{"tag":166,"children":361},[362],"\u003CNuxtImg>"," und ",{"tag":166,"children":365},[366],"\u003CNuxtPicture>"," bei einer reinen Nonce-Richtlinie in SSR kollidiert. Und Hosting-Anbieter, die Ihr Bundle nach dem Build nachbearbeiten, machen die Subresource-Integrity-Hashes ungültig.",{"type":148,"level":149,"id":115,"text":116},{"type":137,"content":370},[371,372,375,376,379],"Überschreiben Sie das Modul pro Pfad unter ",{"tag":166,"children":373},[374],"routeRules"," im Feld ",{"tag":166,"children":377},[378],"security",". Jede Middleware und jeder Header lässt sich dort setzen, sodass ein teurer API-Pfad ein engeres Limit haben kann als Ihre Marketingseiten, ohne einen eigenen Server.",{"type":166,"code":381},"\u002F\u002F nuxt.config.ts\nexport default defineNuxtConfig({\n  modules: ['nuxt-security'],\n  security: {\n    strict: true,\n    contentSecurityPolicyReportOnly: true,\n    rateLimiter: { tokensPerInterval: 150, interval: 300000 },\n  },\n  routeRules: {\n    \u002F\u002F illustrative values: a tighter limit for one expensive endpoint\n    '\u002Fapi\u002Fgenerate\u002F**': { security: { rateLimiter: { tokensPerInterval: 30, interval: 60000 } } },\n  },\n})",{"type":137,"content":383},[384,385,387,388,391,392,395,396,399,400,403],"Zwei Details stolpern Menschen immer wieder. Erstens gehören Sicherheits-Header nur in das Feld ",{"tag":166,"children":386},[378],". Die Dokumentation rät davon ab, sie über die native Option ",{"tag":166,"children":389},[390],"routeRules.headers"," zu setzen, und wenn beide denselben Header definieren, gewinnt das Feld security. Zweitens sollten manche Werte gar nicht im Repository liegen. Der Nitro-Hook ",{"tag":166,"children":393},[394],"nuxt-security:routeRules"," läuft beim Neustart des Servers und kann den gesamten Regelsatz ändern, was zu einer Liste erlaubter ",{"tag":166,"children":397},[398],"connect-src","-Ursprünge aus einem Secret Manager passt. Sein Gegenstück zur Build-Zeit, ",{"tag":166,"children":401},[402],"nuxt-security:prerenderedHeaders",", deckt statisches Hosting ab.",{"type":137,"content":405},[406,407,409,410,413,414,416,417,422],"Hier wächst die Richtlinie einer App mit LLM-Funktionen. Gestreamte Antworten brauchen ihren Ursprung in ",{"tag":166,"children":408},[398],", und jedes Anbieter-Widget braucht einen Eintrag in ",{"tag":166,"children":411},[412],"script-src",". Das Feld ",{"tag":166,"children":415},[378]," pro Route hält jede Ausnahme dort, wo sie gebraucht wird, statt die ganze Seite zu lockern. Das gleiche Streaming-Setup beschreibt ",{"tag":418,"to":419,"children":420},"link","\u002Fblog\u002Fnuxt-llm-features-ai-sdk-streaming",[421],"der Artikel zu Nuxt-LLM-Streaming",", und genau bei solchen Endpunkten schleicht sich gern eine zu breite Ausnahme ein.",{"type":148,"level":149,"id":118,"text":119},{"type":137,"content":425},[426,427,430,431,434],"Sie bremsen einen einzelnen Client, der zu viele Anfragen oder übergroße Inhalte an eine laufende Instanz schickt. Der Standard erlaubt 150 Anfragen pro IP innerhalb eines Fensters von 300.000 ms (fünf Minuten), verfolgt im LRU-Cache, und beantwortet Anfragen über dem Limit mit ",{"tag":166,"children":428},[429],"429 Too Many Requests",". Der Größenbegrenzer erzwingt 2.000.000 Bytes bei GET-, POST- und DELETE-Anfragen und beantwortet größere mit ",{"tag":166,"children":432},[433],"413 Payload Too Large","; Upload-Routen erhalten 8.000.000 Bytes.",{"type":137,"content":436},[437,438,442],"Die Dokumentation des Moduls nennt die Grenze dieses Ansatzes. Der eingebaute Rate Limiter „ist nicht für komplexe Produktionsanwendungen geeignet“, er soll einfacheren Anwendungen bei Brute-Force-Angriffen helfen, und für den Produktivbetrieb „sollten Sie Lösungen auf der Infrastrukturebene verwenden, nicht auf der Anwendungsebene“. Ich lese das als Arbeitsregel: Der eingebaute Limiter ist eine Bremse, kein Schutz vor Denial of Service. Ein CDN, ein Load Balancer oder eine Web Application Firewall sieht den Verkehr vor dem Node-Prozess und kann ihn abweisen, zu Kosten, die Ihre Anwendung nie trägt. Dieser Limiter ist der dünne Teil der Verteidigung auf Anwendungsebene, den ",{"tag":418,"to":439,"children":440},"\u002Fblog\u002Fllm-endpoint-abuse-denial-of-wallet",[441],"der Artikel zu Denial of Wallet"," für einen teuren Endpunkt beschreibt.",{"type":137,"content":444},[445,446,449,450,453,454,457],"Daraus folgen zwei praktische Punkte. Der LRU-Standard lebt in einem einzigen Prozess; bei mehreren Instanzen oder bei Serverless-Funktionen, die keinen Speicher teilen, zählt jede Instanz für sich, und das wirksame Limit vervielfacht sich. Das ist meine Lesart des Entwurfs und keine zitierte Aussage; ein Test mit zwei Instanzen würde es bestätigen. Der unstorage-Treiber kann die Zähler in gemeinsamen Speicher verlagern, etwa den in der Dokumentation gezeigten Treiber ",{"tag":166,"children":447},[448],"vercelKv",". Zweitens steht hinter einem Proxy die Proxy-Adresse als Client-Adresse, solange Sie nicht ",{"tag":166,"children":451},[452],"ipHeader"," setzen, etwa auf ",{"tag":166,"children":455},[456],"cf-connecting-ip",". Setzen Sie ihn nur, wenn die App ausschließlich über diesen Proxy erreichbar ist, sonst kann ein Client den Header selbst schicken.",{"type":148,"level":149,"id":121,"text":122},{"type":137,"content":460},[461,462,173,465,173,468,173,471,363,474,477,478,481,482,485],"CORS ist global aktiviert und erlaubt standardmäßig die eigene Server-URL als Ursprung. CSRF-Schutz ist aus, bis Sie ihn einschalten; er kommt über eine Integration mit nuxt-csurf. Der CORS-Handler baut auf der eingebauten CORS-Funktionalität von H3 auf. Sie können ",{"tag":166,"children":463},[464],"methods",{"tag":166,"children":466},[467],"allowHeaders",{"tag":166,"children":469},[470],"exposeHeaders",{"tag":166,"children":472},[473],"credentials",{"tag":166,"children":475},[476],"maxAge"," setzen, und der Status für Preflight-Anfragen ist standardmäßig 204. Mit aktiviertem ",{"tag":166,"children":479},[480],"useRegExp"," wird jede Ursprungszeichenkette in einen Regulären Ausdruck ohne Beachtung der Groß- und Kleinschreibung übersetzt. Das ist praktisch für Preview-Deployments und gefährlich, wenn ein Muster zu weit ist; halten Sie die Liste deshalb wo immer möglich explizit. Die ",{"tag":154,"href":49,"children":483},[484],"Dokumentation des CORS-Handlers"," zeigt alle Optionen.",{"type":137,"content":487},[488,489,492,493,496,497,363,500,503,504,507,508,511],"CSRF ist eine Option, die Sie aktivieren. Setzen Sie ",{"tag":166,"children":490},[491],"csrf: true",", nehmen Sie einzelne Routen über die eigene Routenregel ",{"tag":166,"children":494},[495],"csurf: false"," aus und verwenden Sie auf dem Client die automatisch importierten Composables ",{"tag":166,"children":498},[499],"useCsrfFetch",{"tag":166,"children":501},[502],"useCsrf()",". Die Dokumentation zeigt außerdem, wie der Token für einen tRPC-Client im Header ",{"tag":166,"children":505},[506],"csrf-token"," gesendet wird. Basic Auth ist ebenfalls optional. Das Modul verschiebt seine Zugangsdaten in ",{"tag":166,"children":509},[510],"runtimeConfig.private.basicAuth",", sodass sie nicht im Client-Bundle landen. Dort gehören sie hin, aber es bleibt ein gemeinsames Passwort, deshalb würde ich es nicht als Anmeldung für ein öffentliches Produkt verwenden.",{"type":148,"level":149,"id":124,"text":125},{"type":137,"content":514},[515,516,519,520,523,524,363,527,530],"Rollen Sie eine Richtlinie im Report-Only-Modus aus, lesen Sie die Berichte und erzwingen Sie sie erst dann. Setzen Sie ",{"tag":166,"children":517},[518],"contentSecurityPolicyReportOnly: true",", dann trägt die Antwort ",{"tag":166,"children":521},[522],"Content-Security-Policy-Report-Only"," statt des erzwingenden Headers. Die CSP-Optionen akzeptieren ",{"tag":166,"children":525},[526],"report-uri",{"tag":166,"children":528},[529],"report-to",", global und pro Route. Die Unterstützung für Report-Only kam mit Version 2.6.0, die außerdem die Berechnung der CSP-Hashes geändert hat: Sie erfolgt nun aus dem endgültigen HTML im Render-Hook. Lesen Sie diese Release-Notizen, bevor Sie eine statische Seite aktualisieren.",{"type":137,"content":532},[533,534,537,538,541],"Für eine einmalige Bewertung einer veröffentlichten Seite prüft das ",{"tag":154,"href":67,"children":535},[536],"HTTP Observatory von MDN"," die Header schnell. Es bewertet, was es sieht, kann aber nicht sagen, ob Ihre Seiten noch funktionieren; es ergänzt also Tests im Browser, ersetzt sie aber nicht. Die Prüfung, die Regressionen fängt, ist eine Assertion in einem End-to-End-Test. Die ",{"tag":154,"href":70,"children":539},[540],"Response-Klasse von Playwright"," liefert die Antwort-Header, sodass ein Test fehlschlagen kann, wenn ein Deployment die Richtlinie entfernt:",{"type":166,"code":543},"import { test, expect } from '@playwright\u002Ftest'\n\ntest('the home page sends the security headers', async ({ page }) => {\n  const response = await page.goto('\u002F')\n  const headers = response!.headers()\n  expect(headers['content-security-policy'] ?? headers['content-security-policy-report-only']).toContain(\"script-src 'self'\")\n  expect(headers['strict-transport-security']).toContain('max-age=')\n})",{"type":137,"content":545},[546,547,551],"Führen Sie die Prüfung gegen eine serverseitig gerenderte und eine vorgerenderte Seite aus, denn sie erzeugen unterschiedliche Richtlinien. Dasselbe Playwright-Setup, das ich bereits über Playwright MCP nutze, kann sie bei jedem Deployment laufen lassen, sodass eine Header-Regression an derselben Stelle auftaucht wie eine kaputte Seite. Dieselbe Gewohnheit, vor der Entscheidung zu messen, wende ich auch im ",{"tag":418,"to":548,"children":549},"\u002Fblog\u002Fnuxt-core-web-vitals-performance",[550],"Artikel zu Core Web Vitals"," an, nur ist hier die Messgröße ein Antwort-Header.",{"type":148,"level":149,"id":127,"text":128},{"type":137,"content":554},[555,556,559],"Nutzen Sie das Modul, wenn Ihnen Nonce-Umschreibung, Hashing und Header-Sätze gepflegt abgenommen werden sollen. Schreiben Sie ",{"tag":166,"children":557},[558],"server\u002Fmiddleware"," selbst, wenn Sie jede Antwort exakt steuern müssen und keine Konvention umgehen wollen. Das Modul liefert Dinge, die mühsam sauber zu bauen sind. Das Einfügen des Nonce passiert in der Render-Pipeline, erreicht also auch Elemente, die das Framework erzeugt. Hashes für statische Builds stammen aus dem endgültigen HTML. Die Header-Sätze unterscheiden sich nach Ressourcentyp, mit einer vollständigen Richtlinie für HTML und einem kleineren Satz für andere Assets, und Regeln pro Route werden mit Ihrer globalen Konfiguration zusammengeführt. Das sind die Teile, die ich nicht neu schreiben würde.",{"type":137,"content":561},[562,563,565],"Handgeschriebene Middleware gewinnt an anderer Stelle. Ein paar Header und eine kleine Allowlist in ",{"tag":166,"children":564},[558]," sind leicht zu lesen, brauchen keine Modulkonventionen und fügen keine Abhängigkeit hinzu. Wenn Sie nur HSTS, eine Referrer-Policy und Frame-Optionen brauchen, schreiben Sie diese drei Header selbst.",{"type":137,"content":567},[568],"Nonce-CSP von Hand nachzubauen ist der schlechteste Ausgangspunkt. Der Nonce muss jedes Script, jeden Link und jeden Style erreichen, den das Rendering ausgibt, derselbe Wert muss im Header stehen, und statische Builds brauchen einen ganz anderen Mechanismus. Fehler zeigen sich nicht in einem Unit-Test. Sie zeigen sich als leere Seite in einem einzigen Browser. Meine Empfehlung: Nehmen Sie das Modul für die Richtlinie und schreiben Sie jede Ausnahme selbst.",{"type":148,"level":149,"id":130,"text":131},{"type":137,"content":571},[572],"Bevor Sie eine Richtlinie in einer Produktivanwendung erzwingen, würde ich diese Punkte in dieser Reihenfolge abarbeiten:",{"type":574,"ordered":319,"items":575},"list",[576,578,590,592,598,607,609,611],[577],"Betreiben Sie die Standardwerte auf jeder Seitenart und beheben Sie, was die Browser-Konsole als Verletzung meldet.",[579,580,583,584,586,587,589],"Aktivieren Sie ",{"tag":166,"children":581},[582],"contentSecurityPolicyReportOnly"," mit einem Endpunkt für ",{"tag":166,"children":585},[526]," oder ",{"tag":166,"children":588},[529]," und lesen Sie die Berichte einen vollen Release-Zyklus lang.",[591],"Prüfen Sie, welche Routen serverseitig gerendert und welche vorgerendert sind, und kontrollieren Sie das gebaute HTML auf den Nonce oder das gehashte Meta-Tag.",[593,594,597],"Laden Sie Drittanbieter-Skripte mit ",{"tag":166,"children":595},[596],"useScript"," (Nuxt 3.11 oder neuer) statt Tags von Hand einzufügen.",[599,600,603,604,606],"Tragen Sie externe Bild-Hosts in ",{"tag":166,"children":601},[602],"img-src"," und jeden API-Ursprung in ",{"tag":166,"children":605},[398]," ein, einschließlich der LLM-Endpunkte.",[608],"Prüfen Sie, dass Ihr Host Bundles nach dem Build nicht umschreibt, sonst schlagen die Integritäts-Hashes fehl.",[610],"Legen Sie den Schutz vor Brute-Force und Traffic-Volumen an den Rand, und behandeln Sie den eingebauten Limiter als zweite Schicht.",[612],"Prüfen Sie die Header in einem End-to-End-Test auf einer serverseitig gerenderten und einer vorgerenderten Seite.",{"type":137,"content":614},[615,616,620],"Das Modul ist eine gute Standardschicht, und die verbleibende Arbeit ist dieselbe wie zuvor: wissen, welche Skripte Ihre Seiten laden und welche Ursprünge Ihre App aufruft. Wenn Sie sehen möchten, welche Nuxt-Arbeit hinter diesem Artikel steht, sind meine ",{"tag":418,"to":617,"children":618},"\u002Fexpertise\u002Fvue-nuxt-developer",[619],"Vue- und Nuxt-Projekte"," ein guter Ausgangspunkt.",{"type":148,"level":149,"id":133,"text":134},{"type":574,"ordered":319,"items":623},[624,627,630,633,636,639,642,645,648,651,654,657],[625],{"tag":154,"href":37,"children":626},[36],[628],{"tag":154,"href":40,"children":629},[39],[631],{"tag":154,"href":43,"children":632},[42],[634],{"tag":154,"href":46,"children":635},[45],[637],{"tag":154,"href":49,"children":638},[48],[640],{"tag":154,"href":52,"children":641},[51],[643],{"tag":154,"href":55,"children":644},[54],[646],{"tag":154,"href":58,"children":647},[57],[649],{"tag":154,"href":61,"children":650},[60],[652],{"tag":154,"href":64,"children":653},[63],[655],{"tag":154,"href":67,"children":656},[66],[658],{"tag":154,"href":70,"children":659},[69],[661,735,791,863],{"slug":662,"published":663,"minutes":664,"category":7,"tags":665,"keywords":670,"about":682,"sources":691,"cover":728,"og":729,"expertise":730,"locales":731,"lang":76,"title":732,"description":733,"coverAlt":734},"schema-org-structured-data-b2b-shop","2026-10-17",10,[666,667,668,669,9],"Schema.org","Structured data","B2B e-commerce","Technical SEO",[671,672,673,674,675,676,677,678,679,680,681],"schema.org b2b shop","product structured data b2b","merchant listing structured data","product snippet vs merchant listing","unitpricespecification referencequantity","productgroup variants structured data","organization schema vatid","b2b prices behind login seo","json-ld nuxt schema org","merchant return policy structured data","mpn gtin structured data",[683,685,688],{"name":666,"url":684},"https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FSchema.org",{"name":686,"url":687},"JSON-LD","https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FJSON-LD",{"name":689,"url":690},"Business-to-business","https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FBusiness-to-business",[692,695,698,701,704,707,710,713,716,719,722,725],{"title":693,"url":694},"Google Search Central: Introduction to Product structured data","https:\u002F\u002Fdevelopers.google.com\u002Fsearch\u002Fdocs\u002Fappearance\u002Fstructured-data\u002Fproduct",{"title":696,"url":697},"Google Search Central: Merchant listing (Product, Offer) structured data","https:\u002F\u002Fdevelopers.google.com\u002Fsearch\u002Fdocs\u002Fappearance\u002Fstructured-data\u002Fmerchant-listing",{"title":699,"url":700},"Google Search Central: Product snippet structured data","https:\u002F\u002Fdevelopers.google.com\u002Fsearch\u002Fdocs\u002Fappearance\u002Fstructured-data\u002Fproduct-snippet",{"title":702,"url":703},"Google Search Central: Product variant structured data","https:\u002F\u002Fdevelopers.google.com\u002Fsearch\u002Fdocs\u002Fappearance\u002Fstructured-data\u002Fproduct-variants",{"title":705,"url":706},"Google Search Central: Organization structured data","https:\u002F\u002Fdevelopers.google.com\u002Fsearch\u002Fdocs\u002Fappearance\u002Fstructured-data\u002Forganization",{"title":708,"url":709},"Google Search Central: Merchant return policy structured data","https:\u002F\u002Fdevelopers.google.com\u002Fsearch\u002Fdocs\u002Fappearance\u002Fstructured-data\u002Freturn-policy",{"title":711,"url":712},"Google Search Central: General structured data guidelines","https:\u002F\u002Fdevelopers.google.com\u002Fsearch\u002Fdocs\u002Fappearance\u002Fstructured-data\u002Fsd-policies",{"title":714,"url":715},"Google Search Central: Generate structured data with JavaScript","https:\u002F\u002Fdevelopers.google.com\u002Fsearch\u002Fdocs\u002Fappearance\u002Fstructured-data\u002Fgenerate-structured-data-with-javascript",{"title":717,"url":718},"Schema.org: Offer","https:\u002F\u002Fschema.org\u002FOffer",{"title":720,"url":721},"Schema.org: UnitPriceSpecification","https:\u002F\u002Fschema.org\u002FUnitPriceSpecification",{"title":723,"url":724},"Unhead: Product schema (defineProduct)","https:\u002F\u002Funhead.unjs.io\u002Fdocs\u002Fschema-org\u002Fapi\u002Fschema\u002Fproduct",{"title":726,"url":727},"Nuxt SEO: Schema.org identity setup","https:\u002F\u002Fnuxtseo.com\u002Fdocs\u002Fschema-org\u002Fguides\u002Fsetup-identity","\u002Fimages\u002Fblog\u002Fschema-org-structured-data-b2b-shop\u002Fcover.webp","\u002Fimages\u002Fblog\u002Fschema-org-structured-data-b2b-shop\u002Fog.jpg","b2b-ecommerce-developer",[75,76,77],"Schema.org-Strukturdaten für B2B-Shops: Preise hinter Logins, Einheiten und Varianten","Produkt-Markup für B2B-Shops: Snippet oder Händlereintrag, welcher Preis, Artikelnummern, Grundpreise, Varianten, Organization und SSR in Nuxt.","Ein Produktrechteck mit dünnem Rahmen und einem kleinen Feld, das eine niedrige Wand verdeckt.",{"slug":736,"published":663,"minutes":737,"category":7,"tags":738,"keywords":743,"about":755,"sources":763,"cover":785,"og":786,"expertise":730,"locales":787,"lang":76,"title":788,"description":789,"coverAlt":790},"ai-assistant-b2b-shop-customer-support",9,[668,739,740,741,742],"AI assistant","Customer support","LLM agents","EU AI Act",[744,745,746,747,748,749,750,751,752,753,754],"ai assistant b2b shop","ai customer support b2b ecommerce","llm chatbot order status","ai agent customer service tools","chatbot liability air canada","klarna ai assistant results","human handoff chatbot design","eu ai act chatbot disclosure","owasp excessive agency","ai support resolution rate","b2b customer portal chatbot",[756,759,762],{"name":757,"url":758},"Customer service","https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FCustomer_service",{"name":760,"url":761},"Chatbot","https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FChatbot",{"name":689,"url":690},[764,767,770,773,776,779,782],{"title":765,"url":766},"Klarna: AI assistant handles two-thirds of customer service chats in its first month (press release, 2024)","https:\u002F\u002Fwww.klarna.com\u002Finternational\u002Fpress\u002Fklarna-ai-assistant-handles-two-thirds-of-customer-service-chats-in-its-first-month\u002F",{"title":768,"url":769},"Entrepreneur: Klarna is hiring customer service agents again, according to its CEO (May 2025)","https:\u002F\u002Fwww.entrepreneur.com\u002Fbusiness-news\u002Fklarna-ceo-reverses-course-by-hiring-more-humans-not-ai\u002F491396",{"title":771,"url":772},"ABA Business Law Today: BC tribunal confirms companies remain liable for information provided by AI chatbot","https:\u002F\u002Fwww.americanbar.org\u002Fgroups\u002Fbusiness_law\u002Fresources\u002Fbusiness-law-today\u002F2024-february\u002Fbc-tribunal-confirms-companies-remain-liable-information-provided-ai-chatbot\u002F",{"title":774,"url":775},"OWASP GenAI Security Project: LLM06:2025 Excessive Agency","https:\u002F\u002Fgenai.owasp.org\u002Fllmrisk\u002Fllm062025-excessive-agency\u002F",{"title":777,"url":778},"OWASP GenAI Security Project: LLM05:2025 Improper Output Handling","https:\u002F\u002Fgenai.owasp.org\u002Fllmrisk\u002Fllm052025-improper-output-handling\u002F",{"title":780,"url":781},"EU AI Act, Article 50: Transparency obligations","https:\u002F\u002Fartificialintelligenceact.eu\u002Farticle\u002F50\u002F",{"title":783,"url":784},"Intercom: Fin pricing and billable outcomes","https:\u002F\u002Ffin.ai\u002Fpricing","\u002Fimages\u002Fblog\u002Fai-assistant-b2b-shop-customer-support\u002Fcover.webp","\u002Fimages\u002Fblog\u002Fai-assistant-b2b-shop-customer-support\u002Fog.jpg",[75,76,77],"Ein KI-Assistent für den Support im B2B-Shop: Tools, Berechtigungen und die Übergabe an Menschen","Wie man einen KI-Support-Assistenten für einen B2B-Shop baut: was automatisieren, Tools im Kundenkontext, Übergabe an Menschen, AI Act und Kennzahlen.","Eine hohe Mauer mit schmalem Durchgang: Ein Pfeil führt in ein Feld mit drei Quadraten, ein zweiter nach unten zu einer Ablage.",{"slug":792,"published":663,"minutes":6,"category":7,"tags":793,"keywords":798,"about":810,"sources":820,"cover":857,"og":858,"expertise":73,"locales":859,"lang":76,"title":860,"description":861,"coverAlt":862},"vue-ai-chat-ui-streaming-accessibility",[794,9,795,796,797],"Vue","Accessibility","Streaming","AI chat",[799,800,801,802,803,804,805,806,807,808,809],"vue ai chat ui","nuxt llm streaming","sse vs fetch streaming","aria-live streaming text","accessible chat interface","abort fetch stream vue","dompurify markdown llm","role log chat","reduced motion chat ui","wcag 2.2 chat","screen reader streaming",[811,814,817],{"name":812,"url":813},"Web accessibility","https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FWeb_accessibility",{"name":815,"url":816},"Server-sent events","https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FServer-sent_events",{"name":818,"url":819},"Vue.js","https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FVue.js",[821,824,827,830,833,836,839,842,845,848,851,854],{"title":822,"url":823},"MDN: Using server-sent events","https:\u002F\u002Fdeveloper.mozilla.org\u002Fen-US\u002Fdocs\u002FWeb\u002FAPI\u002FServer-sent_events\u002FUsing_server-sent_events",{"title":825,"url":826},"MDN: AbortController","https:\u002F\u002Fdeveloper.mozilla.org\u002Fen-US\u002Fdocs\u002FWeb\u002FAPI\u002FAbortController",{"title":828,"url":829},"MDN: ReadableStream","https:\u002F\u002Fdeveloper.mozilla.org\u002Fen-US\u002Fdocs\u002FWeb\u002FAPI\u002FReadableStream",{"title":831,"url":832},"MDN: TextDecoderStream","https:\u002F\u002Fdeveloper.mozilla.org\u002Fen-US\u002Fdocs\u002FWeb\u002FAPI\u002FTextDecoderStream",{"title":834,"url":835},"MDN: ARIA log role","https:\u002F\u002Fdeveloper.mozilla.org\u002Fen-US\u002Fdocs\u002FWeb\u002FAccessibility\u002FARIA\u002FReference\u002FRoles\u002Flog_role",{"title":837,"url":838},"W3C: Understanding SC 4.1.3 Status Messages","https:\u002F\u002Fwww.w3.org\u002FWAI\u002FWCAG22\u002FUnderstanding\u002Fstatus-messages.html",{"title":840,"url":841},"W3C WAI: What's new in WCAG 2.2","https:\u002F\u002Fwww.w3.org\u002FWAI\u002Fstandards-guidelines\u002Fwcag\u002Fnew-in-22\u002F",{"title":843,"url":844},"MDN: prefers-reduced-motion","https:\u002F\u002Fdeveloper.mozilla.org\u002Fen-US\u002Fdocs\u002FWeb\u002FCSS\u002F@media\u002Fprefers-reduced-motion",{"title":846,"url":847},"DOMPurify README","https:\u002F\u002Fgithub.com\u002Fcure53\u002FDOMPurify",{"title":849,"url":850},"markdown-it README","https:\u002F\u002Fgithub.com\u002Fmarkdown-it\u002Fmarkdown-it",{"title":852,"url":853},"AI SDK docs: useChat","https:\u002F\u002Fai-sdk.dev\u002Fdocs\u002Fai-sdk-ui\u002Fchatbot",{"title":855,"url":856},"Vue docs: nextTick","https:\u002F\u002Fvuejs.org\u002Fapi\u002Fgeneral.html#nexttick","\u002Fimages\u002Fblog\u002Fvue-ai-chat-ui-streaming-accessibility\u002Fcover.webp","\u002Fimages\u002Fblog\u002Fvue-ai-chat-ui-streaming-accessibility\u002Fog.jpg",[75,76,77],"Streaming-Chat mit KI in Vue und Nuxt: von Anfang an barrierefrei","KI-Chat in Vue oder Nuxt: Fetch-Streams, Abbruch und Retry, sicheres Markdown-Rendering, aria-live-Meldungen, Tastaturnavigation und Reduced Motion.","Eine Nachrichtenkarte mit blinkendem Cursor, eine gepunktete Linie öffnet sich zu Wellen, daneben ein Haken.",{"slug":864,"published":663,"minutes":737,"category":7,"tags":865,"keywords":870,"about":882,"sources":892,"cover":925,"og":926,"expertise":73,"locales":927,"lang":76,"title":928,"description":929,"coverAlt":930},"llm-translation-pipeline-i18n",[866,867,868,794,869],"Translation","i18n","LLM","Localization",[871,872,873,874,875,876,877,878,879,880,881],"llm translation pipeline","icu messageformat placeholders","vue i18n llm translation","translation memory llm","glossary enforcement translation","german informal sie du","hungarian translation quality llm","structured output json translation","machine translation post-editing","locale file validation","cldr plural categories",[883,886,889],{"name":884,"url":885},"Internationalization and localization","https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FInternationalization_and_localization",{"name":887,"url":888},"ICU MessageFormat","https:\u002F\u002Funicode-org.github.io\u002Ficu\u002Fuserguide\u002Fformat_parse\u002Fmessages\u002F",{"name":890,"url":891},"Vue I18n","https:\u002F\u002Fvue-i18n.intlify.dev\u002F",[893,895,898,901,904,907,910,913,916,919,922],{"title":894,"url":888},"Unicode ICU User Guide: Formatting Messages",{"title":896,"url":897},"Vue I18n: Message Format Syntax","https:\u002F\u002Fvue-i18n.intlify.dev\u002Fguide\u002Fessentials\u002Fsyntax",{"title":899,"url":900},"Nuxt i18n: Getting started","https:\u002F\u002Fi18n.nuxtjs.org\u002Fdocs\u002Fgetting-started",{"title":902,"url":903},"Unicode CLDR: Plural rules","https:\u002F\u002Fcldr.unicode.org\u002Findex\u002Fcldr-spec\u002Fplural-rules",{"title":905,"url":906},"OpenAI: Structured outputs","https:\u002F\u002Fplatform.openai.com\u002Fdocs\u002Fguides\u002Fstructured-outputs",{"title":908,"url":909},"DeepL API: Glossaries","https:\u002F\u002Fdevelopers.deepl.com\u002Fdocs\u002Fapi-reference\u002Fglossaries",{"title":911,"url":912},"W3C: Localization vs. internationalization","https:\u002F\u002Fwww.w3.org\u002FInternational\u002Fquestions\u002Fqa-i18n",{"title":914,"url":915},"GNU gettext manual","https:\u002F\u002Fwww.gnu.org\u002Fsoftware\u002Fgettext\u002Fmanual\u002Fgettext.html",{"title":917,"url":918},"RFC 5646: Tags for Identifying Languages","https:\u002F\u002Fwww.rfc-editor.org\u002Frfc\u002Frfc5646",{"title":920,"url":921},"Rat für deutsche Rechtschreibung","https:\u002F\u002Fwww.rechtschreibrat.com\u002F",{"title":923,"url":924},"Microsoft Writing Style Guide","https:\u002F\u002Flearn.microsoft.com\u002Fen-us\u002Fstyle-guide\u002Fwelcome\u002F","\u002Fimages\u002Fblog\u002Fllm-translation-pipeline-i18n\u002Fcover.webp","\u002Fimages\u002Fblog\u002Fllm-translation-pipeline-i18n\u002Fog.jpg",[75,76,77],"Eine LLM-Übersetzungspipeline für i18n: Glossar, Platzhalter und Review","Produkt- und Website-Texte mit LLMs übersetzen, ohne Platzhalter, Pluralformen oder Tonalität zu beschädigen: Glossar, ICU-Nachrichten, QA-Checks, Review.","Drei Quellkarten, eine übersetzte Karte mit Glossar-Lesezeichen, dann eine geprüfte Klemmschiene.",1792337023728]