diff --git a/examples/webtransport/.gitignore b/examples/webtransport/.gitignore
new file mode 100644
index 00000000..cfaad761
--- /dev/null
+++ b/examples/webtransport/.gitignore
@@ -0,0 +1 @@
+*.pem
diff --git a/examples/webtransport/README.md b/examples/webtransport/README.md
new file mode 100644
index 00000000..d7d0e36b
--- /dev/null
+++ b/examples/webtransport/README.md
@@ -0,0 +1,18 @@
+
+# Socket.IO WebTransport example
+
+## How to use
+
+```shell
+# generate a self-signed certificate
+$ ./generate_cert.sh
+
+# install dependencies
+$ npm i
+
+# start the server
+$ node index.js
+
+# open a Chrome browser
+$ ./open_chrome.sh
+```
diff --git a/examples/webtransport/generate_cert.sh b/examples/webtransport/generate_cert.sh
new file mode 100755
index 00000000..72d8198a
--- /dev/null
+++ b/examples/webtransport/generate_cert.sh
@@ -0,0 +1,8 @@
+#!/bin/bash
+openssl req -new -x509 -nodes \
+ -out cert.pem \
+ -keyout key.pem \
+ -newkey ec \
+ -pkeyopt ec_paramgen_curve:prime256v1 \
+ -subj '/CN=127.0.0.1' \
+ -days 14
diff --git a/examples/webtransport/index.html b/examples/webtransport/index.html
new file mode 100644
index 00000000..4909653e
--- /dev/null
+++ b/examples/webtransport/index.html
@@ -0,0 +1,35 @@
+
+
+
+
+ Socket.IO WebTransport exampleqg
+
+
+
+
+
+
diff --git a/examples/webtransport/index.js b/examples/webtransport/index.js
new file mode 100644
index 00000000..75aab49b
--- /dev/null
+++ b/examples/webtransport/index.js
@@ -0,0 +1,68 @@
+import { readFileSync } from "node:fs";
+import { createServer } from "node:https";
+import { Server } from "socket.io";
+import { Http3Server } from "@fails-components/webtransport";
+
+const key = readFileSync("./key.pem");
+const cert = readFileSync("./cert.pem");
+
+const httpsServer = createServer({
+ key,
+ cert
+}, (req, res) => {
+ if (req.method === "GET" && req.url === "/") {
+ const content = readFileSync("./index.html");
+ res.writeHead(200, {
+ "content-type": "text/html"
+ });
+ res.write(content);
+ res.end();
+ } else {
+ res.writeHead(404).end();
+ }
+});
+
+const io = new Server(httpsServer, {
+ transports: ["polling", "websocket", "webtransport"]
+});
+
+const port = process.env.PORT || 3000;
+
+io.on("connection", (socket) => {
+ console.log(`connect ${socket.id}`);
+
+ socket.conn.on("upgrade", (transport) => {
+ console.log(`transport upgraded to ${transport.name}`);
+ });
+
+ socket.on("disconnect", (reason) => {
+ console.log(`disconnect ${socket.id} due to ${reason}`);
+ });
+});
+
+httpsServer.listen(port, () => {
+ console.log(`server listening at https://localhost:${port}`);
+});
+
+const h3Server = new Http3Server({
+ port,
+ host: "0.0.0.0",
+ secret: "changeit",
+ cert,
+ privKey: key,
+});
+
+(async () => {
+ const stream = await h3Server.sessionStream("/socket.io/");
+ const sessionReader = stream.getReader();
+
+ while (true) {
+ const { done, value } = await sessionReader.read();
+ if (done) {
+ break;
+ }
+ io.engine.onWebTransportSession(value);
+ }
+})();
+
+h3Server.startServer();
diff --git a/examples/webtransport/open_chrome.sh b/examples/webtransport/open_chrome.sh
new file mode 100755
index 00000000..de3b8435
--- /dev/null
+++ b/examples/webtransport/open_chrome.sh
@@ -0,0 +1,10 @@
+#!/bin/bash
+HASH=`openssl x509 -pubkey -noout -in cert.pem |
+ openssl pkey -pubin -outform der |
+ openssl dgst -sha256 -binary |
+ base64`
+
+/opt/google/chrome/chrome \
+ --origin-to-force-quic-on=127.0.0.1:3000 \
+ --ignore-certificate-errors-spki-list=$HASH \
+ https://localhost:3000
diff --git a/examples/webtransport/package.json b/examples/webtransport/package.json
new file mode 100644
index 00000000..8e600642
--- /dev/null
+++ b/examples/webtransport/package.json
@@ -0,0 +1,11 @@
+{
+ "name": "webtransport",
+ "version": "0.0.1",
+ "description": "",
+ "private": true,
+ "type": "module",
+ "dependencies": {
+ "@fails-components/webtransport": "^0.1.7",
+ "socket.io": "^4.7.1"
+ }
+}