# Media Server - Development Guide ## Overview Standalone REST API server (FastAPI) for controlling system-wide media playback on Windows, Linux, macOS, and Android. ## Running the Server ### Manual Start ```bash python -m media_server.main ``` ### Auto-Start on Boot (Windows Task Scheduler) Run in **Administrator PowerShell** from the media-server directory: ```powershell .\media_server\service\install_task_windows.ps1 ``` To remove the scheduled task: ```powershell Unregister-ScheduledTask -TaskName "MediaServer" -Confirm:$false ``` ## Development Workflow ### Server Restart After Code Changes **CRITICAL:** When making changes to backend code (Python files, API routes, service logic), the media server MUST be restarted for changes to take effect. **When to restart:** - Changes to any Python files (`*.py`) in the media_server directory - Changes to API endpoints, routes, or request/response models - Changes to service logic, callbacks, or script execution - Changes to configuration handling or startup logic **When restart is NOT needed:** - Static file changes (`*.html`, `*.css`, `*.json`) - browser refresh is enough - README or documentation updates - Changes to install/service scripts (only affects new installations) ### Frontend Rebuild After JS Changes **CRITICAL:** The frontend is bundled via esbuild into `static/dist/app.bundle.js`. After modifying ANY JavaScript file in `media_server/static/js/`, you **MUST** run: ```bash npm run build ``` Raw JS file edits have **NO effect** until the bundle is rebuilt. After rebuilding, a browser hard-refresh (Ctrl+Shift+R) is sufficient — no server restart needed. **How to restart during development:** 1. Find the running server process: ```bash # Windows netstat -ano | findstr :8765 # Linux/macOS lsof -i :8765 ``` 2. Stop the server: ```bash # Windows taskkill //F //PID # Linux/macOS kill ``` 3. Start the server again: ```bash python -m media_server.main ``` **Best Practice:** Always restart the server immediately after committing backend changes to verify they work correctly before pushing. **CRITICAL** Always check acccessibility of WebUI after server restart to ensure that server has started without issues ## Configuration Copy `config.example.yaml` to `config.yaml` and customize. The API token is generated on first run and displayed in the console output. Default port: `8765` ## Internationalization (i18n) The Web UI supports multiple languages with translations stored in separate JSON files. ### Locale Files Translation files are located in: - `media_server/static/locales/en.json` - English (default) - `media_server/static/locales/ru.json` - Russian ### Maintaining Translations **IMPORTANT:** When adding or modifying user-facing text in the Web UI: 1. **Update all locale files** - Add or update the translation key in **both** `en.json` and `ru.json` 2. **Use consistent keys** - Follow the existing key naming pattern (e.g., `section.element`, `scripts.button.save`) 3. **Test both locales** - Verify translations appear correctly by switching between EN/RU ### Adding New Text When adding new UI elements: 1. Add the English text to `static/locales/en.json` 2. Add the Russian translation to `static/locales/ru.json` 3. In HTML: use `data-i18n="key.name"` for text content 4. In HTML: use `data-i18n-placeholder="key.name"` for input placeholders 5. In HTML: use `data-i18n-title="key.name"` for title attributes 6. In JavaScript: use `t('key.name')` or `t('key.name', {param: value})` for dynamic text ### Adding New Locales To add support for a new language: 1. Create `media_server/static/locales/{lang_code}.json` (copy from `en.json`) 2. Translate all strings to the new language 3. Add the language code to `supportedLocales` array in `index.html` ## Versioning **`pyproject.toml`** is the single source of truth for the version string. At runtime, `media_server/__init__.py` reads the version via `importlib.metadata.version()` — no manual syncing needed. Version flow: 1. `git tag v0.3.0` → CI reads the tag 2. Build scripts stamp `pyproject.toml` with the clean version via `sed` 3. `pip install` bakes the version into package metadata 4. `importlib.metadata.version("media-server")` reads it at runtime When bumping the version for a new release, only `pyproject.toml` needs to be updated. **Important:** After making any changes, always ask the user if the version needs to be incremented. ## CI/CD Gitea Actions workflow at `.gitea/workflows/test.yml` runs on every push/PR to `master`: 1. **Lint** — `ruff check media_server/` (rules: E, F, I, W) 2. **Test** — `pytest --tb=short -q` Release workflow at `.gitea/workflows/release.yml` triggers on `v*` tags: 1. **Create release** — Gitea release via REST API (detects pre-release from tag) 2. **Build Windows** — cross-builds on Linux using embedded Python + NSIS installer 3. **Upload assets** — portable ZIP + installer `.exe` attached to the release ### Releasing ```bash # Stable release git tag v1.0.0 && git push origin v1.0.0 # Pre-release git tag v1.1.0-alpha.1 && git push origin v1.1.0-alpha.1 ``` ### Installer The NSIS installer (`installer.nsi`) installs to `%LOCALAPPDATA%\Media Server` (no admin required) with optional: - **Desktop shortcut** - **Start with Windows** (Startup folder shortcut, runs hidden via VBS) Uninstall preserves `config.yaml` (user data). Reference: [gitea-python-ci-cd.md](https://git.dolgolyov-family.by/alexei.dolgolyov/claude-code-facts/src/branch/main/gitea-python-ci-cd.md) **IMPORTANT:** When modifying CI/CD workflows, `installer.nsi`, or build scripts (`build-dist-*.sh`), always fetch and consult the guide above first to ensure changes stay in sync with established patterns. ### Before Pushing Ensure CI will pass locally: ```bash ruff check media_server/ pytest --tb=short -q ``` ## Git Rules - **ALWAYS ask for user approval before committing and pushing changes.** - When pushing, always push to all remotes: `git push origin master && git push github master`