# π€ Contributing to Robotics MCP WebApp
Thank you for your interest in contributing to the Robotics MCP WebApp! This document provides guidelines and information for contributors.
## π Table of Contents
- [Code of Conduct](#code-of-conduct)
- [Getting Started](#getting-started)
- [Development Workflow](#development-workflow)
- [Coding Standards](#coding-standards)
- [Testing](#testing)
- [Documentation](#documentation)
- [Pull Request Process](#pull-request-process)
- [Issue Reporting](#issue-reporting)
- [Community](#community)
---
## π€ Code of Conduct
This project follows a code of conduct to ensure a welcoming environment for all contributors. By participating, you agree to:
- **Be respectful** and inclusive in all interactions
- **Be collaborative** and help others when possible
- **Be patient** with new contributors
- **Be constructive** in feedback and criticism
- **Follow our community guidelines**
### Unacceptable Behavior
- Harassment, discrimination, or offensive comments
- Personal attacks or trolling
- Publishing others' private information
- Any illegal or unethical behavior
Violations should be reported to [robotics@sandraschi.dev](mailto:robotics@sandraschi.dev).
---
## π Getting Started
### Prerequisites
Before you begin, ensure you have:
- **Node.js 18+** and **npm** or **yarn**
- **Python 3.10+** and **pip**
- **Git** for version control
- A modern web browser (Chrome, Firefox, Safari, Edge)
- Basic knowledge of React, TypeScript, and Python
### Environment Setup
1. **Fork and Clone**
```bash
git clone https://github.com/YOUR_USERNAME/robotics-webapp.git
cd robotics-webapp
```
2. **Frontend Setup**
```bash
cd frontend
npm install
cp .env.example .env.local # Configure environment variables
npm run dev
```
3. **Backend Setup**
```bash
cd backend
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
pip install -r requirements.txt
cp .env.example .env # Configure environment variables
python main.py
```
4. **Verify Setup**
- Frontend: http://localhost:3000
- Backend: http://localhost:8354
- API Docs: http://localhost:8354/docs
### Development Tools
We recommend using these tools for development:
- **VS Code** with extensions:
- TypeScript and JavaScript Language Features
- Python
- Prettier
- ESLint
- **GitHub Desktop** or **GitKraken** for Git management
- **Postman** or **Insomnia** for API testing
---
## π Development Workflow
### Branching Strategy
We use a simplified Git Flow:
```bash
# Main branches
main # Production-ready code
develop # Latest development changes
# Feature branches (from develop)
feature/xyz # New features
bugfix/xyz # Bug fixes
hotfix/xyz # Critical production fixes
docs/xyz # Documentation updates
```
### Workflow Steps
1. **Choose an Issue**
- Check [GitHub Issues](https://github.com/sandraschi/robotics-webapp/issues)
- Comment to indicate you're working on it
- Ask questions if the requirements are unclear
2. **Create a Branch**
```bash
git checkout develop
git pull origin develop
git checkout -b feature/your-feature-name
```
3. **Make Changes**
- Write clean, well-documented code
- Follow our coding standards
- Add tests for new functionality
- Update documentation as needed
4. **Test Your Changes**
```bash
# Frontend tests
cd frontend
npm run test
npm run lint
# Backend tests
cd backend
python -m pytest
# Integration tests
npm run test:e2e
```
5. **Commit Your Changes**
```bash
git add .
git commit -m "feat: add new robot control feature
- Add joystick control interface
- Implement velocity mapping
- Add safety limits
Closes #123"
```
6. **Push and Create PR**
```bash
git push origin feature/your-feature-name
```
Then create a Pull Request on GitHub.
### Commit Message Format
We follow [Conventional Commits](https://conventionalcommits.org/):
```bash
type(scope): description
[optional body]
[optional footer]
```
**Types:**
- `feat`: New features
- `fix`: Bug fixes
- `docs`: Documentation
- `style`: Code style changes
- `refactor`: Code refactoring
- `test`: Testing
- `chore`: Maintenance
**Examples:**
```bash
feat(robot-control): add emergency stop functionality
fix(sensor-dashboard): resolve chart rendering issue
docs(api): update WebSocket endpoint documentation
```
---
## π» Coding Standards
### Frontend (TypeScript/React)
#### File Structure
```
src/
βββ app/ # Next.js App Router
β βββ (auth)/ # Route groups
β βββ api/ # API routes
β βββ globals.css # Global styles
βββ components/ # React components
β βββ ui/ # Reusable UI components
β βββ layout/ # Layout components
β βββ features/ # Feature-specific components
βββ lib/ # Utilities and configurations
β βββ utils.ts # General utilities
β βββ api.ts # API client
β βββ validations.ts # Form validations
βββ types/ # TypeScript type definitions
```
#### Code Style
- **TypeScript**: Strict mode enabled
- **ESLint**: Airbnb config with TypeScript support
- **Prettier**: Consistent code formatting
- **Component Naming**: PascalCase for components, camelCase for utilities
- **File Naming**: kebab-case for files, PascalCase for components
#### React Best Practices
```typescript
// β
Good: Proper TypeScript usage
interface RobotControlProps {
robotId: string;
onCommand: (command: RobotCommand) => void;
}
export function RobotControl({ robotId, onCommand }: RobotControlProps) {
const [velocity, setVelocity] = useState({ linear: 0, angular: 0 });
const handleMove = useCallback(() => {
onCommand({
type: 'move',
robotId,
velocity
});
}, [robotId, velocity, onCommand]);
return (
<div>
{/* Component JSX */}
</div>
);
}
// β Bad: Missing types, poor practices
export function RobotControl(props) {
const [vel, setVel] = useState({});
return <div onClick={() => props.onMove(vel)} />;
}
```
### Backend (Python/FastAPI)
#### Code Style
- **Black**: Code formatting
- **isort**: Import sorting
- **mypy**: Type checking
- **flake8**: Linting
- **PEP 8**: Python style guide
#### FastAPI Best Practices
```python
from fastapi import APIRouter, HTTPException, Depends
from pydantic import BaseModel, Field
from typing import Optional, List
import logging
router = APIRouter()
logger = logging.getLogger(__name__)
class RobotCommand(BaseModel):
robot_id: str = Field(..., description="Robot identifier")
command: str = Field(..., description="Command to execute")
parameters: Optional[dict] = Field(default={}, description="Command parameters")
@router.post("/robots/{robot_id}/command")
async def execute_robot_command(
robot_id: str,
command: RobotCommand,
current_user = Depends(get_current_user)
) -> dict:
"""
Execute command on specified robot.
Args:
robot_id: Target robot identifier
command: Command details
current_user: Authenticated user
Returns:
Command execution result
"""
try:
# Validate robot access
if not await check_robot_access(current_user.id, robot_id):
raise HTTPException(status_code=403, detail="Access denied")
# Execute command
result = await robot_service.execute_command(robot_id, command)
logger.info(f"Command executed: {robot_id} - {command.command}")
return {"status": "success", "result": result}
except RobotNotFoundError:
raise HTTPException(status_code=404, detail="Robot not found")
except RobotBusyError:
raise HTTPException(status_code=409, detail="Robot is busy")
except Exception as e:
logger.error(f"Command execution failed: {e}")
raise HTTPException(status_code=500, detail="Internal server error")
```
---
## π§ͺ Testing
### Testing Strategy
We use a comprehensive testing approach:
- **Unit Tests**: Individual functions and components
- **Integration Tests**: Component interactions
- **End-to-End Tests**: Complete user workflows
- **Performance Tests**: Load and stress testing
### Frontend Testing
```bash
# Run unit tests
npm test
# Run tests with coverage
npm run test:coverage
# Run e2e tests
npm run test:e2e
# Run specific test file
npm test -- RobotControl.test.tsx
```
**Testing Libraries:**
- **Jest**: Test runner and assertion library
- **React Testing Library**: React component testing
- **Playwright**: End-to-end testing
- **Vitest**: Fast unit testing
### Backend Testing
```bash
# Run all tests
python -m pytest
# Run with coverage
python -m pytest --cov=app --cov-report=html
# Run specific tests
python -m pytest tests/test_robot_control.py
# Run async tests
python -m pytest tests/ -k "async"
```
**Testing Libraries:**
- **pytest**: Test framework
- **pytest-asyncio**: Async test support
- **pytest-cov**: Coverage reporting
- **httpx**: HTTP client testing
### Test Structure
```
tests/
βββ unit/ # Unit tests
β βββ test_robot_control.py
β βββ test_sensor_data.py
βββ integration/ # Integration tests
β βββ test_websocket.py
β βββ test_api_endpoints.py
βββ e2e/ # End-to-end tests
β βββ robot_control.spec.ts
β βββ sensor_dashboard.spec.ts
βββ fixtures/ # Test data and mocks
βββ robot_data.json
βββ sensor_readings.json
```
### Writing Tests
**Frontend Component Test:**
```typescript
import { render, screen, fireEvent, waitFor } from '@testing-library/react'
import { RobotControl } from '@/components/RobotControl'
describe('RobotControl', () => {
const mockOnCommand = jest.fn()
beforeEach(() => {
mockOnCommand.mockClear()
})
it('renders control interface', () => {
render(<RobotControl robotId="test-robot" onCommand={mockOnCommand} />)
expect(screen.getByText('Robot Control')).toBeInTheDocument()
expect(screen.getByRole('button', { name: /forward/i })).toBeInTheDocument()
})
it('sends move command on button click', async () => {
render(<RobotControl robotId="test-robot" onCommand={mockOnCommand} />)
const forwardButton = screen.getByRole('button', { name: /forward/i })
fireEvent.click(forwardButton)
await waitFor(() => {
expect(mockOnCommand).toHaveBeenCalledWith({
robotId: 'test-robot',
command: 'move',
parameters: { linear: 0.5, angular: 0 }
})
})
})
})
```
**Backend API Test:**
```python
import pytest
from httpx import AsyncClient
from fastapi import FastAPI
@pytest.mark.asyncio
async def test_robot_command_endpoint(client: AsyncClient, test_robot):
"""Test robot command execution endpoint."""
command_data = {
"robot_id": test_robot.id,
"command": "move",
"parameters": {
"linear": 0.5,
"angular": 0.0
}
}
response = await client.post(
f"/api/robots/{test_robot.id}/command",
json=command_data
)
assert response.status_code == 200
data = response.json()
assert data["status"] == "success"
assert "execution_id" in data
@pytest.mark.asyncio
async def test_invalid_robot_command(client: AsyncClient):
"""Test error handling for invalid commands."""
response = await client.post(
"/api/robots/invalid-robot/command",
json={"command": "invalid"}
)
assert response.status_code == 404
data = response.json()
assert "not found" in data["detail"].lower()
```
---
## π Documentation
### Documentation Standards
All code must be well-documented:
**TypeScript/React:**
```typescript
interface RobotControlProps {
/** Unique identifier for the robot */
robotId: string;
/** Callback fired when a command is executed */
onCommand: (command: RobotCommand) => void;
/** Whether the robot is currently online */
isOnline?: boolean;
}
/**
* RobotControl provides a user interface for controlling virtual robots.
*
* Features:
* - Real-time velocity control with sliders
* - Emergency stop functionality
* - Keyboard shortcuts (WASD)
* - Visual feedback for command execution
*
* @example
* ```tsx
* <RobotControl
* robotId="vbot_scout_mini"
* onCommand={(cmd) => console.log('Command:', cmd)}
* isOnline={true}
* />
* ```
*/
export function RobotControl({ robotId, onCommand, isOnline }: RobotControlProps) {
// Component implementation
}
```
**Python/FastAPI:**
```python
from typing import Optional, Dict, Any
async def execute_robot_command(
robot_id: str,
command: str,
parameters: Optional[Dict[str, Any]] = None,
user_id: Optional[str] = None
) -> Dict[str, Any]:
"""
Execute a command on the specified robot.
This function handles the complete command execution workflow including:
- Access control validation
- Command parameter validation
- Robot state updates
- Event logging and monitoring
Args:
robot_id: Unique identifier of the target robot
command: Command to execute (move, stop, reset, etc.)
parameters: Optional command parameters
user_id: ID of the user executing the command
Returns:
Dictionary containing execution results and metadata
Raises:
RobotNotFoundError: If the specified robot doesn't exist
AccessDeniedError: If user lacks permission to control robot
CommandFailedError: If command execution fails
Example:
>>> result = await execute_robot_command(
... robot_id="vbot_scout_mini",
... command="move",
... parameters={"linear": 0.5, "angular": 0.0}
... )
>>> print(result["status"])
"success"
"""
# Implementation
```
### Documentation Updates
When making changes:
1. **Update inline documentation** for modified functions
2. **Add JSDoc/TSDoc comments** for new components
3. **Update README** for new features or breaking changes
4. **Update API documentation** for endpoint changes
5. **Add migration guides** for breaking changes
---
## π Pull Request Process
### PR Checklist
Before submitting a PR, ensure:
- [ ] Code follows our coding standards
- [ ] All tests pass (`npm test` and `pytest`)
- [ ] Documentation is updated
- [ ] Commit messages follow conventional format
- [ ] No linting errors (`npm run lint`)
- [ ] Security review completed for sensitive changes
- [ ] Performance impact assessed
### PR Template
Use this template when creating pull requests:
```markdown
## Description
Brief description of the changes made.
## Type of Change
- [ ] π Bug fix (non-breaking change)
- [ ] β¨ New feature (non-breaking change)
- [ ] π₯ Breaking change (fix or feature)
- [ ] π Documentation update
- [ ] π Refactor (no functional changes)
## Testing
- [ ] Unit tests added/updated
- [ ] Integration tests added/updated
- [ ] E2E tests added/updated
- [ ] Manual testing completed
## Screenshots (if applicable)
Add screenshots of UI changes.
## Additional Notes
Any additional context or considerations.
```
### Review Process
1. **Automated Checks**: CI/CD pipeline runs automatically
2. **Peer Review**: At least one maintainer reviews the code
3. **Testing**: Reviewer verifies functionality
4. **Approval**: PR approved and merged by maintainer
### PR Size Guidelines
- **Small PRs**: < 200 lines - Quick review, preferred
- **Medium PRs**: 200-500 lines - May need detailed review
- **Large PRs**: > 500 lines - Should be broken down or get extra attention
---
## π Issue Reporting
### Bug Reports
When reporting bugs, please include:
```markdown
**Describe the Bug**
Clear, concise description of the issue.
**To Reproduce**
Steps to reproduce:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected Behavior**
What should happen.
**Screenshots**
If applicable, add screenshots.
**Environment:**
- OS: [e.g., Windows 10]
- Browser: [e.g., Chrome 91]
- Version: [e.g., v1.0.0]
**Additional Context**
Any other information.
```
### Feature Requests
For new features, please provide:
```markdown
**Feature Summary**
Brief description of the feature.
**Problem Statement**
What problem does this solve?
**Proposed Solution**
Detailed description of the solution.
**Alternatives Considered**
Other solutions you've considered.
**Additional Context**
Mockups, examples, or additional information.
```
---
## π Community
### Communication Channels
- **GitHub Issues**: Bug reports and feature requests
- **GitHub Discussions**: General discussion and questions
- **Discord**: Real-time chat and community support
- **Twitter**: Announcements and updates
### Community Guidelines
- **Be welcoming** to new contributors
- **Help others** when you can
- **Share knowledge** and best practices
- **Respect different opinions** and approaches
- **Keep discussions on-topic** and professional
### Recognition
Contributors are recognized through:
- **GitHub Contributors**: Listed in repository contributors
- **Changelog Credits**: Mentioned in release notes
- **Community Spotlight**: Featured in community updates
- **Maintainer Status**: Top contributors can become maintainers
---
## π License
By contributing to this project, you agree that your contributions will be licensed under the same license as the project (MIT License).
---
Thank you for contributing to Robotics MCP WebApp! Your contributions help make robotics more accessible and powerful for everyone. ππ€