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