Thank you for your interest in contributing to markupR! This document covers everything you need to get started.
- Code of Conduct
- Getting Started
- How the Pipeline Works
- Development Workflow
- Pull Request Process
- Style Guide
- Reporting Issues
By participating in this project, you agree to maintain a respectful and inclusive environment. Please:
- Be respectful and considerate in all interactions
- Welcome newcomers and help them learn
- Focus on constructive feedback
- Accept responsibility for mistakes and learn from them
- Node.js 18+ (check with
node --version) - npm 9+ (comes with Node.js)
- Git
- ffmpeg -- required for frame extraction and audio processing
- macOS:
brew install ffmpeg - Ubuntu/Debian:
sudo apt install ffmpeg - Windows:
choco install ffmpegor download from ffmpeg.org
- macOS:
- A code editor (VS Code recommended)
Optional:
- Whisper model -- downloaded automatically on first run (~75MB for tiny, ~500MB for base)
- OpenAI API key -- for cloud transcription (configured in-app, not required for development)
- Anthropic API key -- for AI-enhanced analysis (configured in-app, not required for development)
-
Fork the repository on GitHub
-
Clone your fork:
git clone https://github.com/YOUR_USERNAME/markupr.git cd markupr -
Add upstream remote:
git remote add upstream https://github.com/eddiesanjuan/markupr.git
-
Install dependencies:
npm install
-
Start development:
npm run dev
| Command | Purpose |
|---|---|
npm run dev |
Start development mode with hot reload |
npm test |
Run all tests |
npm run test:unit |
Run unit tests only |
npm run test:watch |
Run tests in watch mode |
npm run lint |
Lint code |
npm run lint:fix |
Auto-fix lint issues |
npm run typecheck |
TypeScript type checking |
npm run build |
Build for production |
See CLAUDE.md for the most up-to-date architecture reference, including the full directory structure, key design decisions, and conventions. This file is also used by AI coding assistants (Claude Code, Cursor, etc.) for codebase context.
For detailed development setup and debugging instructions, see docs/DEVELOPMENT.md.
Understanding the post-processing pipeline helps when contributing to any part of the codebase. When recording stops, four stages run in sequence:
- Transcribe (
src/main/transcription/) -- Audio is transcribed using local Whisper (or OpenAI API). Produces timestamped transcript segments. - Analyze (
src/main/pipeline/TranscriptAnalyzer.ts) -- Transcript is analyzed to identify key moments, topic changes, and important observations using heuristic scoring. - Extract (
src/main/pipeline/FrameExtractor.ts) -- ffmpeg extracts video frames at the exact timestamps of each key moment. - Generate (
src/main/output/MarkdownGenerator.ts) -- Everything is stitched into a structured Markdown document with screenshots placed at the correct positions.
Each step degrades gracefully: if transcription fails, frame extraction still runs on a timer; if ffmpeg is missing, a transcript-only document is generated.
The pipeline orchestrator lives at src/main/pipeline/PostProcessor.ts.
Use descriptive branch names:
feature/add-pdf-exportfix/hotkey-conflictdocs/update-readmerefactor/settings-panel
-
Create a branch:
git checkout -b feature/my-feature
-
Make your changes following the style guide
-
Test your changes:
npm test npm run lint npm run typecheck -
Commit your changes using Conventional Commits:
git commit -m "feat(export): add PDF export format"
<type>(<scope>): <description>
[optional body]
[optional footer]
Types:
feat: New featurefix: Bug fixdocs: Documentation onlystyle: Code style (formatting, etc.)refactor: Code change that neither fixes nor addsperf: Performance improvementtest: Adding or updating testschore: Maintenance tasks
Examples:
feat(export): add PDF export format
fix(hotkey): resolve conflict with system shortcuts
docs(readme): update installation instructions
refactor(settings): simplify settings manager
git fetch upstream
git checkout main
git merge upstream/main
git push origin mainEnsure your PR:
- Passes all tests:
npm test - Passes linting:
npm run lint - Passes type checking:
npm run typecheck - Has been tested manually
- Includes documentation updates (if applicable)
- Push your branch:
git push origin feature/my-feature - Open a Pull Request on GitHub
- Fill out the PR template -- describe what the PR does, link related issues, and include screenshots for UI changes
- Request review if not automatically assigned
- Automated checks (CI) must pass
- At least one maintainer must approve
- All comments must be resolved
- No merge conflicts with main
- Delete your branch
- Pull changes to your local main
- Use explicit types for function parameters and return values
- Use interfaces for object shapes
- Use
as constassertions for literal objects - Strict mode is enabled -- no
anywithout justification
// Use explicit types
function createSession(sourceId: string): Session {
// ...
}
// Use interfaces for objects
interface SessionOptions {
sourceId: string;
sourceName?: string;
}
// Use const assertions for literals
const STATUS = {
IDLE: 'idle',
RECORDING: 'recording',
} as const;- Functional components only
- Named exports preferred
- Clean up effects with return functions
export function SessionStatus({ state }: SessionStatusProps) {
const [isActive, setIsActive] = useState(false);
useEffect(() => {
return () => cleanup();
}, []);
return <div className="status">{state}</div>;
}- Use Tailwind utilities for styling
- Use
cn()helper for conditional classes
<div className={cn(
"bg-gray-900 text-white p-4 rounded-lg",
isActive && "ring-2 ring-blue-500",
className
)}>- Framework: Vitest
- Convention: Test files mirror source structure in
tests/unit/,tests/integration/,tests/e2e/ - Expectation: New features should include tests; bug fixes should include a regression test
| Type | Convention | Example |
|---|---|---|
| Components | PascalCase | SessionReview.tsx |
| Hooks | camelCase, use prefix |
useSessionState.ts |
| Utilities | camelCase | formatTime.ts |
| Types | PascalCase | SessionState |
| Constants | UPPER_SNAKE_CASE | MAX_RETRIES |
- Search existing issues for duplicates
- Try the latest version -- the issue may already be fixed
- Collect information: OS, markupR version (visible in Settings footer), steps to reproduce, error messages or logs
Use the bug report template when opening a new issue. Include your OS, markupR version, and steps to reproduce.
Use the feature request template. Describe the problem you're trying to solve, not just the solution you want.
- Check issues labeled "good first issue" for beginner-friendly tasks
- Check issues labeled "help wanted" for tasks where we need help
- For significant changes, open an issue first to discuss the approach
- Open a discussion
- Check the documentation
- Review existing issues
Thank you for contributing to markupR!