\n \u003C/div>\n\u003C/template> \u003C!-- app.vue -->\n\u003Ctemplate>\n \u003CNuxtLayout>\n \u003CNuxtPage />\n \u003C/NuxtLayout>\n\u003C/template> \u003C!-- pages/about.vue -->\n\u003Cscript setup lang=\"ts\">\ndefinePageMeta({\n layout: 'custom'\n})\n\u003C/script> html pre.shiki code .snYqZ, html code.shiki .snYqZ{--shiki-default:#A0ADA0;--shiki-dark:#758575DD}html pre.shiki code .si6no, html code.shiki .si6no{--shiki-default:#999999;--shiki-dark:#666666}html pre.shiki code .sTPum, html code.shiki .sTPum{--shiki-default:#1E754F;--shiki-dark:#4D9375}html pre.shiki code .s8w-G, html code.shiki .s8w-G{--shiki-default:#393A34;--shiki-dark:#DBD7CAEE}html pre.shiki code .sbEgt, html code.shiki .sbEgt{--shiki-default:#999999;--shiki-default-font-style:italic;--shiki-dark:#666666;--shiki-dark-font-style:italic}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 .s9nN2, html code.shiki .s9nN2{--shiki-default:#B07D48;--shiki-dark:#BD976A}html pre.shiki code .scnC2, html code.shiki .scnC2{--shiki-default:#B5695977;--shiki-dark:#C98A7D77}html pre.shiki code .spP0B, html code.shiki .spP0B{--shiki-default:#B56959;--shiki-dark:#C98A7D}html pre.shiki code .s_xSY, html code.shiki .s_xSY{--shiki-default:#59873A;--shiki-dark:#80A665}html pre.shiki code .sHLBJ, html code.shiki .sHLBJ{--shiki-default:#998418;--shiki-dark:#B8A965}",{"id":220,"title":221,"titles":222,"content":84,"level":17},"/en/concepts/meta","Meta",[],{"id":224,"title":221,"titles":225,"content":84,"level":17},"/en/concepts/meta#meta",[],{"id":227,"title":228,"titles":229,"content":230,"level":17},"/en/concepts/rendering-modes","Rendering Modes",[],"Nuxt supports various rendering modes.\nSpecifically, these include Universal Rendering, Client-Side Rendering, and Hybrid Rendering.",{"id":232,"title":228,"titles":233,"content":234,"level":17},"/en/concepts/rendering-modes#rendering-modes",[],"Nuxt supports various rendering modes.\nSpecifically, these include Universal Rendering, Client-Side Rendering, and Hybrid Rendering. By default, Universal Rendering is selected.\nThese modes can easily be switched via nuxt.config.",{"id":236,"title":237,"titles":238,"content":239,"level":27},"/en/concepts/rendering-modes#universal-rendering","Universal Rendering",[228],"In Universal Rendering, the server returns fully rendered HTML.\nThis allows the user to access the application's content immediately. After loading the HTML, the browser also loads JavaScript code to build dynamic UI that requires interaction.\nThis process is called \"hydration\". In this example, we log a count state to the console in app.vue.\nWhen accessing the page, you can see the output both in the terminal (server) and in the browser console. This means that Nuxt executes Vue.js code on the server to generate HTML, and then runs the same code again in the browser.\nThis is why it is called \"Universal Rendering\". The main advantages and disadvantages of Universal Rendering are as follows:",{"id":241,"title":242,"titles":243,"content":244,"level":168},"/en/concepts/rendering-modes#advantages","Advantages",[228,237],"Performance\nSince HTML is generated on the server and read by the browser, it is faster than generating content using JavaScript in the browser.Search Engine Optimization (SEO)\nWeb crawlers can directly index the page content, which is beneficial for SEO.",{"id":246,"title":247,"titles":248,"content":249,"level":168},"/en/concepts/rendering-modes#disadvantages","Disadvantages",[228,237],"Development constraints\nWriting code that runs seamlessly on both server and client sides imposes some limitations.Cost\nRequires a server, which incurs operational costs. For more details, see the official documentation.",{"id":251,"title":252,"titles":253,"content":254,"level":27},"/en/concepts/rendering-modes#client-side-rendering","Client-Side Rendering",[228],"You can enable Client-Side Rendering by setting ssr: false in nuxt.config. // nuxt.config.ts\nexport default defineNuxtConfig({\n ssr: false\n}) With Client-Side Rendering, the application is rendered in the browser.\nThe browser downloads and parses all JavaScript code, which contains the instructions to construct the UI, then generates HTML elements. The main advantages and disadvantages of Client-Side Rendering are as follows:",{"id":256,"title":242,"titles":257,"content":258,"level":168},"/en/concepts/rendering-modes#advantages-1",[228,252],"Development speed\nYou only need to consider how the application works in the browser, without worrying about server integration.Cost-efficient\nNo server is needed, so infrastructure costs are lower.Offline capability\nSince all code runs in the browser, the app can continue working even without an internet connection.",{"id":260,"title":247,"titles":261,"content":262,"level":168},"/en/concepts/rendering-modes#disadvantages-1",[228,252],"Performance\nUsers have to wait for the browser to download, parse, and execute JavaScript, which may affect user experience.Search Engine Optimization (SEO)\nIndexing and updating content rendered on the client side takes time, which is less SEO-friendly compared to server-rendered HTML.",{"id":264,"title":265,"titles":266,"content":267,"level":27},"/en/concepts/rendering-modes#hybrid-rendering","Hybrid Rendering",[228],"Nuxt allows you to specify different cache rules and rendering modes for each route using route rules. This is configured via the routeRules option in nuxt.config. For more details, refer to the official documentation. export default defineNuxtConfig({\n routeRules: {\n // Homepage pre-rendered at build time\n '/': { prerender: true },\n // Blog list page generated on demand, revalidates in background, cached on CDN for 1 hour (3600 seconds)\n '/blog': { isr: 3600 },\n // Blog post pages generated on demand once until next deployment, cached on CDN\n '/blog/**': { isr: true },\n // Admin dashboard rendered only on the client-side\n '/admin/**': { ssr: false },\n }\n})",{"id":269,"title":60,"titles":270,"content":271,"level":27},"/en/concepts/rendering-modes#challenge",[228],"Set up Client-Side Rendering and verify that Vue.js code runs only in the browser. To do this: Set ssr: false in nuxt.config.Log a count state to the console in app.vue.Confirm that there is no output in the terminal.Open the browser devtools and verify that the console shows the output. Next, set up Hybrid Rendering and confirm that you can assign different cache rules and rendering modes per route. To do this: Use the NuxtPage component in app.vue to render pages.Add console output in the script setup of /pages/index.vue and /pages/foo.vue (any message is fine).Set routeRules in nuxt.config, applying different cache and rendering settings to / and /foo.\nThis time, set ssr: false for /foo.Visit / and confirm that the console output appears both on the server and in the browser.Visit /foo and confirm that the console output appears only in the browser. To verify rendering behavior, it's important to check not just console output, but also the request behavior using the browser's \"Network\" tab.With Universal Rendering, since HTML is generated on the server, you'll see a fully populated \u003Cdiv id=\"__nuxt\"> in the network response.\nWith Client-Side Rendering, the HTML will initially be empty and populated by JavaScript.\n(The JavaScript will be visible as separate download requests) html pre.shiki code .snYqZ, html code.shiki .snYqZ{--shiki-default:#A0ADA0;--shiki-dark:#758575DD}html pre.shiki code .sTPum, html code.shiki .sTPum{--shiki-default:#1E754F;--shiki-dark:#4D9375}html pre.shiki code .s_xSY, html code.shiki .s_xSY{--shiki-default:#59873A;--shiki-dark:#80A665}html pre.shiki code .si6no, html code.shiki .si6no{--shiki-default:#999999;--shiki-dark:#666666}html pre.shiki code .sHLBJ, html code.shiki .sHLBJ{--shiki-default:#998418;--shiki-dark:#B8A965}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 .scnC2, html code.shiki .scnC2{--shiki-default:#B5695977;--shiki-dark:#C98A7D77}html pre.shiki code .spP0B, html code.shiki .spP0B{--shiki-default:#B56959;--shiki-dark:#C98A7D}html pre.shiki code .sqbOQ, html code.shiki .sqbOQ{--shiki-default:#2F798A;--shiki-dark:#4C9A91}",{"id":273,"title":274,"titles":275,"content":276,"level":17},"/en/concepts/state-manegement","State Management",[],"In Vue.js, state management refers to managing reactive state within an application.Vue.js Official Documentation: State Management",{"id":278,"title":274,"titles":279,"content":280,"level":17},"/en/concepts/state-manegement#state-management",[],"In Vue.js, state management refers to managing reactive state within an application.Vue.js Official Documentation: State Management When sharing state across multiple components, Vue.js allows for simple state management using the reactivity API.Vue.js Official Documentation: Simple State Management with Reactivity API However, as mentioned in the SSR Considerations, using SSR with Nuxt may lead to certain issues. Although the official Vue.js documentation introduces a state management library called Pinia, the useState() composable provided by Nuxt is also one of the solutions.\n(Of course, using Pinia in Nuxt is also possible.)",{"id":282,"title":283,"titles":284,"content":285,"level":27},"/en/concepts/state-manegement#usestate","useState()",[274],"The useState() composable provides a simple way to manage SSR-friendly state and share it across components.useState() is an SSR-friendly ref() used to define shared state.\nAs mentioned earlier, using Vue.js’s reactivity API such as ref() for cross-component state management in SSR may lead to issues.\nTherefore, in Nuxt, it is considered best practice to avoid defining state with ref() outside of \u003Cscript setup> or the setup() function, and instead use useState(). In the example in this playground, the state is shared between the CounterA and CounterB components using \"count\" as the key.\nNote that when the button rendered by CounterA is clicked, the state in CounterB also updates. For more details, refer to the Nuxt Official Documentation: State Management. Because the data inside useState() will be serialized to JSON, it is important that it does not contain anything that cannot be serialized, such as classes, functions or symbols.",[287],{"title":14,"path":13,"stem":288,"children":289},"en/0.index",[290,291,314],{"title":14,"path":13,"stem":288},{"title":7,"path":8,"stem":9,"children":292},[293,294,298,302,306,310],{"title":7,"path":8,"stem":9},{"title":51,"path":50,"stem":295,"children":296},"en/1.vue/2.reactivity/index",[297],{"title":51,"path":50,"stem":295},{"title":65,"path":64,"stem":299,"children":300},"en/1.vue/3.reactivity-2/index",[301],{"title":65,"path":64,"stem":299},{"title":74,"path":73,"stem":303,"children":304},"en/1.vue/4.composition-api/index",[305],{"title":74,"path":73,"stem":303},{"title":82,"path":81,"stem":307,"children":308},"en/1.vue/5.components/index",[309],{"title":82,"path":81,"stem":307},{"title":90,"path":89,"stem":311,"children":312},"en/1.vue/5.summary/index",[313],{"title":90,"path":89,"stem":311},{"title":99,"path":98,"stem":315,"children":316},"en/2.concepts/1.index",[317,318,322,326,330,334,338,342,346,350],{"title":99,"path":98,"stem":315},{"title":117,"path":116,"stem":319,"children":320},"en/2.concepts/10.data-fetching/index",[321],{"title":117,"path":116,"stem":319},{"title":130,"path":129,"stem":323,"children":324},"en/2.concepts/2.app-vue/index",[325],{"title":130,"path":129,"stem":323},{"title":139,"path":138,"stem":327,"children":328},"en/2.concepts/3.routing/index",[329],{"title":139,"path":138,"stem":327},{"title":171,"path":170,"stem":331,"children":332},"en/2.concepts/4.auto-imports/index",[333],{"title":171,"path":170,"stem":331},{"title":184,"path":183,"stem":335,"children":336},"en/2.concepts/5.middleware/index",[337],{"title":184,"path":183,"stem":335},{"title":212,"path":211,"stem":339,"children":340},"en/2.concepts/6.layout/index",[341],{"title":212,"path":211,"stem":339},{"title":221,"path":220,"stem":343,"children":344},"en/2.concepts/7.meta/index",[345],{"title":221,"path":220,"stem":343},{"title":228,"path":227,"stem":347,"children":348},"en/2.concepts/8.rendering-modes/index",[349],{"title":228,"path":227,"stem":347},{"title":274,"path":273,"stem":351,"children":352},"en/2.concepts/9.state-manegement/index",[353],{"title":274,"path":273,"stem":351},{"id":355,"title":14,"body":356,"description":16,"extension":518,"meta":519,"navigation":526,"path":13,"seo":527,"stem":288,"__hash__":528},"en/en/0.index.md",{"type":357,"value":358,"toc":512},"minimark",[359,363,375,383,387,410,413,421,424,441,444,446,461,464,467,503],[360,361,14],"h1",{"id":362},"welcome-to-nuxt-tutorial",[364,365,366,367,374],"p",{},"This is an interactive tutorial that is composed with guides and challenges to help you learn ",[368,369,373],"a",{"href":370,"rel":371},"https://nuxt.com/",[372],"nofollow","Nuxt"," and its concepts step by step.",[364,376,377,378,382],{},"The goal of this tutorial is to quickly give you an experience of what it feels like to work with Nuxt and Vue, ",[379,380,381],"strong",{},"right in the browser",". It does not aim to be comprehensive, and you don't need to understand everything before moving on. All playgrounds are editable with a full-featured editor and dev environment, so you can play with the code and see the result right away and learn by doing.",[384,385,24],"h2",{"id":386},"whats-nuxt",[364,388,389,390,395,396,401,402,409],{},"Nuxt is a free and ",[368,391,394],{"href":392,"rel":393},"https://github.com/nuxt/nuxt",[372],"open-source framework"," with an intuitive and extendable way to create type-safe, performant and production-grade full-stack web applications and websites with ",[368,397,400],{"href":398,"rel":399},"https://vuejs.org",[372],"Vue.js",". Nuxt has no vendor lock-in, allowing you to deploy your application ",[368,403,406],{"href":404,"rel":405},"https://nuxt.com/blog/nuxt-on-the-edge",[372],[379,407,408],{},"everywhere, even on the edge",".",[384,411,30],{"id":412},"getting-started",[364,414,415,416,420],{},"With this tutorial, we assume you are already familiar with the basic concepts of HTML, CSS and JavaScript. Nuxt is a full-stack framework built on top of ",[368,417,419],{"href":398,"rel":418},[372],"Vue",", we also include a simple Vue tutorial to help you get started quickly.",[364,422,423],{},"Start learning by clicking the topics below:",[425,426,431,437],"div",{"className":427},[428,429,430],"flex","flex-wrap","gap-2",[432,433],"content-card",{"description":434,"icon":435,"title":7,"to":436},"If you are not familiar with Vue, we recommend you to learn the basics of Vue first.","i-logos-vue","/vue",[432,438],{"description":434,"icon":439,"title":99,"to":440},"i-logos-nuxt-icon","/concepts",[384,442,35],{"id":443},"case-studies",[364,445,37],{},[425,447,449,456],{"className":448},[428,429,430],[432,450],{"description":451,"icon":452,"title":453,"to":454,":wip":455},"Build an website to generate custom user profile from GitHub","i-ph-user-circle-duotone","GitHub Profile","/","true",[432,457],{"description":458,"icon":459,"title":460,"to":454,":wip":455},"Build a basic ECommerce site with product display, cart and login","i-ph-shopping-cart-duotone","ECommerce",[384,462,40],{"id":463},"about-this-playground",[364,465,466],{},"This playground itself is also built with Nuxt. It uses:",[468,469,470,479,487,495],"ul",{},[471,472,473,478],"li",{},[368,474,477],{"href":475,"rel":476},"https://webcontainers.io/",[372],"WebContainers"," to create a fully-featured Node.js environment in your browser to run Nuxt dev server.",[471,480,481,486],{},[368,482,485],{"href":483,"rel":484},"https://content.nuxt.com/",[372],"Nuxt Content"," to provide content management for the playground.",[471,488,489,494],{},[368,490,493],{"href":491,"rel":492},"https://microsoft.github.io/monaco-editor/",[372],"Monaco Editor"," to provide a code editor with syntax highlighting and code completion.",[471,496,497,502],{},[368,498,501],{"href":499,"rel":500},"https://github.com/volarjs/volar.js",[372],"Volar"," to provide Vue and TypeScript language support for Monaco Editor.",[364,504,505,506,511],{},"You can find the ",[368,507,510],{"href":508,"rel":509},"https://github.com/nuxt/learn.nuxt.com",[372],"source code on GitHub"," to learn more about how this playground is built.",{"title":84,"searchDepth":27,"depth":27,"links":513},[514,515,516,517],{"id":386,"depth":27,"text":24},{"id":412,"depth":27,"text":30},{"id":443,"depth":27,"text":35},{"id":463,"depth":27,"text":40},"md",{"ogImage":520},{"props":521},{"title":522,"excerpt":523,"colorMode":524,"description":525},"Nuxt Tutorial","Hello","dark","An interactive tutorial for learning Nuxt",true,{"title":14,"description":16},"TnARzxglfEx-KhbIWPNT640dalmAVUAGLsUjOqbymdw",["Reactive",530],{"$si18n:cached-locale-configs":531,"$si18n:resolved-locale":84,"$scolor-mode":536,"$snuxt-seo-utils:routeRules":539,"$ssite-config":540},{"en":532,"ja":534},{"fallbacks":533,"cacheable":526},[],{"fallbacks":535,"cacheable":526},[],{"preference":537,"value":537,"unknown":526,"forced":538},"system",false,{"head":-1,"seoMeta":-1},{"_priority":541,"currentLocale":546,"defaultLocale":546,"env":547,"name":548,"url":549},{"name":542,"env":543,"url":544,"defaultLocale":545,"currentLocale":545},-10,-15,-3,-2,"en","production","learn.nuxt.com","https://learn.nuxt.com",["Set"],["ShallowReactive",552],{"search-sections":-1,"en-/en":-1,"en-navigation":-1,"en-/en-surroundings":-1},{"guide":554,"playground":563,"preview":571,"ui":577,"commands":588},{"features":555,"currentGuide":557,"showingSolution":559,"embeddedDocs":561},["Ref",556],{"fileTree":538,"terminal":538,"navigation":526,"download":526},["EmptyShallowRef",558],"_",["EmptyRef",560],"false",["EmptyRef",562],"\"\"",{"webcontainer":564,"status":565,"error":567,"currentProcess":568,"files":569,"fileSelected":570},["EmptyShallowRef",558],["Ref",566],"init",["EmptyShallowRef",558],["EmptyShallowRef",558],["Map"],["EmptyShallowRef",558],{"clientInfo":572,"location":573,"url":576},["EmptyRef",558],["Ref",574],["Reactive",575],{"origin":84,"fullPath":84},["EmptyRef",562],{"isPanelDragging":578,"isContentDropdownShown":579,"panelDocs":580,"panelEditor":582,"panelPreview":584,"panelFileTree":585,"showTerminal":587},["EmptyRef",560],["EmptyRef",560],["Ref",581],40,["Ref",583],60,["Ref",581],["EmptyRef",586],"0",["Ref",526],{"search":589,"isShown":590,"commandsAll":591},["EmptyRef",562],["EmptyRef",560],["Set"]]