[{"data":1,"prerenderedAt":904},["ShallowReactive",2],{"home-posts":3},[4,153,545],{"id":5,"title":6,"body":7,"date":139,"description":140,"draft":141,"extension":142,"meta":143,"navigation":144,"path":145,"seo":146,"stem":147,"summary":148,"tags":149,"__hash__":152},"posts\u002Fposts\u002Fhello-static-blog.md","用 Nuxt 4 搭一个纯静态博客",{"type":8,"value":9,"toc":131},"minimark",[10,14,19,22,25,38,41,93,96,107,110,121],[11,12,13],"p",{},"这是本站的第一篇文章，也是这份脚手架的自述。",[15,16,18],"h2",{"id":17},"为什么选-ssg","为什么选 SSG",[11,20,21],{},"博客的内容在写作时就定下来了，没有评论也没有登录，所以完全不需要服务端。把页面在构建时全部预渲染成 HTML，部署就只剩复制文件这一步。",[11,23,24],{},"好处很直接：",[26,27,28,32,35],"ul",{},[29,30,31],"li",{},"没有运行时依赖，任意静态服务器都能跑",[29,33,34],{},"首屏是现成的 HTML，不用等 JavaScript",[29,36,37],{},"出问题时不用翻日志，因为根本没有服务进程",[15,39,40],{"id":40},"技术栈",[42,43,44,57],"table",{},[45,46,47],"thead",{},[48,49,50,54],"tr",{},[51,52,53],"th",{},"用途",[51,55,56],{},"选型",[58,59,60,69,77,85],"tbody",{},[48,61,62,66],{},[63,64,65],"td",{},"框架",[63,67,68],{},"Nuxt 4",[48,70,71,74],{},[63,72,73],{},"样式",[63,75,76],{},"Tailwind CSS 4",[48,78,79,82],{},[63,80,81],{},"组件",[63,83,84],{},"daisyUI 5",[48,86,87,90],{},[63,88,89],{},"内容",[63,91,92],{},"@nuxt\u002Fcontent v3",[15,94,95],{"id":95},"目录结构",[97,98,104],"pre",{"className":99,"code":101,"language":102,"meta":103},[100],"language-text","app\u002F               页面、布局、组件、样式\ncontent\u002Fposts\u002F     Markdown 文章\nshared\u002F            页面与构建脚本共用的配置\ndeploy\u002F            nginx 示例配置\ndist\u002F              构建产物（不进 git）\n","text","",[105,106,101],"code",{"__ignoreMap":103},[15,108,109],{"id":109},"写一篇新文章",[11,111,112,113,116,117,120],{},"在 ",[105,114,115],{},"content\u002Fposts\u002F"," 下新建一个 ",[105,118,119],{},".md"," 文件，填好 frontmatter 就够了。列表页、标签页、RSS 和 sitemap 都会自动带上它。",[122,123,124],"blockquote",{},[11,125,126,127,130],{},"全部页面在 ",[105,128,129],{},"pnpm generate"," 时预渲染，因此不需要任何服务端进程。",{"title":103,"searchDepth":132,"depth":132,"links":133},3,[134,136,137,138],{"id":17,"depth":135,"text":18},2,{"id":40,"depth":135,"text":40},{"id":95,"depth":135,"text":95},{"id":109,"depth":135,"text":109},"2026-09-28","这个站点是怎么搭起来的：Nuxt 4 + Tailwind CSS 4 + daisyUI 5 + @nuxt\u002Fcontent，产物是一堆静态文件。",false,"md",{},true,"\u002Fposts\u002Fhello-static-blog",{"title":6,"description":140},"posts\u002Fhello-static-blog","从技术选型到目录结构，把这份脚手架的每一块讲清楚。",[150,151],"Nuxt","SSG","jnZfxGrQ_juLHYrvEdHpKGaNYrcgWTbDetrljxKQmM8",{"id":154,"title":155,"body":156,"date":535,"description":536,"draft":141,"extension":142,"meta":537,"navigation":144,"path":538,"seo":539,"stem":540,"summary":541,"tags":542,"__hash__":544},"posts\u002Fposts\u002Fnuxt-content-frontmatter.md","@nuxt\u002Fcontent 的 frontmatter 怎么写",{"type":8,"value":157,"toc":529},[158,165,169,327,331,395,398,482,497,500,525],[11,159,160,161,164],{},"文章元数据分两层：",[105,162,163],{},"content.config.ts"," 定义 schema，Markdown 的文件头填值。",[15,166,168],{"id":167},"定义-collection","定义 collection",[97,170,174],{"className":171,"code":172,"language":173,"meta":103,"style":103},"language-ts shiki shiki-themes github-light github-dark","import { defineCollection, defineContentConfig, z } from '@nuxt\u002Fcontent'\n\nexport default defineContentConfig({\n  collections: {\n    posts: defineCollection({\n      type: 'page',\n      source: 'posts\u002F*.md',\n      schema: z.object({\n        date: z.date(),\n        tags: z.array(z.string()).default([]),\n      }),\n    }),\n  },\n})\n","ts",[105,175,176,196,201,216,222,233,245,256,267,279,303,309,315,321],{"__ignoreMap":103},[177,178,181,185,189,192],"span",{"class":179,"line":180},"line",1,[177,182,184],{"class":183},"szBVR","import",[177,186,188],{"class":187},"sVt8B"," { defineCollection, defineContentConfig, z } ",[177,190,191],{"class":183},"from",[177,193,195],{"class":194},"sZZnC"," '@nuxt\u002Fcontent'\n",[177,197,198],{"class":179,"line":135},[177,199,200],{"emptyLinePlaceholder":144},"\n",[177,202,203,206,209,213],{"class":179,"line":132},[177,204,205],{"class":183},"export",[177,207,208],{"class":183}," default",[177,210,212],{"class":211},"sScJk"," defineContentConfig",[177,214,215],{"class":187},"({\n",[177,217,219],{"class":179,"line":218},4,[177,220,221],{"class":187},"  collections: {\n",[177,223,225,228,231],{"class":179,"line":224},5,[177,226,227],{"class":187},"    posts: ",[177,229,230],{"class":211},"defineCollection",[177,232,215],{"class":187},[177,234,236,239,242],{"class":179,"line":235},6,[177,237,238],{"class":187},"      type: ",[177,240,241],{"class":194},"'page'",[177,243,244],{"class":187},",\n",[177,246,248,251,254],{"class":179,"line":247},7,[177,249,250],{"class":187},"      source: ",[177,252,253],{"class":194},"'posts\u002F*.md'",[177,255,244],{"class":187},[177,257,259,262,265],{"class":179,"line":258},8,[177,260,261],{"class":187},"      schema: z.",[177,263,264],{"class":211},"object",[177,266,215],{"class":187},[177,268,270,273,276],{"class":179,"line":269},9,[177,271,272],{"class":187},"        date: z.",[177,274,275],{"class":211},"date",[177,277,278],{"class":187},"(),\n",[177,280,282,285,288,291,294,297,300],{"class":179,"line":281},10,[177,283,284],{"class":187},"        tags: z.",[177,286,287],{"class":211},"array",[177,289,290],{"class":187},"(z.",[177,292,293],{"class":211},"string",[177,295,296],{"class":187},"()).",[177,298,299],{"class":211},"default",[177,301,302],{"class":187},"([]),\n",[177,304,306],{"class":179,"line":305},11,[177,307,308],{"class":187},"      }),\n",[177,310,312],{"class":179,"line":311},12,[177,313,314],{"class":187},"    }),\n",[177,316,318],{"class":179,"line":317},13,[177,319,320],{"class":187},"  },\n",[177,322,324],{"class":179,"line":323},14,[177,325,326],{"class":187},"})\n",[15,328,330],{"id":329},"写-frontmatter","写 frontmatter",[97,332,336],{"className":333,"code":334,"language":335,"meta":103,"style":103},"language-yaml shiki shiki-themes github-light github-dark","---\ntitle: 文章标题\ndescription: 列表页与搜索引擎用的摘要\ndate: 2026-09-25\ntags:\n  - Nuxt\n---\n","yaml",[105,337,338,343,355,365,375,383,391],{"__ignoreMap":103},[177,339,340],{"class":179,"line":180},[177,341,342],{"class":211},"---\n",[177,344,345,349,352],{"class":179,"line":135},[177,346,348],{"class":347},"s9eBZ","title",[177,350,351],{"class":187},": ",[177,353,354],{"class":194},"文章标题\n",[177,356,357,360,362],{"class":179,"line":132},[177,358,359],{"class":347},"description",[177,361,351],{"class":187},[177,363,364],{"class":194},"列表页与搜索引擎用的摘要\n",[177,366,367,369,371],{"class":179,"line":218},[177,368,275],{"class":347},[177,370,351],{"class":187},[177,372,374],{"class":373},"sj4cs","2026-09-25\n",[177,376,377,380],{"class":179,"line":224},[177,378,379],{"class":347},"tags",[177,381,382],{"class":187},":\n",[177,384,385,388],{"class":179,"line":235},[177,386,387],{"class":187},"  - ",[177,389,390],{"class":194},"Nuxt\n",[177,392,393],{"class":179,"line":247},[177,394,342],{"class":211},[15,396,397],{"id":397},"在页面里查询",[97,399,401],{"className":171,"code":400,"language":173,"meta":103,"style":103},"const { data: posts } = await useAsyncData('posts', () =>\n  queryCollection('posts').order('date', 'DESC').all(),\n)\n",[105,402,403,444,477],{"__ignoreMap":103},[177,404,405,408,411,415,417,420,423,426,429,432,435,438,441],{"class":179,"line":180},[177,406,407],{"class":183},"const",[177,409,410],{"class":187}," { ",[177,412,414],{"class":413},"s4XuR","data",[177,416,351],{"class":187},[177,418,419],{"class":373},"posts",[177,421,422],{"class":187}," } ",[177,424,425],{"class":183},"=",[177,427,428],{"class":183}," await",[177,430,431],{"class":211}," useAsyncData",[177,433,434],{"class":187},"(",[177,436,437],{"class":194},"'posts'",[177,439,440],{"class":187},", () ",[177,442,443],{"class":183},"=>\n",[177,445,446,449,451,453,456,459,461,464,467,470,472,475],{"class":179,"line":135},[177,447,448],{"class":211},"  queryCollection",[177,450,434],{"class":187},[177,452,437],{"class":194},[177,454,455],{"class":187},").",[177,457,458],{"class":211},"order",[177,460,434],{"class":187},[177,462,463],{"class":194},"'date'",[177,465,466],{"class":187},", ",[177,468,469],{"class":194},"'DESC'",[177,471,455],{"class":187},[177,473,474],{"class":211},"all",[177,476,278],{"class":187},[177,478,479],{"class":179,"line":132},[177,480,481],{"class":187},")\n",[11,483,484,485,488,489,492,493,496],{},"单篇用 ",[105,486,487],{},".path(route.path).first()","，分页用 ",[105,490,491],{},".skip(n).limit(m)"," 配合 ",[105,494,495],{},".count()","。",[15,498,499],{"id":499},"常见坑",[501,502,503,512,522],"ol",{},[29,504,505,507,508,511],{},[105,506,275],{}," 用 ",[105,509,510],{},"z.date()"," 才能正确排序，写字符串会按字典序比。",[29,513,514,515,518,519,496],{},"文件名决定 URL：",[105,516,517],{},"content\u002Fposts\u002Fhello.md"," 对应 ",[105,520,521],{},"\u002Fposts\u002Fhello",[29,523,524],{},"定好 schema 后，frontmatter 里多写字段不会报错，少写必填字段会在构建时失败。",[526,527,528],"style",{},"html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}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}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}",{"title":103,"searchDepth":132,"depth":132,"links":530},[531,532,533,534],{"id":167,"depth":135,"text":168},{"id":329,"depth":135,"text":330},{"id":397,"depth":135,"text":397},{"id":499,"depth":135,"text":499},"2026-09-25","content.config.ts 里定义 collection 与 schema，Markdown 里填 frontmatter，页面里用 queryCollection 查询。",{},"\u002Fposts\u002Fnuxt-content-frontmatter",{"title":155,"description":536},"posts\u002Fnuxt-content-frontmatter","一份可直接照抄的 frontmatter 与查询写法。",[150,543],"Content","NzDcuZ_q0u7EWO3-OX3yo65qzbHvtn5goFCc7S0Sjso",{"id":546,"title":547,"body":548,"date":892,"description":893,"draft":141,"extension":142,"meta":894,"navigation":144,"path":895,"seo":896,"stem":897,"summary":898,"tags":899,"__hash__":903},"posts\u002Fposts\u002Ftailwind-daisyui-theme.md","Tailwind 4 与 daisyUI 5 的主题、深色模式",{"type":8,"value":549,"toc":886},[550,553,556,623,626,757,763,766,781,873,876,883],[11,551,552],{},"Tailwind 4 把配置搬进了 CSS。daisyUI 5 跟着这个模型走，主题也是 CSS 里的插件选项。",[15,554,555],{"id":555},"接入方式",[97,557,559],{"className":171,"code":558,"language":173,"meta":103,"style":103},"import tailwindcss from '@tailwindcss\u002Fvite'\n\nexport default defineNuxtConfig({\n  css: ['~\u002Fassets\u002Fcss\u002Fmain.css'],\n  vite: {\n    plugins: [tailwindcss()],\n  },\n})\n",[105,560,561,573,577,588,599,604,615,619],{"__ignoreMap":103},[177,562,563,565,568,570],{"class":179,"line":180},[177,564,184],{"class":183},[177,566,567],{"class":187}," tailwindcss ",[177,569,191],{"class":183},[177,571,572],{"class":194}," '@tailwindcss\u002Fvite'\n",[177,574,575],{"class":179,"line":135},[177,576,200],{"emptyLinePlaceholder":144},[177,578,579,581,583,586],{"class":179,"line":132},[177,580,205],{"class":183},[177,582,208],{"class":183},[177,584,585],{"class":211}," defineNuxtConfig",[177,587,215],{"class":187},[177,589,590,593,596],{"class":179,"line":218},[177,591,592],{"class":187},"  css: [",[177,594,595],{"class":194},"'~\u002Fassets\u002Fcss\u002Fmain.css'",[177,597,598],{"class":187},"],\n",[177,600,601],{"class":179,"line":224},[177,602,603],{"class":187},"  vite: {\n",[177,605,606,609,612],{"class":179,"line":235},[177,607,608],{"class":187},"    plugins: [",[177,610,611],{"class":211},"tailwindcss",[177,613,614],{"class":187},"()],\n",[177,616,617],{"class":179,"line":247},[177,618,320],{"class":187},[177,620,621],{"class":179,"line":258},[177,622,326],{"class":187},[15,624,625],{"id":625},"定义两套主题",[97,627,631],{"className":628,"code":629,"language":630,"meta":103,"style":103},"language-css shiki shiki-themes github-light github-dark","@import 'tailwindcss';\n\n@plugin 'daisyui' {\n  themes: false;\n}\n\n@plugin 'daisyui\u002Ftheme' {\n  name: 'myblog';\n  default: true;\n  color-scheme: light;\n  --color-primary: oklch(44% 0.088 250);\n}\n\n@plugin 'daisyui\u002Ftheme' {\n  name: 'myblog-dark';\n  color-scheme: dark;\n  --color-primary: oklch(78% 0.084 235);\n}\n","css",[105,632,633,644,648,656,661,666,670,677,682,687,695,706,710,714,720,732,740,752],{"__ignoreMap":103},[177,634,635,638,641],{"class":179,"line":180},[177,636,637],{"class":183},"@import",[177,639,640],{"class":194}," 'tailwindcss'",[177,642,643],{"class":187},";\n",[177,645,646],{"class":179,"line":135},[177,647,200],{"emptyLinePlaceholder":144},[177,649,650,653],{"class":179,"line":132},[177,651,652],{"class":183},"@plugin",[177,654,655],{"class":187}," 'daisyui' {\n",[177,657,658],{"class":179,"line":218},[177,659,660],{"class":187},"  themes: false;\n",[177,662,663],{"class":179,"line":224},[177,664,665],{"class":187},"}\n",[177,667,668],{"class":179,"line":235},[177,669,200],{"emptyLinePlaceholder":144},[177,671,672,674],{"class":179,"line":247},[177,673,652],{"class":183},[177,675,676],{"class":187}," 'daisyui\u002Ftheme' {\n",[177,678,679],{"class":179,"line":258},[177,680,681],{"class":187},"  name: 'myblog';\n",[177,683,684],{"class":179,"line":269},[177,685,686],{"class":187},"  default: true;\n",[177,688,689,692],{"class":179,"line":281},[177,690,691],{"class":347},"  color-scheme",[177,693,694],{"class":187},": light;\n",[177,696,697,700,703],{"class":179,"line":305},[177,698,699],{"class":187},"  --color-primary: oklch(44% 0",[177,701,702],{"class":211},".088",[177,704,705],{"class":187}," 250);\n",[177,707,708],{"class":179,"line":311},[177,709,665],{"class":187},[177,711,712],{"class":179,"line":317},[177,713,200],{"emptyLinePlaceholder":144},[177,715,716,718],{"class":179,"line":323},[177,717,652],{"class":183},[177,719,676],{"class":187},[177,721,723,726,729],{"class":179,"line":722},15,[177,724,725],{"class":187},"  name: '",[177,727,728],{"class":347},"myblog-dark",[177,730,731],{"class":187},"';\n",[177,733,735,737],{"class":179,"line":734},16,[177,736,691],{"class":347},[177,738,739],{"class":187},": dark;\n",[177,741,743,746,749],{"class":179,"line":742},17,[177,744,745],{"class":187},"  --color-primary: oklch(78% 0",[177,747,748],{"class":211},".084",[177,750,751],{"class":187}," 235);\n",[177,753,755],{"class":179,"line":754},18,[177,756,665],{"class":187},[11,758,759,762],{},[105,760,761],{},"themes: false"," 表示不加载 daisyUI 自带的几十套主题，只留我们自己定义的两套。",[15,764,765],{"id":765},"切换与防闪烁",[11,767,768,769,772,773,776,777,780],{},"切换就是把 ",[105,770,771],{},"data-theme"," 写到 ",[105,774,775],{},"\u003Chtml>"," 上；防闪烁的关键是这个属性必须在首屏绘制前就位，所以要在 ",[105,778,779],{},"\u003Chead>"," 里内联一小段脚本，而不是等 Vue 挂载。",[97,782,786],{"className":783,"code":784,"language":785,"meta":103,"style":103},"language-js shiki shiki-themes github-light github-dark","var stored = localStorage.getItem('myblog-theme')\nvar theme =\n  stored || (matchMedia('(prefers-color-scheme: dark)').matches ? 'myblog-dark' : 'myblog')\ndocument.documentElement.setAttribute('data-theme', theme)\n","js",[105,787,788,811,821,857],{"__ignoreMap":103},[177,789,790,793,796,798,801,804,806,809],{"class":179,"line":180},[177,791,792],{"class":183},"var",[177,794,795],{"class":187}," stored ",[177,797,425],{"class":183},[177,799,800],{"class":187}," localStorage.",[177,802,803],{"class":211},"getItem",[177,805,434],{"class":187},[177,807,808],{"class":194},"'myblog-theme'",[177,810,481],{"class":187},[177,812,813,815,818],{"class":179,"line":135},[177,814,792],{"class":183},[177,816,817],{"class":187}," theme ",[177,819,820],{"class":183},"=\n",[177,822,823,826,829,832,835,837,840,843,846,849,852,855],{"class":179,"line":132},[177,824,825],{"class":187},"  stored ",[177,827,828],{"class":183},"||",[177,830,831],{"class":187}," (",[177,833,834],{"class":211},"matchMedia",[177,836,434],{"class":187},[177,838,839],{"class":194},"'(prefers-color-scheme: dark)'",[177,841,842],{"class":187},").matches ",[177,844,845],{"class":183},"?",[177,847,848],{"class":194}," 'myblog-dark'",[177,850,851],{"class":183}," :",[177,853,854],{"class":194}," 'myblog'",[177,856,481],{"class":187},[177,858,859,862,865,867,870],{"class":179,"line":218},[177,860,861],{"class":187},"document.documentElement.",[177,863,864],{"class":211},"setAttribute",[177,866,434],{"class":187},[177,868,869],{"class":194},"'data-theme'",[177,871,872],{"class":187},", theme)\n",[15,874,875],{"id":875},"顺带一提",[11,877,878,879,882],{},"深色模式下代码块的配色由 Shiki 的双主题负责：浅色写内联样式，深色用 ",[105,880,881],{},"--shiki-dark"," 变量，再用一条属性选择器覆盖即可。",[526,884,885],{},"html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}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}",{"title":103,"searchDepth":132,"depth":132,"links":887},[888,889,890,891],{"id":555,"depth":135,"text":555},{"id":625,"depth":135,"text":625},{"id":765,"depth":135,"text":765},{"id":875,"depth":135,"text":875},"2026-09-20","用 CSS 变量定义两套自定义主题，再用一个 data-theme 属性切换，顺带解决首屏闪烁。",{},"\u002Fposts\u002Ftailwind-daisyui-theme",{"title":547,"description":893},"posts\u002Ftailwind-daisyui-theme","不用 tailwind.config.js，全部写在 CSS 里。",[900,901,902],"Tailwind","daisyUI","CSS","q8g-tw99FVDWTsZB3NvM1UX-ilRMzFgc80P_04eFOvU",1792556024852]