[{"data":1,"prerenderedAt":667},["ShallowReactive",2],{"navigation":3,"-guide":72,"-guide-surround":663},[4,36],{"title":5,"path":6,"stem":7,"children":8,"icon":10},"Getting Started","/guide","1.guide/1.index",[9,11,16,21,26,31],{"title":5,"path":6,"stem":7,"icon":10},"ph:book-open-duotone",{"title":12,"path":13,"stem":14,"icon":15},"Hooks","/guide/hooks","1.guide/2.hooks","material-symbols-light:data-object",{"title":17,"path":18,"stem":19,"icon":20},"Peer","/guide/peer","1.guide/3.peer","mynaui:api",{"title":22,"path":23,"stem":24,"icon":25},"Message","/guide/message","1.guide/4.message","solar:letter-line-duotone",{"title":27,"path":28,"stem":29,"icon":30},"Pub / Sub","/guide/pubsub","1.guide/5.pubsub","simple-icons:googlepubsub",{"title":32,"path":33,"stem":34,"icon":35},"Resolver API","/guide/resolver","1.guide/6.resolver","tabler:route",{"title":37,"path":38,"stem":39,"children":40,"icon":42},"Adapters","/adapters","2.adapters/1.index",[41,43,48,52,57,62,67],{"title":37,"path":38,"stem":39,"icon":42},"emojione-monotone:electric-plug",{"title":44,"path":45,"stem":46,"icon":47},"Bun","/adapters/bun","2.adapters/bun","simple-icons:bun",{"title":49,"path":50,"stem":51},"Bunny","/adapters/bunny","2.adapters/bunny",{"title":53,"path":54,"stem":55,"icon":56},"Cloudflare","/adapters/cloudflare","2.adapters/cloudflare","devicon-plain:cloudflareworkers",{"title":58,"path":59,"stem":60,"icon":61},"Deno","/adapters/deno","2.adapters/deno","teenyicons:deno-solid",{"title":63,"path":64,"stem":65,"icon":66},"Node.js","/adapters/node","2.adapters/node","akar-icons:node-fill",{"title":68,"path":69,"stem":70,"icon":71},"SSE","/adapters/sse","2.adapters/sse","clarity:two-way-arrows-line",{"id":73,"title":5,"body":74,"description":657,"extension":658,"meta":659,"navigation":660,"path":6,"seo":661,"stem":7,"__hash__":662},"content/1.guide/1.index.md",{"type":75,"value":76,"toc":654,"icon":10},"minimark",[77,81,86,100,112,116,119,558,561,615,633,642,650],[78,79,80],"p",{},"Writing a realtime WebSocket server that can work in different runtimes is challenging because there is no single standard for WebSocket servers. You often need to go into many details of different API implementations and it also makes switching from one runtime costly. crossws is a solution to this!",[82,83,85],"h2",{"id":84},"quick-start","Quick Start",[87,88,89],"tip",{},[78,90,91,92,99],{},"\nYou can try crossws with ",[93,94,98],"a",{"href":95,"rel":96},"https://stackblitz.com/github/h3js/crossws/tree/main/playground",[97],"nofollow","online playground",".",[78,101,102,103,107,108,111],{},"Install ",[104,105,106],"code",{},"crossws"," and ",[104,109,110],{},"srvx"," in your project:",[113,114],"pm-install",{"name":115},"crossws srvx",[78,117,118],{},"A simple WebSocket server looks like this:",[120,121,127],"pre",{"className":122,"code":123,"filename":124,"language":125,"meta":126,"style":126},"language-js shiki shiki-themes github-light github-dark github-dark","// Works with Bun, Deno and Node.js (also Cloudflare or SSE as fallback)\nimport { serve } from \"crossws/server\";\n\nserve({\n  websocket: {\n    open(peer) {\n      console.log(\"[ws] open\", peer);\n      peer.send({ user: \"server\", message: `Welcome ${peer}!` });\n    },\n\n    message(peer, message) {\n      console.log(\"[ws] message\", message);\n      if (message.text().includes(\"ping\")) {\n        peer.send({ user: \"server\", message: \"pong\" });\n      } else {\n        peer.send({ user: peer.toString(), message: message.toString() });\n      }\n    },\n\n    close(peer, event) {\n      console.log(\"[ws] close\", peer, event);\n    },\n\n    error(peer, error) {\n      console.log(\"[ws] error\", peer, error);\n    },\n  },\n  fetch: () =>\n    fetch(\n      \"https://raw.githubusercontent.com/h3js/crossws/refs/heads/main/playground/public/index.html\",\n    ).then(\n      (res) =>\n        new Response(res.body, { headers: { \"Content-Type\": \"text/html\" } }),\n    ),\n});\n","server.mjs","js","",[104,128,129,138,159,166,176,182,198,215,244,250,255,273,288,314,333,345,366,372,377,382,399,414,419,424,441,456,461,467,479,488,497,508,522,546,552],{"__ignoreMap":126},[130,131,134],"span",{"class":132,"line":133},"line",1,[130,135,137],{"class":136},"sCsY4","// Works with Bun, Deno and Node.js (also Cloudflare or SSE as fallback)\n",[130,139,141,145,149,152,156],{"class":132,"line":140},2,[130,142,144],{"class":143},"so5gQ","import",[130,146,148],{"class":147},"slsVL"," { serve } ",[130,150,151],{"class":143},"from",[130,153,155],{"class":154},"sfrk1"," \"crossws/server\"",[130,157,158],{"class":147},";\n",[130,160,162],{"class":132,"line":161},3,[130,163,165],{"emptyLinePlaceholder":164},true,"\n",[130,167,169,173],{"class":132,"line":168},4,[130,170,172],{"class":171},"shcOC","serve",[130,174,175],{"class":147},"({\n",[130,177,179],{"class":132,"line":178},5,[130,180,181],{"class":147},"  websocket: {\n",[130,183,185,188,191,195],{"class":132,"line":184},6,[130,186,187],{"class":171},"    open",[130,189,190],{"class":147},"(",[130,192,194],{"class":193},"sQHwn","peer",[130,196,197],{"class":147},") {\n",[130,199,201,204,207,209,212],{"class":132,"line":200},7,[130,202,203],{"class":147},"      console.",[130,205,206],{"class":171},"log",[130,208,190],{"class":147},[130,210,211],{"class":154},"\"[ws] open\"",[130,213,214],{"class":147},", peer);\n",[130,216,218,221,224,227,230,233,236,238,241],{"class":132,"line":217},8,[130,219,220],{"class":147},"      peer.",[130,222,223],{"class":171},"send",[130,225,226],{"class":147},"({ user: ",[130,228,229],{"class":154},"\"server\"",[130,231,232],{"class":147},", message: ",[130,234,235],{"class":154},"`Welcome ${",[130,237,194],{"class":147},[130,239,240],{"class":154},"}!`",[130,242,243],{"class":147}," });\n",[130,245,247],{"class":132,"line":246},9,[130,248,249],{"class":147},"    },\n",[130,251,253],{"class":132,"line":252},10,[130,254,165],{"emptyLinePlaceholder":164},[130,256,258,261,263,265,268,271],{"class":132,"line":257},11,[130,259,260],{"class":171},"    message",[130,262,190],{"class":147},[130,264,194],{"class":193},[130,266,267],{"class":147},", ",[130,269,270],{"class":193},"message",[130,272,197],{"class":147},[130,274,276,278,280,282,285],{"class":132,"line":275},12,[130,277,203],{"class":147},[130,279,206],{"class":171},[130,281,190],{"class":147},[130,283,284],{"class":154},"\"[ws] message\"",[130,286,287],{"class":147},", message);\n",[130,289,291,294,297,300,303,306,308,311],{"class":132,"line":290},13,[130,292,293],{"class":143},"      if",[130,295,296],{"class":147}," (message.",[130,298,299],{"class":171},"text",[130,301,302],{"class":147},"().",[130,304,305],{"class":171},"includes",[130,307,190],{"class":147},[130,309,310],{"class":154},"\"ping\"",[130,312,313],{"class":147},")) {\n",[130,315,317,320,322,324,326,328,331],{"class":132,"line":316},14,[130,318,319],{"class":147},"        peer.",[130,321,223],{"class":171},[130,323,226],{"class":147},[130,325,229],{"class":154},[130,327,232],{"class":147},[130,329,330],{"class":154},"\"pong\"",[130,332,243],{"class":147},[130,334,336,339,342],{"class":132,"line":335},15,[130,337,338],{"class":147},"      } ",[130,340,341],{"class":143},"else",[130,343,344],{"class":147}," {\n",[130,346,348,350,352,355,358,361,363],{"class":132,"line":347},16,[130,349,319],{"class":147},[130,351,223],{"class":171},[130,353,354],{"class":147},"({ user: peer.",[130,356,357],{"class":171},"toString",[130,359,360],{"class":147},"(), message: message.",[130,362,357],{"class":171},[130,364,365],{"class":147},"() });\n",[130,367,369],{"class":132,"line":368},17,[130,370,371],{"class":147},"      }\n",[130,373,375],{"class":132,"line":374},18,[130,376,249],{"class":147},[130,378,380],{"class":132,"line":379},19,[130,381,165],{"emptyLinePlaceholder":164},[130,383,385,388,390,392,394,397],{"class":132,"line":384},20,[130,386,387],{"class":171},"    close",[130,389,190],{"class":147},[130,391,194],{"class":193},[130,393,267],{"class":147},[130,395,396],{"class":193},"event",[130,398,197],{"class":147},[130,400,402,404,406,408,411],{"class":132,"line":401},21,[130,403,203],{"class":147},[130,405,206],{"class":171},[130,407,190],{"class":147},[130,409,410],{"class":154},"\"[ws] close\"",[130,412,413],{"class":147},", peer, event);\n",[130,415,417],{"class":132,"line":416},22,[130,418,249],{"class":147},[130,420,422],{"class":132,"line":421},23,[130,423,165],{"emptyLinePlaceholder":164},[130,425,427,430,432,434,436,439],{"class":132,"line":426},24,[130,428,429],{"class":171},"    error",[130,431,190],{"class":147},[130,433,194],{"class":193},[130,435,267],{"class":147},[130,437,438],{"class":193},"error",[130,440,197],{"class":147},[130,442,444,446,448,450,453],{"class":132,"line":443},25,[130,445,203],{"class":147},[130,447,206],{"class":171},[130,449,190],{"class":147},[130,451,452],{"class":154},"\"[ws] error\"",[130,454,455],{"class":147},", peer, error);\n",[130,457,459],{"class":132,"line":458},26,[130,460,249],{"class":147},[130,462,464],{"class":132,"line":463},27,[130,465,466],{"class":147},"  },\n",[130,468,470,473,476],{"class":132,"line":469},28,[130,471,472],{"class":171},"  fetch",[130,474,475],{"class":147},": () ",[130,477,478],{"class":143},"=>\n",[130,480,482,485],{"class":132,"line":481},29,[130,483,484],{"class":171},"    fetch",[130,486,487],{"class":147},"(\n",[130,489,491,494],{"class":132,"line":490},30,[130,492,493],{"class":154},"      \"https://raw.githubusercontent.com/h3js/crossws/refs/heads/main/playground/public/index.html\"",[130,495,496],{"class":147},",\n",[130,498,500,503,506],{"class":132,"line":499},31,[130,501,502],{"class":147},"    ).",[130,504,505],{"class":171},"then",[130,507,487],{"class":147},[130,509,511,514,517,520],{"class":132,"line":510},32,[130,512,513],{"class":147},"      (",[130,515,516],{"class":193},"res",[130,518,519],{"class":147},") ",[130,521,478],{"class":143},[130,523,525,528,531,534,537,540,543],{"class":132,"line":524},33,[130,526,527],{"class":143},"        new",[130,529,530],{"class":171}," Response",[130,532,533],{"class":147},"(res.body, { headers: { ",[130,535,536],{"class":154},"\"Content-Type\"",[130,538,539],{"class":147},": ",[130,541,542],{"class":154},"\"text/html\"",[130,544,545],{"class":147}," } }),\n",[130,547,549],{"class":132,"line":548},34,[130,550,551],{"class":147},"    ),\n",[130,553,555],{"class":132,"line":554},35,[130,556,557],{"class":147},"});\n",[78,559,560],{},"Then, run the server using your favorite runtime:",[562,563,564,579,601],"code-group",{},[120,565,570],{"className":566,"code":567,"filename":568,"language":569,"meta":126,"style":126},"language-bash shiki shiki-themes github-light github-dark github-dark","node server.mjs\n","node","bash",[104,571,572],{"__ignoreMap":126},[130,573,574,576],{"class":132,"line":133},[130,575,568],{"class":171},[130,577,578],{"class":154}," server.mjs\n",[120,580,583],{"className":566,"code":581,"filename":582,"language":569,"meta":126,"style":126},"deno run --allow-env --allow-net server.mjs\n","deno",[104,584,585],{"__ignoreMap":126},[130,586,587,589,592,596,599],{"class":132,"line":133},[130,588,582],{"class":171},[130,590,591],{"class":154}," run",[130,593,595],{"class":594},"suiK_"," --allow-env",[130,597,598],{"class":594}," --allow-net",[130,600,578],{"class":154},[120,602,605],{"className":566,"code":603,"filename":604,"language":569,"meta":126,"style":126},"bun run server.mjs\n","bun",[104,606,607],{"__ignoreMap":126},[130,608,609,611,613],{"class":132,"line":133},[130,610,604],{"class":171},[130,612,591],{"class":154},[130,614,578],{"class":154},[616,617,618],"alert",{},[78,619,620,621,624,625,630,631,99],{},"When using ",[104,622,623],{},"crossws/server",", export conditions automatically resolve the right runtime adapter and integrate with ",[93,626,629],{"href":627,"rel":628},"https://srvx.h3.dev",[97],"💥 srvx",". You can alternatively, manually integrate crossws with ",[93,632,37],{"href":38},[634,635,636],"read-more",{"title":12,"to":13},[78,637,638,639,641],{},"See ",[93,640,12],{"href":13}," for more usage details.",[634,643,644],{"title":37,"to":38},[78,645,646,647,649],{},"Hooks API is exactly same on all runtimes. See ",[93,648,37],{"href":38}," for integration details.",[651,652,653],"style",{},"html pre.shiki code .sCsY4, html code.shiki .sCsY4{--shiki-light:#6A737D;--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .so5gQ, html code.shiki .so5gQ{--shiki-light:#D73A49;--shiki-default:#F97583;--shiki-dark:#F97583}html pre.shiki code .slsVL, html code.shiki .slsVL{--shiki-light:#24292E;--shiki-default:#E1E4E8;--shiki-dark:#E1E4E8}html pre.shiki code .sfrk1, html code.shiki .sfrk1{--shiki-light:#032F62;--shiki-default:#9ECBFF;--shiki-dark:#9ECBFF}html pre.shiki code .shcOC, html code.shiki .shcOC{--shiki-light:#6F42C1;--shiki-default:#B392F0;--shiki-dark:#B392F0}html pre.shiki code .sQHwn, html code.shiki .sQHwn{--shiki-light:#E36209;--shiki-default:#FFAB70;--shiki-dark:#FFAB70}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .suiK_, html code.shiki .suiK_{--shiki-light:#005CC5;--shiki-default:#79B8FF;--shiki-dark:#79B8FF}",{"title":126,"searchDepth":140,"depth":140,"links":655},[656],{"id":84,"depth":140,"text":85},"crossws provides a cross-platform toolkit to define well-typed WebSocket apps that can then be integrated into various WebSocket servers using built-in adapters.","md",{"automd":164,"icon":10},{"icon":10},{"title":5,"description":657},"RfTak40HmGKJXQCgXEsflLZAsAnNIE5mHJiV9BoqKbY",[664,665],null,{"title":12,"path":13,"stem":14,"description":666,"icon":15,"children":-1},"Using hooks, you can define a WebSocket server that works across runtimes with the same syntax.",1771506026542]