[{"data":1,"prerenderedAt":764},["ShallowReactive",2],{"navigation":3,"-examples-serve-static-assets":179,"-examples-serve-static-assets-surround":759},[4,86,128,156,163],{"title":5,"path":6,"stem":7,"children":8,"icon":85},"Guide","/guide","1.guide/0.index",[9,12,48,64],{"title":10,"path":6,"stem":7,"icon":11},"Getting Started","pixel:play",{"title":5,"icon":13,"path":14,"stem":15,"children":16,"page":47},"ph:book-open-duotone","/guide/basics","1.guide/1.basics",[17,22,27,32,37,42],{"title":18,"path":19,"stem":20,"icon":21},"Request Lifecycle","/guide/basics/lifecycle","1.guide/1.basics/1.lifecycle","icon-park-outline:handle-round",{"title":23,"path":24,"stem":25,"icon":26},"Routing","/guide/basics/routing","1.guide/1.basics/2.routing","solar:routing-bold",{"title":28,"path":29,"stem":30,"icon":31},"Middleware","/guide/basics/middleware","1.guide/1.basics/3.middleware","mdi:middleware-outline",{"title":33,"path":34,"stem":35,"icon":36},"Event Handlers","/guide/basics/handler","1.guide/1.basics/4.handler","mdi:function",{"title":38,"path":39,"stem":40,"icon":41},"Sending Response","/guide/basics/response","1.guide/1.basics/5.response","tabler:json",{"title":43,"path":44,"stem":45,"icon":46},"Error Handling","/guide/basics/error","1.guide/1.basics/6.error","tabler:error-404",false,{"title":49,"icon":50,"path":51,"stem":52,"children":53,"page":47},"API","material-symbols-light:api-rounded","/guide/api","1.guide/900.api",[54,59],{"title":55,"path":56,"stem":57,"icon":58},"H3","/guide/api/h3","1.guide/900.api/1.h3","material-symbols:bolt-rounded",{"title":60,"path":61,"stem":62,"icon":63},"H3Event","/guide/api/h3event","1.guide/900.api/2.h3event","material-symbols:data-object-rounded",{"title":65,"icon":66,"path":67,"stem":68,"children":69,"page":47},"Advanced","hugeicons:more-01","/guide/advanced","1.guide/901.advanced",[70,75,80],{"title":71,"path":72,"stem":73,"icon":74},"Plugins","/guide/advanced/plugins","1.guide/901.advanced/1.plugins","clarity:plugin-line",{"title":76,"path":77,"stem":78,"icon":79},"WebSockets","/guide/advanced/websocket","1.guide/901.advanced/2.websocket","hugeicons:live-streaming-02",{"title":81,"path":82,"stem":83,"icon":84},"Nightly Builds","/guide/advanced/nightly","1.guide/901.advanced/9.nightly","game-icons:barn-owl","i-ph:book-open-duotone",{"title":87,"path":88,"stem":89,"children":90,"icon":92},"H3 Utils","/utils","2.utils/0.index",[91,93,98,103,108,113,118,123],{"title":87,"path":88,"stem":89,"icon":92},"ph:function-bold",{"title":94,"path":95,"stem":96,"icon":97},"Request","/utils/request","2.utils/1.request","material-symbols-light:input",{"title":99,"path":100,"stem":101,"icon":102},"Response","/utils/response","2.utils/2.response","material-symbols-light:output",{"title":104,"path":105,"stem":106,"icon":107},"Cookie","/utils/cookie","2.utils/3.cookie","material-symbols:cookie-outline",{"title":109,"path":110,"stem":111,"icon":112},"Security","/utils/security","2.utils/4.security","wpf:key-security",{"title":114,"path":115,"stem":116,"icon":117},"Proxy","/utils/proxy","2.utils/5.proxy","arcticons:super-proxy",{"title":119,"path":120,"stem":121,"icon":122},"More utils","/utils/more","2.utils/9.more","mingcute:plus-line",{"title":124,"path":125,"stem":126,"icon":127},"Community","/utils/community","2.utils/99.community","lets-icons:external",{"title":129,"path":130,"stem":131,"children":132,"icon":134},"Examples","/examples","4.examples/0.index",[133,135,140,144,148,152],{"title":129,"path":130,"stem":131,"icon":134},"ph:code",{"title":136,"path":137,"stem":138,"icon":139},"Cookies","/examples/handle-cookie","4.examples/handle-cookie","ph:arrow-right",{"title":141,"path":142,"stem":143,"icon":139},"Sessions","/examples/handle-session","4.examples/handle-session",{"title":145,"path":146,"stem":147,"icon":139},"Static Assets","/examples/serve-static-assets","4.examples/serve-static-assets",{"title":149,"path":150,"stem":151,"icon":139},"Stream Response","/examples/stream-response","4.examples/stream-response",{"title":153,"path":154,"stem":155,"icon":139},"Validate Data","/examples/validate-data","4.examples/validate-data",{"title":157,"path":158,"stem":159,"children":160,"icon":162},"Migration guide for v1 to v2","/migration","5.migration/0.index",[161],{"title":157,"path":158,"stem":159,"icon":162},"icons8:up-round",{"title":164,"path":165,"stem":166,"children":167,"page":-1},"Blog","/blog","99.blog",[168,171,175],{"title":164,"path":165,"stem":169,"icon":170},"99.blog/index","i-lucide-file-text",{"title":172,"path":173,"stem":174,"icon":170},"H3 1.8 - Towards the Edge of the Web","/blog/v1.8","99.blog/1.v1.8",{"title":176,"path":177,"stem":178,"icon":170},"H3 v2 beta","/blog/v2-beta","99.blog/2.v2-beta",{"id":180,"title":145,"body":181,"description":753,"extension":754,"meta":755,"navigation":756,"path":146,"seo":757,"stem":147,"__hash__":758},"content/4.examples/serve-static-assets.md",{"type":182,"value":183,"toc":750,"icon":139},"minimark",[184,188,196,375,386,413,424,429,447,455,723,739,746],[185,186,187],"p",{},"H3 can serve static assets such as HTML, images, CSS, JavaScript, etc.",[185,189,190,191,195],{},"To serve a static directory, you can use the ",[192,193,194],"code",{},"serveStatic"," utility.",[197,198,203],"pre",{"className":199,"code":200,"language":201,"meta":202,"style":202},"language-ts shiki shiki-themes github-light github-dark github-dark","import { H3, serveStatic } from \"h3\";\n\nconst app = new H3();\n\napp.use(\"/public/**\", (event) => {\n  return serveStatic(event, {\n    getContents: (id) => {\n      // TODO\n    },\n    getMeta: (id) => {\n      // TODO\n    },\n  });\n});\n","ts","",[192,204,205,228,235,258,263,294,306,324,331,337,353,358,363,369],{"__ignoreMap":202},[206,207,210,214,218,221,225],"span",{"class":208,"line":209},"line",1,[206,211,213],{"class":212},"so5gQ","import",[206,215,217],{"class":216},"slsVL"," { H3, serveStatic } ",[206,219,220],{"class":212},"from",[206,222,224],{"class":223},"sfrk1"," \"h3\"",[206,226,227],{"class":216},";\n",[206,229,231],{"class":208,"line":230},2,[206,232,234],{"emptyLinePlaceholder":233},true,"\n",[206,236,238,241,245,248,251,255],{"class":208,"line":237},3,[206,239,240],{"class":212},"const",[206,242,244],{"class":243},"suiK_"," app",[206,246,247],{"class":212}," =",[206,249,250],{"class":212}," new",[206,252,254],{"class":253},"shcOC"," H3",[206,256,257],{"class":216},"();\n",[206,259,261],{"class":208,"line":260},4,[206,262,234],{"emptyLinePlaceholder":233},[206,264,266,269,272,275,278,281,285,288,291],{"class":208,"line":265},5,[206,267,268],{"class":216},"app.",[206,270,271],{"class":253},"use",[206,273,274],{"class":216},"(",[206,276,277],{"class":223},"\"/public/**\"",[206,279,280],{"class":216},", (",[206,282,284],{"class":283},"sQHwn","event",[206,286,287],{"class":216},") ",[206,289,290],{"class":212},"=>",[206,292,293],{"class":216}," {\n",[206,295,297,300,303],{"class":208,"line":296},6,[206,298,299],{"class":212},"  return",[206,301,302],{"class":253}," serveStatic",[206,304,305],{"class":216},"(event, {\n",[206,307,309,312,315,318,320,322],{"class":208,"line":308},7,[206,310,311],{"class":253},"    getContents",[206,313,314],{"class":216},": (",[206,316,317],{"class":283},"id",[206,319,287],{"class":216},[206,321,290],{"class":212},[206,323,293],{"class":216},[206,325,327],{"class":208,"line":326},8,[206,328,330],{"class":329},"sCsY4","      // TODO\n",[206,332,334],{"class":208,"line":333},9,[206,335,336],{"class":216},"    },\n",[206,338,340,343,345,347,349,351],{"class":208,"line":339},10,[206,341,342],{"class":253},"    getMeta",[206,344,314],{"class":216},[206,346,317],{"class":283},[206,348,287],{"class":216},[206,350,290],{"class":212},[206,352,293],{"class":216},[206,354,356],{"class":208,"line":355},11,[206,357,330],{"class":329},[206,359,361],{"class":208,"line":360},12,[206,362,336],{"class":216},[206,364,366],{"class":208,"line":365},13,[206,367,368],{"class":216},"  });\n",[206,370,372],{"class":208,"line":371},14,[206,373,374],{"class":216},"});\n",[185,376,377,378,381,382,385],{},"This does not serve any files yet. You need to implement the ",[192,379,380],{},"getContents"," and ",[192,383,384],{},"getMeta"," methods.",[387,388,389,403],"ul",{},[390,391,392,394,395,398,399,402],"li",{},[192,393,380],{}," is used to read the contents of a file. It should return a ",[192,396,397],{},"Promise"," that resolves to the contents of the file or ",[192,400,401],{},"undefined"," if the file does not exist.",[390,404,405,407,408,410,411,402],{},[192,406,384],{}," is used to get the metadata of a file. It should return a ",[192,409,397],{}," that resolves to the metadata of the file or ",[192,412,401],{},[185,414,415,416,419,420,423],{},"They are separated to allow H3 to respond to ",[192,417,418],{},"HEAD"," requests without reading the contents of the file and to use the ",[192,421,422],{},"Last-Modified"," header.",[425,426,428],"h2",{"id":427},"read-files","Read files",[185,430,431,432,435,436,439,440,446],{},"Now, create a ",[192,433,434],{},"index.html"," file in the ",[192,437,438],{},"public"," directory with a simple message and open your browser to ",[441,442,443],"a",{"href":443,"rel":444},"http://localhost:3000",[445],"nofollow",". You should see the message.",[185,448,449,450,381,452,454],{},"Then, we can create the ",[192,451,380],{},[192,453,384],{}," methods:",[197,456,458],{"className":199,"code":457,"language":201,"meta":202,"style":202},"import { stat, readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { H3, serve, serveStatic } from \"h3\";\n\nconst app = new H3();\n\napp.use(\"/public/**\", (event) => {\n  return serveStatic(event, {\n    indexNames: [\"/index.html\"],\n    getContents: (id) => readFile(join(\"public\", id)),\n    getMeta: async (id) => {\n      const stats = await stat(join(\"public\", id)).catch(() => {});\n      if (stats?.isFile()) {\n        return {\n          size: stats.size,\n          mtime: stats.mtimeMs,\n        };\n      }\n    },\n  });\n});\n\nserve(app);\n",[192,459,460,474,488,501,505,519,523,543,551,562,590,611,649,663,670,676,682,688,694,699,704,709,714],{"__ignoreMap":202},[206,461,462,464,467,469,472],{"class":208,"line":209},[206,463,213],{"class":212},[206,465,466],{"class":216}," { stat, readFile } ",[206,468,220],{"class":212},[206,470,471],{"class":223}," \"node:fs/promises\"",[206,473,227],{"class":216},[206,475,476,478,481,483,486],{"class":208,"line":230},[206,477,213],{"class":212},[206,479,480],{"class":216}," { join } ",[206,482,220],{"class":212},[206,484,485],{"class":223}," \"node:path\"",[206,487,227],{"class":216},[206,489,490,492,495,497,499],{"class":208,"line":237},[206,491,213],{"class":212},[206,493,494],{"class":216}," { H3, serve, serveStatic } ",[206,496,220],{"class":212},[206,498,224],{"class":223},[206,500,227],{"class":216},[206,502,503],{"class":208,"line":260},[206,504,234],{"emptyLinePlaceholder":233},[206,506,507,509,511,513,515,517],{"class":208,"line":265},[206,508,240],{"class":212},[206,510,244],{"class":243},[206,512,247],{"class":212},[206,514,250],{"class":212},[206,516,254],{"class":253},[206,518,257],{"class":216},[206,520,521],{"class":208,"line":296},[206,522,234],{"emptyLinePlaceholder":233},[206,524,525,527,529,531,533,535,537,539,541],{"class":208,"line":308},[206,526,268],{"class":216},[206,528,271],{"class":253},[206,530,274],{"class":216},[206,532,277],{"class":223},[206,534,280],{"class":216},[206,536,284],{"class":283},[206,538,287],{"class":216},[206,540,290],{"class":212},[206,542,293],{"class":216},[206,544,545,547,549],{"class":208,"line":326},[206,546,299],{"class":212},[206,548,302],{"class":253},[206,550,305],{"class":216},[206,552,553,556,559],{"class":208,"line":333},[206,554,555],{"class":216},"    indexNames: [",[206,557,558],{"class":223},"\"/index.html\"",[206,560,561],{"class":216},"],\n",[206,563,564,566,568,570,572,574,577,579,582,584,587],{"class":208,"line":339},[206,565,311],{"class":253},[206,567,314],{"class":216},[206,569,317],{"class":283},[206,571,287],{"class":216},[206,573,290],{"class":212},[206,575,576],{"class":253}," readFile",[206,578,274],{"class":216},[206,580,581],{"class":253},"join",[206,583,274],{"class":216},[206,585,586],{"class":223},"\"public\"",[206,588,589],{"class":216},", id)),\n",[206,591,592,594,597,600,603,605,607,609],{"class":208,"line":355},[206,593,342],{"class":253},[206,595,596],{"class":216},": ",[206,598,599],{"class":212},"async",[206,601,602],{"class":216}," (",[206,604,317],{"class":283},[206,606,287],{"class":216},[206,608,290],{"class":212},[206,610,293],{"class":216},[206,612,613,616,619,621,624,627,629,631,633,635,638,641,644,646],{"class":208,"line":360},[206,614,615],{"class":212},"      const",[206,617,618],{"class":243}," stats",[206,620,247],{"class":212},[206,622,623],{"class":212}," await",[206,625,626],{"class":253}," stat",[206,628,274],{"class":216},[206,630,581],{"class":253},[206,632,274],{"class":216},[206,634,586],{"class":223},[206,636,637],{"class":216},", id)).",[206,639,640],{"class":253},"catch",[206,642,643],{"class":216},"(() ",[206,645,290],{"class":212},[206,647,648],{"class":216}," {});\n",[206,650,651,654,657,660],{"class":208,"line":365},[206,652,653],{"class":212},"      if",[206,655,656],{"class":216}," (stats?.",[206,658,659],{"class":253},"isFile",[206,661,662],{"class":216},"()) {\n",[206,664,665,668],{"class":208,"line":371},[206,666,667],{"class":212},"        return",[206,669,293],{"class":216},[206,671,673],{"class":208,"line":672},15,[206,674,675],{"class":216},"          size: stats.size,\n",[206,677,679],{"class":208,"line":678},16,[206,680,681],{"class":216},"          mtime: stats.mtimeMs,\n",[206,683,685],{"class":208,"line":684},17,[206,686,687],{"class":216},"        };\n",[206,689,691],{"class":208,"line":690},18,[206,692,693],{"class":216},"      }\n",[206,695,697],{"class":208,"line":696},19,[206,698,336],{"class":216},[206,700,702],{"class":208,"line":701},20,[206,703,368],{"class":216},[206,705,707],{"class":208,"line":706},21,[206,708,374],{"class":216},[206,710,712],{"class":208,"line":711},22,[206,713,234],{"emptyLinePlaceholder":233},[206,715,717,720],{"class":208,"line":716},23,[206,718,719],{"class":253},"serve",[206,721,722],{"class":216},"(app);\n",[185,724,725,726,728,729,731,732,735,736,738],{},"The ",[192,727,380],{}," read the file and returns its contents, pretty simple. The ",[192,730,384],{}," uses ",[192,733,734],{},"fs.stat"," to get the file metadata. If the file does not exist or is not a file, it returns ",[192,737,401],{},". Otherwise, it returns the file size and the last modification time.",[185,740,741,742,745],{},"The file size and last modification time are used to create an etag to send a ",[192,743,744],{},"304 Not Modified"," response if the file has not been modified since the last request. This is useful to avoid sending the same file multiple times if it has not changed.",[747,748,749],"style",{},"html pre.shiki code .so5gQ, html code.shiki .so5gQ{--shiki-light:#D73A49;--shiki-default:#F97583;--shiki-dark:#F97583}html pre.shiki code .slsVL, html code.shiki .slsVL{--shiki-light:#24292E;--shiki-default:#E1E4E8;--shiki-dark:#E1E4E8}html pre.shiki code .sfrk1, html code.shiki .sfrk1{--shiki-light:#032F62;--shiki-default:#9ECBFF;--shiki-dark:#9ECBFF}html pre.shiki code .suiK_, html code.shiki .suiK_{--shiki-light:#005CC5;--shiki-default:#79B8FF;--shiki-dark:#79B8FF}html pre.shiki code .shcOC, html code.shiki .shcOC{--shiki-light:#6F42C1;--shiki-default:#B392F0;--shiki-dark:#B392F0}html pre.shiki code .sQHwn, html code.shiki .sQHwn{--shiki-light:#E36209;--shiki-default:#FFAB70;--shiki-dark:#FFAB70}html pre.shiki code .sCsY4, html code.shiki .sCsY4{--shiki-light:#6A737D;--shiki-default:#6A737D;--shiki-dark:#6A737D}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);}",{"title":202,"searchDepth":230,"depth":230,"links":751},[752],{"id":427,"depth":230,"text":428},"Serve static assets such as HTML, images, CSS, JavaScript, etc.","md",{"icon":139},{"icon":139},{"title":145,"description":753},"JZ5op164k0tXftlf0f8yOBEkVDj41cWQ8mQPhiS_sIY",[760,762],{"title":141,"path":142,"stem":143,"description":761,"icon":139,"children":-1},"Remember your users using a session.",{"title":149,"path":150,"stem":151,"description":763,"icon":139,"children":-1},"Stream response to the client.",1750976021838]