PanelsXR

PanelsXR

Docker app from dervish's Repository

Overview

Panel is a WebXR comic reader that streams your self-hosted Komga library into a Meta Quest 3 headset. Resume where your iPad left off, turn pages on the thumbstick, and browse a 3D library of your series. Runs in the Quest browser (no store, no sideload). Set KOMGA_URL to your Komga address and KOMGA_API_KEY to a Komga API key (Komga, Account Settings, API Keys). The key is injected server-side and never reaches the browser. IMPORTANT: WebXR needs HTTPS. Access this behind a reverse proxy (SWAG / Nginx Proxy Manager / Cloudflare Tunnel). A plain http address loads the 2D page but the Quest browser will not enter VR.

Panel — WebXR comic reader for Komga

Panel streams a self-hosted Komga comic library straight into a Meta Quest 3 headset. Put the headset on and it opens where you left off on the iPad; browse your whole library as a wall of floating covers; turn pages on the thumbstick. It runs in the Quest browser — no store, no native build, no sideload — and self-hosts as a single Docker container next to Komga.

The A–Z alphabet shelf — each letter is a stack of your comics; pick one to be surrounded by that letter's series

Status: v0.2.0 — self-hostable and on Docker Hub. Single-user / family focused, young but real. See CHANGELOG.md.

Features

Recent mode surrounds you with your continue-reading and on-deck covers

  • Auto-resume — reopens your last book fresh from Komga on load, so progress read anywhere (e.g. the iPad) carries over with zero clicks. Read-progress syncs back on every page turn.
  • A 3D library — browse the whole collection as an A–Z "Alphabet Shelf": letter stacks sized by how much you have under each, pick a letter to be surrounded by its series, drill into a series' issues, page through big sets. Plus a Recent mode (continue-reading + on-deck) and a flat 2D browser.
  • A comfortable reader — the page composited crisp on a plane with a backing board + paper stack so it reads as a physical object; single-page and two-page spreads; grab-to-move, two-handed resize, stick locomotion, recenter.
  • Comic-shop-pulp look — warm-black palette, one pulp-red accent, chunky display type, halftone and hard-offset "misregistration" shadows.

Self-hosting (Docker)

Panel ships as one container: the static app + a Caddy proxy that talks to your Komga with the API key injected server-side (so the browser never sees it).

docker run -d --name panel -p 8677:80 \
  -e KOMGA_URL="http://192.168.1.10:8080" \
  -e KOMGA_API_KEY="your-read-only-komga-key" \
  -e PANEL_PASSWORD="a-strong-password" \
  --restart unless-stopped \
  dervish/panelsxr:latest

Two things to get right:

  1. WebXR needs HTTPS. A plain http://…:8677 loads the 2D page but the Quest won't enter VR — front Panel with a reverse proxy / tunnel (SWAG, Nginx Proxy Manager, Cloudflare Tunnel) so it's served over https://.
  2. Gate it. The proxy injects your Komga key, so an ungated public Panel is an open proxy to your library. Panel is fail-closed: it won't serve /komga unless you set PANEL_PASSWORD (built-in login, cached one-time by the Quest) or explicitly PANEL_AUTH=none (LAN-only / gated upstream). Use a dedicated read-only Komga user's key to cap the blast radius.

Full guide, env reference, and an Unraid Community Applications template: deploy/unraid/.

Development

npm install
npm run dev          # http://localhost:5173 — desktop iteration
npm run dev:quest    # HTTPS on the LAN for a real headset (self-signed)
npm run build        # tsc --noEmit && vite build
npm test             # vitest — headset-independent logic

On localhost with no WebXR, @react-three/xr v6 auto-activates an emulated Quest 3 (IWER), so Enter VR gives a real emulated session on desktop. Set your Komga connection in .env.local (copy .env.example); the dev server proxies /komga/* and injects the key, same as the container.

Tech

Vite + React 19 + TypeScript · three.js · @react-three/fiber · @react-three/xr v6 (createXRStore, XRLayer, controller state) · @react-three/handle · drei · JSZip (dev-only .cbz). Container: multi-stage build → Caddy. Node 22.

License

MIT.

Install PanelsXR on Unraid in a few clicks.

Find PanelsXR in Community Apps on your Unraid server, review the template, and click Install. Unraid handles the Docker app or plugin setup from the published template.

Open the Apps tab on your Unraid server Search Community Apps for PanelsXR Review the template variables and paths Click Install

Download Statistics

119
Total Downloads

Related apps

Explore more like this

Explore all

Details

Repository
dervish/panelsxr:latest
Last Updated2026-07-05
First Seen2026-07-06

Runtime arguments

Web UI
http://[IP]:[PORT:80]/
Network
bridge
Shell
sh
Privileged
false

Template configuration

WebUI PortPorttcp

Port for the Panel web UI

Target
80
Default
8677
Value
8677
Komga URLVariable

Your Komga base URL, e.g. http://192.168.1.10:8080

Target
KOMGA_URL
Komga API KeyVariable

Use a DEDICATED READ-ONLY Komga user's key (Komga, Account Settings, API Keys). It is injected server-side and never sent to the browser, but it also bypasses Komga's own auth, so a read-only key caps the blast radius to 'someone saw my comics' instead of full account access.

Target
KOMGA_API_KEY
Basic Auth UserVariable

Username for the built-in login (only used if a password is set below).

Target
PANEL_USER
Default
panel
Value
panel
PasswordVariable

Set a password to lock the whole app + Komga proxy behind a login (the Quest browser remembers it, so it's a one-time login). SAFE BY DEFAULT: if you leave this blank, Panel refuses to serve your library (503) until you set one — unless you set the Auth Mode below to 'none'. Set it here before first run.

Target
PANEL_PASSWORD
Auth Mode (advanced)Variable

Leave blank to use the Password above (recommended). Set to 'none' ONLY if Panel is LAN-only or already gated by a reverse proxy / Cloudflare Access / Authelia — 'none' serves your whole library to anyone who can reach the URL.

Target
PANEL_AUTH