[{"data":1,"prerenderedAt":1268},["ShallowReactive",2],{"blog-headless-wordpress-nuxt":3},{"id":4,"title":5,"articleType":6,"author":7,"authorSlug":8,"body":9,"cta":1240,"date":1241,"description":1242,"extension":1243,"faq":1244,"featured":1255,"image":1256,"meta":1257,"navigation":495,"noCtaBox":1255,"path":1258,"readTime":1259,"seo":1260,"seoTitle":1261,"stem":1262,"tags":1263,"__hash__":1267},"blog\u002Fblog\u002Fheadless-wordpress-nuxt.md","What Is Headless WordPress With Nuxt and How to Get Started?","TechArticle","Pavel Mironov","pavel-mironov",{"type":10,"value":11,"toc":1217},"minimark",[12,16,21,24,27,30,34,42,45,65,72,81,85,100,103,106,110,170,173,181,185,188,193,200,204,211,308,315,319,325,617,628,632,635,1069,1072,1076,1091,1105,1109,1112,1127,1131,1134,1147,1151,1155,1161,1165,1168,1172,1175,1179,1187,1191,1198,1202,1208,1213],[13,14,15],"p",{},"Headless WordPress Nuxt setups keep WordPress for writing and managing content and hand the public site to Nuxt. Editors keep the dashboard they know, and developers get a fast Vue frontend. This guide explains how the two connect, when to use the REST API or WPGraphQL, the trade-offs, and how to set up your first project step by step.",[17,18,20],"h2",{"id":19},"what-is-headless-wordpress-with-nuxt","What Is Headless WordPress With Nuxt?",[13,22,23],{},"Headless WordPress with Nuxt is a setup where WordPress only stores and manages content, and a separate Nuxt app renders the website. Nuxt reads posts, pages and media from WordPress through its REST API or GraphQL, then serves the pages as server-rendered or prerendered HTML.",[13,25,26],{},"\"Headless\" means the WordPress theme, the head, is removed. WordPress still runs: editors log in, write posts, upload images and manage users exactly as before. Visitors just never see a page that WordPress rendered.",[13,28,29],{},"This comes up a lot, because WordPress is everywhere. W3Techs counts it on 39.4% of all websites and 58.1% of sites with a known CMS (November 2026). Plenty of teams have years of posts and a trained editorial team in WordPress. They want a faster frontend, not a content migration.",[17,31,33],{"id":32},"how-a-nuxt-wordpress-headless-setup-works","How a Nuxt WordPress Headless Setup Works",[13,35,36,37,41],{},"In a Nuxt WordPress headless setup there are two apps with one job each. WordPress, usually on a subdomain like ",[38,39,40],"code",{},"cms.example.com",", holds the content and exposes it as JSON. Nuxt, on the main domain, fetches that JSON and turns it into pages.",[13,43,44],{},"The flow looks like this:",[46,47,48,52,59,62],"ol",{},[49,50,51],"li",{},"An editor publishes a post in WordPress.",[49,53,54,55,58],{},"Nuxt requests it from ",[38,56,57],{},"\u002Fwp-json\u002Fwp\u002Fv2\u002Fposts"," (or the GraphQL endpoint).",[49,60,61],{},"Nuxt renders the page on the server or at build time and sends full HTML to the browser.",[49,63,64],{},"Vue hydrates the page, and navigation from there works like a single-page app.",[13,66,67,68,71],{},"When the page is rendered is up to you. With ",[38,69,70],{},"nuxt generate",", every page is built once and served as static files, so new content needs a rebuild. With server rendering, pages are built per request and can be cached, so new posts appear without a deploy.",[13,73,74,75,80],{},"If you're new to the framework itself, our guide ",[76,77,79],"a",{"href":78},"\u002Fblog\u002Fwhat-is-nuxt","What is Nuxt"," covers routing, rendering and the Nitro server layer.",[17,82,84],{"id":83},"rest-api-vs-wpgraphql-for-nuxt","REST API vs WPGraphQL for Nuxt",[13,86,87,88,91,92,95,96,99],{},"The REST API is built into WordPress core, so it needs no plugin. Every resource has a URL, like ",[38,89,90],{},"\u002Fwp-json\u002Fwp\u002Fv2\u002Fposts?slug=hello-world",", which makes responses easy to cache on a CDN. Responses include more fields than you need, but ",[38,93,94],{},"_fields"," trims them and ",[38,97,98],{},"_embed"," pulls in featured images and authors in the same request. Yoast SEO adds its meta data to REST responses, and WooCommerce's Store API is REST too.",[13,101,102],{},"WPGraphQL is a plugin, and WordPress.org lists it as becoming a canonical plugin. It gives you one endpoint and a typed schema, and each page asks for exactly the fields it uses, including related content, in one request. Add-ons such as WPGraphQL for ACF expose custom fields. The cost is one more plugin to update, and GraphQL requests usually go out as POST, which CDNs don't cache by default.",[13,104,105],{},"Our pick: REST for blogs, marketing sites and WooCommerce stores; WPGraphQL for content models with many relations, such as ACF-heavy sites where one page pulls from several post types.",[17,107,109],{"id":108},"pros-and-cons-of-nuxt-with-headless-wordpress","Pros and Cons of Nuxt With Headless WordPress",[111,112,113,126],"table",{},[114,115,116],"thead",{},[117,118,119,123],"tr",{},[120,121,122],"th",{},"Pros",[120,124,125],{},"Cons",[127,128,129,138,146,154,162],"tbody",{},[117,130,131,135],{},[132,133,134],"td",{},"Editors keep the WordPress dashboard, roles and workflow",[132,136,137],{},"Two apps to host, update and monitor",[117,139,140,143],{},[132,141,142],{},"Fast pages: prerendered or server-rendered HTML, then Vue",[132,144,145],{},"Theme-level plugins stop working on the frontend",[117,147,148,151],{},[132,149,150],{},"The frontend is a normal Vue codebase with components and TypeScript",[132,152,153],{},"Previews need extra setup",[117,155,156,159],{},[132,157,158],{},"WordPress admin can live off the public domain, with less exposed",[132,160,161],{},"New content may need a rebuild or cache rules",[117,163,164,167],{},[132,165,166],{},"The same content can feed apps and other channels",[132,168,169],{},"The team needs both WordPress and Vue skills",[13,171,172],{},"The trade pays off on content-heavy sites with an editorial team that already lives in WordPress. It hurts on sites assembled from front-end plugins, since every one of them has to be rebuilt in Nuxt or dropped.",[13,174,175,176,180],{},"Rendering is the decision that shapes the rest. A blog that changes a few times a day can be fully prerendered. A site with thousands of pages or frequent updates is better served per request with caching. Our explainer on ",[76,177,179],{"href":178},"\u002Fblog\u002Fvue-js-seo-rendering","SSR, SSG and CSR in Vue"," covers the options and what each means for SEO.",[17,182,184],{"id":183},"how-to-set-up-headless-wordpress-nuxt","How to Set Up Headless WordPress + Nuxt",[13,186,187],{},"Here's a minimal path from a WordPress install to a working Nuxt blog.",[189,190,192],"h3",{"id":191},"prepare-wordpress-as-a-backend","Prepare WordPress as a Backend",[13,194,195,196,199],{},"Set permalinks to \"Post name\" so slugs are clean, and check that ",[38,197,198],{},"https:\u002F\u002Fcms.example.com\u002Fwp-json\u002Fwp\u002Fv2\u002Fposts"," returns JSON. Install the plugins that add data you need, such as ACF or Yoast SEO. If you want GraphQL, install WPGraphQL now. Then keep the WordPress domain out of search results, for example with the \"Discourage search engines from indexing this site\" option under Settings → Reading, so only the Nuxt site gets indexed.",[189,201,203],{"id":202},"create-the-nuxt-app","Create the Nuxt App",[13,205,206,207,210],{},"Create the app with ",[38,208,209],{},"npm create nuxt@latest",", then store the WordPress URL in runtime config so each environment can set its own:",[212,213,218],"pre",{"className":214,"code":215,"language":216,"meta":217,"style":217},"language-ts shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","\u002F\u002F nuxt.config.ts\nexport default defineNuxtConfig({\n  runtimeConfig: {\n    public: { wpUrl: 'https:\u002F\u002Fcms.example.com' },\n  },\n})\n","ts","",[38,219,220,229,251,264,293,299],{"__ignoreMap":217},[221,222,225],"span",{"class":223,"line":224},"line",1,[221,226,228],{"class":227},"sHwdD","\u002F\u002F nuxt.config.ts\n",[221,230,232,236,239,243,247],{"class":223,"line":231},2,[221,233,235],{"class":234},"s7zQu","export",[221,237,238],{"class":234}," default",[221,240,242],{"class":241},"s2Zo4"," defineNuxtConfig",[221,244,246],{"class":245},"sTEyZ","(",[221,248,250],{"class":249},"sMK4o","{\n",[221,252,254,258,261],{"class":223,"line":253},3,[221,255,257],{"class":256},"swJcz","  runtimeConfig",[221,259,260],{"class":249},":",[221,262,263],{"class":249}," {\n",[221,265,267,270,272,275,278,280,283,287,290],{"class":223,"line":266},4,[221,268,269],{"class":256},"    public",[221,271,260],{"class":249},[221,273,274],{"class":249}," {",[221,276,277],{"class":256}," wpUrl",[221,279,260],{"class":249},[221,281,282],{"class":249}," '",[221,284,286],{"class":285},"sfazB","https:\u002F\u002Fcms.example.com",[221,288,289],{"class":249},"'",[221,291,292],{"class":249}," },\n",[221,294,296],{"class":223,"line":295},5,[221,297,298],{"class":249},"  },\n",[221,300,302,305],{"class":223,"line":301},6,[221,303,304],{"class":249},"}",[221,306,307],{"class":245},")\n",[13,309,310,311,314],{},"The ",[38,312,313],{},"NUXT_PUBLIC_WP_URL"," environment variable overrides it at runtime.",[189,316,318],{"id":317},"fetch-posts-and-pages","Fetch Posts and Pages",[13,320,321,324],{},[38,322,323],{},"useFetch"," runs on the server during rendering and passes the result to the browser, so the request isn't repeated on hydration:",[212,326,330],{"className":327,"code":328,"language":329,"meta":217,"style":217},"language-vue shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","\u003C!-- app\u002Fpages\u002Fblog\u002Findex.vue -->\n\u003Cscript setup lang=\"ts\">\nconst { public: { wpUrl } } = useRuntimeConfig()\nconst { data: posts } = await useFetch(`${wpUrl}\u002Fwp-json\u002Fwp\u002Fv2\u002Fposts`, {\n  query: { per_page: 20, _fields: 'id,slug,title,excerpt' },\n})\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003Carticle v-for=\"post in posts\" :key=\"post.id\">\n    \u003CNuxtLink :to=\"`\u002Fblog\u002F${post.slug}`\">\n      \u003Cspan v-html=\"post.title.rendered\" \u002F>\n    \u003C\u002FNuxtLink>\n  \u003C\u002Farticle>\n\u003C\u002Ftemplate>\n","vue",[38,331,332,337,365,396,440,474,480,490,497,507,542,565,588,598,608],{"__ignoreMap":217},[221,333,334],{"class":223,"line":224},[221,335,336],{"class":227},"\u003C!-- app\u002Fpages\u002Fblog\u002Findex.vue -->\n",[221,338,339,342,345,349,352,355,358,360,362],{"class":223,"line":231},[221,340,341],{"class":249},"\u003C",[221,343,344],{"class":256},"script",[221,346,348],{"class":347},"spNyl"," setup",[221,350,351],{"class":347}," lang",[221,353,354],{"class":249},"=",[221,356,357],{"class":249},"\"",[221,359,216],{"class":285},[221,361,357],{"class":249},[221,363,364],{"class":249},">\n",[221,366,367,370,372,375,377,379,382,384,387,390,393],{"class":223,"line":253},[221,368,369],{"class":347},"const",[221,371,274],{"class":249},[221,373,374],{"class":256}," public",[221,376,260],{"class":249},[221,378,274],{"class":249},[221,380,381],{"class":245}," wpUrl ",[221,383,304],{"class":249},[221,385,386],{"class":249}," }",[221,388,389],{"class":249}," =",[221,391,392],{"class":241}," useRuntimeConfig",[221,394,395],{"class":245},"()\n",[221,397,398,400,402,405,407,410,412,414,417,420,422,425,428,430,432,435,438],{"class":223,"line":266},[221,399,369],{"class":347},[221,401,274],{"class":249},[221,403,404],{"class":256}," data",[221,406,260],{"class":249},[221,408,409],{"class":245}," posts ",[221,411,304],{"class":249},[221,413,389],{"class":249},[221,415,416],{"class":234}," await",[221,418,419],{"class":241}," useFetch",[221,421,246],{"class":245},[221,423,424],{"class":249},"`${",[221,426,427],{"class":245},"wpUrl",[221,429,304],{"class":249},[221,431,57],{"class":285},[221,433,434],{"class":249},"`",[221,436,437],{"class":249},",",[221,439,263],{"class":249},[221,441,442,445,447,449,452,454,458,460,463,465,467,470,472],{"class":223,"line":295},[221,443,444],{"class":256},"  query",[221,446,260],{"class":249},[221,448,274],{"class":249},[221,450,451],{"class":256}," per_page",[221,453,260],{"class":249},[221,455,457],{"class":456},"sbssI"," 20",[221,459,437],{"class":249},[221,461,462],{"class":256}," _fields",[221,464,260],{"class":249},[221,466,282],{"class":249},[221,468,469],{"class":285},"id,slug,title,excerpt",[221,471,289],{"class":249},[221,473,292],{"class":249},[221,475,476,478],{"class":223,"line":301},[221,477,304],{"class":249},[221,479,307],{"class":245},[221,481,483,486,488],{"class":223,"line":482},7,[221,484,485],{"class":249},"\u003C\u002F",[221,487,344],{"class":256},[221,489,364],{"class":249},[221,491,493],{"class":223,"line":492},8,[221,494,496],{"emptyLinePlaceholder":495},true,"\n",[221,498,500,502,505],{"class":223,"line":499},9,[221,501,341],{"class":249},[221,503,504],{"class":256},"template",[221,506,364],{"class":249},[221,508,510,513,516,519,521,523,526,528,531,533,535,538,540],{"class":223,"line":509},10,[221,511,512],{"class":249},"  \u003C",[221,514,515],{"class":256},"article",[221,517,518],{"class":347}," v-for",[221,520,354],{"class":249},[221,522,357],{"class":249},[221,524,525],{"class":285},"post in posts",[221,527,357],{"class":249},[221,529,530],{"class":347}," :key",[221,532,354],{"class":249},[221,534,357],{"class":249},[221,536,537],{"class":285},"post.id",[221,539,357],{"class":249},[221,541,364],{"class":249},[221,543,545,548,551,554,556,558,561,563],{"class":223,"line":544},11,[221,546,547],{"class":249},"    \u003C",[221,549,550],{"class":256},"NuxtLink",[221,552,553],{"class":347}," :to",[221,555,354],{"class":249},[221,557,357],{"class":249},[221,559,560],{"class":285},"`\u002Fblog\u002F${post.slug}`",[221,562,357],{"class":249},[221,564,364],{"class":249},[221,566,568,571,573,576,578,580,583,585],{"class":223,"line":567},12,[221,569,570],{"class":249},"      \u003C",[221,572,221],{"class":256},[221,574,575],{"class":347}," v-html",[221,577,354],{"class":249},[221,579,357],{"class":249},[221,581,582],{"class":285},"post.title.rendered",[221,584,357],{"class":249},[221,586,587],{"class":249}," \u002F>\n",[221,589,591,594,596],{"class":223,"line":590},13,[221,592,593],{"class":249},"    \u003C\u002F",[221,595,550],{"class":256},[221,597,364],{"class":249},[221,599,601,604,606],{"class":223,"line":600},14,[221,602,603],{"class":249},"  \u003C\u002F",[221,605,515],{"class":256},[221,607,364],{"class":249},[221,609,611,613,615],{"class":223,"line":610},15,[221,612,485],{"class":249},[221,614,504],{"class":256},[221,616,364],{"class":249},[13,618,619,620,623,624,627],{},"WordPress returns titles and content as rendered HTML, so ",[38,621,622],{},"v-html"," is the simplest way to show them. The REST API returns at most 100 items per request; the ",[38,625,626],{},"X-WP-TotalPages"," header tells you how many pages to request.",[189,629,631],{"id":630},"add-dynamic-routes-and-seo-meta","Add Dynamic Routes and SEO Meta",[13,633,634],{},"One file handles every post. It fetches by slug, returns a real 404 for unknown slugs and reuses the Yoast meta data:",[212,636,638],{"className":327,"code":637,"language":329,"meta":217,"style":217},"\u003C!-- app\u002Fpages\u002Fblog\u002F[slug].vue -->\n\u003Cscript setup lang=\"ts\">\nconst route = useRoute()\nconst { public: { wpUrl } } = useRuntimeConfig()\nconst { data: post } = await useFetch(`${wpUrl}\u002Fwp-json\u002Fwp\u002Fv2\u002Fposts`, {\n  query: { slug: route.params.slug, _embed: 1 },\n  transform: (posts: any[]) => posts[0],\n})\n\nif (!post.value) {\n  throw createError({ statusCode: 404, statusMessage: 'Post not found', fatal: true })\n}\n\nuseSeoMeta({\n  title: post.value.yoast_head_json?.title,\n  description: post.value.yoast_head_json?.description,\n})\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003Carticle>\n    \u003Ch1 v-html=\"post.title.rendered\" \u002F>\n    \u003Cdiv v-html=\"post.content.rendered\" \u002F>\n  \u003C\u002Farticle>\n\u003C\u002Ftemplate>\n",[38,639,640,645,665,679,703,740,779,820,826,830,850,900,905,909,918,946,971,978,987,992,1001,1010,1030,1051,1060],{"__ignoreMap":217},[221,641,642],{"class":223,"line":224},[221,643,644],{"class":227},"\u003C!-- app\u002Fpages\u002Fblog\u002F[slug].vue -->\n",[221,646,647,649,651,653,655,657,659,661,663],{"class":223,"line":231},[221,648,341],{"class":249},[221,650,344],{"class":256},[221,652,348],{"class":347},[221,654,351],{"class":347},[221,656,354],{"class":249},[221,658,357],{"class":249},[221,660,216],{"class":285},[221,662,357],{"class":249},[221,664,364],{"class":249},[221,666,667,669,672,674,677],{"class":223,"line":253},[221,668,369],{"class":347},[221,670,671],{"class":245}," route ",[221,673,354],{"class":249},[221,675,676],{"class":241}," useRoute",[221,678,395],{"class":245},[221,680,681,683,685,687,689,691,693,695,697,699,701],{"class":223,"line":266},[221,682,369],{"class":347},[221,684,274],{"class":249},[221,686,374],{"class":256},[221,688,260],{"class":249},[221,690,274],{"class":249},[221,692,381],{"class":245},[221,694,304],{"class":249},[221,696,386],{"class":249},[221,698,389],{"class":249},[221,700,392],{"class":241},[221,702,395],{"class":245},[221,704,705,707,709,711,713,716,718,720,722,724,726,728,730,732,734,736,738],{"class":223,"line":295},[221,706,369],{"class":347},[221,708,274],{"class":249},[221,710,404],{"class":256},[221,712,260],{"class":249},[221,714,715],{"class":245}," post ",[221,717,304],{"class":249},[221,719,389],{"class":249},[221,721,416],{"class":234},[221,723,419],{"class":241},[221,725,246],{"class":245},[221,727,424],{"class":249},[221,729,427],{"class":245},[221,731,304],{"class":249},[221,733,57],{"class":285},[221,735,434],{"class":249},[221,737,437],{"class":249},[221,739,263],{"class":249},[221,741,742,744,746,748,751,753,756,759,762,764,767,769,772,774,777],{"class":223,"line":301},[221,743,444],{"class":256},[221,745,260],{"class":249},[221,747,274],{"class":249},[221,749,750],{"class":256}," slug",[221,752,260],{"class":249},[221,754,755],{"class":245}," route",[221,757,758],{"class":249},".",[221,760,761],{"class":245},"params",[221,763,758],{"class":249},[221,765,766],{"class":245},"slug",[221,768,437],{"class":249},[221,770,771],{"class":256}," _embed",[221,773,260],{"class":249},[221,775,776],{"class":456}," 1",[221,778,292],{"class":249},[221,780,781,784,786,789,793,795,799,802,805,808,811,814,817],{"class":223,"line":482},[221,782,783],{"class":241},"  transform",[221,785,260],{"class":249},[221,787,788],{"class":249}," (",[221,790,792],{"class":791},"sHdIc","posts",[221,794,260],{"class":249},[221,796,798],{"class":797},"sBMFI"," any",[221,800,801],{"class":245},"[]",[221,803,804],{"class":249},")",[221,806,807],{"class":347}," =>",[221,809,810],{"class":245}," posts[",[221,812,813],{"class":456},"0",[221,815,816],{"class":245},"]",[221,818,819],{"class":249},",\n",[221,821,822,824],{"class":223,"line":492},[221,823,304],{"class":249},[221,825,307],{"class":245},[221,827,828],{"class":223,"line":499},[221,829,496],{"emptyLinePlaceholder":495},[221,831,832,835,837,840,843,845,848],{"class":223,"line":509},[221,833,834],{"class":234},"if",[221,836,788],{"class":245},[221,838,839],{"class":249},"!",[221,841,842],{"class":245},"post",[221,844,758],{"class":249},[221,846,847],{"class":245},"value) ",[221,849,250],{"class":249},[221,851,852,855,858,860,863,866,868,871,873,876,878,880,883,885,887,890,892,896,898],{"class":223,"line":544},[221,853,854],{"class":234},"  throw",[221,856,857],{"class":241}," createError",[221,859,246],{"class":256},[221,861,862],{"class":249},"{",[221,864,865],{"class":256}," statusCode",[221,867,260],{"class":249},[221,869,870],{"class":456}," 404",[221,872,437],{"class":249},[221,874,875],{"class":256}," statusMessage",[221,877,260],{"class":249},[221,879,282],{"class":249},[221,881,882],{"class":285},"Post not found",[221,884,289],{"class":249},[221,886,437],{"class":249},[221,888,889],{"class":256}," fatal",[221,891,260],{"class":249},[221,893,895],{"class":894},"sfNiH"," true",[221,897,386],{"class":249},[221,899,307],{"class":256},[221,901,902],{"class":223,"line":567},[221,903,904],{"class":249},"}\n",[221,906,907],{"class":223,"line":590},[221,908,496],{"emptyLinePlaceholder":495},[221,910,911,914,916],{"class":223,"line":600},[221,912,913],{"class":241},"useSeoMeta",[221,915,246],{"class":245},[221,917,250],{"class":249},[221,919,920,923,925,928,930,933,935,938,941,944],{"class":223,"line":610},[221,921,922],{"class":256},"  title",[221,924,260],{"class":249},[221,926,927],{"class":245}," post",[221,929,758],{"class":249},[221,931,932],{"class":245},"value",[221,934,758],{"class":249},[221,936,937],{"class":245},"yoast_head_json",[221,939,940],{"class":249},"?.",[221,942,943],{"class":245},"title",[221,945,819],{"class":249},[221,947,949,952,954,956,958,960,962,964,966,969],{"class":223,"line":948},16,[221,950,951],{"class":256},"  description",[221,953,260],{"class":249},[221,955,927],{"class":245},[221,957,758],{"class":249},[221,959,932],{"class":245},[221,961,758],{"class":249},[221,963,937],{"class":245},[221,965,940],{"class":249},[221,967,968],{"class":245},"description",[221,970,819],{"class":249},[221,972,974,976],{"class":223,"line":973},17,[221,975,304],{"class":249},[221,977,307],{"class":245},[221,979,981,983,985],{"class":223,"line":980},18,[221,982,485],{"class":249},[221,984,344],{"class":256},[221,986,364],{"class":249},[221,988,990],{"class":223,"line":989},19,[221,991,496],{"emptyLinePlaceholder":495},[221,993,995,997,999],{"class":223,"line":994},20,[221,996,341],{"class":249},[221,998,504],{"class":256},[221,1000,364],{"class":249},[221,1002,1004,1006,1008],{"class":223,"line":1003},21,[221,1005,512],{"class":249},[221,1007,515],{"class":256},[221,1009,364],{"class":249},[221,1011,1013,1015,1018,1020,1022,1024,1026,1028],{"class":223,"line":1012},22,[221,1014,547],{"class":249},[221,1016,1017],{"class":256},"h1",[221,1019,575],{"class":347},[221,1021,354],{"class":249},[221,1023,357],{"class":249},[221,1025,582],{"class":285},[221,1027,357],{"class":249},[221,1029,587],{"class":249},[221,1031,1033,1035,1038,1040,1042,1044,1047,1049],{"class":223,"line":1032},23,[221,1034,547],{"class":249},[221,1036,1037],{"class":256},"div",[221,1039,575],{"class":347},[221,1041,354],{"class":249},[221,1043,357],{"class":249},[221,1045,1046],{"class":285},"post.content.rendered",[221,1048,357],{"class":249},[221,1050,587],{"class":249},[221,1052,1054,1056,1058],{"class":223,"line":1053},24,[221,1055,603],{"class":249},[221,1057,515],{"class":256},[221,1059,364],{"class":249},[221,1061,1063,1065,1067],{"class":223,"line":1062},25,[221,1064,485],{"class":249},[221,1066,504],{"class":256},[221,1068,364],{"class":249},[13,1070,1071],{},"Add canonical URLs that point to the Nuxt domain, and generate the sitemap on the Nuxt side, for example with the Nuxt SEO module.",[189,1073,1075],{"id":1074},"set-up-previews-and-deploy","Set Up Previews and Deploy",[13,1077,1078,1079,1082,1083,1086,1087,1090],{},"Drafts aren't public, so a preview has to fetch them with credentials. WordPress has had Application Passwords since 5.6: create one for a preview user, keep it in private runtime config, and fetch drafts through a Nitro server route so the password never reaches the browser. Nuxt's ",[38,1080,1081],{},"usePreviewMode"," composable switches pages into preview when the URL has ",[38,1084,1085],{},"?preview=true",". On the WordPress side, the ",[38,1088,1089],{},"preview_post_link"," filter points the Preview button at your Nuxt URL.",[13,1092,1093,1094,1096,1097,1100,1101,1104],{},"For a static site, run ",[38,1095,70],{}," and add a deploy hook: the host gives you a build hook URL, and WordPress calls it when a post is published, through a small plugin or a few lines on the ",[38,1098,1099],{},"transition_post_status"," action. For server rendering, deploy to a Node.js host or a platform like Vercel or Netlify, and cache pages with route rules such as ",[38,1102,1103],{},"swr"," so new posts appear without a rebuild. Previews always need the server version, because a static site can't keep secrets.",[17,1106,1108],{"id":1107},"common-nuxt-wordpress-problems","Common Nuxt WordPress Problems",[13,1110,1111],{},"Most Nuxt WordPress projects hit the same four issues, usually in the week before launch.",[1113,1114,1115,1118,1121,1124],"ul",{},[49,1116,1117],{},"The Preview button keeps opening the old theme until you change its link and add an authenticated draft route, as shown above.",[49,1119,1120],{},"Plugins that output HTML through the theme, from page builders to sliders, stop working. Page-builder content can also arrive as markup that still expects the builder's CSS.",[49,1122,1123],{},"Form plugins render their own markup, so each form gets rebuilt in Vue and posts to the plugin's REST endpoint, if it has one, or to a Nitro route that sends the email.",[49,1125,1126],{},"Redirects saved in a WordPress plugin only apply to the WordPress domain. Copy them into the Nuxt host's redirect rules, or old URLs will 404.",[17,1128,1130],{"id":1129},"conclusion","Conclusion",[13,1132,1133],{},"Headless WordPress with Nuxt makes sense when your content and editors live in WordPress but the frontend needs to be faster or more flexible than a theme allows. Start with the REST API, decide on static or server rendering early and plan previews, forms and redirects before launch.",[13,1135,1136,1137,1141,1142,1146],{},"We're an ",[76,1138,1140],{"href":1139},"\u002Fblog\u002Fepicmax-official-nuxt-partner","official Nuxt partner",". If you're planning a Nuxt frontend for WordPress or another CMS, our ",[76,1143,1145],{"href":1144},"\u002Fservices\u002Fnuxt-development","Nuxt development services"," can help.",[17,1148,1150],{"id":1149},"faqs","FAQs",[189,1152,1154],{"id":1153},"is-headless-wordpress-good-for-seo","Is headless WordPress good for SEO?",[13,1156,1157,1158,1160],{},"Yes, as long as Nuxt renders the HTML on the server or at build time, so crawlers get full pages. You do have to rebuild the SEO layer in Nuxt: titles, meta tags, canonical URLs and the sitemap. If you use Yoast SEO, its meta data comes through the REST API in the ",[38,1159,937],{}," field.",[189,1162,1164],{"id":1163},"do-wordpress-plugins-work-with-a-nuxt-frontend","Do WordPress plugins work with a Nuxt frontend?",[13,1166,1167],{},"Plugins that add data work, because the data reaches Nuxt through the API: custom fields, custom post types and SEO fields. Plugins that change what the theme outputs don't, because the theme no longer renders the site. That includes page builders, sliders, form plugins' front-end markup and caching plugins.",[189,1169,1171],{"id":1170},"do-i-need-wpgraphql-to-use-nuxt-with-wordpress","Do I need WPGraphQL to use Nuxt with WordPress?",[13,1173,1174],{},"No. The REST API is built into WordPress and covers posts, pages, media, categories and custom post types. WPGraphQL is worth adding when your content model has many relations and you want each page to load in one typed query.",[189,1176,1178],{"id":1177},"can-i-move-an-existing-wordpress-site-to-nuxt","Can I move an existing WordPress site to Nuxt?",[13,1180,1181,1182,1186],{},"Yes. Keep WordPress and its content as the backend, rebuild the theme as a Nuxt app and keep every URL the same so rankings carry over. Move redirects and meta data along with it. If the site's frontend is already an older Nuxt 2 app, our ",[76,1183,1185],{"href":1184},"\u002Fservices\u002Fnuxt-migration","Nuxt migration services"," cover the upgrade to Nuxt 3 and 4.",[189,1188,1190],{"id":1189},"does-woocommerce-work-with-nuxt","Does WooCommerce work with Nuxt?",[13,1192,1193,1194,758],{},"Yes. WooCommerce's Store API exposes products, the cart and checkout as public REST endpoints that a Nuxt storefront can call. Its sessions are cookie-based, so plan for that when Nuxt and WordPress run on different domains. For a new store, a dedicated commerce backend can be simpler, as in our guide to an ",[76,1195,1197],{"href":1196},"\u002Fblog\u002Fhow-to-create-medusa-js-with-nuxt-4","e-commerce store with Medusa and Nuxt 4",[189,1199,1201],{"id":1200},"do-i-need-separate-hosting-for-wordpress-and-nuxt","Do I need separate hosting for WordPress and Nuxt?",[13,1203,1204,1205,1207],{},"Usually, yes. WordPress needs PHP and MySQL, while Nuxt runs on Node.js or as static files on a CDN like Netlify or Vercel. Many teams put WordPress on a subdomain such as ",[38,1206,40],{}," and serve the public site from the Nuxt host.",[1209,1210],"blog-button",{"label":1211,"to":1212},"Talk to a Nuxt expert","https:\u002F\u002Fcalendar.app.google\u002FXwRzASZitZRSVLxq6",[1214,1215,1216],"style",{},"html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sfNiH, html code.shiki .sfNiH{--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC}",{"title":217,"searchDepth":253,"depth":253,"links":1218},[1219,1220,1221,1222,1223,1230,1231,1232],{"id":19,"depth":231,"text":20},{"id":32,"depth":231,"text":33},{"id":83,"depth":231,"text":84},{"id":108,"depth":231,"text":109},{"id":183,"depth":231,"text":184,"children":1224},[1225,1226,1227,1228,1229],{"id":191,"depth":253,"text":192},{"id":202,"depth":253,"text":203},{"id":317,"depth":253,"text":318},{"id":630,"depth":253,"text":631},{"id":1074,"depth":253,"text":1075},{"id":1107,"depth":231,"text":1108},{"id":1129,"depth":231,"text":1130},{"id":1149,"depth":231,"text":1150,"children":1233},[1234,1235,1236,1237,1238,1239],{"id":1153,"depth":253,"text":1154},{"id":1163,"depth":253,"text":1164},{"id":1170,"depth":253,"text":1171},{"id":1177,"depth":253,"text":1178},{"id":1189,"depth":253,"text":1190},{"id":1200,"depth":253,"text":1201},null,"2026-11-12","Nuxt WordPress headless setups explained: REST API vs WPGraphQL, the pros and cons, and how to connect Nuxt and WordPress step by step.","md",[1245,1247,1248,1249,1251,1253],{"question":1154,"answer":1246},"Yes, as long as Nuxt renders the HTML on the server or at build time, so crawlers get full pages. You do have to rebuild the SEO layer in Nuxt: titles, meta tags, canonical URLs and the sitemap. If you use Yoast SEO, its meta data comes through the REST API in the yoast_head_json field.",{"question":1164,"answer":1167},{"question":1171,"answer":1174},{"question":1178,"answer":1250},"Yes. Keep WordPress and its content as the backend, rebuild the theme as a Nuxt app and keep every URL the same so rankings carry over. Move redirects and meta data along with it. If the site's frontend is already an older Nuxt 2 app, our Nuxt migration services cover the upgrade to Nuxt 3 and 4.",{"question":1190,"answer":1252},"Yes. WooCommerce's Store API exposes products, the cart and checkout as public REST endpoints that a Nuxt storefront can call. Its sessions are cookie-based, so plan for that when Nuxt and WordPress run on different domains. For a new store, a dedicated commerce backend can be simpler, as in our guide to an e-commerce store with Medusa and Nuxt 4.",{"question":1201,"answer":1254},"Usually, yes. WordPress needs PHP and MySQL, while Nuxt runs on Node.js or as static files on a CDN like Netlify or Vercel. Many teams put WordPress on a subdomain such as cms.example.com and serve the public site from the Nuxt host.",false,"\u002Fimages\u002Fblog\u002Fheadless-wordpress-nuxt\u002Fcard.png",{},"\u002Fblog\u002Fheadless-wordpress-nuxt","9 min read",{"title":5,"description":1242},"Headless WordPress Nuxt Guide: What It Is and How to Start","blog\u002Fheadless-wordpress-nuxt",[1264,1265,1266],"Nuxt","WordPress","Headless CMS","19CRVu4THGmryGua3D71WjD_WO2ojvzDagAl8o2CJ4k",1794485445179]