Thank you for your interest in contributing to ResCanvas! This document provides guidelines and instructions for contributing to the project.
- How to Contribute
- Development Setup
- Project Structure
- Coding Standards
- Testing Requirements
- API Development Guidelines
- Pull Request Process
- Commit Message Guidelines
- Getting Help
ResCanvas is committed to providing a welcoming and inclusive environment for all contributors. We expect all participants to:
- Be respectful and considerate in communication
- Welcome diverse perspectives and experiences
- Accept constructive criticism gracefully
- Focus on what is best for the community
- Show empathy towards other community members
Unacceptable behavior includes harassment, trolling, personal attacks, or any conduct that creates an intimidating or hostile environment.
There are many ways to contribute to ResCanvas:
- Check existing issues to avoid duplicates
- Use the bug report template
- Include detailed steps to reproduce
- Provide system information (OS, browser, Node/Python versions)
- Include relevant error messages and logs
- Check existing feature requests
- Clearly describe the feature and its use case
- Explain why this feature would benefit users
- Consider backward compatibility and API versioning
- Fix bugs or implement features from the issue tracker
- Improve documentation
- Add or improve tests
- Optimize performance
- Enhance security
- Fix typos or unclear explanations
- Add examples and tutorials
- Improve API documentation
- Translate documentation
- Node.js 14+ and npm
- Python 3.8+
- MongoDB (local or Atlas cluster)
- Redis 6+
- Git
- Fork and Clone
git clone https://github.com/YOUR_USERNAME/ResCanvas.git
cd ResCanvas- Backend Setup
cd backend
# Create virtual environment
python3 -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
# Install dependencies
pip install -r requirements.txt
# Generate keys for ResilientDB
python gen_keys.py
# Create .env file
cat > .env << EOF
MONGO_ATLAS_URI=mongodb://localhost:27017/rescanvas_dev
SIGNER_PUBLIC_KEY=<from gen_keys.py>
SIGNER_PRIVATE_KEY=<from gen_keys.py>
RESILIENTDB_BASE_URI=https://crow.resilientdb.com
RESILIENTDB_GRAPHQL_URI=https://cloud.resilientdb.com/graphql
JWT_SECRET=your-dev-secret-key
EOF
# Start backend
python app.py- Frontend Setup
cd frontend
# Install dependencies
npm install
# Start development server
npm start- Redis Setup
# Install Redis (Ubuntu/Debian)
sudo apt install redis-server
# Start Redis
sudo systemctl start redis
# Verify Redis is running
redis-cli ping # Should return PONG- Sync Service Setup (Optional for full functionality)
cd backend/incubator-resilientdb-resilient-python-cache
# Install dependencies
pip install resilient-python-cache
# Create .env
cat > .env << EOF
MONGO_URL=mongodb://localhost:27017/
MONGO_DB=canvasCache
MONGO_COLLECTION=strokes
EOF
# Run sync service
python example.pyResCanvas/
├── backend/
│ ├── app.py # Flask application entry point
│ ├── config.py # Configuration and environment variables
│ ├── routes/ # REST API route handlers
│ │ ├── auth.py # Authentication endpoints
│ │ ├── rooms.py # Room management endpoints
│ │ ├── submit_room_line.py # Stroke submission logic
│ │ └── ...
│ ├── api_v1/ # Versioned API layer (v1)
│ │ ├── __init__.py # API v1 blueprint factory
│ │ ├── auth.py # v1 auth endpoints
│ │ ├── rooms.py # v1 room endpoints
│ │ └── ...
│ ├── middleware/ # Authentication middleware
│ ├── services/ # Business logic and utilities
│ │ ├── db.py # Database connections
│ │ ├── graphql_service.py # ResilientDB GraphQL client
│ │ ├── socketio_service.py # Socket.IO helpers
│ │ └── ...
│ └── tests/ # Backend test suites
│ ├── test_api_v1.py # API v1 endpoint tests
│ └── ...
├── frontend/
│ ├── src/
│ │ ├── components/ # React components
│ │ ├── pages/ # Page components
│ │ ├── api/ # API client wrappers
│ │ ├── services/ # Frontend services
│ │ └── utils/ # Utility functions
│ └── tests/ # Frontend test suites
├── sdk/
│ └── javascript/ # Official JavaScript SDK
│ ├── src/ # SDK source code
│ └── tests/ # SDK tests
└── docs/ # Documentation
- Style: Follow PEP 8
- Formatting: Use 4 spaces for indentation
- Imports: Group stdlib, third-party, local imports
- Docstrings: Use triple quotes for module/function docs
- Type Hints: Use when helpful for clarity
from typing import Dict, List, Optional
def create_room(name: str, room_type: str = "public") -> Dict:
"""
Create a new collaborative drawing room.
Args:
name: The room name
room_type: Room visibility (public, private, secure)
Returns:
Dict containing room details and ID
"""
pass- Style: Use ESLint configuration in project
- Formatting: 2 spaces for indentation
- ES6+: Use modern JavaScript features (arrow functions, async/await, destructuring)
- Components: Use functional components with hooks
- Naming: camelCase for variables/functions, PascalCase for components
// Good
const MyComponent = ({ userId, onUpdate }) => {
const [data, setData] = useState(null);
useEffect(() => {
fetchData();
}, [userId]);
const handleClick = async () => {
await onUpdate(data);
};
return <div onClick={handleClick}>{data}</div>;
};- Keep functions small and focused (single responsibility)
- Write self-documenting code (clear variable names)
- Add comments for complex logic (explain "why", not "what")
- Handle errors gracefully (try/catch, proper error messages)
- Validate input (never trust client data)
- Log important operations (use appropriate log levels)
All contributions must include appropriate tests.
cd backend
# Run all tests
pytest
# Run specific test file
pytest tests/test_api_v1.py
# Run with coverage
pytest --cov=. --cov-report=html
# Run specific test
pytest tests/test_api_v1.py::TestAPIv1Auth::test_login_successTest Guidelines:
- One test file per module or feature area
- Use fixtures for common setup (see
conftest_v1.py) - Test success cases, error cases, and edge cases
- Mock external services (ResilientDB, MongoDB when appropriate)
- Clean up test data in teardown
class TestMyFeature:
def test_success_case(self, client, auth_token):
"""Test the happy path"""
response = client.post('/api/v1/endpoint',
headers={"Authorization": f"Bearer {auth_token}"},
json={"data": "value"})
assert response.status_code == 200
def test_validation_error(self, client, auth_token):
"""Test input validation"""
response = client.post('/api/v1/endpoint',
headers={"Authorization": f"Bearer {auth_token}"},
json={}) # Missing required field
assert response.status_code == 400cd frontend
# Run all tests
npm test
# Run with coverage
npm test -- --coverage
# Run specific test file
npm test -- Canvas.test.js- Test complete workflows (register → login → create room → add stroke)
- Test cross-component interactions
- Test real-time Socket.IO events
- Use test databases, not production data
ResCanvas uses URL-based versioning for the public API:
- Current version:
/api/v1/* - Legacy endpoints: Continue to work without version prefix
- Future versions: Will be
/api/v2/*, etc.
- Implement in routes/ first (core functionality)
- Wrap in api_v1/ (versioned API layer)
- Write comprehensive tests
- Update documentation (README.md, SDK docs)
- Update SDK client (if applicable)
Example structure:
# backend/api_v1/my_feature.py
from flask import Blueprint, request, jsonify
from middleware.auth import require_auth
from routes.my_feature import do_something
my_feature_bp = Blueprint('api_v1_my_feature', __name__)
@my_feature_bp.route('/my-endpoint', methods=['POST'])
@require_auth
def v1_my_endpoint():
"""v1 wrapper for my_endpoint functionality"""
return do_something(request)- Never break existing endpoints without major version bump
- Deprecate gracefully (announce, provide migration path)
- Add optional parameters (required params → breaking change)
- Return additional fields (OK, but document)
- Change field types/formats (breaking change)
- All protected endpoints MUST use
@require_authdecorator - Check room access with
@require_room_accesswhen applicable - Return proper HTTP status codes:
401 Unauthorized— Missing/invalid token403 Forbidden— Valid token but insufficient permissions404 Not Found— Resource doesn't exist or user has no access
Return consistent error format:
{
"error": "Brief error message",
"details": "More detailed explanation (optional)",
"code": "ERROR_CODE" // Optional error code
}HTTP Status Codes:
200 OK— Success201 Created— Resource created204 No Content— Success with no response body400 Bad Request— Invalid input401 Unauthorized— Authentication required403 Forbidden— Insufficient permissions404 Not Found— Resource not found409 Conflict— Resource already exists500 Internal Server Error— Server error
-
Create a feature branch from
maingit checkout -b feature/my-feature # or git checkout -b fix/bug-description -
Make your changes
- Follow coding standards
- Add tests
- Update documentation
-
Test thoroughly
# Backend tests cd backend && pytest # Frontend tests cd frontend && npm test
-
Commit changes (see commit guidelines below)
-
Push to your fork
git push origin feature/my-feature
- Go to the original repository
- Click "New Pull Request"
- Select your fork and branch
- Fill out the PR template:
- Title: Clear, concise description
- Description: What changed and why
- Related Issues: Link to related issues
- Testing: How you tested the changes
- Screenshots: For UI changes
- Maintainers will review your PR
- Address feedback and requested changes
- Update your branch if needed
- Once approved, a maintainer will merge
- Code follows project coding standards
- Tests added/updated and passing
- Documentation updated (if needed)
- No breaking changes (or clearly documented)
- Commits follow commit message guidelines
- PR description is clear and complete
Use conventional commit format:
<type>(<scope>): <subject>
<body>
<footer>
- feat: New feature
- fix: Bug fix
- docs: Documentation changes
- style: Code style changes (formatting, no logic change)
- refactor: Code refactoring
- test: Adding or updating tests
- chore: Maintenance tasks (dependencies, build config)
- perf: Performance improvements
feat(api): add user search endpoint to v1 API
Implement /api/v1/users/search endpoint to allow searching
users by username. Includes fuzzy matching and pagination.
Closes #123
fix(canvas): prevent stroke duplication on slow networks
Add debouncing to stroke submission to prevent duplicates
when network latency is high.
Fixes #456
docs(readme): update API documentation with v1 endpoints
Add comprehensive documentation for /api/v1/* endpoints
including authentication, rooms, and SDK usage examples.
- Keep commits atomic (one logical change per commit)
- Write clear, descriptive messages
- Use imperative mood ("add" not "added")
- Limit subject line to 72 characters
- Reference issues and PRs in footer
- GitHub Discussions: For questions, ideas, and general discussion
- GitHub Issues: For bug reports and feature requests
- Documentation: Check README.md and docs/ folder first
By contributing to ResCanvas, you agree that your contributions will be licensed under the same license as the project (see LICENSE file).
Thank you for contributing to ResCanvas! Your efforts help make collaborative drawing more accessible, private, and decentralized for everyone.