[{"data":1,"prerenderedAt":1774},["ShallowReactive",2],{"til-entries":3},[4,1226,1378,1478,1595,1691],{"id":5,"title":6,"body":7,"date":1205,"description":1206,"extension":1207,"language":1208,"meta":1209,"navigation":254,"path":1211,"seo":1212,"stem":1213,"tags":1214,"__hash__":1225},"til/til/cloudflare-pages-wrangler-bindings.md","Cloudflare Pages: Environments mit wrangler.jsonc sauber trennen",{"type":8,"value":9,"toc":1187},"minimark",[10,28,33,74,78,83,98,104,137,141,147,168,176,196,203,210,408,418,426,714,719,742,746,971,993,997,1034,1038,1047,1086,1093,1097,1177,1183],[11,12,13,14,18,19,23,24,27],"p",{},"Wenn du ein ",[15,16,17],"strong",{},"Cloudflare Pages","-Projekt mit Nuxt/Nitro betreibst und separate Datenbanken für Production und Preview willst, stehst du vor einem Problem: Cloudflare Pages unterstützt die ",[20,21,22],"code",{},"env","-Sektion in der generierten Worker-Config ",[15,25,26],{},"nicht",". Hier ist die Lösung, die wir nach einigem Trial-and-Error gefunden haben.",[29,30,32],"h2",{"id":31},"das-ziel","Das Ziel",[34,35,36,53,67],"ul",{},[37,38,39,42,43,46,47,46,50],"li",{},[15,40,41],{},"Production"," → ",[20,44,45],{},"my-app-d1",", ",[20,48,49],{},"my-app-kv",[20,51,52],{},"my-app-r2",[37,54,55,42,58,46,61,46,64],{},[15,56,57],{},"Preview",[20,59,60],{},"my-app-d1-preview",[20,62,63],{},"my-app-kv-preview",[20,65,66],{},"my-app-r2-preview",[37,68,69,70,73],{},"Alles ",[15,71,72],{},"versioniert im Repo",", nicht manuell im Dashboard gepflegt",[29,75,77],{"id":76},"die-herausforderung","Die Herausforderung",[79,80,82],"h3",{"id":81},"workers-vs-pages","Workers vs. Pages",[11,84,85,86,89,90,93,94,97],{},"Bei Cloudflare ",[15,87,88],{},"Workers"," funktioniert ",[20,91,92],{},"env.preview"," in der ",[20,95,96],{},"wrangler.toml/jsonc"," einwandfrei — Wrangler wählt automatisch das richtige Environment.",[11,99,85,100,103],{},[15,101,102],{},"Pages"," ist das anders:",[34,105,106,117,127],{},[37,107,108,111,112,114,115],{},[20,109,110],{},"wrangler pages deploy --branch=preview"," wählt ",[15,113,26],{}," automatisch ",[20,116,92],{},[37,118,119,120,123,124,126],{},"Nitro/Nuxt kopiert die gesamte ",[20,121,122],{},"wrangler.jsonc"," (inkl. ",[20,125,22],{},") in den Build-Output",[37,128,129,130,133,134,136],{},"Cloudflare Pages ",[15,131,132],{},"verweigert"," den Deploy, wenn die generierte Config eine ",[20,135,22],{},"-Sektion enthält",[79,138,140],{"id":139},"was-nicht-funktioniert","Was NICHT funktioniert",[11,142,143,146],{},[15,144,145],{},"Dashboard als Source of Truth"," (alter Ansatz):",[34,148,149,155,165],{},[37,150,151,154],{},[20,152,153],{},"pages_build_output_dir"," aus der Config entfernen → Dashboard-Bindings bleiben editierbar",[37,156,157,158,161,162,164],{},"Problem: Bindings nicht im Git, ",[20,159,160],{},"postbuild","-Hack nötig um ",[20,163,153],{}," aus dem Nitro-Output zu entfernen",[37,166,167],{},"Fragil und intransparent",[11,169,170,175],{},[15,171,172,174],{},[20,173,22],{},"-Sektion direkt nutzen"," (naiver Ansatz):",[34,177,178],{},[37,179,180,182,183,185,186],{},[20,181,122],{}," mit ",[20,184,92],{}," → Nitro kopiert alles in den Output → Cloudflare Pages lehnt den Deploy ab mit:\n",[187,188,193],"pre",{"className":189,"code":191,"language":192},[190],"language-text","Redirected configurations cannot include environments\n","text",[20,194,191],{"__ignoreMap":195},"",[29,197,199,200,202],{"id":198},"die-lösung-wranglerjsonc-postbuild-script","Die Lösung: ",[20,201,122],{}," + Postbuild-Script",[79,204,206,207,209],{"id":205},"_1-wranglerjsonc-als-source-of-truth","1. ",[20,208,122],{}," als Source of Truth",[187,211,215],{"className":212,"code":213,"language":214,"meta":195,"style":195},"language-jsonc shiki shiki-themes github-light github-dark","{\n  \"name\": \"my-app\",\n  \"pages_build_output_dir\": \"dist\",\n  \"compatibility_date\": \"2025-07-15\",\n  \"compatibility_flags\": [\"nodejs_compat\"],\n\n  // Production bindings (default)\n  \"d1_databases\": [\n    { \"binding\": \"DB\", \"database_name\": \"my-app-d1\", \"database_id\": \"prod-id-hier\" }\n  ],\n  \"kv_namespaces\": [\n    { \"binding\": \"KV\", \"id\": \"prod-kv-id-hier\" }\n  ],\n  \"r2_buckets\": [\n    { \"binding\": \"BUCKET\", \"bucket_name\": \"my-app-r2\" }\n  ],\n\n  // Preview overrides — werden vom Postbuild-Script angewendet\n  \"env\": {\n    \"preview\": {\n      \"d1_databases\": [\n        { \"binding\": \"DB\", \"database_name\": \"my-app-d1-preview\", \"database_id\": \"preview-id-hier\" }\n      ],\n      \"kv_namespaces\": [\n        { \"binding\": \"KV\", \"id\": \"preview-kv-id-hier\" }\n      ],\n      \"r2_buckets\": [\n        { \"binding\": \"BUCKET\", \"bucket_name\": \"my-app-r2-preview\" }\n      ]\n    }\n  }\n}\n","jsonc",[20,216,217,225,231,237,243,249,256,262,268,274,280,286,292,297,303,309,314,319,325,331,337,343,349,355,361,367,372,378,384,390,396,402],{"__ignoreMap":195},[218,219,222],"span",{"class":220,"line":221},"line",1,[218,223,224],{},"{\n",[218,226,228],{"class":220,"line":227},2,[218,229,230],{},"  \"name\": \"my-app\",\n",[218,232,234],{"class":220,"line":233},3,[218,235,236],{},"  \"pages_build_output_dir\": \"dist\",\n",[218,238,240],{"class":220,"line":239},4,[218,241,242],{},"  \"compatibility_date\": \"2025-07-15\",\n",[218,244,246],{"class":220,"line":245},5,[218,247,248],{},"  \"compatibility_flags\": [\"nodejs_compat\"],\n",[218,250,252],{"class":220,"line":251},6,[218,253,255],{"emptyLinePlaceholder":254},true,"\n",[218,257,259],{"class":220,"line":258},7,[218,260,261],{},"  // Production bindings (default)\n",[218,263,265],{"class":220,"line":264},8,[218,266,267],{},"  \"d1_databases\": [\n",[218,269,271],{"class":220,"line":270},9,[218,272,273],{},"    { \"binding\": \"DB\", \"database_name\": \"my-app-d1\", \"database_id\": \"prod-id-hier\" }\n",[218,275,277],{"class":220,"line":276},10,[218,278,279],{},"  ],\n",[218,281,283],{"class":220,"line":282},11,[218,284,285],{},"  \"kv_namespaces\": [\n",[218,287,289],{"class":220,"line":288},12,[218,290,291],{},"    { \"binding\": \"KV\", \"id\": \"prod-kv-id-hier\" }\n",[218,293,295],{"class":220,"line":294},13,[218,296,279],{},[218,298,300],{"class":220,"line":299},14,[218,301,302],{},"  \"r2_buckets\": [\n",[218,304,306],{"class":220,"line":305},15,[218,307,308],{},"    { \"binding\": \"BUCKET\", \"bucket_name\": \"my-app-r2\" }\n",[218,310,312],{"class":220,"line":311},16,[218,313,279],{},[218,315,317],{"class":220,"line":316},17,[218,318,255],{"emptyLinePlaceholder":254},[218,320,322],{"class":220,"line":321},18,[218,323,324],{},"  // Preview overrides — werden vom Postbuild-Script angewendet\n",[218,326,328],{"class":220,"line":327},19,[218,329,330],{},"  \"env\": {\n",[218,332,334],{"class":220,"line":333},20,[218,335,336],{},"    \"preview\": {\n",[218,338,340],{"class":220,"line":339},21,[218,341,342],{},"      \"d1_databases\": [\n",[218,344,346],{"class":220,"line":345},22,[218,347,348],{},"        { \"binding\": \"DB\", \"database_name\": \"my-app-d1-preview\", \"database_id\": \"preview-id-hier\" }\n",[218,350,352],{"class":220,"line":351},23,[218,353,354],{},"      ],\n",[218,356,358],{"class":220,"line":357},24,[218,359,360],{},"      \"kv_namespaces\": [\n",[218,362,364],{"class":220,"line":363},25,[218,365,366],{},"        { \"binding\": \"KV\", \"id\": \"preview-kv-id-hier\" }\n",[218,368,370],{"class":220,"line":369},26,[218,371,354],{},[218,373,375],{"class":220,"line":374},27,[218,376,377],{},"      \"r2_buckets\": [\n",[218,379,381],{"class":220,"line":380},28,[218,382,383],{},"        { \"binding\": \"BUCKET\", \"bucket_name\": \"my-app-r2-preview\" }\n",[218,385,387],{"class":220,"line":386},29,[218,388,389],{},"      ]\n",[218,391,393],{"class":220,"line":392},30,[218,394,395],{},"    }\n",[218,397,399],{"class":220,"line":398},31,[218,400,401],{},"  }\n",[218,403,405],{"class":220,"line":404},32,[218,406,407],{},"}\n",[11,409,410,411,413,414,417],{},"Die ",[20,412,22],{},"-Sektion dient als ",[15,415,416],{},"Referenz und wird vom Postbuild-Script ausgewertet"," — Cloudflare Pages sieht sie nie.",[79,419,421,422,425],{"id":420},"_2-postbuild-script-scriptspostbuildmjs","2. Postbuild-Script (",[20,423,424],{},"scripts/postbuild.mjs",")",[187,427,431],{"className":428,"code":429,"language":430,"meta":195,"style":195},"language-js shiki shiki-themes github-light github-dark","/**\n * Cloudflare Pages unterstützt keine `env`-Sektion in der Worker-Config.\n * Dieses Script wendet die richtigen Bindings an und entfernt `env`.\n *\n * Usage: node scripts/postbuild.mjs [preview]\n */\nimport { readFileSync, writeFileSync } from 'node:fs'\n\nconst env = process.argv[2] // 'preview' oder undefined (= production)\nconst path = 'dist/_worker.js/wrangler.json'\nconst config = JSON.parse(readFileSync(path, 'utf8'))\n\nif (env && config.env?.[env]) {\n  const envConfig = config.env[env]\n  for (const [key, value] of Object.entries(envConfig)) {\n    config[key] = value\n  }\n  console.log(`✔ Applied \"${env}\" bindings`)\n}\n\ndelete config.env\nwriteFileSync(path, JSON.stringify(config, null, 2))\nconsole.log('✔ Ready for deploy')\n","js",[20,432,433,439,444,449,454,459,464,481,485,509,521,555,559,573,586,621,632,636,657,661,665,673,700],{"__ignoreMap":195},[218,434,435],{"class":220,"line":221},[218,436,438],{"class":437},"sJ8bj","/**\n",[218,440,441],{"class":220,"line":227},[218,442,443],{"class":437}," * Cloudflare Pages unterstützt keine `env`-Sektion in der Worker-Config.\n",[218,445,446],{"class":220,"line":233},[218,447,448],{"class":437}," * Dieses Script wendet die richtigen Bindings an und entfernt `env`.\n",[218,450,451],{"class":220,"line":239},[218,452,453],{"class":437}," *\n",[218,455,456],{"class":220,"line":245},[218,457,458],{"class":437}," * Usage: node scripts/postbuild.mjs [preview]\n",[218,460,461],{"class":220,"line":251},[218,462,463],{"class":437}," */\n",[218,465,466,470,474,477],{"class":220,"line":258},[218,467,469],{"class":468},"szBVR","import",[218,471,473],{"class":472},"sVt8B"," { readFileSync, writeFileSync } ",[218,475,476],{"class":468},"from",[218,478,480],{"class":479},"sZZnC"," 'node:fs'\n",[218,482,483],{"class":220,"line":264},[218,484,255],{"emptyLinePlaceholder":254},[218,486,487,490,494,497,500,503,506],{"class":220,"line":270},[218,488,489],{"class":468},"const",[218,491,493],{"class":492},"sj4cs"," env",[218,495,496],{"class":468}," =",[218,498,499],{"class":472}," process.argv[",[218,501,502],{"class":492},"2",[218,504,505],{"class":472},"] ",[218,507,508],{"class":437},"// 'preview' oder undefined (= production)\n",[218,510,511,513,516,518],{"class":220,"line":276},[218,512,489],{"class":468},[218,514,515],{"class":492}," path",[218,517,496],{"class":468},[218,519,520],{"class":479}," 'dist/_worker.js/wrangler.json'\n",[218,522,523,525,528,530,533,536,540,543,546,549,552],{"class":220,"line":282},[218,524,489],{"class":468},[218,526,527],{"class":492}," config",[218,529,496],{"class":468},[218,531,532],{"class":492}," JSON",[218,534,535],{"class":472},".",[218,537,539],{"class":538},"sScJk","parse",[218,541,542],{"class":472},"(",[218,544,545],{"class":538},"readFileSync",[218,547,548],{"class":472},"(path, ",[218,550,551],{"class":479},"'utf8'",[218,553,554],{"class":472},"))\n",[218,556,557],{"class":220,"line":288},[218,558,255],{"emptyLinePlaceholder":254},[218,560,561,564,567,570],{"class":220,"line":294},[218,562,563],{"class":468},"if",[218,565,566],{"class":472}," (env ",[218,568,569],{"class":468},"&&",[218,571,572],{"class":472}," config.env?.[env]) {\n",[218,574,575,578,581,583],{"class":220,"line":299},[218,576,577],{"class":468},"  const",[218,579,580],{"class":492}," envConfig",[218,582,496],{"class":468},[218,584,585],{"class":472}," config.env[env]\n",[218,587,588,591,594,596,599,602,604,607,609,612,615,618],{"class":220,"line":305},[218,589,590],{"class":468},"  for",[218,592,593],{"class":472}," (",[218,595,489],{"class":468},[218,597,598],{"class":472}," [",[218,600,601],{"class":492},"key",[218,603,46],{"class":472},[218,605,606],{"class":492},"value",[218,608,505],{"class":472},[218,610,611],{"class":468},"of",[218,613,614],{"class":472}," Object.",[218,616,617],{"class":538},"entries",[218,619,620],{"class":472},"(envConfig)) {\n",[218,622,623,626,629],{"class":220,"line":311},[218,624,625],{"class":472},"    config[key] ",[218,627,628],{"class":468},"=",[218,630,631],{"class":472}," value\n",[218,633,634],{"class":220,"line":316},[218,635,401],{"class":472},[218,637,638,641,644,646,649,651,654],{"class":220,"line":321},[218,639,640],{"class":472},"  console.",[218,642,643],{"class":538},"log",[218,645,542],{"class":472},[218,647,648],{"class":479},"`✔ Applied \"${",[218,650,22],{"class":472},[218,652,653],{"class":479},"}\" bindings`",[218,655,656],{"class":472},")\n",[218,658,659],{"class":220,"line":327},[218,660,407],{"class":472},[218,662,663],{"class":220,"line":333},[218,664,255],{"emptyLinePlaceholder":254},[218,666,667,670],{"class":220,"line":339},[218,668,669],{"class":468},"delete",[218,671,672],{"class":472}," config.env\n",[218,674,675,678,680,683,685,688,691,694,696,698],{"class":220,"line":345},[218,676,677],{"class":538},"writeFileSync",[218,679,548],{"class":472},[218,681,682],{"class":492},"JSON",[218,684,535],{"class":472},[218,686,687],{"class":538},"stringify",[218,689,690],{"class":472},"(config, ",[218,692,693],{"class":492},"null",[218,695,46],{"class":472},[218,697,502],{"class":492},[218,699,554],{"class":472},[218,701,702,705,707,709,712],{"class":220,"line":351},[218,703,704],{"class":472},"console.",[218,706,643],{"class":538},[218,708,542],{"class":472},[218,710,711],{"class":479},"'✔ Ready for deploy'",[218,713,656],{"class":472},[11,715,716],{},[15,717,718],{},"Was passiert:",[34,720,721,730],{},[37,722,723,726,727,729],{},[15,724,725],{},"Ohne Argument"," (Production): ",[20,728,22],{}," wird entfernt, Root-Bindings bleiben → Prod-Deploy",[37,731,732,738,739,741],{},[15,733,734,735],{},"Mit ",[20,736,737],{},"preview",": Preview-Bindings überschreiben die Root-Bindings, ",[20,740,22],{}," wird entfernt → Preview-Deploy",[79,743,745],{"id":744},"_3-taskfileyml-für-saubere-workflows","3. Taskfile.yml für saubere Workflows",[187,747,751],{"className":748,"code":749,"language":750,"meta":195,"style":195},"language-yaml shiki shiki-themes github-light github-dark","version: '3'\n\ntasks:\n  build:\n    desc: Build Nuxt app\n    cmds: [bunx nuxi build]\n\n  deploy:\n    desc: Build & deploy to production\n    cmds:\n      - task: build\n      - node scripts/postbuild.mjs\n      - bunx wrangler pages deploy dist --project-name=my-app --branch=main\n\n  deploy:preview:\n    desc: Build & deploy to preview\n    cmds:\n      - task: build\n      - node scripts/postbuild.mjs preview\n      - bunx wrangler pages deploy dist --project-name=my-app --branch=preview\n\n  deploy:all:\n    desc: Deploy to both environments\n    cmds:\n      - task: build\n      - node scripts/postbuild.mjs\n      - bunx wrangler pages deploy dist --project-name=my-app --branch=main\n      - node scripts/postbuild.mjs preview\n      - bunx wrangler pages deploy dist --project-name=my-app --branch=preview\n","yaml",[20,752,753,765,769,777,784,794,808,812,819,828,834,847,854,861,865,872,881,887,897,904,911,915,922,931,937,947,953,959,965],{"__ignoreMap":195},[218,754,755,759,762],{"class":220,"line":221},[218,756,758],{"class":757},"s9eBZ","version",[218,760,761],{"class":472},": ",[218,763,764],{"class":479},"'3'\n",[218,766,767],{"class":220,"line":227},[218,768,255],{"emptyLinePlaceholder":254},[218,770,771,774],{"class":220,"line":233},[218,772,773],{"class":757},"tasks",[218,775,776],{"class":472},":\n",[218,778,779,782],{"class":220,"line":239},[218,780,781],{"class":757},"  build",[218,783,776],{"class":472},[218,785,786,789,791],{"class":220,"line":245},[218,787,788],{"class":757},"    desc",[218,790,761],{"class":472},[218,792,793],{"class":479},"Build Nuxt app\n",[218,795,796,799,802,805],{"class":220,"line":251},[218,797,798],{"class":757},"    cmds",[218,800,801],{"class":472},": [",[218,803,804],{"class":479},"bunx nuxi build",[218,806,807],{"class":472},"]\n",[218,809,810],{"class":220,"line":258},[218,811,255],{"emptyLinePlaceholder":254},[218,813,814,817],{"class":220,"line":264},[218,815,816],{"class":757},"  deploy",[218,818,776],{"class":472},[218,820,821,823,825],{"class":220,"line":270},[218,822,788],{"class":757},[218,824,761],{"class":472},[218,826,827],{"class":479},"Build & deploy to production\n",[218,829,830,832],{"class":220,"line":276},[218,831,798],{"class":757},[218,833,776],{"class":472},[218,835,836,839,842,844],{"class":220,"line":282},[218,837,838],{"class":472},"      - ",[218,840,841],{"class":757},"task",[218,843,761],{"class":472},[218,845,846],{"class":479},"build\n",[218,848,849,851],{"class":220,"line":288},[218,850,838],{"class":472},[218,852,853],{"class":479},"node scripts/postbuild.mjs\n",[218,855,856,858],{"class":220,"line":294},[218,857,838],{"class":472},[218,859,860],{"class":479},"bunx wrangler pages deploy dist --project-name=my-app --branch=main\n",[218,862,863],{"class":220,"line":299},[218,864,255],{"emptyLinePlaceholder":254},[218,866,867,870],{"class":220,"line":305},[218,868,869],{"class":757},"  deploy:preview",[218,871,776],{"class":472},[218,873,874,876,878],{"class":220,"line":311},[218,875,788],{"class":757},[218,877,761],{"class":472},[218,879,880],{"class":479},"Build & deploy to preview\n",[218,882,883,885],{"class":220,"line":316},[218,884,798],{"class":757},[218,886,776],{"class":472},[218,888,889,891,893,895],{"class":220,"line":321},[218,890,838],{"class":472},[218,892,841],{"class":757},[218,894,761],{"class":472},[218,896,846],{"class":479},[218,898,899,901],{"class":220,"line":327},[218,900,838],{"class":472},[218,902,903],{"class":479},"node scripts/postbuild.mjs preview\n",[218,905,906,908],{"class":220,"line":333},[218,907,838],{"class":472},[218,909,910],{"class":479},"bunx wrangler pages deploy dist --project-name=my-app --branch=preview\n",[218,912,913],{"class":220,"line":339},[218,914,255],{"emptyLinePlaceholder":254},[218,916,917,920],{"class":220,"line":345},[218,918,919],{"class":757},"  deploy:all",[218,921,776],{"class":472},[218,923,924,926,928],{"class":220,"line":351},[218,925,788],{"class":757},[218,927,761],{"class":472},[218,929,930],{"class":479},"Deploy to both environments\n",[218,932,933,935],{"class":220,"line":357},[218,934,798],{"class":757},[218,936,776],{"class":472},[218,938,939,941,943,945],{"class":220,"line":363},[218,940,838],{"class":472},[218,942,841],{"class":757},[218,944,761],{"class":472},[218,946,846],{"class":479},[218,948,949,951],{"class":220,"line":369},[218,950,838],{"class":472},[218,952,853],{"class":479},[218,954,955,957],{"class":220,"line":374},[218,956,838],{"class":472},[218,958,860],{"class":479},[218,960,961,963],{"class":220,"line":380},[218,962,838],{"class":472},[218,964,903],{"class":479},[218,966,967,969],{"class":220,"line":386},[218,968,838],{"class":472},[218,970,910],{"class":479},[11,972,973,980,981,984,985,988,989,992],{},[15,974,975,976,979],{},"Wichtig bei ",[20,977,978],{},"deploy:all",":"," Es wird nur ",[15,982,983],{},"einmal"," gebaut. Das Postbuild-Script modifiziert nur die generierte ",[20,986,987],{},"wrangler.json"," im ",[20,990,991],{},"dist/","-Ordner — das geht schnell und erfordert keinen Rebuild.",[29,994,996],{"id":995},"deploy-workflow","Deploy-Workflow",[187,998,1002],{"className":999,"code":1000,"language":1001,"meta":195,"style":195},"language-bash shiki shiki-themes github-light github-dark","task deploy           # Production\ntask deploy:preview   # Preview\ntask deploy:all       # Beide\n","bash",[20,1003,1004,1014,1024],{"__ignoreMap":195},[218,1005,1006,1008,1011],{"class":220,"line":221},[218,1007,841],{"class":538},[218,1009,1010],{"class":479}," deploy",[218,1012,1013],{"class":437},"           # Production\n",[218,1015,1016,1018,1021],{"class":220,"line":227},[218,1017,841],{"class":538},[218,1019,1020],{"class":479}," deploy:preview",[218,1022,1023],{"class":437},"   # Preview\n",[218,1025,1026,1028,1031],{"class":220,"line":233},[218,1027,841],{"class":538},[218,1029,1030],{"class":479}," deploy:all",[218,1032,1033],{"class":437},"       # Beide\n",[29,1035,1037],{"id":1036},"secrets","Secrets",[11,1039,1040,1041,1043,1044,1046],{},"Secrets (API-Keys, Auth-Secrets) gehören ",[15,1042,26],{}," in die ",[20,1045,122],{},". Sie werden pro Environment im Cloudflare Dashboard gesetzt:",[187,1048,1050],{"className":999,"code":1049,"language":1001,"meta":195,"style":195},"# Oder via CLI:\necho \"dein-secret\" | wrangler pages secret put SECRET_NAME --project-name=my-app\n",[20,1051,1052,1057],{"__ignoreMap":195},[218,1053,1054],{"class":220,"line":221},[218,1055,1056],{"class":437},"# Oder via CLI:\n",[218,1058,1059,1062,1065,1068,1071,1074,1077,1080,1083],{"class":220,"line":227},[218,1060,1061],{"class":492},"echo",[218,1063,1064],{"class":479}," \"dein-secret\"",[218,1066,1067],{"class":468}," |",[218,1069,1070],{"class":538}," wrangler",[218,1072,1073],{"class":479}," pages",[218,1075,1076],{"class":479}," secret",[218,1078,1079],{"class":479}," put",[218,1081,1082],{"class":479}," SECRET_NAME",[218,1084,1085],{"class":492}," --project-name=my-app\n",[11,1087,1088,1089],{},"Im Dashboard: ",[1090,1091,1092],"em",{},"Workers & Pages → Projekt → Settings → Environment Variables → Production/Preview wählen",[29,1094,1096],{"id":1095},"fazit","Fazit",[1098,1099,1100,1116],"table",{},[1101,1102,1103],"thead",{},[1104,1105,1106,1110,1113],"tr",{},[1107,1108,1109],"th",{},"Aspekt",[1107,1111,1112],{},"Alter Ansatz (Dashboard)",[1107,1114,1115],{},"Neuer Ansatz (wrangler.jsonc)",[1117,1118,1119,1131,1142,1153,1162],"tbody",{},[1104,1120,1121,1125,1128],{},[1122,1123,1124],"td",{},"Source of Truth",[1122,1126,1127],{},"Dashboard",[1122,1129,1130],{},"Git-Repo",[1104,1132,1133,1136,1139],{},[1122,1134,1135],{},"Versioniert",[1122,1137,1138],{},"❌",[1122,1140,1141],{},"✅",[1104,1143,1144,1147,1150],{},[1122,1145,1146],{},"Environment-Trennung",[1122,1148,1149],{},"Manuell im Dashboard",[1122,1151,1152],{},"Automatisch via Postbuild",[1104,1154,1155,1158,1160],{},[1122,1156,1157],{},"Reproduzierbar",[1122,1159,1138],{},[1122,1161,1141],{},[1104,1163,1164,1167,1172],{},[1122,1165,1166],{},"Workaround nötig",[1122,1168,1169,1171],{},[20,1170,153],{}," entfernen",[1122,1173,1174,1176],{},[20,1175,22],{}," strippen",[11,1178,1179,1180,1182],{},"Der Postbuild-Schritt ist ein Workaround für eine Cloudflare Pages Limitation — kein Hack. Sobald Cloudflare Pages ",[20,1181,22],{},"-Sektionen nativ unterstützt, kann das Script einfach gelöscht werden.",[1184,1185,1186],"style",{},"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);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}",{"title":195,"searchDepth":227,"depth":227,"links":1188},[1189,1190,1194,1202,1203,1204],{"id":31,"depth":227,"text":32},{"id":76,"depth":227,"text":77,"children":1191},[1192,1193],{"id":81,"depth":233,"text":82},{"id":139,"depth":233,"text":140},{"id":198,"depth":227,"text":1195,"children":1196},"Die Lösung: wrangler.jsonc + Postbuild-Script",[1197,1199,1201],{"id":205,"depth":233,"text":1198},"1. wrangler.jsonc als Source of Truth",{"id":420,"depth":233,"text":1200},"2. Postbuild-Script (scripts/postbuild.mjs)",{"id":744,"depth":233,"text":745},{"id":995,"depth":227,"text":996},{"id":1036,"depth":227,"text":1037},{"id":1095,"depth":227,"text":1096},"2025-01-29","Wenn du ein Cloudflare Pages-Projekt mit Nuxt/Nitro betreibst und separate Datenbanken für Production und Preview willst, stehst du vor einem Problem: Cloudflare Pages unterstützt die env-Sektion in der generierten Worker-Config nicht. Hier ist die Lösung, die wir nach einigem Trial-and-Error gefunden haben.","md","de",{"updated":1210},"2026-01-30","/til/cloudflare-pages-wrangler-bindings",{"title":6,"description":1206},"til/cloudflare-pages-wrangler-bindings",[1215,1216,1217,1218,1219,1220,1221,1222,1223,1224],"cloudflare","pages","wrangler","d1","kv","r2","bindings","deployment","nuxt","nitro","sMFnJSOTGTxyLELgnOxR742lm0xiEpgVNMgpPx7u9lo",{"id":1227,"title":1228,"body":1229,"date":1366,"description":1367,"extension":1207,"language":1208,"meta":1368,"navigation":254,"path":1369,"seo":1370,"stem":1371,"tags":1372,"__hash__":1377},"til/til/absolute-positioned-decorations.md","Dekorative Hintergründe ohne Layout-Chaos",{"type":8,"value":1230,"toc":1364},[1231,1245,1280,1286,1346,1361],[11,1232,1233,1236,1237,1240,1241,1244],{},[15,1234,1235],{},"Problem:"," Du willst einen Kreis hinter Text — aber ",[20,1238,1239],{},"padding"," und ",[20,1242,1243],{},"background"," zerstören das Spacing.",[187,1246,1250],{"className":1247,"code":1248,"language":1249,"meta":195,"style":195},"language-html shiki shiki-themes github-light github-dark","\u003C!-- Kaputt: Buchstaben werden auseinandergerissen -->\n\u003Cspan class=\"bg-error/20 rounded-full px-2\">ai\u003C/span>\n","html",[20,1251,1252,1257],{"__ignoreMap":195},[218,1253,1254],{"class":220,"line":221},[218,1255,1256],{"class":437},"\u003C!-- Kaputt: Buchstaben werden auseinandergerissen -->\n",[218,1258,1259,1262,1264,1267,1269,1272,1275,1277],{"class":220,"line":227},[218,1260,1261],{"class":472},"\u003C",[218,1263,218],{"class":757},[218,1265,1266],{"class":538}," class",[218,1268,628],{"class":472},[218,1270,1271],{"class":479},"\"bg-error/20 rounded-full px-2\"",[218,1273,1274],{"class":472},">ai\u003C/",[218,1276,218],{"class":757},[218,1278,1279],{"class":472},">\n",[11,1281,1282,1285],{},[15,1283,1284],{},"Lösung:"," Absolute Positionierung mit negativem z-index:",[187,1287,1289],{"className":1247,"code":1288,"language":1249,"meta":195,"style":195},"\u003Cspan class=\"relative\">\n  \u003Cspan class=\"absolute -inset-x-2 -inset-y-0.5 \n               bg-error/20 rounded-full -z-10\">\u003C/span>\n  ai\n\u003C/span>\n",[20,1290,1291,1306,1320,1332,1337],{"__ignoreMap":195},[218,1292,1293,1295,1297,1299,1301,1304],{"class":220,"line":221},[218,1294,1261],{"class":472},[218,1296,218],{"class":757},[218,1298,1266],{"class":538},[218,1300,628],{"class":472},[218,1302,1303],{"class":479},"\"relative\"",[218,1305,1279],{"class":472},[218,1307,1308,1311,1313,1315,1317],{"class":220,"line":227},[218,1309,1310],{"class":472},"  \u003C",[218,1312,218],{"class":757},[218,1314,1266],{"class":538},[218,1316,628],{"class":472},[218,1318,1319],{"class":479},"\"absolute -inset-x-2 -inset-y-0.5 \n",[218,1321,1322,1325,1328,1330],{"class":220,"line":233},[218,1323,1324],{"class":479},"               bg-error/20 rounded-full -z-10\"",[218,1326,1327],{"class":472},">\u003C/",[218,1329,218],{"class":757},[218,1331,1279],{"class":472},[218,1333,1334],{"class":220,"line":239},[218,1335,1336],{"class":472},"  ai\n",[218,1338,1339,1342,1344],{"class":220,"line":245},[218,1340,1341],{"class":472},"\u003C/",[218,1343,218],{"class":757},[218,1345,1279],{"class":472},[11,1347,1348,1349,1352,1353,1356,1357,1360],{},"Der Hintergrund ist jetzt ",[15,1350,1351],{},"aus dem Textfluss genommen",". ",[20,1354,1355],{},"-inset-x-2"," erweitert ihn über die Textbreite hinaus. ",[20,1358,1359],{},"-z-10"," schiebt ihn hinter den Text. Clean.",[1184,1362,1363],{},"html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}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);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":195,"searchDepth":227,"depth":227,"links":1365},[],"2025-01-28","Problem: Du willst einen Kreis hinter Text — aber padding und background zerstören das Spacing.",{},"/til/absolute-positioned-decorations",{"title":1228,"description":1367},"til/absolute-positioned-decorations",[1373,1374,1375,1376],"css","tailwind","layout","design","QD049rU-iTGppge_DXPHhb-5wbCKO40ciP07pYP82cI",{"id":1379,"title":1380,"body":1381,"date":1366,"description":1468,"extension":1207,"language":1208,"meta":1469,"navigation":254,"path":1470,"seo":1471,"stem":1472,"tags":1473,"__hash__":1477},"til/til/better-auth-session-cache.md","better-auth Session-Cache umgehen",{"type":8,"value":1382,"toc":1466},[1383,1389,1394,1403,1458,1463],[11,1384,1385,1386,535],{},"Wenn du User-Daten direkt in der DB änderst (z.B. via Admin-Panel), aktualisiert sich die better-auth Session ",[15,1387,1388],{},"nicht automatisch",[11,1390,1391,1393],{},[15,1392,1235],{}," User ändert seinen Namen → Navbar zeigt noch den alten.",[11,1395,1396,1398,1399,1402],{},[15,1397,1284],{}," Den lokalen State direkt updaten statt ",[20,1400,1401],{},"fetchSession()"," zu rufen:",[187,1404,1408],{"className":1405,"code":1406,"language":1407,"meta":195,"style":195},"language-typescript shiki shiki-themes github-light github-dark","// Nach dem API-Call\nif (isSelf(selectedUser)) {\n  currentUser.value = { \n    ...currentUser.value, \n    name: form.name \n  }\n}\n","typescript",[20,1409,1410,1415,1427,1437,1445,1450,1454],{"__ignoreMap":195},[218,1411,1412],{"class":220,"line":221},[218,1413,1414],{"class":437},"// Nach dem API-Call\n",[218,1416,1417,1419,1421,1424],{"class":220,"line":227},[218,1418,563],{"class":468},[218,1420,593],{"class":472},[218,1422,1423],{"class":538},"isSelf",[218,1425,1426],{"class":472},"(selectedUser)) {\n",[218,1428,1429,1432,1434],{"class":220,"line":233},[218,1430,1431],{"class":472},"  currentUser.value ",[218,1433,628],{"class":468},[218,1435,1436],{"class":472}," { \n",[218,1438,1439,1442],{"class":220,"line":239},[218,1440,1441],{"class":468},"    ...",[218,1443,1444],{"class":472},"currentUser.value, \n",[218,1446,1447],{"class":220,"line":245},[218,1448,1449],{"class":472},"    name: form.name \n",[218,1451,1452],{"class":220,"line":251},[218,1453,401],{"class":472},[218,1455,1456],{"class":220,"line":258},[218,1457,407],{"class":472},[11,1459,1460,1462],{},[20,1461,1401],{}," liest aus dem Session-Cache — der weiß nichts von deinem direkten DB-Update. Der lokale Vue-State ist reaktiv und sofort sichtbar.",[1184,1464,1465],{},"html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}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);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":195,"searchDepth":227,"depth":227,"links":1467},[],"Wenn du User-Daten direkt in der DB änderst (z.B. via Admin-Panel), aktualisiert sich die better-auth Session nicht automatisch.",{},"/til/better-auth-session-cache",{"title":1380,"description":1468},"til/better-auth-session-cache",[1223,1474,1475,1476],"better-auth","session","vue","YmDPhmMmcdrhMubmIqz14w3nnX-5appVqfpd0npkcyI",{"id":1479,"title":1480,"body":1481,"date":1366,"description":1587,"extension":1207,"language":1208,"meta":1588,"navigation":254,"path":1589,"seo":1590,"stem":1591,"tags":1592,"__hash__":1594},"til/til/dynamic-email-urls.md","E-Mail Links dynamisch aus Request-URL ableiten",{"type":8,"value":1482,"toc":1585},[1483,1488,1493,1530,1535,1575,1582],[11,1484,1485,1487],{},[15,1486,1235],{}," Preview-Deployment schickt E-Mails mit Links auf Production — wo das Feature noch gar nicht existiert.",[11,1489,1490],{},[15,1491,1492],{},"Falsch:",[187,1494,1496],{"className":1405,"code":1495,"language":1407,"meta":195,"style":195},"const loginUrl = `${process.env.BASE_URL}/login`\n// → immer intellibrain.ch, auch auf Preview\n",[20,1497,1498,1525],{"__ignoreMap":195},[218,1499,1500,1502,1505,1507,1510,1513,1515,1517,1519,1522],{"class":220,"line":221},[218,1501,489],{"class":468},[218,1503,1504],{"class":492}," loginUrl",[218,1506,496],{"class":468},[218,1508,1509],{"class":479}," `${",[218,1511,1512],{"class":472},"process",[218,1514,535],{"class":479},[218,1516,22],{"class":472},[218,1518,535],{"class":479},[218,1520,1521],{"class":492},"BASE_URL",[218,1523,1524],{"class":479},"}/login`\n",[218,1526,1527],{"class":220,"line":227},[218,1528,1529],{"class":437},"// → immer intellibrain.ch, auch auf Preview\n",[11,1531,1532],{},[15,1533,1534],{},"Richtig:",[187,1536,1538],{"className":1405,"code":1537,"language":1407,"meta":195,"style":195},"const origin = getRequestURL(event).origin\nconst loginUrl = `${origin}/login`\n// → feature-branch.intellibrain.pages.dev ✓\n",[20,1539,1540,1555,1570],{"__ignoreMap":195},[218,1541,1542,1544,1547,1549,1552],{"class":220,"line":221},[218,1543,489],{"class":468},[218,1545,1546],{"class":492}," origin",[218,1548,496],{"class":468},[218,1550,1551],{"class":538}," getRequestURL",[218,1553,1554],{"class":472},"(event).origin\n",[218,1556,1557,1559,1561,1563,1565,1568],{"class":220,"line":227},[218,1558,489],{"class":468},[218,1560,1504],{"class":492},[218,1562,496],{"class":468},[218,1564,1509],{"class":479},[218,1566,1567],{"class":472},"origin",[218,1569,1524],{"class":479},[218,1571,1572],{"class":220,"line":233},[218,1573,1574],{"class":437},"// → feature-branch.intellibrain.pages.dev ✓\n",[11,1576,1577,1578,1581],{},"Nitro's ",[20,1579,1580],{},"getRequestURL(event)"," gibt dir die tatsächliche Request-URL. Funktioniert auf localhost, Preview und Production — ohne Environment-Variablen jonglieren.",[1184,1583,1584],{},"html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}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);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}",{"title":195,"searchDepth":227,"depth":227,"links":1586},[],"Problem: Preview-Deployment schickt E-Mails mit Links auf Production — wo das Feature noch gar nicht existiert.",{},"/til/dynamic-email-urls",{"title":1480,"description":1587},"til/dynamic-email-urls",[1223,1224,1593,1215],"email","unU7PXl1Vq6UKPb1M-4qR_bVBsaMrxNu8r5mzLqOUiY",{"id":1596,"title":1597,"body":1598,"date":1679,"description":1680,"extension":1207,"language":1208,"meta":1681,"navigation":254,"path":1682,"seo":1683,"stem":1684,"tags":1685,"__hash__":1690},"til/til/clawdbot-ai-agent.md","Clawdbot macht Claude zum echten Agenten",{"type":8,"value":1599,"toc":1677},[1600,1606,1611,1625,1631,1658,1674],[11,1601,1602,1605],{},[15,1603,1604],{},"Clawdbot"," ist ein Open-Source Gateway, das Claude (Anthropic) in einen vollwertigen AI-Agenten verwandelt.",[11,1607,1608],{},[15,1609,1610],{},"Was es kann:",[34,1612,1613,1616,1619,1622],{},[37,1614,1615],{},"📱 Multi-Channel: Telegram, Discord, Slack, WhatsApp, Signal",[37,1617,1618],{},"🛠️ Tool-Zugriff: Shell, Browser, Dateien, Cron-Jobs",[37,1620,1621],{},"🧠 Persistente Memory via Markdown-Files",[37,1623,1624],{},"⏰ Proaktive Heartbeats & Reminders",[11,1626,1627,1630],{},[15,1628,1629],{},"Der Trick:"," Claude bekommt Zugriff auf echte Tools (exec, browser, nodes) und kann damit autonom Aufgaben erledigen — nicht nur chatten.",[187,1632,1634],{"className":999,"code":1633,"language":1001,"meta":195,"style":195},"npm install -g clawdbot\nclawdbot init\n",[20,1635,1636,1650],{"__ignoreMap":195},[218,1637,1638,1641,1644,1647],{"class":220,"line":221},[218,1639,1640],{"class":538},"npm",[218,1642,1643],{"class":479}," install",[218,1645,1646],{"class":492}," -g",[218,1648,1649],{"class":479}," clawdbot\n",[218,1651,1652,1655],{"class":220,"line":227},[218,1653,1654],{"class":538},"clawdbot",[218,1656,1657],{"class":479}," init\n",[11,1659,1660,1661,1668,1669],{},"→ ",[1662,1663,1667],"a",{"href":1664,"rel":1665},"https://docs.clawd.bot",[1666],"nofollow","docs.clawd.bot"," | ",[1662,1670,1673],{"href":1671,"rel":1672},"https://github.com/clawdbot/clawdbot",[1666],"GitHub",[1184,1675,1676],{},"html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}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);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":195,"searchDepth":227,"depth":227,"links":1678},[],"2025-01-27","Clawdbot ist ein Open-Source Gateway, das Claude (Anthropic) in einen vollwertigen AI-Agenten verwandelt.",{},"/til/clawdbot-ai-agent",{"title":1597,"description":1680},"til/clawdbot-ai-agent",[1686,1687,1688,1689],"ai","agents","claude","automation","p5zOmPF-Ys0yUqcLKB4xAfmkyA6afEPu9BDS6Sdtcj8",{"id":1692,"title":1693,"body":1694,"date":1679,"description":1698,"extension":1207,"language":1208,"meta":1767,"navigation":254,"path":1768,"seo":1769,"stem":1770,"tags":1771,"__hash__":1773},"til/til/nuxt-content-collections.md","Nuxt Content Collections sind mächtig",{"type":8,"value":1695,"toc":1765},[1696,1699,1755,1762],[11,1697,1698],{},"Heute gelernt: Mit Nuxt Content 3 kann man mehrere Collections definieren, jede mit eigenem Schema.",[187,1700,1702],{"className":1405,"code":1701,"language":1407,"meta":195,"style":195},"export const collections = {\n  blog: defineCollection({ ... }),\n  til: defineCollection({ ... })\n}\n",[20,1703,1704,1720,1737,1751],{"__ignoreMap":195},[218,1705,1706,1709,1712,1715,1717],{"class":220,"line":221},[218,1707,1708],{"class":468},"export",[218,1710,1711],{"class":468}," const",[218,1713,1714],{"class":492}," collections",[218,1716,496],{"class":468},[218,1718,1719],{"class":472}," {\n",[218,1721,1722,1725,1728,1731,1734],{"class":220,"line":227},[218,1723,1724],{"class":472},"  blog: ",[218,1726,1727],{"class":538},"defineCollection",[218,1729,1730],{"class":472},"({ ",[218,1732,1733],{"class":468},"...",[218,1735,1736],{"class":472}," }),\n",[218,1738,1739,1742,1744,1746,1748],{"class":220,"line":233},[218,1740,1741],{"class":472},"  til: ",[218,1743,1727],{"class":538},[218,1745,1730],{"class":472},[218,1747,1733],{"class":468},[218,1749,1750],{"class":472}," })\n",[218,1752,1753],{"class":220,"line":239},[218,1754,407],{"class":472},[11,1756,1757,1758,1761],{},"Jede Collection kann eigene Felder haben und wird separat abgefragt mit ",[20,1759,1760],{},"queryCollection('til')",". Super für verschiedene Content-Typen auf einer Site!",[1184,1763,1764],{},"html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}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);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":195,"searchDepth":227,"depth":227,"links":1766},[],{},"/til/nuxt-content-collections",{"title":1693,"description":1698},"til/nuxt-content-collections",[1223,1476,1772],"content","_hpVV3BWlxHfa6jtKsM9RTO53RxogfSRGZHw_5vT9k0",1784088102670]