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