[{"data":1,"prerenderedAt":429},["ShallowReactive",2],{"i-base:v-logo":3,"i-lucide:user":8,"i-lucide:folder-kanban":11,"i-lucide:heart":13,"i-lucide:file-text":15,"i-lucide:sun":17,"i-lucide:github":19,"i-lucide:twitter":22,"i-lucide:linkedin":24,"i-simple-icons:reddit":26,"i-lucide:globe":28,"article-migrating-a-nuxt-site-from-cloudflare-pages-to-workers":30,"articles-all":384,"i-lucide:arrow-left":427},{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":7},0,512,false,"\u003Cg fill=\"currentColor\">\u003Cg transform=\"translate(0,512) scale(0.1,-0.1)\">\n    \u003Cpath d=\"M2866 3193 c-203 -209 -341 -393 -541 -718 -57 -93 -198 -309 -212 -325 -9 -9 -22 26 -28 75 -4 27 -8 61 -10 75 -2 14 -7 70 -10 125 -21 363 -72 541 -187 656 -30 30 -54 64 -56 78 -7 55 -65 113 -130 130 -21 6 -34 1 -62 -23 -64 -57 -86 -84 -97 -119 -12 -41 -9 -201 7 -349 6 -57 12 -204 12 -327 0 -191 2 -232 18 -270 10 -27 20 -89 24 -148 5 -92 21 -182 84 -478 12 -56 30 -105 46 -129 14 -21 27 -48 27 -60 1 -12 3 -39 4 -61 1 -23 8 -41 16 -44 8 -2 39 -31 69 -63 66 -72 98 -90 159 -91 133 -1 245 118 254 271 4 67 7 74 45 114 22 24 50 55 61 70 33 42 81 138 81 162 0 12 21 44 50 74 27 28 63 80 80 114 57 114 131 230 244 378 48 64 213 266 249 305 78 85 167 207 167 230 0 14 11 47 23 73 34 67 29 133 -20 252 l-38 95 -50 6 c-28 3 -67 13 -87 22 -21 10 -47 17 -58 17 -13 0 -62 -43 -134 -117z\"\u002F>\n    \u003Cpath d=\"M3070 1649 c-30 -44 -76 -96 -102 -115 -27 -20 -48 -40 -48 -45 0 -5 8 -21 17 -36 17 -25 17 -27 -5 -41 l-22 -14 30 -35 c17 -18 30 -39 30 -47 0 -36 34 -118 58 -140 102 -92 120 -104 159 -100 108 10 153 24 153 49 0 7 27 28 59 45 62 33 92 74 90 121 -1 13 10 57 25 97 32 87 33 90 17 165 -15 70 -24 75 -177 111 -159 38 -194 48 -200 57 -12 21 -32 4 -84 -72z\"\u002F>\n  \u003C\u002Fg>\u003C\u002Fg>",{"left":4,"top":4,"width":9,"height":9,"rotate":4,"vFlip":6,"hFlip":6,"body":10},24,"\u003Cg fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\">\u003Cpath d=\"M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2\"\u002F>\u003Ccircle cx=\"12\" cy=\"7\" r=\"4\"\u002F>\u003C\u002Fg>",{"left":4,"top":4,"width":9,"height":9,"rotate":4,"vFlip":6,"hFlip":6,"body":12},"\u003Cpath fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M4 20h16a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.93a2 2 0 0 1-1.66-.9l-.82-1.2A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13c0 1.1.9 2 2 2m4-10v4m4-4v2m4-2v6\"\u002F>",{"left":4,"top":4,"width":9,"height":9,"rotate":4,"vFlip":6,"hFlip":6,"body":14},"\u003Cpath fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M2 9.5a5.5 5.5 0 0 1 9.591-3.676a.56.56 0 0 0 .818 0A5.49 5.49 0 0 1 22 9.5c0 2.29-1.5 4-3 5.5l-5.492 5.313a2 2 0 0 1-3 .019L5 15c-1.5-1.5-3-3.2-3-5.5\"\u002F>",{"left":4,"top":4,"width":9,"height":9,"rotate":4,"vFlip":6,"hFlip":6,"body":16},"\u003Cg fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\">\u003Cpath d=\"M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z\"\u002F>\u003Cpath d=\"M14 2v5a1 1 0 0 0 1 1h5M10 9H8m8 4H8m8 4H8\"\u002F>\u003C\u002Fg>",{"left":4,"top":4,"width":9,"height":9,"rotate":4,"vFlip":6,"hFlip":6,"body":18},"\u003Cg fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\">\u003Ccircle cx=\"12\" cy=\"12\" r=\"4\"\u002F>\u003Cpath d=\"M12 2v2m0 16v2M4.93 4.93l1.41 1.41m11.32 11.32l1.41 1.41M2 12h2m16 0h2M6.34 17.66l-1.41 1.41M19.07 4.93l-1.41 1.41\"\u002F>\u003C\u002Fg>",{"left":4,"top":4,"width":9,"height":9,"rotate":4,"vFlip":6,"hFlip":6,"body":20,"hidden":21},"\u003Cg fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\">\u003Cpath d=\"M15 22v-4a4.8 4.8 0 0 0-1-3.5c3 0 6-2 6-5.5c.08-1.25-.27-2.48-1-3.5c.28-1.15.28-2.35 0-3.5c0 0-1 0-3 1.5c-2.64-.5-5.36-.5-8 0C6 2 5 2 5 2c-.3 1.15-.3 2.35 0 3.5A5.4 5.4 0 0 0 4 9c0 3.5 3 5.5 6 5.5c-.39.49-.68 1.05-.85 1.65S8.93 17.38 9 18v4\"\u002F>\u003Cpath d=\"M9 18c-4.51 2-5-2-7-2\"\u002F>\u003C\u002Fg>",true,{"left":4,"top":4,"width":9,"height":9,"rotate":4,"vFlip":6,"hFlip":6,"body":23,"hidden":21},"\u003Cpath fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M22 4s-.7 2.1-2 3.4c1.6 10-9.4 17.3-18 11.6c2.2.1 4.4-.6 6-2C3 15.5.5 9.6 3 5c2.2 2.6 5.6 4.1 9 4c-.9-4.2 4-6.6 7-3.8c1.1 0 3-1.2 3-1.2\"\u002F>",{"left":4,"top":4,"width":9,"height":9,"rotate":4,"vFlip":6,"hFlip":6,"body":25,"hidden":21},"\u003Cg fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\">\u003Cpath d=\"M16 8a6 6 0 0 1 6 6v7h-4v-7a2 2 0 0 0-2-2a2 2 0 0 0-2 2v7h-4v-7a6 6 0 0 1 6-6M2 9h4v12H2z\"\u002F>\u003Ccircle cx=\"4\" cy=\"4\" r=\"2\"\u002F>\u003C\u002Fg>",{"left":4,"top":4,"width":9,"height":9,"rotate":4,"vFlip":6,"hFlip":6,"body":27},"\u003Cpath fill=\"currentColor\" d=\"M12 0C5.373 0 0 5.373 0 12c0 3.314 1.343 6.314 3.515 8.485l-2.286 2.286A.72.72 0 0 0 1.738 24H12c6.627 0 12-5.373 12-12S18.627 0 12 0m4.388 3.199a1.999 1.999 0 1 1-1.947 2.46v.002a2.37 2.37 0 0 0-2.032 2.341v.007c1.776.067 3.4.567 4.686 1.363a2.802 2.802 0 1 1 2.908 4.753c-.088 3.256-3.637 5.876-7.997 5.876c-4.361 0-7.905-2.617-7.998-5.87a2.8 2.8 0 0 1 1.189-5.34c.645 0 1.239.218 1.712.585c1.275-.79 2.881-1.291 4.64-1.365v-.01a3.23 3.23 0 0 1 2.88-3.207a2 2 0 0 1 1.959-1.595m-8.085 8.376c-.784 0-1.459.78-1.506 1.797s.64 1.429 1.426 1.429s1.371-.369 1.418-1.385s-.553-1.841-1.338-1.841m7.406 0c-.786 0-1.385.824-1.338 1.841s.634 1.385 1.418 1.385c.785 0 1.473-.413 1.426-1.429c-.046-1.017-.721-1.797-1.506-1.797m-3.703 4.013c-.974 0-1.907.048-2.77.135a.222.222 0 0 0-.183.305a3.2 3.2 0 0 0 2.953 1.964a3.2 3.2 0 0 0 2.953-1.964a.222.222 0 0 0-.184-.305a28 28 0 0 0-2.769-.135\"\u002F>",{"left":4,"top":4,"width":9,"height":9,"rotate":4,"vFlip":6,"hFlip":6,"body":29},"\u003Cg fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\">\u003Ccircle cx=\"12\" cy=\"12\" r=\"10\"\u002F>\u003Cpath d=\"M12 2a14.5 14.5 0 0 0 0 20a14.5 14.5 0 0 0 0-20M2 12h20\"\u002F>\u003C\u002Fg>",{"id":31,"title":32,"body":33,"category":368,"date":369,"description":370,"extension":371,"image":372,"meta":373,"navigation":21,"path":374,"seo":375,"status":376,"stem":377,"tags":378,"updatedAt":372,"__hash__":383},"articles\u002Farticles\u002F5.migrating-a-nuxt-site-from-cloudflare-pages-to-workers.md","Migrating a Nuxt site from Cloudflare Pages to Workers",{"type":34,"value":35,"toc":362},"minimark",[36,46,49,54,70,255,266,286,290,298,305,308,315,319,345,351,355,358],[37,38,39,40,45],"p",{},"I moved this site off Cloudflare Pages and onto a Cloudflare Worker. The reasons were concrete: Workers gives you the ",[41,42,44],"a",{"href":43},"\u002Farticles\u002Ftil-workers-cache-nitro-passthrough","Workers Cache API",", smart placement, per-Worker observability, and a deploy model that no longer treats the framework output as a second-class citizen. Pages had served the site fine for years, but the ceiling was lower than where I wanted to build.",[37,47,48],{},"Here is what the migration actually involved, including the parts no tutorial warns you about.",[50,51,53],"h2",{"id":52},"the-preset-and-the-deploy-config","The preset and the deploy config",[37,55,56,57,61,62,65,66,69],{},"The core change is the Nitro preset. Pages uses ",[58,59,60],"code",{},"cloudflare-pages","; a Worker uses ",[58,63,64],{},"cloudflare_module",". With the module preset you also inline the deploy config so Nitro generates a complete ",[58,67,68],{},"wrangler.json"," at build time:",[71,72,77],"pre",{"className":73,"code":74,"language":75,"meta":76,"style":76},"language-ts shiki shiki-themes github-dark github-dark github-light","export default defineNuxtConfig({\n  nitro: {\n    preset: 'cloudflare_module',\n    cloudflare: {\n      deployConfig: true,\n      wrangler: {\n        name: 'my-site',\n        workers_dev: false,\n        d1_databases: [\n          { binding: 'DB', database_name: 'my-site-db', database_id: '...' },\n        ],\n        cache: { enabled: true },\n        observability: { enabled: true },\n        placement: { mode: 'smart' },\n      },\n    },\n  },\n});\n","ts","",[58,78,79,99,105,118,124,136,142,153,164,170,194,200,210,220,231,237,243,249],{"__ignoreMap":76},[80,81,84,88,91,95],"span",{"class":82,"line":83},"line",1,[80,85,87],{"class":86},"s6ubI","export",[80,89,90],{"class":86}," default",[80,92,94],{"class":93},"s5n6i"," defineNuxtConfig",[80,96,98],{"class":97},"sAvwS","({\n",[80,100,102],{"class":82,"line":101},2,[80,103,104],{"class":97},"  nitro: {\n",[80,106,108,111,115],{"class":82,"line":107},3,[80,109,110],{"class":97},"    preset: ",[80,112,114],{"class":113},"s4Y1p","'cloudflare_module'",[80,116,117],{"class":97},",\n",[80,119,121],{"class":82,"line":120},4,[80,122,123],{"class":97},"    cloudflare: {\n",[80,125,127,130,134],{"class":82,"line":126},5,[80,128,129],{"class":97},"      deployConfig: ",[80,131,133],{"class":132},"sXWYR","true",[80,135,117],{"class":97},[80,137,139],{"class":82,"line":138},6,[80,140,141],{"class":97},"      wrangler: {\n",[80,143,145,148,151],{"class":82,"line":144},7,[80,146,147],{"class":97},"        name: ",[80,149,150],{"class":113},"'my-site'",[80,152,117],{"class":97},[80,154,156,159,162],{"class":82,"line":155},8,[80,157,158],{"class":97},"        workers_dev: ",[80,160,161],{"class":132},"false",[80,163,117],{"class":97},[80,165,167],{"class":82,"line":166},9,[80,168,169],{"class":97},"        d1_databases: [\n",[80,171,173,176,179,182,185,188,191],{"class":82,"line":172},10,[80,174,175],{"class":97},"          { binding: ",[80,177,178],{"class":113},"'DB'",[80,180,181],{"class":97},", database_name: ",[80,183,184],{"class":113},"'my-site-db'",[80,186,187],{"class":97},", database_id: ",[80,189,190],{"class":113},"'...'",[80,192,193],{"class":97}," },\n",[80,195,197],{"class":82,"line":196},11,[80,198,199],{"class":97},"        ],\n",[80,201,203,206,208],{"class":82,"line":202},12,[80,204,205],{"class":97},"        cache: { enabled: ",[80,207,133],{"class":132},[80,209,193],{"class":97},[80,211,213,216,218],{"class":82,"line":212},13,[80,214,215],{"class":97},"        observability: { enabled: ",[80,217,133],{"class":132},[80,219,193],{"class":97},[80,221,223,226,229],{"class":82,"line":222},14,[80,224,225],{"class":97},"        placement: { mode: ",[80,227,228],{"class":113},"'smart'",[80,230,193],{"class":97},[80,232,234],{"class":82,"line":233},15,[80,235,236],{"class":97},"      },\n",[80,238,240],{"class":82,"line":239},16,[80,241,242],{"class":97},"    },\n",[80,244,246],{"class":82,"line":245},17,[80,247,248],{"class":97},"  },\n",[80,250,252],{"class":82,"line":251},18,[80,253,254],{"class":97},"});\n",[37,256,257,258,261,262,265],{},"Because Nitro passes arbitrary keys in that ",[58,259,260],{},"wrangler"," block straight through, you configure the whole Worker here: the D1 binding, smart placement, observability, and Workers Cache all live in one place. I deleted the standalone ",[58,263,264],{},"wrangler.jsonc"," entirely; the generated file is now the source of truth. The CD step changed to deploy that generated file directly:",[71,267,271],{"className":268,"code":269,"language":270,"meta":76,"style":76},"language-bash shiki shiki-themes github-dark github-dark github-light","wrangler deploy --config .output\u002Fserver\u002Fwrangler.json\n","bash",[58,272,273],{"__ignoreMap":76},[80,274,275,277,280,283],{"class":82,"line":83},[80,276,260],{"class":93},[80,278,279],{"class":113}," deploy",[80,281,282],{"class":132}," --config",[80,284,285],{"class":113}," .output\u002Fserver\u002Fwrangler.json\n",[50,287,289],{"id":288},"the-custom-domain-cutover-nobody-automates","The custom-domain cutover nobody automates",[37,291,292,293,297],{},"This is the part that surprised me. Deploying the Worker does ",[294,295,296],"strong",{},"not"," move your custom domain to it.",[37,299,300,301,304],{},"My site was a proxied CNAME pointing at the Pages project. The Pages project owned the domain. When I deployed the Worker with ",[58,302,303],{},"workers_dev: false"," and no routes, Wrangler reported \"No targets deployed\", which is technically correct: the Worker had nowhere to serve from because the domain still belonged to Pages.",[37,306,307],{},"There is no deploy flag for this. You move the custom domain from the Pages project to the Worker manually in the Cloudflare dashboard. It is a one-time, user-driven step, and it is the moment the switch actually happens. Everything before it is preparation.",[37,309,310,311,314],{},"One nice side effect: after the cutover, the Worker's own ",[58,312,313],{},"robots.txt"," route replaced Cloudflare's managed AI-bot block automatically. I did not need a separate toggle. Your MX and TXT records (mail, SPF) are untouched throughout, since you are only re-pointing the site's hostname.",[50,316,318],{"id":317},"two-gotchas-that-only-appeared-in-ci","Two gotchas that only appeared in CI",[37,320,321,324,325,328,329,332,333,336,337,340,341,344],{},[294,322,323],{},"Formatting shims."," This repo runs ",[58,326,327],{},"oxfmt"," and ",[58,330,331],{},"oxlint"," through vite-plus LSP shims. Running the shimmed formatter locally corrupted source files: doubled quotes, mangled strings. The fix was to call the real binaries directly (",[58,334,335],{},".\u002Fnode_modules\u002F.bin\u002Foxfmt",", ",[58,338,339],{},".\u002Fnode_modules\u002F.bin\u002Foxlint","). CI was fine because it invokes them through ",[58,342,343],{},"pnpm run",", which resolves the real binaries. So the corruption only happened in local ad-hoc runs, which is exactly the kind of divergence that wastes an afternoon.",[37,346,347,350],{},[294,348,349],{},"A quality gate that passed locally and failed in CI."," I run a doctor action on deploy. It passed identically on my machine (zero errors, healthy score, HTTP 200) but failed in CI. One real cause was findable and fixed: the action was forwarding an invalid preset value. A second divergence I could not reproduce. Rather than chase a CI-only ghost that was blocking every deploy, I made the gate advisory: it still reports and comments on pull requests, but it no longer sits in the deploy's critical path. Advisory-but-visible beats blocking-but-flaky.",[50,352,354],{"id":353},"was-it-worth-it","Was it worth it",[37,356,357],{},"Yes, but be honest about the shape of the work. The config migration is an afternoon. The custom-domain cutover is five minutes of dashboard clicking that you cannot script. The long tail is the CI divergences, which are where the real time goes. Budget for the tail, not the config.",[359,360,361],"style",{},"html pre.shiki code .s6ubI, html code.shiki .s6ubI{--shiki-default:#F97583;--shiki-dark:#F97583;--shiki-light:#D73A49}html pre.shiki code .s5n6i, html code.shiki .s5n6i{--shiki-default:#B392F0;--shiki-dark:#B392F0;--shiki-light:#6F42C1}html pre.shiki code .sAvwS, html code.shiki .sAvwS{--shiki-default:#E1E4E8;--shiki-dark:#E1E4E8;--shiki-light:#24292E}html pre.shiki code .s4Y1p, html code.shiki .s4Y1p{--shiki-default:#9ECBFF;--shiki-dark:#9ECBFF;--shiki-light:#032F62}html pre.shiki code .sXWYR, html code.shiki .sXWYR{--shiki-default:#79B8FF;--shiki-dark:#79B8FF;--shiki-light:#005CC5}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 .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}",{"title":76,"searchDepth":101,"depth":101,"links":363},[364,365,366,367],{"id":52,"depth":101,"text":53},{"id":288,"depth":101,"text":289},{"id":317,"depth":101,"text":318},{"id":353,"depth":101,"text":354},"cloudflare","2026-07-06T21:00:00.000+05:30","The full path from the cloudflare-pages preset to a cloudflare_module Worker: the config changes, the custom-domain cutover that no deploy step handles for you, and the gotchas that only show up in CI.","md",null,{"position":126},"\u002Farticles\u002Fmigrating-a-nuxt-site-from-cloudflare-pages-to-workers",{"title":32,"description":370},"published","articles\u002F5.migrating-a-nuxt-site-from-cloudflare-pages-to-workers",[368,379,380,381,382],"workers","nuxt","nitro","devops","0rSn-N7IzVjwz3YkpWgd5_pOxUeMN63uvCgUOI7678U",[385,394,402,404,413,418],{"path":386,"title":387,"description":388,"date":389,"updatedAt":372,"category":380,"tags":390,"image":372,"status":376},"\u002Farticles\u002Ftil-shiki-multitheme-code-block-background","TIL: Shiki multi-theme highlighting does not switch the code-block background","Shiki multi-theme mode swaps token colours per colour scheme but leaves the pre background variable empty, so light-theme text can land on a dark block. You have to theme the container yourself.","2026-07-07T02:30:00.000+05:30",[380,391,392,393],"shiki","nuxt-content","dark-mode",{"path":395,"title":396,"description":397,"date":398,"updatedAt":372,"category":368,"tags":399,"image":372,"status":376},"\u002Farticles\u002Fdynamic-og-images-on-cloudflare-workers","Generating dynamic Open Graph images on Cloudflare Workers","Rendering per-page and per-article social cards at the edge with Satori and @cf-wasm\u002Fog: how the route works, what Satori refuses to render, and the cold-versus-warm numbers.","2026-07-06T22:00:00.000+05:30",[368,379,400,401,380],"open-graph","satori",{"path":374,"title":32,"description":370,"date":369,"updatedAt":372,"category":368,"tags":403,"image":372,"status":376},[368,379,380,381,382],{"path":405,"title":406,"description":407,"date":408,"updatedAt":372,"category":409,"tags":410,"image":372,"status":376},"\u002Farticles\u002Ftil-tailwind-v4-webkit-mask-prefix","TIL: Tailwind v4 mask utilities need the webkit prefix in plain CSS","Porting a Tailwind mask-composite utility to scoped CSS quietly breaks in Chrome and Safari unless you also write the -webkit-mask-* properties, because Tailwind was emitting them for you.","2026-07-06T20:15:00.000+05:30","css",[411,409,412],"tailwind","webkit",{"path":43,"title":414,"description":415,"date":416,"updatedAt":372,"category":368,"tags":417,"image":372,"status":376},"TIL: Enabling Workers Cache through Nitro without a native option","Nitro forwards arbitrary keys into the generated wrangler config, so you can turn on Cloudflare Workers Cache with a single line even though there is no dedicated Nitro option for it.","2026-07-06T14:30:00.000+05:30",[368,379,381,380],{"path":419,"title":420,"description":421,"date":422,"updatedAt":372,"category":423,"tags":424,"image":372,"status":376},"\u002Farticles\u002Fbuild-and-publish-vue-3-components-using-rollup","Build & Publish Vue 3 Components using Rollup.js","Let's build a reusable Vue 3 component using rollup","2022-07-04T16:20:09.000+05:30","vue",[425,426],"vue 3","rollup",{"left":4,"top":4,"width":9,"height":9,"rotate":4,"vFlip":6,"hFlip":6,"body":428},"\u003Cpath fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"m12 19l-7-7l7-7m7 7H5\"\u002F>",1783374868970]