diff --git a/README.md b/README.md
index cef5181..78fbae4 100644
--- a/README.md
+++ b/README.md
@@ -126,12 +126,18 @@ browser loads its JavaScript from that origin, is in the
## Status
-Pre-1.0, and honest about it. The local terminal, the login service, the
-fleet-wide sessions list and the end-to-end pairing all work. The Cloudflare
-relay is built and deployable but has not been through its manual end-to-end
-gate against a real account ([docs/RELAY.md](docs/RELAY.md)), so treat it as
-ready to try rather than ready to rely on. Known rough edges live in
-[docs/FOLLOW-UPS.md](docs/FOLLOW-UPS.md).
+Released and in daily use. v0.5.1 is the current release, `brew install
+karnstack/tap/flue` gets it, and the whole of it works: the local terminal, the
+login service, the fleet-wide sessions list, pairing, and the Cloudflare relay.
+The relay has been through its manual end-to-end gate
+([docs/RELAY.md](docs/RELAY.md)) against a real account, with a phone on a
+different network paired to it and a second machine joined to the same relay.
+There is a recording of that run at
+[flue.sh/docs/setup](https://flue.sh/docs/setup).
+
+It is 0.x, which means what it usually means: commands, flags and the config
+file can still change between releases, and an upgrade may ask something of
+you. Known rough edges live in [docs/FOLLOW-UPS.md](docs/FOLLOW-UPS.md).
flue is open source and always free.
diff --git a/site/package.json b/site/package.json
index fbfdd84..1b58c09 100644
--- a/site/package.json
+++ b/site/package.json
@@ -13,6 +13,7 @@
"deploy": "wrangler deploy"
},
"dependencies": {
+ "@karnstack/kino": "^0.12.0",
"@tanstack/react-router": "1.170.17",
"@tanstack/react-start": "1.168.27",
"class-variance-authority": "^0.7.1",
diff --git a/site/pnpm-lock.yaml b/site/pnpm-lock.yaml
index d512239..59c6a56 100644
--- a/site/pnpm-lock.yaml
+++ b/site/pnpm-lock.yaml
@@ -8,6 +8,9 @@ importers:
.:
dependencies:
+ '@karnstack/kino':
+ specifier: ^0.12.0
+ version: 0.12.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
'@tanstack/react-router':
specifier: 1.170.17
version: 1.170.17(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
@@ -539,6 +542,22 @@ packages:
'@jridgewell/trace-mapping@0.3.9':
resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==}
+ '@karnstack/kino@0.12.0':
+ resolution: {integrity: sha512-kwrpXfSNPY+lSVms4uI62TQkGRPdPgLs0AhTNfU9FPqtZI7jm2A96B60W+LAYqhWfuxPtt6ZNf3UijIvWyivWg==}
+ engines: {node: '>=24'}
+ peerDependencies:
+ react: '>=19'
+ react-dom: '>=19'
+
+ '@mux/mux-data-google-ima@0.3.17':
+ resolution: {integrity: sha512-4wpH6dYybyZhqLn9qGn/+67Z8MZnQRAdqTFEEZw2bx61M9q01uPYYHxd8qwOnYtUGEeafsdTwVHVxKHGD3oc1A==}
+
+ '@mux/mux-video@0.31.2':
+ resolution: {integrity: sha512-waahxlrat1PpRzcY2pwMQJ5Gyhos+D6iRyKnYzF0wBf4SESfBtunSBj3EuKuljypm8bamh9gWnlA0LSzm5Pz1w==}
+
+ '@mux/playback-core@0.35.2':
+ resolution: {integrity: sha512-AsMV0LMwJm9T1ig6BBYSddeMlkzz+2RGcd6dkOgYk+L5Hx477ovbTxJZJ/vTW+rZjNWHcG3BvgNbSLgiubyZhw==}
+
'@napi-rs/wasm-runtime@1.2.2':
resolution: {integrity: sha512-JfB4kuJQjaoHuCTseIINHtHWeJnvgEcxjwA5t/Y00ZgaOO1Crz3fjT/p8kT28zA/Caz7oiUMn3d6H2yOVCVwuw==}
engines: {node: ^20.19.0 || ^22.13.0 || >=23.5.0}
@@ -1599,6 +1618,9 @@ packages:
'@tybys/wasm-util@0.10.3':
resolution: {integrity: sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==}
+ '@types/google_interactive_media_ads_types@3.697.1':
+ resolution: {integrity: sha512-gRjJoPKQRjjTuySHqZe8Pnu6a5B0bKbTUD2ioDLPSWlEuBaAc2p1mzUzy42SCeWkyYffo2Mnv+blUGuvVvx3dQ==}
+
'@types/react-dom@19.2.3':
resolution: {integrity: sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==}
peerDependencies:
@@ -1650,6 +1672,9 @@ packages:
caniuse-lite@1.0.30001809:
resolution: {integrity: sha512-xxWVywk6a6Arlk+hymeycyn/VgqEfLDxupvhH/xiY5SJ/18kmi9o6MiO320DCUzypORHLtvh0I4i04tUhCNHNQ==}
+ castable-video@1.1.16:
+ resolution: {integrity: sha512-wBhe2dZu2afhewL3EaGgVYTyDsa9HvNhY98clMZkNzDrLelOValSrTaoMos9YX7PPBCrgpd1j6YmNyyI2Vbq3w==}
+
chokidar@5.0.0:
resolution: {integrity: sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==}
engines: {node: '>= 20.19.0'}
@@ -1674,6 +1699,9 @@ packages:
csstype@3.2.3:
resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==}
+ custom-media-element@1.4.6:
+ resolution: {integrity: sha512-/HRYqJOa1ob5ik4q7FIJVYxTJCFs/FL3+cQPAJjUf2uiqrDEzbTgB315gQ2rG8oK3w094W9m5tcB8S5Qah+caA==}
+
debug@4.4.3:
resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==}
engines: {node: '>=6.0'}
@@ -1754,6 +1782,9 @@ packages:
crossws:
optional: true
+ hls.js@1.6.17:
+ resolution: {integrity: sha512-NUplVGVuc1hSPwdB/9/cbRkUmLrYi75/hqiXKdA+l300pJNxDu96R7jRb2imDzWJqIUF4I5ThmAdp9GvOCXsuQ==}
+
isbot@5.2.1:
resolution: {integrity: sha512-dJ+LpKyClQZ7NG+j3OensC/mAZkGpukE9YUrgPYvAZj2doVL0edfDgywTUh5CXa0o+nW9a1V9e5+CJTX8+SxRw==}
engines: {node: '>=18'}
@@ -1942,6 +1973,9 @@ packages:
magic-string@0.30.21:
resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==}
+ media-tracks@0.3.5:
+ resolution: {integrity: sha512-l54rkKXlLBt3ob3zOLWHcnjvwUmX5bNEZ70igyapOZZC9imzqBmq1oz8p2roiV04KhjblFIi2hetLPF1oYVLRA==}
+
miniflare@4.20260701.0:
resolution: {integrity: sha512-L6eAAi6IKtyb/7J6L+YsH2vb1yBrJWKRXI293JYDiMl70+6nncdAgigex58w6WBd+CwvdMsqOyNyGs95Op5gWQ==}
engines: {node: '>=22.0.0'}
@@ -1950,6 +1984,9 @@ packages:
ms@2.1.3:
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
+ mux-embed@5.18.1:
+ resolution: {integrity: sha512-ePsHjiEKY+FgrSBiMmaF+LOtTQSSBWv/1zqpREQFN96JE93xlsArT/MEi30yKOE06MgjOlL70YI750molu3y7g==}
+
nanoid@3.3.18:
resolution: {integrity: sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w==}
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
@@ -2655,6 +2692,30 @@ snapshots:
'@jridgewell/resolve-uri': 3.1.2
'@jridgewell/sourcemap-codec': 1.5.5
+ '@karnstack/kino@0.12.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7)':
+ dependencies:
+ '@mux/mux-video': 0.31.2
+ react: 19.2.7
+ react-dom: 19.2.7(react@19.2.7)
+
+ '@mux/mux-data-google-ima@0.3.17':
+ dependencies:
+ mux-embed: 5.18.1
+
+ '@mux/mux-video@0.31.2':
+ dependencies:
+ '@mux/mux-data-google-ima': 0.3.17
+ '@mux/playback-core': 0.35.2
+ '@types/google_interactive_media_ads_types': 3.697.1
+ castable-video: 1.1.16
+ custom-media-element: 1.4.6
+ media-tracks: 0.3.5
+
+ '@mux/playback-core@0.35.2':
+ dependencies:
+ hls.js: 1.6.17
+ mux-embed: 5.18.1
+
'@napi-rs/wasm-runtime@1.2.2(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)':
dependencies:
'@emnapi/core': 1.11.1
@@ -3784,6 +3845,8 @@ snapshots:
tslib: 2.8.1
optional: true
+ '@types/google_interactive_media_ads_types@3.697.1': {}
+
'@types/react-dom@19.2.3(@types/react@19.2.17)':
dependencies:
'@types/react': 19.2.17
@@ -3828,6 +3891,10 @@ snapshots:
caniuse-lite@1.0.30001809: {}
+ castable-video@1.1.16:
+ dependencies:
+ custom-media-element: 1.4.6
+
chokidar@5.0.0:
dependencies:
readdirp: 5.1.1
@@ -3846,6 +3913,8 @@ snapshots:
csstype@3.2.3: {}
+ custom-media-element@1.4.6: {}
+
debug@4.4.3:
dependencies:
ms: 2.1.3
@@ -3918,6 +3987,8 @@ snapshots:
rou3: 0.8.1
srvx: 0.11.22
+ hls.js@1.6.17: {}
+
isbot@5.2.1: {}
jiti@2.7.0: {}
@@ -4044,6 +4115,8 @@ snapshots:
dependencies:
'@jridgewell/sourcemap-codec': 1.5.5
+ media-tracks@0.3.5: {}
+
miniflare@4.20260701.0:
dependencies:
'@cspotcode/source-map-support': 0.8.1
@@ -4058,6 +4131,8 @@ snapshots:
ms@2.1.3: {}
+ mux-embed@5.18.1: {}
+
nanoid@3.3.18: {}
node-releases@2.0.53: {}
diff --git a/site/src/components/walkthrough.tsx b/site/src/components/walkthrough.tsx
new file mode 100644
index 0000000..a9ea46c
--- /dev/null
+++ b/site/src/components/walkthrough.tsx
@@ -0,0 +1,66 @@
+import { MuxPlayer } from '@karnstack/kino/mux'
+import '@karnstack/kino/styles.css'
+import { Clapperboard } from 'lucide-react'
+
+import {
+ WALKTHROUGH_BLUR,
+ WALKTHROUGH_PLAYBACK_ID,
+ WALKTHROUGH_POSTER,
+ WALKTHROUGH_RUNTIME,
+} from '@/lib/site'
+import { cn } from '@/lib/utils'
+
+/**
+ * The setup walkthrough.
+ *
+ * Nothing here starts playback, and that is worth saying because kino's
+ * `autoPlay` prop is right there and using it breaks in a way that takes a
+ * while to see. kino builds its
Everything crossing it is end-to-end encrypted with Noise IK. Your browser pins the
daemon’s key when it pairs, so the Worker forwards ciphertext it holds no key
- for. The relay is new: it works, but it has not been through its release gate, so
- treat it as ready to try rather than ready to rely on.
+ for. It is a 0.x release, so commands and config can still change between versions.