[{"data":1,"prerenderedAt":1936},["ShallowReactive",2],{"\u002Fblog\u002F2026\u002Fnuxtv3to4":3},{"id":4,"title":5,"author":6,"body":7,"content_type":1917,"date_created":1918,"date_modified":1919,"description":1920,"editor":1919,"extension":1921,"guide":1919,"image":1922,"image_alt":1923,"is_list_exclude":1924,"is_manual_image":1924,"is_manual_title":1924,"is_toc":283,"keywords":1925,"meta":1927,"navigation":283,"og_description":1919,"og_image":1919,"og_image_alt":1919,"og_title":1919,"path":1928,"peer_order":1929,"project":1919,"projects":1930,"published":1931,"seo":1932,"sitemap":1933,"stem":1934,"tagline":1919,"version":1919,"x_card":1919,"x_creator_handle":1919,"x_description":1919,"x_image":1919,"x_image_alt":1919,"x_title":1919,"__hash__":1935},"content\u002Fblog\u002F2026\u002FNuxtV3to4.md","Nuxt v3 to v4 Migration","John Pennock",{"type":8,"value":9,"toc":1899},"minimark",[10,15,19,28,33,49,53,76,80,88,93,96,121,124,389,392,448,451,455,466,480,484,489,496,500,520,560,573,577,580,584,591,762,773,777,783,867,871,874,923,934,937,961,1048,1051,1055,1067,1097,1184,1187,1222,1235,1248,1352,1361,1480,1484,1491,1500,1509,1551,1555,1564,1626,1636,1666,1670,1676,1891,1895],[11,12,14],"h2",{"id":13},"introduction","Introduction",[16,17,18],"p",{},"I've been using Nuxt.js v3 for my content sites for a while now, and with the release of Nuxt v4, I finally decided to take the plunge.",[16,20,21],{},[22,23,27],"a",{"href":24,"rel":25},"https:\u002F\u002Fnuxt.com\u002Fdocs\u002F4.x\u002Fgetting-started\u002Fupgrade#migrating-to-nuxt-4",[26],"nofollow","Migration Docs",[29,30,32],"h4",{"id":31},"related-blog-posts","Related Blog Posts",[34,35,36,43],"ol",{},[37,38,39],"li",{},[22,40,42],{"href":41},"\u002Fblog\u002F2026\u002Fnuxtcontentv2to3","Nuxt Content v2 to v3 (on Nuxt v4)",[37,44,45],{},[22,46,48],{"href":47},"\u002Fblog\u002F2026\u002Fnuxtcontentschema","Nuxt Content v3 Schema and Collections",[29,50,52],{"id":51},"projects-updated","Projects Updated",[34,54,55,63],{},[37,56,57,62],{},[22,58,61],{"href":59,"rel":60},"https:\u002F\u002Fpennockprojects.com",[26],"Pennock Projects"," - My personal blog where I share articles, projects, and updates about my work and interests. I had to upgrade this site from Nuxt v2 to v4.  Two full feature jumps.This site was built with Nuxt v2 and Nuxt Content v2, so it required a significant upgrade to Nuxt v4 and Nuxt Content v3.",[37,64,65,70,71,75],{},[22,66,69],{"href":67,"rel":68},"http:\u002F\u002Fjamstart.pennockprojects.com",[26],"JAMStart"," - My starter template for new static content sites. This site was already running Nuxt v3 with ",[72,73,74],"code",{},"compatibilityVersion: 4",", which made the upgrade to Nuxt v4 much smoother.",[11,77,79],{"id":78},"upgrade-vs-install","Upgrade vs Install",[16,81,82,83,87],{},"In review the ",[22,84,86],{"href":24,"rel":85},[26],"Nuxt 4 Upgrade Guide"," The main steps involved in the Nuxt v4 upgrade were:",[34,89,90],{},[37,91,92],{},"Installing Nuxt v4",[16,94,95],{},"The first instruction was to install Nuxt v4 using npm.  Like this:",[97,98,103],"pre",{"className":99,"code":100,"language":101,"meta":102,"style":102},"language-bash shiki shiki-themes min-light min-dark monokai","npm install nuxt@^4.0.0\n","bash","",[72,104,105],{"__ignoreMap":102},[106,107,110,114,118],"span",{"class":108,"line":109},"line",1,[106,111,113],{"class":112},"srTi1","npm",[106,115,117],{"class":116},"sCqw6"," install",[106,119,120],{"class":116}," nuxt@^4.0.0\n",[16,122,123],{},"This lead to weird warnings about deprecated packages and an outdated version of Nuxt.",[97,125,127],{"className":99,"code":126,"language":101,"meta":102,"style":102},"npm install nuxt@^4.0.0\nnpm warn deprecated node-domexception@1.0.0: Use your platforms native DOMException instead\nnpm warn deprecated unplugin-vue-router@0.14.0: Merged into vuejs\u002Frouter. Migrate: https:\u002F\u002Frouter.vuejs.org\u002Fguide\u002Fmigration\u002Fv4-to-v5.html  \nnpm warn deprecated glob@10.5.0: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. \n\nadded 255 packages, removed 38 packages, changed 90 packages, and audited 1451 packages in 50s\n\n>npm outdated\nPackage                               Current  Wanted  Latest  Location                                           Depended by\nnuxt                                    4.0.0   4.4.2   4.4.2  node_modules\u002Fnuxt                                  JAMStart\n",[72,128,129,137,169,200,278,285,330,335,345,369],{"__ignoreMap":102},[106,130,131,133,135],{"class":108,"line":109},[106,132,113],{"class":112},[106,134,117],{"class":116},[106,136,120],{"class":116},[106,138,140,142,145,148,151,154,157,160,163,166],{"class":108,"line":139},2,[106,141,113],{"class":112},[106,143,144],{"class":116}," warn",[106,146,147],{"class":116}," deprecated",[106,149,150],{"class":116}," node-domexception@1.0.0:",[106,152,153],{"class":116}," Use",[106,155,156],{"class":116}," your",[106,158,159],{"class":116}," platforms",[106,161,162],{"class":116}," native",[106,164,165],{"class":116}," DOMException",[106,167,168],{"class":116}," instead\n",[106,170,172,174,176,178,181,184,187,190,193,196],{"class":108,"line":171},3,[106,173,113],{"class":112},[106,175,144],{"class":116},[106,177,147],{"class":116},[106,179,180],{"class":116}," unplugin-vue-router@0.14.0:",[106,182,183],{"class":116}," Merged",[106,185,186],{"class":116}," into",[106,188,189],{"class":116}," vuejs\u002Frouter.",[106,191,192],{"class":116}," Migrate:",[106,194,195],{"class":116}," https:\u002F\u002Frouter.vuejs.org\u002Fguide\u002Fmigration\u002Fv4-to-v5.html",[106,197,199],{"class":198},"sxUMQ","  \n",[106,201,203,205,207,209,212,215,218,221,224,227,230,233,236,239,242,245,248,251,254,257,260,263,266,269,272,275],{"class":108,"line":202},4,[106,204,113],{"class":112},[106,206,144],{"class":116},[106,208,147],{"class":116},[106,210,211],{"class":116}," glob@10.5.0:",[106,213,214],{"class":116}," Old",[106,216,217],{"class":116}," versions",[106,219,220],{"class":116}," of",[106,222,223],{"class":116}," glob",[106,225,226],{"class":116}," are",[106,228,229],{"class":116}," not",[106,231,232],{"class":116}," supported,",[106,234,235],{"class":116}," and",[106,237,238],{"class":116}," contain",[106,240,241],{"class":116}," widely",[106,243,244],{"class":116}," publicized",[106,246,247],{"class":116}," security",[106,249,250],{"class":116}," vulnerabilities,",[106,252,253],{"class":116}," which",[106,255,256],{"class":116}," have",[106,258,259],{"class":116}," been",[106,261,262],{"class":116}," fixed",[106,264,265],{"class":116}," in",[106,267,268],{"class":116}," the",[106,270,271],{"class":116}," current",[106,273,274],{"class":116}," version.",[106,276,277],{"class":198}," \n",[106,279,281],{"class":108,"line":280},5,[106,282,284],{"emptyLinePlaceholder":283},true,"\n",[106,286,288,291,295,298,301,304,306,309,312,314,316,319,322,325,327],{"class":108,"line":287},6,[106,289,290],{"class":112},"added",[106,292,294],{"class":293},"s0Ixy"," 255",[106,296,297],{"class":116}," packages,",[106,299,300],{"class":116}," removed",[106,302,303],{"class":293}," 38",[106,305,297],{"class":116},[106,307,308],{"class":116}," changed",[106,310,311],{"class":293}," 90",[106,313,297],{"class":116},[106,315,235],{"class":116},[106,317,318],{"class":116}," audited",[106,320,321],{"class":293}," 1451",[106,323,324],{"class":116}," packages",[106,326,265],{"class":116},[106,328,329],{"class":116}," 50s\n",[106,331,333],{"class":108,"line":332},7,[106,334,284],{"emptyLinePlaceholder":283},[106,336,338,342],{"class":108,"line":337},8,[106,339,341],{"class":340},"s-2sM",">",[106,343,344],{"class":198},"npm outdated\n",[106,346,348,351,354,357,360,363,366],{"class":108,"line":347},9,[106,349,350],{"class":112},"Package",[106,352,353],{"class":116},"                               Current",[106,355,356],{"class":116},"  Wanted",[106,358,359],{"class":116},"  Latest",[106,361,362],{"class":116},"  Location",[106,364,365],{"class":116},"                                           Depended",[106,367,368],{"class":116}," by\n",[106,370,372,375,378,381,383,386],{"class":108,"line":371},10,[106,373,374],{"class":112},"nuxt",[106,376,377],{"class":293},"                                    4.0.0",[106,379,380],{"class":293},"   4.4.2",[106,382,380],{"class":293},[106,384,385],{"class":116},"  node_modules\u002Fnuxt",[106,387,388],{"class":116},"                                  JAMStart\n",[16,390,391],{},"So this was a bit of a mistake as the NPM command literally upgraded Nuxt to the Nuxt 4.0.0 release, which was a bit too old and had deprecation warnings. I then upgraded to the latest Nuxt v4 with:",[97,393,395],{"className":99,"code":394,"language":101,"meta":102,"style":102},"npm upgrade nuxt\n\nadded 52 packages, removed 276 packages, changed 60 packages, and audited 1227 packages in 30s\n\n",[72,396,397,407,411],{"__ignoreMap":102},[106,398,399,401,404],{"class":108,"line":109},[106,400,113],{"class":112},[106,402,403],{"class":116}," upgrade",[106,405,406],{"class":116}," nuxt\n",[106,408,409],{"class":108,"line":139},[106,410,284],{"emptyLinePlaceholder":283},[106,412,413,415,418,420,422,425,427,429,432,434,436,438,441,443,445],{"class":108,"line":171},[106,414,290],{"class":112},[106,416,417],{"class":293}," 52",[106,419,297],{"class":116},[106,421,300],{"class":116},[106,423,424],{"class":293}," 276",[106,426,297],{"class":116},[106,428,308],{"class":116},[106,430,431],{"class":293}," 60",[106,433,297],{"class":116},[106,435,235],{"class":116},[106,437,318],{"class":116},[106,439,440],{"class":293}," 1227",[106,442,324],{"class":116},[106,444,265],{"class":116},[106,446,447],{"class":116}," 30s\n",[16,449,450],{},"which put latest Nuxt 4.4.2 release.",[29,452,454],{"id":453},"avoiding-this-mistake","Avoiding this Mistake",[16,456,457,458,461,462,465],{},"Something I've learned is to use ",[72,459,460],{},"install"," instead of ",[72,463,464],{},"upgrade",", so you can specify the exact version of Nuxt to install with:",[97,467,469],{"className":99,"code":468,"language":101,"meta":102,"style":102},"npm install nuxt@4.4.2\n",[72,470,471],{"__ignoreMap":102},[106,472,473,475,477],{"class":108,"line":109},[106,474,113],{"class":112},[106,476,117],{"class":116},[106,478,479],{"class":116}," nuxt@4.4.2\n",[11,481,483],{"id":482},"migration-doc","Migration Doc",[485,486,488],"h3",{"id":487},"app-directory","App Directory",[16,490,491,492,495],{},"I was prepared to move all my site into the new ",[72,493,494],{},"app"," directory, but I was pleasantly surprised that I did not have to do this. I decided with the other issues, I would postpone this for for my next git check in. I'll update this topic when I do that.",[485,497,499],{"id":498},"single-data-fetching","Single Data Fetching",[16,501,502,503,506,507,510,511,516,517,519],{},"In reading the migration guide, I made aware of the change to single data fetching with ",[72,504,505],{},"useAsyncData"," (and ",[72,508,509],{},"useFetch","). Given I haven't implemented a central store layer, using  something like ",[22,512,515],{"href":513,"rel":514},"https:\u002F\u002Fpinia.vuejs.org\u002F",[26],"pinia",", which is overkill on a static site like mine. But I did uncover an issue with  with custom controls and using unique names to all my ",[72,518,505],{},".",[16,521,522,523,526,527,530,531,534,535,537,538,541,542,545,546,545,549,552,553,556,557,559],{},"For example, I have a custom controls, like ",[72,524,525],{},"ArticleList"," and ",[72,528,529],{},"PostList"," which fetches markdown content pages from different subdirectories within the ",[72,532,533],{},"content"," directory and may have limited depth and or sorting.   These controls can exist on multiple pages, such as the blog list, top 3 new posts, or the cheat sheet list.  To avoid hydration errors, I had to give each ",[72,536,505],{}," call a unique name based on the content being fetched.  For example, in my ",[72,539,540],{},"PostList.vue"," component, I had to generate a unique query name based on the ",[72,543,544],{},"rootPath",", ",[72,547,548],{},"sortBy",[72,550,551],{},"sortOrder",", and ",[72,554,555],{},"limit"," props.  This ensures that each instance of the ",[72,558,529],{}," component fetches its own data without conflicts.  For example, I might use the names:",[561,562,563,568],"ul",{},[37,564,565],{},[72,566,567],{},"blog-posts-3-newest",[37,569,570],{},[72,571,572],{},"cheat-posts",[11,574,576],{"id":575},"configuration-problems","Configuration Problems",[16,578,579],{},"Most of migration issues were related to configuration problems.  The Nuxt v4 migration guide has a section on configuration changes, but it was not comprehensive and did not cover all the issues I encountered.  For some, I had to do a lot of research, replace a module, and trial and error to figure out how to update my configuration files to work with Nuxt v4.",[485,581,583],{"id":582},"devtools-warning","devtools Warning",[16,585,586,587,590],{},"When I started up the development server with ",[72,588,589],{},"npm run dev"," I got the following warning:",[97,592,594],{"className":99,"code":593,"language":101,"meta":102,"style":102},"Vite discovered new dependencies at runtime:                                                                                4:20:36 PM\n  .\u002Fvirtual:nuxt:C%3A%2Fdev%2Fpp%2FJAMStart%2F.nuxt%2Fruntime.vue-devtools-client.E24JpsC1QHyv30MzBlyQv2ApgjFxiuh969Gs938_Ip8.js\n    @vue\u002Fdevtools-core\n    @vue\u002Fdevtools-kit\n\nPre-bundle them in your nuxt.config.ts to avoid page reloads:\n\nexport default defineNuxtConfig({\n  vite: {\n    optimizeDeps: {\n      include: [\n        '@vue\u002Fdevtools-core',\n        '@vue\u002Fdevtools-kit',\n      ]\n    }\n  }\n})\n\nLearn more: https:\u002F\u002Fvite.dev\u002Fguide\u002Fdep-pre-bundling.html\n",[72,595,596,622,627,632,637,641,668,672,680,688,695,704,713,721,727,733,739,745,750],{"__ignoreMap":102},[106,597,598,601,604,607,610,613,616,619],{"class":108,"line":109},[106,599,600],{"class":112},"Vite",[106,602,603],{"class":116}," discovered",[106,605,606],{"class":116}," new",[106,608,609],{"class":116}," dependencies",[106,611,612],{"class":116}," at",[106,614,615],{"class":116}," runtime:",[106,617,618],{"class":116},"                                                                                4:20:36",[106,620,621],{"class":116}," PM\n",[106,623,624],{"class":108,"line":139},[106,625,626],{"class":112},"  .\u002Fvirtual:nuxt:C%3A%2Fdev%2Fpp%2FJAMStart%2F.nuxt%2Fruntime.vue-devtools-client.E24JpsC1QHyv30MzBlyQv2ApgjFxiuh969Gs938_Ip8.js\n",[106,628,629],{"class":108,"line":171},[106,630,631],{"class":112},"    @vue\u002Fdevtools-core\n",[106,633,634],{"class":108,"line":202},[106,635,636],{"class":112},"    @vue\u002Fdevtools-kit\n",[106,638,639],{"class":108,"line":280},[106,640,284],{"emptyLinePlaceholder":283},[106,642,643,646,649,651,653,656,659,662,665],{"class":108,"line":287},[106,644,645],{"class":112},"Pre-bundle",[106,647,648],{"class":116}," them",[106,650,265],{"class":116},[106,652,156],{"class":116},[106,654,655],{"class":116}," nuxt.config.ts",[106,657,658],{"class":116}," to",[106,660,661],{"class":116}," avoid",[106,663,664],{"class":116}," page",[106,666,667],{"class":116}," reloads:\n",[106,669,670],{"class":108,"line":332},[106,671,284],{"emptyLinePlaceholder":283},[106,673,674,677],{"class":108,"line":337},[106,675,676],{"class":340},"export",[106,678,679],{"class":198}," default defineNuxtConfig({\n",[106,681,682,685],{"class":108,"line":347},[106,683,684],{"class":112},"  vite:",[106,686,687],{"class":116}," {\n",[106,689,690,693],{"class":108,"line":371},[106,691,692],{"class":112},"    optimizeDeps:",[106,694,687],{"class":116},[106,696,698,701],{"class":108,"line":697},11,[106,699,700],{"class":112},"      include:",[106,702,703],{"class":198}," [\n",[106,705,707,710],{"class":108,"line":706},12,[106,708,709],{"class":112},"        '@vue\u002Fdevtools-core'",[106,711,712],{"class":112},",\n",[106,714,716,719],{"class":108,"line":715},13,[106,717,718],{"class":112},"        '@vue\u002Fdevtools-kit'",[106,720,712],{"class":112},[106,722,724],{"class":108,"line":723},14,[106,725,726],{"class":198},"      ]\n",[106,728,730],{"class":108,"line":729},15,[106,731,732],{"class":198},"    }\n",[106,734,736],{"class":108,"line":735},16,[106,737,738],{"class":198},"  }\n",[106,740,742],{"class":108,"line":741},17,[106,743,744],{"class":198},"})\n",[106,746,748],{"class":108,"line":747},18,[106,749,284],{"emptyLinePlaceholder":283},[106,751,753,756,759],{"class":108,"line":752},19,[106,754,755],{"class":112},"Learn",[106,757,758],{"class":116}," more:",[106,760,761],{"class":116}," https:\u002F\u002Fvite.dev\u002Fguide\u002Fdep-pre-bundling.html\n",[16,763,764,765,768,769,772],{},"To solve this I added the ",[72,766,767],{},"optimizeDeps"," configuration to my ",[72,770,771],{},"nuxt.config.ts"," file as shown in the warning message.  This pre-bundles the dependencies and should prevent the warning from appearing again.",[485,774,776],{"id":775},"zod-warning","zod Warning",[16,778,779,780,782],{},"I also got a warning about Zod, a new schema module for Nuxt Content, about it not being optimized for production when I started the development server, so I added it to the ",[72,781,767],{}," configuration as well like this:",[97,784,788],{"className":785,"code":786,"language":787,"meta":102,"style":102},"language-ts shiki shiki-themes min-light min-dark monokai","export default defineNuxtConfig({\n  vite: {\n    optimizeDeps: {\n      include: [\n        '@vue\u002Fdevtools-core',\n        '@vue\u002Fdevtools-kit',\n        'zod'\n      ]\n    }\n  }\n})\n","ts",[72,789,790,803,814,823,832,840,846,851,855,859,863],{"__ignoreMap":102},[106,791,792,794,797,800],{"class":108,"line":109},[106,793,676],{"class":340},[106,795,796],{"class":340}," default",[106,798,799],{"class":112}," defineNuxtConfig",[106,801,802],{"class":198},"({\n",[106,804,805,808,812],{"class":108,"line":139},[106,806,807],{"class":198},"  vite",[106,809,811],{"class":810},"skixG",":",[106,813,687],{"class":198},[106,815,816,819,821],{"class":108,"line":171},[106,817,818],{"class":198},"    optimizeDeps",[106,820,811],{"class":810},[106,822,687],{"class":198},[106,824,825,828,830],{"class":108,"line":202},[106,826,827],{"class":198},"      include",[106,829,811],{"class":810},[106,831,703],{"class":198},[106,833,834,837],{"class":108,"line":280},[106,835,709],{"class":836},"shHn5",[106,838,712],{"class":839},"sizxJ",[106,841,842,844],{"class":108,"line":287},[106,843,718],{"class":836},[106,845,712],{"class":839},[106,847,848],{"class":108,"line":332},[106,849,850],{"class":836},"        'zod'\n",[106,852,853],{"class":108,"line":337},[106,854,726],{"class":198},[106,856,857],{"class":108,"line":347},[106,858,732],{"class":198},[106,860,861],{"class":108,"line":371},[106,862,738],{"class":198},[106,864,865],{"class":108,"line":697},[106,866,744],{"class":198},[485,868,870],{"id":869},"incompatible-cloudflare-module","Incompatible CloudFlare Module",[16,872,873],{},"The basic module for CloudFlare Analytics is not compatible with Nuxt v4.",[97,875,877],{"className":99,"code":876,"language":101,"meta":102,"style":102}," WARN  Module nuxt-cloudflare-analytics is disabled due to incompatibility issues:                                             4:19:21 PM  \n - [nuxt] Nuxt version ^3.0.0 is required but currently using 4.4.2\n",[72,878,879,915],{"__ignoreMap":102},[106,880,881,884,887,890,893,896,899,901,904,907,910,913],{"class":108,"line":109},[106,882,883],{"class":112}," WARN",[106,885,886],{"class":116},"  Module",[106,888,889],{"class":116}," nuxt-cloudflare-analytics",[106,891,892],{"class":116}," is",[106,894,895],{"class":116}," disabled",[106,897,898],{"class":116}," due",[106,900,658],{"class":116},[106,902,903],{"class":116}," incompatibility",[106,905,906],{"class":116}," issues:",[106,908,909],{"class":116},"                                             4:19:21",[106,911,912],{"class":116}," PM",[106,914,199],{"class":198},[106,916,917,920],{"class":108,"line":139},[106,918,919],{"class":112}," -",[106,921,922],{"class":198}," [nuxt] Nuxt version ^3.0.0 is required but currently using 4.4.2\n",[16,924,925,926,929,930,933],{},"There was no update available for the ",[72,927,928],{},"nuxt-cloudflare-analytics"," module, and it seems to be abandoned.  I looked for an alternative CloudFlare Analytics module, but there were no other Nuxt modules available for CloudFlare Analytics.  I then looked for a more general solution that would allow me to use the CloudFlare Analytics script without relying on a specific module.  This led me to the ",[72,931,932],{},"NuxtScripts"," module, which allows you to easily add third-party scripts to your Nuxt application.",[16,935,936],{},"I removed the deprecated modules like this:",[34,938,939,949],{},[37,940,941,942],{},"Uninstall the deprecated module: :\n",[561,943,944],{},[37,945,946],{},[72,947,948],{},"npm uninstall nuxt-cloudflare-analytics",[37,950,951,952,954,955,958,959,519],{},"Remove the module ",[72,953,928],{}," from the ",[72,956,957],{},"modules"," array in ",[72,960,771],{},[97,962,964],{"className":785,"code":963,"language":787,"meta":102,"style":102},"export default defineNuxtConfig({\n  modules: [\n    \u002F\u002F other modules...\n    'nuxt-cloudflare-analytics'   \u002F\u002F remove this element from the array\n  ],\n});\n3. Commented out the configuration token like this: \n```ts\nexport default defineNuxtConfig({\n\u002F\u002F   cloudflareAnalytics: {\n\u002F\u002F    token: 'XXXXXXXXXXXX'\n\u002F\u002F  },\n\n",[72,965,966,976,985,991,999,1006,1011,1023,1028,1033,1038,1043],{"__ignoreMap":102},[106,967,968,970,972,974],{"class":108,"line":109},[106,969,676],{"class":340},[106,971,796],{"class":340},[106,973,799],{"class":112},[106,975,802],{"class":198},[106,977,978,981,983],{"class":108,"line":139},[106,979,980],{"class":198},"  modules",[106,982,811],{"class":810},[106,984,703],{"class":198},[106,986,987],{"class":108,"line":171},[106,988,990],{"class":989},"sNgeA","    \u002F\u002F other modules...\n",[106,992,993,996],{"class":108,"line":202},[106,994,995],{"class":836},"    'nuxt-cloudflare-analytics'",[106,997,998],{"class":989},"   \u002F\u002F remove this element from the array\n",[106,1000,1001,1004],{"class":108,"line":280},[106,1002,1003],{"class":198},"  ]",[106,1005,712],{"class":839},[106,1007,1008],{"class":108,"line":287},[106,1009,1010],{"class":198},"});\n",[106,1012,1013,1016,1019,1021],{"class":108,"line":332},[106,1014,1015],{"class":293},"3.",[106,1017,1018],{"class":198}," Commented out the configuration token like this",[106,1020,811],{"class":839},[106,1022,277],{"class":198},[106,1024,1025],{"class":108,"line":337},[106,1026,1027],{"class":836},"```ts\n",[106,1029,1030],{"class":108,"line":347},[106,1031,1032],{"class":836},"export default defineNuxtConfig({\n",[106,1034,1035],{"class":108,"line":371},[106,1036,1037],{"class":836},"\u002F\u002F   cloudflareAnalytics: {\n",[106,1039,1040],{"class":108,"line":697},[106,1041,1042],{"class":836},"\u002F\u002F    token: 'XXXXXXXXXXXX'\n",[106,1044,1045],{"class":108,"line":706},[106,1046,1047],{"class":836},"\u002F\u002F  },\n",[16,1049,1050],{},"You'll need this token later.",[485,1052,1054],{"id":1053},"new-nuxtscripts-cloudflare","New NuxtScripts CloudFlare",[16,1056,1057,1058,1062,1063,1066],{},"I found a new nuxt module called ",[22,1059,932],{"href":1060,"rel":1061},"https:\u002F\u002Fscripts.nuxt.com\u002Fscripts",[26]," that contains many third party scripts including CloudFlare Analytics. It recently left beta and is at ",[72,1064,1065],{},"1.1.1"," as of this writing. It also has a host of other scripts from GA, Ads, etc. but I'm only interested in CloudFlare Analytics as it is cookie-less and free. Here's what happened when I upgraded.",[34,1068,1069,1082],{},[37,1070,1071,1072,1074,1075],{},"Then I installed the ",[72,1073,932],{}," module.\n",[561,1076,1077],{},[37,1078,1079],{},[72,1080,1081],{},"npx nuxi@latest module add scripts",[37,1083,1084,1085,1087,1088,1090,1091,1094,1095,811],{},"Then I edited the ",[72,1086,771],{}," file to move my CloudFlare token to a new key for the ",[72,1089,932],{}," module.  I added the following to the ",[72,1092,1093],{},"scripts.registry"," key in ",[72,1096,771],{},[97,1098,1100],{"className":785,"code":1099,"language":787,"meta":102,"style":102},"export default defineNuxtConfig({\n  scripts: {\n    registry: {\n      cloudflareWebAnalytics: {\n        token: 'a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4',   \u002F\u002F replace with your actual token\n        trigger: 'onNuxtReady',\n      }\n    }\n  }\n});\n",[72,1101,1102,1112,1121,1130,1139,1155,1167,1172,1176,1180],{"__ignoreMap":102},[106,1103,1104,1106,1108,1110],{"class":108,"line":109},[106,1105,676],{"class":340},[106,1107,796],{"class":340},[106,1109,799],{"class":112},[106,1111,802],{"class":198},[106,1113,1114,1117,1119],{"class":108,"line":139},[106,1115,1116],{"class":198},"  scripts",[106,1118,811],{"class":810},[106,1120,687],{"class":198},[106,1122,1123,1126,1128],{"class":108,"line":171},[106,1124,1125],{"class":198},"    registry",[106,1127,811],{"class":810},[106,1129,687],{"class":198},[106,1131,1132,1135,1137],{"class":108,"line":202},[106,1133,1134],{"class":198},"      cloudflareWebAnalytics",[106,1136,811],{"class":810},[106,1138,687],{"class":198},[106,1140,1141,1144,1146,1149,1152],{"class":108,"line":280},[106,1142,1143],{"class":198},"        token",[106,1145,811],{"class":810},[106,1147,1148],{"class":836}," 'a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4'",[106,1150,1151],{"class":839},",",[106,1153,1154],{"class":989},"   \u002F\u002F replace with your actual token\n",[106,1156,1157,1160,1162,1165],{"class":108,"line":287},[106,1158,1159],{"class":198},"        trigger",[106,1161,811],{"class":810},[106,1163,1164],{"class":836}," 'onNuxtReady'",[106,1166,712],{"class":839},[106,1168,1169],{"class":108,"line":332},[106,1170,1171],{"class":198},"      }\n",[106,1173,1174],{"class":108,"line":337},[106,1175,732],{"class":198},[106,1177,1178],{"class":108,"line":347},[106,1179,738],{"class":198},[106,1181,1182],{"class":108,"line":371},[106,1183,1010],{"class":198},[16,1185,1186],{},"Initially this looked like it was working, but then when I inspected it on my dev site at AWS S3 I could see the cloudflare beacon the following network error:",[97,1188,1190],{"className":99,"code":1189,"language":101,"meta":102,"style":102},"\"Request URL\nhttp:\u002F\u002Fdev.pennockprojects.com\u002F_scripts\u002Fp\u002Fcloudflareinsights.com\u002Fcdn-cgi\u002Frum\nRequest Method\nPOST\nStatus Code\n405 Method Not Allowed\n",[72,1191,1192,1197,1202,1207,1212,1217],{"__ignoreMap":102},[106,1193,1194],{"class":108,"line":109},[106,1195,1196],{"class":112},"\"Request URL\n",[106,1198,1199],{"class":108,"line":139},[106,1200,1201],{"class":112},"http:\u002F\u002Fdev.pennockprojects.com\u002F_scripts\u002Fp\u002Fcloudflareinsights.com\u002Fcdn-cgi\u002Frum\n",[106,1203,1204],{"class":108,"line":171},[106,1205,1206],{"class":112},"Request Method\n",[106,1208,1209],{"class":108,"line":202},[106,1210,1211],{"class":112},"POST\n",[106,1213,1214],{"class":108,"line":280},[106,1215,1216],{"class":112},"Status Code\n",[106,1218,1219],{"class":108,"line":287},[106,1220,1221],{"class":112},"405 Method Not Allowed\n",[16,1223,1224,1225,1227,1228,1231,1232,1234],{},"This was because the ",[72,1226,932],{}," CloudFlare module was using some sort of local proxy.  Notice how it was trying to connect to itself ",[72,1229,1230],{},"dev.pennockprojects.com"," rather than to the actual CloudFlare CDN.  I guess the ",[72,1233,932],{}," module uses some sort of local proxy for all its scripts, which on an S3 WebSite will fail with a 405 Method Not Allowed.",[16,1236,1237,1238,526,1241,1244,1245,1247],{},"To resolve I had to add two additional settings, ",[72,1239,1240],{},"proxy: false",[72,1242,1243],{},"bundle: false",", to prevent the ",[72,1246,932],{}," module from trying to proxy the CloudFlare script through the local server.",[97,1249,1251],{"className":785,"code":1250,"language":787,"meta":102,"style":102},"export default defineNuxtConfig({\n  scripts: {\n    registry: {\n      cloudflareWebAnalytics: {\n        token: 'a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4',   \u002F\u002F replace with your actual token\n        trigger: 'onNuxtReady',\n        proxy: false,    \u002F\u002F add this for S3 hosting\n        bundle: false    \u002F\u002F add this for S3 hosting\n      }\n    }\n  }\n});\n",[72,1252,1253,1263,1271,1279,1287,1299,1309,1325,1336,1340,1344,1348],{"__ignoreMap":102},[106,1254,1255,1257,1259,1261],{"class":108,"line":109},[106,1256,676],{"class":340},[106,1258,796],{"class":340},[106,1260,799],{"class":112},[106,1262,802],{"class":198},[106,1264,1265,1267,1269],{"class":108,"line":139},[106,1266,1116],{"class":198},[106,1268,811],{"class":810},[106,1270,687],{"class":198},[106,1272,1273,1275,1277],{"class":108,"line":171},[106,1274,1125],{"class":198},[106,1276,811],{"class":810},[106,1278,687],{"class":198},[106,1280,1281,1283,1285],{"class":108,"line":202},[106,1282,1134],{"class":198},[106,1284,811],{"class":810},[106,1286,687],{"class":198},[106,1288,1289,1291,1293,1295,1297],{"class":108,"line":280},[106,1290,1143],{"class":198},[106,1292,811],{"class":810},[106,1294,1148],{"class":836},[106,1296,1151],{"class":839},[106,1298,1154],{"class":989},[106,1300,1301,1303,1305,1307],{"class":108,"line":287},[106,1302,1159],{"class":198},[106,1304,811],{"class":810},[106,1306,1164],{"class":836},[106,1308,712],{"class":839},[106,1310,1311,1314,1316,1320,1322],{"class":108,"line":332},[106,1312,1313],{"class":198},"        proxy",[106,1315,811],{"class":810},[106,1317,1319],{"class":1318},"snb_r"," false",[106,1321,1151],{"class":839},[106,1323,1324],{"class":989},"    \u002F\u002F add this for S3 hosting\n",[106,1326,1327,1330,1332,1334],{"class":108,"line":337},[106,1328,1329],{"class":198},"        bundle",[106,1331,811],{"class":810},[106,1333,1319],{"class":1318},[106,1335,1324],{"class":989},[106,1337,1338],{"class":108,"line":347},[106,1339,1171],{"class":198},[106,1341,1342],{"class":108,"line":371},[106,1343,732],{"class":198},[106,1345,1346],{"class":108,"line":697},[106,1347,738],{"class":198},[106,1349,1350],{"class":108,"line":706},[106,1351,1010],{"class":198},[16,1353,1354,1355,1094,1358,1360],{},"The final configuration tweak was that I only wanted it to beacon in production, so I forced it to use the beacon only in production (only when generated) by wrapping the scripts configuration to the ",[72,1356,1357],{},"$production",[72,1359,771],{}," like this:",[97,1362,1364],{"className":785,"code":1363,"language":787,"meta":102,"style":102},"export default defineNuxtConfig({\n  $production: {          \u002F\u002F These options only in prod.\n    scripts: {\n      registry: {\n        cloudflareWebAnalytics: {\n          token: 'a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4',\n          trigger: 'onNuxtReady',\n          proxy: false,\n          bundle: false\n        }\n      }\n    }\n  }\n});\n",[72,1365,1366,1376,1389,1398,1407,1416,1427,1438,1449,1459,1464,1468,1472,1476],{"__ignoreMap":102},[106,1367,1368,1370,1372,1374],{"class":108,"line":109},[106,1369,676],{"class":340},[106,1371,796],{"class":340},[106,1373,799],{"class":112},[106,1375,802],{"class":198},[106,1377,1378,1381,1383,1386],{"class":108,"line":139},[106,1379,1380],{"class":198},"  $production",[106,1382,811],{"class":810},[106,1384,1385],{"class":198}," {          ",[106,1387,1388],{"class":989},"\u002F\u002F These options only in prod.\n",[106,1390,1391,1394,1396],{"class":108,"line":171},[106,1392,1393],{"class":198},"    scripts",[106,1395,811],{"class":810},[106,1397,687],{"class":198},[106,1399,1400,1403,1405],{"class":108,"line":202},[106,1401,1402],{"class":198},"      registry",[106,1404,811],{"class":810},[106,1406,687],{"class":198},[106,1408,1409,1412,1414],{"class":108,"line":280},[106,1410,1411],{"class":198},"        cloudflareWebAnalytics",[106,1413,811],{"class":810},[106,1415,687],{"class":198},[106,1417,1418,1421,1423,1425],{"class":108,"line":287},[106,1419,1420],{"class":198},"          token",[106,1422,811],{"class":810},[106,1424,1148],{"class":836},[106,1426,712],{"class":839},[106,1428,1429,1432,1434,1436],{"class":108,"line":332},[106,1430,1431],{"class":198},"          trigger",[106,1433,811],{"class":810},[106,1435,1164],{"class":836},[106,1437,712],{"class":839},[106,1439,1440,1443,1445,1447],{"class":108,"line":337},[106,1441,1442],{"class":198},"          proxy",[106,1444,811],{"class":810},[106,1446,1319],{"class":1318},[106,1448,712],{"class":839},[106,1450,1451,1454,1456],{"class":108,"line":347},[106,1452,1453],{"class":198},"          bundle",[106,1455,811],{"class":810},[106,1457,1458],{"class":1318}," false\n",[106,1460,1461],{"class":108,"line":371},[106,1462,1463],{"class":198},"        }\n",[106,1465,1466],{"class":108,"line":697},[106,1467,1171],{"class":198},[106,1469,1470],{"class":108,"line":706},[106,1471,732],{"class":198},[106,1473,1474],{"class":108,"line":715},[106,1475,738],{"class":198},[106,1477,1478],{"class":108,"line":723},[106,1479,1010],{"class":198},[485,1481,1483],{"id":1482},"sitemap-zeroruntime","Sitemap zeroRuntime",[16,1485,1486,1487,1490],{},"After upgrading to Nuxt v4, I noticed that the sitemap was not being generated correctly.  I was using the ",[72,1488,1489],{},"@nuxtjs\u002Fsitemap"," module, which is compatible with Nuxt v4, but it was not generating any dynamic sources for the sitemap.  This was likely due to a change in how Nuxt v4 handles dynamic imports and modules.",[97,1492,1494],{"className":99,"code":1493,"language":101,"meta":102,"style":102},"[@nuxtjs\u002Fsitemap 3:49:49 PM] ℹ No dynamic sources detected. Consider enabling zeroRuntime to reduce server bundle size. See https:\u002F\u002Fnuxtseo.com\u002Fsitemap\u002Fguides\u002Fzero-runtime\n",[72,1495,1496],{"__ignoreMap":102},[106,1497,1498],{"class":108,"line":109},[106,1499,1493],{"class":198},[16,1501,1502,1503,1506,1507,811],{},"The warning message suggested enabling ",[72,1504,1505],{},"zeroRuntime"," to reduce server bundle size, which I did by adding the following configuration to ",[72,1508,771],{},[97,1510,1512],{"className":785,"code":1511,"language":787,"meta":102,"style":102},"export default defineNuxtConfig({\n  sitemap: {\n    zeroRuntime: true\n  }\n});\n",[72,1513,1514,1524,1533,1543,1547],{"__ignoreMap":102},[106,1515,1516,1518,1520,1522],{"class":108,"line":109},[106,1517,676],{"class":340},[106,1519,796],{"class":340},[106,1521,799],{"class":112},[106,1523,802],{"class":198},[106,1525,1526,1529,1531],{"class":108,"line":139},[106,1527,1528],{"class":198},"  sitemap",[106,1530,811],{"class":810},[106,1532,687],{"class":198},[106,1534,1535,1538,1540],{"class":108,"line":171},[106,1536,1537],{"class":198},"    zeroRuntime",[106,1539,811],{"class":810},[106,1541,1542],{"class":1318}," true\n",[106,1544,1545],{"class":108,"line":202},[106,1546,738],{"class":198},[106,1548,1549],{"class":108,"line":280},[106,1550,1010],{"class":198},[485,1552,1554],{"id":1553},"sourcemap-client-only","Sourcemap Client Only",[16,1556,1557,1558,1561,1562,519],{},"After upgrading to Nuxt v4, other warnings were about missing sourcemaps for sub dependencies, for example in ",[72,1559,1560],{},"module-preload-polyfill"," which is a dependency of ",[72,1563,932],{},[97,1565,1567],{"className":99,"code":1566,"language":101,"meta":102,"style":102}," WARN  [plugin nuxt:module-preload-polyfill] Sourcemap is likely to be incorrect: a plugin (nuxt:module-preload-polyfill) was \nused to transform files, but didn't generate a sourcemap for the transformation. Consult the plugin documentation for help\n",[72,1568,1569,1604],{"__ignoreMap":102},[106,1570,1571,1573,1576,1579,1582,1584,1587,1589,1592,1595,1598,1601],{"class":108,"line":109},[106,1572,883],{"class":112},[106,1574,1575],{"class":198},"  [plugin ",[106,1577,1578],{"class":116},"nuxt:module-preload-polyfill]",[106,1580,1581],{"class":116}," Sourcemap",[106,1583,892],{"class":116},[106,1585,1586],{"class":116}," likely",[106,1588,658],{"class":116},[106,1590,1591],{"class":116}," be",[106,1593,1594],{"class":116}," incorrect:",[106,1596,1597],{"class":116}," a",[106,1599,1600],{"class":116}," plugin",[106,1602,1603],{"class":198}," (nuxt:module-preload-polyfill) was \n",[106,1605,1606,1609,1611,1614,1617,1620,1623],{"class":108,"line":139},[106,1607,1608],{"class":112},"used",[106,1610,658],{"class":116},[106,1612,1613],{"class":116}," transform",[106,1615,1616],{"class":116}," files,",[106,1618,1619],{"class":116}," but",[106,1621,1622],{"class":116}," didn",[106,1624,1625],{"class":836},"'t generate a sourcemap for the transformation. Consult the plugin documentation for help\n",[16,1627,1628,1629,1633,1634,1360],{},"I was able to resolve this by enabling sourcemaps in the ",[1630,1631,1632],"strong",{},"client"," only.  A static web site does not need server-side sourcemaps, so this reduces the bundle size, as well. You can choose client-side sourcemaps in ",[72,1635,771],{},[97,1637,1641],{"className":1638,"code":1639,"language":1640,"meta":102,"style":102},"language-json shiki shiki-themes min-light min-dark monokai","  sourcemap: {\n    client: true,\n  },\n\n","json",[72,1642,1643,1648,1661],{"__ignoreMap":102},[106,1644,1645],{"class":108,"line":109},[106,1646,1647],{"class":198},"  sourcemap: {\n",[106,1649,1650,1654,1656,1659],{"class":108,"line":139},[106,1651,1653],{"class":1652},"sA23Y","    client",[106,1655,811],{"class":839},[106,1657,1658],{"class":1318}," true",[106,1660,712],{"class":839},[106,1662,1663],{"class":108,"line":171},[106,1664,1665],{"class":198},"  },\n",[485,1667,1669],{"id":1668},"full-configuration-diff","Full Configuration Diff",[16,1671,1672,1673,1675],{},"Here is the diff of the ",[72,1674,771],{}," file showing all the configuration changes I made to upgrade to Nuxt v4:",[97,1677,1681],{"className":1678,"code":1679,"language":1680,"meta":102,"style":102},"language-diff shiki shiki-themes min-light min-dark monokai","export default defineNuxtConfig({\n   modules: [\n-    'nuxt-cloudflare-analytics'\n+    '@nuxt\u002Fscripts',\n   ],\n-  cloudflareAnalytics: {\n-    token: 'XXXXXXXXXXXXXXX'\n-  },\n+  $production: {\n+    scripts: {\n+      registry: {\n+        cloudflareWebAnalytics: {\n+          token: 'XXXXXXXXXXXXXXXX',\n+          trigger: 'onNuxtReady',\n+          proxy: false,\n+          bundle: false\n+        }\n+      }\n+    },\n+  },\n+ \n   sitemap: {\n-    strictNuxtContentPaths: true\n+    zeroRuntime: true\n   },\n+  sourcemap: {\n+    client: true,\n+  },\n+  vite: {\n+    optimizeDeps: {\n+      include: [\n+        '@vue\u002Fdevtools-core',\n+        '@vue\u002Fdevtools-kit',\n+        'zod',\n+      ]\n+    }\n+ }\n})\n","diff",[72,1682,1683,1687,1692,1698,1704,1709,1714,1719,1724,1729,1734,1739,1744,1749,1754,1759,1764,1769,1774,1779,1785,1791,1797,1803,1809,1815,1821,1827,1832,1838,1844,1850,1856,1862,1868,1874,1880,1886],{"__ignoreMap":102},[106,1684,1685],{"class":108,"line":109},[106,1686,1032],{"class":198},[106,1688,1689],{"class":108,"line":139},[106,1690,1691],{"class":198},"   modules: [\n",[106,1693,1694],{"class":108,"line":171},[106,1695,1697],{"class":1696},"smRRp","-    'nuxt-cloudflare-analytics'\n",[106,1699,1700],{"class":108,"line":202},[106,1701,1703],{"class":1702},"sZ4bb","+    '@nuxt\u002Fscripts',\n",[106,1705,1706],{"class":108,"line":280},[106,1707,1708],{"class":198},"   ],\n",[106,1710,1711],{"class":108,"line":287},[106,1712,1713],{"class":1696},"-  cloudflareAnalytics: {\n",[106,1715,1716],{"class":108,"line":332},[106,1717,1718],{"class":1696},"-    token: 'XXXXXXXXXXXXXXX'\n",[106,1720,1721],{"class":108,"line":337},[106,1722,1723],{"class":1696},"-  },\n",[106,1725,1726],{"class":108,"line":347},[106,1727,1728],{"class":1702},"+  $production: {\n",[106,1730,1731],{"class":108,"line":371},[106,1732,1733],{"class":1702},"+    scripts: {\n",[106,1735,1736],{"class":108,"line":697},[106,1737,1738],{"class":1702},"+      registry: {\n",[106,1740,1741],{"class":108,"line":706},[106,1742,1743],{"class":1702},"+        cloudflareWebAnalytics: {\n",[106,1745,1746],{"class":108,"line":715},[106,1747,1748],{"class":1702},"+          token: 'XXXXXXXXXXXXXXXX',\n",[106,1750,1751],{"class":108,"line":723},[106,1752,1753],{"class":1702},"+          trigger: 'onNuxtReady',\n",[106,1755,1756],{"class":108,"line":729},[106,1757,1758],{"class":1702},"+          proxy: false,\n",[106,1760,1761],{"class":108,"line":735},[106,1762,1763],{"class":1702},"+          bundle: false\n",[106,1765,1766],{"class":108,"line":741},[106,1767,1768],{"class":1702},"+        }\n",[106,1770,1771],{"class":108,"line":747},[106,1772,1773],{"class":1702},"+      }\n",[106,1775,1776],{"class":108,"line":752},[106,1777,1778],{"class":1702},"+    },\n",[106,1780,1782],{"class":108,"line":1781},20,[106,1783,1784],{"class":1702},"+  },\n",[106,1786,1788],{"class":108,"line":1787},21,[106,1789,1790],{"class":1702},"+ \n",[106,1792,1794],{"class":108,"line":1793},22,[106,1795,1796],{"class":198},"   sitemap: {\n",[106,1798,1800],{"class":108,"line":1799},23,[106,1801,1802],{"class":1696},"-    strictNuxtContentPaths: true\n",[106,1804,1806],{"class":108,"line":1805},24,[106,1807,1808],{"class":1702},"+    zeroRuntime: true\n",[106,1810,1812],{"class":108,"line":1811},25,[106,1813,1814],{"class":198},"   },\n",[106,1816,1818],{"class":108,"line":1817},26,[106,1819,1820],{"class":1702},"+  sourcemap: {\n",[106,1822,1824],{"class":108,"line":1823},27,[106,1825,1826],{"class":1702},"+    client: true,\n",[106,1828,1830],{"class":108,"line":1829},28,[106,1831,1784],{"class":1702},[106,1833,1835],{"class":108,"line":1834},29,[106,1836,1837],{"class":1702},"+  vite: {\n",[106,1839,1841],{"class":108,"line":1840},30,[106,1842,1843],{"class":1702},"+    optimizeDeps: {\n",[106,1845,1847],{"class":108,"line":1846},31,[106,1848,1849],{"class":1702},"+      include: [\n",[106,1851,1853],{"class":108,"line":1852},32,[106,1854,1855],{"class":1702},"+        '@vue\u002Fdevtools-core',\n",[106,1857,1859],{"class":108,"line":1858},33,[106,1860,1861],{"class":1702},"+        '@vue\u002Fdevtools-kit',\n",[106,1863,1865],{"class":108,"line":1864},34,[106,1866,1867],{"class":1702},"+        'zod',\n",[106,1869,1871],{"class":108,"line":1870},35,[106,1872,1873],{"class":1702},"+      ]\n",[106,1875,1877],{"class":108,"line":1876},36,[106,1878,1879],{"class":1702},"+    }\n",[106,1881,1883],{"class":108,"line":1882},37,[106,1884,1885],{"class":1702},"+ }\n",[106,1887,1889],{"class":108,"line":1888},38,[106,1890,744],{"class":198},[11,1892,1894],{"id":1893},"summary-of-upgrade-process","Summary of Upgrade Process",[1896,1897,1898],"style",{},"html pre.shiki code .srTi1, html code.shiki .srTi1{--shiki-default:#6F42C1;--shiki-dark:#B392F0;--shiki-sepia:#A6E22E}html pre.shiki code .sCqw6, html code.shiki .sCqw6{--shiki-default:#2B5581;--shiki-dark:#9DB1C5;--shiki-sepia:#E6DB74}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 .sepia .shiki span {color: var(--shiki-sepia);background: var(--shiki-sepia-bg);font-style: var(--shiki-sepia-font-style);font-weight: var(--shiki-sepia-font-weight);text-decoration: var(--shiki-sepia-text-decoration);}html.sepia .shiki span {color: var(--shiki-sepia);background: var(--shiki-sepia-bg);font-style: var(--shiki-sepia-font-style);font-weight: var(--shiki-sepia-font-weight);text-decoration: var(--shiki-sepia-text-decoration);}html pre.shiki code .sxUMQ, html code.shiki .sxUMQ{--shiki-default:#24292EFF;--shiki-dark:#B392F0;--shiki-sepia:#F8F8F2}html pre.shiki code .s0Ixy, html code.shiki .s0Ixy{--shiki-default:#1976D2;--shiki-dark:#F8F8F8;--shiki-sepia:#AE81FF}html pre.shiki code .s-2sM, html code.shiki .s-2sM{--shiki-default:#D32F2F;--shiki-dark:#F97583;--shiki-sepia:#F92672}html pre.shiki code .skixG, html code.shiki .skixG{--shiki-default:#D32F2F;--shiki-dark:#F97583;--shiki-sepia:#F8F8F2}html pre.shiki code .shHn5, html code.shiki .shHn5{--shiki-default:#22863A;--shiki-dark:#FFAB70;--shiki-sepia:#E6DB74}html pre.shiki code .sizxJ, html code.shiki .sizxJ{--shiki-default:#212121;--shiki-dark:#BBBBBB;--shiki-sepia:#F8F8F2}html pre.shiki code .sNgeA, html code.shiki .sNgeA{--shiki-default:#C2C3C5;--shiki-dark:#6B737C;--shiki-sepia:#88846F}html pre.shiki code .snb_r, html code.shiki .snb_r{--shiki-default:#1976D2;--shiki-dark:#79B8FF;--shiki-sepia:#AE81FF}html pre.shiki code .sA23Y, html code.shiki .sA23Y{--shiki-default:#24292EFF;--shiki-dark:#B392F0;--shiki-sepia:#F44747}html pre.shiki code .smRRp, html code.shiki .smRRp{--shiki-default:#24292EFF;--shiki-dark:#B392F0;--shiki-sepia:#F92672}html pre.shiki code .sZ4bb, html code.shiki .sZ4bb{--shiki-default:#24292EFF;--shiki-dark:#B392F0;--shiki-sepia:#A6E22E}",{"title":102,"searchDepth":139,"depth":139,"links":1900},[1901,1902,1903,1907,1916],{"id":13,"depth":139,"text":14},{"id":78,"depth":139,"text":79},{"id":482,"depth":139,"text":483,"children":1904},[1905,1906],{"id":487,"depth":171,"text":488},{"id":498,"depth":171,"text":499},{"id":575,"depth":139,"text":576,"children":1908},[1909,1910,1911,1912,1913,1914,1915],{"id":582,"depth":171,"text":583},{"id":775,"depth":171,"text":776},{"id":869,"depth":171,"text":870},{"id":1053,"depth":171,"text":1054},{"id":1482,"depth":171,"text":1483},{"id":1553,"depth":171,"text":1554},{"id":1668,"depth":171,"text":1669},{"id":1893,"depth":139,"text":1894},"article","2026-05-16",null,"A detailed account of the issues, process and considerations involved in upgrading the Nuxt framework to version 4.x.","md","\u002Fimages\u002Fblog\u002FUpgradingNuxt.jpg","Two programmers working on a Nuxt upgrade project.",false,[374,464,1926],"migration",{},"\u002Fblog\u002F2026\u002Fnuxtv3to4",0,[69],"published",{"title":5,"description":1920},{"loc":1928},"blog\u002F2026\u002FNuxtV3to4","0D3ok4O-iJtPqaF5VJaXhQGECWiTMh_7TUAFLw46z3Q",1780531288483]