Skip to content

About

This is a fork for my personal use, due to the need for a few simple and specific features I wouldn't ask from the official developers.

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

 
 

Latest commit

 

History

586 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

FeedBack

A self-hosted web app for browsing, playing, and practicing interactive music notation — a scrolling note highway, standard notation, synced lyrics, and live note detection from your instrument, all running on hardware you own.

Charts come from importing Guitar Pro (GP3–GP8) or MusicXML, or from authoring in the Song Editor plugin. FeedBack stores them in its own open, hand-editable package format.

License: AGPL v3


Quick start

FeedBack ships as a Docker container.

git clone https://github.com/get-flashbacks/feedBack.git
cd feedBack
LIBRARY_PATH=/path/to/your/songs docker compose up -d

Open http://localhost:8000.

LIBRARY_PATH points at the folder holding your songs; it defaults to ./library if unset. Config and caches persist in a named feedBack-config volume, so they survive a container rebuild.

There is a separate docker-compose.nas.yml for NAS deployments, and build-proxmox-ct.sh for a Proxmox container.

Running without Docker

pip install -r requirements.txt
python main.py                          # 0.0.0.0:8000
HOST=127.0.0.1 PORT=8001 python main.py  # or pick your own

Configuration

Set these in docker-compose.yml or the environment:

Variable Purpose
DLC_DIR Song library folder inside the container (default /dlc)
CONFIG_DIR Persistent config + cache. /config inside the container; on bare metal it defaults to ~/.local/share/feedback
LOG_LEVEL DEBUG | INFO | WARNING | ERROR (default INFO)
LOG_FORMAT json | text (default text, coloured console)
APP_SOURCE_URL Overrides the Settings → About source link
APP_LICENSE_URL Overrides the licence link — set this explicitly if you host on a non-GitHub forge

Reverse proxies

FeedBack is meant to be reached directly — over the LAN, or through a VPN into your own network. The LAN-share relay (/ws/sync/…, used by Split Screen) caps how fast one address may open connections. No feedBack code reads a client-IP header: the cap is keyed on websocket.client.host, the client address the ASGI layer hands the app — the connecting proxy's address unless the server's proxy-header middleware rewrites it. So whether clients keep separate buckets comes down to the topology:

  • Proxy on the same host as feedBack — uvicorn applies X-Forwarded-For from an address it trusts, 127.0.0.1 by default (recent versions add ::1), so a proxy on IPv4 loopback gives every client its own bucket. Set FORWARDED_ALLOW_IPS if it connects over ::1 or from another address you trust, and make sure it overwrites the header rather than appending to it.
  • Proxy reaching feedBack from an address it doesn't trust — a tunnel or gateway on another machine, say. The header is ignored, so every client behind it shares one bucket and a join storm big enough to exhaust that shared budget is turned away before it reaches the room. That budget is sized for a full room's worth of near-simultaneous joins, which covers ordinary reconnect bursts; for a larger deployment, move the proxy onto the feedBack host or widen the cap (lib/routers/ws_sync.py, CONN_BURST).

Nothing else in feedBack distinguishes clients by address, so a proxy that doesn't preserve the client address costs the relay its per-client rate accounting — not its functionality.


Song formats

Loose folder — a directory of arrangement XML plus an audio file, with an optional manifest.json and album art. Played directly, no import step.

Sloppak — FeedBack's own package format, and the preferred one for new work. It exists interchangeably as a .sloppak zip (for distribution) or a .sloppak/ directory (for authoring), holding a YAML manifest, per-arrangement note data, audio stems, cover art, and syllable-level lyrics.

The format itself is specified outside this repo, in got-feedback/feedpak-spec — published there as feedpak; the same on-disk format this codebase still calls sloppak internally. The spec is the authority: a new manifest key is not part of the format until it lands there. CI enforces this, and there is no in-repo bypass. See docs/sloppak-spec.md for the local code map and docs/feedpak-spec-gate.md for how the gate works.


Plugins

Plugins are the main extension point, and most of FeedBack's features are built as one. A plugin lives in plugins/<id>/ with a plugin.json manifest and can contribute any mix of frontend screen, backend routes, and settings panel.

Name the directory to match the manifest's id (case-sensitive). That pairing is what marks a plugin as a bundled core one for duplicate resolution — it is not a discovery requirement, since the loader registers plugins by their manifest id whatever the folder is called. A plugin that genuinely won't load is usually missing plugin.json, has a manifest that fails to parse, or has an id that is absent, empty, or not a string.

A few of the things a plugin can do:

  • Replace the highway renderer — declare "type": "visualization" and export a window.feedBackViz_<id> factory. Works in the main player and per-panel under split screen.
  • Layer an overlay on top of whichever renderer is active — fretboard diagrams, chord labels, practice feedback.
  • Score playing and feed per-note judgments back so any renderer can light up the gems.
  • Register a mixer fader, keyboard shortcuts, a library source, or a detachable pane the user can pop into its own window.

Start with feedBack-plugin-template. The contracts are documented in CLAUDE.md, with deeper guides in docs/ — see plugin-v3-ui.md, plugin-styles.md, plugin-modules.md, plugin-panes.md, capability-recipes.md, plugin-host-compat.md (how to probe required vs optional host APIs so a missing feature degrades alone, never the plugin), and compatibility.md (which host commit each plugin feature needs, pinned by hash rather than version string).


Development

pip install -r requirements.txt -r requirements-test.txt
pytest                        # Python suite
npm run test:js               # JS unit tests
npm test                      # Playwright end-to-end
npm run lint                  # ESLint
bash scripts/build-tailwind.sh  # regenerate static/tailwind.min.css

Tailwind is served as a prebuilt stylesheet, never the Play CDN — the CDN's runtime JIT rescanned the DOM on the main thread and cost ~26% of frames. CI rebuilds and diffs the committed CSS, so run the build script and commit the result when you add new classes.

VERSION at the repo root is the single source of truth for the version, and is synced automatically when a desktop release is cut. GET /api/version serves it.

Library-scan cost is measured and documented in docs/scaling-envelope.md — per-song scan time, warm-rescan time, metadata-cache growth, and the per-worker memory footprint — so you can size a deployment (FEEDBACK_MAX_SCAN_WORKERS) instead of guessing.


Contributing

Please read CONTRIBUTING.md first. Two things to know up front:

  • Every commit needs a DCO sign-off (git commit -s).
  • Never push directly to main — branch, then open a PR.

Curated plugins should be AGPL-3.0 or AGPL-compatible (MIT, BSD, Apache-2.0).


License

AGPL-3.0-only. Contributions are inbound = outbound under the same terms.

About

This is a fork for my personal use, due to the need for a few simple and specific features I wouldn't ask from the official developers.

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages