Development Setup¶
Guide for setting up a local WireBuddy development environment.
Prerequisites¶
Required¶
- Python 3.11+ (3.13 recommended)
- Git
- pip and venv
System Dependencies¶
Clone Repository¶
Python Environment¶
Create Virtual Environment¶
Install Dependencies¶
# Core dependencies
pip install -r requirements.txt
# Development dependencies
pip install -r requirements-dev.txt
Configuration¶
Create .env File¶
Edit .env¶
# Required
WIREBUDDY_SECRET_KEY=dev-secret-key-change-me
# Development settings
LOG_LEVEL=DEBUG
PORT=8000
HOST=0.0.0.0
# Database (dev)
DATABASE_PATH=dev-data/wirebuddy.db
DATA_DIR=./dev-data
# Disable security for dev
SESSION_COOKIE_SECURE=false
RATELIMIT_ENABLED=false
SWAGGER_ENABLED=true
System Configuration¶
# Enable IP forwarding
sudo sysctl -w net.ipv4.ip_forward=1
sudo sysctl -w net.ipv6.conf.all.forwarding=1
# Enable conntrack accounting
sudo sysctl -w net.netfilter.nf_conntrack_acct=1
Database Setup¶
WireBuddy automatically creates database on first run:
This creates dev-data/wirebuddy.db with schema and default admin user.
Running WireBuddy¶
Development Server¶
Or with hot reload:
Access: http://localhost:8000
Run Tests¶
With coverage:
Run Linter¶
Format Code¶
IDE Setup¶
VS Code¶
Install recommended extensions:
{
"recommendations": [
"ms-python.python",
"ms-python.vscode-pylance",
"ms-python.black-formatter",
"charliermarsh.ruff",
"tamasfe.even-better-toml"
]
}
Settings:
{
"python.linting.enabled": true,
"python.linting.ruffEnabled": true,
"python.formatting.provider": "black",
"[python]": {
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.organizeImports": true
}
}
}
PyCharm¶
- Open project
- Configure Python interpreter (point to
.venv/bin/python) - Enable:
- Black formatter
- Ruff linting
- Type checking
Project Structure¶
wirebuddy/
├── app/ # Application code
│ ├── __init__.py
│ ├── main.py # FastAPI app entry point
│ ├── api/ # API endpoints
│ │ ├── auth.py
│ │ ├── wireguard.py
│ │ └── ...
│ ├── db/ # Database modules
│ │ ├── sqlite_*.py
│ │ └── ...
│ ├── dns/ # DNS resolver
│ ├── models/ # Pydantic models
│ ├── utils/ # Utilities
│ ├── static/ # CSS, JS, images
│ └── templates/ # Jinja2 templates
├── tests/ # Test suite
│ ├── test_api.py
│ ├── test_auth.py
│ └── ...
├── docs/ # MkDocs documentation
├── data/ # Runtime data (gitignored)
├── dev-data/ # Development data (gitignored)
├── requirements.txt # Production dependencies
├── requirements-dev.txt # Development dependencies
├── run.py # Development entry point
├── setup.conf # Configuration
├── VERSION # Version file
├── README.md
├── LICENSE
└── .gitignore
Development Workflow¶
Create Feature Branch¶
Make Changes¶
- Write code
- Add tests
- Run tests:
pytest - Format code:
black .+isort . - Lint code:
ruff check . - Type check:
mypy app/
Commit Changes¶
Use conventional commits:
feat:New featurefix:Bug fixdocs:Documentationstyle:Formattingrefactor:Code restructuringtest:Testschore:Maintenance
Push and Create PR¶
Create Pull Request on GitHub.
Debugging¶
VS Code Debugger¶
.vscode/launch.json:
{
"version": "0.2.0",
"configurations": [
{
"name": "Python: FastAPI",
"type": "python",
"request": "launch",
"module": "uvicorn",
"args": [
"app.main:app",
"--reload",
"--host", "0.0.0.0",
"--port", "8000"
],
"jinja": true,
"justMyCode": false
}
]
}
Python Debugger¶
Insert breakpoint:
Logging¶
import logging
logger = logging.getLogger(__name__)
logger.debug("Debug message")
logger.info("Info message")
logger.warning("Warning message")
logger.error("Error message")
Database Management¶
SQLite CLI¶
sqlite3 dev-data/wirebuddy.db
# Common commands
.schema # Show schema
.tables # List tables
SELECT * FROM users; # Query
.quit # Exit
Database Migrations¶
(If implementing Alembic in future)
# Create migration
alembic revision --autogenerate -m "Add new field"
# Apply migration
alembic upgrade head
# Rollback
alembic downgrade -1
Testing¶
Unit Tests¶
Integration Tests¶
End-to-End Tests¶
Test Coverage¶
Fixtures¶
import pytest
from app.main import app
from fastapi.testclient import TestClient
@pytest.fixture
def client():
return TestClient(app)
@pytest.fixture
def admin_user(client):
# Create and return admin user
pass
def test_login(client, admin_user):
response = client.post("/api/auth/login", json={
"username": "admin",
"password": "admin"
})
assert response.status_code == 200
Frontend Development¶
CSS¶
Located in app/static/css/:
wb-ui-system.css- Design system tokenscustom.css- Custom styles
JavaScript¶
Located in app/static/js/:
main.js- Main application logiccharts.js- Chart.js integration
Templates¶
Jinja2 templates in app/templates/:
{% extends "base.html" %}
{% block title %}Dashboard{% endblock %}
{% block content %}
<h1>Dashboard</h1>
<!-- content -->
{% endblock %}
Hot Reload¶
Templates auto-reload on save (development mode).
Documentation¶
Build Docs Locally¶
# Install docs dependencies
pip install -r requirements-docs.txt
# Serve docs
mkdocs serve
# Open http://127.0.0.1:8000
Add Documentation¶
- Create markdown file in
docs/ - Add to
mkdocs.ymlnavigation - Preview with
mkdocs serve - Commit changes
Building Docker Image¶
Local Build¶
Multi-Platform Build¶
Run Local Image¶
docker run -d \
--name wirebuddy-dev \
--network host \
--cap-add NET_ADMIN \
-e WIREBUDDY_SECRET_KEY=dev-key \
-v $(pwd)/data:/app/data \
wirebuddy:dev
Troubleshooting¶
Import Errors¶
# Ensure virtual environment is activated
source .venv/bin/activate
# Reinstall dependencies
pip install -r requirements.txt
Database Locked¶
Port Already in Use¶
Next Steps¶
- Architecture - System architecture
- Contributing - Contribution guidelines
- API Documentation - API reference