Software
Features
Experiences

Experiences Gallery

The gallery on cloud.pieeg.com (opens in a new tab) (and the self-hosted dashboard) is a card-based launcher for immersive EEG experiences. Every entry is lazy-loaded from a single registry — adding one does not grow the initial dashboard bundle.

Open the gallery with V, or from the dashboard header. Search and filter by category (VR, AR, XR/MR, BCI, ML, EOG, Face/EMG, Audio, Games, Lab, Meditation). Featured cards currently highlight octoCaptcha, Neural Flight, PiEEG Virtual Lab, Room Buddy, Mind Reader, and Spoon Bend.

Catalog below matches the local PiEEG-server-cloud registry (cloud/src/experiences/registry.ts) — 34 playable experiences. Empty folders that are not registered (blink-runner, affective-mirror) are omitted.

How to run them

WhereHow
Cloudcloud.pieeg.com (opens in a new tab) → connect a board (or Use Demo Server) → V
Self-hostedPiEEG Server dashboard at http://<host>:1617 → same gallery
HardwareMost run on the raw browser EEG stream (IronBCI BLE / Serial, demo signal). A few need extra hardware or a local server — see badges below.
BadgeMeaning
PiEEG ServerNeeds a locally running PiEEG Server (WebSocket commands). Will not work in 100% cloud.
Aura requiredNeeds Aura VR (8-ch palm EMG + IMU).
VR / handsWebXR headset and optional hand tracking.

Every experience must explain itself in the UI: a How it works overlay on first open, a header button to reopen it, and honest sensor limits. Do not bury that only in a README.


Featured

ExperienceTagDescription
octoCaptchaEOG / LivenessCognitive CAPTCHA: blink N times after a random GO cue. Verifies living EOG morphology on Fp1/Fp2 (envelope, spatial coherence, count, human timing). Proof-of-concept liveness, not a production credential.
Neural FlightVR / ARFirst-person flight over a procedural world — focus is lift. Demo autopilot, then Live. Asset-free noise terrain. VR or AR.
PiEEG Virtual LabLab / VRPhotoreal lab with the live dashboard on the workstation monitor. WASD + mouse, sit to interact, or enter VR.
Room Buddy (AR)ARPlace a buddy on your floor with phone AR. It waves, hops on focus, flinches on blink. Vanilla three.js WebXR.
Mind ReaderBCI / MLP300 “guess my number” (1–9). Cued teaching trains placement-agnostic shrinkage-LDA; Bayesian accumulation reads live. Each round folds back into training.
Spoon BendFocusMatrix-style telekinesis. Beta/gamma drive the 3D spoon; digital rain; baseline calibration.

Liveness & identity

ExperienceTagDescription
octoCaptchaEOG / LivenessRandom nonce blink count after GO. Replay fails; a compromised EEG source can spoof any sensor CAPTCHA.
octoAuthBCI / BiometricOctopus-16 neck array. Random neck-action challenge + high-density EMG identity (group-lasso electrode map, LORO-CV). Proof-of-concept, not a production credential.

Learn

ExperienceTagDescription
Signal LabLearn / GameDSP mini-course: Time Domain → Cleaning → Frequency Domain. Theory, live EEG sandbox, quiz (up to 3 stars). Progress saved.

XR, VR & AR

ExperienceTagNotesDescription
Room Buddy (AR)ARPhone AR buddy driven by focus and blinks.
PiEEG Virtual LabLab / VRVR + handsWalk a neuroscience lab; full dashboard on the in-world monitor.
Neural Wave SpaceVR / 3DVR + hands3D EEG wave arc in a starfield.
Neural FlightVR / ARVR + handsFocus-controlled flight over an endless daylit world.
Northern LightsVR / AudioVR + handsAurora curtains shaped by δ/α/γ; ethereal sonification.
Premeditatio MalorumXR / StoicVRMixed-reality Stoic pairs of 360° YouTube scenes. Hold high alpha through disruption; score is beta-spike recovery to baseline.
The Glitching RealityMR / ShaderCamera passthrough + WebGL2. Frontal Alpha Asymmetry: equanimity keeps the room clear; load shreds it. Optional mental-arithmetic stressor.

Audio

ExperienceTagDescription
Neural SonificationAudioBands → music: Delta drone, Theta FM pad, Alpha lead, Beta harmonics, Gamma shimmer. DJ controls for scale, key, reverb, delay.
MindCastAudioPodcast speed follows focus — zone out and it slows, lock in and it speeds up.
Northern LightsVR / AudioWind, drones, and chimes layered on the aurora.

Games

ExperienceTagNotesDescription
Spoon BendFocusBend a virtual spoon with focus.
Penalty ShootersBCI / GameRetro SNES penalty kicks. Blink to shoot; trainless adaptive frontal detector.
Neural Maze LockBCI / GameEOG gaze maze with focus / calm / blink gates. Tracks false triggers and completion time.
Orb ControlBCI / EOGFocus grabs the orb, gaze moves it, calm steadies it, artifacts destabilize it, blink releases charge.
Hand of GodBCI / Game / sEMGAuraMexico ’86 hang-ball punch. Space/click, or Aura fist. Score only when the referee looks away.

BCI & machine learning

ExperienceTagDescription
Blink BrowserBCIScroll articles with blinks. Per-user calibration on frontal electrodes.
Eye TrackBCIEOG gaze from Fp1/Fp2. Polynomial ridge regression, online adaptive learning, localStorage models, live algorithm editor.
P300 Mini-GameBCI / MLShrinkage-LDA P300 decoder, Bayesian accumulation, labelled-dataset export. Themeable stimulus grid; reusable marker contract.
Mind ReaderBCI / MLP300 number oracle with live teaching.
Silent Speech InterfaceBCI / ML / sEMGSubvocal word decoder (AlterEgo-inspired). Closed vocabulary, onset epoching, L2 + group-lasso, LORO-CV. Not open dictation.

See also Detectors for the shared useFocus / useRelax / useBlink / useBandPowers hooks many of these sit on.


Avatar, face & EMG

ExperienceTagDescription
Avatar Neurofeedback StudioBCI / AvatarVRM face from EEG. Drag channel × band → expression. Contrastive REST vs ACTIVE trainer ranks 32 ch × 5 bands by Cohen’s d.
Avatar Neurofeedback Studio v2BCI / AvatarSame mapping studio on the v2 trainer shell.
Face TrainerBCI / ML / FacePlacement-agnostic 8-ch fEMG. Per-expression L2 + group-lasso, leave-one-rep-out balanced accuracy, channel-importance bars.
Face Trainer v2BCI / ML / Face3-2-1 recording (3× samples per press). 3 reps vs 6 in v1. Independent storage.

Aura VR (palm EMG + IMU)

These need Aura VR. Orientation comes from the IMU; EMG is for grip / pen-down — not wrist pose.

ExperienceTagDescription
Hand TrainerBCI / ML / sEMGFist, open, pinch, point, thumb-up. Face Trainer v2 protocol on 8-ch palm EMG. Wrist flexion is not a class.
Aura IMU LabIMU / DebugLSM6DS3 debugger: still-hold cal, gravity-compensated accel, ZUPT, translating 3D hand. 6-axis, no magnetometer — position drifts.
Aura Dataset LabsEMG / DatasetGuided 3-2-1 EMG + IMU with rest/hold labels. Optional MediaPipe Hand Landmarker autolabel. Export JSON or a ZIP of native-rate CSVs plus a 50 Hz label table. Optical is a vision estimate, not ground truth.
Aura HandwritingIMU / sEMG / GameEMG gates pen-down; yaw/pitch rates draw a unistroke. 1-NN Sakoe-Chiba DTW. EMG does not identify the glyph.
Hand of GodBCI / Game / sEMGOptional Aura fist → punch.

Lab & recording

ExperienceTagDescription
PiEEG Virtual LabLab / VRIn-world dashboard workstation.
Signal LabLearn / GameInteractive DSP curriculum on live EEG.
BioPose RecorderLab / PoseSplit bench: 33-point body stick + live bio traces on independent clocks. Confirmed frontal blinks write a blink mark on the take clock (useBlink, default Fp1/Fp2). Review holds last pose ≤150 ms. Export biopose-take:v1 JSON (points only; camera pixels are not stored). Pose is a vision estimate, not mocap. Blink marks are EOG detections, not eyelid tracking.
Aura Dataset LabsEMG / DatasetWrist Aura: guided 3-2-1 EMG + IMU labels, optional 21-point autolabel. Three independent clocks. Export aura-dataset:v1 JSON or native-rate ZIP. Optical is a vision estimate, not ground truth.

Integrations (need PiEEG Server)

These send commands or OSC and will not work in the 100% cloud tab. Use self-hosted PiEEG Server, or Local Bridge where OSC is involved.

ExperienceTagDescription
VRChat OSC BridgeVRChatBand powers over OSC UDP. Chatbox bubble + avatar float parameters.
VRChat OSC · Brain RegionsVRChatPer-region band powers (/avatar/parameters/EEG_{Region}_{Band}). Montage presets, sync-budget guide.
Webhook WizardAutomation60-second first webhook — IFTTT, Zapier, or any URL — with live EEG feedback.

Creating an Experience

Time to first playable: ~15 minutes. One .tsx file + one entry in the registry.

Cloud path: cloud/src/experiences/. Self-hosted path: dashboard/src/experiences/. Same contract.

Create your component

Create cloud/src/experiences/my-game/MyGame.tsx (or the dashboard equivalent):

import { useRef, useEffect } from "react";
import type { ExperienceProps } from "../registry";
import { useFocus, useRelax, useBlink } from "../../hooks/detectors";
 
export default function MyGame({ eegData, onExit }: ExperienceProps) {
  const { state: focus } = useFocus(eegData);
  const { state: relax } = useRelax(eegData);
  const { state: blink } = useBlink(eegData);
  const canvasRef = useRef<HTMLCanvasElement>(null);
 
  useEffect(() => {
    let raf: number;
    function loop() {
      const f = focus.current.focus;       // 0–1
      const r = relax.current.relaxation;  // 0–1
      const blinkCount = blink.current.count; // edge-detect vs last count
      // --- your game logic here ---
      raf = requestAnimationFrame(loop);
    }
    raf = requestAnimationFrame(loop);
    return () => cancelAnimationFrame(raf);
  }, []);
 
  return (
    <div style={{ position: "fixed", inset: 0, background: "#000" }}>
      <canvas ref={canvasRef} />
      <button onClick={onExit} style={{ position: "absolute", top: 12, left: 12 }}>
        ← Exit
      </button>
    </div>
  );
}

Register in the gallery

Add to cloud/src/experiences/registry.ts (and the matching dashboard file if you ship both):

const MyGameExperience = lazy(() => import("./my-game/MyGame"));
 
// Add to EXPERIENCES array:
{
  id: "my-game",
  name: "My Game",
  description: "One-sentence summary.",
  tag: "Focus",
  gradient: ["#ec4899", "#8b5cf6"],
  component: MyGameExperience,
  author: "Your Name",
}

Explain how it works

Required in the UI, not only in a README:

  • How it works overlay on first open (useState(true)).
  • Header How it works button to reopen.
  • Cover purpose, live loop, numbered protocol, and honest sensor limits.

The gallery picks it up automatically. Each experience is code-split — no impact on initial load.

ExperienceProps

FieldTypeDescription
eegDataEEGDataRing buffers with live samples (mutable refs — no re-renders)
yScalenumberCurrent amplitude scale
onExit() => voidReturn to the gallery
sendCommand?(cmd) => voidWebSocket command to pieeg-server
wsUrl?stringLive connection URL (e.g. Virtual Lab embeds the dashboard)
bridge?OscBridgeHandleShared Local Bridge handle for OSC. Never create a second bridge.

Set requiresServer: true or requiresAura: true on the registry entry so the gallery can badge the card.

Shared detector hooks (useBandPowers, useBlink, useFocus, useRelax) are documented in Detectors.


Advanced: Eye Track (EOG gaze estimation)

Eye Track bypasses the detector hooks and reads the ring buffer directly — custom signal processing, multi-phase calibration, and a trained model.

How it works

  1. EOG extraction — Horizontal gaze ≈ Fp2 − Fp1 (differential), Vertical ≈ (Fp1 + Fp2) / 2 (common-mode). The corneal-retinal dipole (~0.4–1.0 mV) shifts with gaze angle.
  2. 5-point calibration — Fixate center, up, down, left, right for 2.5 s each. Mean EOG features per target.
  3. Polynomial ridge regression — Features [1, h, v, h², h·v, v²] fit with λ = 0.01 (Gaussian elimination). Captures nonlinear response at extreme angles.
  4. Online adaptive learning — New (EOG, target) pairs ~4 Hz; model refits every 12 samples. Pause/resume learning.
  5. Persistence — Model + samples in localStorage; load on the next session.
  6. Algorithm editor — Edit the gaze function live in a code panel.

Key code patterns

// Direct ring-buffer read (no hooks)
function readEOGFeatures(eeg: EEGData, windowSamples: number) {
  const fp1 = eeg.buffers.current[0]; // Fp1
  const fp2 = eeg.buffers.current[1]; // Fp2
  // Slide backwards from writeIndex
  for (let i = 0; i < windowSamples; i++) {
    const idx = (writeIndex - windowSamples + i + bufferSize) % bufferSize;
    sumH += fp2[idx] - fp1[idx];       // horizontal
    sumV += (fp1[idx] + fp2[idx]) * 0.5; // vertical
  }
  return { hEOG: sumH / windowSamples, vEOG: sumV / windowSamples };
}
 
// Polynomial feature expansion
const feat = [1, h, v, h*h, h*v, v*v]; // 6 features
let x = 0;
for (let i = 0; i < feat.length; i++) x += feat[i] * model.weightsX[i];

Related