OverviewFilesCommitsIssuesDocsReleasesPeers

pearbrowser-desktop / examples / headless-tab / wrapper.html

45 lines · html ref:
<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <title>headless tab</title>
  <script src="/htmx.min.js"></script>
  <script src="/pear-request-client.bundle.js"></script>
  <style>body{background:#0b0e14;margin:0}#boot{font:15px system-ui;color:#7a8;margin:40px auto;max-width:560px}</style>
</head>
<body>
  <div id="boot">connecting to headless worker…</div>
  <script>
  (function () {
    // A pipe shim over a WebSocket. The WS bridges to the Pear worker's duplex
    // pipe on the backend. WS preserves message boundaries, so each frame is
    // one pear-request message (the framing the client/router already expect).
    var proto = location.protocol === 'https:' ? 'wss' : 'ws'
    var ws = new WebSocket(proto + '://' + location.host + '/__pipe' + location.search)
    ws.binaryType = 'arraybuffer'

    var listeners = {}
    function on (ev, cb) { (listeners[ev] || (listeners[ev] = [])).push(cb) }
    var pipe = {
      write: function (buf) { ws.send(buf); return true },
      on: on,
      once: function (ev, cb) { var w = function () { var i = listeners[ev].indexOf(w); if (i >= 0) listeners[ev].splice(i, 1); cb.apply(null, arguments) }; on(ev, w) }
    }
    ws.onmessage = function (e) {
      var data = globalThis.Buffer.from(e.data)
      ;(listeners.data || []).forEach(function (cb) { cb(data) })
    }
    ws.onerror = function () { document.getElementById('boot') && (document.getElementById('boot').textContent = 'worker pipe error') }
    ws.onclose = function () { var b = document.getElementById('boot'); if (b) b.textContent = 'worker disconnected' }
    ws.onopen = function () {
      // swap in the stream-backed XMLHttpRequest, then let htmx pull the app's
      // root UI from the worker (GET /) into <body>. From here it's all htmx.
      globalThis.XMLHttpRequest = globalThis.createPearRequest(pipe)
      window.__PEAR_TAB_READY = true
      htmx.ajax('GET', '/', { target: 'body', swap: 'innerHTML' })
    }
  })()
  </script>
</body>
</html>