[{"data":1,"prerenderedAt":3762},["ShallowReactive",2],{"blog":3},[4,195,318,440,564,687,849,1134,1256,1377,1497,1618,1742,1864,2443,2564,2686,2806,2927,3046,3168,3287],{"id":5,"title":6,"author":7,"body":8,"date":174,"description":14,"extension":175,"meta":176,"navigation":123,"path":177,"seo":178,"slug":186,"status":187,"stem":188,"summary":189,"tags":190,"__hash__":194},"blog\u002Fblog\u002Faccessibility-in-web-development.md","Accessibility in Web Development","Sharique",{"type":9,"value":10,"toc":164},"minimark",[11,15,20,23,26,30,33,38,57,61,64,66,70,131,135,137,152,156,158,160],[12,13,14],"p",{},"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.",[16,17,19],"h2",{"id":18},"introduction","Introduction",[12,21,22],{},"Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.",[12,24,25],{},"Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo.",[16,27,29],{"id":28},"key-concepts","Key Concepts",[12,31,32],{},"Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt.",[34,35,37],"h3",{"id":36},"important-points","Important Points",[39,40,41,45,48,51,54],"ul",{},[42,43,44],"li",{},"First important consideration about this topic",[42,46,47],{},"Second key aspect to understand",[42,49,50],{},"Third critical element to remember",[42,52,53],{},"Fourth essential principle to follow",[42,55,56],{},"Fifth fundamental concept to grasp",[16,58,60],{"id":59},"deep-dive","Deep Dive",[12,62,63],{},"Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.",[12,65,14],{},[16,67,69],{"id":68},"code-example","Code Example",[71,72,77],"pre",{"className":73,"code":74,"language":75,"meta":76,"style":76},"language-javascript shiki shiki-themes github-light github-dark","\u002F\u002F Example code snippet\nfunction exampleFunction() {\n  const data = 'Lorem ipsum';\n  console.log(data);\n  return data.toUpperCase();\n}\n\nexampleFunction();\n","javascript","",[78,79,80,88,94,100,106,112,118,125],"code",{"__ignoreMap":76},[81,82,85],"span",{"class":83,"line":84},"line",1,[81,86,87],{},"\u002F\u002F Example code snippet\n",[81,89,91],{"class":83,"line":90},2,[81,92,93],{},"function exampleFunction() {\n",[81,95,97],{"class":83,"line":96},3,[81,98,99],{},"  const data = 'Lorem ipsum';\n",[81,101,103],{"class":83,"line":102},4,[81,104,105],{},"  console.log(data);\n",[81,107,109],{"class":83,"line":108},5,[81,110,111],{},"  return data.toUpperCase();\n",[81,113,115],{"class":83,"line":114},6,[81,116,117],{},"}\n",[81,119,121],{"class":83,"line":120},7,[81,122,124],{"emptyLinePlaceholder":123},true,"\n",[81,126,128],{"class":83,"line":127},8,[81,129,130],{},"exampleFunction();\n",[16,132,134],{"id":133},"best-practices","Best Practices",[12,136,22],{},[138,139,140,143,146,149],"ol",{},[42,141,142],{},"First best practice to follow",[42,144,145],{},"Second recommended approach",[42,147,148],{},"Third important guideline",[42,150,151],{},"Fourth essential technique",[16,153,155],{"id":154},"conclusion","Conclusion",[12,157,25],{},[12,159,32],{},[161,162,163],"style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":76,"searchDepth":90,"depth":96,"links":165},[166,167,170,171,172,173],{"id":18,"depth":90,"text":19},{"id":28,"depth":90,"text":29,"children":168},[169],{"id":36,"depth":96,"text":37},{"id":59,"depth":90,"text":60},{"id":68,"depth":90,"text":69},{"id":133,"depth":90,"text":134},{"id":154,"depth":90,"text":155},"2025-07-09","md",{"url":177},"\u002Fblog\u002Faccessibility-in-web-development",{"description":179,"keywords":180,"title":6},"A practical guide to building accessible web applications — covering ARIA roles, semantic HTML, keyboard navigation, and inclusive design principles.",[181,182,183,184,185],"Accessibility","ARIA","Inclusive Design","Web Standards","a11y","accessibility-in-web-development","published","blog\u002Faccessibility-in-web-development","Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, q...",[191,192,193],"Testing","Quality Assurance","Development","VVEitotXIw5uAddHJNixHqYEndmxSwDeTyxy5MgBKLE",{"id":196,"title":197,"author":7,"body":198,"date":302,"description":14,"extension":175,"meta":303,"navigation":123,"path":304,"seo":305,"slug":312,"status":187,"stem":313,"summary":189,"tags":314,"__hash__":317},"blog\u002Fblog\u002Fapi-development-guidelines.md","API Development Guidelines",{"type":9,"value":199,"toc":292},[200,202,204,206,208,210,212,214,226,228,230,232,234,270,272,274,284,286,288,290],[12,201,14],{},[16,203,19],{"id":18},[12,205,22],{},[12,207,25],{},[16,209,29],{"id":28},[12,211,32],{},[34,213,37],{"id":36},[39,215,216,218,220,222,224],{},[42,217,44],{},[42,219,47],{},[42,221,50],{},[42,223,53],{},[42,225,56],{},[16,227,60],{"id":59},[12,229,63],{},[12,231,14],{},[16,233,69],{"id":68},[71,235,236],{"className":73,"code":74,"language":75,"meta":76,"style":76},[78,237,238,242,246,250,254,258,262,266],{"__ignoreMap":76},[81,239,240],{"class":83,"line":84},[81,241,87],{},[81,243,244],{"class":83,"line":90},[81,245,93],{},[81,247,248],{"class":83,"line":96},[81,249,99],{},[81,251,252],{"class":83,"line":102},[81,253,105],{},[81,255,256],{"class":83,"line":108},[81,257,111],{},[81,259,260],{"class":83,"line":114},[81,261,117],{},[81,263,264],{"class":83,"line":120},[81,265,124],{"emptyLinePlaceholder":123},[81,267,268],{"class":83,"line":127},[81,269,130],{},[16,271,134],{"id":133},[12,273,22],{},[138,275,276,278,280,282],{},[42,277,142],{},[42,279,145],{},[42,281,148],{},[42,283,151],{},[16,285,155],{"id":154},[12,287,25],{},[12,289,32],{},[161,291,163],{},{"title":76,"searchDepth":90,"depth":96,"links":293},[294,295,298,299,300,301],{"id":18,"depth":90,"text":19},{"id":28,"depth":90,"text":29,"children":296},[297],{"id":36,"depth":96,"text":37},{"id":59,"depth":90,"text":60},{"id":68,"depth":90,"text":69},{"id":133,"depth":90,"text":134},{"id":154,"depth":90,"text":155},"2025-05-14",{"url":304},"\u002Fblog\u002Fapi-development-guidelines",{"description":306,"keywords":307,"title":197},"Best practices for designing and building reliable APIs — covering REST conventions, versioning, error handling, and documentation.",[308,309,310,134,311],"API Design","REST","Backend Development","HTTP","api-development-guidelines","blog\u002Fapi-development-guidelines",[315,316,134],"TypeScript","Programming","5hgFsqCyWYlP9p4GFZCz9FbaqsGVLk05VFScyLXClh4",{"id":319,"title":320,"author":7,"body":321,"date":425,"description":14,"extension":175,"meta":426,"navigation":123,"path":427,"seo":428,"slug":436,"status":187,"stem":437,"summary":189,"tags":438,"__hash__":439},"blog\u002Fblog\u002Fbuilding-scalable-applications.md","Building Scalable Applications",{"type":9,"value":322,"toc":415},[323,325,327,329,331,333,335,337,349,351,353,355,357,393,395,397,407,409,411,413],[12,324,14],{},[16,326,19],{"id":18},[12,328,22],{},[12,330,25],{},[16,332,29],{"id":28},[12,334,32],{},[34,336,37],{"id":36},[39,338,339,341,343,345,347],{},[42,340,44],{},[42,342,47],{},[42,344,50],{},[42,346,53],{},[42,348,56],{},[16,350,60],{"id":59},[12,352,63],{},[12,354,14],{},[16,356,69],{"id":68},[71,358,359],{"className":73,"code":74,"language":75,"meta":76,"style":76},[78,360,361,365,369,373,377,381,385,389],{"__ignoreMap":76},[81,362,363],{"class":83,"line":84},[81,364,87],{},[81,366,367],{"class":83,"line":90},[81,368,93],{},[81,370,371],{"class":83,"line":96},[81,372,99],{},[81,374,375],{"class":83,"line":102},[81,376,105],{},[81,378,379],{"class":83,"line":108},[81,380,111],{},[81,382,383],{"class":83,"line":114},[81,384,117],{},[81,386,387],{"class":83,"line":120},[81,388,124],{"emptyLinePlaceholder":123},[81,390,391],{"class":83,"line":127},[81,392,130],{},[16,394,134],{"id":133},[12,396,22],{},[138,398,399,401,403,405],{},[42,400,142],{},[42,402,145],{},[42,404,148],{},[42,406,151],{},[16,408,155],{"id":154},[12,410,25],{},[12,412,32],{},[161,414,163],{},{"title":76,"searchDepth":90,"depth":96,"links":416},[417,418,421,422,423,424],{"id":18,"depth":90,"text":19},{"id":28,"depth":90,"text":29,"children":419},[420],{"id":36,"depth":96,"text":37},{"id":59,"depth":90,"text":60},{"id":68,"depth":90,"text":69},{"id":133,"depth":90,"text":134},{"id":154,"depth":90,"text":155},"2025-12-25",{"url":427},"\u002Fblog\u002Fbuilding-scalable-applications",{"description":429,"keywords":430,"title":320},"How to architect web applications that scale — covering load balancing, caching strategies, database sharding, and microservices patterns.",[431,432,433,434,435],"Scalability","System Design","Architecture","Performance","Backend","building-scalable-applications","blog\u002Fbuilding-scalable-applications",[315,316,134],"KRawUHhCjWsxa28-Bdw8pDEQZMsPeWTCv1iy3RocnXE",{"id":441,"title":442,"author":7,"body":443,"date":547,"description":14,"extension":175,"meta":548,"navigation":123,"path":549,"seo":550,"slug":558,"status":187,"stem":559,"summary":189,"tags":560,"__hash__":563},"blog\u002Fblog\u002Fcloud-computing-essentials.md","Cloud Computing Essentials",{"type":9,"value":444,"toc":537},[445,447,449,451,453,455,457,459,471,473,475,477,479,515,517,519,529,531,533,535],[12,446,14],{},[16,448,19],{"id":18},[12,450,22],{},[12,452,25],{},[16,454,29],{"id":28},[12,456,32],{},[34,458,37],{"id":36},[39,460,461,463,465,467,469],{},[42,462,44],{},[42,464,47],{},[42,466,50],{},[42,468,53],{},[42,470,56],{},[16,472,60],{"id":59},[12,474,63],{},[12,476,14],{},[16,478,69],{"id":68},[71,480,481],{"className":73,"code":74,"language":75,"meta":76,"style":76},[78,482,483,487,491,495,499,503,507,511],{"__ignoreMap":76},[81,484,485],{"class":83,"line":84},[81,486,87],{},[81,488,489],{"class":83,"line":90},[81,490,93],{},[81,492,493],{"class":83,"line":96},[81,494,99],{},[81,496,497],{"class":83,"line":102},[81,498,105],{},[81,500,501],{"class":83,"line":108},[81,502,111],{},[81,504,505],{"class":83,"line":114},[81,506,117],{},[81,508,509],{"class":83,"line":120},[81,510,124],{"emptyLinePlaceholder":123},[81,512,513],{"class":83,"line":127},[81,514,130],{},[16,516,134],{"id":133},[12,518,22],{},[138,520,521,523,525,527],{},[42,522,142],{},[42,524,145],{},[42,526,148],{},[42,528,151],{},[16,530,155],{"id":154},[12,532,25],{},[12,534,32],{},[161,536,163],{},{"title":76,"searchDepth":90,"depth":96,"links":538},[539,540,543,544,545,546],{"id":18,"depth":90,"text":19},{"id":28,"depth":90,"text":29,"children":541},[542],{"id":36,"depth":96,"text":37},{"id":59,"depth":90,"text":60},{"id":68,"depth":90,"text":69},{"id":133,"depth":90,"text":134},{"id":154,"depth":90,"text":155},"2025-04-30",{"url":549},"\u002Fblog\u002Fcloud-computing-essentials",{"description":551,"keywords":552,"title":442},"An introduction to cloud computing fundamentals — covering IaaS, PaaS, SaaS, major cloud providers, and how to choose the right deployment model.",[553,554,555,556,557],"Cloud Computing","AWS","Infrastructure","DevOps","IaaS","cloud-computing-essentials","blog\u002Fcloud-computing-essentials",[434,561,562],"Optimization","SEO","quzmbhx1DrzS2iyAINypL5naIj4Ypix-blL77hWpubY",{"id":565,"title":566,"author":7,"body":567,"date":671,"description":14,"extension":175,"meta":672,"navigation":123,"path":673,"seo":674,"slug":682,"status":187,"stem":683,"summary":189,"tags":684,"__hash__":686},"blog\u002Fblog\u002Fcomponent-based-architecture-explained.md","Component-Based Architecture Explained",{"type":9,"value":568,"toc":661},[569,571,573,575,577,579,581,583,595,597,599,601,603,639,641,643,653,655,657,659],[12,570,14],{},[16,572,19],{"id":18},[12,574,22],{},[12,576,25],{},[16,578,29],{"id":28},[12,580,32],{},[34,582,37],{"id":36},[39,584,585,587,589,591,593],{},[42,586,44],{},[42,588,47],{},[42,590,50],{},[42,592,53],{},[42,594,56],{},[16,596,60],{"id":59},[12,598,63],{},[12,600,14],{},[16,602,69],{"id":68},[71,604,605],{"className":73,"code":74,"language":75,"meta":76,"style":76},[78,606,607,611,615,619,623,627,631,635],{"__ignoreMap":76},[81,608,609],{"class":83,"line":84},[81,610,87],{},[81,612,613],{"class":83,"line":90},[81,614,93],{},[81,616,617],{"class":83,"line":96},[81,618,99],{},[81,620,621],{"class":83,"line":102},[81,622,105],{},[81,624,625],{"class":83,"line":108},[81,626,111],{},[81,628,629],{"class":83,"line":114},[81,630,117],{},[81,632,633],{"class":83,"line":120},[81,634,124],{"emptyLinePlaceholder":123},[81,636,637],{"class":83,"line":127},[81,638,130],{},[16,640,134],{"id":133},[12,642,22],{},[138,644,645,647,649,651],{},[42,646,142],{},[42,648,145],{},[42,650,148],{},[42,652,151],{},[16,654,155],{"id":154},[12,656,25],{},[12,658,32],{},[161,660,163],{},{"title":76,"searchDepth":90,"depth":96,"links":662},[663,664,667,668,669,670],{"id":18,"depth":90,"text":19},{"id":28,"depth":90,"text":29,"children":665},[666],{"id":36,"depth":96,"text":37},{"id":59,"depth":90,"text":60},{"id":68,"depth":90,"text":69},{"id":133,"depth":90,"text":134},{"id":154,"depth":90,"text":155},"2025-09-17",{"url":673},"\u002Fblog\u002Fcomponent-based-architecture-explained",{"description":675,"keywords":676,"title":566},"A deep dive into component-based UI architecture — how to think in components, manage props and state, and build reusable UI across Vue, React, and Angular.",[677,678,679,680,681],"Components","Vue","React","Frontend Architecture","UI","component-based-architecture-explained","blog\u002Fcomponent-based-architecture-explained",[678,679,685],"Angular","9KP6LBgfMf_DJPSfzfI9tBKzI-Tqthndv6qebrMZFH4",{"id":688,"title":689,"author":7,"body":690,"date":834,"description":14,"extension":175,"meta":835,"navigation":123,"path":836,"seo":837,"slug":845,"status":187,"stem":846,"summary":189,"tags":847,"__hash__":848},"blog\u002Fblog\u002Fdatabase-design-patterns.md","Database Design Patterns",{"type":9,"value":691,"toc":824},[692,694,696,698,700,702,704,706,708,710,712,714,716,718,730,732,734,736,738,774,776,778,788,790,792,794,796,798,800,802,804,806,808,810,812,814,816,818,820,822],[12,693,14],{},[12,695,22],{},[12,697,25],{},[12,699,22],{},[12,701,25],{},[16,703,19],{"id":18},[12,705,22],{},[12,707,25],{},[16,709,29],{"id":28},[12,711,32],{},[12,713,22],{},[12,715,25],{},[34,717,37],{"id":36},[39,719,720,722,724,726,728],{},[42,721,44],{},[42,723,47],{},[42,725,50],{},[42,727,53],{},[42,729,56],{},[16,731,60],{"id":59},[12,733,63],{},[12,735,14],{},[16,737,69],{"id":68},[71,739,740],{"className":73,"code":74,"language":75,"meta":76,"style":76},[78,741,742,746,750,754,758,762,766,770],{"__ignoreMap":76},[81,743,744],{"class":83,"line":84},[81,745,87],{},[81,747,748],{"class":83,"line":90},[81,749,93],{},[81,751,752],{"class":83,"line":96},[81,753,99],{},[81,755,756],{"class":83,"line":102},[81,757,105],{},[81,759,760],{"class":83,"line":108},[81,761,111],{},[81,763,764],{"class":83,"line":114},[81,765,117],{},[81,767,768],{"class":83,"line":120},[81,769,124],{"emptyLinePlaceholder":123},[81,771,772],{"class":83,"line":127},[81,773,130],{},[16,775,134],{"id":133},[12,777,22],{},[138,779,780,782,784,786],{},[42,781,142],{},[42,783,145],{},[42,785,148],{},[42,787,151],{},[12,789,22],{},[12,791,25],{},[16,793,155],{"id":154},[12,795,25],{},[12,797,32],{},[12,799,22],{},[12,801,25],{},[12,803,22],{},[12,805,25],{},[12,807,22],{},[12,809,25],{},[12,811,22],{},[12,813,25],{},[12,815,22],{},[12,817,25],{},[12,819,22],{},[12,821,25],{},[161,823,163],{},{"title":76,"searchDepth":90,"depth":96,"links":825},[826,827,830,831,832,833],{"id":18,"depth":90,"text":19},{"id":28,"depth":90,"text":29,"children":828},[829],{"id":36,"depth":96,"text":37},{"id":59,"depth":90,"text":60},{"id":68,"depth":90,"text":69},{"id":133,"depth":90,"text":134},{"id":154,"depth":90,"text":155},"2026-01-28",{"url":836},"\u002Fblog\u002Fdatabase-design-patterns",{"description":838,"keywords":839,"title":689},"Core database design patterns every developer should know — normalization, indexing strategies, ORMs, and when to choose SQL vs NoSQL.",[840,841,842,843,844],"Database Design","SQL","NoSQL","Data Modeling","Indexing","database-design-patterns","blog\u002Fdatabase-design-patterns",[678,679,685],"vtPlvOV21obP54x3kW6AQjSeAdWEXYxqP5q9zzPN7ek",{"id":850,"title":851,"author":7,"body":852,"date":1121,"description":856,"extension":175,"meta":1122,"navigation":123,"path":1123,"seo":1124,"slug":1129,"status":187,"stem":1130,"summary":1131,"tags":1132,"__hash__":1133},"blog\u002Fblog\u002Fdeep-dive-into-typescript.md","Deep Dive into TypeScript",{"type":9,"value":853,"toc":1115},[854,857,861,868,940,946,950,965,1009,1012,1016,1026,1102,1105,1109,1112],[12,855,856],{},"TypeScript's type system goes far beyond simple annotations. Once you move past the basics, a handful of features unlock a completely different way of thinking about your code.",[16,858,860],{"id":859},"generics","Generics",[12,862,863,864,867],{},"Generics let you write logic once and reuse it across types without losing safety. A common pitfall is reaching for ",[78,865,866],{},"any"," when a function needs to be flexible — a generic parameter is almost always the right tool instead.",[71,869,873],{"className":870,"code":871,"language":872,"meta":76,"style":76},"language-typescript shiki shiki-themes github-light github-dark","function first\u003CT>(arr: T[]): T | undefined {\n  return arr[0];\n}\n","typescript",[78,874,875,922,936],{"__ignoreMap":76},[81,876,877,881,885,889,892,895,899,902,905,908,910,912,915,919],{"class":83,"line":84},[81,878,880],{"class":879},"szBVR","function",[81,882,884],{"class":883},"sScJk"," first",[81,886,888],{"class":887},"sVt8B","\u003C",[81,890,891],{"class":883},"T",[81,893,894],{"class":887},">(",[81,896,898],{"class":897},"s4XuR","arr",[81,900,901],{"class":879},":",[81,903,904],{"class":883}," T",[81,906,907],{"class":887},"[])",[81,909,901],{"class":879},[81,911,904],{"class":883},[81,913,914],{"class":879}," |",[81,916,918],{"class":917},"sj4cs"," undefined",[81,920,921],{"class":887}," {\n",[81,923,924,927,930,933],{"class":83,"line":90},[81,925,926],{"class":879},"  return",[81,928,929],{"class":887}," arr[",[81,931,932],{"class":917},"0",[81,934,935],{"class":887},"];\n",[81,937,938],{"class":83,"line":96},[81,939,117],{"class":887},[12,941,942,943,945],{},"The inferred return type follows the input automatically. No casting, no ",[78,944,866],{},".",[16,947,949],{"id":948},"utility-types","Utility Types",[12,951,952,953,956,957,960,961,964],{},"TypeScript ships with a set of built-in mapped types that cover the most common transformations. ",[78,954,955],{},"Partial\u003CT>"," makes every property optional, ",[78,958,959],{},"Required\u003CT>"," does the opposite, and ",[78,962,963],{},"Pick\u003CT, K>"," narrows a type to just the keys you need.",[71,966,968],{"className":870,"code":967,"language":872,"meta":76,"style":76},"type UserPreview = Pick\u003CUser, \"id\" | \"name\" | \"avatarUrl\">;\n",[78,969,970],{"__ignoreMap":76},[81,971,972,975,978,981,984,986,989,992,996,998,1001,1003,1006],{"class":83,"line":84},[81,973,974],{"class":879},"type",[81,976,977],{"class":883}," UserPreview",[81,979,980],{"class":879}," =",[81,982,983],{"class":883}," Pick",[81,985,888],{"class":887},[81,987,988],{"class":883},"User",[81,990,991],{"class":887},", ",[81,993,995],{"class":994},"sZZnC","\"id\"",[81,997,914],{"class":879},[81,999,1000],{"class":994}," \"name\"",[81,1002,914],{"class":879},[81,1004,1005],{"class":994}," \"avatarUrl\"",[81,1007,1008],{"class":887},">;\n",[12,1010,1011],{},"Reaching for these before defining a new interface keeps your type graph from growing out of control.",[16,1013,1015],{"id":1014},"discriminated-unions","Discriminated Unions",[12,1017,1018,1019,1022,1023,1025],{},"When a value can be one of several shapes, a discriminated union beats optional properties every time. Add a shared literal field — conventionally called ",[78,1020,1021],{},"kind"," or ",[78,1024,974],{}," — and TypeScript narrows automatically inside each branch.",[71,1027,1029],{"className":870,"code":1028,"language":872,"meta":76,"style":76},"type Result\u003CT> =\n  | { kind: \"ok\"; value: T }\n  | { kind: \"error\"; message: string };\n",[78,1030,1031,1048,1076],{"__ignoreMap":76},[81,1032,1033,1035,1038,1040,1042,1045],{"class":83,"line":84},[81,1034,974],{"class":879},[81,1036,1037],{"class":883}," Result",[81,1039,888],{"class":887},[81,1041,891],{"class":883},[81,1043,1044],{"class":887},"> ",[81,1046,1047],{"class":879},"=\n",[81,1049,1050,1053,1056,1058,1060,1063,1066,1069,1071,1073],{"class":83,"line":90},[81,1051,1052],{"class":879},"  |",[81,1054,1055],{"class":887}," { ",[81,1057,1021],{"class":897},[81,1059,901],{"class":879},[81,1061,1062],{"class":994}," \"ok\"",[81,1064,1065],{"class":887},"; ",[81,1067,1068],{"class":897},"value",[81,1070,901],{"class":879},[81,1072,904],{"class":883},[81,1074,1075],{"class":887}," }\n",[81,1077,1078,1080,1082,1084,1086,1089,1091,1094,1096,1099],{"class":83,"line":96},[81,1079,1052],{"class":879},[81,1081,1055],{"class":887},[81,1083,1021],{"class":897},[81,1085,901],{"class":879},[81,1087,1088],{"class":994}," \"error\"",[81,1090,1065],{"class":887},[81,1092,1093],{"class":897},"message",[81,1095,901],{"class":879},[81,1097,1098],{"class":917}," string",[81,1100,1101],{"class":887}," };\n",[12,1103,1104],{},"The exhaustiveness check is free: if you forget a case, the compiler tells you immediately.",[16,1106,1108],{"id":1107},"key-takeaway","Key Takeaway",[12,1110,1111],{},"These three features — generics, utility types, and discriminated unions — cover the majority of real-world TypeScript complexity. Master them and you will spend far less time fighting the type system and far more time using it as a design tool.",[161,1113,1114],{},"html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}",{"title":76,"searchDepth":90,"depth":96,"links":1116},[1117,1118,1119,1120],{"id":859,"depth":90,"text":860},{"id":948,"depth":90,"text":949},{"id":1014,"depth":90,"text":1015},{"id":1107,"depth":90,"text":1108},"2025-12-11",{"url":1123},"\u002Fblog\u002Fdeep-dive-into-typescript",{"description":1125,"keywords":1126,"title":851},"A comprehensive look at TypeScript's type system — generics, utility types, discriminated unions, and patterns for writing safer, more maintainable code.",[315,1127,1128,860,316],"JavaScript","Type Safety","deep-dive-into-typescript","blog\u002Fdeep-dive-into-typescript","A practical look at TypeScript's most powerful features — generics, utility types, and discriminated unions — with patterns you can apply today.",[315,1127,316],"WL07kcUzMNxlbmhyC3DONwlvqGPGvsXXUsUx33iS9eY",{"id":1135,"title":1136,"author":7,"body":1137,"date":1241,"description":14,"extension":175,"meta":1242,"navigation":123,"path":1243,"seo":1244,"slug":1251,"status":187,"stem":1252,"summary":189,"tags":1253,"__hash__":1255},"blog\u002Fblog\u002Fdeployment-and-devops-fundamentals.md","Deployment and DevOps Fundamentals",{"type":9,"value":1138,"toc":1231},[1139,1141,1143,1145,1147,1149,1151,1153,1165,1167,1169,1171,1173,1209,1211,1213,1223,1225,1227,1229],[12,1140,14],{},[16,1142,19],{"id":18},[12,1144,22],{},[12,1146,25],{},[16,1148,29],{"id":28},[12,1150,32],{},[34,1152,37],{"id":36},[39,1154,1155,1157,1159,1161,1163],{},[42,1156,44],{},[42,1158,47],{},[42,1160,50],{},[42,1162,53],{},[42,1164,56],{},[16,1166,60],{"id":59},[12,1168,63],{},[12,1170,14],{},[16,1172,69],{"id":68},[71,1174,1175],{"className":73,"code":74,"language":75,"meta":76,"style":76},[78,1176,1177,1181,1185,1189,1193,1197,1201,1205],{"__ignoreMap":76},[81,1178,1179],{"class":83,"line":84},[81,1180,87],{},[81,1182,1183],{"class":83,"line":90},[81,1184,93],{},[81,1186,1187],{"class":83,"line":96},[81,1188,99],{},[81,1190,1191],{"class":83,"line":102},[81,1192,105],{},[81,1194,1195],{"class":83,"line":108},[81,1196,111],{},[81,1198,1199],{"class":83,"line":114},[81,1200,117],{},[81,1202,1203],{"class":83,"line":120},[81,1204,124],{"emptyLinePlaceholder":123},[81,1206,1207],{"class":83,"line":127},[81,1208,130],{},[16,1210,134],{"id":133},[12,1212,22],{},[138,1214,1215,1217,1219,1221],{},[42,1216,142],{},[42,1218,145],{},[42,1220,148],{},[42,1222,151],{},[16,1224,155],{"id":154},[12,1226,25],{},[12,1228,32],{},[161,1230,163],{},{"title":76,"searchDepth":90,"depth":96,"links":1232},[1233,1234,1237,1238,1239,1240],{"id":18,"depth":90,"text":19},{"id":28,"depth":90,"text":29,"children":1235},[1236],{"id":36,"depth":96,"text":37},{"id":59,"depth":90,"text":60},{"id":68,"depth":90,"text":69},{"id":133,"depth":90,"text":134},{"id":154,"depth":90,"text":155},"2025-08-06",{"url":1243},"\u002Fblog\u002Fdeployment-and-devops-fundamentals",{"description":1245,"keywords":1246,"title":1136},"Everything you need to start deploying confidently — CI\u002FCD pipelines, Docker containers, environment variables, and blue-green deployment strategies.",[556,1247,1248,1249,1250],"CI\u002FCD","Docker","Deployment","GitHub Actions","deployment-and-devops-fundamentals","blog\u002Fdeployment-and-devops-fundamentals",[1254,435,433],"API","dUSlvJNV0Y4BcAc8zV97ERiFJpQD0ZHgarRIxJG6bXw",{"id":1257,"title":1258,"author":7,"body":1259,"date":1363,"description":14,"extension":175,"meta":1364,"navigation":123,"path":1365,"seo":1366,"slug":1373,"status":187,"stem":1374,"summary":189,"tags":1375,"__hash__":1376},"blog\u002Fblog\u002Fexploring-server-side-rendering.md","Exploring Server-Side Rendering",{"type":9,"value":1260,"toc":1353},[1261,1263,1265,1267,1269,1271,1273,1275,1287,1289,1291,1293,1295,1331,1333,1335,1345,1347,1349,1351],[12,1262,14],{},[16,1264,19],{"id":18},[12,1266,22],{},[12,1268,25],{},[16,1270,29],{"id":28},[12,1272,32],{},[34,1274,37],{"id":36},[39,1276,1277,1279,1281,1283,1285],{},[42,1278,44],{},[42,1280,47],{},[42,1282,50],{},[42,1284,53],{},[42,1286,56],{},[16,1288,60],{"id":59},[12,1290,63],{},[12,1292,14],{},[16,1294,69],{"id":68},[71,1296,1297],{"className":73,"code":74,"language":75,"meta":76,"style":76},[78,1298,1299,1303,1307,1311,1315,1319,1323,1327],{"__ignoreMap":76},[81,1300,1301],{"class":83,"line":84},[81,1302,87],{},[81,1304,1305],{"class":83,"line":90},[81,1306,93],{},[81,1308,1309],{"class":83,"line":96},[81,1310,99],{},[81,1312,1313],{"class":83,"line":102},[81,1314,105],{},[81,1316,1317],{"class":83,"line":108},[81,1318,111],{},[81,1320,1321],{"class":83,"line":114},[81,1322,117],{},[81,1324,1325],{"class":83,"line":120},[81,1326,124],{"emptyLinePlaceholder":123},[81,1328,1329],{"class":83,"line":127},[81,1330,130],{},[16,1332,134],{"id":133},[12,1334,22],{},[138,1336,1337,1339,1341,1343],{},[42,1338,142],{},[42,1340,145],{},[42,1342,148],{},[42,1344,151],{},[16,1346,155],{"id":154},[12,1348,25],{},[12,1350,32],{},[161,1352,163],{},{"title":76,"searchDepth":90,"depth":96,"links":1354},[1355,1356,1359,1360,1361,1362],{"id":18,"depth":90,"text":19},{"id":28,"depth":90,"text":29,"children":1357},[1358],{"id":36,"depth":96,"text":37},{"id":59,"depth":90,"text":60},{"id":68,"depth":90,"text":69},{"id":133,"depth":90,"text":134},{"id":154,"depth":90,"text":155},"2025-11-27",{"url":1365},"\u002Fblog\u002Fexploring-server-side-rendering",{"description":1367,"keywords":1368,"title":1258},"What server-side rendering is, why it matters for SEO and performance, and how frameworks like Nuxt and Next.js implement SSR under the hood.",[1369,1370,1371,1372,434],"SSR","Server-Side Rendering","Nuxt","Next.js","exploring-server-side-rendering","blog\u002Fexploring-server-side-rendering",[1254,435,433],"2fdfLYek_JDfoa4Ei3szWNititnU_jizjveEtLqOkuY",{"id":1378,"title":1379,"author":7,"body":1380,"date":1484,"description":14,"extension":175,"meta":1485,"navigation":123,"path":1486,"seo":1487,"slug":1493,"status":187,"stem":1494,"summary":189,"tags":1495,"__hash__":1496},"blog\u002Fblog\u002Fgraphql-vs-rest-apis.md","GraphQL vs REST APIs",{"type":9,"value":1381,"toc":1474},[1382,1384,1386,1388,1390,1392,1394,1396,1408,1410,1412,1414,1416,1452,1454,1456,1466,1468,1470,1472],[12,1383,14],{},[16,1385,19],{"id":18},[12,1387,22],{},[12,1389,25],{},[16,1391,29],{"id":28},[12,1393,32],{},[34,1395,37],{"id":36},[39,1397,1398,1400,1402,1404,1406],{},[42,1399,44],{},[42,1401,47],{},[42,1403,50],{},[42,1405,53],{},[42,1407,56],{},[16,1409,60],{"id":59},[12,1411,63],{},[12,1413,14],{},[16,1415,69],{"id":68},[71,1417,1418],{"className":73,"code":74,"language":75,"meta":76,"style":76},[78,1419,1420,1424,1428,1432,1436,1440,1444,1448],{"__ignoreMap":76},[81,1421,1422],{"class":83,"line":84},[81,1423,87],{},[81,1425,1426],{"class":83,"line":90},[81,1427,93],{},[81,1429,1430],{"class":83,"line":96},[81,1431,99],{},[81,1433,1434],{"class":83,"line":102},[81,1435,105],{},[81,1437,1438],{"class":83,"line":108},[81,1439,111],{},[81,1441,1442],{"class":83,"line":114},[81,1443,117],{},[81,1445,1446],{"class":83,"line":120},[81,1447,124],{"emptyLinePlaceholder":123},[81,1449,1450],{"class":83,"line":127},[81,1451,130],{},[16,1453,134],{"id":133},[12,1455,22],{},[138,1457,1458,1460,1462,1464],{},[42,1459,142],{},[42,1461,145],{},[42,1463,148],{},[42,1465,151],{},[16,1467,155],{"id":154},[12,1469,25],{},[12,1471,32],{},[161,1473,163],{},{"title":76,"searchDepth":90,"depth":96,"links":1475},[1476,1477,1480,1481,1482,1483],{"id":18,"depth":90,"text":19},{"id":28,"depth":90,"text":29,"children":1478},[1479],{"id":36,"depth":96,"text":37},{"id":59,"depth":90,"text":60},{"id":68,"depth":90,"text":69},{"id":133,"depth":90,"text":134},{"id":154,"depth":90,"text":155},"2025-10-15",{"url":1486},"\u002Fblog\u002Fgraphql-vs-rest-apis",{"description":1488,"keywords":1489,"title":1379},"A practical comparison of GraphQL and REST — when to use each, key trade-offs around flexibility, caching, tooling, and team conventions.",[1490,1491,308,435,1492],"GraphQL","REST API","Query Language","graphql-vs-rest-apis","blog\u002Fgraphql-vs-rest-apis",[556,1249,1247],"8tx4KUEm8xfpDl816MgADFFaloKHE_f_6Vn-d48_QoA",{"id":1498,"title":1499,"author":7,"body":1500,"date":1604,"description":14,"extension":175,"meta":1605,"navigation":123,"path":1606,"seo":1607,"slug":1614,"status":187,"stem":1615,"summary":189,"tags":1616,"__hash__":1617},"blog\u002Fblog\u002Fintroduction-to-web-performance.md","Introduction to Web Performance",{"type":9,"value":1501,"toc":1594},[1502,1504,1506,1508,1510,1512,1514,1516,1528,1530,1532,1534,1536,1572,1574,1576,1586,1588,1590,1592],[12,1503,14],{},[16,1505,19],{"id":18},[12,1507,22],{},[12,1509,25],{},[16,1511,29],{"id":28},[12,1513,32],{},[34,1515,37],{"id":36},[39,1517,1518,1520,1522,1524,1526],{},[42,1519,44],{},[42,1521,47],{},[42,1523,50],{},[42,1525,53],{},[42,1527,56],{},[16,1529,60],{"id":59},[12,1531,63],{},[12,1533,14],{},[16,1535,69],{"id":68},[71,1537,1538],{"className":73,"code":74,"language":75,"meta":76,"style":76},[78,1539,1540,1544,1548,1552,1556,1560,1564,1568],{"__ignoreMap":76},[81,1541,1542],{"class":83,"line":84},[81,1543,87],{},[81,1545,1546],{"class":83,"line":90},[81,1547,93],{},[81,1549,1550],{"class":83,"line":96},[81,1551,99],{},[81,1553,1554],{"class":83,"line":102},[81,1555,105],{},[81,1557,1558],{"class":83,"line":108},[81,1559,111],{},[81,1561,1562],{"class":83,"line":114},[81,1563,117],{},[81,1565,1566],{"class":83,"line":120},[81,1567,124],{"emptyLinePlaceholder":123},[81,1569,1570],{"class":83,"line":127},[81,1571,130],{},[16,1573,134],{"id":133},[12,1575,22],{},[138,1577,1578,1580,1582,1584],{},[42,1579,142],{},[42,1581,145],{},[42,1583,148],{},[42,1585,151],{},[16,1587,155],{"id":154},[12,1589,25],{},[12,1591,32],{},[161,1593,163],{},{"title":76,"searchDepth":90,"depth":96,"links":1595},[1596,1597,1600,1601,1602,1603],{"id":18,"depth":90,"text":19},{"id":28,"depth":90,"text":29,"children":1598},[1599],{"id":36,"depth":96,"text":37},{"id":59,"depth":90,"text":60},{"id":68,"depth":90,"text":69},{"id":133,"depth":90,"text":134},{"id":154,"depth":90,"text":155},"2025-10-30",{"url":1606},"\u002Fblog\u002Fintroduction-to-web-performance",{"description":1608,"keywords":1609,"title":1499},"Core concepts for making web pages fast — Core Web Vitals, lazy loading, code splitting, image optimization, and measuring with Lighthouse.",[1610,1611,561,1612,1613],"Web Performance","Core Web Vitals","Lighthouse","Speed","introduction-to-web-performance","blog\u002Fintroduction-to-web-performance",[191,192,193],"zB3eEcZ2WXKGNWACtjBX01h7VRiqLj3eiZuwp89g0KQ",{"id":1619,"title":1620,"author":7,"body":1621,"date":1725,"description":14,"extension":175,"meta":1726,"navigation":123,"path":1727,"seo":1728,"slug":1735,"status":187,"stem":1736,"summary":189,"tags":1737,"__hash__":1741},"blog\u002Fblog\u002Fmastering-css-grid-and-flexbox.md","Mastering CSS Grid and Flexbox",{"type":9,"value":1622,"toc":1715},[1623,1625,1627,1629,1631,1633,1635,1637,1649,1651,1653,1655,1657,1693,1695,1697,1707,1709,1711,1713],[12,1624,14],{},[16,1626,19],{"id":18},[12,1628,22],{},[12,1630,25],{},[16,1632,29],{"id":28},[12,1634,32],{},[34,1636,37],{"id":36},[39,1638,1639,1641,1643,1645,1647],{},[42,1640,44],{},[42,1642,47],{},[42,1644,50],{},[42,1646,53],{},[42,1648,56],{},[16,1650,60],{"id":59},[12,1652,63],{},[12,1654,14],{},[16,1656,69],{"id":68},[71,1658,1659],{"className":73,"code":74,"language":75,"meta":76,"style":76},[78,1660,1661,1665,1669,1673,1677,1681,1685,1689],{"__ignoreMap":76},[81,1662,1663],{"class":83,"line":84},[81,1664,87],{},[81,1666,1667],{"class":83,"line":90},[81,1668,93],{},[81,1670,1671],{"class":83,"line":96},[81,1672,99],{},[81,1674,1675],{"class":83,"line":102},[81,1676,105],{},[81,1678,1679],{"class":83,"line":108},[81,1680,111],{},[81,1682,1683],{"class":83,"line":114},[81,1684,117],{},[81,1686,1687],{"class":83,"line":120},[81,1688,124],{"emptyLinePlaceholder":123},[81,1690,1691],{"class":83,"line":127},[81,1692,130],{},[16,1694,134],{"id":133},[12,1696,22],{},[138,1698,1699,1701,1703,1705],{},[42,1700,142],{},[42,1702,145],{},[42,1704,148],{},[42,1706,151],{},[16,1708,155],{"id":154},[12,1710,25],{},[12,1712,32],{},[161,1714,163],{},{"title":76,"searchDepth":90,"depth":96,"links":1716},[1717,1718,1721,1722,1723,1724],{"id":18,"depth":90,"text":19},{"id":28,"depth":90,"text":29,"children":1719},[1720],{"id":36,"depth":96,"text":37},{"id":59,"depth":90,"text":60},{"id":68,"depth":90,"text":69},{"id":133,"depth":90,"text":134},{"id":154,"depth":90,"text":155},"2025-11-13",{"url":1727},"\u002Fblog\u002Fmastering-css-grid-and-flexbox",{"description":1729,"keywords":1730,"title":1620},"A hands-on guide to CSS layout with Grid and Flexbox — when to use each, alignment tricks, responsive patterns, and common pitfalls.",[1731,1732,1733,1734,681],"CSS Grid","Flexbox","CSS Layout","Responsive Design","mastering-css-grid-and-flexbox","blog\u002Fmastering-css-grid-and-flexbox",[1738,1739,1740],"CSS","Design","UI\u002FUX","_DH94STyObDpP7LkhFhwkSzxGvOQbDfYFITD84xB5RE",{"id":1743,"title":1744,"author":7,"body":1745,"date":1849,"description":14,"extension":175,"meta":1850,"navigation":123,"path":1851,"seo":1852,"slug":1858,"status":187,"stem":1859,"summary":189,"tags":1860,"__hash__":1863},"blog\u002Fblog\u002Fmicroservices-architecture-overview.md","Microservices Architecture Overview",{"type":9,"value":1746,"toc":1839},[1747,1749,1751,1753,1755,1757,1759,1761,1773,1775,1777,1779,1781,1817,1819,1821,1831,1833,1835,1837],[12,1748,14],{},[16,1750,19],{"id":18},[12,1752,22],{},[12,1754,25],{},[16,1756,29],{"id":28},[12,1758,32],{},[34,1760,37],{"id":36},[39,1762,1763,1765,1767,1769,1771],{},[42,1764,44],{},[42,1766,47],{},[42,1768,50],{},[42,1770,53],{},[42,1772,56],{},[16,1774,60],{"id":59},[12,1776,63],{},[12,1778,14],{},[16,1780,69],{"id":68},[71,1782,1783],{"className":73,"code":74,"language":75,"meta":76,"style":76},[78,1784,1785,1789,1793,1797,1801,1805,1809,1813],{"__ignoreMap":76},[81,1786,1787],{"class":83,"line":84},[81,1788,87],{},[81,1790,1791],{"class":83,"line":90},[81,1792,93],{},[81,1794,1795],{"class":83,"line":96},[81,1796,99],{},[81,1798,1799],{"class":83,"line":102},[81,1800,105],{},[81,1802,1803],{"class":83,"line":108},[81,1804,111],{},[81,1806,1807],{"class":83,"line":114},[81,1808,117],{},[81,1810,1811],{"class":83,"line":120},[81,1812,124],{"emptyLinePlaceholder":123},[81,1814,1815],{"class":83,"line":127},[81,1816,130],{},[16,1818,134],{"id":133},[12,1820,22],{},[138,1822,1823,1825,1827,1829],{},[42,1824,142],{},[42,1826,145],{},[42,1828,148],{},[42,1830,151],{},[16,1832,155],{"id":154},[12,1834,25],{},[12,1836,32],{},[161,1838,163],{},{"title":76,"searchDepth":90,"depth":96,"links":1840},[1841,1842,1845,1846,1847,1848],{"id":18,"depth":90,"text":19},{"id":28,"depth":90,"text":29,"children":1843},[1844],{"id":36,"depth":96,"text":37},{"id":59,"depth":90,"text":60},{"id":68,"depth":90,"text":69},{"id":133,"depth":90,"text":134},{"id":154,"depth":90,"text":155},"2025-06-11",{"url":1851},"\u002Fblog\u002Fmicroservices-architecture-overview",{"description":1853,"keywords":1854,"title":1744},"An overview of microservices architecture — service decomposition, inter-service communication, API gateways, and trade-offs vs monoliths.",[1855,433,1856,1857,435],"Microservices","Distributed Systems","API Gateway","microservices-architecture-overview","blog\u002Fmicroservices-architecture-overview",[1127,1861,1862],"Web Development","Frontend","IwSrZ0OER_fhd2L2g4GjeJrZoUPv27ygvd1rO8eGN_0",{"id":1865,"title":1866,"author":7,"body":1867,"date":2427,"description":1871,"extension":175,"meta":2428,"navigation":123,"path":2429,"seo":2430,"slug":2437,"status":187,"stem":2438,"summary":2439,"tags":2440,"__hash__":2442},"blog\u002Fblog\u002Fnuxt-content-example.md","Getting Started with Folio",{"type":9,"value":1868,"toc":2410},[1869,1872,1876,1883,1891,1903,1907,1910,2066,2073,2077,2084,2088,2095,2255,2259,2278,2282,2296,2300,2303,2307,2324,2328,2331,2351,2355,2375,2379,2388,2392,2407],[12,1870,1871],{},"This post walks through how Folio is built — how posts are written, what the frontmatter schema looks like, and how SEO and social sharing tags are generated automatically for every post.",[16,1873,1875],{"id":1874},"writing-a-post","Writing a Post",[12,1877,1878,1879,1882],{},"Every blog post is a plain Markdown file stored in ",[78,1880,1881],{},"content\u002Fblog\u002F",". The filename becomes the URL slug:",[71,1884,1889],{"className":1885,"code":1887,"language":1888},[1886],"language-text","content\u002Fblog\u002Fmy-post-title.md  →  \u002Fblog\u002Fmy-post-title\n","text",[78,1890,1887],{"__ignoreMap":76},[12,1892,1893,1894,1898,1899,1902],{},"At the top of each file is a ",[1895,1896,1897],"strong",{},"frontmatter block"," — a YAML section wrapped in ",[78,1900,1901],{},"---"," that provides metadata about the post.",[16,1904,1906],{"id":1905},"frontmatter-schema","Frontmatter Schema",[12,1908,1909],{},"Here is the full schema this blog supports:",[71,1911,1915],{"className":1912,"code":1913,"language":1914,"meta":76,"style":76},"language-yaml shiki shiki-themes github-light github-dark","---\ntitle: \"My Post Title\"        # required — shown in the page heading and browser tab\ndate: 2025-01-15              # required — used for sorting and displayed on the post\nsummary: \"Short description\"  # required — shown on the blog listing card\ntags: [\"Vue\", \"Nuxt\"]         # optional — displayed as pills at the bottom of the post\nauthor: \"Your Name\"           # optional — defaults to \"Unknown\"\nstatus: \"published\"           # \"draft\" | \"published\" — drafts are hidden from the listing\nseo:\n  description: \"Custom text for search engines and social previews\"\n  keywords: [\"keyword1\", \"keyword2\"]\n  og:image: \"https:\u002F\u002Fexample.com\u002Fcover.jpg\"\n---\n","yaml",[78,1916,1917,1922,1938,1951,1964,1986,1999,2012,2020,2031,2050,2061],{"__ignoreMap":76},[81,1918,1919],{"class":83,"line":84},[81,1920,1921],{"class":883},"---\n",[81,1923,1924,1928,1931,1934],{"class":83,"line":90},[81,1925,1927],{"class":1926},"s9eBZ","title",[81,1929,1930],{"class":887},": ",[81,1932,1933],{"class":994},"\"My Post Title\"",[81,1935,1937],{"class":1936},"sJ8bj","        # required — shown in the page heading and browser tab\n",[81,1939,1940,1943,1945,1948],{"class":83,"line":96},[81,1941,1942],{"class":1926},"date",[81,1944,1930],{"class":887},[81,1946,1947],{"class":917},"2025-01-15",[81,1949,1950],{"class":1936},"              # required — used for sorting and displayed on the post\n",[81,1952,1953,1956,1958,1961],{"class":83,"line":102},[81,1954,1955],{"class":1926},"summary",[81,1957,1930],{"class":887},[81,1959,1960],{"class":994},"\"Short description\"",[81,1962,1963],{"class":1936},"  # required — shown on the blog listing card\n",[81,1965,1966,1969,1972,1975,1977,1980,1983],{"class":83,"line":108},[81,1967,1968],{"class":1926},"tags",[81,1970,1971],{"class":887},": [",[81,1973,1974],{"class":994},"\"Vue\"",[81,1976,991],{"class":887},[81,1978,1979],{"class":994},"\"Nuxt\"",[81,1981,1982],{"class":887},"]         ",[81,1984,1985],{"class":1936},"# optional — displayed as pills at the bottom of the post\n",[81,1987,1988,1991,1993,1996],{"class":83,"line":114},[81,1989,1990],{"class":1926},"author",[81,1992,1930],{"class":887},[81,1994,1995],{"class":994},"\"Your Name\"",[81,1997,1998],{"class":1936},"           # optional — defaults to \"Unknown\"\n",[81,2000,2001,2004,2006,2009],{"class":83,"line":120},[81,2002,2003],{"class":1926},"status",[81,2005,1930],{"class":887},[81,2007,2008],{"class":994},"\"published\"",[81,2010,2011],{"class":1936},"           # \"draft\" | \"published\" — drafts are hidden from the listing\n",[81,2013,2014,2017],{"class":83,"line":127},[81,2015,2016],{"class":1926},"seo",[81,2018,2019],{"class":887},":\n",[81,2021,2023,2026,2028],{"class":83,"line":2022},9,[81,2024,2025],{"class":1926},"  description",[81,2027,1930],{"class":887},[81,2029,2030],{"class":994},"\"Custom text for search engines and social previews\"\n",[81,2032,2034,2037,2039,2042,2044,2047],{"class":83,"line":2033},10,[81,2035,2036],{"class":1926},"  keywords",[81,2038,1971],{"class":887},[81,2040,2041],{"class":994},"\"keyword1\"",[81,2043,991],{"class":887},[81,2045,2046],{"class":994},"\"keyword2\"",[81,2048,2049],{"class":887},"]\n",[81,2051,2053,2056,2058],{"class":83,"line":2052},11,[81,2054,2055],{"class":1926},"  og:image",[81,2057,1930],{"class":887},[81,2059,2060],{"class":994},"\"https:\u002F\u002Fexample.com\u002Fcover.jpg\"\n",[81,2062,2064],{"class":83,"line":2063},12,[81,2065,1921],{"class":883},[12,2067,2068,2069,2072],{},"All fields are validated at build time using ",[1895,2070,2071],{},"Zod",". If a required field is missing, the build will fail with a clear error.",[34,2074,2076],{"id":2075},"draft-vs-published","Draft vs Published",[12,2078,2079,2080,2083],{},"Setting ",[78,2081,2082],{},"status: \"draft\""," hides the post from the blog listing and sitemap. It is still accessible by direct URL during development, making it easy to preview before publishing.",[16,2085,2087],{"id":2086},"seo-and-open-graph-tags","SEO and Open Graph Tags",[12,2089,2090,2091,2094],{},"Every page on this blog sets meta tags automatically using Nuxt's built-in ",[78,2092,2093],{},"useSeoMeta()"," composable. On post pages, the tags are populated from the frontmatter:",[71,2096,2100],{"className":2097,"code":2098,"language":2099,"meta":76,"style":76},"language-ts shiki shiki-themes github-light github-dark","useSeoMeta({\n  title: () => post.value?.title,\n  description: () => post.value?.seo?.description || post.value?.summary,\n  \u002F\u002F Open Graph — controls previews on LinkedIn, Slack, iMessage, etc.\n  ogTitle: () => post.value?.title,\n  ogDescription: () => post.value?.seo?.description || post.value?.summary,\n  ogImage: () => post.value?.seo?.[\"og:image\"] || \"\",\n  ogType: \"article\",\n  \u002F\u002F Twitter \u002F X Card\n  twitterCard: \"summary_large_image\",\n  twitterTitle: () => post.value?.title,\n  twitterDescription: () => post.value?.seo?.description || post.value?.summary,\n});\n","ts",[78,2101,2102,2110,2124,2141,2146,2157,2172,2198,2208,2213,2223,2234,2249],{"__ignoreMap":76},[81,2103,2104,2107],{"class":83,"line":84},[81,2105,2106],{"class":883},"useSeoMeta",[81,2108,2109],{"class":887},"({\n",[81,2111,2112,2115,2118,2121],{"class":83,"line":90},[81,2113,2114],{"class":883},"  title",[81,2116,2117],{"class":887},": () ",[81,2119,2120],{"class":879},"=>",[81,2122,2123],{"class":887}," post.value?.title,\n",[81,2125,2126,2128,2130,2132,2135,2138],{"class":83,"line":96},[81,2127,2025],{"class":883},[81,2129,2117],{"class":887},[81,2131,2120],{"class":879},[81,2133,2134],{"class":887}," post.value?.seo?.description ",[81,2136,2137],{"class":879},"||",[81,2139,2140],{"class":887}," post.value?.summary,\n",[81,2142,2143],{"class":83,"line":102},[81,2144,2145],{"class":1936},"  \u002F\u002F Open Graph — controls previews on LinkedIn, Slack, iMessage, etc.\n",[81,2147,2148,2151,2153,2155],{"class":83,"line":108},[81,2149,2150],{"class":883},"  ogTitle",[81,2152,2117],{"class":887},[81,2154,2120],{"class":879},[81,2156,2123],{"class":887},[81,2158,2159,2162,2164,2166,2168,2170],{"class":83,"line":114},[81,2160,2161],{"class":883},"  ogDescription",[81,2163,2117],{"class":887},[81,2165,2120],{"class":879},[81,2167,2134],{"class":887},[81,2169,2137],{"class":879},[81,2171,2140],{"class":887},[81,2173,2174,2177,2179,2181,2184,2187,2190,2192,2195],{"class":83,"line":120},[81,2175,2176],{"class":883},"  ogImage",[81,2178,2117],{"class":887},[81,2180,2120],{"class":879},[81,2182,2183],{"class":887}," post.value?.seo?.[",[81,2185,2186],{"class":994},"\"og:image\"",[81,2188,2189],{"class":887},"] ",[81,2191,2137],{"class":879},[81,2193,2194],{"class":994}," \"\"",[81,2196,2197],{"class":887},",\n",[81,2199,2200,2203,2206],{"class":83,"line":127},[81,2201,2202],{"class":887},"  ogType: ",[81,2204,2205],{"class":994},"\"article\"",[81,2207,2197],{"class":887},[81,2209,2210],{"class":83,"line":2022},[81,2211,2212],{"class":1936},"  \u002F\u002F Twitter \u002F X Card\n",[81,2214,2215,2218,2221],{"class":83,"line":2033},[81,2216,2217],{"class":887},"  twitterCard: ",[81,2219,2220],{"class":994},"\"summary_large_image\"",[81,2222,2197],{"class":887},[81,2224,2225,2228,2230,2232],{"class":83,"line":2052},[81,2226,2227],{"class":883},"  twitterTitle",[81,2229,2117],{"class":887},[81,2231,2120],{"class":879},[81,2233,2123],{"class":887},[81,2235,2236,2239,2241,2243,2245,2247],{"class":83,"line":2063},[81,2237,2238],{"class":883},"  twitterDescription",[81,2240,2117],{"class":887},[81,2242,2120],{"class":879},[81,2244,2134],{"class":887},[81,2246,2137],{"class":879},[81,2248,2140],{"class":887},[81,2250,2252],{"class":83,"line":2251},13,[81,2253,2254],{"class":887},"});\n",[34,2256,2258],{"id":2257},"fallback-chain-for-description","Fallback chain for description",[12,2260,2261,2262,2265,2266,2268,2269,2271,2272,2274,2275,2277],{},"The ",[78,2263,2264],{},"seo.description"," field is optional. When it is absent, ",[78,2267,2106],{}," falls back to the post's ",[78,2270,1955],{},". This means every post gets a meaningful social preview as long as ",[78,2273,1955],{}," is set — even without a dedicated ",[78,2276,2016],{}," block.",[34,2279,2281],{"id":2280},"ogimage","og:image",[12,2283,2284,2285,2287,2288,2291,2292,2295],{},"If you provide an ",[78,2286,2281],{}," URL in the frontmatter, it will appear as the preview image when the post is shared on social platforms. The URL must be ",[1895,2289,2290],{},"absolute"," (e.g. ",[78,2293,2294],{},"https:\u002F\u002Fexample.com\u002Fcover.jpg",") — relative paths are not fetched by social crawlers.",[16,2297,2299],{"id":2298},"markdown-features","Markdown Features",[12,2301,2302],{},"Standard Markdown is fully supported inside the post body:",[34,2304,2306],{"id":2305},"headings","Headings",[71,2308,2312],{"className":2309,"code":2310,"language":2311,"meta":76,"style":76},"language-markdown shiki shiki-themes github-light github-dark","## H2 heading\n### H3 heading (also appears in the table of contents)\n","markdown",[78,2313,2314,2319],{"__ignoreMap":76},[81,2315,2316],{"class":83,"line":84},[81,2317,2318],{},"## H2 heading\n",[81,2320,2321],{"class":83,"line":90},[81,2322,2323],{},"### H3 heading (also appears in the table of contents)\n",[34,2325,2327],{"id":2326},"code-blocks","Code Blocks",[12,2329,2330],{},"Fenced code blocks with language hints get syntax highlighting automatically:",[71,2332,2334],{"className":2309,"code":2333,"language":2311,"meta":76,"style":76},"```ts\nconst greeting = (name: string) => `Hello, ${name}!`\n```\n",[78,2335,2336,2341,2346],{"__ignoreMap":76},[81,2337,2338],{"class":83,"line":84},[81,2339,2340],{},"```ts\n",[81,2342,2343],{"class":83,"line":90},[81,2344,2345],{},"const greeting = (name: string) => `Hello, ${name}!`\n",[81,2347,2348],{"class":83,"line":96},[81,2349,2350],{},"```\n",[34,2352,2354],{"id":2353},"lists-bold-italic","Lists, Bold, Italic",[71,2356,2358],{"className":2309,"code":2357,"language":2311,"meta":76,"style":76},"- item one\n- **bold text**\n- _italic text_\n",[78,2359,2360,2365,2370],{"__ignoreMap":76},[81,2361,2362],{"class":83,"line":84},[81,2363,2364],{},"- item one\n",[81,2366,2367],{"class":83,"line":90},[81,2368,2369],{},"- **bold text**\n",[81,2371,2372],{"class":83,"line":96},[81,2373,2374],{},"- _italic text_\n",[34,2376,2378],{"id":2377},"links","Links",[71,2380,2382],{"className":2309,"code":2381,"language":2311,"meta":76,"style":76},"[Link text](https:\u002F\u002Fexample.com)\n",[78,2383,2384],{"__ignoreMap":76},[81,2385,2386],{"class":83,"line":84},[81,2387,2381],{},[16,2389,2391],{"id":2390},"sitemap","Sitemap",[12,2393,2394,2395,2398,2399,2402,2403,2406],{},"Published posts are included in ",[78,2396,2397],{},"\u002Fsitemap.xml"," automatically. A server endpoint queries all posts with ",[78,2400,2401],{},"status: \"published\""," and passes them to ",[78,2404,2405],{},"@nuxtjs\u002Fsitemap",", which pre-renders the sitemap file at build time. Draft posts are excluded.",[161,2408,2409],{},"html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}",{"title":76,"searchDepth":90,"depth":96,"links":2411},[2412,2413,2416,2420,2426],{"id":1874,"depth":90,"text":1875},{"id":1905,"depth":90,"text":1906,"children":2414},[2415],{"id":2075,"depth":96,"text":2076},{"id":2086,"depth":90,"text":2087,"children":2417},[2418,2419],{"id":2257,"depth":96,"text":2258},{"id":2280,"depth":96,"text":2281},{"id":2298,"depth":90,"text":2299,"children":2421},[2422,2423,2424,2425],{"id":2305,"depth":96,"text":2306},{"id":2326,"depth":96,"text":2327},{"id":2353,"depth":96,"text":2354},{"id":2377,"depth":96,"text":2378},{"id":2390,"depth":90,"text":2391},"2026-03-22",{},"\u002Fblog\u002Fnuxt-content-example",{"description":2431,"keywords":2432,"title":1866},"Learn how this Nuxt 4 blog works — Markdown posts, frontmatter schema, Zod validation, and automatic Open Graph and Twitter Card meta tags via useSeoMeta.",[2433,2434,2435,2106,2436],"Nuxt Content","Markdown blog","Open Graph","frontmatter","nuxt-content-example","blog\u002Fnuxt-content-example","A practical walkthrough of how this blog works — writing posts in Markdown, the frontmatter schema, and how SEO and Open Graph tags are generated automatically from post metadata.",[1371,678,2441,562],"Content Management","0U4u9FLqde-XiMBfzMtlSRokC1NaN55sN0oITa9wQLI",{"id":2444,"title":2445,"author":7,"body":2446,"date":2550,"description":14,"extension":175,"meta":2551,"navigation":123,"path":2552,"seo":2553,"slug":2560,"status":187,"stem":2561,"summary":189,"tags":2562,"__hash__":2563},"blog\u002Fblog\u002Freactive-programming-concepts.md","Reactive Programming Concepts",{"type":9,"value":2447,"toc":2540},[2448,2450,2452,2454,2456,2458,2460,2462,2474,2476,2478,2480,2482,2518,2520,2522,2532,2534,2536,2538],[12,2449,14],{},[16,2451,19],{"id":18},[12,2453,22],{},[12,2455,25],{},[16,2457,29],{"id":28},[12,2459,32],{},[34,2461,37],{"id":36},[39,2463,2464,2466,2468,2470,2472],{},[42,2465,44],{},[42,2467,47],{},[42,2469,50],{},[42,2471,53],{},[42,2473,56],{},[16,2475,60],{"id":59},[12,2477,63],{},[12,2479,14],{},[16,2481,69],{"id":68},[71,2483,2484],{"className":73,"code":74,"language":75,"meta":76,"style":76},[78,2485,2486,2490,2494,2498,2502,2506,2510,2514],{"__ignoreMap":76},[81,2487,2488],{"class":83,"line":84},[81,2489,87],{},[81,2491,2492],{"class":83,"line":90},[81,2493,93],{},[81,2495,2496],{"class":83,"line":96},[81,2497,99],{},[81,2499,2500],{"class":83,"line":102},[81,2501,105],{},[81,2503,2504],{"class":83,"line":108},[81,2505,111],{},[81,2507,2508],{"class":83,"line":114},[81,2509,117],{},[81,2511,2512],{"class":83,"line":120},[81,2513,124],{"emptyLinePlaceholder":123},[81,2515,2516],{"class":83,"line":127},[81,2517,130],{},[16,2519,134],{"id":133},[12,2521,22],{},[138,2523,2524,2526,2528,2530],{},[42,2525,142],{},[42,2527,145],{},[42,2529,148],{},[42,2531,151],{},[16,2533,155],{"id":154},[12,2535,25],{},[12,2537,32],{},[161,2539,163],{},{"title":76,"searchDepth":90,"depth":96,"links":2541},[2542,2543,2546,2547,2548,2549],{"id":18,"depth":90,"text":19},{"id":28,"depth":90,"text":29,"children":2544},[2545],{"id":36,"depth":96,"text":37},{"id":59,"depth":90,"text":60},{"id":68,"depth":90,"text":69},{"id":133,"depth":90,"text":134},{"id":154,"depth":90,"text":155},"2025-06-25",{"url":2552},"\u002Fblog\u002Freactive-programming-concepts",{"description":2554,"keywords":2555,"title":2445},"An introduction to reactive programming — observables, streams, operators, and how RxJS brings reactive patterns to JavaScript.",[2556,2557,2558,1127,2559],"Reactive Programming","RxJS","Observables","Streams","reactive-programming-concepts","blog\u002Freactive-programming-concepts",[556,1249,1247],"N0iF9ZlVOOx9xnKRqOiMJhUiH5reknCvOaDngQ-OHMY",{"id":2565,"title":2566,"author":7,"body":2567,"date":2671,"description":14,"extension":175,"meta":2672,"navigation":123,"path":2673,"seo":2674,"slug":2682,"status":187,"stem":2683,"summary":189,"tags":2684,"__hash__":2685},"blog\u002Fblog\u002Fsecurity-best-practices-for-web.md","Security Best Practices for Web",{"type":9,"value":2568,"toc":2661},[2569,2571,2573,2575,2577,2579,2581,2583,2595,2597,2599,2601,2603,2639,2641,2643,2653,2655,2657,2659],[12,2570,14],{},[16,2572,19],{"id":18},[12,2574,22],{},[12,2576,25],{},[16,2578,29],{"id":28},[12,2580,32],{},[34,2582,37],{"id":36},[39,2584,2585,2587,2589,2591,2593],{},[42,2586,44],{},[42,2588,47],{},[42,2590,50],{},[42,2592,53],{},[42,2594,56],{},[16,2596,60],{"id":59},[12,2598,63],{},[12,2600,14],{},[16,2602,69],{"id":68},[71,2604,2605],{"className":73,"code":74,"language":75,"meta":76,"style":76},[78,2606,2607,2611,2615,2619,2623,2627,2631,2635],{"__ignoreMap":76},[81,2608,2609],{"class":83,"line":84},[81,2610,87],{},[81,2612,2613],{"class":83,"line":90},[81,2614,93],{},[81,2616,2617],{"class":83,"line":96},[81,2618,99],{},[81,2620,2621],{"class":83,"line":102},[81,2622,105],{},[81,2624,2625],{"class":83,"line":108},[81,2626,111],{},[81,2628,2629],{"class":83,"line":114},[81,2630,117],{},[81,2632,2633],{"class":83,"line":120},[81,2634,124],{"emptyLinePlaceholder":123},[81,2636,2637],{"class":83,"line":127},[81,2638,130],{},[16,2640,134],{"id":133},[12,2642,22],{},[138,2644,2645,2647,2649,2651],{},[42,2646,142],{},[42,2648,145],{},[42,2650,148],{},[42,2652,151],{},[16,2654,155],{"id":154},[12,2656,25],{},[12,2658,32],{},[161,2660,163],{},{"title":76,"searchDepth":90,"depth":96,"links":2662},[2663,2664,2667,2668,2669,2670],{"id":18,"depth":90,"text":19},{"id":28,"depth":90,"text":29,"children":2665},[2666],{"id":36,"depth":96,"text":37},{"id":59,"depth":90,"text":60},{"id":68,"depth":90,"text":69},{"id":133,"depth":90,"text":134},{"id":154,"depth":90,"text":155},"2025-07-23",{"url":2673},"\u002Fblog\u002Fsecurity-best-practices-for-web",{"description":2675,"keywords":2676,"title":2566},"Essential web security practices — preventing XSS, CSRF, SQL injection, securing authentication flows, and following OWASP guidelines.",[2677,2678,2679,2680,2681],"Web Security","OWASP","XSS","Authentication","CSRF","security-best-practices-for-web","blog\u002Fsecurity-best-practices-for-web",[1738,1739,1740],"7wj8zqy1cikHh9gquEskeUzhr1jXwynIaicnlNVT_7w",{"id":2687,"title":2688,"author":7,"body":2689,"date":2793,"description":14,"extension":175,"meta":2794,"navigation":123,"path":2795,"seo":2796,"slug":2802,"status":187,"stem":2803,"summary":189,"tags":2804,"__hash__":2805},"blog\u002Fblog\u002Fstate-management-best-practices.md","State Management Best Practices",{"type":9,"value":2690,"toc":2783},[2691,2693,2695,2697,2699,2701,2703,2705,2717,2719,2721,2723,2725,2761,2763,2765,2775,2777,2779,2781],[12,2692,14],{},[16,2694,19],{"id":18},[12,2696,22],{},[12,2698,25],{},[16,2700,29],{"id":28},[12,2702,32],{},[34,2704,37],{"id":36},[39,2706,2707,2709,2711,2713,2715],{},[42,2708,44],{},[42,2710,47],{},[42,2712,50],{},[42,2714,53],{},[42,2716,56],{},[16,2718,60],{"id":59},[12,2720,63],{},[12,2722,14],{},[16,2724,69],{"id":68},[71,2726,2727],{"className":73,"code":74,"language":75,"meta":76,"style":76},[78,2728,2729,2733,2737,2741,2745,2749,2753,2757],{"__ignoreMap":76},[81,2730,2731],{"class":83,"line":84},[81,2732,87],{},[81,2734,2735],{"class":83,"line":90},[81,2736,93],{},[81,2738,2739],{"class":83,"line":96},[81,2740,99],{},[81,2742,2743],{"class":83,"line":102},[81,2744,105],{},[81,2746,2747],{"class":83,"line":108},[81,2748,111],{},[81,2750,2751],{"class":83,"line":114},[81,2752,117],{},[81,2754,2755],{"class":83,"line":120},[81,2756,124],{"emptyLinePlaceholder":123},[81,2758,2759],{"class":83,"line":127},[81,2760,130],{},[16,2762,134],{"id":133},[12,2764,22],{},[138,2766,2767,2769,2771,2773],{},[42,2768,142],{},[42,2770,145],{},[42,2772,148],{},[42,2774,151],{},[16,2776,155],{"id":154},[12,2778,25],{},[12,2780,32],{},[161,2782,163],{},{"title":76,"searchDepth":90,"depth":96,"links":2784},[2785,2786,2789,2790,2791,2792],{"id":18,"depth":90,"text":19},{"id":28,"depth":90,"text":29,"children":2787},[2788],{"id":36,"depth":96,"text":37},{"id":59,"depth":90,"text":60},{"id":68,"depth":90,"text":69},{"id":133,"depth":90,"text":134},{"id":154,"depth":90,"text":155},"2025-09-03",{"url":2795},"\u002Fblog\u002Fstate-management-best-practices",{"description":2797,"keywords":2798,"title":2688},"How to manage application state effectively — comparing Pinia, Vuex, and reactive composables, with patterns for avoiding common pitfalls.",[2799,2800,2801,678,1862],"State Management","Pinia","Vuex","state-management-best-practices","blog\u002Fstate-management-best-practices",[315,316,134],"-PlQPjj8xcFu0eIHyk1R-frqpk1jpkihDFbKocHJVSQ",{"id":2807,"title":2808,"author":7,"body":2809,"date":2913,"description":14,"extension":175,"meta":2914,"navigation":123,"path":2915,"seo":2916,"slug":2923,"status":187,"stem":2924,"summary":189,"tags":2925,"__hash__":2926},"blog\u002Fblog\u002Ftesting-strategies-for-modern-apps.md","Testing Strategies for Modern Apps",{"type":9,"value":2810,"toc":2903},[2811,2813,2815,2817,2819,2821,2823,2825,2837,2839,2841,2843,2845,2881,2883,2885,2895,2897,2899,2901],[12,2812,14],{},[16,2814,19],{"id":18},[12,2816,22],{},[12,2818,25],{},[16,2820,29],{"id":28},[12,2822,32],{},[34,2824,37],{"id":36},[39,2826,2827,2829,2831,2833,2835],{},[42,2828,44],{},[42,2830,47],{},[42,2832,50],{},[42,2834,53],{},[42,2836,56],{},[16,2838,60],{"id":59},[12,2840,63],{},[12,2842,14],{},[16,2844,69],{"id":68},[71,2846,2847],{"className":73,"code":74,"language":75,"meta":76,"style":76},[78,2848,2849,2853,2857,2861,2865,2869,2873,2877],{"__ignoreMap":76},[81,2850,2851],{"class":83,"line":84},[81,2852,87],{},[81,2854,2855],{"class":83,"line":90},[81,2856,93],{},[81,2858,2859],{"class":83,"line":96},[81,2860,99],{},[81,2862,2863],{"class":83,"line":102},[81,2864,105],{},[81,2866,2867],{"class":83,"line":108},[81,2868,111],{},[81,2870,2871],{"class":83,"line":114},[81,2872,117],{},[81,2874,2875],{"class":83,"line":120},[81,2876,124],{"emptyLinePlaceholder":123},[81,2878,2879],{"class":83,"line":127},[81,2880,130],{},[16,2882,134],{"id":133},[12,2884,22],{},[138,2886,2887,2889,2891,2893],{},[42,2888,142],{},[42,2890,145],{},[42,2892,148],{},[42,2894,151],{},[16,2896,155],{"id":154},[12,2898,25],{},[12,2900,32],{},[161,2902,163],{},{"title":76,"searchDepth":90,"depth":96,"links":2904},[2905,2906,2909,2910,2911,2912],{"id":18,"depth":90,"text":19},{"id":28,"depth":90,"text":29,"children":2907},[2908],{"id":36,"depth":96,"text":37},{"id":59,"depth":90,"text":60},{"id":68,"depth":90,"text":69},{"id":133,"depth":90,"text":134},{"id":154,"depth":90,"text":155},"2025-08-20",{"url":2915},"\u002Fblog\u002Ftesting-strategies-for-modern-apps",{"description":2917,"keywords":2918,"title":2808},"A comprehensive guide to testing modern web apps — unit tests, integration tests, end-to-end tests, and how to balance coverage with confidence.",[191,2919,2920,2921,2922],"Vitest","Unit Testing","TDD","End-to-End Testing","testing-strategies-for-modern-apps","blog\u002Ftesting-strategies-for-modern-apps",[434,561,562],"Olg3bTC_F-4ikHeF4E_dEcSQ9bsPp4bkaLKIy8tsCJw",{"id":2928,"title":2929,"author":7,"body":2930,"date":3034,"description":14,"extension":175,"meta":3035,"navigation":123,"path":3036,"seo":3037,"slug":3042,"status":187,"stem":3043,"summary":189,"tags":3044,"__hash__":3045},"blog\u002Fblog\u002Fthe-future-of-javascript-frameworks.md","The Future of JavaScript Frameworks",{"type":9,"value":2931,"toc":3024},[2932,2934,2936,2938,2940,2942,2944,2946,2958,2960,2962,2964,2966,3002,3004,3006,3016,3018,3020,3022],[12,2933,14],{},[16,2935,19],{"id":18},[12,2937,22],{},[12,2939,25],{},[16,2941,29],{"id":28},[12,2943,32],{},[34,2945,37],{"id":36},[39,2947,2948,2950,2952,2954,2956],{},[42,2949,44],{},[42,2951,47],{},[42,2953,50],{},[42,2955,53],{},[42,2957,56],{},[16,2959,60],{"id":59},[12,2961,63],{},[12,2963,14],{},[16,2965,69],{"id":68},[71,2967,2968],{"className":73,"code":74,"language":75,"meta":76,"style":76},[78,2969,2970,2974,2978,2982,2986,2990,2994,2998],{"__ignoreMap":76},[81,2971,2972],{"class":83,"line":84},[81,2973,87],{},[81,2975,2976],{"class":83,"line":90},[81,2977,93],{},[81,2979,2980],{"class":83,"line":96},[81,2981,99],{},[81,2983,2984],{"class":83,"line":102},[81,2985,105],{},[81,2987,2988],{"class":83,"line":108},[81,2989,111],{},[81,2991,2992],{"class":83,"line":114},[81,2993,117],{},[81,2995,2996],{"class":83,"line":120},[81,2997,124],{"emptyLinePlaceholder":123},[81,2999,3000],{"class":83,"line":127},[81,3001,130],{},[16,3003,134],{"id":133},[12,3005,22],{},[138,3007,3008,3010,3012,3014],{},[42,3009,142],{},[42,3011,145],{},[42,3013,148],{},[42,3015,151],{},[16,3017,155],{"id":154},[12,3019,25],{},[12,3021,32],{},[161,3023,163],{},{"title":76,"searchDepth":90,"depth":96,"links":3025},[3026,3027,3030,3031,3032,3033],{"id":18,"depth":90,"text":19},{"id":28,"depth":90,"text":29,"children":3028},[3029],{"id":36,"depth":96,"text":37},{"id":59,"depth":90,"text":60},{"id":68,"depth":90,"text":69},{"id":133,"depth":90,"text":134},{"id":154,"depth":90,"text":155},"2026-01-08",{"url":3036},"\u002Fblog\u002Fthe-future-of-javascript-frameworks",{"description":3038,"keywords":3039,"title":2929},"Where JavaScript frameworks are headed — signals, server components, partial hydration, and what Vue, React, and Svelte are converging on.",[3040,678,679,3041,1862],"JavaScript Frameworks","Svelte","the-future-of-javascript-frameworks","blog\u002Fthe-future-of-javascript-frameworks",[678,679,685],"x6ekKM3rAVZy8dZ5e-HCSXo9zxpNe-DSyZce5hzFI2w",{"id":3047,"title":3048,"author":7,"body":3049,"date":3153,"description":14,"extension":175,"meta":3154,"navigation":123,"path":3155,"seo":3156,"slug":3164,"status":187,"stem":3165,"summary":189,"tags":3166,"__hash__":3167},"blog\u002Fblog\u002Fthe-power-of-progressive-web-apps.md","The Power of Progressive Web Apps",{"type":9,"value":3050,"toc":3143},[3051,3053,3055,3057,3059,3061,3063,3065,3077,3079,3081,3083,3085,3121,3123,3125,3135,3137,3139,3141],[12,3052,14],{},[16,3054,19],{"id":18},[12,3056,22],{},[12,3058,25],{},[16,3060,29],{"id":28},[12,3062,32],{},[34,3064,37],{"id":36},[39,3066,3067,3069,3071,3073,3075],{},[42,3068,44],{},[42,3070,47],{},[42,3072,50],{},[42,3074,53],{},[42,3076,56],{},[16,3078,60],{"id":59},[12,3080,63],{},[12,3082,14],{},[16,3084,69],{"id":68},[71,3086,3087],{"className":73,"code":74,"language":75,"meta":76,"style":76},[78,3088,3089,3093,3097,3101,3105,3109,3113,3117],{"__ignoreMap":76},[81,3090,3091],{"class":83,"line":84},[81,3092,87],{},[81,3094,3095],{"class":83,"line":90},[81,3096,93],{},[81,3098,3099],{"class":83,"line":96},[81,3100,99],{},[81,3102,3103],{"class":83,"line":102},[81,3104,105],{},[81,3106,3107],{"class":83,"line":108},[81,3108,111],{},[81,3110,3111],{"class":83,"line":114},[81,3112,117],{},[81,3114,3115],{"class":83,"line":120},[81,3116,124],{"emptyLinePlaceholder":123},[81,3118,3119],{"class":83,"line":127},[81,3120,130],{},[16,3122,134],{"id":133},[12,3124,22],{},[138,3126,3127,3129,3131,3133],{},[42,3128,142],{},[42,3130,145],{},[42,3132,148],{},[42,3134,151],{},[16,3136,155],{"id":154},[12,3138,25],{},[12,3140,32],{},[161,3142,163],{},{"title":76,"searchDepth":90,"depth":96,"links":3144},[3145,3146,3149,3150,3151,3152],{"id":18,"depth":90,"text":19},{"id":28,"depth":90,"text":29,"children":3147},[3148],{"id":36,"depth":96,"text":37},{"id":59,"depth":90,"text":60},{"id":68,"depth":90,"text":69},{"id":133,"depth":90,"text":134},{"id":154,"depth":90,"text":155},"2025-10-01",{"url":3155},"\u002Fblog\u002Fthe-power-of-progressive-web-apps",{"description":3157,"keywords":3158,"title":3048},"How Progressive Web Apps bring app-like experiences to the browser — service workers, offline support, push notifications, and installability.",[3159,3160,3161,3162,3163],"PWA","Progressive Web Apps","Service Workers","Offline","Mobile","the-power-of-progressive-web-apps","blog\u002Fthe-power-of-progressive-web-apps",[1127,1861,1862],"eeAsXKCv9M5HzjxfH0omhe0Aqp-sJ4kR6nCWY_a2Q5E",{"id":3169,"title":3170,"author":7,"body":3171,"date":3275,"description":14,"extension":175,"meta":3276,"navigation":123,"path":3277,"seo":3278,"slug":3283,"status":187,"stem":3284,"summary":189,"tags":3285,"__hash__":3286},"blog\u002Fblog\u002Funderstanding-modern-web-development.md","Understanding Modern Web Development",{"type":9,"value":3172,"toc":3265},[3173,3175,3177,3179,3181,3183,3185,3187,3199,3201,3203,3205,3207,3243,3245,3247,3257,3259,3261,3263],[12,3174,14],{},[16,3176,19],{"id":18},[12,3178,22],{},[12,3180,25],{},[16,3182,29],{"id":28},[12,3184,32],{},[34,3186,37],{"id":36},[39,3188,3189,3191,3193,3195,3197],{},[42,3190,44],{},[42,3192,47],{},[42,3194,50],{},[42,3196,53],{},[42,3198,56],{},[16,3200,60],{"id":59},[12,3202,63],{},[12,3204,14],{},[16,3206,69],{"id":68},[71,3208,3209],{"className":73,"code":74,"language":75,"meta":76,"style":76},[78,3210,3211,3215,3219,3223,3227,3231,3235,3239],{"__ignoreMap":76},[81,3212,3213],{"class":83,"line":84},[81,3214,87],{},[81,3216,3217],{"class":83,"line":90},[81,3218,93],{},[81,3220,3221],{"class":83,"line":96},[81,3222,99],{},[81,3224,3225],{"class":83,"line":102},[81,3226,105],{},[81,3228,3229],{"class":83,"line":108},[81,3230,111],{},[81,3232,3233],{"class":83,"line":114},[81,3234,117],{},[81,3236,3237],{"class":83,"line":120},[81,3238,124],{"emptyLinePlaceholder":123},[81,3240,3241],{"class":83,"line":127},[81,3242,130],{},[16,3244,134],{"id":133},[12,3246,22],{},[138,3248,3249,3251,3253,3255],{},[42,3250,142],{},[42,3252,145],{},[42,3254,148],{},[42,3256,151],{},[16,3258,155],{"id":154},[12,3260,25],{},[12,3262,32],{},[161,3264,163],{},{"title":76,"searchDepth":90,"depth":96,"links":3266},[3267,3268,3271,3272,3273,3274],{"id":18,"depth":90,"text":19},{"id":28,"depth":90,"text":29,"children":3269},[3270],{"id":36,"depth":96,"text":37},{"id":59,"depth":90,"text":60},{"id":68,"depth":90,"text":69},{"id":133,"depth":90,"text":134},{"id":154,"depth":90,"text":155},"2026-01-22",{"url":3277},"\u002Fblog\u002Funderstanding-modern-web-development",{"description":3279,"keywords":3280,"title":3170},"A broad overview of the modern web development landscape — tooling, frameworks, the JAMstack, and how front-end and back-end have evolved.",[1861,1127,3281,1862,3282],"JAMstack","Modern Web","understanding-modern-web-development","blog\u002Funderstanding-modern-web-development",[1127,1861,1862],"xrl1EFLh-JMRWCzxDol_no4o4AiSEj3ML5KiIRDxq70",{"id":3288,"title":3289,"author":7,"body":3290,"date":3748,"description":3294,"extension":175,"meta":3749,"navigation":123,"path":3750,"seo":3751,"slug":3756,"status":187,"stem":3757,"summary":3758,"tags":3759,"__hash__":3761},"blog\u002Fblog\u002Fupgrading-to-vite-8-with-nuxt.md","Upgrading to Vite 8 in a Nuxt Project",{"type":9,"value":3291,"toc":3736},[3292,3295,3299,3310,3321,3331,3335,3344,3383,3386,3401,3407,3423,3429,3433,3436,3451,3454,3460,3467,3471,3474,3478,3495,3498,3539,3546,3550,3561,3565,3568,3633,3636,3640,3643,3682,3685,3689,3695,3722,3733],[12,3293,3294],{},"Vite 8 is out, and it's not a small release. The entire build pipeline has been replaced — esbuild and Rollup are out, Rolldown and Oxc are in. For most projects, the upgrade is seamless. But if you're on Nuxt, there's a catch you need to know about before you do anything.",[16,3296,3298],{"id":3297},"the-problem-with-nuxt-and-vite-versions","The Problem with Nuxt and Vite Versions",[12,3300,3301,3302,3305,3306,3309],{},"If you look at your Nuxt project's ",[78,3303,3304],{},"package.json",", you won't find a ",[78,3307,3308],{},"vite"," entry. That's because Nuxt manages Vite as an internal dependency — it ships its own version of Vite and handles all Vite configuration internally.",[12,3311,3312,3313,3316,3317,3320],{},"This means running ",[78,3314,3315],{},"npm install vite@8"," won't do what you want. npm will install Vite 8 in your ",[78,3318,3319],{},"node_modules",", but Nuxt will continue using its own bundled version. You'd end up with two copies of Vite and no actual upgrade.",[12,3322,3323,3324,3327,3328,3330],{},"The correct approach is to use npm's ",[78,3325,3326],{},"overrides"," field, which forces every package in your dependency tree — including Nuxt — to resolve ",[78,3329,3308],{}," to the version you specify.",[16,3332,3334],{"id":3333},"the-fix","The Fix",[12,3336,3337,3338,3340,3341,3343],{},"Open your ",[78,3339,3304],{}," and add an ",[78,3342,3326],{}," field at the top level:",[71,3345,3349],{"className":3346,"code":3347,"language":3348,"meta":76,"style":76},"language-json shiki shiki-themes github-light github-dark","{\n  \"overrides\": {\n    \"vite\": \"^8.0.0\"\n  }\n}\n","json",[78,3350,3351,3356,3364,3374,3379],{"__ignoreMap":76},[81,3352,3353],{"class":83,"line":84},[81,3354,3355],{"class":887},"{\n",[81,3357,3358,3361],{"class":83,"line":90},[81,3359,3360],{"class":917},"  \"overrides\"",[81,3362,3363],{"class":887},": {\n",[81,3365,3366,3369,3371],{"class":83,"line":96},[81,3367,3368],{"class":917},"    \"vite\"",[81,3370,1930],{"class":887},[81,3372,3373],{"class":994},"\"^8.0.0\"\n",[81,3375,3376],{"class":83,"line":102},[81,3377,3378],{"class":887},"  }\n",[81,3380,3381],{"class":83,"line":108},[81,3382,117],{"class":887},[12,3384,3385],{},"Then run:",[71,3387,3391],{"className":3388,"code":3389,"language":3390,"meta":76,"style":76},"language-bash shiki shiki-themes github-light github-dark","npm install\n","bash",[78,3392,3393],{"__ignoreMap":76},[81,3394,3395,3398],{"class":83,"line":84},[81,3396,3397],{"class":883},"npm",[81,3399,3400],{"class":994}," install\n",[12,3402,3403,3404,3406],{},"That's it. npm will now resolve all ",[78,3405,3308],{}," imports across your entire dependency tree to Vite 8. You can confirm it worked by checking the installed version:",[71,3408,3410],{"className":3388,"code":3409,"language":3390,"meta":76,"style":76},"node -e \"console.log(require('.\u002Fnode_modules\u002Fvite\u002Fpackage.json').version)\"\n",[78,3411,3412],{"__ignoreMap":76},[81,3413,3414,3417,3420],{"class":83,"line":84},[81,3415,3416],{"class":883},"node",[81,3418,3419],{"class":917}," -e",[81,3421,3422],{"class":994}," \"console.log(require('.\u002Fnode_modules\u002Fvite\u002Fpackage.json').version)\"\n",[12,3424,3425,3426,945],{},"You should see ",[78,3427,3428],{},"8.0.0",[16,3430,3432],{"id":3431},"verifying-the-build","Verifying the Build",[12,3434,3435],{},"Run your production build to make sure everything works:",[71,3437,3439],{"className":3388,"code":3438,"language":3390,"meta":76,"style":76},"npm run build\n",[78,3440,3441],{"__ignoreMap":76},[81,3442,3443,3445,3448],{"class":83,"line":84},[81,3444,3397],{"class":883},[81,3446,3447],{"class":994}," run",[81,3449,3450],{"class":994}," build\n",[12,3452,3453],{},"If the upgrade is successful, you'll see Vite's version reported in Nuxt's build output:",[71,3455,3458],{"className":3456,"code":3457,"language":1888},[1886],"Nuxt 4.4.2 (with Nitro 2.13.1, Vite 8.0.0 and Vue 3.5.30)\n",[78,3459,3457],{"__ignoreMap":76},[12,3461,3462,3463,3466],{},"For this project — a Nuxt 4 blog using ",[78,3464,3465],{},"@nuxt\u002Fcontent",", Tailwind CSS v4, and DaisyUI — the build completed without any errors or warnings. The client built in ~2.9 seconds and the server in ~1.5 seconds.",[16,3468,3470],{"id":3469},"what-actually-changed-in-vite-8","What Actually Changed in Vite 8",[12,3472,3473],{},"Understanding what changed helps you know what to watch out for if you do run into issues.",[34,3475,3477],{"id":3476},"rolldown-replaces-rollup-and-esbuild","Rolldown replaces Rollup and esbuild",[12,3479,3480,3481,3488,3489,3494],{},"The biggest change in Vite 8 is that Rollup (used for production bundling) and esbuild (used for dependency pre-bundling and JS transforms) have been replaced by ",[3482,3483,3487],"a",{"href":3484,"rel":3485},"https:\u002F\u002Frolldown.rs\u002F",[3486],"nofollow","Rolldown"," — a new Rust-based bundler — and ",[3482,3490,3493],{"href":3491,"rel":3492},"https:\u002F\u002Foxc.rs\u002F",[3486],"Oxc"," for transforms and minification.",[12,3496,3497],{},"In practice, this means:",[39,3499,3500,3511,3521],{},[42,3501,3502,3507,3508],{},[1895,3503,3504],{},[78,3505,3506],{},"build.rollupOptions"," is now ",[78,3509,3510],{},"build.rolldownOptions",[42,3512,3513,3507,3518],{},[1895,3514,3515],{},[78,3516,3517],{},"optimizeDeps.esbuildOptions",[78,3519,3520],{},"optimizeDeps.rolldownOptions",[42,3522,3523,3532,3533,3528,3536],{},[1895,3524,3525,3528,3529],{},[78,3526,3527],{},"esbuild.jsx"," \u002F ",[78,3530,3531],{},"esbuild.define"," options move to ",[78,3534,3535],{},"oxc.jsx",[78,3537,3538],{},"oxc.define",[12,3540,3541,3542,3545],{},"If you have a custom ",[78,3543,3544],{},"vite.config.ts"," using any of these options, you'll need to update them. For a standard Nuxt project with no custom Vite config (like this one), none of this matters — Nuxt handles it internally.",[34,3547,3549],{"id":3548},"javascript-minification-now-uses-oxc","JavaScript minification now uses Oxc",[12,3551,3552,3553,3556,3557,3560],{},"The default JS minifier has switched from esbuild to Oxc Minifier. This is generally faster and produces similar output, but there's one limitation to be aware of: ",[1895,3554,3555],{},"Oxc does not support lowering native decorators",". If your code uses the ",[78,3558,3559],{},"@decorator"," syntax and you need it transpiled for older browsers, you'll need to add a Babel or SWC plugin as a workaround.",[34,3562,3564],{"id":3563},"browser-targets-have-been-raised","Browser targets have been raised",[12,3566,3567],{},"The minimum browser targets in Vite 8 are slightly higher:",[3569,3570,3571,3587],"table",{},[3572,3573,3574],"thead",{},[3575,3576,3577,3581,3584],"tr",{},[3578,3579,3580],"th",{},"Browser",[3578,3582,3583],{},"Vite 7",[3578,3585,3586],{},"Vite 8",[3588,3589,3590,3602,3611,3622],"tbody",{},[3575,3591,3592,3596,3599],{},[3593,3594,3595],"td",{},"Chrome",[3593,3597,3598],{},"107",[3593,3600,3601],{},"111",[3575,3603,3604,3607,3609],{},[3593,3605,3606],{},"Edge",[3593,3608,3598],{},[3593,3610,3601],{},[3575,3612,3613,3616,3619],{},[3593,3614,3615],{},"Firefox",[3593,3617,3618],{},"104",[3593,3620,3621],{},"114",[3575,3623,3624,3627,3630],{},[3593,3625,3626],{},"Safari",[3593,3628,3629],{},"16.0",[3593,3631,3632],{},"16.4",[12,3634,3635],{},"For most modern web apps this is a non-issue, but if you're targeting older browsers, double-check that your target audience falls within the new minimums.",[34,3637,3639],{"id":3638},"some-advanced-options-have-been-removed","Some advanced options have been removed",[12,3641,3642],{},"A few less commonly used features were dropped:",[39,3644,3645,3655,3668],{},[42,3646,2261,3647,3650,3651,3654],{},[78,3648,3649],{},"\"system\""," and ",[78,3652,3653],{},"\"amd\""," output formats are no longer supported",[42,3656,2261,3657,991,3660,3663,3664,3667],{},[78,3658,3659],{},"shouldTransformCachedModule",[78,3661,3662],{},"resolveImportMeta",", and ",[78,3665,3666],{},"renderDynamicImport"," plugin hooks have been removed",[42,3669,3670,3673,3674,3677,3678,3681],{},[78,3671,3672],{},"build()"," now throws a ",[78,3675,3676],{},"BundleError"," (with an ",[78,3679,3680],{},".errors"," property) instead of a raw error object",[12,3683,3684],{},"Again, for a typical Nuxt app you're unlikely to hit any of these.",[16,3686,3688],{"id":3687},"should-you-do-this","Should You Do This?",[12,3690,3691,3692,3694],{},"Nuxt 4.2.2 ships with Vite 7 by default. Using ",[78,3693,3326],{}," to force Vite 8 is a reasonable thing to do — it's the standard approach for testing ahead of official framework support — but it's worth knowing that:",[138,3696,3697,3707,3713],{},[42,3698,3699,3702,3703,3706],{},[1895,3700,3701],{},"It's not officially supported yet."," Nuxt hasn't cut a release with Vite 8. If something breaks after a future ",[78,3704,3705],{},"npm update",", the override is the first thing to check.",[42,3708,3709,3712],{},[1895,3710,3711],{},"It works fine for this project."," No issues encountered — the build is clean, dev server starts up, and all pages render correctly.",[42,3714,3715,3718,3719,3721],{},[1895,3716,3717],{},"Remove the override when Nuxt officially upgrades."," Once a Nuxt version ships with Vite 8 natively, you can drop the ",[78,3720,3326],{}," field and let Nuxt manage the version again.",[12,3723,3724,3725,3729,3730,3732],{},"The migration itself took less than five minutes. The harder part was understanding ",[3726,3727,3728],"em",{},"why"," ",[78,3731,3315],{}," doesn't work for a Nuxt project — and now you know.",[161,3734,3735],{},"html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}",{"title":76,"searchDepth":90,"depth":96,"links":3737},[3738,3739,3740,3741,3747],{"id":3297,"depth":90,"text":3298},{"id":3333,"depth":90,"text":3334},{"id":3431,"depth":90,"text":3432},{"id":3469,"depth":90,"text":3470,"children":3742},[3743,3744,3745,3746],{"id":3476,"depth":96,"text":3477},{"id":3548,"depth":96,"text":3549},{"id":3563,"depth":96,"text":3564},{"id":3638,"depth":96,"text":3639},{"id":3687,"depth":90,"text":3688},"2026-03-15",{},"\u002Fblog\u002Fupgrading-to-vite-8-with-nuxt",{"description":3752,"keywords":3753,"title":3289},"Step-by-step guide to upgrading a Nuxt 4 project to Vite 8 using npm overrides, including what changed in Vite 8 and how to verify the migration.",[3586,1371,3754,3755,3487,3493],"Vite upgrade","npm overrides","upgrading-to-vite-8-with-nuxt","blog\u002Fupgrading-to-vite-8-with-nuxt","Vite 8 ships with a completely new build engine under the hood. Here's how I upgraded my Nuxt blog to Vite 8, why a direct npm install won't work, and what actually changed.",[3760,1371,1127],"Vite","WjqxAKbo2n7U_jxyD8wYxmz_ovQBFWnf0z36erkebV8",1778492224479]