# Contributing to Dune Weaver Thanks for your interest in contributing to Dune Weaver! Whether it's a bug fix, a new feature, or improved docs, every contribution helps make kinetic sand tables more accessible. If you have questions or ideas, join the [#dev channel on Discord](https://discord.com/channels/864079106424832021/1329553521032560791) or browse the existing [Issues](https://github.com/tuanchris/dune-weaver/issues). ## Development Setup ### Prerequisites - Python 3.10+ - Node.js 18+ and npm - Git ### Clone and install ```bash git clone https://github.com/tuanchris/dune-weaver.git cd dune-weaver # Python dependencies (use nonrpi on a dev machine, full requirements.txt on a Raspberry Pi) pip install -r requirements-nonrpi.txt # Testing/dev extras pip install -r requirements-dev.txt # Frontend + root dependencies npm install cd frontend && npm install && cd .. ``` ### Start the dev server ```bash npm run dev ``` This runs **both** servers concurrently: | Service | URL | Notes | | -------- | ---------------------- | ---------------------------------- | | Frontend | `http://localhost:5173` | Vite dev server with hot reload | | Backend | `http://localhost:8080` | FastAPI (proxied by Vite in dev) | Open `http://localhost:5173` in your browser. Vite proxies all API and WebSocket requests to the backend automatically. ## Project Structure ``` dune-weaver/ ├── frontend/ # React 19 + TypeScript + Vite │ ├── src/ │ │ ├── pages/ # Route-level page components │ │ ├── components/ # Shared UI and feature components │ │ ├── hooks/ # Custom React hooks │ │ ├── lib/ # Utilities and API client │ │ └── contexts/ # React contexts (multi-table, etc.) │ └── package.json ├── modules/ # Backend modules │ ├── core/ # Pattern/playlist managers, state, scheduling │ ├── connection/ # Serial and WebSocket hardware communication │ ├── led/ # WLED integration │ └── mqtt/ # MQTT integration ├── patterns/ # .thr pattern files (theta-rho coordinates) ├── main.py # FastAPI application entry point └── package.json # Root scripts (dev, build, prepare) ``` ## Running Tests ### Backend (pytest) ```bash pytest tests/unit/ -v pytest tests/unit/ -v --cov # with coverage ``` ### Frontend (Vitest) ```bash cd frontend && npm test # single run cd frontend && npm run test:watch # watch mode cd frontend && npm run test:coverage ``` ### End-to-end (Playwright) ```bash cd frontend && npx playwright install chromium # first time only cd frontend && npm run test:e2e cd frontend && npm run test:e2e:ui # interactive UI mode ``` ### Hardware Integration Tests (pytest) Integration tests exercise real hardware — serial connections, homing, movement, and pattern execution. They are **skipped by default** and in CI. ```bash # Run all integration tests (hardware must be connected via USB) pytest tests/integration/ --run-hardware -v # Run a specific suite pytest tests/integration/test_hardware.py --run-hardware -v # Show live output (useful for watching motor activity) pytest tests/integration/ --run-hardware -v -s ``` | Test file | What it covers | Approx. duration | | --------- | -------------- | ---------------- | | `test_hardware.py` | Serial connection, homing, movement, pattern execution | ~5–10 min | | `test_playback_controls.py` | Pause, resume, stop, skip, speed control | ~5 min | | `test_playlist.py` | Playlist modes, clear patterns, state updates | ~5 min | > **Safety:** These tests physically move the table. Make sure the ball path is clear and the table is powered on before running them. ## Linting ### Python — Ruff ```bash ruff check . # check for issues ruff check --fix . # auto-fix what it can ``` ### Frontend — ESLint ```bash cd frontend && npm run lint ``` ### Pre-commit hook A pre-commit hook runs Ruff on staged Python files and Vitest on staged TypeScript files automatically. It's installed when you run `npm install` at the repo root (via the `prepare` script). You can also install it manually: ```bash cp scripts/pre-commit .git/hooks/pre-commit && chmod +x .git/hooks/pre-commit ``` ## Branch and Commit Conventions ### Branching Create branches from `main` using these prefixes: - `feature/` — new functionality (e.g., `feature/pattern-editor`) - `fix/` — bug fixes (e.g., `fix/playlist-reorder`) - `chore/` — maintenance, tooling, docs (e.g., `chore/update-deps`) ### Commit messages We follow [Conventional Commits](https://www.conventionalcommits.org/): ``` feat(ui): add dark mode toggle to settings page fix(backend): prevent crash when serial port disconnects chore: update Python dependencies ``` ## Adding API Endpoints When you add a new backend endpoint, you **must** also register its path in the Vite proxy so it works during development: 1. Add the route in `main.py` (or the appropriate module). 2. Open `frontend/vite.config.ts` and add the endpoint path to the `server.proxy` object: ```ts '/my_new_endpoint': 'http://localhost:8080', ``` 3. Restart the Vite dev server (`npm run dev`). > **Tip:** Endpoints under the `/api` prefix are already proxied by a single rule, so prefer using `/api/...` paths for new routes. ## Submitting a Pull Request 1. **Fork** the repository and clone your fork. 2. Create a branch from `main` (see [Branch and Commit Conventions](#branch-and-commit-conventions)). 3. Make sure all tests pass and linting is clean: ```bash ruff check . cd frontend && npm run lint && npm test && cd .. pytest tests/unit/ -v ``` 4. Push your branch to your fork and open a PR against `main` on the upstream repo. 5. Fill in a clear description of **what** changed and **why**. 6. CI will run backend tests, frontend tests, E2E tests, and Ruff lint automatically. ## Contributor License Agreement Because Dune Weaver is offered under a dual-license model (GPL-3.0 and a commercial license), all contributors must sign a Contributor License Agreement (CLA) before their pull requests can be merged. The CLA grants Dune Weaver Inc. the right to relicense your contribution under both licenses while you retain copyright of your work. We use [CLA Assistant](https://cla-assistant.io) to automate this. When you open your first pull request, the bot will prompt you to sign. For questions about the CLA, contact hello@duneweaver.com. Thanks for helping make Dune Weaver better!