Contributing¶
Guidelines for contributing to BuckPow.
Welcome¶
BuckPow welcomes contributions from engineers, researchers, educators, and makers interested in energy observability for embedded systems.
Whether you improve documentation, firmware, hardware integrations, benchmarking methods, or the web platform, your contributions are appreciated.
Please open an issue before submitting large changes to discuss the proposed implementation.
Getting Started¶
Prerequisites¶
- Python 3.12+
- Node.js (for frontend tooling, optional)
- Git
Development Setup¶
# Clone the repository
git clone https://github.com/arifnd/buckpow.git
cd buckpow
# Install dependencies (creates .venv with uv)
uv sync
# Start development server
fastapi dev src/main.py --port 8000
Running Tests¶
Sending Dummy Data¶
Project Structure¶
buckpow/
├── src/
│ ├── __init__.py # App factory, lifespan, middleware
│ ├── main.py # Entrypoint
│ ├── config.py # Settings
│ ├── database.py # SQLAlchemy engine
│ ├── models.py # Shared Pydantic / ORM bases
│ ├── router.py # Router aggregation
│ ├── dependencies.py # FastAPI dependencies (re-exports)
│ ├── template_helpers.py # Jinja2 rendering helpers
│ ├── version.py # App version
│ ├── auth/ # Auth domain
│ ├── devices/ # Device domain
│ ├── sessions/ # Session domain
│ ├── measurements/ # Measurement domain
│ ├── projects/ # Project domain
│ ├── alerts/ # Alert domain
│ ├── audit/ # Audit log domain
│ ├── benchmark/ # Benchmark domain
│ ├── settings/ # Settings domain
│ ├── dashboard/ # Dashboard pages
│ ├── middleware/ # ASGI middleware
│ ├── utils/ # Utility functions
├── templates/ # Jinja2 templates (project root)
├── static/ # CSS, JS
├── firmware/ # Arduino sketches
├── migrations/ # Alembic migrations
├── tests/ # Test suite (by domain)
├── scripts/ # Helper scripts
├── tasks/ # Task management
├── nginx/ # Nginx config for Docker
├── requirements/ # pip-compatible requirements (mirror pyproject.toml)
├── pyproject.toml # Single source of truth for deps, ruff, pytest
├── mkdocs.yml # MkDocs config
├── alembic.ini # Alembic config
├── Dockerfile # Container build
├── docker-compose.yml # Production stack (PostgreSQL + Nginx)
├── docker-compose.cloud.yml # Cloud deployment stack
├── run.py # Alternative entrypoint
├── .pre-commit-config.yaml # Pre-commit hooks
├── .env.example # Environment template
├── .github/ # CI/CD workflows
└── LICENSE # MIT License
Development Workflow¶
1. Create a Branch¶
2. Make Changes¶
Follow the existing code style and patterns:
- Services — Business logic goes in
src/{domain}/service.py - Routes — API routes go in
src/{domain}/router.py, dashboard page routes insrc/dashboard/ - Models — SQLAlchemy models in
src/{domain}/models.py - Schemas — Pydantic schemas in
src/{domain}/schemas.py
3. Run Tests¶
4. Commit¶
Write clear, concise commit messages:
5. Push and Create PR¶
Then open a Pull Request on GitHub.
Code Style¶
Python¶
- Follow PEP 8
- Use type hints where appropriate
- Keep functions focused and concise
- Use
snake_casefor variables and functions - Use
PascalCasefor classes
Services¶
All business logic lives in the service layer:
class DeviceService:
def __init__(self, db: Session):
self.db = db
def get_all(self):
return self.db.query(Device).all()
def get_by_id(self, device_id: int):
return self.db.query(Device).filter(Device.id == device_id).first()
Routes¶
API routes use dependency injection:
@router.get('/devices')
def list_devices(
db: Session = Depends(get_db),
current_user: User = Depends(require_user),
):
devices = DeviceService(db).get_all()
return devices
Templates¶
- Extend
base.html - Use Tailwind CSS utility classes (compiled from
resources/css/app.css) - Use HTMX for interactivity and Alpine.js for dropdowns/sidebar state
- Use inline SVG icons (heroicons) — see
docs/developer-guide/frontend.md
Testing¶
Test Structure¶
Tests are in the tests/ directory, organized by domain:
tests/
├── auth/
├── devices/
├── sessions/
├── measurements/
├── projects/
├── alerts/
├── audit/
├── benchmark/
├── dashboard/
├── health/
├── settings/
└── conftest.py
Running Tests¶
# Run all tests
python -m pytest tests/ -v
# Run specific test file
python -m pytest tests/devices/test_devices_routes.py -v
# Run with coverage
python -m pytest tests/ --cov=src --cov-report=term-missing
Writing Tests¶
Follow existing patterns:
def test_create_device(client, auth_headers):
response = client.post(
'/api/v1/devices',
json={'device_id': 'test-01', 'name': 'Test Device'},
headers=auth_headers,
)
assert response.status_code == 201
data = response.json()
assert data['device_id'] == 'test-01'
Documentation¶
Documentation is built with MkDocs Material:
# Serve locally (MkDocs is installed via `uv sync`)
uv run mkdocs serve
# Build static site
uv run mkdocs build
Adding Pages¶
- Create markdown file in
docs/ - Add to
mkdocs.ymlnav - Use
##for sections,###for subsections
Reporting Issues¶
Bug Reports¶
Include:
- Steps to reproduce
- Expected behavior
- Actual behavior
- Environment (OS, Python version, browser)
Feature Requests¶
Include:
- Use case
- Proposed solution
- Alternatives considered
License¶
By contributing, you agree that your contributions will be licensed under the MIT License.