My personal projects

Synchronised viewing, narrative role-playing and development from a phone: explore the use cases, technical choices and current stage of each project.

7 projectsProduction, development and launch

DEVELOPMENT METHOD

  1. 1. Scope

    With a conversational agent, I define the need, constraints and acceptance criteria. I give the coding agents the specifications, context and access to development and testing tools.

  2. 2. Develop

    Codex and Claude Code implement the tasks using the instructions, roles and skills I’ve prepared. I retain decisions and reviews.

  3. 3. Test

    The agents use the application, in a browser, on a device or through the CLI depending on the project. They observe results, diagnose discrepancies and retest after fixes.

  4. 4. Validate

    I personally test the application, check the acceptance criteria and give final approval.

Development and testing repeat until the acceptance criteria defined during scoping are met.

Project technologies

Projects built around my own use cases

Watching several streams together, playing with an AI game master or developing from a phone: these are the needs behind my projects.

7 projects3 in productionpersonal projects

Development tools:Claude CodeCodexCursor

See the full tech stack

Technologies used in my projects, grouped by area.

Frontend & UI
Angular 21Angular SignalsAngular SSGAstro 5Fuse.jshls.jsJavaScriptjsPDFNode.jsPostCSSPySide6 (Qt)React 18RxJSSCSSTailwind CSSTailwind CSS 4TypeScriptViteVite 8
Backend & APIs
AxumFastAPIJWT + bcryptOBS WebSocketPydantic v2PythonPython 3.12RustTyper + RichWebSocket
AI, voice & ML
ChatGPT (OpenAI)Claude (Anthropic)CUDAGemini (Google)Ollama / llama.cpp / vLLMOpenAIPyTorchQwen-TTS (Alibaba)Whisper (OpenAI)
Mobile & Cross-platform
AndroidFlutterLinux (X11 / Wayland)PipeWireRustDesk (fork)
Integration & DevOps
async SQLiteDockerEd25519FFmpegNDI SDKOpenCVSQLite
Other
CargoCloudflare PagesMCP (Model Context Protocol)Media3 / ExoPlayerMineflayerngx-translatepnpmPWA / Service WorkerSolid 1.9Tauri 2VitestWASMWeb Workers
Project 01

MultiPOV — synchronised multi-POV viewer for YouTube, Twitch & Kick

In production

Synchronised YouTube, Twitch and Kick viewpoints in one viewer. The web app is public; the Android app is tested on a device and shares the Rust media core.

  • Public web appwatchmultipov.app is live: shareable multi-POV sessions, a Solid + TypeScript PWA and a bilingual FR/EN interface.
  • Rust/WASM media coreA shared Rust engine carries sync, clock, offset, liveness and fallback rules; it is exposed as WASM on the web and compiled natively on Android.
  • Session encoded in the URLThe whole configuration lives in the /s/ path, with no account or session backend: a link you can drop in a comment or a DM.
  • Android app and on-device checksThe Tauri 2 app embeds the web control room with a shared Rust core, native Media3/ExoPlayer players and live sync instrumented for on-device checks.
RustWASMTauri 2AndroidMedia3 / ExoPlayerSolid 1.9TypeScriptVite 8Cloudflare Pageshls.jsWeb WorkersPWA / Service WorkerVitestCargopnpm

See it in practice

Multi-POV control room in production

Open the web app to create a shareable session and compare YouTube, Twitch and Kick viewpoints.

How I developed it

  1. Implement the change

    Modify the code for the scoped task and criteria.

  2. Test the WebView

    Drive the scenario via MCP/CDP on an identified build.

  3. Inspect native behaviour

    Read ADB logs when the diagnosis requires them.

  4. Fix the issue

    Address the identified cause and review the fix.

  5. Retest the scenario

    Repeat the checks suited to the scenario.

Native video rendering is checked separately from the DOM, using recordings and SyncBench measurements suited to the scenario.

Development tools:
CodexClaude CodeWebView MCP / CDPADBSyncBench

My role I prepare the phone workflow, instructions and skills, scenarios and criteria; I review fixes and testing tools before qualifying the build.

How it works

MultiPOV brings together YouTube, Twitch and Kick viewpoints for Discord sessions and events. In VOD, audio synchronisation measures delays; a clock and offsets then maintain alignment. The web app is live at watchmultipov.app (Solid, TypeScript, Vite, PWA and hls.js). The shared Rust engine runs as WASM on the web and natively in the Tauri 2 Android app. The Android app embeds the web viewer, Media3/ExoPlayer players and instrumented live synchronisation for on-device testing.

  • Web VOD sync: GCC-PHAT measures audio offsets, then a master clock and offsets keep POVs aligned after pause, seek or layout changes
  • Shared Rust core: common media engine exposed as WASM on the web and compiled natively on Android to centralise timing, offsets, provider capabilities, errors and fallbacks
  • YouTube, Twitch and Kick in one view, with a shared provider layer that handles platform differences
  • Account-free shareable sessions encoded in the URL path (/s/), portable in a comment or a DM
  • Configurable layout engine: auto grid, spotlight, theater and stacks; drag, resize and saved layouts (localStorage)
  • Immersive fullscreen mode: Fullscreen API on the whole stage, with landscape orientation lock and Wake Lock to keep the screen on during playback
  • Unified chat overlay (Twitch/YouTube/Kick): repositionable per-POV ephemeral overlay or side dock, messages merged with a per-platform colour dot and aligned to the timeline in VOD
  • Android native app: Tauri 2, embedded web control room, shared Rust core, native Media3/ExoPlayer players and live sync instrumented for on-device checks
  • Claude/Codex-assisted development: specifications, implementation, review and checks in production and on device, with scoped commits
Project 02

Aidventures — multiplayer narrative RPG with an AI game master

Production launch

An AI runs the story; the engine resolves rules and checks state changes. Players create and share their own worlds.

  • A game system built for the LLMOriginal mechanics (2d6+stat, Vows & Clocks, GM Moves) and a deterministic engine (HP, momentum, checkpoints): the model receives rule outcomes to build the narrative.
  • 19-invariant drift gate19 invariants check each LLM output; out-of-range values are clamped before the game state is updated.
  • Models selected by taskHaiku validates and extracts, Sonnet drives the narrative, Opus settles dilemmas — all switchable to Gemini, OpenAI or a local model.
  • A direction for the playerVows & Clocks trace a clear path, and on every turn the game offers three suggested actions — or lets you write a free-text response.
Python 3.12FastAPIWebSocketPydantic v2Claude (Anthropic)Gemini (Google)OpenAIOllama / llama.cpp / vLLMasync SQLiteViteDockerQwen-TTS (Alibaba)JWT + bcryptTyper + Rich

See it in practice

Production launch

Explore the narrative game: the AI runs the story and the engine checks rules and game state.

How I developed it

  1. Implement the engine

    Tackle the complex core before the interface.

  2. Run a scenario

    Exercise the game through the shared CLI.

  3. Diagnose the mismatch

    In audits, compare game state, raw LLM exchanges and drift checks.

  4. Fix the cause

    Update the engine or tools based on the diagnosis.

  5. Replay and verify

    Replay the scenario and check for regressions.

The CLI shares the web engine; replay rereads a trace without another LLM call. Raw exchanges are captured in instrumented audit scenarios.

Development tools:
CodexClaude CodeTyper / Rich CLIpytestJSONL traces / replay

My role I define game rules and development order, give agents engine access and prepare context; I review diagnoses, traces and testing criteria.

How it works

Multiplayer text-based TTRPG web platform where a generative AI acts as the game master. Original game system (2d6+stat, GM Moves, Trait Cards, Vows & Clocks, 5 pacing modes) secured by a 19-invariant 'drift gate' that validates every LLM output before applying state. Designed with Claude (Anthropic) as primary provider, the application also supports Gemini, OpenAI or a local model (Ollama, llama.cpp, vLLM via OpenAI-compatible API) through an adapter architecture. The community creates its own universes via an 11-step wizard in 4 phases (Fandom import, AI-assisted generation, voice profiles, lore by season/episode, translation) and publishes after moderation. Python 3.12 / FastAPI + WebSocket backend, asynchronous SQLite, Vite frontend, multi-container Qwen TTS pool and a free tier with virtual Flares currency.

  • Dice-first game system: the 2d6+stat roll is resolved by the engine BEFORE the LLM call (frozen roll handed over as established fact), deterministic Position & Effect, 5 pacing modes, Bold Move, HP/Momentum managed 100% by the engine (never by the LLM)
  • Objectives & clocks driven by the LLM: the Architect agent defines Vows (objectives from 0 to 10) and Clocks of 4, 6 or 8 segments — at setup or created dynamically mid-game — which the engine advances and aggregates deterministically
  • 19-invariant drift gate: each AI response validated before state patch (automatic clamp if drift detected on HP, momentum, pacing, position, effects)
  • Multi-provider via adapters: optimised for Claude (Sonnet for turns, Haiku for validation and extraction, Opus for moral dilemmas), also compatible with Gemini, OpenAI and local models (Ollama, llama.cpp, vLLM) via OpenAI-compatible API
  • Community universe creation: 11-step wizard in 4 phases with Fandom import (scraping → Haiku extraction → Sonnet builder), AI Generate buttons per step, WAV voice profiles per character/language, lore enrichment by season/episode and EN ↔ FR translation
  • Lifecycle & moderation: draft → pending → published → flagged → removed, user reports, DMCA/LCEN/DSA takedown procedure, email notifications to creators
  • Public landing + authenticated SPA: universe gallery served with HTTP 60s cache, auth redirect on /app, user accounts (JWT, bcrypt, OAuth, magic-link)
  • Free tier with virtual Flares currency: inscription credit, daily claim, rewarded ads (dynamic CSP per user, service worker exclusion)
  • Immersive audio with cloned voices: multi-container Docker Qwen TTS pool synthesising a cloned voice per character and per language (from a reference sample), with least-connections dispatch, per-user semaphore, LRU cache for voice profiles, intro music per universe and mood-categorised track catalog
  • Observability tools: JSONL traces, 0-API replay, narrative/mechanical audit, per-session cost tracker, HMAC-auth admin panel
Project 03

Nomad — Joy-Con + voice remote desktop for mobile Linux coding

Access on request

Use Claude Code or Codex on a remote Linux machine from an Android phone. Dictate prompts and control the mouse and shortcuts with a Joy-Con, without a physical keyboard.

  • Your phone as a mobile workstationThe Android displays the remote Linux machine; the Joy-Con held in the other hand drives the mouse with its stick and triggers CLI shortcuts through button combinations.
  • Voice dictation into the terminalFrom the Android, one tap starts dictation: local STT transcribes speech and injects it straight into Claude Code, Codex or another CLI on the Linux machine.
  • Linux-side orchestrationAs soon as a RustDesk client connects, display, audio and voice transcription are orchestrated automatically on the Linux side.
  • Ecosystem developed soloAdapted RustDesk fork, standalone Ed25519 licence server and bilingual distribution website.
RustAxumSQLiteEd25519RustDesk (fork)FlutterAstro 5Tailwind CSS 4Linux (X11 / Wayland)PipeWire

See it in practice

Request access to Nomad

Send a message through the form at nomadrust.dev to request access. The site explains the Android/Linux setup, dictation and Joy-Con controls.

How I developed it

  1. Scope the usage feedback

    Define the expected behaviour and task for the relevant role.

  2. Implement the adaptation

    Assign the Rust, Flutter or patch work to Claude Code.

  3. Check the component

    Run suitable tests; Rust tests and Clippy for Rust code.

  4. Fix and retest

    Address mismatches, then rerun the checks.

  5. Review the integration

    Check consistency across the Android/Linux journey.

Claude Code works on Rust, Flutter, patch and distribution adaptations around the RustDesk foundation.

Development tools:
Claude CodeSpecialist rolesRust testsClippyGitHub Actions

My role I define the Android/Linux journey, prepare context for each role and decide on RustDesk adaptations; I check integration and expected behaviours against my own usage.

How it works

Nomad lets you develop from an Android phone connected to a Linux workstation over RustDesk. The phone displays the remote desktop and captures dictation; a Nintendo Switch Joy-Con in the other hand controls the mouse and shortcuts through configurable profiles for Claude Code, OpenCode or Codex. A Linux daemon orchestrates display, audio and transcription when the mobile client connects. The project includes an adapted RustDesk fork (gamepad, voice call, branding), an Axum + SQLite + Ed25519 licence server with offline and expiry grace periods, and the bilingual nomadrust.dev website. Access is available on request through the website form.

  • Concept design: use an Android as a voice terminal to drive a remote Linux machine through RustDesk
  • Nintendo Switch Joy-Con integration: companion peripheral that frees the phone for dictation — mouse movement via analog stick and keyboard shortcuts triggered by button combinations
  • Configurable button profiles (Claude code, Open code, codex...) providing enough actions to operate these CLIs without a physical keyboard
  • Voice dictation to talk to the LLM: the Android app opens a voice call (RustDesk) to the daemon, which transcribes speech locally (Voxtype / Whisper large-v3-turbo) and injects the text as keystrokes (wtype on Wayland, xdotool on X11) straight into the target CLI (Claude Code, Codex…) — you speak, the text types itself into the terminal
  • Linux daemon automatically orchestrating screen, audio and transcription as soon as a mobile client connects
  • Custom RustDesk fork with dedicated patches (Joy-Con gamepad mapping, voice call, rebrand)
  • Standalone license server (Axum + SQLite + Ed25519) with offline and expiry grace periods
  • Bilingual EN/FR website (Astro 5 + Tailwind CSS 4) for distribution
  • Planned pricing: €5/month or €50 for a lifetime licence, without a free trial; V1.0 limited to Linux
Project 04

Bilingual portfolio — Angular 21 and static generation

Production

A French/English site pre-rendered with Angular, a PDF CV generated from portfolio data and an animated astronomical background.

  • Lighthouse 100/100Angular 21 with static generation. Reported Core Web Vitals: LCP < 2.5 s, INP < 200 ms, CLS < 0.1.
  • Daily astronomical selectionEach day, the pipeline selects a real astronomy image from NASA APOD, ESA/Hubble, ESA/Webb or ESO, then rejects flat, annotated or repeated visuals with dedicated filters.
  • Layered animated backgroundVoronoi fragments, sparkles, an energy field and shooting stars animate the background. Colours sampled from the image feed the surfaces, cards and accents.
  • Stellar easter eggA shooting star occasionally crosses the screen, with a colour sampled from bright zones and a subtle trail echoed through the fragments.
Angular 21TypeScriptTailwind CSS 4Angular SSGngx-translateRxJSAngular SignalsSCSSPostCSSjsPDF

See it in practice

The animated background, live

Compare the source image with the animated result and its integrated effects.

How it works

French/English portfolio built with Angular 21 and pre-rendered as static HTML. It combines canonical routes per language, SEO and social-sharing metadata, a responsive Tailwind CSS 4 layout and PDF CV generation. An astronomical background is selected daily; its layered animation has a static fallback based on device capabilities and preferences.

  • Angular 21 static generation: pre-rendered HTML for public routes
  • Core Web Vitals: LCP < 2.5s, INP < 200ms, CLS < 0.1
  • Lighthouse score 100/100 on performance, accessibility, best practices and SEO
  • Bilingual FR/EN switch through canonical routes: FR on /, EN on /en/*
  • Daily multi-source cosmic background: a script (images:fetch via GitHub Actions) selects a real image each day from NASA APOD, ESA Hubble, ESA Webb or ESO Picture of the Week; brightness and entropy filters, an OCR guard, host allowlist, denylist and anti-stagnation guard reject flat, annotated or repeated images, with a local-cache fallback
  • Layered background animation: around 300 Voronoi fragments modulated by an energy field, sparkles detected on bright zones and occasional shooting stars
  • Performance by design: the energy loop is capped at 30 FPS, fragment computation runs in a Web Worker, loading is deferred and animation is disabled for mobile or low-capability profiles
  • Glassmorphism design: translucent backdrop-filter surfaces (blur + saturate), per-card hue rotation and background sampling (photo-tint) for coherent highlights
  • Progressive CSS animations between pages and on scroll, with reduced-motion support
  • PDF CV generator: on-demand creation from portfolio data with jsPDF
  • Tailwind CSS 4 for responsive layouts and animations
  • WebP images and lazy loading to reduce load times
  • Dynamic metadata: Open Graph, Twitter Cards and JSON-LD
  • GitHub Actions CI/CD: automatic static prerender build and SFTP deployment on each push
  • Angular Signals, standalone components, static pre-rendering and HTTP caching
Project 05

Intelligent Podcast Analyzer — Generative AI and multi-engine transcription

In development

Turn hours of podcast audio into structured, searchable data while keeping the API budget in check.

  • Whisper anti-hallucinationDetecting and correcting transcription errors cuts API calls by 55% while preserving accuracy.
  • AI-extracted metadataGuests, topics and key moments are pulled out automatically with precise timestamps, ready for real-time fuzzy search.
PythonReact 18TypeScriptChatGPT (OpenAI)Whisper (OpenAI)PyTorchFFmpegCUDAViteTailwind CSSFuse.jsSQLite

See it in practice

Demo in development

Open the demo to search podcast transcripts and extracted metadata.

How it works

The analyser transcribes podcasts with Whisper, then uses ChatGPT to extract guests, topics and timestamped passages. A React interface provides search. Processing takes about 2 hours per hour of audio. This personal project has processed 20% of the Floodcast catalogue and 10% of TFTC.

  • Multi-engine transcription: local Whisper (GPU/CPU) + OpenAI API with automatic chunking of large files
  • Anti-hallucination system: Whisper error detection/correction (-55% API calls)
  • AI metadata extraction: guests, topics, key moments with precise timestamps
  • React 18 + TypeScript mobile-first interface with Fuse.js real-time fuzzy search
  • Automatic CUDA GPU acceleration (8-15x faster on RTX)
  • Integrated Spotify widget with timestamp-synchronized playback
  • CLI: 25+ commands with batch mode for bulk processing
  • Clean Architecture: decoupled services, factory pattern, dependency injection
Project 06

NDI Video Automation System — Real-time visual detection and OBS Studio control

In development

Automate a live stream control room in real time: the video itself triggers OBS scene changes.

  • Visual detection: around 100 msA CUDA-accelerated OpenCV pipeline spots patterns in configurable zones and drives OBS over WebSocket, hands-free.
  • Drag-and-drop zonesThe operator draws detection zones and maps them to OBS actions right in the UI, without touching the code.
PythonPySide6 (Qt)OpenCVNDI SDKOBS WebSocketCUDA
How it works

Automation application for my Call of Duty streams on TikTok. Visual patterns detected in NDI streams trigger OBS Studio actions, with latency of around 100 ms. The PySide6 interface configures detection zones; OpenCV processes images with CUDA GPU acceleration.

  • High-performance NDI video stream capture over IP network
  • Real-time visual pattern detection with OpenCV (CUDA-accelerated)
  • OBS Studio automation (scene changes, source control)
  • GUI with real-time preview
  • Customizable detection zones system via drag-and-drop
  • CUDA GPU support for high-performance image processing
Project 07

Autonomous Minecraft bot — learning how to give an LLM rules and context

Sandbox

By having an LLM play Minecraft for fun, I figured out how to give it rules and the right context — the foundation I reused in Aidventures and in how I develop with Claude Code.

  • LLM decides, bot executesThe bot only runs atomic actions and decides nothing; all strategy lives in the LLM. No hidden decision logic in the code.
  • Sensors, not ordersOn every block broken, raw context is returned — new blocks, water, void, hazards — and the LLM reasons over that data instead of fixed instructions.
  • Quality comes from the rulesDigging stairs, mining a vein without losing drops: the outcome depends on how well the rules are framed for the model.
Node.jsMineflayerMCP (Model Context Protocol)Claude (Anthropic)SQLiteJavaScript
How it works

Autonomous Minecraft bot driven by an LLM through the Model Context Protocol (MCP). A deliberately strict "atomic" architecture: the Mineflayer bot is only an executing arm (unit actions, no decisions), while the LLM reasons over raw data surfaced by sensors (discovered blocks, hazards, inventory, Y-levels) to decide what to mine, build or flee. Three MCP servers separate actions, Minecraft knowledge (recipes, Y-levels, tools) and a persistent spatial memory in SQLite. A learning project that taught me, through play, how to frame explicit rules and provide the right context to an LLM — a skill directly reused in the Aidventures drift gate and in the way I scope Claude Code-assisted development.

  • Atomic architecture: the bot runs unit actions (dig, place, equip) and makes no decisions — all reasoning is delegated to the LLM
  • Sensors returning raw data (surrounding blocks, water/void, hazards, optimal Y-levels, inventory) instead of orders, so the LLM reasons over the real context
  • Three separate MCP servers: actions, Minecraft knowledge (recipes, Y-levels, tools) and persistent spatial memory in SQLite (known staircases, houses and veins)
  • Explicit gameplay rules (vein mining order, scaffolding technique to avoid trapping yourself) showing that output quality depends on the quality of the rules given
  • Parallel agents (perception, safety, reasoning) that collect and analyse world state before each action