Thank you for your interest in contributing to MetaHuman Engine!
Found a bug? Please create an issue with:
- Clear description of the problem
- Steps to reproduce
- Expected vs actual behavior
- Environment details (OS, browser, versions)
- Screenshots/recordings if applicable
Have an idea? Open an issue with:
- Use case description
- Proposed solution
- Alternatives considered
Want to fix a bug or add a feature? Follow the workflow below.
Improvements to docs, README, or code comments are always welcome.
# Fork the repository on GitHub, then:
git clone https://github.com/your-username/meta-human.git
cd meta-human
git remote add upstream https://github.com/LessUp/meta-human.git# Frontend
npm install
# Backend (optional)
cd server
python -m venv venv
source venv/bin/activate
pip install -r requirements.txt
cd ..git checkout -b feat/your-feature-name
# or: git checkout -b fix/bug-descriptionFollow Conventional Commits:
<type>(<scope>): <subject>
<body>
<footer>
Types:
| Type | Description |
|---|---|
feat |
New feature |
fix |
Bug fix |
docs |
Documentation changes |
style |
Code style (formatting, semicolons, etc.) |
refactor |
Code refactoring |
perf |
Performance improvements |
test |
Adding or updating tests |
chore |
Maintenance tasks |
Examples:
feat(avatar): add wave animation trigger
docs(api): update WebSocket documentation
fix(dialogue): resolve memory leak in streamNaming:
PascalCasefor components, types, interfacescamelCasefor functions, variablesSCREAMING_SNAKE_CASEfor constants
Imports:
// 1. External imports
import React from 'react';
// 2. Internal absolute imports
import { Button } from '@/components/ui/Button';
// 3. Internal relative imports
import { helper } from './utils';Comments:
// Good: Explains why, not what
// Retry with exponential backoff for network resilience
await retry(operation, { delay: 1000 * attempts });
// Bad: Restates the code
// Multiply delay by attempts
delay = 1000 * attempts;The project uses automated formatting:
# Format code
npm run format
# Check formatting
npm run format:check
# Lint
npm run lint
# Fix lint issues
npm run lint:fix# Watch mode
npm run test
# Single run
npm run test:run
# With coverage
npm run test:coverageComponent Example:
import { render, screen } from '@testing-library/react';
import { ChatDock } from './ChatDock';
describe('ChatDock', () => {
it('renders input field', () => {
render(<ChatDock />);
expect(screen.getByPlaceholderText('Type a message...')).toBeInTheDocument();
});
});Hook Example:
import { renderHook } from '@testing-library/react';
import { useChatStream } from './useChatStream';
describe('useChatStream', () => {
it('sends message successfully', async () => {
const { result } = renderHook(() => useChatStream());
await result.current.sendMessage('Hello');
expect(result.current.messages).toHaveLength(1);
});
});- Code follows style guidelines
- Tests pass:
npm run test:run - Linting passes:
npm run lint - TypeScript compiles:
npm run typecheck - Commits follow conventional format
- Documentation updated if needed
- Push branch to your fork
- Open PR against
mainbranch - Fill out PR template
- Link related issues
- Maintainers will review within 48 hours
- Address review comments
- Keep PR focused on single concern
Once approved, a maintainer will merge your PR.
src/
├── components/ # React components
│ ├── ui/ # Primitive UI components
│ ├── forms/ # Form-specific components
│ └── panels/ # Panel/layout components
├── core/ # Business logic
│ ├── avatar/ # 3D avatar engine
│ ├── audio/ # TTS/ASR
│ ├── dialogue/ # Chat services
│ └── vision/ # Face tracking
├── store/ # State management
├── hooks/ # Custom React hooks
├── lib/ # Utilities
├── types/ # TypeScript types
└── __tests__/ # Tests
- Create file:
components/ComponentName.tsx - Add styles (Tailwind classes)
- Add types if complex props
- Write tests
- Export from
components/index.ts
- Create file:
hooks/useHookName.ts - Follow existing hook patterns
- Add JSDoc comments
- Write tests
- Export from
hooks/index.ts
- Create file:
store/storeName.ts - Use Zustand pattern
- Define TypeScript interfaces
- Add persistence if needed
- Document public API
Use JSDoc for public APIs:
/**
* Send a chat message and receive streaming response
* @param message - User's message text
* @param options - Streaming callbacks
* @returns Promise that resolves when stream completes
* @throws {ChatError} When transport fails
*/
async function streamMessage(
message: string,
options: StreamOptions
): Promise<void>When adding features:
- Update main README.md if user-facing
- Add to docs/ if API changes
- Update CHANGELOG.md
- Issues: Bug reports, feature requests
- Discussions: Questions, ideas, show-and-tell
- Pull Requests: Code contributions
- Be respectful and inclusive
- Welcome newcomers
- Focus on constructive feedback
- Respect differing viewpoints
- Check existing issues
- Start a discussion
- Ask in your PR/issue
Thank you for contributing to MetaHuman Engine! 🎉