[{"data":1,"prerenderedAt":1343},["ShallowReactive",2],{"blog":3},[4,890,927,1254],{"id":5,"title":6,"author":7,"backfeed":8,"body":10,"date":879,"description":880,"draft":9,"extension":881,"meta":882,"navigation":188,"path":883,"reply":884,"seo":885,"shortId":886,"sitemap":887,"stem":888,"__hash__":889},"blog\u002Fblog\u002Fprerendering-all-routes-by-default-with-nuxt-content.md","Prerendering All Routes By Default With Nuxt Content","Sylvester Duda",{"twitter":9,"github":9,"mastodon":9,"flickr":9},false,{"type":11,"value":12,"toc":876},"minimark",[13,37,132,135,140,148,156,162,310,317,323,344,347,572,581,584,866,872],[14,15,16,17,21,22,25,26,29,30,32,33,36],"p",{},"When I was first using ",[18,19,20],"code",{},"@nuxt\u002Fcontent"," I had trouble figuring out how to render my blog posts. My Nuxt Static site was building correctly, but none of the routes seemed to be getting included. If you are like I was, frustrated that things were not working, you've come to the right place. The issue is that the Nuxt crawler does not know about the routes in the ",[18,23,24],{},"\u002Fcontent"," directory it only knows about the routes in ",[18,27,28],{},"\u002Fpages",". The crawler looks for links mentioned in the built routes and builds those routes as well. This may be why you might have noticed some ",[18,31,24],{}," routes being included in the final build and others not being included. The workaround is to hard-code all of these routes in your ",[18,34,35],{},"nuxt.config.ts"," file like so:",[38,39,44],"pre",{"className":40,"code":41,"language":42,"meta":43,"style":43},"language-ts shiki shiki-themes one-dark-pro","\u002F\u002F https:\u002F\u002Fv3.nuxtjs.org\u002Fapi\u002Fconfiguration\u002Fnuxt.config\nexport default defineNuxtConfig({\n    nitro: {\n        prerender: {      \n            routes: ['\u002Fblog\u002Fpost1.md', '\u002Fblog\u002Fpost2.md'] \n        },\n    }\n}\n","ts","",[18,45,46,55,73,83,92,114,120,126],{"__ignoreMap":43},[47,48,51],"span",{"class":49,"line":50},"line",1,[47,52,54],{"class":53},"sV9Aq","\u002F\u002F https:\u002F\u002Fv3.nuxtjs.org\u002Fapi\u002Fconfiguration\u002Fnuxt.config\n",[47,56,58,62,65,69],{"class":49,"line":57},2,[47,59,61],{"class":60},"seHd6","export",[47,63,64],{"class":60}," default",[47,66,68],{"class":67},"sVbv2"," defineNuxtConfig",[47,70,72],{"class":71},"sn6KH","({\n",[47,74,76,80],{"class":49,"line":75},3,[47,77,79],{"class":78},"sVyAn","    nitro",[47,81,82],{"class":71},": {\n",[47,84,86,89],{"class":49,"line":85},4,[47,87,88],{"class":78},"        prerender",[47,90,91],{"class":71},": {      \n",[47,93,95,98,101,105,108,111],{"class":49,"line":94},5,[47,96,97],{"class":78},"            routes",[47,99,100],{"class":71},": [",[47,102,104],{"class":103},"subq3","'\u002Fblog\u002Fpost1.md'",[47,106,107],{"class":71},", ",[47,109,110],{"class":103},"'\u002Fblog\u002Fpost2.md'",[47,112,113],{"class":71},"] \n",[47,115,117],{"class":49,"line":116},6,[47,118,119],{"class":71},"        },\n",[47,121,123],{"class":49,"line":122},7,[47,124,125],{"class":71},"    }\n",[47,127,129],{"class":49,"line":128},8,[47,130,131],{"class":71},"}\n",[14,133,134],{},"This isn't ideal (at least for me) because in the future I want to build a CLI that allows me to generate a blog template and have it work out of the box on my next static build without having to try to manipulate any other files. So here's how to do it.",[136,137,139],"h2",{"id":138},"the-solution","The Solution",[14,141,142,143,147],{},"We could write a bash script that travels through the content directory ",[144,145,146],"em",{},"OR"," we could take another route and do this insido of Node. To do this we need to install Glob a library that allows us to have access to similar pattern matching that we have in the command line. To get started:",[38,149,154],{"className":150,"code":152,"language":153},[151],"language-text","npm install --save-dev glob\n","text",[18,155,152],{"__ignoreMap":43},[14,157,158,159,161],{},"The next thing we'll do is import it in our ",[18,160,35],{}," and start using it to see how we might be able to leverage it directly inside of our config.",[38,163,165],{"className":40,"code":164,"language":42,"meta":43,"style":43},"import glob from 'glob';\n\nconst files = glob.sync('content' + '\u002F**\u002F*')\nconsole.log(files)\n\n\u002F\u002F https:\u002F\u002Fv3.nuxtjs.org\u002Fapi\u002Fconfiguration\u002Fnuxt.config\nexport default defineNuxtConfig({\n    nitro: {\n        prerender: {      \n            routes: ['\u002Fblog\u002Fpost1.md', '\u002Fblog\u002Fpost2.md', ...files]\n        },\n    }\n}\n",[18,166,167,184,190,226,243,247,251,261,267,274,295,300,305],{"__ignoreMap":43},[47,168,169,172,175,178,181],{"class":49,"line":50},[47,170,171],{"class":60},"import",[47,173,174],{"class":78}," glob",[47,176,177],{"class":60}," from",[47,179,180],{"class":103}," 'glob'",[47,182,183],{"class":71},";\n",[47,185,186],{"class":49,"line":57},[47,187,189],{"emptyLinePlaceholder":188},true,"\n",[47,191,192,195,199,203,205,208,211,214,217,220,223],{"class":49,"line":75},[47,193,194],{"class":60},"const",[47,196,198],{"class":197},"sU0A5"," files",[47,200,202],{"class":201},"sjrmR"," =",[47,204,174],{"class":197},[47,206,207],{"class":71},".",[47,209,210],{"class":67},"sync",[47,212,213],{"class":71},"(",[47,215,216],{"class":103},"'content'",[47,218,219],{"class":201}," +",[47,221,222],{"class":103}," '\u002F**\u002F*'",[47,224,225],{"class":71},")\n",[47,227,228,231,233,236,238,241],{"class":49,"line":85},[47,229,230],{"class":197},"console",[47,232,207],{"class":71},[47,234,235],{"class":67},"log",[47,237,213],{"class":71},[47,239,240],{"class":78},"files",[47,242,225],{"class":71},[47,244,245],{"class":49,"line":94},[47,246,189],{"emptyLinePlaceholder":188},[47,248,249],{"class":49,"line":116},[47,250,54],{"class":53},[47,252,253,255,257,259],{"class":49,"line":122},[47,254,61],{"class":60},[47,256,64],{"class":60},[47,258,68],{"class":67},[47,260,72],{"class":71},[47,262,263,265],{"class":49,"line":128},[47,264,79],{"class":78},[47,266,82],{"class":71},[47,268,270,272],{"class":49,"line":269},9,[47,271,88],{"class":78},[47,273,91],{"class":71},[47,275,277,279,281,283,285,287,290,292],{"class":49,"line":276},10,[47,278,97],{"class":78},[47,280,100],{"class":71},[47,282,104],{"class":103},[47,284,107],{"class":71},[47,286,110],{"class":103},[47,288,289],{"class":71},", ...",[47,291,240],{"class":78},[47,293,294],{"class":71},"]\n",[47,296,298],{"class":49,"line":297},11,[47,299,119],{"class":71},[47,301,303],{"class":49,"line":302},12,[47,304,125],{"class":71},[47,306,308],{"class":49,"line":307},13,[47,309,131],{"class":71},[14,311,312,313,316],{},"One issue we have is that we don't need to prepend each route with ",[18,314,315],{},"content",". Another issue is the routes that we are including. With the following directory:",[38,318,321],{"className":319,"code":320,"language":153},[151],"\u002Fcontent\n|---\u002Fblog\n    |---post1.md\n    |---post1.md\n",[18,322,320],{"__ignoreMap":43},[14,324,325,326,329,330,332,333,336,337,339,340,343],{},"Our files array would include ",[18,327,328],{},"\u002Fblog"," in the list of files as well. If we already have a Nuxt Page for ",[18,331,328],{}," this would be fine and Nuxt would see the route in the ",[18,334,335],{},"pages"," directory, but if we did not, we would be telling nuxt to render a route that does not exist since ",[18,338,328],{}," is a directory and not a file. Along with that if we have any other file types (for whatever reason) like ",[18,341,342],{},".jpg"," inside of our content folder we would run into the same issue.",[14,345,346],{},"To fix this, we need to do some filtering:",[38,348,350],{"className":40,"code":349,"language":42,"meta":43,"style":43},"\u002F\u002F These are Contents supported formats\nconst formats = ['.md', '.json', '.csv', 'yml']\n\nconst files = glob.sync('content' + '\u002F**\u002F*')\ncontentFiles = files\n    .map(dir => dir.replace('content', ''))\n    .filter(dir => formats.some(ft => dir.endsWith(ft)))\n    .map(dir => dir.replace(\u002F\\.[^\u002F.]+$\u002F, \"\"));\nconsole.log(contentFiles)\n",[18,351,352,357,389,393,417,427,464,505,558],{"__ignoreMap":43},[47,353,354],{"class":49,"line":50},[47,355,356],{"class":53},"\u002F\u002F These are Contents supported formats\n",[47,358,359,361,364,366,369,372,374,377,379,382,384,387],{"class":49,"line":57},[47,360,194],{"class":60},[47,362,363],{"class":197}," formats",[47,365,202],{"class":201},[47,367,368],{"class":71}," [",[47,370,371],{"class":103},"'.md'",[47,373,107],{"class":71},[47,375,376],{"class":103},"'.json'",[47,378,107],{"class":71},[47,380,381],{"class":103},"'.csv'",[47,383,107],{"class":71},[47,385,386],{"class":103},"'yml'",[47,388,294],{"class":71},[47,390,391],{"class":49,"line":75},[47,392,189],{"emptyLinePlaceholder":188},[47,394,395,397,399,401,403,405,407,409,411,413,415],{"class":49,"line":85},[47,396,194],{"class":60},[47,398,198],{"class":197},[47,400,202],{"class":201},[47,402,174],{"class":197},[47,404,207],{"class":71},[47,406,210],{"class":67},[47,408,213],{"class":71},[47,410,216],{"class":103},[47,412,219],{"class":201},[47,414,222],{"class":103},[47,416,225],{"class":71},[47,418,419,422,424],{"class":49,"line":94},[47,420,421],{"class":78},"contentFiles",[47,423,202],{"class":201},[47,425,426],{"class":78}," files\n",[47,428,429,432,435,437,441,444,447,449,452,454,456,458,461],{"class":49,"line":116},[47,430,431],{"class":71},"    .",[47,433,434],{"class":67},"map",[47,436,213],{"class":71},[47,438,440],{"class":439},"s_ZVi","dir",[47,442,443],{"class":60}," =>",[47,445,446],{"class":197}," dir",[47,448,207],{"class":71},[47,450,451],{"class":67},"replace",[47,453,213],{"class":71},[47,455,216],{"class":103},[47,457,107],{"class":71},[47,459,460],{"class":103},"''",[47,462,463],{"class":71},"))\n",[47,465,466,468,471,473,475,477,479,481,484,486,489,491,493,495,498,500,502],{"class":49,"line":122},[47,467,431],{"class":71},[47,469,470],{"class":67},"filter",[47,472,213],{"class":71},[47,474,440],{"class":439},[47,476,443],{"class":60},[47,478,363],{"class":197},[47,480,207],{"class":71},[47,482,483],{"class":67},"some",[47,485,213],{"class":71},[47,487,488],{"class":439},"ft",[47,490,443],{"class":60},[47,492,446],{"class":197},[47,494,207],{"class":71},[47,496,497],{"class":67},"endsWith",[47,499,213],{"class":71},[47,501,488],{"class":78},[47,503,504],{"class":71},")))\n",[47,506,507,509,511,513,515,517,519,521,523,525,528,531,535,538,540,542,545,548,550,552,555],{"class":49,"line":128},[47,508,431],{"class":71},[47,510,434],{"class":67},[47,512,213],{"class":71},[47,514,440],{"class":439},[47,516,443],{"class":60},[47,518,446],{"class":197},[47,520,207],{"class":71},[47,522,451],{"class":67},[47,524,213],{"class":71},[47,526,527],{"class":78},"\u002F",[47,529,530],{"class":201},"\\.",[47,532,534],{"class":533},"sVC51","[",[47,536,537],{"class":71},"^",[47,539,527],{"class":533},[47,541,207],{"class":78},[47,543,544],{"class":533},"]+",[47,546,547],{"class":60},"$",[47,549,527],{"class":78},[47,551,107],{"class":71},[47,553,554],{"class":103},"\"\"",[47,556,557],{"class":71},"));\n",[47,559,560,562,564,566,568,570],{"class":49,"line":269},[47,561,230],{"class":197},[47,563,207],{"class":71},[47,565,235],{"class":67},[47,567,213],{"class":71},[47,569,421],{"class":78},[47,571,225],{"class":71},[14,573,574,575,577,578,580],{},"The first map gets rid of the ",[18,576,315],{}," portion of the directory. The filter makes sure that any file not supported by ",[18,579,20],{}," is not included in the array. The last map gets rid of our file type at the end of the file.",[14,582,583],{},"Our code should now look like the following:",[38,585,587],{"className":40,"code":586,"language":42,"meta":43,"style":43},"import glob from 'glob';\n\nconst files = glob.sync('content' + '\u002F**\u002F*')\n\n\u002F\u002F These are Contents supported formats\nconst formats = ['.md', '.json', '.csv', 'yml']\nconst files = glob.sync('content' + '\u002F**\u002F*')\nconst contentFiles = files\n    .map(dir => dir.replace('content', ''))\n    .filter(dir => formats.some(ft => dir.endsWith(ft)))\n    .map(dir => dir.replace(\u002F\\.[^\u002F.]+$\u002F, \"\"));\n\n\u002F\u002F https:\u002F\u002Fv3.nuxtjs.org\u002Fapi\u002Fconfiguration\u002Fnuxt.config\nexport default defineNuxtConfig({\n    nitro: {\n        prerender: {      \n            routes: [...contentFiles]\n        },\n    }\n}\n",[18,588,589,601,605,629,633,637,663,687,698,726,762,806,810,814,825,832,839,851,856,861],{"__ignoreMap":43},[47,590,591,593,595,597,599],{"class":49,"line":50},[47,592,171],{"class":60},[47,594,174],{"class":78},[47,596,177],{"class":60},[47,598,180],{"class":103},[47,600,183],{"class":71},[47,602,603],{"class":49,"line":57},[47,604,189],{"emptyLinePlaceholder":188},[47,606,607,609,611,613,615,617,619,621,623,625,627],{"class":49,"line":75},[47,608,194],{"class":60},[47,610,198],{"class":197},[47,612,202],{"class":201},[47,614,174],{"class":197},[47,616,207],{"class":71},[47,618,210],{"class":67},[47,620,213],{"class":71},[47,622,216],{"class":103},[47,624,219],{"class":201},[47,626,222],{"class":103},[47,628,225],{"class":71},[47,630,631],{"class":49,"line":85},[47,632,189],{"emptyLinePlaceholder":188},[47,634,635],{"class":49,"line":94},[47,636,356],{"class":53},[47,638,639,641,643,645,647,649,651,653,655,657,659,661],{"class":49,"line":116},[47,640,194],{"class":60},[47,642,363],{"class":197},[47,644,202],{"class":201},[47,646,368],{"class":71},[47,648,371],{"class":103},[47,650,107],{"class":71},[47,652,376],{"class":103},[47,654,107],{"class":71},[47,656,381],{"class":103},[47,658,107],{"class":71},[47,660,386],{"class":103},[47,662,294],{"class":71},[47,664,665,667,669,671,673,675,677,679,681,683,685],{"class":49,"line":122},[47,666,194],{"class":60},[47,668,198],{"class":197},[47,670,202],{"class":201},[47,672,174],{"class":197},[47,674,207],{"class":71},[47,676,210],{"class":67},[47,678,213],{"class":71},[47,680,216],{"class":103},[47,682,219],{"class":201},[47,684,222],{"class":103},[47,686,225],{"class":71},[47,688,689,691,694,696],{"class":49,"line":128},[47,690,194],{"class":60},[47,692,693],{"class":197}," contentFiles",[47,695,202],{"class":201},[47,697,426],{"class":78},[47,699,700,702,704,706,708,710,712,714,716,718,720,722,724],{"class":49,"line":269},[47,701,431],{"class":71},[47,703,434],{"class":67},[47,705,213],{"class":71},[47,707,440],{"class":439},[47,709,443],{"class":60},[47,711,446],{"class":197},[47,713,207],{"class":71},[47,715,451],{"class":67},[47,717,213],{"class":71},[47,719,216],{"class":103},[47,721,107],{"class":71},[47,723,460],{"class":103},[47,725,463],{"class":71},[47,727,728,730,732,734,736,738,740,742,744,746,748,750,752,754,756,758,760],{"class":49,"line":276},[47,729,431],{"class":71},[47,731,470],{"class":67},[47,733,213],{"class":71},[47,735,440],{"class":439},[47,737,443],{"class":60},[47,739,363],{"class":197},[47,741,207],{"class":71},[47,743,483],{"class":67},[47,745,213],{"class":71},[47,747,488],{"class":439},[47,749,443],{"class":60},[47,751,446],{"class":197},[47,753,207],{"class":71},[47,755,497],{"class":67},[47,757,213],{"class":71},[47,759,488],{"class":78},[47,761,504],{"class":71},[47,763,764,766,768,770,772,774,776,778,780,782,784,786,788,790,792,794,796,798,800,802,804],{"class":49,"line":297},[47,765,431],{"class":71},[47,767,434],{"class":67},[47,769,213],{"class":71},[47,771,440],{"class":439},[47,773,443],{"class":60},[47,775,446],{"class":197},[47,777,207],{"class":71},[47,779,451],{"class":67},[47,781,213],{"class":71},[47,783,527],{"class":78},[47,785,530],{"class":201},[47,787,534],{"class":533},[47,789,537],{"class":71},[47,791,527],{"class":533},[47,793,207],{"class":78},[47,795,544],{"class":533},[47,797,547],{"class":60},[47,799,527],{"class":78},[47,801,107],{"class":71},[47,803,554],{"class":103},[47,805,557],{"class":71},[47,807,808],{"class":49,"line":302},[47,809,189],{"emptyLinePlaceholder":188},[47,811,812],{"class":49,"line":307},[47,813,54],{"class":53},[47,815,817,819,821,823],{"class":49,"line":816},14,[47,818,61],{"class":60},[47,820,64],{"class":60},[47,822,68],{"class":67},[47,824,72],{"class":71},[47,826,828,830],{"class":49,"line":827},15,[47,829,79],{"class":78},[47,831,82],{"class":71},[47,833,835,837],{"class":49,"line":834},16,[47,836,88],{"class":78},[47,838,91],{"class":71},[47,840,842,844,847,849],{"class":49,"line":841},17,[47,843,97],{"class":78},[47,845,846],{"class":71},": [...",[47,848,421],{"class":78},[47,850,294],{"class":71},[47,852,854],{"class":49,"line":853},18,[47,855,119],{"class":71},[47,857,859],{"class":49,"line":858},19,[47,860,125],{"class":71},[47,862,864],{"class":49,"line":863},20,[47,865,131],{"class":71},[14,867,868,869,871],{},"Tada! Each supported file in the ",[18,870,315],{}," directory should now be discoverable.",[873,874,875],"style",{},"html pre.shiki code .sV9Aq, html code.shiki .sV9Aq{--shiki-default:#7F848E;--shiki-default-font-style:italic}html pre.shiki code .seHd6, html code.shiki .seHd6{--shiki-default:#C678DD}html pre.shiki code .sVbv2, html code.shiki .sVbv2{--shiki-default:#61AFEF}html pre.shiki code .sn6KH, html code.shiki .sn6KH{--shiki-default:#ABB2BF}html pre.shiki code .sVyAn, html code.shiki .sVyAn{--shiki-default:#E06C75}html pre.shiki code .subq3, html code.shiki .subq3{--shiki-default:#98C379}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 pre.shiki code .sU0A5, html code.shiki .sU0A5{--shiki-default:#E5C07B}html pre.shiki code .sjrmR, html code.shiki .sjrmR{--shiki-default:#56B6C2}html pre.shiki code .s_ZVi, html code.shiki .s_ZVi{--shiki-default:#E06C75;--shiki-default-font-style:italic}html pre.shiki code .sVC51, html code.shiki .sVC51{--shiki-default:#D19A66}",{"title":43,"searchDepth":75,"depth":75,"links":877},[878],{"id":138,"depth":57,"text":139},1663771293000,"A guide prerendering all routes located in the content folder for @nuxt\u002Fcontent","md",{},"\u002Fblog\u002Fprerendering-all-routes-by-default-with-nuxt-content",null,{"title":6,"description":880},"g54j",{"loc":883},"blog\u002Fprerendering-all-routes-by-default-with-nuxt-content","89GEilh-_lsnTiCDIWMdHhtxUYSYddUWZ-x8DEy_WuM",{"id":891,"title":892,"author":7,"backfeed":893,"body":894,"date":915,"description":916,"draft":9,"extension":881,"meta":917,"navigation":188,"path":921,"reply":884,"seo":922,"shortId":923,"sitemap":924,"stem":925,"__hash__":926},"blog\u002Fblog\u002Fwebmention-test.md","Webmention Test",{"twitter":9,"github":9,"mastodon":9,"flickr":9},{"type":11,"value":895,"toc":913},[896,907,910],[14,897,898,899,906],{},"Hi ",[900,901,905],"a",{"href":902,"rel":903},"https:\u002F\u002Fjacky.wtf\u002Fabout",[904],"nofollow","Jacky","!",[14,908,909],{},"Thanks for being an incredible human being and being so persistent and passionate about the tech that you advocate for! I just wanted to give you a quick shoutout on my blog that gets absolutely no traffic. I hope you are doing well and more importantly I hope that this WebMention thing works so that you get the message.",[14,911,912],{},"♥ your friend!",{"title":43,"searchDepth":75,"depth":75,"links":914},[],1663585490000,"A test to see how the webmention API looks to integrate it into a blog.",{"webmentions":918},{"https:\u002F\u002Fjacky":919},{"wtf\u002Fabout":920},"https:\u002F\u002Fwebmention.io\u002Fjacky.wtf\u002Fwebmention\u002FinkijBaX4vfFO6rgXjXg","\u002Fblog\u002Fwebmention-test",{"title":892,"description":916},"7tgj",{"loc":921},"blog\u002Fwebmention-test","W3ZrB0N34vmauHTq75Un8BpPPw-s2_7Feqf_KLY7aUw",{"id":928,"title":929,"author":7,"backfeed":930,"body":931,"date":1245,"description":1246,"draft":9,"extension":881,"meta":1247,"navigation":188,"path":1248,"reply":884,"seo":1249,"shortId":1250,"sitemap":1251,"stem":1252,"__hash__":1253},"blog\u002Fblog\u002Fcreating-a-static-blog-with-nuxt.md","Creating a Static Blog with Nuxt",{"twitter":9,"github":9,"mastodon":9,"flickr":9},{"type":11,"value":932,"toc":1237},[933,936,940,952,956,965,971,975,984,988,999,1005,1018,1100,1111,1169,1176,1186,1197,1201,1208,1221,1225,1234],[14,934,935],{},"There comes a time when we finally get around to setting up that new blog\u002Fsite that we have always wanted to create. For whatever reason we may have wanted to create one, to market oneself, to have an online journal, to publicly display and talk about our portfolio, to consolidate the engagement we get online, etc., the hardest part can be figuring out how we want to host or deploy it. So in this post I am going to talk about my thought process and how I went about it",[136,937,939],{"id":938},"choosing-nuxt","Choosing Nuxt",[14,941,942,943,947,948,951],{},"Over the past 5 years, I have worked extenively in Vue and Nuxt and I ",[944,945,946],"strong",{},"love"," both frameworks. Vue, in my opinion, lowers the barrier of entry to modern web design as we know it compared to other popular web development frameworks like React and Angular. Nuxt is built on Vue to host a Server-Side Rendered version of your Vue web app, but we're here to talk about ",[944,949,950],{},"static sites",". Over the years, Nuxt's static site generation has gotten better and better. This site was entirely built with Nuxt and some of Nuxt's official modules or \"add-ons\".",[136,953,955],{"id":954},"installing-nuxt","Installing Nuxt",[14,957,958,959,964],{},"To install the latest and most powerful version of Nuxt (v3) start by following Nuxt's installation guide ",[900,960,963],{"href":961,"rel":962},"https:\u002F\u002Fv3.nuxtjs.org\u002Fgetting-started\u002Finstallation\u002F",[904],"here"," or just follow along below:",[38,966,969],{"className":967,"code":968,"language":153},[151],"npx nuxi init nuxt-app\ncd nuxt-app\nnpm install\nnpm run dev\n",[18,970,968],{"__ignoreMap":43},[136,972,974],{"id":973},"choosing-content","Choosing Content",[14,976,977,978,981,982,207],{},"Tada 🎉, we have a working Nuxt web app! But out of the box, Nuxt does not give us good tools to write blog content. If we take a look at modern blog examples, each paragraph, heading, list, code block, etc. is wrapped with some html and styling. Just imagine having to wrap every single piece of your content with html code every single time! Seems tedious, right? We want some kind of add-on that allows us to write in plain-text or more specifically ",[944,979,980],{},"markdown"," that will get converted to HTML on build. We're in luck! There is an official Nuxt package that we can use called ",[18,983,20],{},[136,985,987],{"id":986},"installing-content","Installing Content",[14,989,990,991,993,994,998],{},"You can install ",[18,992,20],{}," by following the installation guide for Nuxt v3 ",[900,995,963],{"href":996,"rel":997},"https:\u002F\u002Fcontent.nuxtjs.org\u002Fget-started",[904]," or you can follow along below:",[38,1000,1003],{"className":1001,"code":1002,"language":153},[151],"npm install --save-dev @nuxt\u002Fcontent\ncd nuxt-app\nnpm install\nnpm run dev\n",[18,1004,1002],{"__ignoreMap":43},[14,1006,1007,1008,1010,1011,1014,1015,1017],{},"Then, add ",[18,1009,20],{}," to the ",[18,1012,1013],{},"modules"," section of ",[18,1016,35],{},":",[38,1019,1021],{"className":40,"code":1020,"language":42,"meta":43,"style":43},"import { defineNuxtConfig } from 'nuxt'\n\nexport default defineNuxtConfig({  \n    modules: [    \n        '@nuxt\u002Fcontent'  \n    ],  \n    content: {    \n        \u002F\u002F https:\u002F\u002Fcontent.nuxtjs.org\u002Fapi\u002Fconfiguration  \n    }\n})\n",[18,1022,1023,1042,1046,1057,1065,1073,1078,1086,1091,1095],{"__ignoreMap":43},[47,1024,1025,1027,1030,1033,1036,1039],{"class":49,"line":50},[47,1026,171],{"class":60},[47,1028,1029],{"class":71}," { ",[47,1031,1032],{"class":78},"defineNuxtConfig",[47,1034,1035],{"class":71}," } ",[47,1037,1038],{"class":60},"from",[47,1040,1041],{"class":103}," 'nuxt'\n",[47,1043,1044],{"class":49,"line":57},[47,1045,189],{"emptyLinePlaceholder":188},[47,1047,1048,1050,1052,1054],{"class":49,"line":75},[47,1049,61],{"class":60},[47,1051,64],{"class":60},[47,1053,68],{"class":67},[47,1055,1056],{"class":71},"({  \n",[47,1058,1059,1062],{"class":49,"line":85},[47,1060,1061],{"class":78},"    modules",[47,1063,1064],{"class":71},": [    \n",[47,1066,1067,1070],{"class":49,"line":94},[47,1068,1069],{"class":103},"        '@nuxt\u002Fcontent'",[47,1071,1072],{"class":71},"  \n",[47,1074,1075],{"class":49,"line":116},[47,1076,1077],{"class":71},"    ],  \n",[47,1079,1080,1083],{"class":49,"line":122},[47,1081,1082],{"class":78},"    content",[47,1084,1085],{"class":71},": {    \n",[47,1087,1088],{"class":49,"line":128},[47,1089,1090],{"class":53},"        \u002F\u002F https:\u002F\u002Fcontent.nuxtjs.org\u002Fapi\u002Fconfiguration  \n",[47,1092,1093],{"class":49,"line":269},[47,1094,125],{"class":71},[47,1096,1097],{"class":49,"line":276},[47,1098,1099],{"class":71},"})\n",[14,1101,1102,1103,1106,1107,1110],{},"Create a catch-all document in your ",[18,1104,1105],{},"pages\u002F"," directory called ",[18,1108,1109],{},"[...slug].vue"," and add the following code:",[38,1112,1116],{"className":1113,"code":1114,"language":1115,"meta":43,"style":43},"language-vue shiki shiki-themes one-dark-pro","\u003Ctemplate>\n    \u003Cmain>    \n        \u003CContentDoc \u002F>  \n    \u003C\u002Fmain>\n\u003C\u002Ftemplate>\n","vue",[18,1117,1118,1129,1140,1151,1160],{"__ignoreMap":43},[47,1119,1120,1123,1126],{"class":49,"line":50},[47,1121,1122],{"class":71},"\u003C",[47,1124,1125],{"class":78},"template",[47,1127,1128],{"class":71},">\n",[47,1130,1131,1134,1137],{"class":49,"line":57},[47,1132,1133],{"class":71},"    \u003C",[47,1135,1136],{"class":78},"main",[47,1138,1139],{"class":71},">    \n",[47,1141,1142,1145,1148],{"class":49,"line":75},[47,1143,1144],{"class":71},"        \u003C",[47,1146,1147],{"class":78},"ContentDoc",[47,1149,1150],{"class":71}," \u002F>  \n",[47,1152,1153,1156,1158],{"class":49,"line":85},[47,1154,1155],{"class":71},"    \u003C\u002F",[47,1157,1136],{"class":78},[47,1159,1128],{"class":71},[47,1161,1162,1165,1167],{"class":49,"line":94},[47,1163,1164],{"class":71},"\u003C\u002F",[47,1166,1125],{"class":78},[47,1168,1128],{"class":71},[14,1170,1171,1172,1175],{},"Place your markdown files inside the ",[18,1173,1174],{},"content\u002F"," directory in the root directory of your project.",[38,1177,1180],{"className":1178,"code":1179,"language":881,"meta":43,"style":43},"language-md shiki shiki-themes one-dark-pro","# Hello Content\n",[18,1181,1182],{"__ignoreMap":43},[47,1183,1184],{"class":49,"line":50},[47,1185,1179],{"class":78},[14,1187,1188,1189,1191,1192,207],{},"If your app is still running in development, you should be able to now route to the title of the markdown file in your local dev server. For more information about how routing works with ",[18,1190,20],{}," check the ",[900,1193,1196],{"href":1194,"rel":1195},"https:\u002F\u002Fcontent.nuxtjs.org\u002Fguide\u002Fwriting\u002Fcontent-directory",[904],"content directory docs",[136,1198,1200],{"id":1199},"final-build","Final Build",[14,1202,1203,1204,1207],{},"In order to generate your full static site you will need to run ",[18,1205,1206],{},"nuxi run generate",". You may notice that some of your content files are not included in your final build.",[14,1209,1210,1211,1213,1214,1217,1218,1220],{},"This is because, by default, ",[18,1212,20],{}," does not build any files within content that are not referenced anywhere else in your project meaning you must use a ",[18,1215,1216],{},"NuxtLink"," or a direct link to it somewhere in your project. To get around this you can add each file that you want to include in your ",[18,1219,35],{}," file. This is not ideal and in a later post we will automate this and add new features.",[136,1222,1224],{"id":1223},"deployment","Deployment",[14,1226,1227,1228,1233],{},"There are a couple of ways that you can deploy your app to the web. The easiest of these is to follow Nuxt's ",[900,1229,1232],{"href":1230,"rel":1231},"https:\u002F\u002Fv3.nuxtjs.org\u002Fguide\u002Fdeploy\u002Fpresets#deployment-presets",[904],"guide"," on pushing apps. In a later blog post, we will go over nginx configurations that will allow us to serve our content much faster than these methods can.",[873,1235,1236],{},"html pre.shiki code .seHd6, html code.shiki .seHd6{--shiki-default:#C678DD}html pre.shiki code .sn6KH, html code.shiki .sn6KH{--shiki-default:#ABB2BF}html pre.shiki code .sVyAn, html code.shiki .sVyAn{--shiki-default:#E06C75}html pre.shiki code .subq3, html code.shiki .subq3{--shiki-default:#98C379}html pre.shiki code .sVbv2, html code.shiki .sVbv2{--shiki-default:#61AFEF}html pre.shiki code .sV9Aq, html code.shiki .sV9Aq{--shiki-default:#7F848E;--shiki-default-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);}",{"title":43,"searchDepth":75,"depth":75,"links":1238},[1239,1240,1241,1242,1243,1244],{"id":938,"depth":57,"text":939},{"id":954,"depth":57,"text":955},{"id":973,"depth":57,"text":974},{"id":986,"depth":57,"text":987},{"id":1199,"depth":57,"text":1200},{"id":1223,"depth":57,"text":1224},1663366162000,"A guide to building a blogging site from scratch with Nuxt and Nuxt Content",{},"\u002Fblog\u002Fcreating-a-static-blog-with-nuxt",{"title":929,"description":1246},"u8gO",{"loc":1248},"blog\u002Fcreating-a-static-blog-with-nuxt","EpTFjOrDQGrWqHzW1xjTAjzqAkbblm8Do9cyk37nZu4",{"id":1255,"title":1256,"author":7,"backfeed":1257,"body":1258,"date":1334,"description":1335,"draft":9,"extension":881,"meta":1336,"navigation":188,"path":1337,"reply":884,"seo":1338,"shortId":1339,"sitemap":1340,"stem":1341,"__hash__":1342},"blog\u002Fblog\u002Fhello-world.md","Hello World",{"twitter":9,"github":9,"mastodon":9,"flickr":9},{"type":11,"value":1259,"toc":1332},[1260,1263],[14,1261,1262],{},"Welcome to my blog! I will be adding all sorts of goodies here in the future. There is a whole lot that I want to do still and I will update and edit this intro as I go. Here are a few things that I'm looking forward to doing here:",[1264,1265,1268,1281,1287,1293,1299,1305,1311,1320,1326],"ul",{"className":1266},[1267],"contains-task-list",[1269,1270,1273,1277,1278],"li",{"className":1271},[1272],"task-list-item",[1274,1275],"input",{"checked":188,"disabled":188,"type":1276},"checkbox"," Deploying a static site to ",[18,1279,1280],{},"slyduda.com",[1269,1282,1284,1286],{"className":1283},[1272],[1274,1285],{"checked":188,"disabled":188,"type":1276}," Add content rendering system to display markdown as HTML",[1269,1288,1290,1292],{"className":1289},[1272],[1274,1291],{"checked":188,"disabled":188,"type":1276}," Added RSS feed",[1269,1294,1296,1298],{"className":1295},[1272],[1274,1297],{"checked":188,"disabled":188,"type":1276}," Adding newly provisioned public keys to root",[1269,1300,1302,1304],{"className":1301},[1272],[1274,1303],{"disabled":188,"type":1276}," Add Web Mentions integration",[1269,1306,1308,1310],{"className":1307},[1272],[1274,1309],{"disabled":188,"type":1276}," Add Web Subscriptions integration",[1269,1312,1314,1316,1317],{"className":1313},[1272],[1274,1315],{"disabled":188,"type":1276}," Create custom Web Mentions and Comments app and launch at ",[18,1318,1319],{},"engage.slyduda.com",[1269,1321,1323,1325],{"className":1322},[1272],[1274,1324],{"disabled":188,"type":1276}," Convert current blog to a service",[1269,1327,1329,1331],{"className":1328},[1272],[1274,1330],{"disabled":188,"type":1276}," Integrate some sort of resource based game to the application promoting Open Web",{"title":43,"searchDepth":75,"depth":75,"links":1333},[],1663345908000,"A short introduction to my blog.",{},"\u002Fblog\u002Fhello-world",{"title":1256,"description":1335},"a4gk",{"loc":1337},"blog\u002Fhello-world","x2DruPlDl8dp6cVtCPkAarmw-ZgqAS3zDvvSJpGvfgk",1792202290232]