diff --git a/deploy/truenas/core/Dockerfile b/deploy/truenas/core/Dockerfile
index 6495ab3..8cc7a3c 100644
--- a/deploy/truenas/core/Dockerfile
+++ b/deploy/truenas/core/Dockerfile
@@ -47,7 +47,13 @@ COPY --from=builder /src/ffmigrate /core/bin/ffmigrate
COPY --from=builder /src/mime.types /core/mime.types
COPY --from=builder /src/run.sh /core/bin/run.sh
-RUN mkdir -p /core/config /core/data
+# Dragon Fork landing page + browser WHEP player. Seeded into
+# /core/data on first boot by /core/bin/seed-data.sh below; the seed
+# is a no-op when the operator has already put content in /core/data.
+COPY --from=builder /src/deploy/truenas/core/static/ /core/static/
+COPY --from=builder /src/deploy/truenas/core/seed-data.sh /core/bin/seed-data.sh
+
+RUN chmod +x /core/bin/seed-data.sh && mkdir -p /core/config /core/data
ENV CORE_CONFIGFILE=/core/config/config.json
ENV CORE_STORAGE_DISK_DIR=/core/data
@@ -56,5 +62,8 @@ ENV CORE_DB_DIR=/core/config
VOLUME ["/core/data", "/core/config"]
EXPOSE 8080/tcp
-ENTRYPOINT ["/sbin/tini", "--", "/core/bin/run.sh"]
+# Seed /core/data on first boot, then exec the upstream run.sh which
+# handles imports, ffmpeg migrations, and the core binary. tini reaps
+# child PIDs and forwards signals.
+ENTRYPOINT ["/sbin/tini", "--", "/bin/sh", "-c", "/core/bin/seed-data.sh && exec /core/bin/run.sh"]
WORKDIR /core
diff --git a/deploy/truenas/core/seed-data.sh b/deploy/truenas/core/seed-data.sh
new file mode 100755
index 0000000..3d05a52
--- /dev/null
+++ b/deploy/truenas/core/seed-data.sh
@@ -0,0 +1,33 @@
+#!/bin/sh
+# seed-data.sh — first-boot seed of /core/data with Dragon Fork
+# landing page artifacts (index.html, whep-player.html).
+#
+# Runs from the entrypoint before bin/core. Skips itself if any of the
+# target files already exist, so user-supplied content (or content from
+# a previous deploy that they edited) is never clobbered.
+#
+# Source dir: /core/static (baked by the Dockerfile)
+# Target dir: /core/data (operator-mounted; what Core serves at /)
+
+set -e
+
+SRC=/core/static
+DST="${CORE_STORAGE_DISK_DIR:-/core/data}"
+
+if [ ! -d "$SRC" ]; then
+ # No static dir baked — nothing to seed. Fall through silently.
+ exit 0
+fi
+
+if [ ! -d "$DST" ]; then
+ mkdir -p "$DST"
+fi
+
+for f in "$SRC"/*; do
+ [ -e "$f" ] || continue
+ name=$(basename "$f")
+ if [ ! -e "$DST/$name" ]; then
+ cp -p "$f" "$DST/$name"
+ echo "seed-data: copied $name -> $DST/$name"
+ fi
+done
diff --git a/deploy/truenas/core/static/index.html b/deploy/truenas/core/static/index.html
new file mode 100644
index 0000000..ba88bf8
--- /dev/null
+++ b/deploy/truenas/core/static/index.html
@@ -0,0 +1,69 @@
+
+
+
+
+Datarhei — Dragon Fork
+
+
+
+
+
+
+ Quick links
+
+
API documentation (Swagger UI)
+
Full HTTP API including /api/v3/process, /api/v3/whep/{id}, RTMP / SRT / config / metrics. Most endpoints require a JWT — issue one via POST /api/login.
+
+
+
Browser WHEP player
+
Self-contained subscriber for any process whose config.webrtc.enabled = true. Paste the WHEP URL and a JWT; press Subscribe.
+
+
+ About this build
+ Loading…
+
+ How to add a WebRTC stream
+
+
Create a process with "webrtc": { "enabled": true }. Once it starts, POST /api/v3/whep/<process-id> takes an SDP offer and returns an SDP answer.
+
+
+ Datarhei — Dragon Fork · Apache License 2.0 · Built on datarhei Core + Pion WebRTC
+
+
+
diff --git a/deploy/truenas/core/static/whep-player.html b/deploy/truenas/core/static/whep-player.html
new file mode 100644
index 0000000..0ecb568
--- /dev/null
+++ b/deploy/truenas/core/static/whep-player.html
@@ -0,0 +1,354 @@
+
+
+
+
+Dragon Fork — WHEP Player
+
+
+
+
+
+ Dragon Fork WHEP
+ manual smoke test for the WebRTC egress path
+
+
+
+
+
+
+
+
+
+
+