@webqit/webflo 0.20.1 → 0.20.2-next.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/site/.vitepress/config.ts +1 -0
- package/site/.vitepress/dist/-/_.html +56 -0
- package/site/.vitepress/dist/-/docs.old.html +679 -0
- package/site/.vitepress/dist/404.html +23 -0
- package/site/.vitepress/dist/api/webflo-fetch/FormData.html +55 -0
- package/site/.vitepress/dist/api/webflo-fetch/Headers.html +55 -0
- package/site/.vitepress/dist/api/webflo-fetch/LiveResponse.html +55 -0
- package/site/.vitepress/dist/api/webflo-fetch/Request.html +55 -0
- package/site/.vitepress/dist/api/webflo-fetch/Response.html +55 -0
- package/site/.vitepress/dist/api/webflo-fetch/fetch.html +55 -0
- package/site/.vitepress/dist/api/webflo-routing/HttpCookies.html +55 -0
- package/site/.vitepress/dist/api/webflo-routing/HttpEvent/respondWith.html +55 -0
- package/site/.vitepress/dist/api/webflo-routing/HttpEvent/waitUntil.html +55 -0
- package/site/.vitepress/dist/api/webflo-routing/HttpEvent/waitUntilNavigate.html +55 -0
- package/site/.vitepress/dist/api/webflo-routing/HttpEvent.html +55 -0
- package/site/.vitepress/dist/api/webflo-routing/HttpSession.html +55 -0
- package/site/.vitepress/dist/api/webflo-routing/HttpState.html +55 -0
- package/site/.vitepress/dist/api/webflo-routing/HttpUser.html +55 -0
- package/site/.vitepress/dist/api/webflo-routing/handler/fetch.html +59 -0
- package/site/.vitepress/dist/api/webflo-routing/handler/next.html +61 -0
- package/site/.vitepress/dist/api/webflo-routing/handler.html +65 -0
- package/site/.vitepress/dist/api.html +55 -0
- package/site/.vitepress/dist/assets/-__.md.wD5kDRhS.js +1 -0
- package/site/.vitepress/dist/assets/-__.md.wD5kDRhS.lean.js +1 -0
- package/site/.vitepress/dist/assets/-_docs.old.md.CiqucE_1.js +625 -0
- package/site/.vitepress/dist/assets/-_docs.old.md.CiqucE_1.lean.js +1 -0
- package/site/.vitepress/dist/assets/api.md.C9KRNLi_.js +1 -0
- package/site/.vitepress/dist/assets/api.md.C9KRNLi_.lean.js +1 -0
- package/site/.vitepress/dist/assets/api_webflo-fetch_FormData.md.CDuexUTz.js +1 -0
- package/site/.vitepress/dist/assets/api_webflo-fetch_FormData.md.CDuexUTz.lean.js +1 -0
- package/site/.vitepress/dist/assets/api_webflo-fetch_Headers.md.Cl_4-FUP.js +1 -0
- package/site/.vitepress/dist/assets/api_webflo-fetch_Headers.md.Cl_4-FUP.lean.js +1 -0
- package/site/.vitepress/dist/assets/api_webflo-fetch_LiveResponse.md.BMidKMB1.js +1 -0
- package/site/.vitepress/dist/assets/api_webflo-fetch_LiveResponse.md.BMidKMB1.lean.js +1 -0
- package/site/.vitepress/dist/assets/api_webflo-fetch_Request.md.DPwZCPmi.js +1 -0
- package/site/.vitepress/dist/assets/api_webflo-fetch_Request.md.DPwZCPmi.lean.js +1 -0
- package/site/.vitepress/dist/assets/api_webflo-fetch_Response.md.BaSyoOLE.js +1 -0
- package/site/.vitepress/dist/assets/api_webflo-fetch_Response.md.BaSyoOLE.lean.js +1 -0
- package/site/.vitepress/dist/assets/api_webflo-fetch_fetch.md.Bc9r3Q9I.js +1 -0
- package/site/.vitepress/dist/assets/api_webflo-fetch_fetch.md.Bc9r3Q9I.lean.js +1 -0
- package/site/.vitepress/dist/assets/api_webflo-routing_HttpCookies.md.B5ok3jrM.js +1 -0
- package/site/.vitepress/dist/assets/api_webflo-routing_HttpCookies.md.B5ok3jrM.lean.js +1 -0
- package/site/.vitepress/dist/assets/api_webflo-routing_HttpEvent.md.DBkSQRTa.js +1 -0
- package/site/.vitepress/dist/assets/api_webflo-routing_HttpEvent.md.DBkSQRTa.lean.js +1 -0
- package/site/.vitepress/dist/assets/api_webflo-routing_HttpEvent_respondWith.md.aAxq-5Ie.js +1 -0
- package/site/.vitepress/dist/assets/api_webflo-routing_HttpEvent_respondWith.md.aAxq-5Ie.lean.js +1 -0
- package/site/.vitepress/dist/assets/api_webflo-routing_HttpEvent_waitUntil.md.DyQZLhPR.js +1 -0
- package/site/.vitepress/dist/assets/api_webflo-routing_HttpEvent_waitUntil.md.DyQZLhPR.lean.js +1 -0
- package/site/.vitepress/dist/assets/api_webflo-routing_HttpEvent_waitUntilNavigate.md.DKLylwhl.js +1 -0
- package/site/.vitepress/dist/assets/api_webflo-routing_HttpEvent_waitUntilNavigate.md.DKLylwhl.lean.js +1 -0
- package/site/.vitepress/dist/assets/api_webflo-routing_HttpSession.md.bkeCy7_Q.js +1 -0
- package/site/.vitepress/dist/assets/api_webflo-routing_HttpSession.md.bkeCy7_Q.lean.js +1 -0
- package/site/.vitepress/dist/assets/api_webflo-routing_HttpState.md.DO53IAM1.js +1 -0
- package/site/.vitepress/dist/assets/api_webflo-routing_HttpState.md.DO53IAM1.lean.js +1 -0
- package/site/.vitepress/dist/assets/api_webflo-routing_HttpUser.md.CfsaBFdl.js +1 -0
- package/site/.vitepress/dist/assets/api_webflo-routing_HttpUser.md.CfsaBFdl.lean.js +1 -0
- package/site/.vitepress/dist/assets/api_webflo-routing_handler.md.B0eVFluL.js +11 -0
- package/site/.vitepress/dist/assets/api_webflo-routing_handler.md.B0eVFluL.lean.js +1 -0
- package/site/.vitepress/dist/assets/api_webflo-routing_handler_fetch.md.CpwUMFMz.js +1 -0
- package/site/.vitepress/dist/assets/api_webflo-routing_handler_fetch.md.CpwUMFMz.lean.js +1 -0
- package/site/.vitepress/dist/assets/api_webflo-routing_handler_next.md.CA4tDXtV.js +7 -0
- package/site/.vitepress/dist/assets/api_webflo-routing_handler_next.md.CA4tDXtV.lean.js +1 -0
- package/site/.vitepress/dist/assets/app.B989j-Lw.js +256 -0
- package/site/.vitepress/dist/assets/chunks/@localSearchIndexroot.IcaIAE_s.js +1 -0
- package/site/.vitepress/dist/assets/chunks/VPLocalSearchBox.CxstEVOs.js +8 -0
- package/site/.vitepress/dist/assets/chunks/arc.CNNknwAo.js +1 -0
- package/site/.vitepress/dist/assets/chunks/architectureDiagram-VXUJARFQ.DCLYhNHD.js +36 -0
- package/site/.vitepress/dist/assets/chunks/basePickBy.Cxi84nlK.js +1 -0
- package/site/.vitepress/dist/assets/chunks/baseUniq.DDTOgUAc.js +1 -0
- package/site/.vitepress/dist/assets/chunks/blockDiagram-VD42YOAC.BcpiarhA.js +122 -0
- package/site/.vitepress/dist/assets/chunks/c4Diagram-YG6GDRKO.BI_5dKaW.js +10 -0
- package/site/.vitepress/dist/assets/chunks/channel.CxIJmpCu.js +1 -0
- package/site/.vitepress/dist/assets/chunks/chunk-4BX2VUAB.C6goADHj.js +1 -0
- package/site/.vitepress/dist/assets/chunks/chunk-55IACEB6.BLGj4Pud.js +1 -0
- package/site/.vitepress/dist/assets/chunks/chunk-B4BG7PRW.DsAzxoJ_.js +165 -0
- package/site/.vitepress/dist/assets/chunks/chunk-DI55MBZ5.BnE2NeEC.js +220 -0
- package/site/.vitepress/dist/assets/chunks/chunk-FMBD7UC4.DGeT8zu4.js +15 -0
- package/site/.vitepress/dist/assets/chunks/chunk-QN33PNHL.Bc78W0xn.js +1 -0
- package/site/.vitepress/dist/assets/chunks/chunk-QZHKN3VN.BFSSbGEs.js +1 -0
- package/site/.vitepress/dist/assets/chunks/chunk-TZMSLE5B.DyZR9PPb.js +1 -0
- package/site/.vitepress/dist/assets/chunks/classDiagram-2ON5EDUG._0fUH5ha.js +1 -0
- package/site/.vitepress/dist/assets/chunks/classDiagram-v2-WZHVMYZB._0fUH5ha.js +1 -0
- package/site/.vitepress/dist/assets/chunks/clone.BYyOtvOD.js +1 -0
- package/site/.vitepress/dist/assets/chunks/cose-bilkent-S5V4N54A.TlhUFBAR.js +1 -0
- package/site/.vitepress/dist/assets/chunks/cytoscape.esm.CyJtwmzi.js +331 -0
- package/site/.vitepress/dist/assets/chunks/dagre-6UL2VRFP.D__9IqfC.js +4 -0
- package/site/.vitepress/dist/assets/chunks/defaultLocale.C4B-KCzX.js +1 -0
- package/site/.vitepress/dist/assets/chunks/diagram-PSM6KHXK.DYSDWndU.js +24 -0
- package/site/.vitepress/dist/assets/chunks/diagram-QEK2KX5R.FZi2c8WB.js +43 -0
- package/site/.vitepress/dist/assets/chunks/diagram-S2PKOQOG.D-Xxss9Z.js +24 -0
- package/site/.vitepress/dist/assets/chunks/erDiagram-Q2GNP2WA.CNdrcxqE.js +60 -0
- package/site/.vitepress/dist/assets/chunks/flowDiagram-NV44I4VS.C_6PWuGm.js +162 -0
- package/site/.vitepress/dist/assets/chunks/framework.9Uv4PgnO.js +18 -0
- package/site/.vitepress/dist/assets/chunks/ganttDiagram-LVOFAZNH._TBJejxF.js +267 -0
- package/site/.vitepress/dist/assets/chunks/gitGraphDiagram-NY62KEGX.BmQODSWS.js +65 -0
- package/site/.vitepress/dist/assets/chunks/graph.BHWe3GDJ.js +1 -0
- package/site/.vitepress/dist/assets/chunks/infoDiagram-ER5ION4S.CbdOaGtv.js +2 -0
- package/site/.vitepress/dist/assets/chunks/init.Gi6I4Gst.js +1 -0
- package/site/.vitepress/dist/assets/chunks/journeyDiagram-XKPGCS4Q.B-PjYmDZ.js +139 -0
- package/site/.vitepress/dist/assets/chunks/kanban-definition-3W4ZIXB7.Bc_8e9KR.js +89 -0
- package/site/.vitepress/dist/assets/chunks/katex.BbEIqZs1.js +261 -0
- package/site/.vitepress/dist/assets/chunks/layout.hswMW8l0.js +1 -0
- package/site/.vitepress/dist/assets/chunks/linear.CUHYPplj.js +1 -0
- package/site/.vitepress/dist/assets/chunks/mindmap-definition-VGOIOE7T.CvIaZI8e.js +68 -0
- package/site/.vitepress/dist/assets/chunks/ordinal.BYWQX77i.js +1 -0
- package/site/.vitepress/dist/assets/chunks/pieDiagram-ADFJNKIX.BSTQM2Ms.js +30 -0
- package/site/.vitepress/dist/assets/chunks/quadrantDiagram-AYHSOK5B.CkEJjNYC.js +7 -0
- package/site/.vitepress/dist/assets/chunks/requirementDiagram-UZGBJVZJ.QsTahBza.js +64 -0
- package/site/.vitepress/dist/assets/chunks/sankeyDiagram-TZEHDZUN.NRsUNMzF.js +10 -0
- package/site/.vitepress/dist/assets/chunks/sequenceDiagram-WL72ISMW.rq-YLOb-.js +145 -0
- package/site/.vitepress/dist/assets/chunks/stateDiagram-FKZM4ZOC.BseVQjcW.js +1 -0
- package/site/.vitepress/dist/assets/chunks/stateDiagram-v2-4FDKWEC3.CH4mdaj_.js +1 -0
- package/site/.vitepress/dist/assets/chunks/theme.Jp0RA4YE.js +2 -0
- package/site/.vitepress/dist/assets/chunks/timeline-definition-IT6M3QCI.N8DNMk16.js +61 -0
- package/site/.vitepress/dist/assets/chunks/treemap-KMMF4GRG.CAwkr_aP.js +128 -0
- package/site/.vitepress/dist/assets/chunks/virtual_mermaid-config.DDnGl6nM.js +1 -0
- package/site/.vitepress/dist/assets/chunks/xychartDiagram-PRI3JC2R.CF4KVQhG.js +7 -0
- package/site/.vitepress/dist/assets/contributing.md.gqIMCtVI.js +1 -0
- package/site/.vitepress/dist/assets/contributing.md.gqIMCtVI.lean.js +1 -0
- package/site/.vitepress/dist/assets/docs.md.hvbqYbFY.js +1 -0
- package/site/.vitepress/dist/assets/docs.md.hvbqYbFY.lean.js +1 -0
- package/site/.vitepress/dist/assets/docs_advanced.md.D048cxnq.js +1 -0
- package/site/.vitepress/dist/assets/docs_advanced.md.D048cxnq.lean.js +1 -0
- package/site/.vitepress/dist/assets/docs_advanced_lifecycles.md.BICPL-da.js +1 -0
- package/site/.vitepress/dist/assets/docs_advanced_lifecycles.md.BICPL-da.lean.js +1 -0
- package/site/.vitepress/dist/assets/docs_advanced_redirects.md.BMha6D3W.js +1 -0
- package/site/.vitepress/dist/assets/docs_advanced_redirects.md.BMha6D3W.lean.js +1 -0
- package/site/.vitepress/dist/assets/docs_advanced_routing.md.Cv63UDJF.js +1 -0
- package/site/.vitepress/dist/assets/docs_advanced_routing.md.Cv63UDJF.lean.js +1 -0
- package/site/.vitepress/dist/assets/docs_concepts.md.Clwx81Hz.js +3 -0
- package/site/.vitepress/dist/assets/docs_concepts.md.Clwx81Hz.lean.js +1 -0
- package/site/.vitepress/dist/assets/docs_concepts_realtime.md.CBrMq5Ln.js +218 -0
- package/site/.vitepress/dist/assets/docs_concepts_realtime.md.CBrMq5Ln.lean.js +1 -0
- package/site/.vitepress/dist/assets/docs_concepts_rendering.md.BWr5Lxgn.js +24 -0
- package/site/.vitepress/dist/assets/docs_concepts_rendering.md.BWr5Lxgn.lean.js +1 -0
- package/site/.vitepress/dist/assets/docs_concepts_request-response.md.DhplzNqt.js +4 -0
- package/site/.vitepress/dist/assets/docs_concepts_request-response.md.DhplzNqt.lean.js +1 -0
- package/site/.vitepress/dist/assets/docs_concepts_routing.md.C2KO1eAu.js +228 -0
- package/site/.vitepress/dist/assets/docs_concepts_routing.md.C2KO1eAu.lean.js +1 -0
- package/site/.vitepress/dist/assets/docs_concepts_state.md.CtbMVS_K.js +10 -0
- package/site/.vitepress/dist/assets/docs_concepts_state.md.CtbMVS_K.lean.js +1 -0
- package/site/.vitepress/dist/assets/docs_concepts_templates.md.4i6jQcYw.js +15 -0
- package/site/.vitepress/dist/assets/docs_concepts_templates.md.4i6jQcYw.lean.js +1 -0
- package/site/.vitepress/dist/assets/docs_getting-started.md.CNGtwB_L.js +75 -0
- package/site/.vitepress/dist/assets/docs_getting-started.md.CNGtwB_L.lean.js +1 -0
- package/site/.vitepress/dist/assets/docs_tech-stack.md.xiWGQstL.js +1 -0
- package/site/.vitepress/dist/assets/docs_tech-stack.md.xiWGQstL.lean.js +1 -0
- package/site/.vitepress/dist/assets/examples.md.BqDfJd4G.js +1 -0
- package/site/.vitepress/dist/assets/examples.md.BqDfJd4G.lean.js +1 -0
- package/site/.vitepress/dist/assets/examples_pwa.md.DREN7J2F.js +1 -0
- package/site/.vitepress/dist/assets/examples_pwa.md.DREN7J2F.lean.js +1 -0
- package/site/.vitepress/dist/assets/examples_web.md.DUhZ0IQL.js +1 -0
- package/site/.vitepress/dist/assets/examples_web.md.DUhZ0IQL.lean.js +1 -0
- package/site/.vitepress/dist/assets/faq.md.DtfXaXUI.js +1 -0
- package/site/.vitepress/dist/assets/faq.md.DtfXaXUI.lean.js +1 -0
- package/site/.vitepress/dist/assets/guides.md.BVdQyeU-.js +1 -0
- package/site/.vitepress/dist/assets/guides.md.BVdQyeU-.lean.js +1 -0
- package/site/.vitepress/dist/assets/guides_guide-auth.md.DNFuRudp.js +1 -0
- package/site/.vitepress/dist/assets/guides_guide-auth.md.DNFuRudp.lean.js +1 -0
- package/site/.vitepress/dist/assets/guides_guide-file-upload.md.DRbRLk7h.js +1 -0
- package/site/.vitepress/dist/assets/guides_guide-file-upload.md.DRbRLk7h.lean.js +1 -0
- package/site/.vitepress/dist/assets/guides_guide-service-worker.md.B0wEVcQw.js +1 -0
- package/site/.vitepress/dist/assets/guides_guide-service-worker.md.B0wEVcQw.lean.js +1 -0
- package/site/.vitepress/dist/assets/guides_tutorial-1-todo.md.D9ket3Re.js +3 -0
- package/site/.vitepress/dist/assets/guides_tutorial-1-todo.md.D9ket3Re.lean.js +1 -0
- package/site/.vitepress/dist/assets/index.md.DB-CsGEX.js +1 -0
- package/site/.vitepress/dist/assets/index.md.DB-CsGEX.lean.js +1 -0
- package/site/.vitepress/dist/assets/inter-italic-cyrillic-ext.r48I6akx.woff2 +0 -0
- package/site/.vitepress/dist/assets/inter-italic-cyrillic.By2_1cv3.woff2 +0 -0
- package/site/.vitepress/dist/assets/inter-italic-greek-ext.1u6EdAuj.woff2 +0 -0
- package/site/.vitepress/dist/assets/inter-italic-greek.DJ8dCoTZ.woff2 +0 -0
- package/site/.vitepress/dist/assets/inter-italic-latin-ext.CN1xVJS-.woff2 +0 -0
- package/site/.vitepress/dist/assets/inter-italic-latin.C2AdPX0b.woff2 +0 -0
- package/site/.vitepress/dist/assets/inter-italic-vietnamese.BSbpV94h.woff2 +0 -0
- package/site/.vitepress/dist/assets/inter-roman-cyrillic-ext.BBPuwvHQ.woff2 +0 -0
- package/site/.vitepress/dist/assets/inter-roman-cyrillic.C5lxZ8CY.woff2 +0 -0
- package/site/.vitepress/dist/assets/inter-roman-greek-ext.CqjqNYQ-.woff2 +0 -0
- package/site/.vitepress/dist/assets/inter-roman-greek.BBVDIX6e.woff2 +0 -0
- package/site/.vitepress/dist/assets/inter-roman-latin-ext.4ZJIpNVo.woff2 +0 -0
- package/site/.vitepress/dist/assets/inter-roman-latin.Di8DUHzh.woff2 +0 -0
- package/site/.vitepress/dist/assets/inter-roman-vietnamese.BjW4sHH5.woff2 +0 -0
- package/site/.vitepress/dist/assets/recipes_realtime.md.CX1Vs2FD.js +1 -0
- package/site/.vitepress/dist/assets/recipes_realtime.md.CX1Vs2FD.lean.js +1 -0
- package/site/.vitepress/dist/assets/recipes_streaming.md.C7GFShgF.js +5 -0
- package/site/.vitepress/dist/assets/recipes_streaming.md.C7GFShgF.lean.js +1 -0
- package/site/.vitepress/dist/assets/reference_cli.md.DERqaQJm.js +1 -0
- package/site/.vitepress/dist/assets/reference_cli.md.DERqaQJm.lean.js +1 -0
- package/site/.vitepress/dist/assets/reference_config.md.DI_yG-7N.js +1 -0
- package/site/.vitepress/dist/assets/reference_config.md.DI_yG-7N.lean.js +1 -0
- package/site/.vitepress/dist/assets/reference_tools.md.DZxjdVFX.js +1 -0
- package/site/.vitepress/dist/assets/reference_tools.md.DZxjdVFX.lean.js +1 -0
- package/site/.vitepress/dist/assets/style.BD0LzINo.css +1 -0
- package/site/.vitepress/dist/contributing.html +55 -0
- package/site/.vitepress/dist/docs/advanced/lifecycles.html +55 -0
- package/site/.vitepress/dist/docs/advanced/redirects.html +55 -0
- package/site/.vitepress/dist/docs/advanced/routing.html +55 -0
- package/site/.vitepress/dist/docs/advanced.html +55 -0
- package/site/.vitepress/dist/docs/concepts/realtime.html +272 -0
- package/site/.vitepress/dist/docs/concepts/rendering.html +78 -0
- package/site/.vitepress/dist/docs/concepts/request-response.html +58 -0
- package/site/.vitepress/dist/docs/concepts/routing.html +282 -0
- package/site/.vitepress/dist/docs/concepts/state.html +64 -0
- package/site/.vitepress/dist/docs/concepts/templates.html +69 -0
- package/site/.vitepress/dist/docs/concepts.html +57 -0
- package/site/.vitepress/dist/docs/getting-started.html +129 -0
- package/site/.vitepress/dist/docs/tech-stack.html +55 -0
- package/site/.vitepress/dist/docs.html +55 -0
- package/site/.vitepress/dist/examples/pwa.html +55 -0
- package/site/.vitepress/dist/examples/web.html +55 -0
- package/site/.vitepress/dist/examples.html +55 -0
- package/site/.vitepress/dist/faq.html +55 -0
- package/site/.vitepress/dist/guides/guide-auth.html +55 -0
- package/site/.vitepress/dist/guides/guide-file-upload.html +55 -0
- package/site/.vitepress/dist/guides/guide-service-worker.html +55 -0
- package/site/.vitepress/dist/guides/tutorial-1-todo.html +57 -0
- package/site/.vitepress/dist/guides.html +55 -0
- package/site/.vitepress/dist/hashmap.json +1 -0
- package/site/.vitepress/dist/img/brand/logo-670x670.png +0 -0
- package/site/.vitepress/dist/index.html +55 -0
- package/site/.vitepress/dist/recipes/realtime.html +55 -0
- package/site/.vitepress/dist/recipes/streaming.html +59 -0
- package/site/.vitepress/dist/reference/cli.html +55 -0
- package/site/.vitepress/dist/reference/config.html +55 -0
- package/site/.vitepress/dist/reference/tools.html +55 -0
- package/site/.vitepress/dist/vp-icons.css +1 -0
- package/site/.vitepress/cache/deps/@braintree_sanitize-url 2.js +0 -93
- package/site/.vitepress/cache/deps/@braintree_sanitize-url.js 2.map +0 -7
- package/site/.vitepress/cache/deps/_metadata 2.json +0 -85
- package/site/.vitepress/cache/deps/_metadata.json +0 -85
- package/site/.vitepress/cache/deps/chunk-BUSYA2B4 2.js +0 -9
- package/site/.vitepress/cache/deps/chunk-BUSYA2B4.js 2.map +0 -7
- package/site/.vitepress/cache/deps/chunk-Q2AYPHVK 2.js +0 -9719
- package/site/.vitepress/cache/deps/chunk-Q2AYPHVK.js 2.map +0 -7
- package/site/.vitepress/cache/deps/chunk-QAXAIFA7 2.js +0 -12705
- package/site/.vitepress/cache/deps/chunk-QAXAIFA7.js 2.map +0 -7
- package/site/.vitepress/cache/deps/cytoscape 2.js +0 -30278
- package/site/.vitepress/cache/deps/cytoscape-cose-bilkent 2.js +0 -4710
- package/site/.vitepress/cache/deps/cytoscape-cose-bilkent.js 2.map +0 -7
- package/site/.vitepress/cache/deps/cytoscape.js 2.map +0 -7
- package/site/.vitepress/cache/deps/dayjs 2.js +0 -285
- package/site/.vitepress/cache/deps/dayjs.js 2.map +0 -7
- package/site/.vitepress/cache/deps/debug 2.js +0 -453
- package/site/.vitepress/cache/deps/debug.js 2.map +0 -7
- package/site/.vitepress/cache/deps/package 2.json +0 -3
- package/site/.vitepress/cache/deps/vitepress___@vue_devtools-api 2.js +0 -4507
- package/site/.vitepress/cache/deps/vitepress___@vue_devtools-api.js 2.map +0 -7
- package/site/.vitepress/cache/deps/vitepress___@vueuse_core 2.js +0 -584
- package/site/.vitepress/cache/deps/vitepress___@vueuse_core.js 2.map +0 -7
- package/site/.vitepress/cache/deps/vitepress___@vueuse_integrations_useFocusTrap 2.js +0 -1166
- package/site/.vitepress/cache/deps/vitepress___@vueuse_integrations_useFocusTrap.js 2.map +0 -7
- package/site/.vitepress/cache/deps/vitepress___mark__js_src_vanilla__js 2.js +0 -1667
- package/site/.vitepress/cache/deps/vitepress___mark__js_src_vanilla__js.js 2.map +0 -7
- package/site/.vitepress/cache/deps/vitepress___minisearch 2.js +0 -1815
- package/site/.vitepress/cache/deps/vitepress___minisearch.js 2.map +0 -7
- package/site/.vitepress/cache/deps/vue 2.js +0 -344
- package/site/.vitepress/cache/deps/vue.js 2.map +0 -7
- /package/site/.vitepress/cache/{deps → deps_temp_9b107c53}/@braintree_sanitize-url.js +0 -0
- /package/site/.vitepress/cache/{deps → deps_temp_9b107c53}/@braintree_sanitize-url.js.map +0 -0
- /package/site/.vitepress/cache/{deps → deps_temp_9b107c53}/chunk-BUSYA2B4.js +0 -0
- /package/site/.vitepress/cache/{deps → deps_temp_9b107c53}/chunk-BUSYA2B4.js.map +0 -0
- /package/site/.vitepress/cache/{deps → deps_temp_9b107c53}/chunk-Q2AYPHVK.js +0 -0
- /package/site/.vitepress/cache/{deps → deps_temp_9b107c53}/chunk-Q2AYPHVK.js.map +0 -0
- /package/site/.vitepress/cache/{deps → deps_temp_9b107c53}/chunk-QAXAIFA7.js +0 -0
- /package/site/.vitepress/cache/{deps → deps_temp_9b107c53}/chunk-QAXAIFA7.js.map +0 -0
- /package/site/.vitepress/cache/{deps → deps_temp_9b107c53}/cytoscape-cose-bilkent.js +0 -0
- /package/site/.vitepress/cache/{deps → deps_temp_9b107c53}/cytoscape-cose-bilkent.js.map +0 -0
- /package/site/.vitepress/cache/{deps → deps_temp_9b107c53}/cytoscape.js +0 -0
- /package/site/.vitepress/cache/{deps → deps_temp_9b107c53}/cytoscape.js.map +0 -0
- /package/site/.vitepress/cache/{deps → deps_temp_9b107c53}/dayjs.js +0 -0
- /package/site/.vitepress/cache/{deps → deps_temp_9b107c53}/dayjs.js.map +0 -0
- /package/site/.vitepress/cache/{deps → deps_temp_9b107c53}/debug.js +0 -0
- /package/site/.vitepress/cache/{deps → deps_temp_9b107c53}/debug.js.map +0 -0
- /package/site/.vitepress/cache/{deps → deps_temp_9b107c53}/package.json +0 -0
- /package/site/.vitepress/cache/{deps → deps_temp_9b107c53}/vitepress___@vue_devtools-api.js +0 -0
- /package/site/.vitepress/cache/{deps → deps_temp_9b107c53}/vitepress___@vue_devtools-api.js.map +0 -0
- /package/site/.vitepress/cache/{deps → deps_temp_9b107c53}/vitepress___@vueuse_core.js +0 -0
- /package/site/.vitepress/cache/{deps → deps_temp_9b107c53}/vitepress___@vueuse_core.js.map +0 -0
- /package/site/.vitepress/cache/{deps → deps_temp_9b107c53}/vitepress___@vueuse_integrations_useFocusTrap.js +0 -0
- /package/site/.vitepress/cache/{deps → deps_temp_9b107c53}/vitepress___@vueuse_integrations_useFocusTrap.js.map +0 -0
- /package/site/.vitepress/cache/{deps → deps_temp_9b107c53}/vitepress___mark__js_src_vanilla__js.js +0 -0
- /package/site/.vitepress/cache/{deps → deps_temp_9b107c53}/vitepress___mark__js_src_vanilla__js.js.map +0 -0
- /package/site/.vitepress/cache/{deps → deps_temp_9b107c53}/vitepress___minisearch.js +0 -0
- /package/site/.vitepress/cache/{deps → deps_temp_9b107c53}/vitepress___minisearch.js.map +0 -0
- /package/site/.vitepress/cache/{deps → deps_temp_9b107c53}/vue.js +0 -0
- /package/site/.vitepress/cache/{deps → deps_temp_9b107c53}/vue.js.map +0 -0
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en-US" dir="ltr">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
6
|
+
<title>Webflo Routing | Webflo</title>
|
|
7
|
+
<meta name="description" content="A universal, standards-first web framework for building web-native apps.">
|
|
8
|
+
<meta name="generator" content="VitePress v1.6.4">
|
|
9
|
+
<link rel="preload stylesheet" href="/assets/style.BD0LzINo.css" as="style">
|
|
10
|
+
<link rel="preload stylesheet" href="/vp-icons.css" as="style">
|
|
11
|
+
|
|
12
|
+
<script type="module" src="/assets/app.B989j-Lw.js"></script>
|
|
13
|
+
<link rel="preload" href="/assets/inter-roman-latin.Di8DUHzh.woff2" as="font" type="font/woff2" crossorigin="">
|
|
14
|
+
<link rel="modulepreload" href="/assets/chunks/framework.9Uv4PgnO.js">
|
|
15
|
+
<link rel="modulepreload" href="/assets/chunks/theme.Jp0RA4YE.js">
|
|
16
|
+
<link rel="modulepreload" href="/assets/chunks/katex.BbEIqZs1.js">
|
|
17
|
+
<link rel="modulepreload" href="/assets/chunks/dagre-6UL2VRFP.D__9IqfC.js">
|
|
18
|
+
<link rel="modulepreload" href="/assets/chunks/cose-bilkent-S5V4N54A.TlhUFBAR.js">
|
|
19
|
+
<link rel="modulepreload" href="/assets/chunks/c4Diagram-YG6GDRKO.BI_5dKaW.js">
|
|
20
|
+
<link rel="modulepreload" href="/assets/chunks/flowDiagram-NV44I4VS.C_6PWuGm.js">
|
|
21
|
+
<link rel="modulepreload" href="/assets/chunks/erDiagram-Q2GNP2WA.CNdrcxqE.js">
|
|
22
|
+
<link rel="modulepreload" href="/assets/chunks/gitGraphDiagram-NY62KEGX.BmQODSWS.js">
|
|
23
|
+
<link rel="modulepreload" href="/assets/chunks/ganttDiagram-LVOFAZNH._TBJejxF.js">
|
|
24
|
+
<link rel="modulepreload" href="/assets/chunks/infoDiagram-ER5ION4S.CbdOaGtv.js">
|
|
25
|
+
<link rel="modulepreload" href="/assets/chunks/pieDiagram-ADFJNKIX.BSTQM2Ms.js">
|
|
26
|
+
<link rel="modulepreload" href="/assets/chunks/quadrantDiagram-AYHSOK5B.CkEJjNYC.js">
|
|
27
|
+
<link rel="modulepreload" href="/assets/chunks/xychartDiagram-PRI3JC2R.CF4KVQhG.js">
|
|
28
|
+
<link rel="modulepreload" href="/assets/chunks/requirementDiagram-UZGBJVZJ.QsTahBza.js">
|
|
29
|
+
<link rel="modulepreload" href="/assets/chunks/sequenceDiagram-WL72ISMW.rq-YLOb-.js">
|
|
30
|
+
<link rel="modulepreload" href="/assets/chunks/classDiagram-2ON5EDUG._0fUH5ha.js">
|
|
31
|
+
<link rel="modulepreload" href="/assets/chunks/classDiagram-v2-WZHVMYZB._0fUH5ha.js">
|
|
32
|
+
<link rel="modulepreload" href="/assets/chunks/stateDiagram-FKZM4ZOC.BseVQjcW.js">
|
|
33
|
+
<link rel="modulepreload" href="/assets/chunks/stateDiagram-v2-4FDKWEC3.CH4mdaj_.js">
|
|
34
|
+
<link rel="modulepreload" href="/assets/chunks/journeyDiagram-XKPGCS4Q.B-PjYmDZ.js">
|
|
35
|
+
<link rel="modulepreload" href="/assets/chunks/timeline-definition-IT6M3QCI.N8DNMk16.js">
|
|
36
|
+
<link rel="modulepreload" href="/assets/chunks/mindmap-definition-VGOIOE7T.CvIaZI8e.js">
|
|
37
|
+
<link rel="modulepreload" href="/assets/chunks/kanban-definition-3W4ZIXB7.Bc_8e9KR.js">
|
|
38
|
+
<link rel="modulepreload" href="/assets/chunks/sankeyDiagram-TZEHDZUN.NRsUNMzF.js">
|
|
39
|
+
<link rel="modulepreload" href="/assets/chunks/diagram-S2PKOQOG.D-Xxss9Z.js">
|
|
40
|
+
<link rel="modulepreload" href="/assets/chunks/diagram-QEK2KX5R.FZi2c8WB.js">
|
|
41
|
+
<link rel="modulepreload" href="/assets/chunks/blockDiagram-VD42YOAC.BcpiarhA.js">
|
|
42
|
+
<link rel="modulepreload" href="/assets/chunks/architectureDiagram-VXUJARFQ.DCLYhNHD.js">
|
|
43
|
+
<link rel="modulepreload" href="/assets/chunks/diagram-PSM6KHXK.DYSDWndU.js">
|
|
44
|
+
<link rel="modulepreload" href="/assets/chunks/virtual_mermaid-config.DDnGl6nM.js">
|
|
45
|
+
<link rel="modulepreload" href="/assets/docs_concepts_routing.md.C2KO1eAu.lean.js">
|
|
46
|
+
<meta name="theme-color" content="#0f172a">
|
|
47
|
+
<script id="check-dark-mode">document.documentElement.classList.add("dark");</script>
|
|
48
|
+
<script id="check-mac-os">document.documentElement.classList.toggle("mac",/Mac|iPhone|iPod|iPad/i.test(navigator.platform));</script>
|
|
49
|
+
</head>
|
|
50
|
+
<body>
|
|
51
|
+
<div id="app"><div class="Layout" data-v-5d98c3a5><!--[--><!--]--><!--[--><span tabindex="-1" data-v-0b0ada53></span><a href="#VPContent" class="VPSkipLink visually-hidden" data-v-0b0ada53>Skip to content</a><!--]--><!----><header class="VPNav" data-v-5d98c3a5 data-v-ae24b3ad><div class="VPNavBar" data-v-ae24b3ad data-v-6aa21345><div class="wrapper" data-v-6aa21345><div class="container" data-v-6aa21345><div class="title" data-v-6aa21345><div class="VPNavBarTitle has-sidebar" data-v-6aa21345 data-v-1168a8e4><a class="title" href="/" data-v-1168a8e4><!--[--><!--]--><!----><span data-v-1168a8e4>Webflo</span><!--[--><!--]--></a></div></div><div class="content" data-v-6aa21345><div class="content-body" data-v-6aa21345><!--[--><!--]--><div class="VPNavBarSearch search" data-v-6aa21345><!--[--><!----><div id="local-search"><button type="button" class="DocSearch DocSearch-Button" aria-label="Search"><span class="DocSearch-Button-Container"><span class="vp-icon DocSearch-Search-Icon"></span><span class="DocSearch-Button-Placeholder">Search</span></span><span class="DocSearch-Button-Keys"><kbd class="DocSearch-Button-Key"></kbd><kbd class="DocSearch-Button-Key">K</kbd></span></button></div><!--]--></div><nav aria-labelledby="main-nav-aria-label" class="VPNavBarMenu menu" data-v-6aa21345 data-v-dc692963><span id="main-nav-aria-label" class="visually-hidden" data-v-dc692963> Main Navigation </span><!--[--><!--[--><a class="VPLink link VPNavBarMenuLink active" href="/docs" tabindex="0" data-v-dc692963 data-v-e56f3d57><!--[--><span data-v-e56f3d57>Docs</span><!--]--></a><!--]--><!--[--><a class="VPLink link VPNavBarMenuLink" href="/api" tabindex="0" data-v-dc692963 data-v-e56f3d57><!--[--><span data-v-e56f3d57>API</span><!--]--></a><!--]--><!--[--><a class="VPLink link VPNavBarMenuLink" href="/guides" tabindex="0" data-v-dc692963 data-v-e56f3d57><!--[--><span data-v-e56f3d57>Guides</span><!--]--></a><!--]--><!--[--><a class="VPLink link VPNavBarMenuLink" href="/examples" tabindex="0" data-v-dc692963 data-v-e56f3d57><!--[--><span data-v-e56f3d57>Examples</span><!--]--></a><!--]--><!--]--></nav><!----><!----><div class="VPSocialLinks VPNavBarSocialLinks social-links" data-v-6aa21345 data-v-0394ad82 data-v-7bc22406><!--[--><a class="VPSocialLink no-icon" href="https://github.com/webqit/webflo" aria-label="github" target="_blank" rel="noopener" data-v-7bc22406 data-v-bd121fe5><span class="vpi-social-github"></span></a><!--]--></div><div class="VPFlyout VPNavBarExtra extra" data-v-6aa21345 data-v-bb2aa2f0 data-v-cf11d7a2><button type="button" class="button" aria-haspopup="true" aria-expanded="false" aria-label="extra navigation" data-v-cf11d7a2><span class="vpi-more-horizontal icon" data-v-cf11d7a2></span></button><div class="menu" data-v-cf11d7a2><div class="VPMenu" data-v-cf11d7a2 data-v-b98bc113><!----><!--[--><!--[--><!----><!----><div class="group" data-v-bb2aa2f0><div class="item social-links" data-v-bb2aa2f0><div class="VPSocialLinks social-links-list" data-v-bb2aa2f0 data-v-7bc22406><!--[--><a class="VPSocialLink no-icon" href="https://github.com/webqit/webflo" aria-label="github" target="_blank" rel="noopener" data-v-7bc22406 data-v-bd121fe5><span class="vpi-social-github"></span></a><!--]--></div></div></div><!--]--><!--]--></div></div></div><!--[--><!--]--><button type="button" class="VPNavBarHamburger hamburger" aria-label="mobile navigation" aria-expanded="false" aria-controls="VPNavScreen" data-v-6aa21345 data-v-e5dd9c1c><span class="container" data-v-e5dd9c1c><span class="top" data-v-e5dd9c1c></span><span class="middle" data-v-e5dd9c1c></span><span class="bottom" data-v-e5dd9c1c></span></span></button></div></div></div></div><div class="divider" data-v-6aa21345><div class="divider-line" data-v-6aa21345></div></div></div><!----></header><div class="VPLocalNav has-sidebar empty" data-v-5d98c3a5 data-v-a6f0e41e><div class="container" data-v-a6f0e41e><button class="menu" aria-expanded="false" aria-controls="VPSidebarNav" data-v-a6f0e41e><span class="vpi-align-left menu-icon" data-v-a6f0e41e></span><span class="menu-text" data-v-a6f0e41e>Menu</span></button><div class="VPLocalNavOutlineDropdown" style="--vp-vh:0px;" data-v-a6f0e41e data-v-8a42e2b4><button data-v-8a42e2b4>Return to top</button><!----></div></div></div><aside class="VPSidebar" data-v-5d98c3a5 data-v-319d5ca6><div class="curtain" data-v-319d5ca6></div><nav class="nav" id="VPSidebarNav" aria-labelledby="sidebar-aria-label" tabindex="-1" data-v-319d5ca6><span class="visually-hidden" id="sidebar-aria-label" data-v-319d5ca6> Sidebar Navigation </span><!--[--><!--]--><!--[--><div class="no-transition group" data-v-c40bc020><section class="VPSidebarItem level-0" data-v-c40bc020 data-v-b3fd67f8><div class="item" role="button" tabindex="0" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><h2 class="text" data-v-b3fd67f8>Getting Started</h2><!----></div><div class="items" data-v-b3fd67f8><!--[--><div class="VPSidebarItem level-1 is-link" data-v-b3fd67f8 data-v-b3fd67f8><div class="item" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><a class="VPLink link link" href="/docs" data-v-b3fd67f8><!--[--><p class="text" data-v-b3fd67f8>Welcome</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-b3fd67f8 data-v-b3fd67f8><div class="item" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><a class="VPLink link link" href="/docs/getting-started" data-v-b3fd67f8><!--[--><p class="text" data-v-b3fd67f8>Quickstart</p><!--]--></a><!----></div><!----></div><!--]--></div></section></div><div class="no-transition group" data-v-c40bc020><section class="VPSidebarItem level-0 has-active" data-v-c40bc020 data-v-b3fd67f8><div class="item" role="button" tabindex="0" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><h2 class="text" data-v-b3fd67f8>Concepts</h2><!----></div><div class="items" data-v-b3fd67f8><!--[--><div class="VPSidebarItem level-1 is-link" data-v-b3fd67f8 data-v-b3fd67f8><div class="item" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><a class="VPLink link link" href="/docs/concepts" data-v-b3fd67f8><!--[--><p class="text" data-v-b3fd67f8>Concepts Overview</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-b3fd67f8 data-v-b3fd67f8><div class="item" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><a class="VPLink link link" href="/docs/concepts/routing" data-v-b3fd67f8><!--[--><p class="text" data-v-b3fd67f8>Webflo Routing</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-b3fd67f8 data-v-b3fd67f8><div class="item" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><a class="VPLink link link" href="/docs/concepts/rendering" data-v-b3fd67f8><!--[--><p class="text" data-v-b3fd67f8>Rendering</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-b3fd67f8 data-v-b3fd67f8><div class="item" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><a class="VPLink link link" href="/docs/concepts/templates" data-v-b3fd67f8><!--[--><p class="text" data-v-b3fd67f8>Templates</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-b3fd67f8 data-v-b3fd67f8><div class="item" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><a class="VPLink link link" href="/docs/concepts/state" data-v-b3fd67f8><!--[--><p class="text" data-v-b3fd67f8>State Management</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-b3fd67f8 data-v-b3fd67f8><div class="item" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><a class="VPLink link link" href="/docs/concepts/request-response" data-v-b3fd67f8><!--[--><p class="text" data-v-b3fd67f8>Request/Response Lifecycle</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-b3fd67f8 data-v-b3fd67f8><div class="item" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><a class="VPLink link link" href="/docs/concepts/realtime" data-v-b3fd67f8><!--[--><p class="text" data-v-b3fd67f8>Webflo Realtime</p><!--]--></a><!----></div><!----></div><!--]--></div></section></div><div class="no-transition group" data-v-c40bc020><section class="VPSidebarItem level-0" data-v-c40bc020 data-v-b3fd67f8><div class="item" role="button" tabindex="0" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><h2 class="text" data-v-b3fd67f8>Advanced</h2><!----></div><div class="items" data-v-b3fd67f8><!--[--><div class="VPSidebarItem level-1 is-link" data-v-b3fd67f8 data-v-b3fd67f8><div class="item" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><a class="VPLink link link" href="/docs/advanced" data-v-b3fd67f8><!--[--><p class="text" data-v-b3fd67f8>Advanced Overview</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-b3fd67f8 data-v-b3fd67f8><div class="item" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><a class="VPLink link link" href="/docs/advanced/redirects" data-v-b3fd67f8><!--[--><p class="text" data-v-b3fd67f8>Redirects</p><!--]--></a><!----></div><!----></div><!--]--></div></section></div><div class="no-transition group" data-v-c40bc020><section class="VPSidebarItem level-0" data-v-c40bc020 data-v-b3fd67f8><div class="item" role="button" tabindex="0" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><h2 class="text" data-v-b3fd67f8>API Reference</h2><!----></div><div class="items" data-v-b3fd67f8><!--[--><section class="VPSidebarItem level-1 collapsible collapsed" data-v-b3fd67f8 data-v-b3fd67f8><div class="item" role="button" tabindex="0" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><h3 class="text" data-v-b3fd67f8>Webflo Routing</h3><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-b3fd67f8><span class="vpi-chevron-right caret-icon" data-v-b3fd67f8></span></div></div><div class="items" data-v-b3fd67f8><!--[--><div class="VPSidebarItem level-2 is-link" data-v-b3fd67f8 data-v-b3fd67f8><div class="item" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><a class="VPLink link link" href="/api/webflo-routing/handler" data-v-b3fd67f8><!--[--><p class="text" data-v-b3fd67f8>Handler</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-b3fd67f8 data-v-b3fd67f8><div class="item" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><a class="VPLink link link" href="/api/webflo-routing/HttpEvent" data-v-b3fd67f8><!--[--><p class="text" data-v-b3fd67f8>HttpEvent</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-b3fd67f8 data-v-b3fd67f8><div class="item" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><a class="VPLink link link" href="/api/webflo-routing/handler/next" data-v-b3fd67f8><!--[--><p class="text" data-v-b3fd67f8>next</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-b3fd67f8 data-v-b3fd67f8><div class="item" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><a class="VPLink link link" href="/api/webflo-routing/handler/fetch" data-v-b3fd67f8><!--[--><p class="text" data-v-b3fd67f8>fetch</p><!--]--></a><!----></div><!----></div><!--]--></div></section><section class="VPSidebarItem level-1 collapsible collapsed" data-v-b3fd67f8 data-v-b3fd67f8><div class="item" role="button" tabindex="0" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><h3 class="text" data-v-b3fd67f8>Webflo Fetch</h3><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-b3fd67f8><span class="vpi-chevron-right caret-icon" data-v-b3fd67f8></span></div></div><div class="items" data-v-b3fd67f8><!--[--><div class="VPSidebarItem level-2 is-link" data-v-b3fd67f8 data-v-b3fd67f8><div class="item" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><a class="VPLink link link" href="/api/webflo-fetch/fetch" data-v-b3fd67f8><!--[--><p class="text" data-v-b3fd67f8>fetch</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-b3fd67f8 data-v-b3fd67f8><div class="item" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><a class="VPLink link link" href="/api/webflo-fetch/Request" data-v-b3fd67f8><!--[--><p class="text" data-v-b3fd67f8>Request</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-b3fd67f8 data-v-b3fd67f8><div class="item" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><a class="VPLink link link" href="/api/webflo-fetch/Response" data-v-b3fd67f8><!--[--><p class="text" data-v-b3fd67f8>Response</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-b3fd67f8 data-v-b3fd67f8><div class="item" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><a class="VPLink link link" href="/api/webflo-fetch/LiveResponse" data-v-b3fd67f8><!--[--><p class="text" data-v-b3fd67f8>LiveResponse</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-b3fd67f8 data-v-b3fd67f8><div class="item" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><a class="VPLink link link" href="/api/webflo-fetch/FormData" data-v-b3fd67f8><!--[--><p class="text" data-v-b3fd67f8>FormData</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-b3fd67f8 data-v-b3fd67f8><div class="item" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><a class="VPLink link link" href="/api/webflo-fetch/Headers" data-v-b3fd67f8><!--[--><p class="text" data-v-b3fd67f8>Headers</p><!--]--></a><!----></div><!----></div><!--]--></div></section><section class="VPSidebarItem level-1 collapsible collapsed" data-v-b3fd67f8 data-v-b3fd67f8><div class="item" role="button" tabindex="0" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><h3 class="text" data-v-b3fd67f8>Webflo Messaging</h3><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-b3fd67f8><span class="vpi-chevron-right caret-icon" data-v-b3fd67f8></span></div></div><div class="items" data-v-b3fd67f8><!--[--><div class="VPSidebarItem level-2 is-link" data-v-b3fd67f8 data-v-b3fd67f8><div class="item" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><a class="VPLink link link" href="/api/webflo-messaging/MessageChannel" data-v-b3fd67f8><!--[--><p class="text" data-v-b3fd67f8>MessageChannel</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-b3fd67f8 data-v-b3fd67f8><div class="item" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><a class="VPLink link link" href="/api/webflo-messaging/MessagePort" data-v-b3fd67f8><!--[--><p class="text" data-v-b3fd67f8>MessagePort</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-b3fd67f8 data-v-b3fd67f8><div class="item" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><a class="VPLink link link" href="/api/webflo-messaging/MessageEvent" data-v-b3fd67f8><!--[--><p class="text" data-v-b3fd67f8>MessageEvent</p><!--]--></a><!----></div><!----></div><!--]--></div></section><!--]--></div></section></div><div class="no-transition group" data-v-c40bc020><section class="VPSidebarItem level-0" data-v-c40bc020 data-v-b3fd67f8><div class="item" role="button" tabindex="0" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><h2 class="text" data-v-b3fd67f8>Guides & Recipes</h2><!----></div><div class="items" data-v-b3fd67f8><!--[--><div class="VPSidebarItem level-1 is-link" data-v-b3fd67f8 data-v-b3fd67f8><div class="item" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><a class="VPLink link link" href="/guides/tutorial-1-todo" data-v-b3fd67f8><!--[--><p class="text" data-v-b3fd67f8>Tutorial: Todo App</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-b3fd67f8 data-v-b3fd67f8><div class="item" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><a class="VPLink link link" href="/guides/guide-auth" data-v-b3fd67f8><!--[--><p class="text" data-v-b3fd67f8>Auth</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-b3fd67f8 data-v-b3fd67f8><div class="item" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><a class="VPLink link link" href="/guides/guide-file-upload" data-v-b3fd67f8><!--[--><p class="text" data-v-b3fd67f8>File Upload</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-b3fd67f8 data-v-b3fd67f8><div class="item" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><a class="VPLink link link" href="/guides/guide-service-worker" data-v-b3fd67f8><!--[--><p class="text" data-v-b3fd67f8>Service Worker</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-b3fd67f8 data-v-b3fd67f8><div class="item" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><a class="VPLink link link" href="/recipes/streaming" data-v-b3fd67f8><!--[--><p class="text" data-v-b3fd67f8>Streaming</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-b3fd67f8 data-v-b3fd67f8><div class="item" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><a class="VPLink link link" href="/recipes/realtime" data-v-b3fd67f8><!--[--><p class="text" data-v-b3fd67f8>Realtime Patterns</p><!--]--></a><!----></div><!----></div><!--]--></div></section></div><div class="no-transition group" data-v-c40bc020><section class="VPSidebarItem level-0" data-v-c40bc020 data-v-b3fd67f8><div class="item" role="button" tabindex="0" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><h2 class="text" data-v-b3fd67f8>Examples</h2><!----></div><div class="items" data-v-b3fd67f8><!--[--><div class="VPSidebarItem level-1 is-link" data-v-b3fd67f8 data-v-b3fd67f8><div class="item" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><a class="VPLink link link" href="/examples/web" data-v-b3fd67f8><!--[--><p class="text" data-v-b3fd67f8>Web Example</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-b3fd67f8 data-v-b3fd67f8><div class="item" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><a class="VPLink link link" href="/examples/pwa" data-v-b3fd67f8><!--[--><p class="text" data-v-b3fd67f8>PWA Example</p><!--]--></a><!----></div><!----></div><!--]--></div></section></div><div class="no-transition group" data-v-c40bc020><section class="VPSidebarItem level-0" data-v-c40bc020 data-v-b3fd67f8><div class="item" role="button" tabindex="0" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><h2 class="text" data-v-b3fd67f8>Reference</h2><!----></div><div class="items" data-v-b3fd67f8><!--[--><div class="VPSidebarItem level-1 is-link" data-v-b3fd67f8 data-v-b3fd67f8><div class="item" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><a class="VPLink link link" href="/reference/cli" data-v-b3fd67f8><!--[--><p class="text" data-v-b3fd67f8>CLI</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-b3fd67f8 data-v-b3fd67f8><div class="item" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><a class="VPLink link link" href="/reference/config" data-v-b3fd67f8><!--[--><p class="text" data-v-b3fd67f8>Config</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-b3fd67f8 data-v-b3fd67f8><div class="item" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><a class="VPLink link link" href="/reference/tools" data-v-b3fd67f8><!--[--><p class="text" data-v-b3fd67f8>Tools</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-b3fd67f8 data-v-b3fd67f8><div class="item" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><a class="VPLink link link" href="/faq" data-v-b3fd67f8><!--[--><p class="text" data-v-b3fd67f8>FAQ</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-b3fd67f8 data-v-b3fd67f8><div class="item" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><a class="VPLink link link" href="/contributing" data-v-b3fd67f8><!--[--><p class="text" data-v-b3fd67f8>Contributing</p><!--]--></a><!----></div><!----></div><!--]--></div></section></div><!--]--><!--[--><!--]--></nav></aside><div class="VPContent has-sidebar" id="VPContent" data-v-5d98c3a5 data-v-1428d186><div class="VPDoc has-sidebar has-aside" data-v-1428d186 data-v-39a288b8><!--[--><!--]--><div class="container" data-v-39a288b8><div class="aside" data-v-39a288b8><div class="aside-curtain" data-v-39a288b8></div><div class="aside-container" data-v-39a288b8><div class="aside-content" data-v-39a288b8><div class="VPDocAside" data-v-39a288b8 data-v-3f215769><!--[--><!--]--><!--[--><!--]--><nav aria-labelledby="doc-outline-aria-label" class="VPDocAsideOutline" data-v-3f215769 data-v-a5bbad30><div class="content" data-v-a5bbad30><div class="outline-marker" data-v-a5bbad30></div><div aria-level="2" class="outline-title" id="doc-outline-aria-label" role="heading" data-v-a5bbad30>On this page</div><ul class="VPDocOutlineItem root" data-v-a5bbad30 data-v-b933a997><!--[--><!--]--></ul></div></nav><!--[--><!--]--><div class="spacer" data-v-3f215769></div><!--[--><!--]--><!----><!--[--><!--]--><!--[--><!--]--></div></div></div></div><div class="content" data-v-39a288b8><div class="content-container" data-v-39a288b8><!--[--><!--]--><main class="main" data-v-39a288b8><div style="position:relative;" class="vp-doc _docs_concepts_routing" data-v-39a288b8><div><h1 id="webflo-routing" tabindex="-1">Webflo Routing <a class="header-anchor" href="#webflo-routing" aria-label="Permalink to "Webflo Routing""></a></h1><p>Functions come into play in Webflo when you need to dynamically handle requests. Routing defines how those requests map to functions in a Webflo application. It determines which handler responds to a given URL, how requests move across layers of the stack, and how each step in that process composes into a complete response.</p><h2 id="layout-convention" tabindex="-1">Layout Convention <a class="header-anchor" href="#layout-convention" aria-label="Permalink to "Layout Convention""></a></h2><p>In Webflo, <strong>your filesystem <em>is</em> the router</strong>. Each folder under <code>app/</code> corresponds to a segment in your application’s URL path, and each handler file in that folder defines what happens at that segment.</p><div class="language-html"><button title="Copy Code" class="copy"></button><span class="lang">html</span><pre class="shiki material-theme-palenight vp-code" tabindex="0"><code><span class="line"><span style="color:#BABED8;">app/</span></span>
|
|
52
|
+
<span class="line"><span style="color:#BABED8;">├── handler.server.js → /</span></span>
|
|
53
|
+
<span class="line"><span style="color:#BABED8;">├── about/handler.server.js → /about</span></span>
|
|
54
|
+
<span class="line"><span style="color:#BABED8;">├── products/handler.server.js → /products</span></span>
|
|
55
|
+
<span class="line"><span style="color:#BABED8;">└── products/stickers/handler.server.js → /products/stickers</span></span></code></pre></div><p>Handlers can be designed to match any segment using wildcards. A folder named <code>-</code> acts as a catch-all at its level.</p><div class="language-html"><button title="Copy Code" class="copy"></button><span class="lang">html</span><pre class="shiki material-theme-palenight vp-code" tabindex="0"><code><span class="line"><span style="color:#BABED8;">app/</span></span>
|
|
56
|
+
<span class="line"><span style="color:#BABED8;">├── -/handler.server.js → /*</span></span>
|
|
57
|
+
<span class="line"><span style="color:#BABED8;">└── products/-/handler.server.js → /products/*</span></span></code></pre></div><h2 id="handlers" tabindex="-1">Handlers <a class="header-anchor" href="#handlers" aria-label="Permalink to "Handlers""></a></h2><p>Handlers are standard JavaScript functions that process requests and return responses. They share the same base signature:</p><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight vp-code" tabindex="0"><code><span class="line"><span style="color:#89DDFF;font-style:italic;">export</span><span style="color:#89DDFF;font-style:italic;"> default</span><span style="color:#C792EA;"> async</span><span style="color:#C792EA;"> function</span><span style="color:#89DDFF;"> (</span><span style="color:#BABED8;font-style:italic;">event</span><span style="color:#89DDFF;">,</span><span style="color:#BABED8;font-style:italic;"> next</span><span style="color:#89DDFF;">,</span><span style="color:#BABED8;font-style:italic;"> fetch</span><span style="color:#89DDFF;">)</span><span style="color:#89DDFF;"> {</span></span>
|
|
58
|
+
<span class="line"><span style="color:#89DDFF;font-style:italic;"> if</span><span style="color:#F07178;"> (</span><span style="color:#BABED8;">next</span><span style="color:#89DDFF;">.</span><span style="color:#BABED8;">stepname</span><span style="color:#F07178;">) </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#89DDFF;font-style:italic;"> await</span><span style="color:#82AAFF;"> next</span><span style="color:#F07178;">()</span><span style="color:#89DDFF;">;</span></span>
|
|
59
|
+
<span class="line"><span style="color:#89DDFF;font-style:italic;"> return</span><span style="color:#89DDFF;"> {</span><span style="color:#F07178;"> title</span><span style="color:#89DDFF;">:</span><span style="color:#89DDFF;"> '</span><span style="color:#C3E88D;">Welcome to Webflo</span><span style="color:#89DDFF;">'</span><span style="color:#89DDFF;"> };</span></span>
|
|
60
|
+
<span class="line"><span style="color:#89DDFF;">}</span></span></code></pre></div><p>A route may provide <strong><a href="/api/webflo-routing/handler#naming">named exports</a></strong> to map specific HTTP requests to specific handlers:</p><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight vp-code" tabindex="0"><code><span class="line"><span style="color:#89DDFF;font-style:italic;">export</span><span style="color:#C792EA;"> async</span><span style="color:#C792EA;"> function</span><span style="color:#82AAFF;"> GET</span><span style="color:#89DDFF;">(</span><span style="color:#BABED8;font-style:italic;">event</span><span style="color:#89DDFF;">,</span><span style="color:#BABED8;font-style:italic;"> next</span><span style="color:#89DDFF;">)</span><span style="color:#89DDFF;"> {</span><span style="color:#676E95;font-style:italic;"> /* ... */</span><span style="color:#89DDFF;"> }</span></span></code></pre></div><p>Handlers are fully covered in the <a href="/api/webflo-routing/handler">Handler API</a> section, but below is an overview.</p><h3 id="parameters" tabindex="-1">Parameters <a class="header-anchor" href="#parameters" aria-label="Permalink to "Parameters""></a></h3><p>Parameters recieved include:</p><table tabindex="0"><thead><tr><th style="text-align:left;">Parameter</th><th style="text-align:left;">Type</th><th style="text-align:left;">Description</th></tr></thead><tbody><tr><td style="text-align:left;"><code>event</code></td><td style="text-align:left;"><a href="/api/webflo-routing/HttpEvent"><code>HttpEvent</code></a></td><td style="text-align:left;">Current HTTP event.</td></tr><tr><td style="text-align:left;"><code>next</code></td><td style="text-align:left;"><a href="/api/webflo-routing/handler/next"><code>next</code></a></td><td style="text-align:left;">Control delegation function.</td></tr><tr><td style="text-align:left;"><code>fetch</code></td><td style="text-align:left;"><a href="/api/webflo-routing/handler/fetch"><code>fetch</code></a></td><td style="text-align:left;">Context-aware fetch API for inbound and outbound calls.</td></tr></tbody></table><h3 id="contextual-parameters" tabindex="-1">Contextual Parameters <a class="header-anchor" href="#contextual-parameters" aria-label="Permalink to "Contextual Parameters""></a></h3><p>Within a handler, contextual properties are available on the <a href="/api/webflo-routing/handler#the-this-context"><code>this</code></a> and <a href="/api/webflo-routing/handler/next"><code>next</code></a> interfaces:</p><table tabindex="0"><thead><tr><th style="text-align:left;">Property</th><th style="text-align:left;">Type</th><th>Description</th></tr></thead><tbody><tr><td style="text-align:left;"><code>next.stepname</code></td><td style="text-align:left;"><code>string</code></td><td>The name of the next segment in the URL.</td></tr><tr><td style="text-align:left;"><code>next.pathname</code></td><td style="text-align:left;"><code>string</code></td><td>The full path <em>beyond</em> the the active step.</td></tr><tr><td style="text-align:left;"><code>this.stepname</code></td><td style="text-align:left;"><code>string</code></td><td>The current directory segment being handled.</td></tr><tr><td style="text-align:left;"><code>this.pathname</code></td><td style="text-align:left;"><code>string</code></td><td>The current URL pathname <em>up to</em> the active step.</td></tr><tr><td style="text-align:left;"><code>this.filename</code></td><td style="text-align:left;"><code>string</code></td><td>The filename of the executing handler (server-side only)</td></tr></tbody></table><p>Use these for conditional delegation, or per-segment rules.</p><h3 id="your-first-handler-again" tabindex="-1">Your First Handler (Again) <a class="header-anchor" href="#your-first-handler-again" aria-label="Permalink to "Your First Handler (Again)""></a></h3><p>Your application's routes may be designed with as many or as few handlers as desired.<br> The contextual parameters <code>next.stepname</code> and <code>next.pathname</code> totally make it possible to fit routing logic into a single handler.</p><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight vp-code" tabindex="0"><code><span class="line"><span style="color:#89DDFF;font-style:italic;">export</span><span style="color:#89DDFF;font-style:italic;"> default</span><span style="color:#C792EA;"> function</span><span style="color:#89DDFF;">(</span><span style="color:#BABED8;font-style:italic;">event</span><span style="color:#89DDFF;">,</span><span style="color:#BABED8;font-style:italic;"> next</span><span style="color:#89DDFF;">)</span><span style="color:#89DDFF;"> {</span></span>
|
|
61
|
+
<span class="line"><span style="color:#676E95;font-style:italic;"> // For http://localhost:3000/products</span></span>
|
|
62
|
+
<span class="line"><span style="color:#89DDFF;font-style:italic;"> if</span><span style="color:#F07178;"> (</span><span style="color:#BABED8;">next</span><span style="color:#89DDFF;">.</span><span style="color:#BABED8;">pathname</span><span style="color:#89DDFF;"> ===</span><span style="color:#89DDFF;"> '</span><span style="color:#C3E88D;">products</span><span style="color:#89DDFF;">'</span><span style="color:#F07178;">) </span><span style="color:#89DDFF;">{</span></span>
|
|
63
|
+
<span class="line"><span style="color:#89DDFF;font-style:italic;"> return</span><span style="color:#89DDFF;"> {</span><span style="color:#F07178;"> title</span><span style="color:#89DDFF;">:</span><span style="color:#89DDFF;"> '</span><span style="color:#C3E88D;">Products</span><span style="color:#89DDFF;">'</span><span style="color:#89DDFF;"> };</span></span>
|
|
64
|
+
<span class="line"><span style="color:#89DDFF;"> }</span></span>
|
|
65
|
+
<span class="line"></span>
|
|
66
|
+
<span class="line"><span style="color:#676E95;font-style:italic;"> // For http://localhost:3000/products/stickers</span></span>
|
|
67
|
+
<span class="line"><span style="color:#89DDFF;font-style:italic;"> if</span><span style="color:#F07178;"> (</span><span style="color:#BABED8;">next</span><span style="color:#89DDFF;">.</span><span style="color:#BABED8;">pathname</span><span style="color:#89DDFF;"> ===</span><span style="color:#89DDFF;"> '</span><span style="color:#C3E88D;">products/stickers</span><span style="color:#89DDFF;">'</span><span style="color:#F07178;">) </span><span style="color:#89DDFF;">{</span></span>
|
|
68
|
+
<span class="line"><span style="color:#89DDFF;font-style:italic;"> return</span><span style="color:#89DDFF;"> {</span><span style="color:#F07178;"> title</span><span style="color:#89DDFF;">:</span><span style="color:#89DDFF;"> '</span><span style="color:#C3E88D;">Stickers</span><span style="color:#89DDFF;">'</span><span style="color:#89DDFF;"> };</span></span>
|
|
69
|
+
<span class="line"><span style="color:#89DDFF;"> }</span></span>
|
|
70
|
+
<span class="line"><span style="color:#F07178;"> </span></span>
|
|
71
|
+
<span class="line"><span style="color:#676E95;font-style:italic;"> // Should we later support other URLs like static assets http://localhost:3000/logo.png</span></span>
|
|
72
|
+
<span class="line"><span style="color:#89DDFF;font-style:italic;"> if</span><span style="color:#F07178;"> (</span><span style="color:#BABED8;">next</span><span style="color:#89DDFF;">.</span><span style="color:#BABED8;">pathname</span><span style="color:#F07178;">) </span><span style="color:#89DDFF;">{</span></span>
|
|
73
|
+
<span class="line"><span style="color:#89DDFF;font-style:italic;"> return</span><span style="color:#82AAFF;"> next</span><span style="color:#F07178;">()</span><span style="color:#89DDFF;">;</span></span>
|
|
74
|
+
<span class="line"><span style="color:#89DDFF;"> }</span></span>
|
|
75
|
+
<span class="line"><span style="color:#F07178;"> </span></span>
|
|
76
|
+
<span class="line"><span style="color:#676E95;font-style:italic;"> // For the root URL http://localhost:3000</span></span>
|
|
77
|
+
<span class="line"><span style="color:#89DDFF;font-style:italic;"> return</span><span style="color:#89DDFF;"> {</span><span style="color:#F07178;"> title</span><span style="color:#89DDFF;">:</span><span style="color:#89DDFF;"> '</span><span style="color:#C3E88D;">Home</span><span style="color:#89DDFF;">'</span><span style="color:#89DDFF;"> };</span></span>
|
|
78
|
+
<span class="line"><span style="color:#89DDFF;">}</span></span></code></pre></div><p>But the power of Webflo routing model really shines as you spread out to more handlers.</p><h2 id="the-delegation-model" tabindex="-1">The Delegation Model <a class="header-anchor" href="#the-delegation-model" aria-label="Permalink to "The Delegation Model""></a></h2><p>In Webflo, nested URLs such as <code>/products/stickers</code> don’t directly invoke their corresponding leaf handler (<code>app/products/stickers/handler.server.js</code>) in isolation. Instead, requests are handled <strong>step-by-step — from parent to child</strong>, forming a <strong>pipeline</strong>.</p><p>The <code>next()</code> function is how a handler delegates control to the next step in that pipeline.</p><p>This is simulated below for a URL like <code>/products/stickers</code>.<br> Each handler uses <code>next()</code> to delegate, and the final step returns the response.</p><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight vp-code" tabindex="0"><code><span class="line"><span style="color:#BABED8;">┌──────────┐ ┌──────────────┐ ┌──────────────────┐</span></span>
|
|
79
|
+
<span class="line"><span style="color:#BABED8;">│ app</span><span style="color:#89DDFF;">/</span><span style="color:#BABED8;"> │ → │ products</span><span style="color:#89DDFF;">/</span><span style="color:#BABED8;"> │ → │ stickers</span><span style="color:#89DDFF;">/</span><span style="color:#BABED8;"> │</span></span>
|
|
80
|
+
<span class="line"><span style="color:#BABED8;">│ handler │ │ handler │ │ handler │</span></span>
|
|
81
|
+
<span class="line"><span style="color:#BABED8;">│ </span><span style="color:#82AAFF;">next</span><span style="color:#BABED8;">() │ │ </span><span style="color:#82AAFF;">next</span><span style="color:#BABED8;">() │ │ </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#89DDFF;"> {}</span><span style="color:#BABED8;"> │</span></span>
|
|
82
|
+
<span class="line"><span style="color:#BABED8;">└──────────┘ └──────────────┘ └──────────────────┘</span></span></code></pre></div><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight vp-code" tabindex="0"><code><span class="line"><span style="color:#676E95;font-style:italic;">// app/handler.server.js</span></span>
|
|
83
|
+
<span class="line"><span style="color:#89DDFF;font-style:italic;">export</span><span style="color:#89DDFF;font-style:italic;"> default</span><span style="color:#C792EA;"> async</span><span style="color:#C792EA;"> function</span><span style="color:#89DDFF;"> (</span><span style="color:#BABED8;font-style:italic;">event</span><span style="color:#89DDFF;">,</span><span style="color:#BABED8;font-style:italic;"> next</span><span style="color:#89DDFF;">)</span><span style="color:#89DDFF;"> {</span></span>
|
|
84
|
+
<span class="line"><span style="color:#89DDFF;font-style:italic;"> if</span><span style="color:#F07178;"> (</span><span style="color:#BABED8;">next</span><span style="color:#89DDFF;">.</span><span style="color:#BABED8;">stepname</span><span style="color:#F07178;">) </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#89DDFF;font-style:italic;"> await</span><span style="color:#82AAFF;"> next</span><span style="color:#F07178;">()</span><span style="color:#89DDFF;">;</span></span>
|
|
85
|
+
<span class="line"><span style="color:#89DDFF;font-style:italic;"> return</span><span style="color:#89DDFF;"> {</span><span style="color:#F07178;"> title</span><span style="color:#89DDFF;">:</span><span style="color:#89DDFF;"> '</span><span style="color:#C3E88D;">Home</span><span style="color:#89DDFF;">'</span><span style="color:#89DDFF;"> };</span></span>
|
|
86
|
+
<span class="line"><span style="color:#89DDFF;">}</span></span></code></pre></div><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight vp-code" tabindex="0"><code><span class="line"><span style="color:#676E95;font-style:italic;">// app/products/handler.server.js</span></span>
|
|
87
|
+
<span class="line"><span style="color:#89DDFF;font-style:italic;">export</span><span style="color:#89DDFF;font-style:italic;"> default</span><span style="color:#C792EA;"> async</span><span style="color:#C792EA;"> function</span><span style="color:#89DDFF;"> (</span><span style="color:#BABED8;font-style:italic;">event</span><span style="color:#89DDFF;">,</span><span style="color:#BABED8;font-style:italic;"> next</span><span style="color:#89DDFF;">)</span><span style="color:#89DDFF;"> {</span></span>
|
|
88
|
+
<span class="line"><span style="color:#89DDFF;font-style:italic;"> if</span><span style="color:#F07178;"> (</span><span style="color:#BABED8;">next</span><span style="color:#89DDFF;">.</span><span style="color:#BABED8;">stepname</span><span style="color:#F07178;">) </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#89DDFF;font-style:italic;"> await</span><span style="color:#82AAFF;"> next</span><span style="color:#F07178;">()</span><span style="color:#89DDFF;">;</span></span>
|
|
89
|
+
<span class="line"><span style="color:#89DDFF;font-style:italic;"> return</span><span style="color:#89DDFF;"> {</span><span style="color:#F07178;"> title</span><span style="color:#89DDFF;">:</span><span style="color:#89DDFF;"> '</span><span style="color:#C3E88D;">Products</span><span style="color:#89DDFF;">'</span><span style="color:#89DDFF;"> };</span></span>
|
|
90
|
+
<span class="line"><span style="color:#89DDFF;">}</span></span></code></pre></div><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight vp-code" tabindex="0"><code><span class="line"><span style="color:#676E95;font-style:italic;">// app/products/stickers/handler.server.js</span></span>
|
|
91
|
+
<span class="line"><span style="color:#89DDFF;font-style:italic;">export</span><span style="color:#89DDFF;font-style:italic;"> default</span><span style="color:#C792EA;"> async</span><span style="color:#C792EA;"> function</span><span style="color:#89DDFF;"> ()</span><span style="color:#89DDFF;"> {</span></span>
|
|
92
|
+
<span class="line"><span style="color:#89DDFF;font-style:italic;"> if</span><span style="color:#F07178;"> (</span><span style="color:#BABED8;">next</span><span style="color:#89DDFF;">.</span><span style="color:#BABED8;">stepname</span><span style="color:#F07178;">) </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#89DDFF;font-style:italic;"> await</span><span style="color:#82AAFF;"> next</span><span style="color:#F07178;">()</span><span style="color:#89DDFF;">;</span></span>
|
|
93
|
+
<span class="line"><span style="color:#89DDFF;font-style:italic;"> return</span><span style="color:#89DDFF;"> {</span><span style="color:#F07178;"> title</span><span style="color:#89DDFF;">:</span><span style="color:#89DDFF;"> '</span><span style="color:#C3E88D;">Stickers</span><span style="color:#89DDFF;">'</span><span style="color:#89DDFF;"> };</span></span>
|
|
94
|
+
<span class="line"><span style="color:#89DDFF;">}</span></span></code></pre></div><ul><li>The request enters at the top level (<code>app/handler.server.js</code>).</li><li>Each handler may perform logic and either return a response or call <code>next()</code>.</li><li><code>next()</code> advances the request to the next directory level in the URL.</li><li>Delegation stops when there are no further segments (<code>next.stepname</code> is falsy).</li></ul><h3 id="internal-rerouting" tabindex="-1">Internal Rerouting <a class="header-anchor" href="#internal-rerouting" aria-label="Permalink to "Internal Rerouting""></a></h3><p>Beyond the default parent-child flow, a handler can explicitly <strong>reroute</strong> a request to another path within the app by calling <code>next(path)</code> or <code>next(context, path)</code>.</p><p>This is simulated below for a URL like <code>/products/stickers</code>.<br> Here, the root handler conditionally reroutes the request to <code>/api/inventory</code>, all within the same app.</p><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight vp-code" tabindex="0"><code><span class="line"><span style="color:#676E95;font-style:italic;">// app/handler.server.js</span></span>
|
|
95
|
+
<span class="line"><span style="color:#89DDFF;font-style:italic;">export</span><span style="color:#89DDFF;font-style:italic;"> default</span><span style="color:#C792EA;"> async</span><span style="color:#C792EA;"> function</span><span style="color:#89DDFF;"> (</span><span style="color:#BABED8;font-style:italic;">event</span><span style="color:#89DDFF;">,</span><span style="color:#BABED8;font-style:italic;"> next</span><span style="color:#89DDFF;">)</span><span style="color:#89DDFF;"> {</span></span>
|
|
96
|
+
<span class="line"><span style="color:#89DDFF;font-style:italic;"> if</span><span style="color:#F07178;"> (</span><span style="color:#BABED8;">next</span><span style="color:#89DDFF;">.</span><span style="color:#BABED8;">stepname</span><span style="color:#89DDFF;"> ===</span><span style="color:#89DDFF;"> '</span><span style="color:#C3E88D;">products</span><span style="color:#89DDFF;">'</span><span style="color:#F07178;">) </span><span style="color:#89DDFF;">{</span></span>
|
|
97
|
+
<span class="line"><span style="color:#C792EA;"> const</span><span style="color:#BABED8;"> inventory</span><span style="color:#89DDFF;"> =</span><span style="color:#89DDFF;font-style:italic;"> await</span><span style="color:#82AAFF;"> next</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">/api/inventory?range=7d</span><span style="color:#89DDFF;">'</span><span style="color:#F07178;">)</span><span style="color:#89DDFF;">;</span></span>
|
|
98
|
+
<span class="line"><span style="color:#89DDFF;font-style:italic;"> return</span><span style="color:#89DDFF;"> {</span><span style="color:#F07178;"> title</span><span style="color:#89DDFF;">:</span><span style="color:#89DDFF;"> '</span><span style="color:#C3E88D;">Products</span><span style="color:#89DDFF;">'</span><span style="color:#89DDFF;">,</span><span style="color:#89DDFF;"> ...</span><span style="color:#BABED8;">inventory</span><span style="color:#89DDFF;"> };</span></span>
|
|
99
|
+
<span class="line"><span style="color:#89DDFF;"> }</span></span>
|
|
100
|
+
<span class="line"><span style="color:#89DDFF;font-style:italic;"> return</span><span style="color:#89DDFF;"> {</span><span style="color:#F07178;"> title</span><span style="color:#89DDFF;">:</span><span style="color:#89DDFF;"> '</span><span style="color:#C3E88D;">Home</span><span style="color:#89DDFF;">'</span><span style="color:#89DDFF;"> };</span></span>
|
|
101
|
+
<span class="line"><span style="color:#89DDFF;">}</span></span></code></pre></div><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight vp-code" tabindex="0"><code><span class="line"><span style="color:#BABED8;">┌──────────┐ ┌──────────────┐ ┌──────────────────┐</span></span>
|
|
102
|
+
<span class="line"><span style="color:#BABED8;">│ app</span><span style="color:#89DDFF;">/</span><span style="color:#BABED8;"> │─┐ │ products</span><span style="color:#89DDFF;">/</span><span style="color:#BABED8;"> │ → │ stickers</span><span style="color:#89DDFF;">/</span><span style="color:#BABED8;"> │</span></span>
|
|
103
|
+
<span class="line"><span style="color:#BABED8;">│ handler │ │ │ handler │ │ handler │</span></span>
|
|
104
|
+
<span class="line"><span style="color:#BABED8;">│ </span><span style="color:#82AAFF;">next</span><span style="color:#BABED8;">(▼) │ │ │ │ │ │</span></span>
|
|
105
|
+
<span class="line"><span style="color:#BABED8;">└──────────┘ │ └──────────────┘ └──────────────────┘</span></span>
|
|
106
|
+
<span class="line"><span style="color:#BABED8;"> │</span></span>
|
|
107
|
+
<span class="line"><span style="color:#BABED8;"> │ (internal call)</span></span>
|
|
108
|
+
<span class="line"><span style="color:#BABED8;"> ▼</span></span>
|
|
109
|
+
<span class="line"><span style="color:#BABED8;">┌──────────┐ ┌──────────────┐ ┌──────────────────┐</span></span>
|
|
110
|
+
<span class="line"><span style="color:#BABED8;">│ app</span><span style="color:#89DDFF;">/</span><span style="color:#BABED8;"> │ → │ api</span><span style="color:#89DDFF;">/</span><span style="color:#BABED8;"> │ → │ inventory</span><span style="color:#89DDFF;">/</span><span style="color:#BABED8;"> │</span></span>
|
|
111
|
+
<span class="line"><span style="color:#BABED8;">│ handler │ │ handler │ │ handler │</span></span>
|
|
112
|
+
<span class="line"><span style="color:#BABED8;">│ </span><span style="color:#82AAFF;">next</span><span style="color:#BABED8;">() │ │ </span><span style="color:#82AAFF;">next</span><span style="color:#BABED8;">() │ │ </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#89DDFF;"> {}</span><span style="color:#BABED8;"> │</span></span>
|
|
113
|
+
<span class="line"><span style="color:#BABED8;">└──────────┘ └──────────────┘ └──────────────────┘</span></span></code></pre></div><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight vp-code" tabindex="0"><code><span class="line"><span style="color:#676E95;font-style:italic;">// app/api/inventory/handler.server.js</span></span>
|
|
114
|
+
<span class="line"><span style="color:#89DDFF;font-style:italic;">export</span><span style="color:#89DDFF;font-style:italic;"> default</span><span style="color:#C792EA;"> async</span><span style="color:#C792EA;"> function</span><span style="color:#89DDFF;"> (</span><span style="color:#BABED8;font-style:italic;">event</span><span style="color:#89DDFF;">,</span><span style="color:#BABED8;font-style:italic;"> next</span><span style="color:#89DDFF;">)</span><span style="color:#89DDFF;"> {</span></span>
|
|
115
|
+
<span class="line"><span style="color:#C792EA;"> const</span><span style="color:#BABED8;"> range</span><span style="color:#89DDFF;"> =</span><span style="color:#BABED8;"> event</span><span style="color:#89DDFF;">.</span><span style="color:#BABED8;">url</span><span style="color:#89DDFF;">.</span><span style="color:#BABED8;">searchParams</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">get</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">range</span><span style="color:#89DDFF;">'</span><span style="color:#F07178;">)</span><span style="color:#89DDFF;">;</span></span>
|
|
116
|
+
<span class="line"><span style="color:#C792EA;"> const</span><span style="color:#BABED8;"> result</span><span style="color:#89DDFF;"> =</span><span style="color:#89DDFF;font-style:italic;"> await</span><span style="color:#BABED8;"> db</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">query</span><span style="color:#F07178;">(</span></span>
|
|
117
|
+
<span class="line"><span style="color:#89DDFF;"> `</span><span style="color:#C3E88D;">SELECT * FROM inventory WHERE date_added < $1</span><span style="color:#89DDFF;">`</span><span style="color:#89DDFF;">,</span></span>
|
|
118
|
+
<span class="line"><span style="color:#F07178;"> [</span><span style="color:#BABED8;">range</span><span style="color:#F07178;">]</span></span>
|
|
119
|
+
<span class="line"><span style="color:#F07178;"> )</span><span style="color:#89DDFF;">;</span></span>
|
|
120
|
+
<span class="line"><span style="color:#89DDFF;font-style:italic;"> return</span><span style="color:#89DDFF;"> {</span><span style="color:#F07178;"> title</span><span style="color:#89DDFF;">:</span><span style="color:#89DDFF;"> '</span><span style="color:#C3E88D;">Inventory</span><span style="color:#89DDFF;">'</span><span style="color:#89DDFF;">,</span><span style="color:#BABED8;"> result</span><span style="color:#89DDFF;"> };</span></span>
|
|
121
|
+
<span class="line"><span style="color:#89DDFF;">}</span></span></code></pre></div><p>The rerouted request travels through the normal routing tree (<code>app/</code> → <code>api/</code> → <code>inventory/</code>) as if it had originated normally.</p><p>A relative path (e.g., <code>next('./api/inventory?range=7d')</code>) may be used to bypass lineage. But this must be done intentionally: deeper routes often inherit authentication or other contexts that should not be bypassed.</p><p>This technique enables <strong>in-app data composition</strong> — using existing route logic without additional network requests.</p><h3 id="request-and-response-rewriting" tabindex="-1">Request and Response Rewriting <a class="header-anchor" href="#request-and-response-rewriting" aria-label="Permalink to "Request and Response Rewriting""></a></h3><p>At any stage, a handler may rewrite parts of a request or modify the returned response before passing it on. This allows dynamic query shaping, conditional caching, or on-the-fly header injection.</p><p>This is simulated below for a scenario where the parent adds a parameter (<code>p=3</code>) to the child route, and then post-processes the response to set a custom header.</p><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight vp-code" tabindex="0"><code><span class="line"><span style="color:#676E95;font-style:italic;">// app/products/handler.server.js</span></span>
|
|
122
|
+
<span class="line"><span style="color:#89DDFF;font-style:italic;">export</span><span style="color:#89DDFF;font-style:italic;"> default</span><span style="color:#C792EA;"> async</span><span style="color:#C792EA;"> function</span><span style="color:#89DDFF;"> (</span><span style="color:#BABED8;font-style:italic;">event</span><span style="color:#89DDFF;">,</span><span style="color:#BABED8;font-style:italic;"> next</span><span style="color:#89DDFF;">)</span><span style="color:#89DDFF;"> {</span></span>
|
|
123
|
+
<span class="line"><span style="color:#676E95;font-style:italic;"> // Clone the request with a new query param</span></span>
|
|
124
|
+
<span class="line"><span style="color:#C792EA;"> const</span><span style="color:#BABED8;"> url</span><span style="color:#89DDFF;"> =</span><span style="color:#89DDFF;"> new</span><span style="color:#82AAFF;"> URL</span><span style="color:#F07178;">(</span><span style="color:#BABED8;">event</span><span style="color:#89DDFF;">.</span><span style="color:#BABED8;">url</span><span style="color:#F07178;">)</span><span style="color:#89DDFF;">;</span></span>
|
|
125
|
+
<span class="line"><span style="color:#BABED8;"> url</span><span style="color:#89DDFF;">.</span><span style="color:#BABED8;">searchParams</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">set</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">p</span><span style="color:#89DDFF;">'</span><span style="color:#89DDFF;">,</span><span style="color:#F78C6C;"> 3</span><span style="color:#F07178;">)</span><span style="color:#89DDFF;">;</span></span>
|
|
126
|
+
<span class="line"></span>
|
|
127
|
+
<span class="line"><span style="color:#676E95;font-style:italic;"> // Delegate with the modified URL</span></span>
|
|
128
|
+
<span class="line"><span style="color:#C792EA;"> const</span><span style="color:#BABED8;"> res</span><span style="color:#89DDFF;"> =</span><span style="color:#89DDFF;font-style:italic;"> await</span><span style="color:#82AAFF;"> next</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">{},</span><span style="color:#BABED8;"> url</span><span style="color:#89DDFF;">.</span><span style="color:#BABED8;">pathname</span><span style="color:#89DDFF;"> +</span><span style="color:#BABED8;"> url</span><span style="color:#89DDFF;">.</span><span style="color:#BABED8;">search</span><span style="color:#F07178;">)</span><span style="color:#89DDFF;">;</span></span>
|
|
129
|
+
<span class="line"></span>
|
|
130
|
+
<span class="line"><span style="color:#676E95;font-style:italic;"> // Post-process response before returning</span></span>
|
|
131
|
+
<span class="line"><span style="color:#C792EA;"> const</span><span style="color:#BABED8;"> headers</span><span style="color:#89DDFF;"> =</span><span style="color:#89DDFF;"> new</span><span style="color:#82AAFF;"> Headers</span><span style="color:#F07178;">(</span><span style="color:#BABED8;">res</span><span style="color:#89DDFF;">.</span><span style="color:#BABED8;">headers</span><span style="color:#F07178;">)</span><span style="color:#89DDFF;">;</span></span>
|
|
132
|
+
<span class="line"><span style="color:#BABED8;"> headers</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">set</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">X-Pipeline-Step</span><span style="color:#89DDFF;">'</span><span style="color:#89DDFF;">,</span><span style="color:#89DDFF;"> '</span><span style="color:#C3E88D;">products</span><span style="color:#89DDFF;">'</span><span style="color:#F07178;">)</span><span style="color:#89DDFF;">;</span></span>
|
|
133
|
+
<span class="line"><span style="color:#89DDFF;font-style:italic;"> return</span><span style="color:#89DDFF;"> new</span><span style="color:#82AAFF;"> Response</span><span style="color:#F07178;">(</span><span style="color:#BABED8;">res</span><span style="color:#89DDFF;">.</span><span style="color:#BABED8;">body</span><span style="color:#89DDFF;">,</span><span style="color:#89DDFF;"> {</span><span style="color:#F07178;"> status</span><span style="color:#89DDFF;">:</span><span style="color:#BABED8;"> res</span><span style="color:#89DDFF;">.</span><span style="color:#BABED8;">status</span><span style="color:#89DDFF;">,</span><span style="color:#BABED8;"> headers</span><span style="color:#89DDFF;"> }</span><span style="color:#F07178;">)</span><span style="color:#89DDFF;">;</span></span>
|
|
134
|
+
<span class="line"><span style="color:#89DDFF;">}</span></span></code></pre></div><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight vp-code" tabindex="0"><code><span class="line"><span style="color:#BABED8;">┌──────────┐ ┌──────────────┐ ┌──────────────────┐</span></span>
|
|
135
|
+
<span class="line"><span style="color:#BABED8;">│ app</span><span style="color:#89DDFF;">/</span><span style="color:#BABED8;"> │ → │ products</span><span style="color:#89DDFF;">/</span><span style="color:#BABED8;"> │ → │ stickers</span><span style="color:#89DDFF;">/?</span><span style="color:#BABED8;">p</span><span style="color:#89DDFF;">=</span><span style="color:#F78C6C;">3</span><span style="color:#BABED8;"> │</span></span>
|
|
136
|
+
<span class="line"><span style="color:#BABED8;">│ handler │ │ handler │ │ handler │</span></span>
|
|
137
|
+
<span class="line"><span style="color:#BABED8;">│ </span><span style="color:#82AAFF;">next</span><span style="color:#BABED8;">() │ ← │ </span><span style="color:#82AAFF;">next</span><span style="color:#BABED8;">() │ │ return </span><span style="color:#89DDFF;">{}</span><span style="color:#BABED8;"> │</span></span>
|
|
138
|
+
<span class="line"><span style="color:#BABED8;">└──────────┘ └──────────────┘ └──────────────────┘</span></span></code></pre></div><p>Through this mechanism, Webflo lets handlers <strong>reshape requests or responses inline</strong>, without needing extra middleware layers or global hooks.</p><h2 id="the-client-server-flow" tabindex="-1">The Client-Server Flow <a class="header-anchor" href="#the-client-server-flow" aria-label="Permalink to "The Client-Server Flow""></a></h2><p>While the <strong>Delegation Model</strong> describes how a request flows through a <em>horizontal</em> route path (parent → child), the <strong>Client-Server Flow</strong> represents the <em>vertical</em> flow of the same request through the application stack (client → server).</p><p>Webflo follows a model that supports request handling and routing at all three layers in this stack: the browser window layer (<strong>client</strong>), the service worker layer (<strong>worker</strong>), the server layer (<strong>server</strong>).</p><p>Handlers fit into this stack by their filename suffix:</p><div class="language-html"><button title="Copy Code" class="copy"></button><span class="lang">html</span><pre class="shiki material-theme-palenight vp-code" tabindex="0"><code><span class="line"><span style="color:#BABED8;">handler.client.js → Executes in the browser (first to see navigations)</span></span>
|
|
139
|
+
<span class="line"><span style="color:#BABED8;">handler.worker.js → Executes in the Service Worker (next in line)</span></span>
|
|
140
|
+
<span class="line"><span style="color:#BABED8;">handler.server.js → Executes on the server (last in line)</span></span>
|
|
141
|
+
<span class="line"><span style="color:#BABED8;">handler.js → Executes anywhere (default handler)</span></span></code></pre></div><p>Together, these form a vertical routing pipeline.</p><p>Below is a conceptual diagram of how a navigation request flows donw the layers:</p><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight vp-code" tabindex="0"><code><span class="line"><span style="color:#BABED8;">┌─────────────┐ │ ┌─────────────────────────────────┐</span></span>
|
|
142
|
+
<span class="line"><span style="color:#BABED8;">│ </span><span style="color:#82AAFF;">navigate</span><span style="color:#BABED8;">() │ → │ </span><span style="color:#89DDFF;">?</span><span style="color:#BABED8;"> │ handler</span><span style="color:#89DDFF;">.</span><span style="color:#BABED8;">client</span><span style="color:#89DDFF;">.</span><span style="color:#BABED8;">js </span><span style="color:#89DDFF;">??</span><span style="color:#BABED8;"> handler</span><span style="color:#89DDFF;">.</span><span style="color:#BABED8;">js │</span></span>
|
|
143
|
+
<span class="line"><span style="color:#BABED8;">│ │ ← │ └─────────────────────────────────┘</span></span>
|
|
144
|
+
<span class="line"><span style="color:#BABED8;">│ app │ │ ┌─────────────────────────────────┐</span></span>
|
|
145
|
+
<span class="line"><span style="color:#BABED8;">└─────────────┘ │ </span><span style="color:#89DDFF;">?</span><span style="color:#BABED8;"> │ handler</span><span style="color:#89DDFF;">.</span><span style="color:#BABED8;">worker</span><span style="color:#89DDFF;">.</span><span style="color:#BABED8;">js </span><span style="color:#89DDFF;">??</span><span style="color:#BABED8;"> handler</span><span style="color:#89DDFF;">.</span><span style="color:#BABED8;">js │</span></span>
|
|
146
|
+
<span class="line"><span style="color:#BABED8;"> │ └─────────────────────────────────┘</span></span>
|
|
147
|
+
<span class="line"><span style="color:#BABED8;"> │ ┌─────────────────────────────────┐</span></span>
|
|
148
|
+
<span class="line"><span style="color:#BABED8;"> │ </span><span style="color:#89DDFF;">?</span><span style="color:#BABED8;"> │ handler</span><span style="color:#89DDFF;">.</span><span style="color:#BABED8;">server</span><span style="color:#89DDFF;">.</span><span style="color:#BABED8;">js </span><span style="color:#89DDFF;">??</span><span style="color:#BABED8;"> handler</span><span style="color:#89DDFF;">.</span><span style="color:#BABED8;">js │</span></span>
|
|
149
|
+
<span class="line"><span style="color:#BABED8;"> ▼ └─────────────────────────────────┘</span></span></code></pre></div><p>Handlers are optional; if a level-specific file doesn’t exist, Webflo automatically falls back to the unsuffixed one <code>handler.js</code>, if defined. Otherwise, the request continues to the next layer. Each request gets a graceful path from local logic to remote fulfillment.</p><p>As with the horizontal flow, each layer may intercept, fulfill, or delegate down the request.<br> Handlers at higher layers (like the browser) are able to respond instantly or hand the request down the stack.</p><p>This model grants profound flexibility — enabling progressive enhancement, offline support, and universal routing, all through the same <code>next()</code> interface.</p><h3 id="layer-semantics" tabindex="-1">Layer Semantics <a class="header-anchor" href="#layer-semantics" aria-label="Permalink to "Layer Semantics""></a></h3><p>These layers are differentiated by various factors and use cases.</p><table tabindex="0"><thead><tr><th style="text-align:left;">Scope</th><th style="text-align:left;">Purpose</th><th style="text-align:left;">Typical Usage</th></tr></thead><tbody><tr><td style="text-align:left;"><strong>handler.client.js</strong></td><td style="text-align:left;">Runs in the browser during navigation</td><td style="text-align:left;">SPA transitions, local data hydration</td></tr><tr><td style="text-align:left;"><strong>handler.worker.js</strong></td><td style="text-align:left;">Runs in the Service Worker</td><td style="text-align:left;">Offline caching, background synchronization</td></tr><tr><td style="text-align:left;"><strong>handler.server.js</strong></td><td style="text-align:left;">Runs on the server</td><td style="text-align:left;">Database queries, SSR, API endpoints</td></tr><tr><td style="text-align:left;"><strong>handler.js</strong></td><td style="text-align:left;">Fallback when no scope-specific handler exists</td><td style="text-align:left;">Shared logic or universal defaults</td></tr></tbody></table><h4 id="client-side-handlers" tabindex="-1">Client-Side Handlers <a class="header-anchor" href="#client-side-handlers" aria-label="Permalink to "Client-Side Handlers""></a></h4><p>Client handlers intercept navigations directly in the browser — the first layer that sees user-initiated requests.</p><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight vp-code" tabindex="0"><code><span class="line"><span style="color:#676E95;font-style:italic;">// app/handler.client.js</span></span>
|
|
150
|
+
<span class="line"><span style="color:#89DDFF;font-style:italic;">export</span><span style="color:#89DDFF;font-style:italic;"> default</span><span style="color:#C792EA;"> async</span><span style="color:#C792EA;"> function</span><span style="color:#89DDFF;"> (</span><span style="color:#BABED8;font-style:italic;">event</span><span style="color:#89DDFF;">,</span><span style="color:#BABED8;font-style:italic;"> next</span><span style="color:#89DDFF;">)</span><span style="color:#89DDFF;"> {</span></span>
|
|
151
|
+
<span class="line"><span style="color:#89DDFF;font-style:italic;"> if</span><span style="color:#F07178;"> (</span><span style="color:#BABED8;">next</span><span style="color:#89DDFF;">.</span><span style="color:#BABED8;">stepname</span><span style="color:#F07178;">) </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#89DDFF;font-style:italic;"> await</span><span style="color:#82AAFF;"> next</span><span style="color:#F07178;">()</span><span style="color:#89DDFF;">;</span></span>
|
|
152
|
+
<span class="line"></span>
|
|
153
|
+
<span class="line"><span style="color:#676E95;font-style:italic;"> // Access browser APIs freely</span></span>
|
|
154
|
+
<span class="line"><span style="color:#C792EA;"> const</span><span style="color:#BABED8;"> theme</span><span style="color:#89DDFF;"> =</span><span style="color:#BABED8;"> window</span><span style="color:#89DDFF;">.</span><span style="color:#BABED8;">sessionStorage</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">getItem</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">theme</span><span style="color:#89DDFF;">'</span><span style="color:#F07178;">)</span><span style="color:#89DDFF;">;</span></span>
|
|
155
|
+
<span class="line"><span style="color:#89DDFF;font-style:italic;"> return</span><span style="color:#89DDFF;"> {</span><span style="color:#F07178;"> title</span><span style="color:#89DDFF;">:</span><span style="color:#89DDFF;"> '</span><span style="color:#C3E88D;">Client Navigation</span><span style="color:#89DDFF;">'</span><span style="color:#89DDFF;">,</span><span style="color:#BABED8;"> theme</span><span style="color:#89DDFF;"> };</span></span>
|
|
156
|
+
<span class="line"><span style="color:#89DDFF;">}</span></span></code></pre></div><ul><li>Executes during in-app navigations (SPA behavior)</li><li>Runs within the already loaded document and has access to window</li><li>Can render instantly from local data or cache</li><li>Optionally calls <code>next()</code> to delegate the request</li></ul><div class="info custom-block"><p class="custom-block-title">Handler Lifecycle</p><ul><li>Client handlers begin their lifecycle <em>after</em> the initial page load.</li><li>They therefore cannot intercept the first page load or page reloads.</li></ul></div><h4 id="worker-side-handlers" tabindex="-1">Worker-Side Handlers <a class="header-anchor" href="#worker-side-handlers" aria-label="Permalink to "Worker-Side Handlers""></a></h4><p>Worker handlers run in the Service Worker context, bridging offline and network behavior. They are the connective tissue between local interactivity and remote resources.</p><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight vp-code" tabindex="0"><code><span class="line"><span style="color:#676E95;font-style:italic;">// app/handler.worker.js</span></span>
|
|
157
|
+
<span class="line"><span style="color:#89DDFF;font-style:italic;">export</span><span style="color:#89DDFF;font-style:italic;"> default</span><span style="color:#C792EA;"> async</span><span style="color:#C792EA;"> function</span><span style="color:#89DDFF;"> (</span><span style="color:#BABED8;font-style:italic;">event</span><span style="color:#89DDFF;">,</span><span style="color:#BABED8;font-style:italic;"> next</span><span style="color:#89DDFF;">)</span><span style="color:#89DDFF;"> {</span></span>
|
|
158
|
+
<span class="line"><span style="color:#89DDFF;font-style:italic;"> if</span><span style="color:#F07178;"> (</span><span style="color:#BABED8;">next</span><span style="color:#89DDFF;">.</span><span style="color:#BABED8;">stepname</span><span style="color:#F07178;">) </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#89DDFF;font-style:italic;"> await</span><span style="color:#82AAFF;"> next</span><span style="color:#F07178;">()</span><span style="color:#89DDFF;">;</span></span>
|
|
159
|
+
<span class="line"></span>
|
|
160
|
+
<span class="line"><span style="color:#676E95;font-style:italic;"> // Access Service Worker APIs</span></span>
|
|
161
|
+
<span class="line"><span style="color:#C792EA;"> const</span><span style="color:#BABED8;"> cache</span><span style="color:#89DDFF;"> =</span><span style="color:#89DDFF;font-style:italic;"> await</span><span style="color:#BABED8;"> caches</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">open</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">webflo-assets</span><span style="color:#89DDFF;">'</span><span style="color:#F07178;">)</span><span style="color:#89DDFF;">;</span></span>
|
|
162
|
+
<span class="line"><span style="color:#C792EA;"> const</span><span style="color:#BABED8;"> cached</span><span style="color:#89DDFF;"> =</span><span style="color:#89DDFF;font-style:italic;"> await</span><span style="color:#BABED8;"> cache</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">match</span><span style="color:#F07178;">(</span><span style="color:#BABED8;">event</span><span style="color:#89DDFF;">.</span><span style="color:#BABED8;">request</span><span style="color:#F07178;">)</span><span style="color:#89DDFF;">;</span></span>
|
|
163
|
+
<span class="line"><span style="color:#89DDFF;font-style:italic;"> if</span><span style="color:#F07178;"> (</span><span style="color:#BABED8;">cached</span><span style="color:#F07178;">) </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#BABED8;"> cached</span><span style="color:#89DDFF;">;</span></span>
|
|
164
|
+
<span class="line"></span>
|
|
165
|
+
<span class="line"><span style="color:#C792EA;"> const</span><span style="color:#BABED8;"> network</span><span style="color:#89DDFF;"> =</span><span style="color:#89DDFF;font-style:italic;"> await</span><span style="color:#82AAFF;"> next</span><span style="color:#F07178;">()</span><span style="color:#89DDFF;">;</span><span style="color:#676E95;font-style:italic;"> // fallback to server</span></span>
|
|
166
|
+
<span class="line"><span style="color:#BABED8;"> cache</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">put</span><span style="color:#F07178;">(</span><span style="color:#BABED8;">event</span><span style="color:#89DDFF;">.</span><span style="color:#BABED8;">request</span><span style="color:#89DDFF;">,</span><span style="color:#BABED8;"> network</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">clone</span><span style="color:#F07178;">())</span><span style="color:#89DDFF;">;</span></span>
|
|
167
|
+
<span class="line"><span style="color:#89DDFF;font-style:italic;"> return</span><span style="color:#BABED8;"> network</span><span style="color:#89DDFF;">;</span></span>
|
|
168
|
+
<span class="line"><span style="color:#89DDFF;">}</span></span></code></pre></div><ul><li>Executes for same-origin requests</li><li>Can serve from cache, perform background syncs, or proxy network calls</li><li>Can delegates to the server when offline handling isn’t possible</li></ul><div class="info custom-block"><p class="custom-block-title">Handler Lifecycle</p><ul><li>Worker handlers start intercepting once the app’s Service Worker is installed and activated.</li><li>They therefore cannot intercept the very first page load that installs the app.</li><li>They continue working even when the page isn’t open, making them ideal for offline logic.</li></ul></div><h4 id="server-side-handlers" tabindex="-1">Server-Side Handlers <a class="header-anchor" href="#server-side-handlers" aria-label="Permalink to "Server-Side Handlers""></a></h4><p>Server handlers perform the heavy lifting — database queries, rendering, API endpoints, and integrations. They represent the final dynamic layer before static content resolution.</p><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight vp-code" tabindex="0"><code><span class="line"><span style="color:#676E95;font-style:italic;">// app/handler.server.js</span></span>
|
|
169
|
+
<span class="line"><span style="color:#89DDFF;font-style:italic;">export</span><span style="color:#89DDFF;font-style:italic;"> default</span><span style="color:#C792EA;"> async</span><span style="color:#C792EA;"> function</span><span style="color:#89DDFF;"> (</span><span style="color:#BABED8;font-style:italic;">event</span><span style="color:#89DDFF;">,</span><span style="color:#BABED8;font-style:italic;"> next</span><span style="color:#89DDFF;">)</span><span style="color:#89DDFF;"> {</span></span>
|
|
170
|
+
<span class="line"><span style="color:#89DDFF;font-style:italic;"> if</span><span style="color:#F07178;"> (</span><span style="color:#BABED8;">next</span><span style="color:#89DDFF;">.</span><span style="color:#BABED8;">stepname</span><span style="color:#F07178;">) </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#89DDFF;font-style:italic;"> await</span><span style="color:#82AAFF;"> next</span><span style="color:#F07178;">()</span><span style="color:#89DDFF;">;</span></span>
|
|
171
|
+
<span class="line"></span>
|
|
172
|
+
<span class="line"><span style="color:#C792EA;"> const</span><span style="color:#BABED8;"> user</span><span style="color:#89DDFF;"> =</span><span style="color:#BABED8;"> process</span><span style="color:#89DDFF;">.</span><span style="color:#BABED8;">env</span><span style="color:#89DDFF;">.</span><span style="color:#BABED8;">ADMIN_USER</span><span style="color:#89DDFF;">;</span></span>
|
|
173
|
+
<span class="line"><span style="color:#C792EA;"> const</span><span style="color:#BABED8;"> data</span><span style="color:#89DDFF;"> =</span><span style="color:#89DDFF;font-style:italic;"> await</span><span style="color:#82AAFF;"> fetch</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">https://api.example.com/stats</span><span style="color:#89DDFF;">'</span><span style="color:#F07178;">)</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">then</span><span style="color:#F07178;">(</span><span style="color:#BABED8;font-style:italic;">r</span><span style="color:#C792EA;"> =></span><span style="color:#BABED8;"> r</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">json</span><span style="color:#F07178;">())</span><span style="color:#89DDFF;">;</span></span>
|
|
174
|
+
<span class="line"><span style="color:#89DDFF;font-style:italic;"> return</span><span style="color:#89DDFF;"> {</span><span style="color:#F07178;"> title</span><span style="color:#89DDFF;">:</span><span style="color:#89DDFF;"> `</span><span style="color:#C3E88D;">Dashboard | </span><span style="color:#89DDFF;">${</span><span style="color:#BABED8;">user</span><span style="color:#89DDFF;">}`</span><span style="color:#89DDFF;">,</span><span style="color:#BABED8;"> data</span><span style="color:#89DDFF;"> };</span></span>
|
|
175
|
+
<span class="line"><span style="color:#89DDFF;">}</span></span></code></pre></div><ul><li>Executes for HTTP requests that reach the server</li><li>Accesses environment variables and external APIs</li><li>May call <code>next()</code> to handoff request to Webflo’s static file layer</li></ul><h4 id="universal-handlers" tabindex="-1">Universal Handlers <a class="header-anchor" href="#universal-handlers" aria-label="Permalink to "Universal Handlers""></a></h4><p>Universal handlers (<code>handler.js</code>) are handlers declared without any layer binding. They can coexist with layer-specific handlers but execute wherever no layer-specific handler exists for the current layer, making them perfect for universal logic.</p><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight vp-code" tabindex="0"><code><span class="line"><span style="color:#676E95;font-style:italic;">// app/handler.js</span></span>
|
|
176
|
+
<span class="line"><span style="color:#89DDFF;font-style:italic;">export</span><span style="color:#89DDFF;font-style:italic;"> default</span><span style="color:#C792EA;"> async</span><span style="color:#C792EA;"> function</span><span style="color:#89DDFF;"> (</span><span style="color:#BABED8;font-style:italic;">event</span><span style="color:#89DDFF;">,</span><span style="color:#BABED8;font-style:italic;"> next</span><span style="color:#89DDFF;">)</span><span style="color:#89DDFF;"> {</span></span>
|
|
177
|
+
<span class="line"><span style="color:#676E95;font-style:italic;"> // Purely portable logic — no window, no caches, no env</span></span>
|
|
178
|
+
<span class="line"><span style="color:#89DDFF;font-style:italic;"> return</span><span style="color:#89DDFF;"> {</span><span style="color:#F07178;"> message</span><span style="color:#89DDFF;">:</span><span style="color:#89DDFF;"> '</span><span style="color:#C3E88D;">Handled by default</span><span style="color:#89DDFF;">'</span><span style="color:#89DDFF;"> };</span></span>
|
|
179
|
+
<span class="line"><span style="color:#89DDFF;">}</span></span></code></pre></div><div class="tip custom-block"><p class="custom-block-title">Progressive Enhancement</p><ul><li>Because handlers are modular by filename, promoting a route from server-side to client-side is as simple as renaming the file.</li><li>Webflo’s model turns <em>progressive enhancement</em> into a first-class development workflow.</li></ul></div><h3 id="fall-through-behavior" tabindex="-1">Fall-Through Behavior <a class="header-anchor" href="#fall-through-behavior" aria-label="Permalink to "Fall-Through Behavior""></a></h3><p>If a handler calls <code>next()</code> and no deeper step exists in the current layer, Webflo <strong>falls through to the next layer</strong> in the stack. This continuity is built-in.</p><table tabindex="0"><thead><tr><th style="text-align:left;">Scope</th><th style="text-align:left;">Default Action when <code>next()</code> reaches edge</th></tr></thead><tbody><tr><td style="text-align:left;"><strong>Client</strong></td><td style="text-align:left;">Falls through to the worker layer.</td></tr><tr><td style="text-align:left;"><strong>Worker</strong></td><td style="text-align:left;">Falls through to either: (cache → server) or (server → cache), depending on worker config.</td></tr><tr><td style="text-align:left;"><strong>Server</strong></td><td style="text-align:left;">Falls through to the static file layer <code>/public</code>; returns 404 if no match.</td></tr></tbody></table><p>This is simulated below for a navigation to <code>/products/stickers</code>, where the client and worker layers defer to the server for resolution.</p><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight vp-code" tabindex="0"><code><span class="line"><span style="color:#676E95;font-style:italic;">// app/products/handler.client.js</span></span>
|
|
180
|
+
<span class="line"><span style="color:#89DDFF;font-style:italic;">export</span><span style="color:#89DDFF;font-style:italic;"> default</span><span style="color:#C792EA;"> async</span><span style="color:#C792EA;"> function</span><span style="color:#89DDFF;"> (</span><span style="color:#BABED8;font-style:italic;">event</span><span style="color:#89DDFF;">,</span><span style="color:#BABED8;font-style:italic;"> next</span><span style="color:#89DDFF;">)</span><span style="color:#89DDFF;"> {</span></span>
|
|
181
|
+
<span class="line"><span style="color:#89DDFF;font-style:italic;"> if</span><span style="color:#F07178;"> (</span><span style="color:#BABED8;">next</span><span style="color:#89DDFF;">.</span><span style="color:#BABED8;">stepname</span><span style="color:#F07178;">) </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#89DDFF;font-style:italic;"> await</span><span style="color:#82AAFF;"> next</span><span style="color:#F07178;">()</span><span style="color:#89DDFF;">;</span></span>
|
|
182
|
+
<span class="line"><span style="color:#676E95;font-style:italic;"> // Defer to deeper layers</span></span>
|
|
183
|
+
<span class="line"><span style="color:#89DDFF;font-style:italic;"> return</span><span style="color:#82AAFF;"> next</span><span style="color:#F07178;">()</span><span style="color:#89DDFF;">;</span></span>
|
|
184
|
+
<span class="line"><span style="color:#89DDFF;">}</span></span></code></pre></div><div class="language-html"><button title="Copy Code" class="copy"></button><span class="lang">html</span><pre class="shiki material-theme-palenight vp-code" tabindex="0"><code><span class="line"><span style="color:#BABED8;">┌──────────┐ ┌──────────────┐</span></span>
|
|
185
|
+
<span class="line"><span style="color:#BABED8;">│ app/ │ → │ products/ │─┐ (fall-through)</span></span>
|
|
186
|
+
<span class="line"><span style="color:#BABED8;">│ handler │ │ handler │ │</span></span>
|
|
187
|
+
<span class="line"><span style="color:#BABED8;">│ next() │ │ next() │ │</span></span>
|
|
188
|
+
<span class="line"><span style="color:#BABED8;">└──────────┘ └──────────────┘ │</span></span>
|
|
189
|
+
<span class="line"><span style="color:#BABED8;"> │</span></span>
|
|
190
|
+
<span class="line"><span style="color:#BABED8;"> │ (server layer)</span></span>
|
|
191
|
+
<span class="line"><span style="color:#BABED8;"> ▼</span></span>
|
|
192
|
+
<span class="line"><span style="color:#BABED8;">┌──────────┐ ┌──────────────┐ ┌──────────────────┐</span></span>
|
|
193
|
+
<span class="line"><span style="color:#BABED8;">│ app/ │ → │ products/ │ → │ stickers/ │</span></span>
|
|
194
|
+
<span class="line"><span style="color:#BABED8;">│ handler │ │ handler │ │ handler │</span></span>
|
|
195
|
+
<span class="line"><span style="color:#BABED8;">│ next() │ │ next() │ │ return {} │</span></span>
|
|
196
|
+
<span class="line"><span style="color:#BABED8;">└──────────┘ └──────────────┘ └──────────────────┘</span></span></code></pre></div><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight vp-code" tabindex="0"><code><span class="line"><span style="color:#676E95;font-style:italic;">// app/products/stickers/handler.server.js</span></span>
|
|
197
|
+
<span class="line"><span style="color:#89DDFF;font-style:italic;">export</span><span style="color:#89DDFF;font-style:italic;"> default</span><span style="color:#C792EA;"> async</span><span style="color:#C792EA;"> function</span><span style="color:#89DDFF;"> ()</span><span style="color:#89DDFF;"> {</span></span>
|
|
198
|
+
<span class="line"><span style="color:#C792EA;"> const</span><span style="color:#BABED8;"> result</span><span style="color:#89DDFF;"> =</span><span style="color:#89DDFF;font-style:italic;"> await</span><span style="color:#BABED8;"> db</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">query</span><span style="color:#F07178;">(</span></span>
|
|
199
|
+
<span class="line"><span style="color:#89DDFF;"> `</span><span style="color:#C3E88D;">SELECT * FROM products WHERE category = 'stickers'</span><span style="color:#89DDFF;">`</span></span>
|
|
200
|
+
<span class="line"><span style="color:#F07178;"> )</span><span style="color:#89DDFF;">;</span></span>
|
|
201
|
+
<span class="line"><span style="color:#89DDFF;font-style:italic;"> return</span><span style="color:#89DDFF;"> {</span><span style="color:#F07178;"> title</span><span style="color:#89DDFF;">:</span><span style="color:#89DDFF;"> '</span><span style="color:#C3E88D;">Stickers</span><span style="color:#89DDFF;">'</span><span style="color:#89DDFF;">,</span><span style="color:#BABED8;"> result</span><span style="color:#89DDFF;"> };</span></span>
|
|
202
|
+
<span class="line"><span style="color:#89DDFF;">}</span></span></code></pre></div><p>Here, the client and worker defer, the server handles the query, and the browser receives the composed response. This unlocks the full power of composition, progressive enhancement, and resilience per route — whether online, offline, or hybrid.</p><h2 id="flow-summary" tabindex="-1">Flow Summary <a class="header-anchor" href="#flow-summary" aria-label="Permalink to "Flow Summary""></a></h2><p>While your first handler is perfectly fine to fit routing logic into conditional blocks, Webflo's delegation model makes routing all seamsless as you go from a simple <em>Hello World</em> to a standard app, to a fully distributed system.</p><p>The delegation and composition model turns the traditional “server-first” web into a <strong>collaborative matrix</strong>. Each level decides what it can handle best and delegates what it cannot.</p><p>This composability and control extend to static files handling.</p><h2 id="static-files" tabindex="-1">Static Files <a class="header-anchor" href="#static-files" aria-label="Permalink to "Static Files""></a></h2><p>At the end of Webflo’s routing chain lies the <strong>static layer</strong> — a built-in static file server that operates by the same rules as every other layer.</p><p>In Webflo, static resolution is not a separate middleware; it is simply the final stage of the routing pipeline.</p><p>This layer is reached <strong>from the server routing layer</strong>, when:</p><ul><li>a server handler calls <code>next()</code> and no further route step exists in the pipeline</li></ul><p>Because static serving sits in this same flow, route handlers take first-seat complete control — to intercept, rewrite, or even <em>simulate</em> static responses before they are served.</p><p>This flow is simulated below for an image URL: <code>/img/logo.png</code> embedded on a page.<br> Its resolution goes the standard routing flow until matching a file in the <code>app/public</code> directory.</p><div class="language-html"><button title="Copy Code" class="copy"></button><span class="lang">html</span><pre class="shiki material-theme-palenight vp-code" tabindex="0"><code><span class="line"><span style="color:#BABED8;">┌─────────────┐ │ ┌─────────────────────────────────┐</span></span>
|
|
203
|
+
<span class="line"><span style="color:#BABED8;">│ </span><span style="color:#89DDFF;"><</span><span style="color:#F07178;">img</span><span style="color:#C792EA;"> src</span><span style="color:#89DDFF;">></span><span style="color:#BABED8;"> │ → │ ? │ handler.client.js ?? handler.js │</span></span>
|
|
204
|
+
<span class="line"><span style="color:#BABED8;">│ │ ← │ └─────────────────────────────────┘</span></span>
|
|
205
|
+
<span class="line"><span style="color:#BABED8;">│ app │ │ ┌─────────────────────────────────┐</span></span>
|
|
206
|
+
<span class="line"><span style="color:#BABED8;">└─────────────┘ │ ? │ handler.worker.js ?? handler.js │</span></span>
|
|
207
|
+
<span class="line"><span style="color:#BABED8;"> │ └─────────────────────────────────┘</span></span>
|
|
208
|
+
<span class="line"><span style="color:#BABED8;"> │ ┌─────────────────────────────────┐</span></span>
|
|
209
|
+
<span class="line"><span style="color:#BABED8;"> │ ? │ handler.server.js ?? handler.js │</span></span>
|
|
210
|
+
<span class="line"><span style="color:#BABED8;"> │ └─────────────────────────────────┘</span></span>
|
|
211
|
+
<span class="line"><span style="color:#BABED8;"> │ ┌─────────────────────────────────┐</span></span>
|
|
212
|
+
<span class="line"><span style="color:#BABED8;"> │ ? │ public/img/pic.png │</span></span>
|
|
213
|
+
<span class="line"><span style="color:#BABED8;"> │ │ public/img/banner.png │</span></span>
|
|
214
|
+
<span class="line"><span style="color:#BABED8;"> │ │ public/img/logo.png │</span></span>
|
|
215
|
+
<span class="line"><span style="color:#BABED8;"> ▼ └─────────────────────────────────┘</span></span></code></pre></div><p>Each handler along the flow gets a chance to intercept the request.<br> A worker, for example, may serve a cached image or synthesize a response. A server handler may rewrite the path before handing off to <code>/public</code> or it may <em>gate</em> or authenticate the request before passing it on.</p><p>This handler-first approach to static files serving ensures that asset delivery fits your application logic, authentication, or cache policies.</p><p>But this also requires <strong>proper delegation discipline</strong> by handlers. Handlers must consciously call <code>next()</code> for requests they're not explicitly designed to handle.</p><p>Overall, by merging dynamic logic and static delivery into one continuous flow, Webflo replaces special-case asset middleware with a <strong>first-class, programmable static pipeline</strong>.</p><h3 id="default-resolution" tabindex="-1">Default Resolution <a class="header-anchor" href="#default-resolution" aria-label="Permalink to "Default Resolution""></a></h3><p>When a request reaches the static layer, Webflo performs deterministic file resolution:</p><ol><li>Look for a file in <code>/public</code> matching the request path.</li><li>If found, serve it with correct headers (e.g. <code>Content-Type</code>, <code>Content-Length</code>, caching).</li><li>If not found, return <code>404</code>.</li></ol><h2 id="use-case-patterns" tabindex="-1">Use Case Patterns <a class="header-anchor" href="#use-case-patterns" aria-label="Permalink to "Use Case Patterns""></a></h2><p>The following examples demonstrate how Webflo’s routing primitives—delegation, composition, and explicit fall-through—combine to express real application structures. Each pattern is an applied scenario that builds directly on the models we’ve covered so far.</p><h3 id="parent–child-composition" tabindex="-1">Parent–Child Composition <a class="header-anchor" href="#parent–child-composition" aria-label="Permalink to "Parent–Child Composition""></a></h3><p><strong>Scenario:</strong> A parent route prepares context and then delegates to a child, merging its result. This pattern allows <em>layered composition</em>—logic in parents, data or view in children.</p><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight vp-code" tabindex="0"><code><span class="line"><span style="color:#676E95;font-style:italic;">// app/handler.server.js</span></span>
|
|
216
|
+
<span class="line"><span style="color:#89DDFF;font-style:italic;">export</span><span style="color:#89DDFF;font-style:italic;"> default</span><span style="color:#C792EA;"> async</span><span style="color:#C792EA;"> function</span><span style="color:#89DDFF;"> (</span><span style="color:#BABED8;font-style:italic;">event</span><span style="color:#89DDFF;">,</span><span style="color:#BABED8;font-style:italic;"> context</span><span style="color:#89DDFF;">,</span><span style="color:#BABED8;font-style:italic;"> next</span><span style="color:#89DDFF;">)</span><span style="color:#89DDFF;"> {</span></span>
|
|
217
|
+
<span class="line"><span style="color:#89DDFF;font-style:italic;"> if</span><span style="color:#F07178;"> (</span><span style="color:#BABED8;">next</span><span style="color:#89DDFF;">.</span><span style="color:#BABED8;">stepname</span><span style="color:#F07178;">) </span><span style="color:#89DDFF;">{</span></span>
|
|
218
|
+
<span class="line"><span style="color:#C792EA;"> const</span><span style="color:#BABED8;"> user</span><span style="color:#89DDFF;"> =</span><span style="color:#89DDFF;font-style:italic;"> await</span><span style="color:#82AAFF;"> getSessionUser</span><span style="color:#F07178;">(</span><span style="color:#BABED8;">event</span><span style="color:#89DDFF;">.</span><span style="color:#BABED8;">request</span><span style="color:#F07178;">)</span><span style="color:#89DDFF;">;</span></span>
|
|
219
|
+
<span class="line"><span style="color:#C792EA;"> const</span><span style="color:#BABED8;"> childResult</span><span style="color:#89DDFF;"> =</span><span style="color:#89DDFF;font-style:italic;"> await</span><span style="color:#82AAFF;"> next</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">{</span><span style="color:#BABED8;"> user</span><span style="color:#89DDFF;"> }</span><span style="color:#F07178;">)</span><span style="color:#89DDFF;">;</span></span>
|
|
220
|
+
<span class="line"><span style="color:#89DDFF;font-style:italic;"> return</span><span style="color:#89DDFF;"> {</span><span style="color:#89DDFF;"> ...</span><span style="color:#BABED8;">childResult</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> title</span><span style="color:#89DDFF;">:</span><span style="color:#89DDFF;"> `${</span><span style="color:#BABED8;">childResult</span><span style="color:#89DDFF;">.</span><span style="color:#BABED8;">title</span><span style="color:#89DDFF;">}</span><span style="color:#C3E88D;"> | ExampleApp</span><span style="color:#89DDFF;">`</span><span style="color:#89DDFF;"> };</span></span>
|
|
221
|
+
<span class="line"><span style="color:#89DDFF;"> }</span></span>
|
|
222
|
+
<span class="line"><span style="color:#89DDFF;font-style:italic;"> return</span><span style="color:#89DDFF;"> {</span><span style="color:#F07178;"> title</span><span style="color:#89DDFF;">:</span><span style="color:#89DDFF;"> '</span><span style="color:#C3E88D;">Home</span><span style="color:#89DDFF;">'</span><span style="color:#89DDFF;"> };</span></span>
|
|
223
|
+
<span class="line"><span style="color:#89DDFF;">}</span></span></code></pre></div><p><strong>Takeaway:</strong> Each handler can frame or extend downstream results, making cross-cutting concerns like authentication or analytics fully composable.</p><h3 id="internal-api-consumption" tabindex="-1">Internal API Consumption <a class="header-anchor" href="#internal-api-consumption" aria-label="Permalink to "Internal API Consumption""></a></h3><p><strong>Scenario:</strong> A page handler calls an internal API route using <code>next(path)</code> instead of making an HTTP request. This lets server code reuse API logic without duplication or latency.</p><div class="language-html"><button title="Copy Code" class="copy"></button><span class="lang">html</span><pre class="shiki material-theme-palenight vp-code" tabindex="0"><code><span class="line"><span style="color:#BABED8;">app/</span></span>
|
|
224
|
+
<span class="line"><span style="color:#BABED8;">├── api/</span></span>
|
|
225
|
+
<span class="line"><span style="color:#BABED8;">│ └── products/handler.server.js</span></span>
|
|
226
|
+
<span class="line"><span style="color:#BABED8;">└── shop/handler.server.js</span></span></code></pre></div><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight vp-code" tabindex="0"><code><span class="line"><span style="color:#676E95;font-style:italic;">// app/shop/handler.server.js</span></span>
|
|
227
|
+
<span class="line"><span style="color:#89DDFF;font-style:italic;">export</span><span style="color:#89DDFF;font-style:italic;"> default</span><span style="color:#C792EA;"> async</span><span style="color:#C792EA;"> function</span><span style="color:#89DDFF;"> (</span><span style="color:#BABED8;font-style:italic;">event</span><span style="color:#89DDFF;">,</span><span style="color:#BABED8;font-style:italic;"> next</span><span style="color:#89DDFF;">)</span><span style="color:#89DDFF;"> {</span></span>
|
|
228
|
+
<span class="line"><span style="color:#C792EA;"> const</span><span style="color:#BABED8;"> products</span><span style="color:#89DDFF;"> =</span><span style="color:#89DDFF;font-style:italic;"> await</span><span style="color:#82AAFF;"> next</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">/api/products</span><span style="color:#89DDFF;">'</span><span style="color:#F07178;">)</span><span style="color:#89DDFF;">;</span></span>
|
|
229
|
+
<span class="line"><span style="color:#89DDFF;font-style:italic;"> return</span><span style="color:#89DDFF;"> {</span><span style="color:#F07178;"> title</span><span style="color:#89DDFF;">:</span><span style="color:#89DDFF;"> '</span><span style="color:#C3E88D;">Shop</span><span style="color:#89DDFF;">'</span><span style="color:#89DDFF;">,</span><span style="color:#89DDFF;"> ...</span><span style="color:#BABED8;">products</span><span style="color:#89DDFF;"> };</span></span>
|
|
230
|
+
<span class="line"><span style="color:#89DDFF;">}</span></span></code></pre></div><p><strong>Takeaway:</strong> By re-entering the routing pipeline locally, Webflo turns API composition into simple function calls—no network, no boilerplate.</p><h3 id="auth-guard" tabindex="-1">Auth Guard <a class="header-anchor" href="#auth-guard" aria-label="Permalink to "Auth Guard""></a></h3><p><strong>Scenario:</strong> A parent route gates access for its children, redirecting unauthenticated users and passing context when authorized.</p><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight vp-code" tabindex="0"><code><span class="line"><span style="color:#676E95;font-style:italic;">// app/account/handler.server.js</span></span>
|
|
231
|
+
<span class="line"><span style="color:#89DDFF;font-style:italic;">export</span><span style="color:#89DDFF;font-style:italic;"> default</span><span style="color:#C792EA;"> async</span><span style="color:#C792EA;"> function</span><span style="color:#89DDFF;"> (</span><span style="color:#BABED8;font-style:italic;">event</span><span style="color:#89DDFF;">,</span><span style="color:#BABED8;font-style:italic;"> context</span><span style="color:#89DDFF;">,</span><span style="color:#BABED8;font-style:italic;"> next</span><span style="color:#89DDFF;">)</span><span style="color:#89DDFF;"> {</span></span>
|
|
232
|
+
<span class="line"><span style="color:#C792EA;"> const</span><span style="color:#BABED8;"> user</span><span style="color:#89DDFF;"> =</span><span style="color:#89DDFF;font-style:italic;"> await</span><span style="color:#82AAFF;"> getUserFromSession</span><span style="color:#F07178;">(</span><span style="color:#BABED8;">event</span><span style="color:#89DDFF;">.</span><span style="color:#BABED8;">request</span><span style="color:#F07178;">)</span><span style="color:#89DDFF;">;</span></span>
|
|
233
|
+
<span class="line"><span style="color:#89DDFF;font-style:italic;"> if</span><span style="color:#F07178;"> (</span><span style="color:#89DDFF;">!</span><span style="color:#BABED8;">user</span><span style="color:#F07178;">) </span><span style="color:#89DDFF;">{</span></span>
|
|
234
|
+
<span class="line"><span style="color:#89DDFF;font-style:italic;"> return</span><span style="color:#89DDFF;"> new</span><span style="color:#82AAFF;"> Response</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">null,</span><span style="color:#89DDFF;"> {</span><span style="color:#F07178;"> status</span><span style="color:#89DDFF;">:</span><span style="color:#F78C6C;"> 302</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> headers</span><span style="color:#89DDFF;">:</span><span style="color:#89DDFF;"> {</span><span style="color:#F07178;"> Location</span><span style="color:#89DDFF;">:</span><span style="color:#89DDFF;"> '</span><span style="color:#C3E88D;">/login</span><span style="color:#89DDFF;">'</span><span style="color:#89DDFF;"> }</span><span style="color:#89DDFF;"> }</span><span style="color:#F07178;">)</span><span style="color:#89DDFF;">;</span></span>
|
|
235
|
+
<span class="line"><span style="color:#89DDFF;"> }</span></span>
|
|
236
|
+
<span class="line"><span style="color:#89DDFF;font-style:italic;"> return</span><span style="color:#82AAFF;"> next</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">{</span><span style="color:#89DDFF;"> ...</span><span style="color:#BABED8;">context</span><span style="color:#89DDFF;">,</span><span style="color:#BABED8;"> user</span><span style="color:#89DDFF;"> }</span><span style="color:#F07178;">)</span><span style="color:#89DDFF;">;</span></span>
|
|
237
|
+
<span class="line"><span style="color:#89DDFF;">}</span></span></code></pre></div><p><strong>Takeaway:</strong> Authentication becomes just another layer in the routing flow—no external middleware required.</p><h3 id="file-guards-and-access-control" tabindex="-1">File Guards and Access Control <a class="header-anchor" href="#file-guards-and-access-control" aria-label="Permalink to "File Guards and Access Control""></a></h3><p><strong>Scenario:</strong> Restrict access to premium or user-specific files before they reach the static layer.</p><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight vp-code" tabindex="0"><code><span class="line"><span style="color:#676E95;font-style:italic;">// app/files/handler.server.js</span></span>
|
|
238
|
+
<span class="line"><span style="color:#89DDFF;font-style:italic;">export</span><span style="color:#89DDFF;font-style:italic;"> default</span><span style="color:#C792EA;"> async</span><span style="color:#C792EA;"> function</span><span style="color:#89DDFF;"> (</span><span style="color:#BABED8;font-style:italic;">event</span><span style="color:#89DDFF;">,</span><span style="color:#BABED8;font-style:italic;"> next</span><span style="color:#89DDFF;">)</span><span style="color:#89DDFF;"> {</span></span>
|
|
239
|
+
<span class="line"><span style="color:#C792EA;"> const</span><span style="color:#BABED8;"> user</span><span style="color:#89DDFF;"> =</span><span style="color:#89DDFF;font-style:italic;"> await</span><span style="color:#82AAFF;"> getUserFromSession</span><span style="color:#F07178;">(</span><span style="color:#BABED8;">event</span><span style="color:#89DDFF;">.</span><span style="color:#BABED8;">request</span><span style="color:#F07178;">)</span><span style="color:#89DDFF;">;</span></span>
|
|
240
|
+
<span class="line"><span style="color:#89DDFF;font-style:italic;"> if</span><span style="color:#F07178;"> (</span><span style="color:#89DDFF;">!</span><span style="color:#BABED8;">user</span><span style="color:#89DDFF;">?.</span><span style="color:#BABED8;">isPremium</span><span style="color:#F07178;">) </span><span style="color:#89DDFF;">{</span></span>
|
|
241
|
+
<span class="line"><span style="color:#89DDFF;font-style:italic;"> return</span><span style="color:#89DDFF;"> new</span><span style="color:#82AAFF;"> Response</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">Access denied</span><span style="color:#89DDFF;">'</span><span style="color:#89DDFF;">,</span><span style="color:#89DDFF;"> {</span><span style="color:#F07178;"> status</span><span style="color:#89DDFF;">:</span><span style="color:#F78C6C;"> 403</span><span style="color:#89DDFF;"> }</span><span style="color:#F07178;">)</span><span style="color:#89DDFF;">;</span></span>
|
|
242
|
+
<span class="line"><span style="color:#89DDFF;"> }</span></span>
|
|
243
|
+
<span class="line"><span style="color:#89DDFF;font-style:italic;"> return</span><span style="color:#82AAFF;"> next</span><span style="color:#F07178;">()</span><span style="color:#89DDFF;">;</span></span>
|
|
244
|
+
<span class="line"><span style="color:#89DDFF;">}</span></span></code></pre></div><p><strong>Takeaway:</strong> Because static requests flow through the same pipeline, permission checks and audit logic integrate naturally with asset delivery.</p><h3 id="dynamic-file-serving" tabindex="-1">Dynamic File Serving <a class="header-anchor" href="#dynamic-file-serving" aria-label="Permalink to "Dynamic File Serving""></a></h3><p><strong>Scenario:</strong> Rewrite or transform static responses on the fly for caching, personalization, or instrumentation.</p><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight vp-code" tabindex="0"><code><span class="line"><span style="color:#676E95;font-style:italic;">// app/-/handler.server.js</span></span>
|
|
245
|
+
<span class="line"><span style="color:#89DDFF;font-style:italic;">export</span><span style="color:#89DDFF;font-style:italic;"> default</span><span style="color:#C792EA;"> async</span><span style="color:#C792EA;"> function</span><span style="color:#89DDFF;"> (</span><span style="color:#BABED8;font-style:italic;">event</span><span style="color:#89DDFF;">,</span><span style="color:#BABED8;font-style:italic;"> next</span><span style="color:#89DDFF;">)</span><span style="color:#89DDFF;"> {</span></span>
|
|
246
|
+
<span class="line"><span style="color:#C792EA;"> const</span><span style="color:#BABED8;"> res</span><span style="color:#89DDFF;"> =</span><span style="color:#89DDFF;font-style:italic;"> await</span><span style="color:#82AAFF;"> next</span><span style="color:#F07178;">()</span><span style="color:#89DDFF;">;</span><span style="color:#676E95;font-style:italic;"> // delegate to /public</span></span>
|
|
247
|
+
<span class="line"><span style="color:#89DDFF;font-style:italic;"> if</span><span style="color:#F07178;"> (</span><span style="color:#BABED8;">res</span><span style="color:#89DDFF;"> &&</span><span style="color:#BABED8;"> res</span><span style="color:#89DDFF;">.</span><span style="color:#BABED8;">ok</span><span style="color:#89DDFF;"> &&</span><span style="color:#BABED8;"> res</span><span style="color:#89DDFF;">.</span><span style="color:#BABED8;">headers</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">get</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">Content-Type</span><span style="color:#89DDFF;">'</span><span style="color:#F07178;">)</span><span style="color:#89DDFF;">?.</span><span style="color:#82AAFF;">includes</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">text/html</span><span style="color:#89DDFF;">'</span><span style="color:#F07178;">)) </span><span style="color:#89DDFF;">{</span></span>
|
|
248
|
+
<span class="line"><span style="color:#C792EA;"> const</span><span style="color:#BABED8;"> headers</span><span style="color:#89DDFF;"> =</span><span style="color:#89DDFF;"> new</span><span style="color:#82AAFF;"> Headers</span><span style="color:#F07178;">(</span><span style="color:#BABED8;">res</span><span style="color:#89DDFF;">.</span><span style="color:#BABED8;">headers</span><span style="color:#F07178;">)</span><span style="color:#89DDFF;">;</span></span>
|
|
249
|
+
<span class="line"><span style="color:#BABED8;"> headers</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">set</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">Cache-Control</span><span style="color:#89DDFF;">'</span><span style="color:#89DDFF;">,</span><span style="color:#89DDFF;"> '</span><span style="color:#C3E88D;">public, max-age=300</span><span style="color:#89DDFF;">'</span><span style="color:#F07178;">)</span><span style="color:#89DDFF;">;</span></span>
|
|
250
|
+
<span class="line"><span style="color:#BABED8;"> headers</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">set</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">X-Served-By</span><span style="color:#89DDFF;">'</span><span style="color:#89DDFF;">,</span><span style="color:#89DDFF;"> '</span><span style="color:#C3E88D;">Webflo</span><span style="color:#89DDFF;">'</span><span style="color:#F07178;">)</span><span style="color:#89DDFF;">;</span></span>
|
|
251
|
+
<span class="line"><span style="color:#89DDFF;font-style:italic;"> return</span><span style="color:#89DDFF;"> new</span><span style="color:#82AAFF;"> Response</span><span style="color:#F07178;">(</span><span style="color:#BABED8;">res</span><span style="color:#89DDFF;">.</span><span style="color:#BABED8;">body</span><span style="color:#89DDFF;">,</span><span style="color:#89DDFF;"> {</span><span style="color:#F07178;"> status</span><span style="color:#89DDFF;">:</span><span style="color:#BABED8;"> res</span><span style="color:#89DDFF;">.</span><span style="color:#BABED8;">status</span><span style="color:#89DDFF;">,</span><span style="color:#BABED8;"> headers</span><span style="color:#89DDFF;"> }</span><span style="color:#F07178;">)</span><span style="color:#89DDFF;">;</span></span>
|
|
252
|
+
<span class="line"><span style="color:#89DDFF;"> }</span></span>
|
|
253
|
+
<span class="line"><span style="color:#89DDFF;font-style:italic;"> return</span><span style="color:#BABED8;"> res</span><span style="color:#89DDFF;">;</span></span>
|
|
254
|
+
<span class="line"><span style="color:#89DDFF;">}</span></span></code></pre></div><p><strong>Takeaway:</strong> Handlers can shape even static responses—embedding application-level awareness into the file server itself.</p><h3 id="full-stack-routing" tabindex="-1">Full-Stack Routing <a class="header-anchor" href="#full-stack-routing" aria-label="Permalink to "Full-Stack Routing""></a></h3><p><strong>Scenario:</strong> A single navigation passes through multiple layers—client, worker, server, static—each adding incremental behavior.</p><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight vp-code" tabindex="0"><code><span class="line"><span style="color:#82AAFF;">CLIENT</span><span style="color:#BABED8;"> (handler</span><span style="color:#89DDFF;">.</span><span style="color:#BABED8;">client</span><span style="color:#89DDFF;">.</span><span style="color:#BABED8;">js)</span></span>
|
|
255
|
+
<span class="line"><span style="color:#BABED8;"> │ Intercepted navigation</span><span style="color:#89DDFF;">,</span><span style="color:#BABED8;"> local cache check</span></span>
|
|
256
|
+
<span class="line"><span style="color:#BABED8;"> ▼ </span><span style="color:#82AAFF;">next</span><span style="color:#BABED8;">()</span></span>
|
|
257
|
+
<span class="line"><span style="color:#82AAFF;">WORKER</span><span style="color:#BABED8;"> (handler</span><span style="color:#89DDFF;">.</span><span style="color:#BABED8;">worker</span><span style="color:#89DDFF;">.</span><span style="color:#BABED8;">js)</span></span>
|
|
258
|
+
<span class="line"><span style="color:#BABED8;"> │ Offline fallback or cache refresh</span></span>
|
|
259
|
+
<span class="line"><span style="color:#BABED8;"> ▼ </span><span style="color:#82AAFF;">next</span><span style="color:#BABED8;">()</span></span>
|
|
260
|
+
<span class="line"><span style="color:#82AAFF;">SERVER</span><span style="color:#BABED8;"> (handler</span><span style="color:#89DDFF;">.</span><span style="color:#BABED8;">server</span><span style="color:#89DDFF;">.</span><span style="color:#BABED8;">js)</span></span>
|
|
261
|
+
<span class="line"><span style="color:#BABED8;"> │ Query</span><span style="color:#89DDFF;">,</span><span style="color:#BABED8;"> render</span><span style="color:#89DDFF;">,</span><span style="color:#BABED8;"> compose</span></span>
|
|
262
|
+
<span class="line"><span style="color:#BABED8;"> ▼ </span><span style="color:#82AAFF;">next</span><span style="color:#BABED8;">()</span></span>
|
|
263
|
+
<span class="line"><span style="color:#82AAFF;">STATIC</span><span style="color:#BABED8;"> (public</span><span style="color:#89DDFF;">/</span><span style="color:#BABED8;">)</span></span>
|
|
264
|
+
<span class="line"><span style="color:#BABED8;"> │ Fallback to static asset</span></span>
|
|
265
|
+
<span class="line"><span style="color:#BABED8;"> ▼</span></span>
|
|
266
|
+
<span class="line"><span style="color:#BABED8;"> Response returned</span></span></code></pre></div><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight vp-code" tabindex="0"><code><span class="line"><span style="color:#676E95;font-style:italic;">// app/products/handler.client.js</span></span>
|
|
267
|
+
<span class="line"><span style="color:#89DDFF;font-style:italic;">export</span><span style="color:#89DDFF;font-style:italic;"> default</span><span style="color:#C792EA;"> async</span><span style="color:#C792EA;"> function</span><span style="color:#89DDFF;"> (</span><span style="color:#BABED8;font-style:italic;">event</span><span style="color:#89DDFF;">,</span><span style="color:#BABED8;font-style:italic;"> next</span><span style="color:#89DDFF;">)</span><span style="color:#89DDFF;"> {</span></span>
|
|
268
|
+
<span class="line"><span style="color:#89DDFF;font-style:italic;"> if</span><span style="color:#F07178;"> (</span><span style="color:#BABED8;">next</span><span style="color:#89DDFF;">.</span><span style="color:#BABED8;">stepname</span><span style="color:#F07178;">) </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#89DDFF;font-style:italic;"> await</span><span style="color:#82AAFF;"> next</span><span style="color:#F07178;">()</span><span style="color:#89DDFF;">;</span></span>
|
|
269
|
+
<span class="line"><span style="color:#676E95;font-style:italic;"> // Attempt to serve from local state</span></span>
|
|
270
|
+
<span class="line"><span style="color:#C792EA;"> const</span><span style="color:#BABED8;"> cached</span><span style="color:#89DDFF;"> =</span><span style="color:#BABED8;"> sessionStorage</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">getItem</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">products</span><span style="color:#89DDFF;">'</span><span style="color:#F07178;">)</span><span style="color:#89DDFF;">;</span></span>
|
|
271
|
+
<span class="line"><span style="color:#89DDFF;font-style:italic;"> if</span><span style="color:#F07178;"> (</span><span style="color:#BABED8;">cached</span><span style="color:#F07178;">) </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#BABED8;"> JSON</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">parse</span><span style="color:#F07178;">(</span><span style="color:#BABED8;">cached</span><span style="color:#F07178;">)</span><span style="color:#89DDFF;">;</span></span>
|
|
272
|
+
<span class="line"><span style="color:#89DDFF;font-style:italic;"> return</span><span style="color:#82AAFF;"> next</span><span style="color:#F07178;">()</span><span style="color:#89DDFF;">;</span><span style="color:#676E95;font-style:italic;"> // defer to worker/server</span></span>
|
|
273
|
+
<span class="line"><span style="color:#89DDFF;">}</span></span></code></pre></div><p><strong>Takeaway:</strong> Full-stack routing enables progressive enhancement by design—each scope adds value without breaking continuity.</p><h3 id="remote-procedure-calls-clone" tabindex="-1">Remote Procedure Calls Clone <a class="header-anchor" href="#remote-procedure-calls-clone" aria-label="Permalink to "Remote Procedure Calls Clone""></a></h3><p><strong>Scenario:</strong> Think of Webflo’s routing pipeline as RPC with spatial awareness. Each <code>next()</code> is a local procedure call that moves closer to the data or resource in question.</p><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight vp-code" tabindex="0"><code><span class="line"><span style="color:#676E95;font-style:italic;">// app/dashboard/handler.server.js</span></span>
|
|
274
|
+
<span class="line"><span style="color:#89DDFF;font-style:italic;">export</span><span style="color:#89DDFF;font-style:italic;"> default</span><span style="color:#C792EA;"> async</span><span style="color:#C792EA;"> function</span><span style="color:#89DDFF;"> (</span><span style="color:#BABED8;font-style:italic;">event</span><span style="color:#89DDFF;">,</span><span style="color:#BABED8;font-style:italic;"> next</span><span style="color:#89DDFF;">)</span><span style="color:#89DDFF;"> {</span></span>
|
|
275
|
+
<span class="line"><span style="color:#C792EA;"> const</span><span style="color:#BABED8;"> metrics</span><span style="color:#89DDFF;"> =</span><span style="color:#89DDFF;font-style:italic;"> await</span><span style="color:#82AAFF;"> next</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">/api/metrics</span><span style="color:#89DDFF;">'</span><span style="color:#F07178;">)</span><span style="color:#89DDFF;">;</span></span>
|
|
276
|
+
<span class="line"><span style="color:#C792EA;"> const</span><span style="color:#BABED8;"> reports</span><span style="color:#89DDFF;"> =</span><span style="color:#89DDFF;font-style:italic;"> await</span><span style="color:#82AAFF;"> next</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">/api/reports</span><span style="color:#89DDFF;">'</span><span style="color:#F07178;">)</span><span style="color:#89DDFF;">;</span></span>
|
|
277
|
+
<span class="line"><span style="color:#89DDFF;font-style:italic;"> return</span><span style="color:#89DDFF;"> {</span><span style="color:#BABED8;"> metrics</span><span style="color:#89DDFF;">,</span><span style="color:#BABED8;"> reports</span><span style="color:#89DDFF;"> };</span></span>
|
|
278
|
+
<span class="line"><span style="color:#89DDFF;">}</span></span></code></pre></div><p><strong>Takeaway:</strong> Unlike traditional RPC, routing in Webflo preserves URL semantics and context propagation while keeping the call local and synchronous.</p><h2 id="summary" tabindex="-1">Summary <a class="header-anchor" href="#summary" aria-label="Permalink to "Summary""></a></h2><p>Webflo’s routing system unifies <strong>filesystem mapping</strong>, <strong>functional composition</strong>, and <strong>layered execution</strong> into one consistent model.</p><ul><li>The filesystem defines your application structure.</li><li>Handlers define logic for each URL segment.</li><li><code>next()</code> controls flow between steps and scopes.</li><li>Default fallbacks ensure graceful completion through the stack.</li><li>Static serving is part of the same flow, enabling dynamic control.</li></ul><h2 id="next-steps" tabindex="-1">Next Steps <a class="header-anchor" href="#next-steps" aria-label="Permalink to "Next Steps""></a></h2><ul><li><a href="./rendering">Rendering</a>: How handler data becomes UI.</li><li><a href="./templates">Templates</a>: Composing reusable HTML layouts.</li><li><a href="./state">State & Reactivity</a>: Managing state and mutation across requests.</li></ul></div></div></main><footer class="VPDocFooter" data-v-39a288b8 data-v-e257564d><!--[--><!--]--><!----><nav class="prev-next" aria-labelledby="doc-footer-aria-label" data-v-e257564d><span class="visually-hidden" id="doc-footer-aria-label" data-v-e257564d>Pager</span><div class="pager" data-v-e257564d><a class="VPLink link pager-link prev" href="/docs/concepts" data-v-e257564d><!--[--><span class="desc" data-v-e257564d>Previous page</span><span class="title" data-v-e257564d>Concepts Overview</span><!--]--></a></div><div class="pager" data-v-e257564d><a class="VPLink link pager-link next" href="/docs/concepts/rendering" data-v-e257564d><!--[--><span class="desc" data-v-e257564d>Next page</span><span class="title" data-v-e257564d>Rendering</span><!--]--></a></div></nav></footer><!--[--><!--]--></div></div></div><!--[--><!--]--></div></div><footer class="VPFooter has-sidebar" data-v-5d98c3a5 data-v-e315a0ad><div class="container" data-v-e315a0ad><p class="message" data-v-e315a0ad>MIT Licensed</p><p class="copyright" data-v-e315a0ad>© webqit</p></div></footer><!--[--><!--]--></div></div>
|
|
279
|
+
<script>window.__VP_HASH_MAP__=JSON.parse("{\"-__.md\":\"wD5kDRhS\",\"-_docs.old.md\":\"CiqucE_1\",\"api.md\":\"C9KRNLi_\",\"api_webflo-fetch_fetch.md\":\"Bc9r3Q9I\",\"api_webflo-fetch_formdata.md\":\"CDuexUTz\",\"api_webflo-fetch_headers.md\":\"Cl_4-FUP\",\"api_webflo-fetch_liveresponse.md\":\"BMidKMB1\",\"api_webflo-fetch_request.md\":\"DPwZCPmi\",\"api_webflo-fetch_response.md\":\"BaSyoOLE\",\"api_webflo-routing_handler.md\":\"B0eVFluL\",\"api_webflo-routing_handler_fetch.md\":\"CpwUMFMz\",\"api_webflo-routing_handler_next.md\":\"CA4tDXtV\",\"api_webflo-routing_httpcookies.md\":\"B5ok3jrM\",\"api_webflo-routing_httpevent.md\":\"DBkSQRTa\",\"api_webflo-routing_httpevent_respondwith.md\":\"aAxq-5Ie\",\"api_webflo-routing_httpevent_waituntil.md\":\"DyQZLhPR\",\"api_webflo-routing_httpevent_waituntilnavigate.md\":\"DKLylwhl\",\"api_webflo-routing_httpsession.md\":\"bkeCy7_Q\",\"api_webflo-routing_httpstate.md\":\"DO53IAM1\",\"api_webflo-routing_httpuser.md\":\"CfsaBFdl\",\"contributing.md\":\"gqIMCtVI\",\"docs.md\":\"hvbqYbFY\",\"docs_advanced.md\":\"D048cxnq\",\"docs_advanced_lifecycles.md\":\"BICPL-da\",\"docs_advanced_redirects.md\":\"BMha6D3W\",\"docs_advanced_routing.md\":\"Cv63UDJF\",\"docs_concepts.md\":\"Clwx81Hz\",\"docs_concepts_realtime.md\":\"CBrMq5Ln\",\"docs_concepts_rendering.md\":\"BWr5Lxgn\",\"docs_concepts_request-response.md\":\"DhplzNqt\",\"docs_concepts_routing.md\":\"C2KO1eAu\",\"docs_concepts_state.md\":\"CtbMVS_K\",\"docs_concepts_templates.md\":\"4i6jQcYw\",\"docs_getting-started.md\":\"CNGtwB_L\",\"docs_tech-stack.md\":\"xiWGQstL\",\"examples.md\":\"BqDfJd4G\",\"examples_pwa.md\":\"DREN7J2F\",\"examples_web.md\":\"DUhZ0IQL\",\"faq.md\":\"DtfXaXUI\",\"guides.md\":\"BVdQyeU-\",\"guides_guide-auth.md\":\"DNFuRudp\",\"guides_guide-file-upload.md\":\"DRbRLk7h\",\"guides_guide-service-worker.md\":\"B0wEVcQw\",\"guides_tutorial-1-todo.md\":\"D9ket3Re\",\"index.md\":\"DB-CsGEX\",\"recipes_realtime.md\":\"CX1Vs2FD\",\"recipes_streaming.md\":\"C7GFShgF\",\"reference_cli.md\":\"DERqaQJm\",\"reference_config.md\":\"DI_yG-7N\",\"reference_tools.md\":\"DZxjdVFX\"}");window.__VP_SITE_DATA__=JSON.parse("{\"lang\":\"en-US\",\"dir\":\"ltr\",\"title\":\"Webflo\",\"description\":\"A universal, standards-first web framework for building web-native apps.\",\"base\":\"/\",\"head\":[],\"router\":{\"prefetchLinks\":true},\"appearance\":\"force-dark\",\"themeConfig\":{\"logo\":false,\"siteTitle\":\"Webflo\",\"socialLinks\":[{\"icon\":\"github\",\"link\":\"https://github.com/webqit/webflo\"}],\"nav\":[{\"text\":\"Docs\",\"link\":\"/docs\",\"activeMatch\":\"/docs\"},{\"text\":\"API\",\"link\":\"/api\",\"activeMatch\":\"/api/webflo-routing/handler\"},{\"text\":\"Guides\",\"link\":\"/guides\",\"activeMatch\":\"/guides\"},{\"text\":\"Examples\",\"link\":\"/examples\",\"activeMatch\":\"/examples\"}],\"sidebar\":{\"/\":[{\"text\":\"Getting Started\",\"items\":[{\"text\":\"Welcome\",\"link\":\"/docs\"},{\"text\":\"Quickstart\",\"link\":\"/docs/getting-started\"}]},{\"text\":\"Concepts\",\"items\":[{\"text\":\"Concepts Overview\",\"link\":\"/docs/concepts\"},{\"text\":\"Webflo Routing\",\"link\":\"/docs/concepts/routing\"},{\"text\":\"Rendering\",\"link\":\"/docs/concepts/rendering\"},{\"text\":\"Templates\",\"link\":\"/docs/concepts/templates\"},{\"text\":\"State Management\",\"link\":\"/docs/concepts/state\"},{\"text\":\"Request/Response Lifecycle\",\"link\":\"/docs/concepts/request-response\"},{\"text\":\"Webflo Realtime\",\"link\":\"/docs/concepts/realtime\"}]},{\"text\":\"Advanced\",\"items\":[{\"text\":\"Advanced Overview\",\"link\":\"/docs/advanced\"},{\"text\":\"Redirects\",\"link\":\"/docs/advanced/redirects\"}]},{\"text\":\"API Reference\",\"items\":[{\"text\":\"Webflo Routing\",\"collapsed\":true,\"items\":[{\"text\":\"Handler\",\"link\":\"/api/webflo-routing/handler\"},{\"text\":\"HttpEvent\",\"link\":\"/api/webflo-routing/HttpEvent\"},{\"text\":\"next\",\"link\":\"/api/webflo-routing/handler/next\"},{\"text\":\"fetch\",\"link\":\"/api/webflo-routing/handler/fetch\"}]},{\"text\":\"Webflo Fetch\",\"collapsed\":true,\"items\":[{\"text\":\"fetch\",\"link\":\"/api/webflo-fetch/fetch\"},{\"text\":\"Request\",\"link\":\"/api/webflo-fetch/Request\"},{\"text\":\"Response\",\"link\":\"/api/webflo-fetch/Response\"},{\"text\":\"LiveResponse\",\"link\":\"/api/webflo-fetch/LiveResponse\"},{\"text\":\"FormData\",\"link\":\"/api/webflo-fetch/FormData\"},{\"text\":\"Headers\",\"link\":\"/api/webflo-fetch/Headers\"}]},{\"text\":\"Webflo Messaging\",\"collapsed\":true,\"items\":[{\"text\":\"MessageChannel\",\"link\":\"/api/webflo-messaging/MessageChannel\"},{\"text\":\"MessagePort\",\"link\":\"/api/webflo-messaging/MessagePort\"},{\"text\":\"MessageEvent\",\"link\":\"/api/webflo-messaging/MessageEvent\"}]}]},{\"text\":\"Guides & Recipes\",\"items\":[{\"text\":\"Tutorial: Todo App\",\"link\":\"/guides/tutorial-1-todo\"},{\"text\":\"Auth\",\"link\":\"/guides/guide-auth\"},{\"text\":\"File Upload\",\"link\":\"/guides/guide-file-upload\"},{\"text\":\"Service Worker\",\"link\":\"/guides/guide-service-worker\"},{\"text\":\"Streaming\",\"link\":\"/recipes/streaming\"},{\"text\":\"Realtime Patterns\",\"link\":\"/recipes/realtime\"}]},{\"text\":\"Examples\",\"items\":[{\"text\":\"Web Example\",\"link\":\"/examples/web\"},{\"text\":\"PWA Example\",\"link\":\"/examples/pwa\"}]},{\"text\":\"Reference\",\"items\":[{\"text\":\"CLI\",\"link\":\"/reference/cli\"},{\"text\":\"Config\",\"link\":\"/reference/config\"},{\"text\":\"Tools\",\"link\":\"/reference/tools\"},{\"text\":\"FAQ\",\"link\":\"/faq\"},{\"text\":\"Contributing\",\"link\":\"/contributing\"}]}]},\"footer\":{\"message\":\"MIT Licensed\",\"copyright\":\"© webqit\"},\"search\":{\"provider\":\"local\"}},\"locales\":{},\"scrollOffset\":134,\"cleanUrls\":true}");</script>
|
|
280
|
+
|
|
281
|
+
</body>
|
|
282
|
+
</html>
|