Thank you for your interest in contributing to Vinto! This document provides guidelines and information for contributors.
- Node.js 22 or higher
- npm (comes with Node.js)
-
Fork and clone the repository:
git clone https://github.com/YOUR_USERNAME/vinto.git cd vinto -
Install dependencies:
npm install
-
Git Hooks: This project uses
lefthookfor pre-commit hooks- Hooks run automatically on commit
- They enforce linting and formatting standards
- Configuration:
lefthook.yml - Pre-commit hooks will:
- Run ESLint with auto-fix on staged TypeScript/JavaScript files
- Format code with Prettier on staged files
-
Start the development server:
npm start
-
Visit http://localhost:4200 to see the app running.
This is an Nx monorepo with the following structure:
apps/
vinto/ # Main Next.js application
packages/
engine/ # Game engine (pure functions)
bot/ # AI bot logic (MCTS)
local-client/ # Client-side state management
shapes/ # Shared types and interfaces
npm start- Start development servernpm run build- Build all packagesnpm test- Run all testsnpm run lint- Lint and fix all codenpm run format- Format code with Prettiernpm run test:coverage- Run tests with coveragenpm run test:e2e- Run end-to-end tests
npx nx graph- View project dependency graphnpx nx show project game- Show main app project detailsnpx nx <target> <project-name>- Run specific target for a project
Note: The main app directory is apps/vinto/ but the Nx project name is game.
This project uses Dependabot to automatically manage npm dependencies and GitHub Actions. Dependabot helps keep the project secure and up-to-date by creating pull requests for dependency updates.
- Schedule: Dependabot checks for updates every Monday at 09:00 UTC
- Pull Request Limit: Maximum of 5 npm PRs and 3 GitHub Actions PRs at a time
- Grouping: Dependencies are grouped logically to reduce PR noise:
- Production dependencies (minor/patch updates)
- Development dependencies (minor/patch updates)
- Nx-related packages
- React ecosystem packages
- Next.js and related packages
- Major Version Updates: Automatically ignored to prevent breaking changes without review
When reviewing a Dependabot PR:
- Check CI Status: Ensure all tests, linting, and builds pass
- Review Changelog: Click through to the package's changelog to understand changes
- Test Locally (for production dependencies):
gh pr checkout <PR_NUMBER> npm install npm test npm run build
- Verify Functionality: Run the app and test affected features
- Approve and Merge: If everything looks good, approve and merge the PR
Dependabot follows the project's commit message convention:
- Production dependencies:
chore(deps): update <package-name> - Development dependencies:
chore(deps-dev): update <package-name> - GitHub Actions:
chore(ci): update <action-name>
For low-risk updates (patch/minor versions of development dependencies), consider enabling auto-merge:
- Review the PR
- If CI passes and changes look safe, approve the PR
- Enable auto-merge:
gh pr merge <PR_NUMBER> --auto --squash
If a Dependabot PR fails CI:
- Check the Logs: Review the failed test/lint/build output
- Fix Locally: Check out the PR branch and fix the issue
- Push the Fix: Commit and push to the Dependabot branch
- Merge: Once CI passes, merge the PR
Pause Dependabot (if needed during major refactoring):
# Edit .github/dependabot.yml and change schedule to:
schedule:
interval: "monthly" # or comment out the entire update blockReopen Closed Dependabot PRs:
- Comment on the closed PR with:
@dependabot reopen
Ignore Specific Updates:
- Comment on the PR with:
@dependabot ignore this dependency
Configuration Location: .github/dependabot.yml
Dependabot also monitors for security vulnerabilities and creates PRs immediately when vulnerabilities are detected.
- Trigger: Created immediately when a vulnerability is detected (not on schedule)
- Priority: Security updates bypass major version ignore rules when necessary
- Labels: Tagged with
dependenciesandautomated - Action Required: Security PRs should be prioritized over feature development
- Assess Severity: Check the vulnerability details in the PR description
- Review Changes: Understand what's being updated and why
- Test Thoroughly: Security updates may include major version bumps
- Merge Promptly: Don't delay security fixes for non-critical reasons
For Repository Maintainers:
- Go to repository Settings → Security & analysis
- Enable Dependabot security updates
- Enable Dependabot alerts to receive notifications
For updates not handled by Dependabot (or major version upgrades):
- Update
package.jsonmanually - Run
npm installto updatepackage-lock.json - Run tests:
npm test - Run build:
npm run build - Commit changes with message:
chore(deps): update <package-name> to v<version>
- Strict mode is enabled
- Prefer
interfaceovertypefor object shapes - Always export types and interfaces
- Use const for immutable values
- Use functional components with hooks
- Prefer named exports for components
- Use React 19 features
- App Router (not Pages Router)
- Use kebab-case:
my-component.tsx - One component per file
- Organize by feature, not by type
GameStateis immutable and authoritative- UI state lives in MobX stores
- Never duplicate game state in UI stores
- All game logic must be pure functions
- Actions must be serializable JSON
- Use
copy()for state updates (from fast-copy) - Maintain determinism for reproducibility
- Use Tailwind CSS
- Component-scoped styles when needed
- Mobile-first responsive design
Run Prettier before committing:
npm run format- Framework: Vitest
- Location:
*.spec.tsfiles next to source files - Run tests:
npm test - Coverage:
npm run test:coverage
- Framework: Playwright
- Location:
apps/vinto/e2e/ - Run tests:
npm run test:e2e
Game Engine Tests (pure functions):
test('drawing card updates state correctly', () => {
const initialState = createGameState();
const action = { type: 'DRAW_CARD', payload: { playerId: 'player1' } };
const newState = GameEngine.handleAction(initialState, action);
expect(newState.drawPile.length).toBe(initialState.drawPile.length - 1);
});Component Tests:
import { render, screen } from '@testing-library/react';
test('renders button with correct text', () => {
render(<MyButton>Click me</MyButton>);
expect(screen.getByText('Click me')).toBeInTheDocument();
});- Create a branch:
- For GitHub issues:
issue-{ISSUE_NUMBER}(e.g.,issue-42) - For features without issues:
feature/short-description(e.g.,feature/coalition-mode) - For bug fixes without issues:
fix/short-description(e.g.,fix/scoring-bug)
- For GitHub issues:
- Write tests: Add tests for new features or bug fixes
- Run checks locally:
npm run lint npm test npm run build - Update documentation: Update README.md or other docs if needed
- Title: Use conventional commit format:
feat: add coalition modefix: correct scoring calculationdocs: update game ruleschore: update dependenciesrefactor: simplify card action logic
- Description:
- Explain what and why (not just how)
- Reference related issues:
Closes #123 - Include screenshots for UI changes
- Small PRs: Keep PRs focused and manageable
- Draft PRs: Use draft PRs for work-in-progress
- CI must pass (tests, linting, build)
- At least one maintainer approval required
- Address review feedback
- Squash commits when merging (if needed)
Follow conventional commit format:
<type>(<scope>): <subject>
<body>
<footer>
Types:
feat: New featurefix: Bug fixdocs: Documentation changesstyle: Code style changes (formatting, etc.)refactor: Code refactoringtest: Test changeschore: Maintenance tasks
Examples:
feat(engine): add toss-in reaction mechanic
Implement the toss-in mechanic where players can play matching
cards after a discard. Includes validation and penalty handling.
Closes #45
fix(scoring): correct coalition comparison logic
The coalition scoring was comparing wrong player totals.
Fixed to compare Vinto caller vs lowest coalition total.
Fixes #67
When contributing, keep these principles in mind:
- Single Source of Truth: All game state lives in
GameState(immutable) - Pure Game Engine: No side effects, no async operations, deterministic
- Actions as Data: All interactions are serializable actions
- Cloud-Ready: Game engine should be hostable remotely
- Bot AI Integration: Bots use the same action dispatch path as humans
This project is deployed on Vercel with the following configuration:
- Automatic deploys from
masterbranch to production - Preview deploys for all pull requests
- Environment variables managed in Vercel dashboard
For maintainers:
- Merge PR to
masterbranch - Vercel automatically builds and deploys
- Monitor deployment status in PR comments or Vercel Dashboard
- Verify deployment by visiting the production URL
- Every PR gets a unique preview URL
- Preview URLs are posted as PR comments by the Vercel bot
- Use preview deployments to test changes before merging
- Open an issue for bug reports or feature requests
- Start a discussion for questions or ideas
- Check existing issues before creating new ones
By contributing to Vinto, you agree that your contributions will be licensed under the MIT License.
Thank you for contributing! 🎮