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