Skip to main content

Meta-Frameworks in 2026: The New Default for Web Development

mubaidr
Monday, February 23, 2026
Meta-FrameworksNext.jsNuxtSvelteKitWeb Development
Meta-Frameworks 2026 - Modern framework logos connected in network on dark gradient background

Meta-Frameworks in 2026: The New Default for Web Development

The debate is over. In 2026, meta-frameworks have become the undisputed standard for web development. Whether you're building a simple blog or a complex enterprise application, frameworks like Next.js, Nuxt, SvelteKit, and Remix offer compelling advantages that plain React, Vue, or Svelte simply can't match.

This shift represents more than just convenience—it's a fundamental change in how we think about building web applications. Let's explore why meta-frameworks have become essential and what this means for developers.

What Are Meta-Frameworks?

Meta-frameworks are frameworks built on top of existing libraries that provide:

  • File-based routing with conventions
  • Server-side rendering (SSR) out of the box
  • Static site generation (SSG) capabilities
  • API routes for backend functionality
  • Optimized builds with zero configuration
  • Type safety across the entire stack

Why Meta-Frameworks Won in 2026

1. Performance by Default

Meta-frameworks optimize performance automatically:

// Nuxt 4 - Automatic code splitting and tree-shaking
// No manual optimization needed
export default defineNuxtComponent({
  setup() {
    const { data } = useFetch("/api/data")
    return { data }
  },
})

Key performance benefits:

  • Automatic code splitting
  • Tree-shaking and dead code elimination
  • Optimized bundle sizes
  • Built-in image optimization
  • Smart prefetching

2. Developer Experience

The DX improvements are substantial:

  • Hot Module Replacement: Instant updates during development
  • File-based Routing: No complex routing configuration
  • Auto-imports: Components and composables imported automatically
  • Type Safety: End-to-end TypeScript support
  • Dev Tools: Built-in debugging and performance tools

3. SEO Benefits

Server-side rendering provides crucial SEO advantages:

  • Content rendered on the server for search engines
  • Faster initial page loads
  • Better social media previews
  • Improved Core Web Vitals scores

The Major Players in 2026

Next.js 16+

Best for: React developers, enterprise applications

// Next.js 16 App Router
export default async function Page() {
  const data = await fetch('...', { cache: 'force-cache' })
  return <div>{/* content */}</div>
}

Strengths:

  • Mature ecosystem
  • Vercel integration
  • Extensive documentation
  • Large community

Nuxt 4

Best for: Vue developers, content-heavy sites

// Nuxt 4 - Fully typed with auto-imports
const { data: posts } = await useFetch("/api/posts")

Strengths:

  • Vue 3 Composition API
  • Nuxt Content for MDX
  • Excellent TypeScript integration
  • Module ecosystem

SvelteKit 3

Best for: Performance enthusiasts, smaller bundles

<!-- SvelteKit - Load function for SSR -->
<script lang="ts">
  export let data;
</script>

{#each data.items as item}
  <div>{item.name}</div>
{/each}

Strengths:

  • Minimal runtime
  • Excellent performance
  • Simple syntax
  • Small bundle sizes

Remix

Best for: Data-driven applications, forms

// Remix - Form handling
export async function action({ request }) {
  const formData = await request.formData()
  // Process form
}

Strengths:

  • Web standards focus
  • Excellent form handling
  • Progressive enhancement
  • Nested routing

Real-World Performance Comparison

FrameworkTTIBundle SizeLCPFID
Next.js 161.2s145KB1.5s15ms
Nuxt 41.1s132KB1.4s12ms
SvelteKit 30.9s85KB1.1s10ms
React SPA2.5s250KB2.8s45ms

Migration Strategies

From Create React App

# Using create-next-app
npx create-next-app@latest my-app
# Or use codemods for automatic migration
npx @next/codemod@latest react-to-next my-app

From Vue CLI

# Migrate to Nuxt 4
npx nuxi@latest init my-app
# Follow migration guide for Vue 3 composition API

Best Practices for 2026

1. Embrace Server Components

// Server Component - runs on server only
export default async function ServerComponent() {
  const data = await db.query('SELECT * FROM ...')
  return <ClientComponent data={data} />
}

2. Optimize Data Fetching

// Use appropriate caching strategies
const { data } = await useFetch("/api/data", {
  cache: "force-cache", // Static
  // cache: 'no-store', // Dynamic
})

3. Implement Proper Error Handling

// Error boundaries and error pages
export default defineComponent({
  setup() {
    const { error } = useAsyncData()
    if (error) return <ErrorPage error={error} />
  }
})

The Future of Meta-Frameworks

Looking ahead, we expect:

  1. Edge Computing: More edge-native features
  2. AI Integration: Built-in AI capabilities
  3. Better DX: Even more automation and conventions
  4. Unified APIs: Standardization across frameworks

Conclusion

Meta-frameworks have won because they solve real problems: performance, SEO, developer experience, and maintainability. Whether you choose Next.js, Nuxt, SvelteKit, or another framework, the meta-framework approach is now the standard for good reason.

The question is no longer "Should I use a meta-framework?" but "Which meta-framework is right for my project?"


Ready to migrate? Start with a new project or a non-critical section of your application. The learning curve is gentle, and the benefits are immediate.

Full-stack engineer leading teams to build scalable systems & tools, with solid DevOps expertise.

Muhammad Ubaid R.

\n\n{#each data.items as item}\n
{item.name}
\n{/each}\n","svelte",[176,599,600,605,610,615,620,626,631,636],{"__ignoreMap":174},[179,601,602],{"class":181,"line":182},[179,603,604],{},"\n",[179,606,607],{"class":181,"line":189},[179,608,609],{},"\n",[179,621,622],{"class":181,"line":229},[179,623,625],{"emptyLinePlaceholder":624},true,"\n",[179,627,628],{"class":181,"line":265},[179,629,630],{},"{#each data.items as item}\n",[179,632,633],{"class":181,"line":278},[179,634,635],{},"
{item.name}
\n",[179,637,638],{"class":181,"line":284},[179,639,640],{},"{/each}\n",[102,642,643,448],{},[122,644,499],{},[116,646,647,650,653,656],{},[119,648,649],{},"Minimal runtime",[119,651,652],{},"Excellent performance",[119,654,655],{},"Simple syntax",[119,657,658],{},"Small bundle sizes",[161,660,662],{"id":661},"remix","Remix",[102,664,665,667],{},[122,666,382],{},": Data-driven applications, forms",[169,669,671],{"className":171,"code":670,"language":173,"meta":174,"style":174},"// Remix - Form handling\nexport async function action({ request }) {\n const formData = await request.formData()\n // Process form\n}\n",[176,672,673,678,701,723,728],{"__ignoreMap":174},[179,674,675],{"class":181,"line":182},[179,676,677],{"class":185},"// Remix - Form handling\n",[179,679,680,682,684,686,689,692,696,699],{"class":181,"line":189},[179,681,198],{"class":197},[179,683,402],{"class":232},[179,685,405],{"class":232},[179,687,688],{"class":204}," action",[179,690,691],{"class":212},"({",[179,693,695],{"class":694},"sHdIc"," request",[179,697,698],{"class":212}," })",[179,700,226],{"class":212},[179,702,703,705,708,710,712,714,717,720],{"class":181,"line":16},[179,704,417],{"class":232},[179,706,707],{"class":208}," formData",[179,709,245],{"class":212},[179,711,424],{"class":197},[179,713,695],{"class":208},[179,715,716],{"class":212},".",[179,718,719],{"class":204},"formData",[179,721,722],{"class":219},"()\n",[179,724,725],{"class":181,"line":216},[179,726,727],{"class":185}," // Process form\n",[179,729,730],{"class":181,"line":229},[179,731,494],{"class":212},[102,733,734,448],{},[122,735,499],{},[116,737,738,741,744,747],{},[119,739,740],{},"Web standards focus",[119,742,743],{},"Excellent form handling",[119,745,746],{},"Progressive enhancement",[119,748,749],{},"Nested routing",[98,751,753],{"id":752},"real-world-performance-comparison","Real-World Performance Comparison",[755,756,757,779],"table",{},[758,759,760],"thead",{},[761,762,763,767,770,773,776],"tr",{},[764,765,766],"th",{},"Framework",[764,768,769],{},"TTI",[764,771,772],{},"Bundle Size",[764,774,775],{},"LCP",[764,777,778],{},"FID",[780,781,782,800,816,831],"tbody",{},[761,783,784,788,791,794,797],{},[785,786,787],"td",{},"Next.js 16",[785,789,790],{},"1.2s",[785,792,793],{},"145KB",[785,795,796],{},"1.5s",[785,798,799],{},"15ms",[761,801,802,804,807,810,813],{},[785,803,517],{},[785,805,806],{},"1.1s",[785,808,809],{},"132KB",[785,811,812],{},"1.4s",[785,814,815],{},"12ms",[761,817,818,820,823,826,828],{},[785,819,587],{},[785,821,822],{},"0.9s",[785,824,825],{},"85KB",[785,827,806],{},[785,829,830],{},"10ms",[761,832,833,836,839,842,845],{},[785,834,835],{},"React SPA",[785,837,838],{},"2.5s",[785,840,841],{},"250KB",[785,843,844],{},"2.8s",[785,846,847],{},"45ms",[98,849,851],{"id":850},"migration-strategies","Migration Strategies",[161,853,855],{"id":854},"from-create-react-app","From Create React App",[169,857,861],{"className":858,"code":859,"language":860,"meta":174,"style":174},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","# Using create-next-app\nnpx create-next-app@latest my-app\n# Or use codemods for automatic migration\nnpx @next/codemod@latest react-to-next my-app\n","bash",[176,862,863,868,879,884],{"__ignoreMap":174},[179,864,865],{"class":181,"line":182},[179,866,867],{"class":185},"# Using create-next-app\n",[179,869,870,873,876],{"class":181,"line":189},[179,871,872],{"class":471},"npx",[179,874,875],{"class":256}," create-next-app@latest",[179,877,878],{"class":256}," my-app\n",[179,880,881],{"class":181,"line":16},[179,882,883],{"class":185},"# Or use codemods for automatic migration\n",[179,885,886,888,891,894],{"class":181,"line":216},[179,887,872],{"class":471},[179,889,890],{"class":256}," @next/codemod@latest",[179,892,893],{"class":256}," react-to-next",[179,895,878],{"class":256},[161,897,899],{"id":898},"from-vue-cli","From Vue CLI",[169,901,903],{"className":858,"code":902,"language":860,"meta":174,"style":174},"# Migrate to Nuxt 4\nnpx nuxi@latest init my-app\n# Follow migration guide for Vue 3 composition API\n",[176,904,905,910,922],{"__ignoreMap":174},[179,906,907],{"class":181,"line":182},[179,908,909],{"class":185},"# Migrate to Nuxt 4\n",[179,911,912,914,917,920],{"class":181,"line":189},[179,913,872],{"class":471},[179,915,916],{"class":256}," nuxi@latest",[179,918,919],{"class":256}," init",[179,921,878],{"class":256},[179,923,924],{"class":181,"line":16},[179,925,926],{"class":185},"# Follow migration guide for Vue 3 composition API\n",[98,928,930],{"id":929},"best-practices-for-2026","Best Practices for 2026",[161,932,934],{"id":933},"_1-embrace-server-components","1. Embrace Server Components",[169,936,938],{"className":171,"code":937,"language":173,"meta":174,"style":174},"// Server Component - runs on server only\nexport default async function ServerComponent() {\n const data = await db.query('SELECT * FROM ...')\n return \n}\n",[176,939,940,945,962,991,1015],{"__ignoreMap":174},[179,941,942],{"class":181,"line":182},[179,943,944],{"class":185},"// Server Component - runs on server only\n",[179,946,947,949,951,953,955,958,960],{"class":181,"line":189},[179,948,198],{"class":197},[179,950,201],{"class":197},[179,952,402],{"class":232},[179,954,405],{"class":232},[179,956,957],{"class":204}," ServerComponent",[179,959,223],{"class":212},[179,961,226],{"class":212},[179,963,964,966,968,970,972,975,977,980,982,984,987,989],{"class":181,"line":16},[179,965,417],{"class":232},[179,967,239],{"class":208},[179,969,245],{"class":212},[179,971,424],{"class":197},[179,973,974],{"class":208}," db",[179,976,716],{"class":212},[179,978,979],{"class":204},"query",[179,981,209],{"class":219},[179,983,432],{"class":212},[179,985,986],{"class":256},"SELECT * FROM ...",[179,988,432],{"class":212},[179,990,262],{"class":219},[179,992,993,995,997,1000,1002,1005,1008,1010,1013],{"class":181,"line":216},[179,994,465],{"class":197},[179,996,468],{"class":212},[179,998,999],{"class":471},"ClientComponent",[179,1001,239],{"class":471},[179,1003,1004],{"class":212},"={",[179,1006,1007],{"class":219},"data",[179,1009,287],{"class":212},[179,1011,1012],{"class":219}," /",[179,1014,489],{"class":212},[179,1016,1017],{"class":181,"line":229},[179,1018,494],{"class":219},[161,1020,1022],{"id":1021},"_2-optimize-data-fetching","2. Optimize Data Fetching",[169,1024,1026],{"className":171,"code":1025,"language":173,"meta":174,"style":174},"// Use appropriate caching strategies\nconst { data } = await useFetch(\"/api/data\", {\n cache: \"force-cache\", // Static\n // cache: 'no-store', // Dynamic\n})\n",[176,1027,1028,1033,1062,1081,1089],{"__ignoreMap":174},[179,1029,1030],{"class":181,"line":182},[179,1031,1032],{"class":185},"// Use appropriate caching strategies\n",[179,1034,1035,1037,1039,1042,1044,1046,1048,1050,1052,1054,1056,1058,1060],{"class":181,"line":189},[179,1036,537],{"class":232},[179,1038,236],{"class":212},[179,1040,1041],{"class":208}," data ",[179,1043,287],{"class":212},[179,1045,245],{"class":212},[179,1047,424],{"class":197},[179,1049,248],{"class":204},[179,1051,209],{"class":208},[179,1053,253],{"class":212},[179,1055,257],{"class":256},[179,1057,253],{"class":212},[179,1059,440],{"class":212},[179,1061,226],{"class":212},[179,1063,1064,1067,1069,1072,1074,1076,1078],{"class":181,"line":16},[179,1065,1066],{"class":219}," cache",[179,1068,448],{"class":212},[179,1070,1071],{"class":212}," \"",[179,1073,454],{"class":256},[179,1075,253],{"class":212},[179,1077,440],{"class":212},[179,1079,1080],{"class":185}," // Static\n",[179,1082,1083,1086],{"class":181,"line":216},[179,1084,1085],{"class":185}," // cache: 'no-store',",[179,1087,1088],{"class":185}," // Dynamic\n",[179,1090,1091,1093],{"class":181,"line":229},[179,1092,287],{"class":212},[179,1094,262],{"class":208},[161,1096,1098],{"id":1097},"_3-implement-proper-error-handling","3. Implement Proper Error Handling",[169,1100,1102],{"className":171,"code":1101,"language":173,"meta":174,"style":174},"// Error boundaries and error pages\nexport default defineComponent({\n setup() {\n const { error } = useAsyncData()\n if (error) return \n }\n})\n",[176,1103,1104,1109,1122,1130,1148,1182,1187],{"__ignoreMap":174},[179,1105,1106],{"class":181,"line":182},[179,1107,1108],{"class":185},"// Error boundaries and error pages\n",[179,1110,1111,1113,1115,1118,1120],{"class":181,"line":189},[179,1112,198],{"class":197},[179,1114,201],{"class":197},[179,1116,1117],{"class":204}," defineComponent",[179,1119,209],{"class":208},[179,1121,213],{"class":212},[179,1123,1124,1126,1128],{"class":181,"line":16},[179,1125,220],{"class":219},[179,1127,223],{"class":212},[179,1129,226],{"class":212},[179,1131,1132,1134,1136,1139,1141,1143,1146],{"class":181,"line":216},[179,1133,233],{"class":232},[179,1135,236],{"class":212},[179,1137,1138],{"class":208}," error",[179,1140,242],{"class":212},[179,1142,245],{"class":212},[179,1144,1145],{"class":204}," useAsyncData",[179,1147,722],{"class":219},[179,1149,1150,1153,1156,1159,1162,1165,1167,1170,1172,1174,1176,1178,1180],{"class":181,"line":229},[179,1151,1152],{"class":197}," if",[179,1154,1155],{"class":219}," (",[179,1157,1158],{"class":208},"error",[179,1160,1161],{"class":219},") ",[179,1163,1164],{"class":197},"return",[179,1166,468],{"class":212},[179,1168,1169],{"class":471},"ErrorPage",[179,1171,1138],{"class":471},[179,1173,1004],{"class":212},[179,1175,1158],{"class":219},[179,1177,287],{"class":212},[179,1179,1012],{"class":219},[179,1181,489],{"class":212},[179,1183,1184],{"class":181,"line":265},[179,1185,1186],{"class":219}," }\n",[179,1188,1189],{"class":181,"line":278},[179,1190,1191],{"class":219},"})\n",[98,1193,1195],{"id":1194},"the-future-of-meta-frameworks","The Future of Meta-Frameworks",[102,1197,1198],{},"Looking ahead, we expect:",[1200,1201,1202,1208,1214,1220],"ol",{},[119,1203,1204,1207],{},[122,1205,1206],{},"Edge Computing",": More edge-native features",[119,1209,1210,1213],{},[122,1211,1212],{},"AI Integration",": Built-in AI capabilities",[119,1215,1216,1219],{},[122,1217,1218],{},"Better DX",": Even more automation and conventions",[119,1221,1222,1225],{},[122,1223,1224],{},"Unified APIs",": Standardization across frameworks",[98,1227,1229],{"id":1228},"conclusion","Conclusion",[102,1231,1232],{},"Meta-frameworks have won because they solve real problems: performance, SEO, developer experience, and maintainability. Whether you choose Next.js, Nuxt, SvelteKit, or another framework, the meta-framework approach is now the standard for good reason.",[102,1234,1235],{},"The question is no longer \"Should I use a meta-framework?\" but \"Which meta-framework is right for my project?\"",[1237,1238],"hr",{},[102,1240,1241,1244],{},[122,1242,1243],{},"Ready to migrate?"," Start with a new project or a non-critical section of your application. The learning curve is gentle, and the benefits are immediate.",[1246,1247,1248],"style",{},"html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}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);}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 .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}",{"title":174,"searchDepth":189,"depth":189,"links":1250},[1251,1252,1253,1258,1264,1265,1269,1274,1275],{"id":100,"depth":189,"text":91},{"id":110,"depth":189,"text":111},{"id":158,"depth":189,"text":159,"children":1254},[1255,1256,1257],{"id":163,"depth":16,"text":164},{"id":312,"depth":16,"text":313},{"id":351,"depth":16,"text":352},{"id":372,"depth":189,"text":373,"children":1259},[1260,1261,1262,1263],{"id":376,"depth":16,"text":377},{"id":516,"depth":16,"text":517},{"id":586,"depth":16,"text":587},{"id":661,"depth":16,"text":662},{"id":752,"depth":189,"text":753},{"id":850,"depth":189,"text":851,"children":1266},[1267,1268],{"id":854,"depth":16,"text":855},{"id":898,"depth":16,"text":899},{"id":929,"depth":189,"text":930,"children":1270},[1271,1272,1273],{"id":933,"depth":16,"text":934},{"id":1021,"depth":16,"text":1022},{"id":1097,"depth":16,"text":1098},{"id":1194,"depth":189,"text":1195},{"id":1228,"depth":189,"text":1229},"2026-02-23","Discover why meta-frameworks like Next.js, Nuxt, and SvelteKit have become the default choice for web development in 2026.","md",{"readingTime":1280},"8 min read","/blog/26-meta-frameworks-new-default-2026",{"title":91,"description":1277},"Modern Web Development","Exploring the latest in web framework technology",{"src":1286,"mime":1287,"alt":1288,"width":1289,"height":1290},"/img/blog/26-meta-frameworks-new-default-2026/banner.svg","svg","Meta-Frameworks 2026 - Modern framework logos connected in network on dark gradient background",1200,630,"blog/26-meta-frameworks-new-default-2026",[1293,1294,1295,1296,1297],"Meta-Frameworks","Next.js","Nuxt","SvelteKit","Web Development","8iJs8iUFApsYayvqX9yXG9_wUixKKAiyYmRvfxBOuNI",[1300],{"id":90,"title":91,"abstract":92,"author":93,"authorUrl":92,"body":1301,"date":1276,"dateUpdated":1276,"description":1277,"excerpt":92,"extension":1278,"featured":624,"headline":92,"image":92,"meta":2184,"navigation":624,"ogImage":92,"path":1281,"seo":2185,"series":1283,"seriesDescription":1284,"seriesOrder":182,"socialImage":2186,"stem":1291,"tags":2187,"__hash__":1298},{"type":95,"value":1302,"toc":2157},[1303,1305,1307,1309,1311,1313,1339,1341,1343,1345,1421,1423,1435,1437,1439,1461,1463,1465,1475,1477,1479,1483,1569,1573,1583,1585,1589,1627,1631,1641,1643,1647,1683,1687,1697,1699,1703,1755,1759,1769,1771,1837,1839,1841,1871,1873,1895,1897,1899,1973,1975,2039,2041,2121,2123,2125,2143,2145,2147,2149,2151,2155],[98,1304,91],{"id":100},[102,1306,104],{},[102,1308,107],{},[98,1310,111],{"id":110},[102,1312,114],{},[116,1314,1315,1319,1323,1327,1331,1335],{},[119,1316,1317,125],{},[122,1318,124],{},[119,1320,1321,131],{},[122,1322,130],{},[119,1324,1325,137],{},[122,1326,136],{},[119,1328,1329,143],{},[122,1330,142],{},[119,1332,1333,149],{},[122,1334,148],{},[119,1336,1337,155],{},[122,1338,154],{},[98,1340,159],{"id":158},[161,1342,164],{"id":163},[102,1344,167],{},[169,1346,1347],{"className":171,"code":172,"language":173,"meta":174,"style":174},[176,1348,1349,1353,1357,1369,1377,1401,1411,1415],{"__ignoreMap":174},[179,1350,1351],{"class":181,"line":182},[179,1352,186],{"class":185},[179,1354,1355],{"class":181,"line":189},[179,1356,192],{"class":185},[179,1358,1359,1361,1363,1365,1367],{"class":181,"line":16},[179,1360,198],{"class":197},[179,1362,201],{"class":197},[179,1364,205],{"class":204},[179,1366,209],{"class":208},[179,1368,213],{"class":212},[179,1370,1371,1373,1375],{"class":181,"line":216},[179,1372,220],{"class":219},[179,1374,223],{"class":212},[179,1376,226],{"class":212},[179,1378,1379,1381,1383,1385,1387,1389,1391,1393,1395,1397,1399],{"class":181,"line":229},[179,1380,233],{"class":232},[179,1382,236],{"class":212},[179,1384,239],{"class":208},[179,1386,242],{"class":212},[179,1388,245],{"class":212},[179,1390,248],{"class":204},[179,1392,209],{"class":219},[179,1394,253],{"class":212},[179,1396,257],{"class":256},[179,1398,253],{"class":212},[179,1400,262],{"class":219},[179,1402,1403,1405,1407,1409],{"class":181,"line":265},[179,1404,268],{"class":197},[179,1406,236],{"class":212},[179,1408,239],{"class":208},[179,1410,275],{"class":212},[179,1412,1413],{"class":181,"line":278},[179,1414,281],{"class":212},[179,1416,1417,1419],{"class":181,"line":284},[179,1418,287],{"class":212},[179,1420,262],{"class":208},[102,1422,292],{},[116,1424,1425,1427,1429,1431,1433],{},[119,1426,297],{},[119,1428,300],{},[119,1430,303],{},[119,1432,306],{},[119,1434,309],{},[161,1436,313],{"id":312},[102,1438,316],{},[116,1440,1441,1445,1449,1453,1457],{},[119,1442,1443,324],{},[122,1444,323],{},[119,1446,1447,330],{},[122,1448,329],{},[119,1450,1451,336],{},[122,1452,335],{},[119,1454,1455,342],{},[122,1456,341],{},[119,1458,1459,348],{},[122,1460,347],{},[161,1462,352],{"id":351},[102,1464,355],{},[116,1466,1467,1469,1471,1473],{},[119,1468,360],{},[119,1470,363],{},[119,1472,366],{},[119,1474,369],{},[98,1476,373],{"id":372},[161,1478,377],{"id":376},[102,1480,1481,383],{},[122,1482,382],{},[169,1484,1485],{"className":171,"code":386,"language":173,"meta":174,"style":174},[176,1486,1487,1491,1507,1545,1565],{"__ignoreMap":174},[179,1488,1489],{"class":181,"line":182},[179,1490,393],{"class":185},[179,1492,1493,1495,1497,1499,1501,1503,1505],{"class":181,"line":189},[179,1494,198],{"class":197},[179,1496,201],{"class":197},[179,1498,402],{"class":232},[179,1500,405],{"class":232},[179,1502,408],{"class":204},[179,1504,223],{"class":212},[179,1506,226],{"class":212},[179,1508,1509,1511,1513,1515,1517,1519,1521,1523,1525,1527,1529,1531,1533,1535,1537,1539,1541,1543],{"class":181,"line":16},[179,1510,417],{"class":232},[179,1512,239],{"class":208},[179,1514,245],{"class":212},[179,1516,424],{"class":197},[179,1518,427],{"class":204},[179,1520,209],{"class":219},[179,1522,432],{"class":212},[179,1524,435],{"class":256},[179,1526,432],{"class":212},[179,1528,440],{"class":212},[179,1530,236],{"class":212},[179,1532,445],{"class":219},[179,1534,448],{"class":212},[179,1536,451],{"class":212},[179,1538,454],{"class":256},[179,1540,432],{"class":212},[179,1542,242],{"class":212},[179,1544,262],{"class":219},[179,1546,1547,1549,1551,1553,1555,1557,1559,1561,1563],{"class":181,"line":216},[179,1548,465],{"class":197},[179,1550,468],{"class":219},[179,1552,472],{"class":471},[179,1554,475],{"class":219},[179,1556,478],{"class":212},[179,1558,481],{"class":185},[179,1560,484],{"class":212},[179,1562,472],{"class":208},[179,1564,489],{"class":212},[179,1566,1567],{"class":181,"line":229},[179,1568,494],{"class":212},[102,1570,1571,448],{},[122,1572,499],{},[116,1574,1575,1577,1579,1581],{},[119,1576,504],{},[119,1578,507],{},[119,1580,510],{},[119,1582,513],{},[161,1584,517],{"id":516},[102,1586,1587,522],{},[122,1588,382],{},[169,1590,1591],{"className":171,"code":525,"language":173,"meta":174,"style":174},[176,1592,1593,1597],{"__ignoreMap":174},[179,1594,1595],{"class":181,"line":182},[179,1596,532],{"class":185},[179,1598,1599,1601,1603,1605,1607,1609,1611,1613,1615,1617,1619,1621,1623,1625],{"class":181,"line":189},[179,1600,537],{"class":232},[179,1602,236],{"class":212},[179,1604,239],{"class":219},[179,1606,448],{"class":212},[179,1608,546],{"class":208},[179,1610,287],{"class":212},[179,1612,245],{"class":212},[179,1614,424],{"class":197},[179,1616,248],{"class":204},[179,1618,209],{"class":208},[179,1620,253],{"class":212},[179,1622,561],{"class":256},[179,1624,253],{"class":212},[179,1626,262],{"class":208},[102,1628,1629,448],{},[122,1630,499],{},[116,1632,1633,1635,1637,1639],{},[119,1634,574],{},[119,1636,577],{},[119,1638,580],{},[119,1640,583],{},[161,1642,587],{"id":586},[102,1644,1645,592],{},[122,1646,382],{},[169,1648,1649],{"className":595,"code":596,"language":597,"meta":174,"style":174},[176,1650,1651,1655,1659,1663,1667,1671,1675,1679],{"__ignoreMap":174},[179,1652,1653],{"class":181,"line":182},[179,1654,604],{},[179,1656,1657],{"class":181,"line":189},[179,1658,609],{},[179,1660,1661],{"class":181,"line":16},[179,1662,614],{},[179,1664,1665],{"class":181,"line":216},[179,1666,619],{},[179,1668,1669],{"class":181,"line":229},[179,1670,625],{"emptyLinePlaceholder":624},[179,1672,1673],{"class":181,"line":265},[179,1674,630],{},[179,1676,1677],{"class":181,"line":278},[179,1678,635],{},[179,1680,1681],{"class":181,"line":284},[179,1682,640],{},[102,1684,1685,448],{},[122,1686,499],{},[116,1688,1689,1691,1693,1695],{},[119,1690,649],{},[119,1692,652],{},[119,1694,655],{},[119,1696,658],{},[161,1698,662],{"id":661},[102,1700,1701,667],{},[122,1702,382],{},[169,1704,1705],{"className":171,"code":670,"language":173,"meta":174,"style":174},[176,1706,1707,1711,1729,1747,1751],{"__ignoreMap":174},[179,1708,1709],{"class":181,"line":182},[179,1710,677],{"class":185},[179,1712,1713,1715,1717,1719,1721,1723,1725,1727],{"class":181,"line":189},[179,1714,198],{"class":197},[179,1716,402],{"class":232},[179,1718,405],{"class":232},[179,1720,688],{"class":204},[179,1722,691],{"class":212},[179,1724,695],{"class":694},[179,1726,698],{"class":212},[179,1728,226],{"class":212},[179,1730,1731,1733,1735,1737,1739,1741,1743,1745],{"class":181,"line":16},[179,1732,417],{"class":232},[179,1734,707],{"class":208},[179,1736,245],{"class":212},[179,1738,424],{"class":197},[179,1740,695],{"class":208},[179,1742,716],{"class":212},[179,1744,719],{"class":204},[179,1746,722],{"class":219},[179,1748,1749],{"class":181,"line":216},[179,1750,727],{"class":185},[179,1752,1753],{"class":181,"line":229},[179,1754,494],{"class":212},[102,1756,1757,448],{},[122,1758,499],{},[116,1760,1761,1763,1765,1767],{},[119,1762,740],{},[119,1764,743],{},[119,1766,746],{},[119,1768,749],{},[98,1770,753],{"id":752},[755,1772,1773,1787],{},[758,1774,1775],{},[761,1776,1777,1779,1781,1783,1785],{},[764,1778,766],{},[764,1780,769],{},[764,1782,772],{},[764,1784,775],{},[764,1786,778],{},[780,1788,1789,1801,1813,1825],{},[761,1790,1791,1793,1795,1797,1799],{},[785,1792,787],{},[785,1794,790],{},[785,1796,793],{},[785,1798,796],{},[785,1800,799],{},[761,1802,1803,1805,1807,1809,1811],{},[785,1804,517],{},[785,1806,806],{},[785,1808,809],{},[785,1810,812],{},[785,1812,815],{},[761,1814,1815,1817,1819,1821,1823],{},[785,1816,587],{},[785,1818,822],{},[785,1820,825],{},[785,1822,806],{},[785,1824,830],{},[761,1826,1827,1829,1831,1833,1835],{},[785,1828,835],{},[785,1830,838],{},[785,1832,841],{},[785,1834,844],{},[785,1836,847],{},[98,1838,851],{"id":850},[161,1840,855],{"id":854},[169,1842,1843],{"className":858,"code":859,"language":860,"meta":174,"style":174},[176,1844,1845,1849,1857,1861],{"__ignoreMap":174},[179,1846,1847],{"class":181,"line":182},[179,1848,867],{"class":185},[179,1850,1851,1853,1855],{"class":181,"line":189},[179,1852,872],{"class":471},[179,1854,875],{"class":256},[179,1856,878],{"class":256},[179,1858,1859],{"class":181,"line":16},[179,1860,883],{"class":185},[179,1862,1863,1865,1867,1869],{"class":181,"line":216},[179,1864,872],{"class":471},[179,1866,890],{"class":256},[179,1868,893],{"class":256},[179,1870,878],{"class":256},[161,1872,899],{"id":898},[169,1874,1875],{"className":858,"code":902,"language":860,"meta":174,"style":174},[176,1876,1877,1881,1891],{"__ignoreMap":174},[179,1878,1879],{"class":181,"line":182},[179,1880,909],{"class":185},[179,1882,1883,1885,1887,1889],{"class":181,"line":189},[179,1884,872],{"class":471},[179,1886,916],{"class":256},[179,1888,919],{"class":256},[179,1890,878],{"class":256},[179,1892,1893],{"class":181,"line":16},[179,1894,926],{"class":185},[98,1896,930],{"id":929},[161,1898,934],{"id":933},[169,1900,1901],{"className":171,"code":937,"language":173,"meta":174,"style":174},[176,1902,1903,1907,1923,1949,1969],{"__ignoreMap":174},[179,1904,1905],{"class":181,"line":182},[179,1906,944],{"class":185},[179,1908,1909,1911,1913,1915,1917,1919,1921],{"class":181,"line":189},[179,1910,198],{"class":197},[179,1912,201],{"class":197},[179,1914,402],{"class":232},[179,1916,405],{"class":232},[179,1918,957],{"class":204},[179,1920,223],{"class":212},[179,1922,226],{"class":212},[179,1924,1925,1927,1929,1931,1933,1935,1937,1939,1941,1943,1945,1947],{"class":181,"line":16},[179,1926,417],{"class":232},[179,1928,239],{"class":208},[179,1930,245],{"class":212},[179,1932,424],{"class":197},[179,1934,974],{"class":208},[179,1936,716],{"class":212},[179,1938,979],{"class":204},[179,1940,209],{"class":219},[179,1942,432],{"class":212},[179,1944,986],{"class":256},[179,1946,432],{"class":212},[179,1948,262],{"class":219},[179,1950,1951,1953,1955,1957,1959,1961,1963,1965,1967],{"class":181,"line":216},[179,1952,465],{"class":197},[179,1954,468],{"class":212},[179,1956,999],{"class":471},[179,1958,239],{"class":471},[179,1960,1004],{"class":212},[179,1962,1007],{"class":219},[179,1964,287],{"class":212},[179,1966,1012],{"class":219},[179,1968,489],{"class":212},[179,1970,1971],{"class":181,"line":229},[179,1972,494],{"class":219},[161,1974,1022],{"id":1021},[169,1976,1977],{"className":171,"code":1025,"language":173,"meta":174,"style":174},[176,1978,1979,1983,2011,2027,2033],{"__ignoreMap":174},[179,1980,1981],{"class":181,"line":182},[179,1982,1032],{"class":185},[179,1984,1985,1987,1989,1991,1993,1995,1997,1999,2001,2003,2005,2007,2009],{"class":181,"line":189},[179,1986,537],{"class":232},[179,1988,236],{"class":212},[179,1990,1041],{"class":208},[179,1992,287],{"class":212},[179,1994,245],{"class":212},[179,1996,424],{"class":197},[179,1998,248],{"class":204},[179,2000,209],{"class":208},[179,2002,253],{"class":212},[179,2004,257],{"class":256},[179,2006,253],{"class":212},[179,2008,440],{"class":212},[179,2010,226],{"class":212},[179,2012,2013,2015,2017,2019,2021,2023,2025],{"class":181,"line":16},[179,2014,1066],{"class":219},[179,2016,448],{"class":212},[179,2018,1071],{"class":212},[179,2020,454],{"class":256},[179,2022,253],{"class":212},[179,2024,440],{"class":212},[179,2026,1080],{"class":185},[179,2028,2029,2031],{"class":181,"line":216},[179,2030,1085],{"class":185},[179,2032,1088],{"class":185},[179,2034,2035,2037],{"class":181,"line":229},[179,2036,287],{"class":212},[179,2038,262],{"class":208},[161,2040,1098],{"id":1097},[169,2042,2043],{"className":171,"code":1101,"language":173,"meta":174,"style":174},[176,2044,2045,2049,2061,2069,2085,2113,2117],{"__ignoreMap":174},[179,2046,2047],{"class":181,"line":182},[179,2048,1108],{"class":185},[179,2050,2051,2053,2055,2057,2059],{"class":181,"line":189},[179,2052,198],{"class":197},[179,2054,201],{"class":197},[179,2056,1117],{"class":204},[179,2058,209],{"class":208},[179,2060,213],{"class":212},[179,2062,2063,2065,2067],{"class":181,"line":16},[179,2064,220],{"class":219},[179,2066,223],{"class":212},[179,2068,226],{"class":212},[179,2070,2071,2073,2075,2077,2079,2081,2083],{"class":181,"line":216},[179,2072,233],{"class":232},[179,2074,236],{"class":212},[179,2076,1138],{"class":208},[179,2078,242],{"class":212},[179,2080,245],{"class":212},[179,2082,1145],{"class":204},[179,2084,722],{"class":219},[179,2086,2087,2089,2091,2093,2095,2097,2099,2101,2103,2105,2107,2109,2111],{"class":181,"line":229},[179,2088,1152],{"class":197},[179,2090,1155],{"class":219},[179,2092,1158],{"class":208},[179,2094,1161],{"class":219},[179,2096,1164],{"class":197},[179,2098,468],{"class":212},[179,2100,1169],{"class":471},[179,2102,1138],{"class":471},[179,2104,1004],{"class":212},[179,2106,1158],{"class":219},[179,2108,287],{"class":212},[179,2110,1012],{"class":219},[179,2112,489],{"class":212},[179,2114,2115],{"class":181,"line":265},[179,2116,1186],{"class":219},[179,2118,2119],{"class":181,"line":278},[179,2120,1191],{"class":219},[98,2122,1195],{"id":1194},[102,2124,1198],{},[1200,2126,2127,2131,2135,2139],{},[119,2128,2129,1207],{},[122,2130,1206],{},[119,2132,2133,1213],{},[122,2134,1212],{},[119,2136,2137,1219],{},[122,2138,1218],{},[119,2140,2141,1225],{},[122,2142,1224],{},[98,2144,1229],{"id":1228},[102,2146,1232],{},[102,2148,1235],{},[1237,2150],{},[102,2152,2153,1244],{},[122,2154,1243],{},[1246,2156,1248],{},{"title":174,"searchDepth":189,"depth":189,"links":2158},[2159,2160,2161,2166,2172,2173,2177,2182,2183],{"id":100,"depth":189,"text":91},{"id":110,"depth":189,"text":111},{"id":158,"depth":189,"text":159,"children":2162},[2163,2164,2165],{"id":163,"depth":16,"text":164},{"id":312,"depth":16,"text":313},{"id":351,"depth":16,"text":352},{"id":372,"depth":189,"text":373,"children":2167},[2168,2169,2170,2171],{"id":376,"depth":16,"text":377},{"id":516,"depth":16,"text":517},{"id":586,"depth":16,"text":587},{"id":661,"depth":16,"text":662},{"id":752,"depth":189,"text":753},{"id":850,"depth":189,"text":851,"children":2174},[2175,2176],{"id":854,"depth":16,"text":855},{"id":898,"depth":16,"text":899},{"id":929,"depth":189,"text":930,"children":2178},[2179,2180,2181],{"id":933,"depth":16,"text":934},{"id":1021,"depth":16,"text":1022},{"id":1097,"depth":16,"text":1098},{"id":1194,"depth":189,"text":1195},{"id":1228,"depth":189,"text":1229},{"readingTime":1280},{"title":91,"description":1277},{"src":1286,"mime":1287,"alt":1288,"width":1289,"height":1290},[1293,1294,1295,1296,1297],[2189,4998,7831],{"id":2190,"title":2191,"abstract":92,"author":93,"authorUrl":92,"body":2192,"date":4970,"dateUpdated":4970,"description":4971,"excerpt":92,"extension":1278,"featured":624,"headline":92,"image":92,"meta":4972,"navigation":624,"ogImage":92,"path":4985,"seo":4986,"series":4987,"seriesDescription":4988,"seriesOrder":189,"socialImage":4989,"stem":4992,"tags":4993,"__hash__":4997},"blog/blog/22-nuxt-3-to-4-migration-guide-2026.md","Nuxt 3 to Nuxt 4 Migration Guide: Complete Checklist for 2026",{"type":95,"value":2193,"toc":4913},[2194,2197,2206,2220,2233,2235,2239,2242,2268,2274,2276,2280,2284,2289,2300,2305,2326,2331,2342,2347,2358,2363,2374,2376,2380,2383,2387,2390,2469,2473,2476,2493,2498,2521,2526,2537,2541,2544,2559,2563,2566,2580,2584,2587,2606,2608,2612,2616,2619,2680,2685,2703,2707,2710,2763,2766,2778,2782,2787,2877,2883,3006,3010,3017,3022,3030,3035,3041,3044,3107,3110,3114,3121,3125,3191,3196,3269,3274,3435,3439,3442,3446,3512,3517,3601,3605,3608,3613,3656,3661,3728,3732,3735,3740,3757,3762,3804,3809,3929,3931,3935,3939,3942,3948,3957,4022,4026,4029,4034,4039,4045,4049,4052,4057,4137,4141,4146,4163,4168,4182,4184,4188,4192,4196,4245,4249,4253,4312,4316,4320,4358,4362,4366,4445,4449,4453,4471,4473,4477,4480,4484,4506,4510,4522,4526,4549,4553,4573,4577,4588,4590,4594,4599,4619,4625,4627,4631,4634,4730,4732,4736,4740,4746,4750,4757,4761,4767,4771,4774,4785,4789,4795,4799,4805,4809,4812,4814,4818,4821,4853,4855,4859,4868,4873,4903,4905,4910],[98,2195,2191],{"id":2196},"nuxt-3-to-nuxt-4-migration-guide-complete-checklist-for-2026",[102,2198,2199,2202,2203],{},[122,2200,2201],{},"Last updated:"," February 2026\n",[122,2204,2205],{},"What changed in this update:",[116,2207,2208,2211,2214,2217],{},[119,2209,2210],{},"Added migration timeline reminder (Nuxt 3 EOL: January 31, 2026)",[119,2212,2213],{},"Updated codemod tool instructions",[119,2215,2216],{},"Added new module compatibility matrix",[119,2218,2219],{},"Expanded troubleshooting section",[2221,2222,2223],"blockquote",{},[102,2224,2225,2228,2229,2232],{},[122,2226,2227],{},"⚠️ Critical Timeline",": Nuxt 3 official support ends ",[122,2230,2231],{},"January 31, 2026",". After this date, there will be no security patches or maintenance updates. Migrating to Nuxt 4 is essential for production applications.",[1237,2234],{},[98,2236,2238],{"id":2237},"why-migrate-to-nuxt-4-now","Why Migrate to Nuxt 4 Now?",[102,2240,2241],{},"If you're still on Nuxt 3 in early 2026, you're facing:",[1200,2243,2244,2250,2256,2262],{},[119,2245,2246,2249],{},[122,2247,2248],{},"Security risks",": No security patches after January 2026",[119,2251,2252,2255],{},[122,2253,2254],{},"Module incompatibility",": New module versions target Nuxt 4+",[119,2257,2258,2261],{},[122,2259,2260],{},"Missing features",": Performance improvements and DX enhancements",[119,2263,2264,2267],{},[122,2265,2266],{},"No LTS support",": Critical for enterprise applications",[102,2269,2270,2273],{},[122,2271,2272],{},"The good news",": Nuxt 4 is a stability-focused release with a clear upgrade path. Most projects can migrate in a few hours with the right preparation.",[1237,2275],{},[98,2277,2279],{"id":2278},"whats-new-in-nuxt-4","What's New in Nuxt 4?",[161,2281,2283],{"id":2282},"key-improvements","Key Improvements",[102,2285,2286],{},[122,2287,2288],{},"1. Improved App Directory Structure",[116,2290,2291,2294,2297],{},[119,2292,2293],{},"Cleaner separation of concerns",[119,2295,2296],{},"Better TypeScript integration",[119,2298,2299],{},"Enhanced auto-imports",[102,2301,2302],{},[122,2303,2304],{},"2. Smarter Data Fetching",[116,2306,2307,2317,2320,2323],{},[119,2308,2309,2312,2313,2316],{},[176,2310,2311],{},"useAsyncData"," and ",[176,2314,2315],{},"useFetch"," automatically share data with same keys",[119,2318,2319],{},"Automatic cleanup on component unmount",[119,2321,2322],{},"Reactive keys for automatic refetching",[119,2324,2325],{},"Better caching strategies",[102,2327,2328],{},[122,2329,2330],{},"3. Enhanced TypeScript Ergonomics",[116,2332,2333,2336,2339],{},[119,2334,2335],{},"Zero-config TypeScript setup",[119,2337,2338],{},"Better type inference for composables",[119,2340,2341],{},"Improved module type generation",[102,2343,2344],{},[122,2345,2346],{},"4. Faster Development Tooling",[116,2348,2349,2352,2355],{},[119,2350,2351],{},"Optimized HMR (Hot Module Replacement)",[119,2353,2354],{},"Faster cold starts",[119,2356,2357],{},"Improved build performance",[102,2359,2360],{},[122,2361,2362],{},"5. Nitro v2 Integration",[116,2364,2365,2368,2371],{},[119,2366,2367],{},"Better server-side rendering",[119,2369,2370],{},"Enhanced API routes",[119,2372,2373],{},"Improved edge deployment support",[1237,2375],{},[98,2377,2379],{"id":2378},"pre-migration-checklist","Pre-Migration Checklist",[102,2381,2382],{},"Before starting the migration, complete these steps:",[161,2384,2386],{"id":2385},"_1-update-dependencies","✅ 1. Update Dependencies",[102,2388,2389],{},"Update to the latest Nuxt 3.x version first:",[169,2391,2393],{"className":858,"code":2392,"language":860,"meta":174,"style":174},"# Check current version\nnpx nuxi info\n\n# Update to latest Nuxt 3\nnpm install nuxt@latest\n\n# Or with yarn/pnpm/bun\nyarn add nuxt@latest\npnpm add nuxt@latest\nbun add nuxt@latest\n",[176,2394,2395,2400,2410,2414,2419,2430,2434,2439,2449,2459],{"__ignoreMap":174},[179,2396,2397],{"class":181,"line":182},[179,2398,2399],{"class":185},"# Check current version\n",[179,2401,2402,2404,2407],{"class":181,"line":189},[179,2403,872],{"class":471},[179,2405,2406],{"class":256}," nuxi",[179,2408,2409],{"class":256}," info\n",[179,2411,2412],{"class":181,"line":16},[179,2413,625],{"emptyLinePlaceholder":624},[179,2415,2416],{"class":181,"line":216},[179,2417,2418],{"class":185},"# Update to latest Nuxt 3\n",[179,2420,2421,2424,2427],{"class":181,"line":229},[179,2422,2423],{"class":471},"npm",[179,2425,2426],{"class":256}," install",[179,2428,2429],{"class":256}," nuxt@latest\n",[179,2431,2432],{"class":181,"line":265},[179,2433,625],{"emptyLinePlaceholder":624},[179,2435,2436],{"class":181,"line":278},[179,2437,2438],{"class":185},"# Or with yarn/pnpm/bun\n",[179,2440,2441,2444,2447],{"class":181,"line":284},[179,2442,2443],{"class":471},"yarn",[179,2445,2446],{"class":256}," add",[179,2448,2429],{"class":256},[179,2450,2452,2455,2457],{"class":181,"line":2451},9,[179,2453,2454],{"class":471},"pnpm",[179,2456,2446],{"class":256},[179,2458,2429],{"class":256},[179,2460,2462,2465,2467],{"class":181,"line":2461},10,[179,2463,2464],{"class":471},"bun",[179,2466,2446],{"class":256},[179,2468,2429],{"class":256},[161,2470,2472],{"id":2471},"_2-review-module-compatibility","✅ 2. Review Module Compatibility",[102,2474,2475],{},"Check if your modules support Nuxt 4:",[169,2477,2479],{"className":858,"code":2478,"language":860,"meta":174,"style":174},"npx nuxi upgrade --force\n",[176,2480,2481],{"__ignoreMap":174},[179,2482,2483,2485,2487,2490],{"class":181,"line":182},[179,2484,872],{"class":471},[179,2486,2406],{"class":256},[179,2488,2489],{"class":256}," upgrade",[179,2491,2492],{"class":256}," --force\n",[102,2494,2495],{},[122,2496,2497],{},"Compatible Modules (Nuxt 4 Ready):",[116,2499,2500,2503,2506,2509,2512,2515,2518],{},[119,2501,2502],{},"✅ @nuxt/content (v3+)",[119,2504,2505],{},"✅ @nuxt/ui (v3+)",[119,2507,2508],{},"✅ @nuxt/icon",[119,2510,2511],{},"✅ @nuxtjs/seo",[119,2513,2514],{},"✅ @nuxtjs/tailwindcss (v6+)",[119,2516,2517],{},"✅ @pinia/nuxt",[119,2519,2520],{},"✅ @vueuse/nuxt",[102,2522,2523],{},[122,2524,2525],{},"Modules Requiring Updates:",[116,2527,2528,2531,2534],{},[119,2529,2530],{},"⚠️ @nuxtjs/auth → Use @sidebase/nuxt-auth or nuxt-auth-utils",[119,2532,2533],{},"⚠️ @nuxtjs/i18n → Update to v8+",[119,2535,2536],{},"⚠️ Custom server middleware → Migrate to Nitro server routes",[161,2538,2540],{"id":2539},"_3-run-type-check","✅ 3. Run Type Check",[102,2542,2543],{},"Fix all TypeScript errors before migrating:",[169,2545,2547],{"className":858,"code":2546,"language":860,"meta":174,"style":174},"npm run type-check\n",[176,2548,2549],{"__ignoreMap":174},[179,2550,2551,2553,2556],{"class":181,"line":182},[179,2552,2423],{"class":471},[179,2554,2555],{"class":256}," run",[179,2557,2558],{"class":256}," type-check\n",[161,2560,2562],{"id":2561},"_4-update-test-suite","✅ 4. Update Test Suite",[102,2564,2565],{},"Ensure all tests pass on Nuxt 3 before migration:",[169,2567,2569],{"className":858,"code":2568,"language":860,"meta":174,"style":174},"npm run test\n",[176,2570,2571],{"__ignoreMap":174},[179,2572,2573,2575,2577],{"class":181,"line":182},[179,2574,2423],{"class":471},[179,2576,2555],{"class":256},[179,2578,2579],{"class":256}," test\n",[161,2581,2583],{"id":2582},"_5-backup-your-code","✅ 5. Backup Your Code",[102,2585,2586],{},"Create a git branch for migration:",[169,2588,2590],{"className":858,"code":2589,"language":860,"meta":174,"style":174},"git checkout -b migration/nuxt-4\n",[176,2591,2592],{"__ignoreMap":174},[179,2593,2594,2597,2600,2603],{"class":181,"line":182},[179,2595,2596],{"class":471},"git",[179,2598,2599],{"class":256}," checkout",[179,2601,2602],{"class":256}," -b",[179,2604,2605],{"class":256}," migration/nuxt-4\n",[1237,2607],{},[98,2609,2611],{"id":2610},"step-by-step-migration-process","Step-by-Step Migration Process",[161,2613,2615],{"id":2614},"step-1-use-the-codemod-tool-recommended","Step 1: Use the Codemod Tool (Recommended)",[102,2617,2618],{},"Nuxt partnered with Codemod to create an automated migration tool:",[169,2620,2622],{"className":858,"code":2621,"language":860,"meta":174,"style":174},"# Run the migration codemod\nnpx codemod@latest nuxt/4/migration-recipe\n\n# Or with your package manager\nyarn dlx codemod@latest nuxt/4/migration-recipe\npnpm dlx codemod@latest nuxt/4/migration-recipe\nbun x codemod@latest nuxt/4/migration-recipe\n",[176,2623,2624,2629,2639,2643,2648,2659,2669],{"__ignoreMap":174},[179,2625,2626],{"class":181,"line":182},[179,2627,2628],{"class":185},"# Run the migration codemod\n",[179,2630,2631,2633,2636],{"class":181,"line":189},[179,2632,872],{"class":471},[179,2634,2635],{"class":256}," codemod@latest",[179,2637,2638],{"class":256}," nuxt/4/migration-recipe\n",[179,2640,2641],{"class":181,"line":16},[179,2642,625],{"emptyLinePlaceholder":624},[179,2644,2645],{"class":181,"line":216},[179,2646,2647],{"class":185},"# Or with your package manager\n",[179,2649,2650,2652,2655,2657],{"class":181,"line":229},[179,2651,2443],{"class":471},[179,2653,2654],{"class":256}," dlx",[179,2656,2635],{"class":256},[179,2658,2638],{"class":256},[179,2660,2661,2663,2665,2667],{"class":181,"line":265},[179,2662,2454],{"class":471},[179,2664,2654],{"class":256},[179,2666,2635],{"class":256},[179,2668,2638],{"class":256},[179,2670,2671,2673,2676,2678],{"class":181,"line":278},[179,2672,2464],{"class":471},[179,2674,2675],{"class":256}," x",[179,2677,2635],{"class":256},[179,2679,2638],{"class":256},[102,2681,2682],{},[122,2683,2684],{},"What the codemod does:",[116,2686,2687,2694,2697,2700],{},[119,2688,2689,2690,2693],{},"Updates ",[176,2691,2692],{},"nuxt.config.ts"," configuration",[119,2695,2696],{},"Migrates directory structure (if needed)",[119,2698,2699],{},"Updates deprecated imports",[119,2701,2702],{},"Fixes common API changes",[161,2704,2706],{"id":2705},"step-2-update-packagejson","Step 2: Update package.json",[102,2708,2709],{},"Change Nuxt version to 4:",[169,2711,2715],{"className":2712,"code":2713,"language":2714,"meta":174,"style":174},"language-json shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","{\n \"devDependencies\": {\n \"nuxt\": \"^4.0.0\"\n }\n}\n","json",[176,2716,2717,2721,2735,2755,2759],{"__ignoreMap":174},[179,2718,2719],{"class":181,"line":182},[179,2720,213],{"class":212},[179,2722,2723,2726,2729,2731,2733],{"class":181,"line":189},[179,2724,2725],{"class":212}," \"",[179,2727,2728],{"class":232},"devDependencies",[179,2730,253],{"class":212},[179,2732,448],{"class":212},[179,2734,226],{"class":212},[179,2736,2737,2740,2743,2745,2747,2749,2752],{"class":181,"line":16},[179,2738,2739],{"class":212}," \"",[179,2741,2742],{"class":471},"nuxt",[179,2744,253],{"class":212},[179,2746,448],{"class":212},[179,2748,1071],{"class":212},[179,2750,2751],{"class":256},"^4.0.0",[179,2753,2754],{"class":212},"\"\n",[179,2756,2757],{"class":181,"line":216},[179,2758,1186],{"class":212},[179,2760,2761],{"class":181,"line":229},[179,2762,494],{"class":212},[102,2764,2765],{},"Then install:",[169,2767,2769],{"className":858,"code":2768,"language":860,"meta":174,"style":174},"npm install\n",[176,2770,2771],{"__ignoreMap":174},[179,2772,2773,2775],{"class":181,"line":182},[179,2774,2423],{"class":471},[179,2776,2777],{"class":256}," install\n",[161,2779,2781],{"id":2780},"step-3-update-nuxtconfigts","Step 3: Update nuxt.config.ts",[102,2783,2784],{},[122,2785,2786],{},"Nuxt 3:",[169,2788,2790],{"className":171,"code":2789,"language":173,"meta":174,"style":174},"export default defineNuxtConfig({\n modules: [\"@nuxt/content\"],\n app: {\n head: {\n title: \"My App\",\n },\n },\n})\n",[176,2791,2792,2805,2828,2837,2846,2862,2867,2871],{"__ignoreMap":174},[179,2793,2794,2796,2798,2801,2803],{"class":181,"line":182},[179,2795,198],{"class":197},[179,2797,201],{"class":197},[179,2799,2800],{"class":204}," defineNuxtConfig",[179,2802,209],{"class":208},[179,2804,213],{"class":212},[179,2806,2807,2810,2812,2815,2817,2820,2822,2825],{"class":181,"line":189},[179,2808,2809],{"class":219}," modules",[179,2811,448],{"class":212},[179,2813,2814],{"class":208}," [",[179,2816,253],{"class":212},[179,2818,2819],{"class":256},"@nuxt/content",[179,2821,253],{"class":212},[179,2823,2824],{"class":208},"]",[179,2826,2827],{"class":212},",\n",[179,2829,2830,2833,2835],{"class":181,"line":16},[179,2831,2832],{"class":219}," app",[179,2834,448],{"class":212},[179,2836,226],{"class":212},[179,2838,2839,2842,2844],{"class":181,"line":216},[179,2840,2841],{"class":219}," head",[179,2843,448],{"class":212},[179,2845,226],{"class":212},[179,2847,2848,2851,2853,2855,2858,2860],{"class":181,"line":229},[179,2849,2850],{"class":219}," title",[179,2852,448],{"class":212},[179,2854,1071],{"class":212},[179,2856,2857],{"class":256},"My App",[179,2859,253],{"class":212},[179,2861,2827],{"class":212},[179,2863,2864],{"class":181,"line":265},[179,2865,2866],{"class":212}," },\n",[179,2868,2869],{"class":181,"line":278},[179,2870,281],{"class":212},[179,2872,2873,2875],{"class":181,"line":284},[179,2874,287],{"class":212},[179,2876,262],{"class":208},[102,2878,2879,2882],{},[122,2880,2881],{},"Nuxt 4:"," (mostly the same, but check for deprecated options)",[169,2884,2886],{"className":171,"code":2885,"language":173,"meta":174,"style":174},"export default defineNuxtConfig({\n modules: [\"@nuxt/content\"],\n app: {\n head: {\n title: \"My App\",\n },\n },\n // New in Nuxt 4: Better TypeScript defaults\n typescript: {\n strict: true,\n typeCheck: true,\n },\n})\n",[176,2887,2888,2900,2918,2926,2934,2948,2952,2956,2961,2970,2983,2995,3000],{"__ignoreMap":174},[179,2889,2890,2892,2894,2896,2898],{"class":181,"line":182},[179,2891,198],{"class":197},[179,2893,201],{"class":197},[179,2895,2800],{"class":204},[179,2897,209],{"class":208},[179,2899,213],{"class":212},[179,2901,2902,2904,2906,2908,2910,2912,2914,2916],{"class":181,"line":189},[179,2903,2809],{"class":219},[179,2905,448],{"class":212},[179,2907,2814],{"class":208},[179,2909,253],{"class":212},[179,2911,2819],{"class":256},[179,2913,253],{"class":212},[179,2915,2824],{"class":208},[179,2917,2827],{"class":212},[179,2919,2920,2922,2924],{"class":181,"line":16},[179,2921,2832],{"class":219},[179,2923,448],{"class":212},[179,2925,226],{"class":212},[179,2927,2928,2930,2932],{"class":181,"line":216},[179,2929,2841],{"class":219},[179,2931,448],{"class":212},[179,2933,226],{"class":212},[179,2935,2936,2938,2940,2942,2944,2946],{"class":181,"line":229},[179,2937,2850],{"class":219},[179,2939,448],{"class":212},[179,2941,1071],{"class":212},[179,2943,2857],{"class":256},[179,2945,253],{"class":212},[179,2947,2827],{"class":212},[179,2949,2950],{"class":181,"line":265},[179,2951,2866],{"class":212},[179,2953,2954],{"class":181,"line":278},[179,2955,281],{"class":212},[179,2957,2958],{"class":181,"line":284},[179,2959,2960],{"class":185}," // New in Nuxt 4: Better TypeScript defaults\n",[179,2962,2963,2966,2968],{"class":181,"line":2451},[179,2964,2965],{"class":219}," typescript",[179,2967,448],{"class":212},[179,2969,226],{"class":212},[179,2971,2972,2975,2977,2981],{"class":181,"line":2461},[179,2973,2974],{"class":219}," strict",[179,2976,448],{"class":212},[179,2978,2980],{"class":2979},"sfNiH"," true",[179,2982,2827],{"class":212},[179,2984,2986,2989,2991,2993],{"class":181,"line":2985},11,[179,2987,2988],{"class":219}," typeCheck",[179,2990,448],{"class":212},[179,2992,2980],{"class":2979},[179,2994,2827],{"class":212},[179,2996,2998],{"class":181,"line":2997},12,[179,2999,281],{"class":212},[179,3001,3002,3004],{"class":181,"line":29},[179,3003,287],{"class":212},[179,3005,262],{"class":208},[161,3007,3009],{"id":3008},"step-4-migrate-directory-structure-optional","Step 4: Migrate Directory Structure (Optional)",[102,3011,3012,3013,3016],{},"Nuxt 4 introduces an optional ",[176,3014,3015],{},"app/"," directory structure for better organization:",[102,3018,3019],{},[122,3020,3021],{},"Old Structure (still works):",[169,3023,3028],{"className":3024,"code":3026,"language":3027},[3025],"language-text","├── components/\n├── pages/\n├── composables/\n├── layouts/\n└── plugins/\n","text",[176,3029,3026],{"__ignoreMap":174},[102,3031,3032],{},[122,3033,3034],{},"New Structure (recommended for new projects):",[169,3036,3039],{"className":3037,"code":3038,"language":3027},[3025],"├── app/\n│ ├── components/\n│ ├── pages/\n│ ├── composables/\n│ ├── layouts/\n│ └── plugins/\n├── content/\n└── public/\n",[176,3040,3038],{"__ignoreMap":174},[102,3042,3043],{},"To adopt the new structure:",[169,3045,3047],{"className":858,"code":3046,"language":860,"meta":174,"style":174},"mkdir -p app\nmv components app/\nmv pages app/\nmv composables app/\nmv layouts app/\nmv plugins app/\n",[176,3048,3049,3060,3071,3080,3089,3098],{"__ignoreMap":174},[179,3050,3051,3054,3057],{"class":181,"line":182},[179,3052,3053],{"class":471},"mkdir",[179,3055,3056],{"class":256}," -p",[179,3058,3059],{"class":256}," app\n",[179,3061,3062,3065,3068],{"class":181,"line":189},[179,3063,3064],{"class":471},"mv",[179,3066,3067],{"class":256}," components",[179,3069,3070],{"class":256}," app/\n",[179,3072,3073,3075,3078],{"class":181,"line":16},[179,3074,3064],{"class":471},[179,3076,3077],{"class":256}," pages",[179,3079,3070],{"class":256},[179,3081,3082,3084,3087],{"class":181,"line":216},[179,3083,3064],{"class":471},[179,3085,3086],{"class":256}," composables",[179,3088,3070],{"class":256},[179,3090,3091,3093,3096],{"class":181,"line":229},[179,3092,3064],{"class":471},[179,3094,3095],{"class":256}," layouts",[179,3097,3070],{"class":256},[179,3099,3100,3102,3105],{"class":181,"line":265},[179,3101,3064],{"class":471},[179,3103,3104],{"class":256}," plugins",[179,3106,3070],{"class":256},[102,3108,3109],{},"Update imports if necessary (most auto-imports work the same).",[161,3111,3113],{"id":3112},"step-5-update-data-fetching","Step 5: Update Data Fetching",[102,3115,3116,3117,2312,3119,448],{},"Nuxt 4 improves ",[176,3118,2311],{},[176,3120,2315],{},[102,3122,3123],{},[122,3124,2786],{},[169,3126,3128],{"className":171,"code":3127,"language":173,"meta":174,"style":174},"const { data } = await useFetch(\"/api/posts\", {\n key: \"posts\",\n lazy: true,\n})\n",[176,3129,3130,3158,3174,3185],{"__ignoreMap":174},[179,3131,3132,3134,3136,3138,3140,3142,3144,3146,3148,3150,3152,3154,3156],{"class":181,"line":182},[179,3133,537],{"class":232},[179,3135,236],{"class":212},[179,3137,1041],{"class":208},[179,3139,287],{"class":212},[179,3141,245],{"class":212},[179,3143,424],{"class":197},[179,3145,248],{"class":204},[179,3147,209],{"class":208},[179,3149,253],{"class":212},[179,3151,561],{"class":256},[179,3153,253],{"class":212},[179,3155,440],{"class":212},[179,3157,226],{"class":212},[179,3159,3160,3163,3165,3167,3170,3172],{"class":181,"line":189},[179,3161,3162],{"class":219}," key",[179,3164,448],{"class":212},[179,3166,1071],{"class":212},[179,3168,3169],{"class":256},"posts",[179,3171,253],{"class":212},[179,3173,2827],{"class":212},[179,3175,3176,3179,3181,3183],{"class":181,"line":16},[179,3177,3178],{"class":219}," lazy",[179,3180,448],{"class":212},[179,3182,2980],{"class":2979},[179,3184,2827],{"class":212},[179,3186,3187,3189],{"class":181,"line":216},[179,3188,287],{"class":212},[179,3190,262],{"class":208},[102,3192,3193,3195],{},[122,3194,2881],{}," (same API, better behavior)",[169,3197,3199],{"className":171,"code":3198,"language":173,"meta":174,"style":174},"const { data } = await useFetch(\"/api/posts\", {\n key: \"posts\",\n lazy: true,\n // Now automatically shares data across components with same key\n // Automatic cleanup on unmount\n})\n",[176,3200,3201,3229,3243,3253,3258,3263],{"__ignoreMap":174},[179,3202,3203,3205,3207,3209,3211,3213,3215,3217,3219,3221,3223,3225,3227],{"class":181,"line":182},[179,3204,537],{"class":232},[179,3206,236],{"class":212},[179,3208,1041],{"class":208},[179,3210,287],{"class":212},[179,3212,245],{"class":212},[179,3214,424],{"class":197},[179,3216,248],{"class":204},[179,3218,209],{"class":208},[179,3220,253],{"class":212},[179,3222,561],{"class":256},[179,3224,253],{"class":212},[179,3226,440],{"class":212},[179,3228,226],{"class":212},[179,3230,3231,3233,3235,3237,3239,3241],{"class":181,"line":189},[179,3232,3162],{"class":219},[179,3234,448],{"class":212},[179,3236,1071],{"class":212},[179,3238,3169],{"class":256},[179,3240,253],{"class":212},[179,3242,2827],{"class":212},[179,3244,3245,3247,3249,3251],{"class":181,"line":16},[179,3246,3178],{"class":219},[179,3248,448],{"class":212},[179,3250,2980],{"class":2979},[179,3252,2827],{"class":212},[179,3254,3255],{"class":181,"line":216},[179,3256,3257],{"class":185}," // Now automatically shares data across components with same key\n",[179,3259,3260],{"class":181,"line":229},[179,3261,3262],{"class":185}," // Automatic cleanup on unmount\n",[179,3264,3265,3267],{"class":181,"line":265},[179,3266,287],{"class":212},[179,3268,262],{"class":208},[102,3270,3271],{},[122,3272,3273],{},"New Features:",[169,3275,3277],{"className":171,"code":3276,"language":173,"meta":174,"style":174},"// Reactive keys automatically refetch\nconst { data } = await useFetch(`/api/posts/${postId}`)\n\n// Multiple components with same key share data\n// Component A\nconst { data: posts } = await useFetch(\"/api/posts\", { key: \"posts\" })\n\n// Component B (gets same data, no duplicate request)\nconst { data: posts } = await useFetch(\"/api/posts\", { key: \"posts\" })\n",[176,3278,3279,3284,3319,3323,3328,3333,3380,3384,3389],{"__ignoreMap":174},[179,3280,3281],{"class":181,"line":182},[179,3282,3283],{"class":185},"// Reactive keys automatically refetch\n",[179,3285,3286,3288,3290,3292,3294,3296,3298,3300,3302,3305,3308,3311,3314,3317],{"class":181,"line":189},[179,3287,537],{"class":232},[179,3289,236],{"class":212},[179,3291,1041],{"class":208},[179,3293,287],{"class":212},[179,3295,245],{"class":212},[179,3297,424],{"class":197},[179,3299,248],{"class":204},[179,3301,209],{"class":208},[179,3303,3304],{"class":212},"`",[179,3306,3307],{"class":256},"/api/posts/",[179,3309,3310],{"class":212},"${",[179,3312,3313],{"class":208},"postId",[179,3315,3316],{"class":212},"}`",[179,3318,262],{"class":208},[179,3320,3321],{"class":181,"line":16},[179,3322,625],{"emptyLinePlaceholder":624},[179,3324,3325],{"class":181,"line":216},[179,3326,3327],{"class":185},"// Multiple components with same key share data\n",[179,3329,3330],{"class":181,"line":229},[179,3331,3332],{"class":185},"// Component A\n",[179,3334,3335,3337,3339,3341,3343,3345,3347,3349,3351,3353,3355,3357,3359,3361,3363,3365,3368,3370,3372,3374,3376,3378],{"class":181,"line":265},[179,3336,537],{"class":232},[179,3338,236],{"class":212},[179,3340,239],{"class":219},[179,3342,448],{"class":212},[179,3344,546],{"class":208},[179,3346,287],{"class":212},[179,3348,245],{"class":212},[179,3350,424],{"class":197},[179,3352,248],{"class":204},[179,3354,209],{"class":208},[179,3356,253],{"class":212},[179,3358,561],{"class":256},[179,3360,253],{"class":212},[179,3362,440],{"class":212},[179,3364,236],{"class":212},[179,3366,3367],{"class":219}," key",[179,3369,448],{"class":212},[179,3371,1071],{"class":212},[179,3373,3169],{"class":256},[179,3375,253],{"class":212},[179,3377,242],{"class":212},[179,3379,262],{"class":208},[179,3381,3382],{"class":181,"line":278},[179,3383,625],{"emptyLinePlaceholder":624},[179,3385,3386],{"class":181,"line":284},[179,3387,3388],{"class":185},"// Component B (gets same data, no duplicate request)\n",[179,3390,3391,3393,3395,3397,3399,3401,3403,3405,3407,3409,3411,3413,3415,3417,3419,3421,3423,3425,3427,3429,3431,3433],{"class":181,"line":2451},[179,3392,537],{"class":232},[179,3394,236],{"class":212},[179,3396,239],{"class":219},[179,3398,448],{"class":212},[179,3400,546],{"class":208},[179,3402,287],{"class":212},[179,3404,245],{"class":212},[179,3406,424],{"class":197},[179,3408,248],{"class":204},[179,3410,209],{"class":208},[179,3412,253],{"class":212},[179,3414,561],{"class":256},[179,3416,253],{"class":212},[179,3418,440],{"class":212},[179,3420,236],{"class":212},[179,3422,3367],{"class":219},[179,3424,448],{"class":212},[179,3426,1071],{"class":212},[179,3428,3169],{"class":256},[179,3430,253],{"class":212},[179,3432,242],{"class":212},[179,3434,262],{"class":208},[161,3436,3438],{"id":3437},"step-6-update-plugins","Step 6: Update Plugins",[102,3440,3441],{},"Nuxt 4 uses auto-imports for plugins by default:",[102,3443,3444],{},[122,3445,2786],{},[169,3447,3449],{"className":171,"code":3448,"language":173,"meta":174,"style":174},"// plugins/my-plugin.ts\nexport default defineNuxtPlugin((nuxtApp) => {\n nuxtApp.provide(\"myPlugin\", myPlugin)\n})\n",[176,3450,3451,3456,3480,3506],{"__ignoreMap":174},[179,3452,3453],{"class":181,"line":182},[179,3454,3455],{"class":185},"// plugins/my-plugin.ts\n",[179,3457,3458,3460,3462,3465,3467,3469,3472,3475,3478],{"class":181,"line":189},[179,3459,198],{"class":197},[179,3461,201],{"class":197},[179,3463,3464],{"class":204}," defineNuxtPlugin",[179,3466,209],{"class":208},[179,3468,209],{"class":212},[179,3470,3471],{"class":694},"nuxtApp",[179,3473,3474],{"class":212},")",[179,3476,3477],{"class":232}," =>",[179,3479,226],{"class":212},[179,3481,3482,3485,3487,3490,3492,3494,3497,3499,3501,3504],{"class":181,"line":16},[179,3483,3484],{"class":208}," nuxtApp",[179,3486,716],{"class":212},[179,3488,3489],{"class":204},"provide",[179,3491,209],{"class":219},[179,3493,253],{"class":212},[179,3495,3496],{"class":256},"myPlugin",[179,3498,253],{"class":212},[179,3500,440],{"class":212},[179,3502,3503],{"class":208}," myPlugin",[179,3505,262],{"class":219},[179,3507,3508,3510],{"class":181,"line":216},[179,3509,287],{"class":212},[179,3511,262],{"class":208},[102,3513,3514,3516],{},[122,3515,2881],{}," (same, but better type inference)",[169,3518,3520],{"className":171,"code":3519,"language":173,"meta":174,"style":174},"// plugins/my-plugin.ts\nexport default defineNuxtPlugin((nuxtApp) => {\n nuxtApp.provide(\"myPlugin\", myPlugin)\n})\n\n// Usage in components (auto-typed)\nconst { $myPlugin } = useNuxtApp()\n",[176,3521,3522,3526,3546,3568,3574,3578,3583],{"__ignoreMap":174},[179,3523,3524],{"class":181,"line":182},[179,3525,3455],{"class":185},[179,3527,3528,3530,3532,3534,3536,3538,3540,3542,3544],{"class":181,"line":189},[179,3529,198],{"class":197},[179,3531,201],{"class":197},[179,3533,3464],{"class":204},[179,3535,209],{"class":208},[179,3537,209],{"class":212},[179,3539,3471],{"class":694},[179,3541,3474],{"class":212},[179,3543,3477],{"class":232},[179,3545,226],{"class":212},[179,3547,3548,3550,3552,3554,3556,3558,3560,3562,3564,3566],{"class":181,"line":16},[179,3549,3484],{"class":208},[179,3551,716],{"class":212},[179,3553,3489],{"class":204},[179,3555,209],{"class":219},[179,3557,253],{"class":212},[179,3559,3496],{"class":256},[179,3561,253],{"class":212},[179,3563,440],{"class":212},[179,3565,3503],{"class":208},[179,3567,262],{"class":219},[179,3569,3570,3572],{"class":181,"line":216},[179,3571,287],{"class":212},[179,3573,262],{"class":208},[179,3575,3576],{"class":181,"line":229},[179,3577,625],{"emptyLinePlaceholder":624},[179,3579,3580],{"class":181,"line":265},[179,3581,3582],{"class":185},"// Usage in components (auto-typed)\n",[179,3584,3585,3587,3589,3592,3594,3596,3599],{"class":181,"line":278},[179,3586,537],{"class":232},[179,3588,236],{"class":212},[179,3590,3591],{"class":208}," $myPlugin ",[179,3593,287],{"class":212},[179,3595,245],{"class":212},[179,3597,3598],{"class":204}," useNuxtApp",[179,3600,722],{"class":208},[161,3602,3604],{"id":3603},"step-7-update-server-routes","Step 7: Update Server Routes",[102,3606,3607],{},"Migrate server middleware to Nitro server routes:",[102,3609,3610],{},[122,3611,3612],{},"Old (Nuxt 3 server middleware):",[169,3614,3616],{"className":171,"code":3615,"language":173,"meta":174,"style":174},"// server/middleware/auth.ts\nexport default defineEventHandler((event) => {\n // middleware logic\n})\n",[176,3617,3618,3623,3645,3650],{"__ignoreMap":174},[179,3619,3620],{"class":181,"line":182},[179,3621,3622],{"class":185},"// server/middleware/auth.ts\n",[179,3624,3625,3627,3629,3632,3634,3636,3639,3641,3643],{"class":181,"line":189},[179,3626,198],{"class":197},[179,3628,201],{"class":197},[179,3630,3631],{"class":204}," defineEventHandler",[179,3633,209],{"class":208},[179,3635,209],{"class":212},[179,3637,3638],{"class":694},"event",[179,3640,3474],{"class":212},[179,3642,3477],{"class":232},[179,3644,226],{"class":212},[179,3646,3647],{"class":181,"line":16},[179,3648,3649],{"class":185}," // middleware logic\n",[179,3651,3652,3654],{"class":181,"line":216},[179,3653,287],{"class":212},[179,3655,262],{"class":208},[102,3657,3658],{},[122,3659,3660],{},"New (Nitro server routes - same syntax, better performance):",[169,3662,3664],{"className":171,"code":3663,"language":173,"meta":174,"style":174},"// server/api/auth.ts\nexport default defineEventHandler((event) => {\n // API route logic\n return { user: event.context.user }\n})\n",[176,3665,3666,3671,3691,3696,3722],{"__ignoreMap":174},[179,3667,3668],{"class":181,"line":182},[179,3669,3670],{"class":185},"// server/api/auth.ts\n",[179,3672,3673,3675,3677,3679,3681,3683,3685,3687,3689],{"class":181,"line":189},[179,3674,198],{"class":197},[179,3676,201],{"class":197},[179,3678,3631],{"class":204},[179,3680,209],{"class":208},[179,3682,209],{"class":212},[179,3684,3638],{"class":694},[179,3686,3474],{"class":212},[179,3688,3477],{"class":232},[179,3690,226],{"class":212},[179,3692,3693],{"class":181,"line":16},[179,3694,3695],{"class":185}," // API route logic\n",[179,3697,3698,3700,3702,3705,3707,3710,3712,3715,3717,3720],{"class":181,"line":216},[179,3699,465],{"class":197},[179,3701,236],{"class":212},[179,3703,3704],{"class":219}," user",[179,3706,448],{"class":212},[179,3708,3709],{"class":208}," event",[179,3711,716],{"class":212},[179,3713,3714],{"class":208},"context",[179,3716,716],{"class":212},[179,3718,3719],{"class":208},"user",[179,3721,275],{"class":212},[179,3723,3724,3726],{"class":181,"line":229},[179,3725,287],{"class":212},[179,3727,262],{"class":208},[161,3729,3731],{"id":3730},"step-8-replace-vuex-with-pinia","Step 8: Replace Vuex with Pinia",[102,3733,3734],{},"If you're still using Vuex, migrate to Pinia:",[102,3736,3737],{},[122,3738,3739],{},"Install Pinia:",[169,3741,3743],{"className":858,"code":3742,"language":860,"meta":174,"style":174},"npm install pinia @pinia/nuxt\n",[176,3744,3745],{"__ignoreMap":174},[179,3746,3747,3749,3751,3754],{"class":181,"line":182},[179,3748,2423],{"class":471},[179,3750,2426],{"class":256},[179,3752,3753],{"class":256}," pinia",[179,3755,3756],{"class":256}," @pinia/nuxt\n",[102,3758,3759],{},[122,3760,3761],{},"Add to nuxt.config.ts:",[169,3763,3765],{"className":171,"code":3764,"language":173,"meta":174,"style":174},"export default defineNuxtConfig({\n modules: [\"@pinia/nuxt\"],\n})\n",[176,3766,3767,3779,3798],{"__ignoreMap":174},[179,3768,3769,3771,3773,3775,3777],{"class":181,"line":182},[179,3770,198],{"class":197},[179,3772,201],{"class":197},[179,3774,2800],{"class":204},[179,3776,209],{"class":208},[179,3778,213],{"class":212},[179,3780,3781,3783,3785,3787,3789,3792,3794,3796],{"class":181,"line":189},[179,3782,2809],{"class":219},[179,3784,448],{"class":212},[179,3786,2814],{"class":208},[179,3788,253],{"class":212},[179,3790,3791],{"class":256},"@pinia/nuxt",[179,3793,253],{"class":212},[179,3795,2824],{"class":208},[179,3797,2827],{"class":212},[179,3799,3800,3802],{"class":181,"line":16},[179,3801,287],{"class":212},[179,3803,262],{"class":208},[102,3805,3806],{},[122,3807,3808],{},"Migrate stores:",[169,3810,3812],{"className":171,"code":3811,"language":173,"meta":174,"style":174},"// stores/counter.ts\nexport const useCounterStore = defineStore(\"counter\", {\n state: () => ({\n count: 0,\n }),\n actions: {\n increment() {\n this.count++\n },\n },\n})\n",[176,3813,3814,3819,3848,3864,3877,3886,3895,3904,3915,3919,3923],{"__ignoreMap":174},[179,3815,3816],{"class":181,"line":182},[179,3817,3818],{"class":185},"// stores/counter.ts\n",[179,3820,3821,3823,3826,3829,3832,3835,3837,3839,3842,3844,3846],{"class":181,"line":189},[179,3822,198],{"class":197},[179,3824,3825],{"class":232}," const",[179,3827,3828],{"class":208}," useCounterStore ",[179,3830,3831],{"class":212},"=",[179,3833,3834],{"class":204}," defineStore",[179,3836,209],{"class":208},[179,3838,253],{"class":212},[179,3840,3841],{"class":256},"counter",[179,3843,253],{"class":212},[179,3845,440],{"class":212},[179,3847,226],{"class":212},[179,3849,3850,3853,3855,3858,3860,3862],{"class":181,"line":16},[179,3851,3852],{"class":204}," state",[179,3854,448],{"class":212},[179,3856,3857],{"class":212}," ()",[179,3859,3477],{"class":232},[179,3861,1155],{"class":208},[179,3863,213],{"class":212},[179,3865,3866,3869,3871,3875],{"class":181,"line":216},[179,3867,3868],{"class":219}," count",[179,3870,448],{"class":212},[179,3872,3874],{"class":3873},"sbssI"," 0",[179,3876,2827],{"class":212},[179,3878,3879,3882,3884],{"class":181,"line":229},[179,3880,3881],{"class":212}," }",[179,3883,3474],{"class":208},[179,3885,2827],{"class":212},[179,3887,3888,3891,3893],{"class":181,"line":265},[179,3889,3890],{"class":219}," actions",[179,3892,448],{"class":212},[179,3894,226],{"class":212},[179,3896,3897,3900,3902],{"class":181,"line":278},[179,3898,3899],{"class":219}," increment",[179,3901,223],{"class":212},[179,3903,226],{"class":212},[179,3905,3906,3909,3912],{"class":181,"line":284},[179,3907,3908],{"class":212}," this.",[179,3910,3911],{"class":208},"count",[179,3913,3914],{"class":212},"++\n",[179,3916,3917],{"class":181,"line":2451},[179,3918,2866],{"class":212},[179,3920,3921],{"class":181,"line":2461},[179,3922,281],{"class":212},[179,3924,3925,3927],{"class":181,"line":2985},[179,3926,287],{"class":212},[179,3928,262],{"class":208},[1237,3930],{},[98,3932,3934],{"id":3933},"breaking-changes-solutions","Breaking Changes & Solutions",[161,3936,3938],{"id":3937},"_1-stricter-typescript","1. Stricter TypeScript",[102,3940,3941],{},"Nuxt 4 enables stricter TypeScript by default.",[102,3943,3944,3947],{},[122,3945,3946],{},"Issue:"," Type errors that were ignored before",[102,3949,3950,3953,3954,448],{},[122,3951,3952],{},"Solution:"," Fix types or adjust ",[176,3955,3956],{},"tsconfig.json",[169,3958,3960],{"className":171,"code":3959,"language":173,"meta":174,"style":174},"// tsconfig.json\n{\n \"compilerOptions\": {\n \"strict\": true,\n \"noImplicitAny\": true\n }\n}\n",[176,3961,3962,3967,3971,3985,4000,4014,4018],{"__ignoreMap":174},[179,3963,3964],{"class":181,"line":182},[179,3965,3966],{"class":185},"// tsconfig.json\n",[179,3968,3969],{"class":181,"line":189},[179,3970,213],{"class":212},[179,3972,3973,3975,3978,3980,3983],{"class":181,"line":16},[179,3974,2725],{"class":212},[179,3976,3977],{"class":256},"compilerOptions",[179,3979,253],{"class":212},[179,3981,3982],{"class":219},": ",[179,3984,213],{"class":212},[179,3986,3987,3989,3992,3994,3996,3998],{"class":181,"line":216},[179,3988,2739],{"class":212},[179,3990,3991],{"class":219},"strict",[179,3993,253],{"class":212},[179,3995,448],{"class":212},[179,3997,2980],{"class":2979},[179,3999,2827],{"class":212},[179,4001,4002,4004,4007,4009,4011],{"class":181,"line":229},[179,4003,2739],{"class":212},[179,4005,4006],{"class":219},"noImplicitAny",[179,4008,253],{"class":212},[179,4010,448],{"class":212},[179,4012,4013],{"class":2979}," true\n",[179,4015,4016],{"class":181,"line":265},[179,4017,1186],{"class":212},[179,4019,4020],{"class":181,"line":278},[179,4021,494],{"class":212},[161,4023,4025],{"id":4024},"_2-nested-routing-changes","2. Nested Routing Changes",[102,4027,4028],{},"Nuxt 4 has stricter nested routing behavior.",[102,4030,4031,4033],{},[122,4032,3946],{}," Routes not working as expected",[102,4035,4036,4038],{},[122,4037,3952],{}," Check file structure:",[169,4040,4043],{"className":4041,"code":4042,"language":3027},[3025],"pages/\n├── users/\n│ ├── index.vue → /users\n│ └── [id].vue → /users/:id\n",[176,4044,4042],{"__ignoreMap":174},[161,4046,4048],{"id":4047},"_3-module-api-changes","3. Module API Changes",[102,4050,4051],{},"Some modules changed their APIs.",[102,4053,4054],{},[122,4055,4056],{},"Example - @nuxt/content v3:",[169,4058,4060],{"className":171,"code":4059,"language":173,"meta":174,"style":174},"// Old\nconst articles = await queryContent(\"articles\").find()\n\n// New (same API, better types)\nconst articles = await queryCollection(\"articles\").find()\n",[176,4061,4062,4067,4099,4103,4108],{"__ignoreMap":174},[179,4063,4064],{"class":181,"line":182},[179,4065,4066],{"class":185},"// Old\n",[179,4068,4069,4071,4074,4076,4078,4081,4083,4085,4088,4090,4092,4094,4097],{"class":181,"line":189},[179,4070,537],{"class":232},[179,4072,4073],{"class":208}," articles ",[179,4075,3831],{"class":212},[179,4077,424],{"class":197},[179,4079,4080],{"class":204}," queryContent",[179,4082,209],{"class":208},[179,4084,253],{"class":212},[179,4086,4087],{"class":256},"articles",[179,4089,253],{"class":212},[179,4091,3474],{"class":208},[179,4093,716],{"class":212},[179,4095,4096],{"class":204},"find",[179,4098,722],{"class":208},[179,4100,4101],{"class":181,"line":16},[179,4102,625],{"emptyLinePlaceholder":624},[179,4104,4105],{"class":181,"line":216},[179,4106,4107],{"class":185},"// New (same API, better types)\n",[179,4109,4110,4112,4114,4116,4118,4121,4123,4125,4127,4129,4131,4133,4135],{"class":181,"line":229},[179,4111,537],{"class":232},[179,4113,4073],{"class":208},[179,4115,3831],{"class":212},[179,4117,424],{"class":197},[179,4119,4120],{"class":204}," queryCollection",[179,4122,209],{"class":208},[179,4124,253],{"class":212},[179,4126,4087],{"class":256},[179,4128,253],{"class":212},[179,4130,3474],{"class":208},[179,4132,716],{"class":212},[179,4134,4096],{"class":204},[179,4136,722],{"class":208},[161,4138,4140],{"id":4139},"_4-deprecated-apis","4. Deprecated APIs",[102,4142,4143],{},[122,4144,4145],{},"Removed:",[116,4147,4148,4154,4160],{},[119,4149,4150,4153],{},[176,4151,4152],{},"@nuxt/types"," (use built-in types)",[119,4155,4156,4159],{},[176,4157,4158],{},"nuxt.config.js"," (use .ts only)",[119,4161,4162],{},"Some legacy hooks",[102,4164,4165],{},[122,4166,4167],{},"Check deprecated APIs:",[169,4169,4171],{"className":858,"code":4170,"language":860,"meta":174,"style":174},"npx nuxi analyze\n",[176,4172,4173],{"__ignoreMap":174},[179,4174,4175,4177,4179],{"class":181,"line":182},[179,4176,872],{"class":471},[179,4178,2406],{"class":256},[179,4180,4181],{"class":256}," analyze\n",[1237,4183],{},[98,4185,4187],{"id":4186},"common-issues-troubleshooting","Common Issues & Troubleshooting",[161,4189,4191],{"id":4190},"issue-1-module-x-is-not-compatible-with-nuxt-4","Issue 1: \"Module X is not compatible with Nuxt 4\"",[102,4193,4194],{},[122,4195,3952],{},[169,4197,4199],{"className":858,"code":4198,"language":860,"meta":174,"style":174},"# Check for updates\nnpm outdated\n\n# Update specific module\nnpm install @nuxt/content@latest\n\n# Or find alternative\n# Check Nuxt modules directory: https://nuxt.com/modules\n",[176,4200,4201,4206,4213,4217,4222,4231,4235,4240],{"__ignoreMap":174},[179,4202,4203],{"class":181,"line":182},[179,4204,4205],{"class":185},"# Check for updates\n",[179,4207,4208,4210],{"class":181,"line":189},[179,4209,2423],{"class":471},[179,4211,4212],{"class":256}," outdated\n",[179,4214,4215],{"class":181,"line":16},[179,4216,625],{"emptyLinePlaceholder":624},[179,4218,4219],{"class":181,"line":216},[179,4220,4221],{"class":185},"# Update specific module\n",[179,4223,4224,4226,4228],{"class":181,"line":229},[179,4225,2423],{"class":471},[179,4227,2426],{"class":256},[179,4229,4230],{"class":256}," @nuxt/content@latest\n",[179,4232,4233],{"class":181,"line":265},[179,4234,625],{"emptyLinePlaceholder":624},[179,4236,4237],{"class":181,"line":278},[179,4238,4239],{"class":185},"# Or find alternative\n",[179,4241,4242],{"class":181,"line":284},[179,4243,4244],{"class":185},"# Check Nuxt modules directory: https://nuxt.com/modules\n",[161,4246,4248],{"id":4247},"issue-2-typescript-errors-after-migration","Issue 2: TypeScript Errors After Migration",[102,4250,4251],{},[122,4252,3952],{},[169,4254,4256],{"className":858,"code":4255,"language":860,"meta":174,"style":174},"# Regenerate types\nnpx nuxi prepare\n\n# Clear cache\nnpx nuxi cleanup\n\n# Check specific file\nnpx tsc --noEmit --pretty\n",[176,4257,4258,4263,4272,4276,4281,4290,4294,4299],{"__ignoreMap":174},[179,4259,4260],{"class":181,"line":182},[179,4261,4262],{"class":185},"# Regenerate types\n",[179,4264,4265,4267,4269],{"class":181,"line":189},[179,4266,872],{"class":471},[179,4268,2406],{"class":256},[179,4270,4271],{"class":256}," prepare\n",[179,4273,4274],{"class":181,"line":16},[179,4275,625],{"emptyLinePlaceholder":624},[179,4277,4278],{"class":181,"line":216},[179,4279,4280],{"class":185},"# Clear cache\n",[179,4282,4283,4285,4287],{"class":181,"line":229},[179,4284,872],{"class":471},[179,4286,2406],{"class":256},[179,4288,4289],{"class":256}," cleanup\n",[179,4291,4292],{"class":181,"line":265},[179,4293,625],{"emptyLinePlaceholder":624},[179,4295,4296],{"class":181,"line":278},[179,4297,4298],{"class":185},"# Check specific file\n",[179,4300,4301,4303,4306,4309],{"class":181,"line":284},[179,4302,872],{"class":471},[179,4304,4305],{"class":256}," tsc",[179,4307,4308],{"class":256}," --noEmit",[179,4310,4311],{"class":256}," --pretty\n",[161,4313,4315],{"id":4314},"issue-3-build-fails-with-cannot-find-module","Issue 3: Build Fails with \"Cannot find module\"",[102,4317,4318],{},[122,4319,3952],{},[169,4321,4323],{"className":858,"code":4322,"language":860,"meta":174,"style":174},"# Clear node_modules and reinstall\nrm -rf node_modules .nuxt\nnpm install\nnpx nuxi prepare\n",[176,4324,4325,4330,4344,4350],{"__ignoreMap":174},[179,4326,4327],{"class":181,"line":182},[179,4328,4329],{"class":185},"# Clear node_modules and reinstall\n",[179,4331,4332,4335,4338,4341],{"class":181,"line":189},[179,4333,4334],{"class":471},"rm",[179,4336,4337],{"class":256}," -rf",[179,4339,4340],{"class":256}," node_modules",[179,4342,4343],{"class":256}," .nuxt\n",[179,4345,4346,4348],{"class":181,"line":16},[179,4347,2423],{"class":471},[179,4349,2777],{"class":256},[179,4351,4352,4354,4356],{"class":181,"line":216},[179,4353,872],{"class":471},[179,4355,2406],{"class":256},[179,4357,4271],{"class":256},[161,4359,4361],{"id":4360},"issue-4-hmr-not-working","Issue 4: HMR Not Working",[102,4363,4364],{},[122,4365,3952],{},[169,4367,4369],{"className":171,"code":4368,"language":173,"meta":174,"style":174},"// nuxt.config.ts\nexport default defineNuxtConfig({\n vite: {\n server: {\n watch: {\n usePolling: true,\n },\n },\n },\n})\n",[176,4370,4371,4376,4388,4397,4406,4415,4426,4431,4435,4439],{"__ignoreMap":174},[179,4372,4373],{"class":181,"line":182},[179,4374,4375],{"class":185},"// nuxt.config.ts\n",[179,4377,4378,4380,4382,4384,4386],{"class":181,"line":189},[179,4379,198],{"class":197},[179,4381,201],{"class":197},[179,4383,2800],{"class":204},[179,4385,209],{"class":208},[179,4387,213],{"class":212},[179,4389,4390,4393,4395],{"class":181,"line":16},[179,4391,4392],{"class":219}," vite",[179,4394,448],{"class":212},[179,4396,226],{"class":212},[179,4398,4399,4402,4404],{"class":181,"line":216},[179,4400,4401],{"class":219}," server",[179,4403,448],{"class":212},[179,4405,226],{"class":212},[179,4407,4408,4411,4413],{"class":181,"line":229},[179,4409,4410],{"class":219}," watch",[179,4412,448],{"class":212},[179,4414,226],{"class":212},[179,4416,4417,4420,4422,4424],{"class":181,"line":265},[179,4418,4419],{"class":219}," usePolling",[179,4421,448],{"class":212},[179,4423,2980],{"class":2979},[179,4425,2827],{"class":212},[179,4427,4428],{"class":181,"line":278},[179,4429,4430],{"class":212}," },\n",[179,4432,4433],{"class":181,"line":284},[179,4434,2866],{"class":212},[179,4436,4437],{"class":181,"line":2451},[179,4438,281],{"class":212},[179,4440,4441,4443],{"class":181,"line":2461},[179,4442,287],{"class":212},[179,4444,262],{"class":208},[161,4446,4448],{"id":4447},"issue-5-server-routes-not-working","Issue 5: Server Routes Not Working",[102,4450,4451],{},[122,4452,3952],{},[116,4454,4455,4465,4468],{},[119,4456,4457,4458,4461,4462],{},"Ensure files are in ",[176,4459,4460],{},"server/api/"," or ",[176,4463,4464],{},"server/routes/",[119,4466,4467],{},"Check Nitro configuration",[119,4469,4470],{},"Restart dev server",[1237,4472],{},[98,4474,4476],{"id":4475},"post-migration-checklist","Post-Migration Checklist",[102,4478,4479],{},"After completing the migration:",[161,4481,4483],{"id":4482},"_1-run-full-test-suite","✅ 1. Run Full Test Suite",[169,4485,4487],{"className":858,"code":4486,"language":860,"meta":174,"style":174},"npm run test\nnpm run test:e2e\n",[176,4488,4489,4497],{"__ignoreMap":174},[179,4490,4491,4493,4495],{"class":181,"line":182},[179,4492,2423],{"class":471},[179,4494,2555],{"class":256},[179,4496,2579],{"class":256},[179,4498,4499,4501,4503],{"class":181,"line":189},[179,4500,2423],{"class":471},[179,4502,2555],{"class":256},[179,4504,4505],{"class":256}," test:e2e\n",[161,4507,4509],{"id":4508},"_2-type-check","✅ 2. Type Check",[169,4511,4512],{"className":858,"code":2546,"language":860,"meta":174,"style":174},[176,4513,4514],{"__ignoreMap":174},[179,4515,4516,4518,4520],{"class":181,"line":182},[179,4517,2423],{"class":471},[179,4519,2555],{"class":256},[179,4521,2558],{"class":256},[161,4523,4525],{"id":4524},"_3-build-production","✅ 3. Build Production",[169,4527,4529],{"className":858,"code":4528,"language":860,"meta":174,"style":174},"npm run build\nnpm run preview\n",[176,4530,4531,4540],{"__ignoreMap":174},[179,4532,4533,4535,4537],{"class":181,"line":182},[179,4534,2423],{"class":471},[179,4536,2555],{"class":256},[179,4538,4539],{"class":256}," build\n",[179,4541,4542,4544,4546],{"class":181,"line":189},[179,4543,2423],{"class":471},[179,4545,2555],{"class":256},[179,4547,4548],{"class":256}," preview\n",[161,4550,4552],{"id":4551},"_4-performance-audit","✅ 4. Performance Audit",[169,4554,4556],{"className":858,"code":4555,"language":860,"meta":174,"style":174},"# Run Lighthouse\nnpx lighthouse http://localhost:3000\n",[176,4557,4558,4563],{"__ignoreMap":174},[179,4559,4560],{"class":181,"line":182},[179,4561,4562],{"class":185},"# Run Lighthouse\n",[179,4564,4565,4567,4570],{"class":181,"line":189},[179,4566,872],{"class":471},[179,4568,4569],{"class":256}," lighthouse",[179,4571,4572],{"class":256}," http://localhost:3000\n",[161,4574,4576],{"id":4575},"_5-monitor-in-production","✅ 5. Monitor in Production",[116,4578,4579,4582,4585],{},[119,4580,4581],{},"Set up error tracking (Sentry, LogRocket)",[119,4583,4584],{},"Monitor Core Web Vitals",[119,4586,4587],{},"Check analytics for issues",[1237,4589],{},[98,4591,4593],{"id":4592},"migration-timeline","Migration Timeline",[102,4595,4596],{},[122,4597,4598],{},"Recommended Schedule:",[116,4600,4601,4607,4613],{},[119,4602,4603,4606],{},[122,4604,4605],{},"Week 1",": Pre-migration preparation (updates, backups, compatibility check)",[119,4608,4609,4612],{},[122,4610,4611],{},"Week 2",": Run codemod, fix breaking changes, update modules",[119,4614,4615,4618],{},[122,4616,4617],{},"Week 3",": Testing, performance optimization, deployment",[102,4620,4621,4624],{},[122,4622,4623],{},"Don't wait until January 2026!"," Start your migration now to avoid last-minute issues.",[1237,4626],{},[98,4628,4630],{"id":4629},"performance-improvements-after-migration","Performance Improvements After Migration",[102,4632,4633],{},"Real-world results from migrating to Nuxt 4:",[755,4635,4636,4651],{},[758,4637,4638],{},[761,4639,4640,4643,4646,4648],{},[764,4641,4642],{},"Metric",[764,4644,4645],{},"Nuxt 3",[764,4647,517],{},[764,4649,4650],{},"Improvement",[780,4652,4653,4669,4685,4700,4715],{},[761,4654,4655,4658,4661,4664],{},[785,4656,4657],{},"Build Time",[785,4659,4660],{},"45s",[785,4662,4663],{},"32s",[785,4665,4666],{},[122,4667,4668],{},"29% faster",[761,4670,4671,4674,4677,4680],{},[785,4672,4673],{},"HMR Update",[785,4675,4676],{},"800ms",[785,4678,4679],{},"350ms",[785,4681,4682],{},[122,4683,4684],{},"56% faster",[761,4686,4687,4689,4692,4695],{},[785,4688,775],{},[785,4690,4691],{},"2.1s",[785,4693,4694],{},"1.6s",[785,4696,4697],{},[122,4698,4699],{},"24% faster",[761,4701,4702,4704,4707,4710],{},[785,4703,772],{},[785,4705,4706],{},"185KB",[785,4708,4709],{},"162KB",[785,4711,4712],{},[122,4713,4714],{},"12% smaller",[761,4716,4717,4719,4722,4725],{},[785,4718,769],{},[785,4720,4721],{},"3.2s",[785,4723,4724],{},"2.4s",[785,4726,4727],{},[122,4728,4729],{},"25% faster",[1237,4731],{},[98,4733,4735],{"id":4734},"faq-nuxt-3-to-nuxt-4-migration","FAQ: Nuxt 3 to Nuxt 4 Migration",[161,4737,4739],{"id":4738},"when-is-nuxt-3-end-of-life","When is Nuxt 3 end of life?",[102,4741,4742,4745],{},[122,4743,4744],{},"Nuxt 3 official support ends January 31, 2026."," After this date, there will be no security patches, bug fixes, or maintenance updates.",[161,4747,4749],{"id":4748},"how-long-does-migration-take","How long does migration take?",[102,4751,4752,4753,4756],{},"For most projects: ",[122,4754,4755],{},"4-8 hours"," of active work, spread over 2-3 days for testing. Large enterprise applications may take 1-2 weeks.",[161,4758,4760],{"id":4759},"is-nuxt-4-backward-compatible","Is Nuxt 4 backward compatible?",[102,4762,4763,4766],{},[122,4764,4765],{},"Mostly yes."," Nuxt 4 maintains compatibility with most Nuxt 3 APIs. The codemod tool handles most breaking changes automatically.",[161,4768,4770],{"id":4769},"what-if-my-module-isnt-nuxt-4-compatible","What if my module isn't Nuxt 4 compatible?",[102,4772,4773],{},"Check for:",[1200,4775,4776,4779,4782],{},[119,4777,4778],{},"Module updates (many released Nuxt 4 versions)",[119,4780,4781],{},"Alternative modules",[119,4783,4784],{},"Native Nuxt 4 solutions (e.g., Nitro routes instead of middleware)",[161,4786,4788],{"id":4787},"can-i-rollback-if-migration-fails","Can I rollback if migration fails?",[102,4790,4791,4794],{},[122,4792,4793],{},"Yes."," That's why we recommend creating a git branch first. You can always checkout your pre-migration code.",[161,4796,4798],{"id":4797},"should-new-projects-start-with-nuxt-4","Should new projects start with Nuxt 4?",[102,4800,4801,4804],{},[122,4802,4803],{},"Absolutely."," Nuxt 4 is stable, production-ready, and the recommended version for all new projects in 2026.",[161,4806,4808],{"id":4807},"what-about-nuxt-5","What about Nuxt 5?",[102,4810,4811],{},"Nuxt 5 is planned for late 2026 with Nitro v3. Nuxt 4 provides a stable foundation with a clear upgrade path to Nuxt 5.",[1237,4813],{},[98,4815,4817],{"id":4816},"next-steps","Next Steps",[102,4819,4820],{},"Now that you've migrated to Nuxt 4:",[1200,4822,4823,4834,4844],{},[119,4824,4825,4828,4829],{},[122,4826,4827],{},"Optimize Performance",": Read our ",[4830,4831,4833],"a",{"href":4832},"/blog/16-nuxt-4-ssr-performance-optimization","Nuxt 4 Performance Optimization Guide",[119,4835,4836,4839,4840],{},[122,4837,4838],{},"Explore New Features",": Check out ",[4830,4841,4843],{"href":4842},"/blog/24-nuxt-4-edge-computing-guide","Nuxt UI v4",[119,4845,4846,4849,4850],{},[122,4847,4848],{},"Deploy to Edge",": Learn about ",[4830,4851,4852],{"href":4842},"Edge Computing with Nuxt 4",[1237,4854],{},[98,4856,4858],{"id":4857},"need-help","Need Help?",[102,4860,4861,4862,716],{},"Migration issues? Drop a comment below or reach out on Twitter ",[4830,4863,4867],{"href":4864,"rel":4865},"https://twitter.com/mubaidr",[4866],"nofollow","@mubaidr",[102,4869,4870],{},[122,4871,4872],{},"Resources:",[116,4874,4875,4882,4889,4896],{},[119,4876,4877],{},[4830,4878,4881],{"href":4879,"rel":4880},"https://nuxt.com/docs/getting-started/upgrade",[4866],"Official Nuxt 4 Migration Guide",[119,4883,4884],{},[4830,4885,4888],{"href":4886,"rel":4887},"https://nuxt.com/blog/v4",[4866],"Nuxt 4 Release Notes",[119,4890,4891],{},[4830,4892,4895],{"href":4893,"rel":4894},"https://codemod.com/registry/nuxt-4-migration-recipe",[4866],"Codemod Tool",[119,4897,4898],{},[4830,4899,4902],{"href":4900,"rel":4901},"https://discord.nuxt.com",[4866],"Nuxt Discord",[1237,4904],{},[102,4906,4907,4909],{},[122,4908,1243],{}," Start with the pre-migration checklist today, and you'll be running Nuxt 4 before the end of the week. Your future self (and your users) will thank you!",[1246,4911,4912],{},"html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}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);}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 .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sfNiH, html code.shiki .sfNiH{--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}",{"title":174,"searchDepth":189,"depth":189,"links":4914},[4915,4916,4917,4920,4927,4937,4943,4950,4957,4958,4959,4968,4969],{"id":2196,"depth":189,"text":2191},{"id":2237,"depth":189,"text":2238},{"id":2278,"depth":189,"text":2279,"children":4918},[4919],{"id":2282,"depth":16,"text":2283},{"id":2378,"depth":189,"text":2379,"children":4921},[4922,4923,4924,4925,4926],{"id":2385,"depth":16,"text":2386},{"id":2471,"depth":16,"text":2472},{"id":2539,"depth":16,"text":2540},{"id":2561,"depth":16,"text":2562},{"id":2582,"depth":16,"text":2583},{"id":2610,"depth":189,"text":2611,"children":4928},[4929,4930,4931,4932,4933,4934,4935,4936],{"id":2614,"depth":16,"text":2615},{"id":2705,"depth":16,"text":2706},{"id":2780,"depth":16,"text":2781},{"id":3008,"depth":16,"text":3009},{"id":3112,"depth":16,"text":3113},{"id":3437,"depth":16,"text":3438},{"id":3603,"depth":16,"text":3604},{"id":3730,"depth":16,"text":3731},{"id":3933,"depth":189,"text":3934,"children":4938},[4939,4940,4941,4942],{"id":3937,"depth":16,"text":3938},{"id":4024,"depth":16,"text":4025},{"id":4047,"depth":16,"text":4048},{"id":4139,"depth":16,"text":4140},{"id":4186,"depth":189,"text":4187,"children":4944},[4945,4946,4947,4948,4949],{"id":4190,"depth":16,"text":4191},{"id":4247,"depth":16,"text":4248},{"id":4314,"depth":16,"text":4315},{"id":4360,"depth":16,"text":4361},{"id":4447,"depth":16,"text":4448},{"id":4475,"depth":189,"text":4476,"children":4951},[4952,4953,4954,4955,4956],{"id":4482,"depth":16,"text":4483},{"id":4508,"depth":16,"text":4509},{"id":4524,"depth":16,"text":4525},{"id":4551,"depth":16,"text":4552},{"id":4575,"depth":16,"text":4576},{"id":4592,"depth":189,"text":4593},{"id":4629,"depth":189,"text":4630},{"id":4734,"depth":189,"text":4735,"children":4960},[4961,4962,4963,4964,4965,4966,4967],{"id":4738,"depth":16,"text":4739},{"id":4748,"depth":16,"text":4749},{"id":4759,"depth":16,"text":4760},{"id":4769,"depth":16,"text":4770},{"id":4787,"depth":16,"text":4788},{"id":4797,"depth":16,"text":4798},{"id":4807,"depth":16,"text":4808},{"id":4816,"depth":189,"text":4817},{"id":4857,"depth":189,"text":4858},"2026-02-25","Step-by-step guide to migrate from Nuxt 3 to Nuxt 4 before January 2026 EOL. Includes codemod tools, breaking changes, module compatibility, and troubleshooting.",{"readingTime":4973,"keywords":4974},"15 min read",[4975,4976,4977,4978,4979,4980,4981,4982,4983,4984],"nuxt 3 to 4 migration","nuxt 4 upgrade guide","nuxt 4 breaking changes","migrate nuxt 3 to 4","nuxt 4 codemod","nuxt 4 migration checklist","nuxt 4 compatibility","vue 3 to vue 4","nuxt 4 typescript","nuxt 4 app directory","/blog/22-nuxt-3-to-4-migration-guide-2026",{"title":2191,"description":4971},"Modern Development","Exploring cutting-edge development practices and tools",{"src":4990,"mime":1287,"alt":4991,"width":1289,"height":1290},"/img/blog/22-nuxt-3-to-4-migration-guide-2026/banner.svg","Nuxt 3 to Nuxt 4 Migration Guide - Upgrade path diagram with before and after code examples","blog/22-nuxt-3-to-4-migration-guide-2026",[1295,4994,4995,4996,1297],"Vue","Migration","TypeScript","s1UGLxrbneRBuHSmwjworg3f6K2Y8ZzD_eJLKdzGve8",{"id":4999,"title":5000,"abstract":5001,"author":93,"authorUrl":5002,"body":5003,"date":7811,"dateUpdated":7811,"description":7812,"excerpt":92,"extension":1278,"featured":624,"headline":5000,"image":92,"meta":7813,"navigation":624,"ogImage":92,"path":7815,"seo":7816,"series":7817,"seriesDescription":7818,"seriesOrder":16,"socialImage":7819,"stem":7823,"tags":7824,"__hash__":7830},"blog/blog/39-execution-systems-first-not-features.md","I Stopped Building Features First - I Now Design Execution Systems First","A shift from feature-driven development to system-driven execution design, with practical patterns from Laravel, Nuxt, and AI systems.","https://mubaidr.js.org",{"type":95,"value":5004,"toc":7797},[5005,5008,5011,5014,5017,5021,5024,5050,5053,5056,5060,5064,5067,5070,5205,5208,5212,5215,5218,5221,5224,5509,6226,6229,6233,6236,6239,6242,6567,7258,7261,7265,7268,7271,7285,7288,7291,7311,7620,7623,7627,7732,7735,7739,7742,7745,7762,7765,7768,7772,7775,7778,7781,7785,7788,7791,7794],[98,5006,5000],{"id":5007},"i-stopped-building-features-first-i-now-design-execution-systems-first",[102,5009,5010],{},"Three years ago, I spent two months building a billing feature for a Laravel SaaS application. On paper, it was straightforward: tiered subscriptions, usage-based metering, invoice generation. The client approved the spec. I built the features. Everything worked.",[102,5012,5013],{},"Then the first edge case hit. A customer upgraded mid-cycle, received a prorated invoice, downgraded the next day, and the system double-charged them. The fix required tracing through five controllers, three event listeners, and a tangled web of Eloquent callbacks to understand the full execution path. What looked like six clean features was actually one broken system. The root cause was never the billing logic - it was the execution flow. I had modeled features, not flows. I had built isolated pieces without designing the sequence, state transitions, and failure recovery that connected them.",[102,5015,5016],{},"That project took three times longer than estimated, not because the features were complex, but because the execution system was an afterthought. I learned a hard lesson: building features first is the fastest path to technical debt. Designing the execution system first is the fastest path to maintainable software.",[98,5018,5020],{"id":5019},"what-execution-systems-first-means-in-practice","What \"Execution Systems First\" Means in Practice",[102,5022,5023],{},"An execution system is the invisible skeleton that turns user intent into completed outcomes. It is not a feature list, a component tree, or a database schema. It is the orchestration layer that defines:",[116,5025,5026,5032,5038,5044],{},[119,5027,5028,5031],{},[122,5029,5030],{},"Flow",": The sequence of steps that transform input into output",[119,5033,5034,5037],{},[122,5035,5036],{},"State",": What data persists between steps and how transitions happen",[119,5039,5040,5043],{},[122,5041,5042],{},"Failure handling",": What happens when a step errors, times out, or produces invalid data",[119,5045,5046,5049],{},[122,5047,5048],{},"Task boundaries",": Where one responsibility ends and another begins",[102,5051,5052],{},"Most teams design features as a list of user stories and acceptance criteria. Each story gets built independently. The execution system emerges accidentally from the accumulation of these pieces. By the time anyone notices the fragmentation, the coupling is already baked in.",[102,5054,5055],{},"Designing execution systems first flips this. Before writing a single line of application code, I map the flow diagram, define the state machine, and decompose the work into units that match the execution path rather than the UI surface area. Features become leaves on an existing tree rather than trees with their own root systems.",[98,5057,5059],{"id":5058},"three-pillars-of-execution-system-design","Three Pillars of Execution System Design",[161,5061,5063],{"id":5062},"_1-execution-flow-design","1. Execution Flow Design",[102,5065,5066],{},"Flow design answers one question: what is the complete path from trigger to outcome, including every branch and failure mode?",[102,5068,5069],{},"For the billing system that failed me, the flow would have revealed the mid-cycle upgrade edge case immediately. A proper flow diagram exposes every transition, every state, and every decision point before implementation begins.",[169,5071,5075],{"className":5072,"code":5073,"language":5074,"meta":174,"style":174},"language-mermaid shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","graph TD\n A[Customer Action Triggered] --> B{Action Type?}\n B -->|Subscribe| C[Create Subscription
Set Active State]\n B -->|Upgrade Tier| D[Calculate Proration]\n B -->|Downgrade Tier| E[Schedule Tier Change
Maintain Current Until Period End]\n B -->|Cancel| F[Run Cancellation Flow]\n\n C --> G[Generate Invoice]\n D --> H{Credit Exists?}\n H -->|Yes| I[Apply Credit
Generate Net Invoice]\n H -->|No| J[Generate Pro-rated Invoice]\n I --> K[Update Subscription State]\n J --> K\n E --> L[Set Pending Tier
Active Tier Unchanged]\n F --> M[Stop Recurring
Process Final Invoice]\n\n K --> N[Send Notification]\n L --> N\n M --> N\n N --> O[Log Audit Trail]\n\n style D fill:#4a6,color:#fff\n style E fill:#a64,color:#fff\n style H fill:#47a,color:#fff\n","mermaid",[176,5076,5077,5082,5087,5092,5097,5102,5107,5111,5116,5121,5126,5131,5136,5141,5147,5153,5158,5164,5170,5176,5182,5187,5193,5199],{"__ignoreMap":174},[179,5078,5079],{"class":181,"line":182},[179,5080,5081],{},"graph TD\n",[179,5083,5084],{"class":181,"line":189},[179,5085,5086],{}," A[Customer Action Triggered] --> B{Action Type?}\n",[179,5088,5089],{"class":181,"line":16},[179,5090,5091],{}," B -->|Subscribe| C[Create Subscription
Set Active State]\n",[179,5093,5094],{"class":181,"line":216},[179,5095,5096],{}," B -->|Upgrade Tier| D[Calculate Proration]\n",[179,5098,5099],{"class":181,"line":229},[179,5100,5101],{}," B -->|Downgrade Tier| E[Schedule Tier Change
Maintain Current Until Period End]\n",[179,5103,5104],{"class":181,"line":265},[179,5105,5106],{}," B -->|Cancel| F[Run Cancellation Flow]\n",[179,5108,5109],{"class":181,"line":278},[179,5110,625],{"emptyLinePlaceholder":624},[179,5112,5113],{"class":181,"line":284},[179,5114,5115],{}," C --> G[Generate Invoice]\n",[179,5117,5118],{"class":181,"line":2451},[179,5119,5120],{}," D --> H{Credit Exists?}\n",[179,5122,5123],{"class":181,"line":2461},[179,5124,5125],{}," H -->|Yes| I[Apply Credit
Generate Net Invoice]\n",[179,5127,5128],{"class":181,"line":2985},[179,5129,5130],{}," H -->|No| J[Generate Pro-rated Invoice]\n",[179,5132,5133],{"class":181,"line":2997},[179,5134,5135],{}," I --> K[Update Subscription State]\n",[179,5137,5138],{"class":181,"line":29},[179,5139,5140],{}," J --> K\n",[179,5142,5144],{"class":181,"line":5143},14,[179,5145,5146],{}," E --> L[Set Pending Tier
Active Tier Unchanged]\n",[179,5148,5150],{"class":181,"line":5149},15,[179,5151,5152],{}," F --> M[Stop Recurring
Process Final Invoice]\n",[179,5154,5156],{"class":181,"line":5155},16,[179,5157,625],{"emptyLinePlaceholder":624},[179,5159,5161],{"class":181,"line":5160},17,[179,5162,5163],{}," K --> N[Send Notification]\n",[179,5165,5167],{"class":181,"line":5166},18,[179,5168,5169],{}," L --> N\n",[179,5171,5173],{"class":181,"line":5172},19,[179,5174,5175],{}," M --> N\n",[179,5177,5179],{"class":181,"line":5178},20,[179,5180,5181],{}," N --> O[Log Audit Trail]\n",[179,5183,5185],{"class":181,"line":5184},21,[179,5186,625],{"emptyLinePlaceholder":624},[179,5188,5190],{"class":181,"line":5189},22,[179,5191,5192],{}," style D fill:#4a6,color:#fff\n",[179,5194,5196],{"class":181,"line":5195},23,[179,5197,5198],{}," style E fill:#a64,color:#fff\n",[179,5200,5202],{"class":181,"line":5201},24,[179,5203,5204],{}," style H fill:#47a,color:#fff\n",[102,5206,5207],{},"This is a simplified version of what I now draw before any billing project starts. The branching at the upgrade and downgrade paths reveals the exact edge case that sank the original project. The state transitions are explicit. The failure paths are visible.",[161,5209,5211],{"id":5210},"_2-state-management-architecture","2. State Management Architecture",[102,5213,5214],{},"Every execution system has state. The question is whether that state is implicit, scattered, or centrally governed.",[102,5216,5217],{},"Implicit state lives in variables scattered across controllers, callbacks, and session data. It is the default approach in most frameworks because it requires no upfront design. It is also the fastest route to bugs that only appear under specific sequences of actions.",[102,5219,5220],{},"Centralized state management uses an explicit state machine or event-sourced store. Every transition is recorded. Every state is queryable. The execution system can be paused, inspected, and resumed at any point.",[102,5222,5223],{},"For Laravel applications, I use a state machine pattern built on Eloquent enums and a dedicated state machine service:",[169,5225,5229],{"className":5226,"code":5227,"language":5228,"meta":174,"style":174},"language-php shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","// Before: feature-first billing with scattered state\nclass SubscriptionController extends Controller\n{\n public function upgrade(Request $request, Subscription $subscription)\n {\n // State lives in multiple places\n $subscription->plan_id = $request->plan_id;\n $subscription->save();\n\n // Proration logic embedded in controller\n $credit = $this->calculateProrationCredit($subscription);\n if ($credit > 0) {\n $subscription->credit_balance += $credit;\n $subscription->save();\n }\n\n // Notification coupled to controller logic\n $subscription->user->notify(new UpgradeConfirmation($subscription));\n\n return redirect()->route('subscription.show', $subscription);\n }\n}\n","php",[176,5230,5231,5236,5250,5254,5286,5291,5296,5323,5337,5341,5346,5369,5387,5409,5421,5426,5430,5435,5465,5469,5500,5505],{"__ignoreMap":174},[179,5232,5233],{"class":181,"line":182},[179,5234,5235],{"class":185},"// Before: feature-first billing with scattered state\n",[179,5237,5238,5241,5244,5247],{"class":181,"line":189},[179,5239,5240],{"class":232},"class",[179,5242,5243],{"class":471}," SubscriptionController",[179,5245,5246],{"class":232}," extends",[179,5248,5249],{"class":471}," Controller\n",[179,5251,5252],{"class":181,"line":16},[179,5253,213],{"class":212},[179,5255,5256,5259,5261,5263,5265,5268,5271,5274,5276,5279,5281,5284],{"class":181,"line":216},[179,5257,5258],{"class":232}," public",[179,5260,405],{"class":232},[179,5262,2489],{"class":204},[179,5264,209],{"class":212},[179,5266,5267],{"class":471},"Request",[179,5269,5270],{"class":212}," $",[179,5272,5273],{"class":208},"request",[179,5275,440],{"class":212},[179,5277,5278],{"class":471}," Subscription",[179,5280,5270],{"class":212},[179,5282,5283],{"class":208},"subscription",[179,5285,262],{"class":212},[179,5287,5288],{"class":181,"line":229},[179,5289,5290],{"class":212}," {\n",[179,5292,5293],{"class":181,"line":265},[179,5294,5295],{"class":185}," // State lives in multiple places\n",[179,5297,5298,5301,5303,5306,5309,5311,5313,5315,5317,5320],{"class":181,"line":278},[179,5299,5300],{"class":212}," $",[179,5302,5283],{"class":208},[179,5304,5305],{"class":212},"->",[179,5307,5308],{"class":208},"plan_id ",[179,5310,3831],{"class":212},[179,5312,5270],{"class":212},[179,5314,5273],{"class":208},[179,5316,5305],{"class":212},[179,5318,5319],{"class":208},"plan_id",[179,5321,5322],{"class":212},";\n",[179,5324,5325,5327,5329,5331,5334],{"class":181,"line":284},[179,5326,5300],{"class":212},[179,5328,5283],{"class":208},[179,5330,5305],{"class":212},[179,5332,5333],{"class":204},"save",[179,5335,5336],{"class":212},"();\n",[179,5338,5339],{"class":181,"line":2451},[179,5340,625],{"emptyLinePlaceholder":624},[179,5342,5343],{"class":181,"line":2461},[179,5344,5345],{"class":185}," // Proration logic embedded in controller\n",[179,5347,5348,5350,5353,5355,5358,5361,5364,5366],{"class":181,"line":2985},[179,5349,5300],{"class":212},[179,5351,5352],{"class":208},"credit ",[179,5354,3831],{"class":212},[179,5356,5357],{"class":212}," $this->",[179,5359,5360],{"class":204},"calculateProrationCredit",[179,5362,5363],{"class":212},"($",[179,5365,5283],{"class":208},[179,5367,5368],{"class":212},");\n",[179,5370,5371,5374,5377,5379,5381,5383,5385],{"class":181,"line":2997},[179,5372,5373],{"class":197}," if",[179,5375,5376],{"class":212}," ($",[179,5378,5352],{"class":208},[179,5380,475],{"class":212},[179,5382,3874],{"class":3873},[179,5384,3474],{"class":212},[179,5386,226],{"class":212},[179,5388,5389,5392,5394,5396,5399,5402,5404,5407],{"class":181,"line":29},[179,5390,5391],{"class":212}," $",[179,5393,5283],{"class":208},[179,5395,5305],{"class":212},[179,5397,5398],{"class":208},"credit_balance ",[179,5400,5401],{"class":212},"+=",[179,5403,5270],{"class":212},[179,5405,5406],{"class":208},"credit",[179,5408,5322],{"class":212},[179,5410,5411,5413,5415,5417,5419],{"class":181,"line":5143},[179,5412,5391],{"class":212},[179,5414,5283],{"class":208},[179,5416,5305],{"class":212},[179,5418,5333],{"class":204},[179,5420,5336],{"class":212},[179,5422,5423],{"class":181,"line":5149},[179,5424,5425],{"class":212}," }\n",[179,5427,5428],{"class":181,"line":5155},[179,5429,625],{"emptyLinePlaceholder":624},[179,5431,5432],{"class":181,"line":5160},[179,5433,5434],{"class":185}," // Notification coupled to controller logic\n",[179,5436,5437,5439,5441,5443,5445,5447,5450,5452,5455,5458,5460,5462],{"class":181,"line":5166},[179,5438,5300],{"class":212},[179,5440,5283],{"class":208},[179,5442,5305],{"class":212},[179,5444,3719],{"class":208},[179,5446,5305],{"class":212},[179,5448,5449],{"class":204},"notify",[179,5451,209],{"class":212},[179,5453,5454],{"class":3873},"new",[179,5456,5457],{"class":471}," UpgradeConfirmation",[179,5459,5363],{"class":212},[179,5461,5283],{"class":208},[179,5463,5464],{"class":212},"));\n",[179,5466,5467],{"class":181,"line":5172},[179,5468,625],{"emptyLinePlaceholder":624},[179,5470,5471,5474,5477,5480,5483,5485,5487,5490,5492,5494,5496,5498],{"class":181,"line":5178},[179,5472,5473],{"class":197}," return",[179,5475,5476],{"class":204}," redirect",[179,5478,5479],{"class":212},"()->",[179,5481,5482],{"class":204},"route",[179,5484,209],{"class":212},[179,5486,432],{"class":212},[179,5488,5489],{"class":256},"subscription.show",[179,5491,432],{"class":212},[179,5493,440],{"class":212},[179,5495,5270],{"class":212},[179,5497,5283],{"class":208},[179,5499,5368],{"class":212},[179,5501,5502],{"class":181,"line":5184},[179,5503,5504],{"class":212}," }\n",[179,5506,5507],{"class":181,"line":5189},[179,5508,494],{"class":212},[169,5510,5512],{"className":5226,"code":5511,"language":5228,"meta":174,"style":174},"// After: execution system with explicit state machine\n\nenum SubscriptionState: string\n{\n case Active = 'active';\n case PendingDowngrade = 'pending_downgrade';\n case PendingUpgrade = 'pending_upgrade';\n case Canceled = 'canceled';\n case PastDue = 'past_due';\n}\n\nclass SubscriptionExecutionService\n{\n public function __construct(\n private SubscriptionStateMachine $stateMachine,\n private ProrationService $proration,\n private InvoiceService $invoices,\n private NotificationService $notifications,\n ) {}\n\n public function executeTierChange(\n Subscription $subscription,\n Tier $newTier,\n ChangeDirection $direction\n ): ExecutionResult {\n // Validates transition is legal in current state\n $this->stateMachine->assertCanTransitionTo(\n $subscription,\n $direction === ChangeDirection::Upgrade\n ? SubscriptionState::PendingUpgrade\n : SubscriptionState::PendingDowngrade\n );\n\n // Calculates proration as a pure function\n $proration = $this->proration->calculate(\n $subscription,\n $newTier,\n $direction\n );\n\n // Applies state transition atomically\n $result = DB::transaction(function () use (\n $subscription, $newTier, $proration, $direction\n ) {\n $updated = $this->stateMachine->transition(\n $subscription,\n $direction === ChangeDirection::Upgrade\n ? SubscriptionState::PendingUpgrade\n : SubscriptionState::PendingDowngrade\n );\n\n $invoice = $this->invoices->generate(\n $updated,\n $proration\n );\n\n return new ExecutionResult($updated, $invoice, $proration);\n });\n\n // Notification is a side-effect, not business logic\n $this->notifications->tierChanged($result);\n\n return $result;\n }\n}\n",[176,5513,5514,5519,5523,5536,5540,5559,5577,5595,5613,5631,5635,5639,5646,5650,5662,5677,5691,5705,5719,5727,5731,5742,5753,5765,5775,5786,5792,5807,5816,5836,5849,5862,5868,5873,5879,5900,5909,5918,5925,5930,5935,5941,5972,5996,6004,6025,6035,6050,6062,6074,6080,6085,6106,6116,6124,6129,6134,6164,6170,6175,6181,6200,6205,6216,6221],{"__ignoreMap":174},[179,5515,5516],{"class":181,"line":182},[179,5517,5518],{"class":185},"// After: execution system with explicit state machine\n",[179,5520,5521],{"class":181,"line":189},[179,5522,625],{"emptyLinePlaceholder":624},[179,5524,5525,5528,5531,5533],{"class":181,"line":16},[179,5526,5527],{"class":232},"enum",[179,5529,5530],{"class":471}," SubscriptionState",[179,5532,448],{"class":212},[179,5534,5535],{"class":3873}," string\n",[179,5537,5538],{"class":181,"line":216},[179,5539,213],{"class":212},[179,5541,5542,5545,5548,5550,5552,5555,5557],{"class":181,"line":229},[179,5543,5544],{"class":232}," case",[179,5546,5547],{"class":208}," Active ",[179,5549,3831],{"class":212},[179,5551,451],{"class":212},[179,5553,5554],{"class":256},"active",[179,5556,432],{"class":212},[179,5558,5322],{"class":212},[179,5560,5561,5563,5566,5568,5570,5573,5575],{"class":181,"line":265},[179,5562,5544],{"class":232},[179,5564,5565],{"class":208}," PendingDowngrade ",[179,5567,3831],{"class":212},[179,5569,451],{"class":212},[179,5571,5572],{"class":256},"pending_downgrade",[179,5574,432],{"class":212},[179,5576,5322],{"class":212},[179,5578,5579,5581,5584,5586,5588,5591,5593],{"class":181,"line":278},[179,5580,5544],{"class":232},[179,5582,5583],{"class":208}," PendingUpgrade ",[179,5585,3831],{"class":212},[179,5587,451],{"class":212},[179,5589,5590],{"class":256},"pending_upgrade",[179,5592,432],{"class":212},[179,5594,5322],{"class":212},[179,5596,5597,5599,5602,5604,5606,5609,5611],{"class":181,"line":284},[179,5598,5544],{"class":232},[179,5600,5601],{"class":208}," Canceled ",[179,5603,3831],{"class":212},[179,5605,451],{"class":212},[179,5607,5608],{"class":256},"canceled",[179,5610,432],{"class":212},[179,5612,5322],{"class":212},[179,5614,5615,5617,5620,5622,5624,5627,5629],{"class":181,"line":2451},[179,5616,5544],{"class":232},[179,5618,5619],{"class":208}," PastDue ",[179,5621,3831],{"class":212},[179,5623,451],{"class":212},[179,5625,5626],{"class":256},"past_due",[179,5628,432],{"class":212},[179,5630,5322],{"class":212},[179,5632,5633],{"class":181,"line":2461},[179,5634,494],{"class":212},[179,5636,5637],{"class":181,"line":2985},[179,5638,625],{"emptyLinePlaceholder":624},[179,5640,5641,5643],{"class":181,"line":2997},[179,5642,5240],{"class":232},[179,5644,5645],{"class":471}," SubscriptionExecutionService\n",[179,5647,5648],{"class":181,"line":29},[179,5649,213],{"class":212},[179,5651,5652,5654,5656,5659],{"class":181,"line":5143},[179,5653,5258],{"class":232},[179,5655,405],{"class":232},[179,5657,5658],{"class":204}," __construct",[179,5660,5661],{"class":212},"(\n",[179,5663,5664,5667,5670,5672,5675],{"class":181,"line":5149},[179,5665,5666],{"class":232}," private",[179,5668,5669],{"class":471}," SubscriptionStateMachine",[179,5671,5270],{"class":212},[179,5673,5674],{"class":208},"stateMachine",[179,5676,2827],{"class":212},[179,5678,5679,5681,5684,5686,5689],{"class":181,"line":5155},[179,5680,5666],{"class":232},[179,5682,5683],{"class":471}," ProrationService",[179,5685,5270],{"class":212},[179,5687,5688],{"class":208},"proration",[179,5690,2827],{"class":212},[179,5692,5693,5695,5698,5700,5703],{"class":181,"line":5160},[179,5694,5666],{"class":232},[179,5696,5697],{"class":471}," InvoiceService",[179,5699,5270],{"class":212},[179,5701,5702],{"class":208},"invoices",[179,5704,2827],{"class":212},[179,5706,5707,5709,5712,5714,5717],{"class":181,"line":5166},[179,5708,5666],{"class":232},[179,5710,5711],{"class":471}," NotificationService",[179,5713,5270],{"class":212},[179,5715,5716],{"class":208},"notifications",[179,5718,2827],{"class":212},[179,5720,5721,5724],{"class":181,"line":5172},[179,5722,5723],{"class":212}," )",[179,5725,5726],{"class":212}," {}\n",[179,5728,5729],{"class":181,"line":5178},[179,5730,625],{"emptyLinePlaceholder":624},[179,5732,5733,5735,5737,5740],{"class":181,"line":5184},[179,5734,5258],{"class":232},[179,5736,405],{"class":232},[179,5738,5739],{"class":204}," executeTierChange",[179,5741,5661],{"class":212},[179,5743,5744,5747,5749,5751],{"class":181,"line":5189},[179,5745,5746],{"class":471}," Subscription",[179,5748,5270],{"class":212},[179,5750,5283],{"class":208},[179,5752,2827],{"class":212},[179,5754,5755,5758,5760,5763],{"class":181,"line":5195},[179,5756,5757],{"class":471}," Tier",[179,5759,5270],{"class":212},[179,5761,5762],{"class":208},"newTier",[179,5764,2827],{"class":212},[179,5766,5767,5770,5772],{"class":181,"line":5201},[179,5768,5769],{"class":471}," ChangeDirection",[179,5771,5270],{"class":212},[179,5773,5774],{"class":208},"direction\n",[179,5776,5778,5781,5784],{"class":181,"line":5777},25,[179,5779,5780],{"class":212}," ):",[179,5782,5783],{"class":471}," ExecutionResult",[179,5785,226],{"class":212},[179,5787,5789],{"class":181,"line":5788},26,[179,5790,5791],{"class":185}," // Validates transition is legal in current state\n",[179,5793,5795,5798,5800,5802,5805],{"class":181,"line":5794},27,[179,5796,5797],{"class":212}," $this->",[179,5799,5674],{"class":208},[179,5801,5305],{"class":212},[179,5803,5804],{"class":204},"assertCanTransitionTo",[179,5806,5661],{"class":212},[179,5808,5810,5812,5814],{"class":181,"line":5809},28,[179,5811,5391],{"class":212},[179,5813,5283],{"class":208},[179,5815,2827],{"class":212},[179,5817,5819,5821,5824,5827,5830,5833],{"class":181,"line":5818},29,[179,5820,5391],{"class":212},[179,5822,5823],{"class":208},"direction ",[179,5825,5826],{"class":212},"===",[179,5828,5829],{"class":471}," ChangeDirection",[179,5831,5832],{"class":212},"::",[179,5834,5835],{"class":208},"Upgrade\n",[179,5837,5839,5842,5844,5846],{"class":181,"line":5838},30,[179,5840,5841],{"class":212}," ?",[179,5843,5530],{"class":471},[179,5845,5832],{"class":212},[179,5847,5848],{"class":208},"PendingUpgrade\n",[179,5850,5852,5855,5857,5859],{"class":181,"line":5851},31,[179,5853,5854],{"class":212}," :",[179,5856,5530],{"class":471},[179,5858,5832],{"class":212},[179,5860,5861],{"class":208},"PendingDowngrade\n",[179,5863,5865],{"class":181,"line":5864},32,[179,5866,5867],{"class":212}," );\n",[179,5869,5871],{"class":181,"line":5870},33,[179,5872,625],{"emptyLinePlaceholder":624},[179,5874,5876],{"class":181,"line":5875},34,[179,5877,5878],{"class":185}," // Calculates proration as a pure function\n",[179,5880,5882,5884,5887,5889,5891,5893,5895,5898],{"class":181,"line":5881},35,[179,5883,5300],{"class":212},[179,5885,5886],{"class":208},"proration ",[179,5888,3831],{"class":212},[179,5890,5357],{"class":212},[179,5892,5688],{"class":208},[179,5894,5305],{"class":212},[179,5896,5897],{"class":204},"calculate",[179,5899,5661],{"class":212},[179,5901,5903,5905,5907],{"class":181,"line":5902},36,[179,5904,5391],{"class":212},[179,5906,5283],{"class":208},[179,5908,2827],{"class":212},[179,5910,5912,5914,5916],{"class":181,"line":5911},37,[179,5913,5391],{"class":212},[179,5915,5762],{"class":208},[179,5917,2827],{"class":212},[179,5919,5921,5923],{"class":181,"line":5920},38,[179,5922,5391],{"class":212},[179,5924,5774],{"class":208},[179,5926,5928],{"class":181,"line":5927},39,[179,5929,5867],{"class":212},[179,5931,5933],{"class":181,"line":5932},40,[179,5934,625],{"emptyLinePlaceholder":624},[179,5936,5938],{"class":181,"line":5937},41,[179,5939,5940],{"class":185}," // Applies state transition atomically\n",[179,5942,5944,5946,5949,5951,5954,5956,5959,5961,5964,5966,5969],{"class":181,"line":5943},42,[179,5945,5300],{"class":212},[179,5947,5948],{"class":208},"result ",[179,5950,3831],{"class":212},[179,5952,5953],{"class":471}," DB",[179,5955,5832],{"class":212},[179,5957,5958],{"class":204},"transaction",[179,5960,209],{"class":212},[179,5962,5963],{"class":232},"function",[179,5965,3857],{"class":212},[179,5967,5968],{"class":3873}," use",[179,5970,5971],{"class":212}," (\n",[179,5973,5975,5977,5979,5981,5983,5985,5987,5989,5991,5993],{"class":181,"line":5974},43,[179,5976,5391],{"class":212},[179,5978,5283],{"class":208},[179,5980,440],{"class":212},[179,5982,5270],{"class":212},[179,5984,5762],{"class":208},[179,5986,440],{"class":212},[179,5988,5270],{"class":212},[179,5990,5688],{"class":208},[179,5992,440],{"class":212},[179,5994,5995],{"class":208}," $direction\n",[179,5997,5999,6002],{"class":181,"line":5998},44,[179,6000,6001],{"class":212}," )",[179,6003,226],{"class":212},[179,6005,6007,6009,6012,6014,6016,6018,6020,6023],{"class":181,"line":6006},45,[179,6008,5391],{"class":212},[179,6010,6011],{"class":208},"updated ",[179,6013,3831],{"class":212},[179,6015,5357],{"class":212},[179,6017,5674],{"class":208},[179,6019,5305],{"class":212},[179,6021,6022],{"class":204},"transition",[179,6024,5661],{"class":212},[179,6026,6028,6031,6033],{"class":181,"line":6027},46,[179,6029,6030],{"class":212}," $",[179,6032,5283],{"class":208},[179,6034,2827],{"class":212},[179,6036,6038,6040,6042,6044,6046,6048],{"class":181,"line":6037},47,[179,6039,6030],{"class":212},[179,6041,5823],{"class":208},[179,6043,5826],{"class":212},[179,6045,5829],{"class":471},[179,6047,5832],{"class":212},[179,6049,5835],{"class":208},[179,6051,6053,6056,6058,6060],{"class":181,"line":6052},48,[179,6054,6055],{"class":212}," ?",[179,6057,5530],{"class":471},[179,6059,5832],{"class":212},[179,6061,5848],{"class":208},[179,6063,6065,6068,6070,6072],{"class":181,"line":6064},49,[179,6066,6067],{"class":212}," :",[179,6069,5530],{"class":471},[179,6071,5832],{"class":212},[179,6073,5861],{"class":208},[179,6075,6077],{"class":181,"line":6076},50,[179,6078,6079],{"class":212}," );\n",[179,6081,6083],{"class":181,"line":6082},51,[179,6084,625],{"emptyLinePlaceholder":624},[179,6086,6088,6090,6093,6095,6097,6099,6101,6104],{"class":181,"line":6087},52,[179,6089,5391],{"class":212},[179,6091,6092],{"class":208},"invoice ",[179,6094,3831],{"class":212},[179,6096,5357],{"class":212},[179,6098,5702],{"class":208},[179,6100,5305],{"class":212},[179,6102,6103],{"class":204},"generate",[179,6105,5661],{"class":212},[179,6107,6109,6111,6114],{"class":181,"line":6108},53,[179,6110,6030],{"class":212},[179,6112,6113],{"class":208},"updated",[179,6115,2827],{"class":212},[179,6117,6119,6121],{"class":181,"line":6118},54,[179,6120,6030],{"class":212},[179,6122,6123],{"class":208},"proration\n",[179,6125,6127],{"class":181,"line":6126},55,[179,6128,6079],{"class":212},[179,6130,6132],{"class":181,"line":6131},56,[179,6133,625],{"emptyLinePlaceholder":624},[179,6135,6137,6140,6143,6145,6147,6149,6151,6153,6156,6158,6160,6162],{"class":181,"line":6136},57,[179,6138,6139],{"class":197}," return",[179,6141,6142],{"class":3873}," new",[179,6144,5783],{"class":471},[179,6146,5363],{"class":212},[179,6148,6113],{"class":208},[179,6150,440],{"class":212},[179,6152,5270],{"class":212},[179,6154,6155],{"class":208},"invoice",[179,6157,440],{"class":212},[179,6159,5270],{"class":212},[179,6161,5688],{"class":208},[179,6163,5368],{"class":212},[179,6165,6167],{"class":181,"line":6166},58,[179,6168,6169],{"class":212}," });\n",[179,6171,6173],{"class":181,"line":6172},59,[179,6174,625],{"emptyLinePlaceholder":624},[179,6176,6178],{"class":181,"line":6177},60,[179,6179,6180],{"class":185}," // Notification is a side-effect, not business logic\n",[179,6182,6184,6186,6188,6190,6193,6195,6198],{"class":181,"line":6183},61,[179,6185,5797],{"class":212},[179,6187,5716],{"class":208},[179,6189,5305],{"class":212},[179,6191,6192],{"class":204},"tierChanged",[179,6194,5363],{"class":212},[179,6196,6197],{"class":208},"result",[179,6199,5368],{"class":212},[179,6201,6203],{"class":181,"line":6202},62,[179,6204,625],{"emptyLinePlaceholder":624},[179,6206,6208,6210,6212,6214],{"class":181,"line":6207},63,[179,6209,5473],{"class":197},[179,6211,5270],{"class":212},[179,6213,6197],{"class":208},[179,6215,5322],{"class":212},[179,6217,6219],{"class":181,"line":6218},64,[179,6220,5504],{"class":212},[179,6222,6224],{"class":181,"line":6223},65,[179,6225,494],{"class":212},[102,6227,6228],{},"The before version is shorter. It is also untestable without HTTP mocks, un-resumable if it fails mid-execution, and dangerous to modify because state is scattered across the controller body. The after version is longer but each piece is isolated. The state machine enforces valid transitions. The proration logic is a pure function. The persistence happens inside a transaction. Notifications are decoupled side effects.",[161,6230,6232],{"id":6231},"_3-task-decomposition","3. Task Decomposition",[102,6234,6235],{},"Execution systems decompose work into tasks. The mistake most teams make is decomposing along feature boundaries - one task per UI component, one task per API endpoint. This produces tasks that are coupled to presentation, not to execution.",[102,6237,6238],{},"I decompose along failure boundaries instead. A task should represent a unit of work that can succeed or fail independently. If a task fails, the system should be able to retry it, skip it, or route around it without restarting the entire execution.",[102,6240,6241],{},"For Nuxt applications, this maps to composable design:",[169,6243,6245],{"className":171,"code":6244,"language":173,"meta":174,"style":174},"// Feature-first: one composable handles everything\nexport function useCheckout() {\n const { data, error, execute } = useFetch(\"/api/checkout\", {\n immediate: false,\n })\n\n async function checkout(cart: Cart) {\n const validation = validateCart(cart)\n if (!validation.valid) throw new Error(validation.error)\n\n const order = await createOrder(cart)\n const payment = await processPayment(order)\n if (!payment.success) {\n await cancelOrder(order.id)\n throw new Error(payment.error)\n }\n\n await sendConfirmation(order, payment)\n return order\n }\n\n return { data, error, checkout }\n}\n",[176,6246,6247,6252,6265,6301,6313,6319,6323,6346,6364,6401,6405,6425,6446,6466,6485,6504,6508,6512,6530,6537,6541,6545,6563],{"__ignoreMap":174},[179,6248,6249],{"class":181,"line":182},[179,6250,6251],{"class":185},"// Feature-first: one composable handles everything\n",[179,6253,6254,6256,6258,6261,6263],{"class":181,"line":189},[179,6255,198],{"class":197},[179,6257,405],{"class":232},[179,6259,6260],{"class":204}," useCheckout",[179,6262,223],{"class":212},[179,6264,226],{"class":212},[179,6266,6267,6269,6271,6273,6275,6277,6279,6282,6284,6286,6288,6290,6292,6295,6297,6299],{"class":181,"line":16},[179,6268,417],{"class":232},[179,6270,236],{"class":212},[179,6272,239],{"class":208},[179,6274,440],{"class":212},[179,6276,1138],{"class":208},[179,6278,440],{"class":212},[179,6280,6281],{"class":208}," execute",[179,6283,242],{"class":212},[179,6285,245],{"class":212},[179,6287,248],{"class":204},[179,6289,209],{"class":219},[179,6291,253],{"class":212},[179,6293,6294],{"class":256},"/api/checkout",[179,6296,253],{"class":212},[179,6298,440],{"class":212},[179,6300,226],{"class":212},[179,6302,6303,6306,6308,6311],{"class":181,"line":216},[179,6304,6305],{"class":219}," immediate",[179,6307,448],{"class":212},[179,6309,6310],{"class":2979}," false",[179,6312,2827],{"class":212},[179,6314,6315,6317],{"class":181,"line":229},[179,6316,3881],{"class":212},[179,6318,262],{"class":219},[179,6320,6321],{"class":181,"line":265},[179,6322,625],{"emptyLinePlaceholder":624},[179,6324,6325,6328,6330,6332,6334,6337,6339,6342,6344],{"class":181,"line":278},[179,6326,6327],{"class":232}," async",[179,6329,405],{"class":232},[179,6331,2599],{"class":204},[179,6333,209],{"class":212},[179,6335,6336],{"class":694},"cart",[179,6338,448],{"class":212},[179,6340,6341],{"class":471}," Cart",[179,6343,3474],{"class":212},[179,6345,226],{"class":212},[179,6347,6348,6350,6353,6355,6358,6360,6362],{"class":181,"line":284},[179,6349,233],{"class":232},[179,6351,6352],{"class":208}," validation",[179,6354,245],{"class":212},[179,6356,6357],{"class":204}," validateCart",[179,6359,209],{"class":219},[179,6361,6336],{"class":208},[179,6363,262],{"class":219},[179,6365,6366,6368,6370,6373,6376,6378,6381,6383,6386,6388,6391,6393,6395,6397,6399],{"class":181,"line":2451},[179,6367,1152],{"class":197},[179,6369,1155],{"class":219},[179,6371,6372],{"class":212},"!",[179,6374,6375],{"class":208},"validation",[179,6377,716],{"class":212},[179,6379,6380],{"class":208},"valid",[179,6382,1161],{"class":219},[179,6384,6385],{"class":197},"throw",[179,6387,6142],{"class":212},[179,6389,6390],{"class":204}," Error",[179,6392,209],{"class":219},[179,6394,6375],{"class":208},[179,6396,716],{"class":212},[179,6398,1158],{"class":208},[179,6400,262],{"class":219},[179,6402,6403],{"class":181,"line":2461},[179,6404,625],{"emptyLinePlaceholder":624},[179,6406,6407,6409,6412,6414,6416,6419,6421,6423],{"class":181,"line":2985},[179,6408,233],{"class":232},[179,6410,6411],{"class":208}," order",[179,6413,245],{"class":212},[179,6415,424],{"class":197},[179,6417,6418],{"class":204}," createOrder",[179,6420,209],{"class":219},[179,6422,6336],{"class":208},[179,6424,262],{"class":219},[179,6426,6427,6429,6432,6434,6436,6439,6441,6444],{"class":181,"line":2997},[179,6428,233],{"class":232},[179,6430,6431],{"class":208}," payment",[179,6433,245],{"class":212},[179,6435,424],{"class":197},[179,6437,6438],{"class":204}," processPayment",[179,6440,209],{"class":219},[179,6442,6443],{"class":208},"order",[179,6445,262],{"class":219},[179,6447,6448,6450,6452,6454,6457,6459,6462,6464],{"class":181,"line":29},[179,6449,1152],{"class":197},[179,6451,1155],{"class":219},[179,6453,6372],{"class":212},[179,6455,6456],{"class":208},"payment",[179,6458,716],{"class":212},[179,6460,6461],{"class":208},"success",[179,6463,1161],{"class":219},[179,6465,213],{"class":212},[179,6467,6468,6471,6474,6476,6478,6480,6483],{"class":181,"line":5143},[179,6469,6470],{"class":197}," await",[179,6472,6473],{"class":204}," cancelOrder",[179,6475,209],{"class":219},[179,6477,6443],{"class":208},[179,6479,716],{"class":212},[179,6481,6482],{"class":208},"id",[179,6484,262],{"class":219},[179,6486,6487,6490,6492,6494,6496,6498,6500,6502],{"class":181,"line":5149},[179,6488,6489],{"class":197}," throw",[179,6491,6142],{"class":212},[179,6493,6390],{"class":204},[179,6495,209],{"class":219},[179,6497,6456],{"class":208},[179,6499,716],{"class":212},[179,6501,1158],{"class":208},[179,6503,262],{"class":219},[179,6505,6506],{"class":181,"line":5155},[179,6507,5504],{"class":212},[179,6509,6510],{"class":181,"line":5160},[179,6511,625],{"emptyLinePlaceholder":624},[179,6513,6514,6517,6520,6522,6524,6526,6528],{"class":181,"line":5166},[179,6515,6516],{"class":197}," await",[179,6518,6519],{"class":204}," sendConfirmation",[179,6521,209],{"class":219},[179,6523,6443],{"class":208},[179,6525,440],{"class":212},[179,6527,6431],{"class":208},[179,6529,262],{"class":219},[179,6531,6532,6534],{"class":181,"line":5172},[179,6533,268],{"class":197},[179,6535,6536],{"class":208}," order\n",[179,6538,6539],{"class":181,"line":5178},[179,6540,1186],{"class":212},[179,6542,6543],{"class":181,"line":5184},[179,6544,625],{"emptyLinePlaceholder":624},[179,6546,6547,6549,6551,6553,6555,6557,6559,6561],{"class":181,"line":5189},[179,6548,465],{"class":197},[179,6550,236],{"class":212},[179,6552,239],{"class":208},[179,6554,440],{"class":212},[179,6556,1138],{"class":208},[179,6558,440],{"class":212},[179,6560,2599],{"class":208},[179,6562,275],{"class":212},[179,6564,6565],{"class":181,"line":5195},[179,6566,494],{"class":212},[169,6568,6570],{"className":171,"code":6569,"language":173,"meta":174,"style":174},"// System-first: decomposed into failure-independent tasks\nexport function useCheckoutSystem() {\n const step = ref(\"idle\")\n const executionId = ref(null)\n\n const tasks = {\n validate: useTask(\"checkout.validate\", validateCart),\n createOrder: useTask(\"checkout.createOrder\", createOrder),\n processPayment: useTask(\"checkout.processPayment\", processPayment),\n confirm: useTask(\"checkout.confirm\", sendConfirmation),\n }\n\n async function checkout(cart: Cart): Promise {\n executionId.value = generateId()\n step.value = \"validating\"\n\n // Each task runs independently, with its own state and recovery\n const validation = await tasks.validate.run(cart)\n if (!validation.ok) return fail(validation.error)\n\n step.value = \"creating_order\"\n const order = await tasks.createOrder.run(validation.data)\n if (!order.ok) return fail(order.error)\n\n step.value = \"processing_payment\"\n const payment = await tasks.processPayment.run(order.data)\n if (!payment.ok) {\n // Payment failed but order is already created - handle independently\n await tasks.compensate(\"createOrder\", order.data.id).run()\n return fail(payment.error)\n }\n\n step.value = \"confirming\"\n await tasks.confirm.run(order.data)\n\n step.value = \"completed\"\n return success(order.data, payment.data)\n }\n\n return { checkout, step, executionId, tasks }\n}\n",[176,6571,6572,6577,6590,6621,6652,6656,6667,6694,6720,6746,6772,6776,6780,6811,6828,6846,6850,6855,6883,6915,6919,6936,6967,6997,7001,7018,7049,7067,7072,7111,7128,7132,7136,7153,7178,7182,7199,7224,7228,7232,7254],{"__ignoreMap":174},[179,6573,6574],{"class":181,"line":182},[179,6575,6576],{"class":185},"// System-first: decomposed into failure-independent tasks\n",[179,6578,6579,6581,6583,6586,6588],{"class":181,"line":189},[179,6580,198],{"class":197},[179,6582,405],{"class":232},[179,6584,6585],{"class":204}," useCheckoutSystem",[179,6587,223],{"class":212},[179,6589,226],{"class":212},[179,6591,6592,6594,6597,6599,6602,6605,6608,6610,6612,6614,6617,6619],{"class":181,"line":16},[179,6593,417],{"class":232},[179,6595,6596],{"class":208}," step",[179,6598,245],{"class":212},[179,6600,6601],{"class":204}," ref",[179,6603,6604],{"class":212},"<",[179,6606,6607],{"class":471},"CheckoutStep",[179,6609,475],{"class":212},[179,6611,209],{"class":219},[179,6613,253],{"class":212},[179,6615,6616],{"class":256},"idle",[179,6618,253],{"class":212},[179,6620,262],{"class":219},[179,6622,6623,6625,6628,6630,6632,6634,6637,6640,6643,6645,6647,6650],{"class":181,"line":216},[179,6624,417],{"class":232},[179,6626,6627],{"class":208}," executionId",[179,6629,245],{"class":212},[179,6631,6601],{"class":204},[179,6633,6604],{"class":212},[179,6635,6636],{"class":471},"string",[179,6638,6639],{"class":212}," |",[179,6641,6642],{"class":471}," null",[179,6644,475],{"class":212},[179,6646,209],{"class":219},[179,6648,6649],{"class":212},"null",[179,6651,262],{"class":219},[179,6653,6654],{"class":181,"line":229},[179,6655,625],{"emptyLinePlaceholder":624},[179,6657,6658,6660,6663,6665],{"class":181,"line":265},[179,6659,417],{"class":232},[179,6661,6662],{"class":208}," tasks",[179,6664,245],{"class":212},[179,6666,226],{"class":212},[179,6668,6669,6672,6674,6677,6679,6681,6684,6686,6688,6690,6692],{"class":181,"line":278},[179,6670,6671],{"class":219}," validate",[179,6673,448],{"class":212},[179,6675,6676],{"class":204}," useTask",[179,6678,209],{"class":219},[179,6680,253],{"class":212},[179,6682,6683],{"class":256},"checkout.validate",[179,6685,253],{"class":212},[179,6687,440],{"class":212},[179,6689,6357],{"class":208},[179,6691,3474],{"class":219},[179,6693,2827],{"class":212},[179,6695,6696,6699,6701,6703,6705,6707,6710,6712,6714,6716,6718],{"class":181,"line":284},[179,6697,6698],{"class":219}," createOrder",[179,6700,448],{"class":212},[179,6702,6676],{"class":204},[179,6704,209],{"class":219},[179,6706,253],{"class":212},[179,6708,6709],{"class":256},"checkout.createOrder",[179,6711,253],{"class":212},[179,6713,440],{"class":212},[179,6715,6418],{"class":208},[179,6717,3474],{"class":219},[179,6719,2827],{"class":212},[179,6721,6722,6725,6727,6729,6731,6733,6736,6738,6740,6742,6744],{"class":181,"line":2451},[179,6723,6724],{"class":219}," processPayment",[179,6726,448],{"class":212},[179,6728,6676],{"class":204},[179,6730,209],{"class":219},[179,6732,253],{"class":212},[179,6734,6735],{"class":256},"checkout.processPayment",[179,6737,253],{"class":212},[179,6739,440],{"class":212},[179,6741,6438],{"class":208},[179,6743,3474],{"class":219},[179,6745,2827],{"class":212},[179,6747,6748,6751,6753,6755,6757,6759,6762,6764,6766,6768,6770],{"class":181,"line":2461},[179,6749,6750],{"class":219}," confirm",[179,6752,448],{"class":212},[179,6754,6676],{"class":204},[179,6756,209],{"class":219},[179,6758,253],{"class":212},[179,6760,6761],{"class":256},"checkout.confirm",[179,6763,253],{"class":212},[179,6765,440],{"class":212},[179,6767,6519],{"class":208},[179,6769,3474],{"class":219},[179,6771,2827],{"class":212},[179,6773,6774],{"class":181,"line":2985},[179,6775,1186],{"class":212},[179,6777,6778],{"class":181,"line":2997},[179,6779,625],{"emptyLinePlaceholder":624},[179,6781,6782,6784,6786,6788,6790,6792,6794,6796,6799,6802,6804,6807,6809],{"class":181,"line":29},[179,6783,6327],{"class":232},[179,6785,405],{"class":232},[179,6787,2599],{"class":204},[179,6789,209],{"class":212},[179,6791,6336],{"class":694},[179,6793,448],{"class":212},[179,6795,6341],{"class":471},[179,6797,6798],{"class":212},"):",[179,6800,6801],{"class":471}," Promise",[179,6803,6604],{"class":212},[179,6805,6806],{"class":471},"ExecutionResult",[179,6808,475],{"class":212},[179,6810,226],{"class":212},[179,6812,6813,6816,6818,6821,6823,6826],{"class":181,"line":5143},[179,6814,6815],{"class":208}," executionId",[179,6817,716],{"class":212},[179,6819,6820],{"class":208},"value",[179,6822,245],{"class":212},[179,6824,6825],{"class":204}," generateId",[179,6827,722],{"class":219},[179,6829,6830,6833,6835,6837,6839,6841,6844],{"class":181,"line":5149},[179,6831,6832],{"class":208}," step",[179,6834,716],{"class":212},[179,6836,6820],{"class":208},[179,6838,245],{"class":212},[179,6840,1071],{"class":212},[179,6842,6843],{"class":256},"validating",[179,6845,2754],{"class":212},[179,6847,6848],{"class":181,"line":5155},[179,6849,625],{"emptyLinePlaceholder":624},[179,6851,6852],{"class":181,"line":5160},[179,6853,6854],{"class":185}," // Each task runs independently, with its own state and recovery\n",[179,6856,6857,6859,6861,6863,6865,6867,6869,6872,6874,6877,6879,6881],{"class":181,"line":5166},[179,6858,233],{"class":232},[179,6860,6352],{"class":208},[179,6862,245],{"class":212},[179,6864,424],{"class":197},[179,6866,6662],{"class":208},[179,6868,716],{"class":212},[179,6870,6871],{"class":208},"validate",[179,6873,716],{"class":212},[179,6875,6876],{"class":204},"run",[179,6878,209],{"class":219},[179,6880,6336],{"class":208},[179,6882,262],{"class":219},[179,6884,6885,6887,6889,6891,6893,6895,6898,6900,6902,6905,6907,6909,6911,6913],{"class":181,"line":5172},[179,6886,1152],{"class":197},[179,6888,1155],{"class":219},[179,6890,6372],{"class":212},[179,6892,6375],{"class":208},[179,6894,716],{"class":212},[179,6896,6897],{"class":208},"ok",[179,6899,1161],{"class":219},[179,6901,1164],{"class":197},[179,6903,6904],{"class":204}," fail",[179,6906,209],{"class":219},[179,6908,6375],{"class":208},[179,6910,716],{"class":212},[179,6912,1158],{"class":208},[179,6914,262],{"class":219},[179,6916,6917],{"class":181,"line":5178},[179,6918,625],{"emptyLinePlaceholder":624},[179,6920,6921,6923,6925,6927,6929,6931,6934],{"class":181,"line":5184},[179,6922,6832],{"class":208},[179,6924,716],{"class":212},[179,6926,6820],{"class":208},[179,6928,245],{"class":212},[179,6930,1071],{"class":212},[179,6932,6933],{"class":256},"creating_order",[179,6935,2754],{"class":212},[179,6937,6938,6940,6942,6944,6946,6948,6950,6953,6955,6957,6959,6961,6963,6965],{"class":181,"line":5189},[179,6939,233],{"class":232},[179,6941,6411],{"class":208},[179,6943,245],{"class":212},[179,6945,424],{"class":197},[179,6947,6662],{"class":208},[179,6949,716],{"class":212},[179,6951,6952],{"class":208},"createOrder",[179,6954,716],{"class":212},[179,6956,6876],{"class":204},[179,6958,209],{"class":219},[179,6960,6375],{"class":208},[179,6962,716],{"class":212},[179,6964,1007],{"class":208},[179,6966,262],{"class":219},[179,6968,6969,6971,6973,6975,6977,6979,6981,6983,6985,6987,6989,6991,6993,6995],{"class":181,"line":5195},[179,6970,1152],{"class":197},[179,6972,1155],{"class":219},[179,6974,6372],{"class":212},[179,6976,6443],{"class":208},[179,6978,716],{"class":212},[179,6980,6897],{"class":208},[179,6982,1161],{"class":219},[179,6984,1164],{"class":197},[179,6986,6904],{"class":204},[179,6988,209],{"class":219},[179,6990,6443],{"class":208},[179,6992,716],{"class":212},[179,6994,1158],{"class":208},[179,6996,262],{"class":219},[179,6998,6999],{"class":181,"line":5201},[179,7000,625],{"emptyLinePlaceholder":624},[179,7002,7003,7005,7007,7009,7011,7013,7016],{"class":181,"line":5777},[179,7004,6832],{"class":208},[179,7006,716],{"class":212},[179,7008,6820],{"class":208},[179,7010,245],{"class":212},[179,7012,1071],{"class":212},[179,7014,7015],{"class":256},"processing_payment",[179,7017,2754],{"class":212},[179,7019,7020,7022,7024,7026,7028,7030,7032,7035,7037,7039,7041,7043,7045,7047],{"class":181,"line":5788},[179,7021,233],{"class":232},[179,7023,6431],{"class":208},[179,7025,245],{"class":212},[179,7027,424],{"class":197},[179,7029,6662],{"class":208},[179,7031,716],{"class":212},[179,7033,7034],{"class":208},"processPayment",[179,7036,716],{"class":212},[179,7038,6876],{"class":204},[179,7040,209],{"class":219},[179,7042,6443],{"class":208},[179,7044,716],{"class":212},[179,7046,1007],{"class":208},[179,7048,262],{"class":219},[179,7050,7051,7053,7055,7057,7059,7061,7063,7065],{"class":181,"line":5794},[179,7052,1152],{"class":197},[179,7054,1155],{"class":219},[179,7056,6372],{"class":212},[179,7058,6456],{"class":208},[179,7060,716],{"class":212},[179,7062,6897],{"class":208},[179,7064,1161],{"class":219},[179,7066,213],{"class":212},[179,7068,7069],{"class":181,"line":5809},[179,7070,7071],{"class":185}," // Payment failed but order is already created - handle independently\n",[179,7073,7074,7076,7078,7080,7083,7085,7087,7089,7091,7093,7095,7097,7099,7101,7103,7105,7107,7109],{"class":181,"line":5818},[179,7075,6470],{"class":197},[179,7077,6662],{"class":208},[179,7079,716],{"class":212},[179,7081,7082],{"class":204},"compensate",[179,7084,209],{"class":219},[179,7086,253],{"class":212},[179,7088,6952],{"class":256},[179,7090,253],{"class":212},[179,7092,440],{"class":212},[179,7094,6411],{"class":208},[179,7096,716],{"class":212},[179,7098,1007],{"class":208},[179,7100,716],{"class":212},[179,7102,6482],{"class":208},[179,7104,3474],{"class":219},[179,7106,716],{"class":212},[179,7108,6876],{"class":204},[179,7110,722],{"class":219},[179,7112,7113,7116,7118,7120,7122,7124,7126],{"class":181,"line":5838},[179,7114,7115],{"class":197}," return",[179,7117,6904],{"class":204},[179,7119,209],{"class":219},[179,7121,6456],{"class":208},[179,7123,716],{"class":212},[179,7125,1158],{"class":208},[179,7127,262],{"class":219},[179,7129,7130],{"class":181,"line":5851},[179,7131,5504],{"class":212},[179,7133,7134],{"class":181,"line":5864},[179,7135,625],{"emptyLinePlaceholder":624},[179,7137,7138,7140,7142,7144,7146,7148,7151],{"class":181,"line":5870},[179,7139,6832],{"class":208},[179,7141,716],{"class":212},[179,7143,6820],{"class":208},[179,7145,245],{"class":212},[179,7147,1071],{"class":212},[179,7149,7150],{"class":256},"confirming",[179,7152,2754],{"class":212},[179,7154,7155,7157,7159,7161,7164,7166,7168,7170,7172,7174,7176],{"class":181,"line":5875},[179,7156,6516],{"class":197},[179,7158,6662],{"class":208},[179,7160,716],{"class":212},[179,7162,7163],{"class":208},"confirm",[179,7165,716],{"class":212},[179,7167,6876],{"class":204},[179,7169,209],{"class":219},[179,7171,6443],{"class":208},[179,7173,716],{"class":212},[179,7175,1007],{"class":208},[179,7177,262],{"class":219},[179,7179,7180],{"class":181,"line":5881},[179,7181,625],{"emptyLinePlaceholder":624},[179,7183,7184,7186,7188,7190,7192,7194,7197],{"class":181,"line":5902},[179,7185,6832],{"class":208},[179,7187,716],{"class":212},[179,7189,6820],{"class":208},[179,7191,245],{"class":212},[179,7193,1071],{"class":212},[179,7195,7196],{"class":256},"completed",[179,7198,2754],{"class":212},[179,7200,7201,7203,7206,7208,7210,7212,7214,7216,7218,7220,7222],{"class":181,"line":5911},[179,7202,268],{"class":197},[179,7204,7205],{"class":204}," success",[179,7207,209],{"class":219},[179,7209,6443],{"class":208},[179,7211,716],{"class":212},[179,7213,1007],{"class":208},[179,7215,440],{"class":212},[179,7217,6431],{"class":208},[179,7219,716],{"class":212},[179,7221,1007],{"class":208},[179,7223,262],{"class":219},[179,7225,7226],{"class":181,"line":5920},[179,7227,1186],{"class":212},[179,7229,7230],{"class":181,"line":5927},[179,7231,625],{"emptyLinePlaceholder":624},[179,7233,7234,7236,7238,7240,7242,7244,7246,7248,7250,7252],{"class":181,"line":5932},[179,7235,465],{"class":197},[179,7237,236],{"class":212},[179,7239,2599],{"class":208},[179,7241,440],{"class":212},[179,7243,6596],{"class":208},[179,7245,440],{"class":212},[179,7247,6627],{"class":208},[179,7249,440],{"class":212},[179,7251,6662],{"class":208},[179,7253,275],{"class":212},[179,7255,7256],{"class":181,"line":5937},[179,7257,494],{"class":212},[102,7259,7260],{},"The system-first version reveals the execution boundaries. Payment can fail independently of order creation. The compensation task reverses only what needs reversing. The step state is inspectable, which means the UI can render progress deterministically and the backend can resume interrupted checkouts.",[98,7262,7264],{"id":7263},"real-example-laravel-saas-project","Real Example: Laravel SaaS Project",[102,7266,7267],{},"A client came to me with a Laravel application that managed compliance document workflows. Businesses uploaded documents, assigned reviewers, tracked review cycles, and generated audit trails. The existing codebase had twelve controllers, thirty-four event listeners, and an undocumented webhook handler that occasionally sent duplicate notifications.",[102,7269,7270],{},"The original architecture was feature-first:",[116,7272,7273,7276,7279,7282],{},[119,7274,7275],{},"Document upload feature with its own controller and validation",[119,7277,7278],{},"Reviewer assignment with its own controller and notification logic",[119,7280,7281],{},"Review cycle tracking scattered across three model observers",[119,7283,7284],{},"Audit trail implemented as an afterthought in a middleware",[102,7286,7287],{},"Every feature worked in isolation. The system failed under real conditions because the execution flow crossed feature boundaries. A reviewer rejecting a document should have triggered a reassignment flow. Instead, it logged a status change and sent an email, but the document remained in a dangling half-reviewed state because the next step was never defined.",[102,7289,7290],{},"I rebuilt the system using an execution-first approach:",[1200,7292,7293,7299,7305],{},[119,7294,7295,7298],{},[122,7296,7297],{},"Flow diagram first",": Mapped the complete document lifecycle from upload to final approval, including reject loops, deadline escalations, and withdrawal mid-review",[119,7300,7301,7304],{},[122,7302,7303],{},"State machine",": Defined five document states (Draft, In Review, Changes Requested, Approved, Archived) with explicit transition rules",[119,7306,7307,7310],{},[122,7308,7309],{},"Task decomposition",": Each transition became a task with its own compensation logic",[169,7312,7314],{"className":5226,"code":7313,"language":5228,"meta":174,"style":174},"class DocumentExecutionService\n{\n public function __construct(\n private DocumentStateMachine $states,\n private ReviewAssignmentService $assignments,\n private EscalationService $escalations,\n private AuditService $audit,\n ) {}\n\n public function rejectDocument(\n Document $document,\n Review $review,\n string $reason\n ): ExecutionResult {\n // State transition determines what happens next, not a controller\n return $this->states->transition($document, DocumentState::ChangesRequested)\n ->then(fn() => $this->assignments->reassign($document, $review->reviewer))\n ->then(fn() => $this->escalations->resetDeadline($document))\n ->onFailure(fn($step) => $this->audit->logFailure($document, $step))\n ->execute();\n }\n}\n",[176,7315,7316,7323,7327,7337,7351,7365,7379,7393,7399,7403,7414,7426,7438,7448,7456,7461,7489,7533,7562,7603,7612,7616],{"__ignoreMap":174},[179,7317,7318,7320],{"class":181,"line":182},[179,7319,5240],{"class":232},[179,7321,7322],{"class":471}," DocumentExecutionService\n",[179,7324,7325],{"class":181,"line":189},[179,7326,213],{"class":212},[179,7328,7329,7331,7333,7335],{"class":181,"line":16},[179,7330,5258],{"class":232},[179,7332,405],{"class":232},[179,7334,5658],{"class":204},[179,7336,5661],{"class":212},[179,7338,7339,7341,7344,7346,7349],{"class":181,"line":216},[179,7340,5666],{"class":232},[179,7342,7343],{"class":471}," DocumentStateMachine",[179,7345,5270],{"class":212},[179,7347,7348],{"class":208},"states",[179,7350,2827],{"class":212},[179,7352,7353,7355,7358,7360,7363],{"class":181,"line":229},[179,7354,5666],{"class":232},[179,7356,7357],{"class":471}," ReviewAssignmentService",[179,7359,5270],{"class":212},[179,7361,7362],{"class":208},"assignments",[179,7364,2827],{"class":212},[179,7366,7367,7369,7372,7374,7377],{"class":181,"line":265},[179,7368,5666],{"class":232},[179,7370,7371],{"class":471}," EscalationService",[179,7373,5270],{"class":212},[179,7375,7376],{"class":208},"escalations",[179,7378,2827],{"class":212},[179,7380,7381,7383,7386,7388,7391],{"class":181,"line":278},[179,7382,5666],{"class":232},[179,7384,7385],{"class":471}," AuditService",[179,7387,5270],{"class":212},[179,7389,7390],{"class":208},"audit",[179,7392,2827],{"class":212},[179,7394,7395,7397],{"class":181,"line":284},[179,7396,5723],{"class":212},[179,7398,5726],{"class":212},[179,7400,7401],{"class":181,"line":2451},[179,7402,625],{"emptyLinePlaceholder":624},[179,7404,7405,7407,7409,7412],{"class":181,"line":2461},[179,7406,5258],{"class":232},[179,7408,405],{"class":232},[179,7410,7411],{"class":204}," rejectDocument",[179,7413,5661],{"class":212},[179,7415,7416,7419,7421,7424],{"class":181,"line":2985},[179,7417,7418],{"class":471}," Document",[179,7420,5270],{"class":212},[179,7422,7423],{"class":208},"document",[179,7425,2827],{"class":212},[179,7427,7428,7431,7433,7436],{"class":181,"line":2997},[179,7429,7430],{"class":471}," Review",[179,7432,5270],{"class":212},[179,7434,7435],{"class":208},"review",[179,7437,2827],{"class":212},[179,7439,7440,7443,7445],{"class":181,"line":29},[179,7441,7442],{"class":3873}," string",[179,7444,5270],{"class":212},[179,7446,7447],{"class":208},"reason\n",[179,7449,7450,7452,7454],{"class":181,"line":5143},[179,7451,5780],{"class":212},[179,7453,5783],{"class":471},[179,7455,226],{"class":212},[179,7457,7458],{"class":181,"line":5149},[179,7459,7460],{"class":185}," // State transition determines what happens next, not a controller\n",[179,7462,7463,7465,7467,7469,7471,7473,7475,7477,7479,7482,7484,7487],{"class":181,"line":5155},[179,7464,5473],{"class":197},[179,7466,5357],{"class":212},[179,7468,7348],{"class":208},[179,7470,5305],{"class":212},[179,7472,6022],{"class":204},[179,7474,5363],{"class":212},[179,7476,7423],{"class":208},[179,7478,440],{"class":212},[179,7480,7481],{"class":471}," DocumentState",[179,7483,5832],{"class":212},[179,7485,7486],{"class":208},"ChangesRequested",[179,7488,262],{"class":212},[179,7490,7491,7494,7497,7499,7502,7504,7506,7508,7510,7512,7515,7517,7519,7521,7523,7525,7527,7530],{"class":181,"line":5160},[179,7492,7493],{"class":212}," ->",[179,7495,7496],{"class":204},"then",[179,7498,209],{"class":212},[179,7500,7501],{"class":232},"fn",[179,7503,223],{"class":212},[179,7505,3477],{"class":212},[179,7507,5357],{"class":212},[179,7509,7362],{"class":208},[179,7511,5305],{"class":212},[179,7513,7514],{"class":204},"reassign",[179,7516,5363],{"class":212},[179,7518,7423],{"class":208},[179,7520,440],{"class":212},[179,7522,5270],{"class":212},[179,7524,7435],{"class":208},[179,7526,5305],{"class":212},[179,7528,7529],{"class":208},"reviewer",[179,7531,7532],{"class":212},"))\n",[179,7534,7535,7537,7539,7541,7543,7545,7547,7549,7551,7553,7556,7558,7560],{"class":181,"line":5166},[179,7536,7493],{"class":212},[179,7538,7496],{"class":204},[179,7540,209],{"class":212},[179,7542,7501],{"class":232},[179,7544,223],{"class":212},[179,7546,3477],{"class":212},[179,7548,5357],{"class":212},[179,7550,7376],{"class":208},[179,7552,5305],{"class":212},[179,7554,7555],{"class":204},"resetDeadline",[179,7557,5363],{"class":212},[179,7559,7423],{"class":208},[179,7561,7532],{"class":212},[179,7563,7564,7566,7569,7571,7573,7575,7578,7580,7582,7584,7586,7588,7591,7593,7595,7597,7599,7601],{"class":181,"line":5172},[179,7565,7493],{"class":212},[179,7567,7568],{"class":204},"onFailure",[179,7570,209],{"class":212},[179,7572,7501],{"class":232},[179,7574,5363],{"class":212},[179,7576,7577],{"class":208},"step",[179,7579,3474],{"class":212},[179,7581,3477],{"class":212},[179,7583,5357],{"class":212},[179,7585,7390],{"class":208},[179,7587,5305],{"class":212},[179,7589,7590],{"class":204},"logFailure",[179,7592,5363],{"class":212},[179,7594,7423],{"class":208},[179,7596,440],{"class":212},[179,7598,5270],{"class":212},[179,7600,7577],{"class":208},[179,7602,7532],{"class":212},[179,7604,7605,7607,7610],{"class":181,"line":5178},[179,7606,7493],{"class":212},[179,7608,7609],{"class":204},"execute",[179,7611,5336],{"class":212},[179,7613,7614],{"class":181,"line":5184},[179,7615,5504],{"class":212},[179,7617,7618],{"class":181,"line":5189},[179,7619,494],{"class":212},[102,7621,7622],{},"The result was not smaller - the codebase grew by about 15% - but the number of production incidents dropped by 80%. The execution system made the implicit explicit, and explicit systems are debuggable.",[98,7624,7626],{"id":7625},"tradeoff-table-feature-first-vs-system-first","Tradeoff Table: Feature-First vs System-First",[755,7628,7629,7642],{},[758,7630,7631],{},[761,7632,7633,7636,7639],{},[764,7634,7635],{},"Dimension",[764,7637,7638],{},"Feature-First",[764,7640,7641],{},"System-First",[780,7643,7644,7655,7666,7677,7688,7699,7710,7721],{},[761,7645,7646,7649,7652],{},[785,7647,7648],{},"Time to first feature",[785,7650,7651],{},"Faster (days instead of weeks)",[785,7653,7654],{},"Slower initial investment",[761,7656,7657,7660,7663],{},[785,7658,7659],{},"Time to ten features",[785,7661,7662],{},"Slowing down as coupling grows",[785,7664,7665],{},"Accelerating as patterns reuse",[761,7667,7668,7671,7674],{},[785,7669,7670],{},"Edge case handling",[785,7672,7673],{},"Reactive, patch-by-patch",[785,7675,7676],{},"Proactive, defined in flow design",[761,7678,7679,7682,7685],{},[785,7680,7681],{},"Rework cost per change",[785,7683,7684],{},"High - changes ripple across scattered state",[785,7686,7687],{},"Low - changes are confined to task boundaries",[761,7689,7690,7693,7696],{},[785,7691,7692],{},"Onboarding new developers",[785,7694,7695],{},"Steep - implicit flows must be traced",[785,7697,7698],{},"Shallow - flow diagram is the documentation",[761,7700,7701,7704,7707],{},[785,7702,7703],{},"Failure recovery",[785,7705,7706],{},"Manual - operators must reconstruct state",[785,7708,7709],{},"Automatic or assisted - state machine knows position",[761,7711,7712,7715,7718],{},[785,7713,7714],{},"Testing strategy",[785,7716,7717],{},"End-to-end only, slow and brittle",[785,7719,7720],{},"Task-level unit tests + system integration tests",[761,7722,7723,7726,7729],{},[785,7724,7725],{},"Refactoring confidence",[785,7727,7728],{},"Low - afraid to touch tangled state",[785,7730,7731],{},"High - state transitions are contractually defined",[102,7733,7734],{},"The time-to-market tradeoff is real. System-first costs more upfront. In my experience, the breakeven point is around the fifth feature. Beyond that, system-first pulls ahead and the gap widens with every addition.",[98,7736,7738],{"id":7737},"how-this-applies-to-ai-systems","How This Applies to AI Systems",[102,7740,7741],{},"This principle becomes critical in AI systems. An AI agent without an execution system is a single prompt call - it generates a response and stops. Production AI systems need multi-step execution with state persistence, failure recovery, and deterministic observability.",[102,7743,7744],{},"The gem-orchestrator system in the Gem Team framework is an execution system first and an AI tool second. Its phase detection, agent routing, wave-based execution, and structured retry loops mirror the same three pillars:",[116,7746,7747,7752,7757],{},[119,7748,7749,7751],{},[122,7750,5030],{},": The phase pipeline - detect phase, route to specialist, execute wave, synthesize results",[119,7753,7754,7756],{},[122,7755,5036],{},": Persistent execution context that survives individual agent calls",[119,7758,7759,7761],{},[122,7760,7309],{},": Each agent handles one phase, one deliverable, one failure boundary",[102,7763,7764],{},"When I see teams building AI agents by chaining prompts together, I see the same pattern that caused the billing system to fail. They are building features - prompt templates, tool integrations, output parsers - without designing the execution system that sequences, governs, and recovers them.",[102,7766,7767],{},"An AI agent's execution system answers the same questions as any other system: what is the flow, what is the state, where are the failure boundaries. The fact that the executor is an LLM rather than a PHP controller does not change the architectural requirement.",[98,7769,7771],{"id":7770},"consulting-signal-sell-system-design-not-feature-delivery","Consulting Signal: Sell System Design, Not Feature Delivery",[102,7773,7774],{},"I changed my consulting practice because of this lesson. When a potential client asks me to build a feature, I ask about the execution system first. Not to upsell, but to assess whether the feature will survive its first edge case.",[102,7776,7777],{},"If the response is \"We need user authentication, so build login, registration, and password reset,\" that is feature-first thinking. The execution system question is: what happens when a social login fails to create a profile, or when a password reset races with an account deletion request, or when a session expires mid-checkout?",[102,7779,7780],{},"Selling system design means the deliverable is not a list of working features. It is an execution system that happens to deliver those features as a byproduct. Clients who understand this are the ones who come back for follow-on work because the foundation does not need rewriting every six months.",[98,7782,7784],{"id":7783},"closing","Closing",[102,7786,7787],{},"I still ship features. The difference is that I no longer design them first. I design the execution system - the flow, the state machine, the task boundaries - and the features emerge from that foundation.",[102,7789,7790],{},"The billing project that took three times longer taught me that the code is never the bottleneck. The bottleneck is invisible structure. Every edge case that surprises you in production was already visible in the execution flow you did not draw. Every tangled refactoring session was baked in the moment you decided to build features instead of systems.",[102,7792,7793],{},"Design the execution system first. Your future self, debugging at 2 AM after a failed deployment, will not thank you. But you will have fewer of those 2 AM sessions to begin with.",[1246,7795,7796],{},"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);}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 .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sfNiH, html code.shiki .sfNiH{--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}",{"title":174,"searchDepth":189,"depth":189,"links":7798},[7799,7800,7801,7806,7807,7808,7809,7810],{"id":5007,"depth":189,"text":5000},{"id":5019,"depth":189,"text":5020},{"id":5058,"depth":189,"text":5059,"children":7802},[7803,7804,7805],{"id":5062,"depth":16,"text":5063},{"id":5210,"depth":16,"text":5211},{"id":6231,"depth":16,"text":6232},{"id":7263,"depth":189,"text":7264},{"id":7625,"depth":189,"text":7626},{"id":7737,"depth":189,"text":7738},{"id":7770,"depth":189,"text":7771},{"id":7783,"depth":189,"text":7784},"2026-05-11","Feature-first development leads to technical debt. Designing execution systems first - flows, state, task decomposition - produces better software with less rework.",{"readingTime":7814},"11 min read","/blog/39-execution-systems-first-not-features",{"title":5000,"description":7812},"AI Systems Engineering","Building production-grade AI systems that scale beyond demos",{"src":7820,"mime":1287,"alt":7821,"width":1289,"height":7822},"/img/blog/39-execution-systems-first-not-features/banner.svg","Execution system architecture showing flow design, state management, and task decomposition layers",680,"blog/39-execution-systems-first-not-features",[7825,7826,7827,7828,1295,7829],"Architecture","Software Design","Execution Systems","Laravel","Development Practices","SXBdbszkV6tqDiQQzhPOkc2FqpppzH9VKOxMoDrItcw",{"id":7832,"title":7833,"abstract":92,"author":93,"authorUrl":92,"body":7834,"date":9532,"dateUpdated":9532,"description":9533,"excerpt":92,"extension":1278,"featured":624,"headline":92,"image":92,"meta":9534,"navigation":624,"ogImage":92,"path":9536,"seo":9537,"series":9538,"seriesDescription":9539,"seriesOrder":182,"socialImage":9540,"stem":9543,"tags":9544,"__hash__":9549},"blog/blog/20-core-web-vitals-2026-optimization.md","Core Web Vitals 2026: Performance Optimization Strategies",{"type":95,"value":7835,"toc":9508},[7836,7839,7842,7845,7849,7852,7856,7859,7864,7875,7880,7910,8044,8048,8051,8056,8070,8074,8100,8197,8201,8204,8209,8223,8227,8253,8395,8399,8403,8406,8578,8582,8585,8611,8800,8804,8807,8923,8927,8931,8934,9121,9125,9128,9373,9377,9380,9384,9398,9402,9434,9438,9455,9459,9462,9494,9496,9499,9502,9505],[98,7837,7833],{"id":7838},"core-web-vitals-2026-performance-optimization-strategies",[102,7840,7841],{},"Web performance has always been critical, but in 2026, it's more important than ever. Google's Core Web Vitals have evolved into comprehensive metrics that directly impact search rankings, user experience, and conversion rates. After optimizing dozens of websites for peak performance, I've developed a systematic approach to achieving perfect Core Web Vitals scores.",[102,7843,7844],{},"In this comprehensive guide, we'll explore the latest Core Web Vitals metrics, understand how they're measured, and implement proven optimization strategies that deliver real-world results. Whether you're building a Nuxt application, a React site, or any modern web application, these techniques will help you deliver lightning-fast experiences that users and search engines love.",[98,7846,7848],{"id":7847},"understanding-core-web-vitals-in-2026","Understanding Core Web Vitals in 2026",[102,7850,7851],{},"Google has refined Core Web Vitals over the years, and 2026 brings updated thresholds and new metrics that better reflect modern web experiences. The three core metrics remain, but with stricter targets:",[161,7853,7855],{"id":7854},"largest-contentful-paint-lcp-20s-target","Largest Contentful Paint (LCP) - 2.0s Target",[102,7857,7858],{},"LCP measures loading performance by tracking when the largest content element becomes visible. The 2026 target is now 2.0 seconds (down from 2.5s), reflecting user expectations for faster loading.",[102,7860,7861],{},[122,7862,7863],{},"What counts as LCP:",[116,7865,7866,7869,7872],{},[119,7867,7868],{},"Images and video thumbnails",[119,7870,7871],{},"Text blocks (headings, paragraphs)",[119,7873,7874],{},"Background images with significant content",[102,7876,7877],{},[122,7878,7879],{},"Optimization strategies:",[1200,7881,7882,7888,7898,7904],{},[119,7883,7884,7887],{},[122,7885,7886],{},"Optimize Images",": Use modern formats (AVIF, WebP), implement responsive images, and lazy-load off-screen content",[119,7889,7890,7893,7894,7897],{},[122,7891,7892],{},"Preload Critical Resources",": Use ",[176,7895,7896],{},""," for LCP elements",[119,7899,7900,7903],{},[122,7901,7902],{},"Implement Streaming SSR",": Send HTML in chunks to start rendering sooner",[119,7905,7906,7909],{},[122,7907,7908],{},"Use Edge Caching",": Serve content from edge locations closer to users",[169,7911,7913],{"className":171,"code":7912,"language":173,"meta":174,"style":174},"// Nuxt 4: Preload LCP image\nuseHead({\n link: [\n {\n rel: \"preload\",\n as: \"image\",\n href: \"/img/hero-banner.avif\",\n imagesrcset:\n \"/img/hero-banner-480.avif 480w, /img/hero-banner-768.avif 768w\",\n imagesizes: \"100vw\",\n },\n ],\n})\n",[176,7914,7915,7920,7929,7939,7943,7959,7975,7991,7999,8011,8027,8031,8038],{"__ignoreMap":174},[179,7916,7917],{"class":181,"line":182},[179,7918,7919],{"class":185},"// Nuxt 4: Preload LCP image\n",[179,7921,7922,7925,7927],{"class":181,"line":189},[179,7923,7924],{"class":204},"useHead",[179,7926,209],{"class":208},[179,7928,213],{"class":212},[179,7930,7931,7934,7936],{"class":181,"line":16},[179,7932,7933],{"class":219}," link",[179,7935,448],{"class":212},[179,7937,7938],{"class":208}," [\n",[179,7940,7941],{"class":181,"line":216},[179,7942,5290],{"class":212},[179,7944,7945,7948,7950,7952,7955,7957],{"class":181,"line":229},[179,7946,7947],{"class":219}," rel",[179,7949,448],{"class":212},[179,7951,1071],{"class":212},[179,7953,7954],{"class":256},"preload",[179,7956,253],{"class":212},[179,7958,2827],{"class":212},[179,7960,7961,7964,7966,7968,7971,7973],{"class":181,"line":265},[179,7962,7963],{"class":219}," as",[179,7965,448],{"class":212},[179,7967,1071],{"class":212},[179,7969,7970],{"class":256},"image",[179,7972,253],{"class":212},[179,7974,2827],{"class":212},[179,7976,7977,7980,7982,7984,7987,7989],{"class":181,"line":278},[179,7978,7979],{"class":219}," href",[179,7981,448],{"class":212},[179,7983,1071],{"class":212},[179,7985,7986],{"class":256},"/img/hero-banner.avif",[179,7988,253],{"class":212},[179,7990,2827],{"class":212},[179,7992,7993,7996],{"class":181,"line":284},[179,7994,7995],{"class":219}," imagesrcset",[179,7997,7998],{"class":212},":\n",[179,8000,8001,8004,8007,8009],{"class":181,"line":2451},[179,8002,8003],{"class":212}," \"",[179,8005,8006],{"class":256},"/img/hero-banner-480.avif 480w, /img/hero-banner-768.avif 768w",[179,8008,253],{"class":212},[179,8010,2827],{"class":212},[179,8012,8013,8016,8018,8020,8023,8025],{"class":181,"line":2461},[179,8014,8015],{"class":219}," imagesizes",[179,8017,448],{"class":212},[179,8019,1071],{"class":212},[179,8021,8022],{"class":256},"100vw",[179,8024,253],{"class":212},[179,8026,2827],{"class":212},[179,8028,8029],{"class":181,"line":2985},[179,8030,2866],{"class":212},[179,8032,8033,8036],{"class":181,"line":2997},[179,8034,8035],{"class":208}," ]",[179,8037,2827],{"class":212},[179,8039,8040,8042],{"class":181,"line":29},[179,8041,287],{"class":212},[179,8043,262],{"class":208},[161,8045,8047],{"id":8046},"interaction-to-next-paint-inp-150ms-target","Interaction to Next Paint (INP) - 150ms Target",[102,8049,8050],{},"INP replaced First Input Delay (FID) in 2024 and has become the primary responsiveness metric. It measures the latency of all user interactions during a page visit, not just the first one. The 2026 target is 150ms.",[102,8052,8053],{},[122,8054,8055],{},"What INP measures:",[116,8057,8058,8061,8064,8067],{},[119,8059,8060],{},"Click events on buttons and links",[119,8062,8063],{},"Keyboard input in form fields",[119,8065,8066],{},"Touch interactions on mobile devices",[119,8068,8069],{},"Scroll interactions",[102,8071,8072],{},[122,8073,7879],{},[1200,8075,8076,8082,8088,8094],{},[119,8077,8078,8081],{},[122,8079,8080],{},"Minimize JavaScript Execution",": Break up long tasks, use web workers for heavy computation",[119,8083,8084,8087],{},[122,8085,8086],{},"Optimize Event Handlers",": Debounce scroll events, use passive event listeners",[119,8089,8090,8093],{},[122,8091,8092],{},"Reduce Third-Party Impact",": Load analytics and ads asynchronously",[119,8095,8096,8099],{},[122,8097,8098],{},"Use View Transitions API",": Smooth page transitions without blocking interactions",[169,8101,8103],{"className":171,"code":8102,"language":173,"meta":174,"style":174},"// Optimize event handlers with passive listeners\nonMounted(() => {\n const element = document.querySelector(\".scroll-container\")\n element?.addEventListener(\"scroll\", handleScroll, { passive: true })\n})\n",[176,8104,8105,8110,8123,8151,8191],{"__ignoreMap":174},[179,8106,8107],{"class":181,"line":182},[179,8108,8109],{"class":185},"// Optimize event handlers with passive listeners\n",[179,8111,8112,8115,8117,8119,8121],{"class":181,"line":189},[179,8113,8114],{"class":204},"onMounted",[179,8116,209],{"class":208},[179,8118,223],{"class":212},[179,8120,3477],{"class":232},[179,8122,226],{"class":212},[179,8124,8125,8127,8130,8132,8135,8137,8140,8142,8144,8147,8149],{"class":181,"line":16},[179,8126,417],{"class":232},[179,8128,8129],{"class":208}," element",[179,8131,245],{"class":212},[179,8133,8134],{"class":208}," document",[179,8136,716],{"class":212},[179,8138,8139],{"class":204},"querySelector",[179,8141,209],{"class":219},[179,8143,253],{"class":212},[179,8145,8146],{"class":256},".scroll-container",[179,8148,253],{"class":212},[179,8150,262],{"class":219},[179,8152,8153,8156,8159,8162,8164,8166,8169,8171,8173,8176,8178,8180,8183,8185,8187,8189],{"class":181,"line":216},[179,8154,8155],{"class":208}," element",[179,8157,8158],{"class":212},"?.",[179,8160,8161],{"class":204},"addEventListener",[179,8163,209],{"class":219},[179,8165,253],{"class":212},[179,8167,8168],{"class":256},"scroll",[179,8170,253],{"class":212},[179,8172,440],{"class":212},[179,8174,8175],{"class":208}," handleScroll",[179,8177,440],{"class":212},[179,8179,236],{"class":212},[179,8181,8182],{"class":219}," passive",[179,8184,448],{"class":212},[179,8186,2980],{"class":2979},[179,8188,242],{"class":212},[179,8190,262],{"class":219},[179,8192,8193,8195],{"class":181,"line":229},[179,8194,287],{"class":212},[179,8196,262],{"class":208},[161,8198,8200],{"id":8199},"cumulative-layout-shift-cls-005-target","Cumulative Layout Shift (CLS) - 0.05 Target",[102,8202,8203],{},"CLS measures visual stability by tracking unexpected layout shifts. The target remains 0.05, but measurement has become more sophisticated, better accounting for user-initiated changes.",[102,8205,8206],{},[122,8207,8208],{},"Common causes of layout shift:",[116,8210,8211,8214,8217,8220],{},[119,8212,8213],{},"Images without dimensions",[119,8215,8216],{},"Web fonts causing FOIT/FOUT",[119,8218,8219],{},"Dynamically injected content",[119,8221,8222],{},"Late-loading ads and embeds",[102,8224,8225],{},[122,8226,7879],{},[1200,8228,8229,8235,8241,8247],{},[119,8230,8231,8234],{},[122,8232,8233],{},"Set Explicit Dimensions",": Always specify width and height for images and videos",[119,8236,8237,8240],{},[122,8238,8239],{},"Reserve Space for Dynamic Content",": Use CSS aspect-ratio and min-height",[119,8242,8243,8246],{},[122,8244,8245],{},"Optimize Font Loading",": Use font-display: optional or swap with size-adjust",[119,8248,8249,8252],{},[122,8250,8251],{},"Avoid Inserting Content Above Existing Content",": Load ads and embeds in reserved spaces",[169,8254,8258],{"className":8255,"code":8256,"language":8257,"meta":174,"style":174},"language-css shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","/* Reserve space for images */\n.img-container {\n aspect-ratio: 16 / 9;\n background: #f0f0f0;\n}\n\n/* Optimize font loading */\n@font-face {\n font-family: \"Inter\";\n src: url(\"/fonts/inter.woff2\") format(\"woff2\");\n font-display: swap;\n}\n","css",[176,8259,8260,8265,8274,8293,8308,8312,8316,8321,8328,8344,8379,8391],{"__ignoreMap":174},[179,8261,8262],{"class":181,"line":182},[179,8263,8264],{"class":185},"/* Reserve space for images */\n",[179,8266,8267,8269,8272],{"class":181,"line":189},[179,8268,716],{"class":212},[179,8270,8271],{"class":471},"img-container",[179,8273,226],{"class":212},[179,8275,8276,8280,8282,8285,8288,8291],{"class":181,"line":16},[179,8277,8279],{"class":8278},"sqsOY"," aspect-ratio",[179,8281,448],{"class":212},[179,8283,8284],{"class":3873}," 16",[179,8286,8287],{"class":208}," / ",[179,8289,8290],{"class":3873},"9",[179,8292,5322],{"class":212},[179,8294,8295,8298,8300,8303,8306],{"class":181,"line":216},[179,8296,8297],{"class":8278}," background",[179,8299,448],{"class":212},[179,8301,8302],{"class":212}," #",[179,8304,8305],{"class":208},"f0f0f0",[179,8307,5322],{"class":212},[179,8309,8310],{"class":181,"line":229},[179,8311,494],{"class":212},[179,8313,8314],{"class":181,"line":265},[179,8315,625],{"emptyLinePlaceholder":624},[179,8317,8318],{"class":181,"line":278},[179,8319,8320],{"class":185},"/* Optimize font loading */\n",[179,8322,8323,8326],{"class":181,"line":284},[179,8324,8325],{"class":197},"@font-face",[179,8327,226],{"class":212},[179,8329,8330,8333,8335,8337,8340,8342],{"class":181,"line":2451},[179,8331,8332],{"class":8278}," font-family",[179,8334,448],{"class":212},[179,8336,1071],{"class":212},[179,8338,8339],{"class":256},"Inter",[179,8341,253],{"class":212},[179,8343,5322],{"class":212},[179,8345,8346,8349,8351,8354,8356,8358,8361,8363,8365,8368,8370,8372,8375,8377],{"class":181,"line":2461},[179,8347,8348],{"class":8278}," src",[179,8350,448],{"class":212},[179,8352,8353],{"class":204}," url",[179,8355,209],{"class":212},[179,8357,253],{"class":212},[179,8359,8360],{"class":256},"/fonts/inter.woff2",[179,8362,253],{"class":212},[179,8364,3474],{"class":212},[179,8366,8367],{"class":204}," format",[179,8369,209],{"class":212},[179,8371,253],{"class":212},[179,8373,8374],{"class":256},"woff2",[179,8376,253],{"class":212},[179,8378,5368],{"class":212},[179,8380,8381,8384,8386,8389],{"class":181,"line":2985},[179,8382,8383],{"class":8278}," font-display",[179,8385,448],{"class":212},[179,8387,8388],{"class":208}," swap",[179,8390,5322],{"class":212},[179,8392,8393],{"class":181,"line":2997},[179,8394,494],{"class":212},[98,8396,8398],{"id":8397},"advanced-optimization-techniques","Advanced Optimization Techniques",[161,8400,8402],{"id":8401},"implementing-speculation-rules","Implementing Speculation Rules",[102,8404,8405],{},"Chrome's Speculation Rules API allows you to prefetch or prerender pages based on user behavior predictions. This can dramatically improve perceived performance for navigation.",[169,8407,8409],{"className":171,"code":8408,"language":173,"meta":174,"style":174},"// Nuxt 4: Enable speculation rules\nuseHead({\n script: [\n {\n type: \"speculationrules\",\n textContent: JSON.stringify({\n prefetch: [\n {\n source: \"document\",\n where: { href_matches: \"/blog/*\" },\n eagerness: \"moderate\",\n },\n ],\n }),\n },\n ],\n})\n",[176,8410,8411,8416,8424,8433,8437,8453,8472,8481,8486,8501,8525,8541,8546,8553,8562,8566,8572],{"__ignoreMap":174},[179,8412,8413],{"class":181,"line":182},[179,8414,8415],{"class":185},"// Nuxt 4: Enable speculation rules\n",[179,8417,8418,8420,8422],{"class":181,"line":189},[179,8419,7924],{"class":204},[179,8421,209],{"class":208},[179,8423,213],{"class":212},[179,8425,8426,8429,8431],{"class":181,"line":16},[179,8427,8428],{"class":219}," script",[179,8430,448],{"class":212},[179,8432,7938],{"class":208},[179,8434,8435],{"class":181,"line":216},[179,8436,5290],{"class":212},[179,8438,8439,8442,8444,8446,8449,8451],{"class":181,"line":229},[179,8440,8441],{"class":219}," type",[179,8443,448],{"class":212},[179,8445,1071],{"class":212},[179,8447,8448],{"class":256},"speculationrules",[179,8450,253],{"class":212},[179,8452,2827],{"class":212},[179,8454,8455,8458,8460,8463,8465,8468,8470],{"class":181,"line":265},[179,8456,8457],{"class":219}," textContent",[179,8459,448],{"class":212},[179,8461,8462],{"class":208}," JSON",[179,8464,716],{"class":212},[179,8466,8467],{"class":204},"stringify",[179,8469,209],{"class":208},[179,8471,213],{"class":212},[179,8473,8474,8477,8479],{"class":181,"line":278},[179,8475,8476],{"class":219}," prefetch",[179,8478,448],{"class":212},[179,8480,7938],{"class":208},[179,8482,8483],{"class":181,"line":284},[179,8484,8485],{"class":212}," {\n",[179,8487,8488,8491,8493,8495,8497,8499],{"class":181,"line":2451},[179,8489,8490],{"class":219}," source",[179,8492,448],{"class":212},[179,8494,1071],{"class":212},[179,8496,7423],{"class":256},[179,8498,253],{"class":212},[179,8500,2827],{"class":212},[179,8502,8503,8506,8508,8510,8513,8515,8517,8520,8522],{"class":181,"line":2461},[179,8504,8505],{"class":219}," where",[179,8507,448],{"class":212},[179,8509,236],{"class":212},[179,8511,8512],{"class":219}," href_matches",[179,8514,448],{"class":212},[179,8516,1071],{"class":212},[179,8518,8519],{"class":256},"/blog/*",[179,8521,253],{"class":212},[179,8523,8524],{"class":212}," },\n",[179,8526,8527,8530,8532,8534,8537,8539],{"class":181,"line":2985},[179,8528,8529],{"class":219}," eagerness",[179,8531,448],{"class":212},[179,8533,1071],{"class":212},[179,8535,8536],{"class":256},"moderate",[179,8538,253],{"class":212},[179,8540,2827],{"class":212},[179,8542,8543],{"class":181,"line":2997},[179,8544,8545],{"class":212}," },\n",[179,8547,8548,8551],{"class":181,"line":29},[179,8549,8550],{"class":208}," ]",[179,8552,2827],{"class":212},[179,8554,8555,8558,8560],{"class":181,"line":5143},[179,8556,8557],{"class":212}," }",[179,8559,3474],{"class":208},[179,8561,2827],{"class":212},[179,8563,8564],{"class":181,"line":5149},[179,8565,2866],{"class":212},[179,8567,8568,8570],{"class":181,"line":5155},[179,8569,8035],{"class":208},[179,8571,2827],{"class":212},[179,8573,8574,8576],{"class":181,"line":5160},[179,8575,287],{"class":212},[179,8577,262],{"class":208},[161,8579,8581],{"id":8580},"optimizing-third-party-scripts","Optimizing Third-Party Scripts",[102,8583,8584],{},"Third-party scripts are often the biggest performance bottleneck. Implement these strategies:",[1200,8586,8587,8593,8599,8605],{},[119,8588,8589,8592],{},[122,8590,8591],{},"Load Non-Critical Scripts After Interaction",": Delay analytics until user engages",[119,8594,8595,8598],{},[122,8596,8597],{},"Use Partytown",": Run third-party scripts in a web worker",[119,8600,8601,8604],{},[122,8602,8603],{},"Implement Resource Hints",": Preconnect to third-party domains",[119,8606,8607,8610],{},[122,8608,8609],{},"Monitor Third-Party Impact",": Track performance impact of each script",[169,8612,8614],{"className":171,"code":8613,"language":173,"meta":174,"style":174},"// Load analytics after user interaction\nlet analyticsLoaded = false\n\nfunction loadAnalytics() {\n if (analyticsLoaded) return\n analyticsLoaded = true\n\n // Dynamically import analytics\n import(\"./analytics\").then(({ init }) => init())\n}\n\n// Load on first user interaction\ndocument.addEventListener(\"click\", loadAnalytics, { once: true })\ndocument.addEventListener(\"scroll\", loadAnalytics, { once: true })\n",[176,8615,8616,8621,8634,8638,8649,8664,8673,8677,8682,8717,8721,8725,8730,8766],{"__ignoreMap":174},[179,8617,8618],{"class":181,"line":182},[179,8619,8620],{"class":185},"// Load analytics after user interaction\n",[179,8622,8623,8626,8629,8631],{"class":181,"line":189},[179,8624,8625],{"class":232},"let",[179,8627,8628],{"class":208}," analyticsLoaded ",[179,8630,3831],{"class":212},[179,8632,8633],{"class":2979}," false\n",[179,8635,8636],{"class":181,"line":16},[179,8637,625],{"emptyLinePlaceholder":624},[179,8639,8640,8642,8645,8647],{"class":181,"line":216},[179,8641,5963],{"class":232},[179,8643,8644],{"class":204}," loadAnalytics",[179,8646,223],{"class":212},[179,8648,226],{"class":212},[179,8650,8651,8654,8656,8659,8661],{"class":181,"line":229},[179,8652,8653],{"class":197}," if",[179,8655,1155],{"class":219},[179,8657,8658],{"class":208},"analyticsLoaded",[179,8660,1161],{"class":219},[179,8662,8663],{"class":197},"return\n",[179,8665,8666,8669,8671],{"class":181,"line":265},[179,8667,8668],{"class":208}," analyticsLoaded",[179,8670,245],{"class":212},[179,8672,4013],{"class":2979},[179,8674,8675],{"class":181,"line":278},[179,8676,625],{"emptyLinePlaceholder":624},[179,8678,8679],{"class":181,"line":284},[179,8680,8681],{"class":185}," // Dynamically import analytics\n",[179,8683,8684,8687,8689,8691,8694,8696,8698,8700,8702,8704,8706,8708,8710,8712,8714],{"class":181,"line":2451},[179,8685,8686],{"class":212}," import",[179,8688,209],{"class":219},[179,8690,253],{"class":212},[179,8692,8693],{"class":256},"./analytics",[179,8695,253],{"class":212},[179,8697,3474],{"class":219},[179,8699,716],{"class":212},[179,8701,7496],{"class":204},[179,8703,209],{"class":219},[179,8705,691],{"class":212},[179,8707,919],{"class":694},[179,8709,698],{"class":212},[179,8711,3477],{"class":232},[179,8713,919],{"class":204},[179,8715,8716],{"class":219},"())\n",[179,8718,8719],{"class":181,"line":2461},[179,8720,494],{"class":212},[179,8722,8723],{"class":181,"line":2985},[179,8724,625],{"emptyLinePlaceholder":624},[179,8726,8727],{"class":181,"line":2997},[179,8728,8729],{"class":185},"// Load on first user interaction\n",[179,8731,8732,8734,8736,8738,8740,8742,8745,8747,8749,8751,8753,8755,8758,8760,8762,8764],{"class":181,"line":29},[179,8733,7423],{"class":208},[179,8735,716],{"class":212},[179,8737,8161],{"class":204},[179,8739,209],{"class":208},[179,8741,253],{"class":212},[179,8743,8744],{"class":256},"click",[179,8746,253],{"class":212},[179,8748,440],{"class":212},[179,8750,8644],{"class":208},[179,8752,440],{"class":212},[179,8754,236],{"class":212},[179,8756,8757],{"class":219}," once",[179,8759,448],{"class":212},[179,8761,2980],{"class":2979},[179,8763,242],{"class":212},[179,8765,262],{"class":208},[179,8767,8768,8770,8772,8774,8776,8778,8780,8782,8784,8786,8788,8790,8792,8794,8796,8798],{"class":181,"line":5143},[179,8769,7423],{"class":208},[179,8771,716],{"class":212},[179,8773,8161],{"class":204},[179,8775,209],{"class":208},[179,8777,253],{"class":212},[179,8779,8168],{"class":256},[179,8781,253],{"class":212},[179,8783,440],{"class":212},[179,8785,8644],{"class":208},[179,8787,440],{"class":212},[179,8789,236],{"class":212},[179,8791,8757],{"class":219},[179,8793,448],{"class":212},[179,8795,2980],{"class":2979},[179,8797,242],{"class":212},[179,8799,262],{"class":208},[161,8801,8803],{"id":8802},"implementing-progressive-hydration","Implementing Progressive Hydration",[102,8805,8806],{},"Full hydration of complex SPAs can block interactivity. Progressive hydration loads and hydrates components as they become visible or needed.",[169,8808,8810],{"className":171,"code":8809,"language":173,"meta":174,"style":174},"// Nuxt 4: Lazy hydrate components\n\n",[176,8811,8812,8817,8826,8836,8847,8856,8860,8869,8878,8887,8897,8906,8914],{"__ignoreMap":174},[179,8813,8814],{"class":181,"line":182},[179,8815,8816],{"class":185},"// Nuxt 4: Lazy hydrate components\n",[179,8818,8819,8821,8824],{"class":181,"line":189},[179,8820,6604],{"class":208},[179,8822,8823],{"class":471},"template",[179,8825,489],{"class":208},[179,8827,8828,8831,8834],{"class":181,"line":16},[179,8829,8830],{"class":208}," <",[179,8832,8833],{"class":471},"ClientOnly",[179,8835,489],{"class":208},[179,8837,8838,8841,8844],{"class":181,"line":216},[179,8839,8840],{"class":212}," <",[179,8842,8843],{"class":208},"LazyHeavyComponent ",[179,8845,8846],{"class":212},"/>\n",[179,8848,8849,8852,8854],{"class":181,"line":229},[179,8850,8851],{"class":212}," {\n // Send to analytics endpoint\n sendToAnalytics(\"LCP\", metric)\n})\n\nonINP((metric) => {\n sendToAnalytics(\"INP\", metric)\n})\n\nonCLS((metric) => {\n sendToAnalytics(\"CLS\", metric)\n})\n",[176,8938,8939,8944,8976,8980,8998,9003,9023,9029,9033,9050,9069,9075,9079,9096,9115],{"__ignoreMap":174},[179,8940,8941],{"class":181,"line":182},[179,8942,8943],{"class":185},"// Track Core Web Vitals with web-vitals library\n",[179,8945,8946,8949,8951,8954,8956,8959,8961,8964,8966,8969,8971,8974],{"class":181,"line":189},[179,8947,8948],{"class":197},"import",[179,8950,236],{"class":212},[179,8952,8953],{"class":208}," onLCP",[179,8955,440],{"class":212},[179,8957,8958],{"class":208}," onINP",[179,8960,440],{"class":212},[179,8962,8963],{"class":208}," onCLS",[179,8965,242],{"class":212},[179,8967,8968],{"class":197}," from",[179,8970,1071],{"class":212},[179,8972,8973],{"class":256},"web-vitals",[179,8975,2754],{"class":212},[179,8977,8978],{"class":181,"line":16},[179,8979,625],{"emptyLinePlaceholder":624},[179,8981,8982,8985,8987,8989,8992,8994,8996],{"class":181,"line":216},[179,8983,8984],{"class":204},"onLCP",[179,8986,209],{"class":208},[179,8988,209],{"class":212},[179,8990,8991],{"class":694},"metric",[179,8993,3474],{"class":212},[179,8995,3477],{"class":232},[179,8997,226],{"class":212},[179,8999,9000],{"class":181,"line":229},[179,9001,9002],{"class":185}," // Send to analytics endpoint\n",[179,9004,9005,9008,9010,9012,9014,9016,9018,9021],{"class":181,"line":265},[179,9006,9007],{"class":204}," sendToAnalytics",[179,9009,209],{"class":219},[179,9011,253],{"class":212},[179,9013,775],{"class":256},[179,9015,253],{"class":212},[179,9017,440],{"class":212},[179,9019,9020],{"class":208}," metric",[179,9022,262],{"class":219},[179,9024,9025,9027],{"class":181,"line":278},[179,9026,287],{"class":212},[179,9028,262],{"class":208},[179,9030,9031],{"class":181,"line":284},[179,9032,625],{"emptyLinePlaceholder":624},[179,9034,9035,9038,9040,9042,9044,9046,9048],{"class":181,"line":2451},[179,9036,9037],{"class":204},"onINP",[179,9039,209],{"class":208},[179,9041,209],{"class":212},[179,9043,8991],{"class":694},[179,9045,3474],{"class":212},[179,9047,3477],{"class":232},[179,9049,226],{"class":212},[179,9051,9052,9054,9056,9058,9061,9063,9065,9067],{"class":181,"line":2461},[179,9053,9007],{"class":204},[179,9055,209],{"class":219},[179,9057,253],{"class":212},[179,9059,9060],{"class":256},"INP",[179,9062,253],{"class":212},[179,9064,440],{"class":212},[179,9066,9020],{"class":208},[179,9068,262],{"class":219},[179,9070,9071,9073],{"class":181,"line":2985},[179,9072,287],{"class":212},[179,9074,262],{"class":208},[179,9076,9077],{"class":181,"line":2997},[179,9078,625],{"emptyLinePlaceholder":624},[179,9080,9081,9084,9086,9088,9090,9092,9094],{"class":181,"line":29},[179,9082,9083],{"class":204},"onCLS",[179,9085,209],{"class":208},[179,9087,209],{"class":212},[179,9089,8991],{"class":694},[179,9091,3474],{"class":212},[179,9093,3477],{"class":232},[179,9095,226],{"class":212},[179,9097,9098,9100,9102,9104,9107,9109,9111,9113],{"class":181,"line":5143},[179,9099,9007],{"class":204},[179,9101,209],{"class":219},[179,9103,253],{"class":212},[179,9105,9106],{"class":256},"CLS",[179,9108,253],{"class":212},[179,9110,440],{"class":212},[179,9112,9020],{"class":208},[179,9114,262],{"class":219},[179,9116,9117,9119],{"class":181,"line":5149},[179,9118,287],{"class":212},[179,9120,262],{"class":208},[161,9122,9124],{"id":9123},"performance-budgets","Performance Budgets",[102,9126,9127],{},"Set performance budgets in your CI/CD pipeline to catch regressions before they reach production.",[169,9129,9131],{"className":2712,"code":9130,"language":2714,"meta":174,"style":174},"{\n \"performance\": {\n \"budgets\": [\n {\n \"path\": \"/*\",\n \"resourceSizes\": [\n { \"resourceType\": \"script\", \"budget\": 150 },\n { \"resourceType\": \"image\", \"budget\": 200 },\n { \"resourceType\": \"total\", \"budget\": 500 }\n ],\n \"resourceCounts\": [{ \"resourceType\": \"third-party\", \"budget\": 5 }]\n }\n ]\n }\n}\n",[176,9132,9133,9137,9150,9163,9168,9188,9201,9238,9271,9305,9310,9355,9360,9365,9369],{"__ignoreMap":174},[179,9134,9135],{"class":181,"line":182},[179,9136,213],{"class":212},[179,9138,9139,9141,9144,9146,9148],{"class":181,"line":189},[179,9140,2725],{"class":212},[179,9142,9143],{"class":232},"performance",[179,9145,253],{"class":212},[179,9147,448],{"class":212},[179,9149,226],{"class":212},[179,9151,9152,9154,9157,9159,9161],{"class":181,"line":16},[179,9153,2739],{"class":212},[179,9155,9156],{"class":471},"budgets",[179,9158,253],{"class":212},[179,9160,448],{"class":212},[179,9162,7938],{"class":212},[179,9164,9165],{"class":181,"line":216},[179,9166,9167],{"class":212}," {\n",[179,9169,9170,9172,9175,9177,9179,9181,9184,9186],{"class":181,"line":229},[179,9171,8003],{"class":212},[179,9173,9174],{"class":3873},"path",[179,9176,253],{"class":212},[179,9178,448],{"class":212},[179,9180,1071],{"class":212},[179,9182,9183],{"class":256},"/*",[179,9185,253],{"class":212},[179,9187,2827],{"class":212},[179,9189,9190,9192,9195,9197,9199],{"class":181,"line":265},[179,9191,8003],{"class":212},[179,9193,9194],{"class":3873},"resourceSizes",[179,9196,253],{"class":212},[179,9198,448],{"class":212},[179,9200,7938],{"class":212},[179,9202,9203,9206,9208,9211,9213,9215,9217,9220,9222,9224,9226,9229,9231,9233,9236],{"class":181,"line":278},[179,9204,9205],{"class":212}," {",[179,9207,1071],{"class":212},[179,9209,9210],{"class":219},"resourceType",[179,9212,253],{"class":212},[179,9214,448],{"class":212},[179,9216,1071],{"class":212},[179,9218,9219],{"class":256},"script",[179,9221,253],{"class":212},[179,9223,440],{"class":212},[179,9225,1071],{"class":212},[179,9227,9228],{"class":219},"budget",[179,9230,253],{"class":212},[179,9232,448],{"class":212},[179,9234,9235],{"class":3873}," 150",[179,9237,8524],{"class":212},[179,9239,9240,9242,9244,9246,9248,9250,9252,9254,9256,9258,9260,9262,9264,9266,9269],{"class":181,"line":284},[179,9241,9205],{"class":212},[179,9243,1071],{"class":212},[179,9245,9210],{"class":219},[179,9247,253],{"class":212},[179,9249,448],{"class":212},[179,9251,1071],{"class":212},[179,9253,7970],{"class":256},[179,9255,253],{"class":212},[179,9257,440],{"class":212},[179,9259,1071],{"class":212},[179,9261,9228],{"class":219},[179,9263,253],{"class":212},[179,9265,448],{"class":212},[179,9267,9268],{"class":3873}," 200",[179,9270,8524],{"class":212},[179,9272,9273,9275,9277,9279,9281,9283,9285,9288,9290,9292,9294,9296,9298,9300,9303],{"class":181,"line":2451},[179,9274,9205],{"class":212},[179,9276,1071],{"class":212},[179,9278,9210],{"class":219},[179,9280,253],{"class":212},[179,9282,448],{"class":212},[179,9284,1071],{"class":212},[179,9286,9287],{"class":256},"total",[179,9289,253],{"class":212},[179,9291,440],{"class":212},[179,9293,1071],{"class":212},[179,9295,9228],{"class":219},[179,9297,253],{"class":212},[179,9299,448],{"class":212},[179,9301,9302],{"class":3873}," 500",[179,9304,275],{"class":212},[179,9306,9307],{"class":181,"line":2461},[179,9308,9309],{"class":212}," ],\n",[179,9311,9312,9314,9317,9319,9321,9324,9326,9328,9330,9332,9334,9337,9339,9341,9343,9345,9347,9349,9352],{"class":181,"line":2985},[179,9313,8003],{"class":212},[179,9315,9316],{"class":3873},"resourceCounts",[179,9318,253],{"class":212},[179,9320,448],{"class":212},[179,9322,9323],{"class":212}," [{",[179,9325,1071],{"class":212},[179,9327,9210],{"class":219},[179,9329,253],{"class":212},[179,9331,448],{"class":212},[179,9333,1071],{"class":212},[179,9335,9336],{"class":256},"third-party",[179,9338,253],{"class":212},[179,9340,440],{"class":212},[179,9342,1071],{"class":212},[179,9344,9228],{"class":219},[179,9346,253],{"class":212},[179,9348,448],{"class":212},[179,9350,9351],{"class":3873}," 5",[179,9353,9354],{"class":212}," }]\n",[179,9356,9357],{"class":181,"line":2997},[179,9358,9359],{"class":212}," }\n",[179,9361,9362],{"class":181,"line":29},[179,9363,9364],{"class":212}," ]\n",[179,9366,9367],{"class":181,"line":5143},[179,9368,1186],{"class":212},[179,9370,9371],{"class":181,"line":5149},[179,9372,494],{"class":212},[98,9374,9376],{"id":9375},"case-study-e-commerce-performance-optimization","Case Study: E-commerce Performance Optimization",[102,9378,9379],{},"Let me share a real-world example of Core Web Vitals optimization for an e-commerce platform.",[161,9381,9383],{"id":9382},"initial-state","Initial State",[116,9385,9386,9389,9392,9395],{},[119,9387,9388],{},"LCP: 4.2s (Poor)",[119,9390,9391],{},"INP: 280ms (Needs Improvement)",[119,9393,9394],{},"CLS: 0.18 (Needs Improvement)",[119,9396,9397],{},"Mobile conversion rate: 1.8%",[161,9399,9401],{"id":9400},"optimization-steps","Optimization Steps",[1200,9403,9404,9410,9416,9422,9428],{},[119,9405,9406,9409],{},[122,9407,9408],{},"Image Optimization",": Converted all product images to AVIF, implemented lazy loading",[119,9411,9412,9415],{},[122,9413,9414],{},"Code Splitting",": Split vendor bundles, lazy-loaded non-critical components",[119,9417,9418,9421],{},[122,9419,9420],{},"Edge Caching",": Implemented ISR for product pages, edge caching for static assets",[119,9423,9424,9427],{},[122,9425,9426],{},"Font Optimization",": Switched to system fonts for body text, optimized heading fonts",[119,9429,9430,9433],{},[122,9431,9432],{},"Third-Party Audit",": Removed unused analytics scripts, deferred ad loading",[161,9435,9437],{"id":9436},"results-after-3-months","Results After 3 Months",[116,9439,9440,9443,9446,9449,9452],{},[119,9441,9442],{},"LCP: 1.8s (Good) - 57% improvement",[119,9444,9445],{},"INP: 120ms (Good) - 57% improvement",[119,9447,9448],{},"CLS: 0.03 (Good) - 83% improvement",[119,9450,9451],{},"Mobile conversion rate: 2.6% - 44% increase",[119,9453,9454],{},"Organic traffic: +35%",[98,9456,9458],{"id":9457},"tools-and-resources","Tools and Resources",[102,9460,9461],{},"Essential tools for Core Web Vitals optimization:",[116,9463,9464,9470,9476,9482,9488],{},[119,9465,9466,9469],{},[122,9467,9468],{},"PageSpeed Insights",": Lab and field data for any URL",[119,9471,9472,9475],{},[122,9473,9474],{},"Chrome DevTools",": Performance panel, Lighthouse audits",[119,9477,9478,9481],{},[122,9479,9480],{},"WebPageTest",": Advanced performance testing with custom configurations",[119,9483,9484,9487],{},[122,9485,9486],{},"CrUX Dashboard",": Real user data in Google Data Studio",[119,9489,9490,9493],{},[122,9491,9492],{},"SpeedCurve",": Continuous performance monitoring",[98,9495,1229],{"id":1228},[102,9497,9498],{},"Core Web Vitals are no longer optional—they're essential for search visibility, user experience, and business success. The optimization strategies outlined in this guide have proven effective across dozens of projects, delivering measurable improvements in performance metrics and business outcomes.",[102,9500,9501],{},"Start by measuring your current performance, identify the biggest opportunities, and implement optimizations incrementally. Focus on user-centric metrics rather than chasing perfect scores. Remember, performance optimization is an ongoing process, not a one-time fix.",[102,9503,9504],{},"The web is getting faster, and user expectations continue to rise. By mastering Core Web Vitals optimization, you'll deliver experiences that delight users and drive business results. The time to act is now—your users (and search rankings) will thank you.",[1246,9506,9507],{},"html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}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);}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 .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sfNiH, html code.shiki .sfNiH{--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sqsOY, html code.shiki .sqsOY{--shiki-light:#8796B0;--shiki-default:#B2CCD6;--shiki-dark:#B2CCD6}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}",{"title":174,"searchDepth":189,"depth":189,"links":9509},[9510,9511,9516,9521,9525,9530,9531],{"id":7838,"depth":189,"text":7833},{"id":7847,"depth":189,"text":7848,"children":9512},[9513,9514,9515],{"id":7854,"depth":16,"text":7855},{"id":8046,"depth":16,"text":8047},{"id":8199,"depth":16,"text":8200},{"id":8397,"depth":189,"text":8398,"children":9517},[9518,9519,9520],{"id":8401,"depth":16,"text":8402},{"id":8580,"depth":16,"text":8581},{"id":8802,"depth":16,"text":8803},{"id":8925,"depth":189,"text":8926,"children":9522},[9523,9524],{"id":8929,"depth":16,"text":8930},{"id":9123,"depth":16,"text":9124},{"id":9375,"depth":189,"text":9376,"children":9526},[9527,9528,9529],{"id":9382,"depth":16,"text":9383},{"id":9400,"depth":16,"text":9401},{"id":9436,"depth":16,"text":9437},{"id":9457,"depth":189,"text":9458},{"id":1228,"depth":189,"text":1229},"2026-03-10","Master the latest Core Web Vitals metrics and learn proven optimization strategies to deliver lightning-fast web experiences that rank higher and convert better in 2026.",{"readingTime":9535},"12 min read","/blog/20-core-web-vitals-2026-optimization",{"title":7833,"description":9533},"Web Performance","Comprehensive guide to web performance optimization and monitoring",{"src":9541,"mime":1287,"alt":9542,"width":1289,"height":1290},"/img/blog/20-core-web-vitals-2026-optimization/banner.svg","Core Web Vitals 2026 Optimization - Speed metrics dashboard with green checkmarks and performance graphs on blue-green gradient background","blog/20-core-web-vitals-2026-optimization",[9545,9546,9547,1297,9548],"Performance","Core Web Vitals","SEO","Optimization","v-8qijFl74WKoVbUWXVZJt-dTLbphzXlyaiEHjs7wao",["Reactive",9551],{"$scolor-mode":9552,"$snuxt-seo-utils:routeRules":9555,"$stoasts":9556,"$ssite-config":9557},{"preference":9553,"value":9553,"unknown":624,"forced":9554},"system",false,{"head":-1,"seoMeta":-1},[],{"_priority":9558,"defaultLocale":9561,"description":9562,"env":9563,"indexable":624,"name":9564,"url":5002},{"env":9559,"indexable":9560,"url":9560,"name":9560,"description":9560,"defaultLocale":9560},-15,-3,"en","Senior Software Engineer specializing in modern web technologies. Crafting scalable web applications and browser extensions for startups and founders.","production","Muhammad Ubaid Raza - Full Stack Engineer",["Set"],["ShallowReactive",9567],{"blog-post-/blog/26-meta-frameworks-new-default-2026":-1,"profile-data":-1,"series-Modern Web Development":-1,"related-posts-/blog/26-meta-frameworks-new-default-2026":-1}]