Thank you for your interest in contributing to Ghostbook! This document provides guidelines and information for contributors.
- Getting Started
- Development Setup
- Code Style & Formatting
- Making Changes
- Submitting Changes
- Project Structure
- Testing
- Node.js v24 or higher
- npm (comes with Node.js)
- Git
-
Fork the repository on GitHub
-
Clone your fork:
git clone https://github.com/YOUR_USERNAME/ghostbook.git cd ghostbook -
Add upstream remote:
git remote add upstream https://github.com/daedalist/ghostbook.git
-
Install dependencies:
npm install
-
Start the development server:
npm run dev
-
Open the app: Navigate to http://localhost:3000/ghostbook/
⚠️ Important: The app uses the/ghostbookbase path to match GitHub Pages deployment. You must include/ghostbook/in the URL for local development.
This project uses Prettier for consistent code formatting. All formatting is handled automatically.
Before committing:
npm run format # Auto-format all code
npm run format:check # Check if code is formatted (CI-friendly)
npm run type-check # Check TypeScript types
npm run lint:types # Run both type-check and lint (comprehensive)Editor Setup (Recommended):
- Install the Prettier extension for your editor (VS Code, IntelliJ, etc.)
- Enable "Format on Save" in your editor settings
- Prettier will automatically format on save
Formatting Rules:
- Indentation: 2 spaces (no tabs)
- Quotes: Single quotes for JavaScript/TypeScript, double quotes for JSX attributes
- Semicolons: Always required
- Line width: 80 characters
- Trailing commas: ES5 style
Check for issues:
npm run lint # Check code quality
npm run lint:fix # Auto-fix ESLint issuesESLint Rules:
- React best practices
- TypeScript type checking
- Next.js conventions
- No formatting rules (handled by Prettier)
- TypeScript (.tsx, .ts): Use for Next.js app directory files
- JavaScript (.jsx, .js): Acceptable for components and utilities
- Mixed approach: Keep existing JS files as-is, use TS for new App Router files
- Components: PascalCase (e.g.,
ObservationList.jsx) - Utilities: camelCase (e.g.,
evidenceState.js) - Constants: UPPER_SNAKE_CASE (e.g.,
NOT_SELECTED)
- Use functional components with hooks for new code
- Class components exist in legacy code (
Ghostbook.jsx) - OK to keep - Client components must have
'use client'directive (Next.js 16 requirement)
Create a descriptive branch name:
feat/feature-name- New featuresfix/bug-description- Bug fixeschore/task-description- Maintenance tasksdocs/update-description- Documentation updates
Follow conventional commit format:
type: brief description
Longer description if needed
Resolves #123
Types:
feat:- New featurefix:- Bug fixchore:- Maintenance tasksdocs:- Documentation updatesrefactor:- Code refactoringtest:- Adding or updating testsstyle:- Code style changes (formatting, etc.)
Run these checks:
npm run format # Format code
npm run type-check # Check TypeScript types
npm run lint # Check code quality
npm run lint:types # Or run both type-check and lint together
npm run build # Ensure build succeeds-
Update your fork:
git checkout main git fetch upstream git merge upstream/main
-
Create a feature branch:
git checkout -b feat/your-feature-name
-
Make your changes and commit:
git add . git commit -m "feat: add your feature description"
-
Push to your fork:
git push origin feat/your-feature-name
-
Create a Pull Request on GitHub from your fork to the main repository
- Title: Clear, concise description of changes
- Description: Explain what changed and why
- Link issues: Reference related issues with "Resolves #123"
- Tests: Ensure all checks pass
- Screenshots: Include screenshots for UI changes
- Be responsive to feedback
- Make requested changes in new commits
- Keep discussions professional and constructive
- PRs require approval before merging
src/
├── app/ # Next.js App Router (TypeScript)
│ ├── layout.tsx # Root layout with metadata
│ ├── globals.css # Global styles
│ └── [[...slug]]/ # Catch-all route for SPA behavior
│ ├── page.tsx # Main page component
│ └── client.tsx # Client-side wrapper
├── components/ # React components (JavaScript/JSX)
│ ├── Ghostbook.jsx # Main application component (class)
│ ├── ObservationList.jsx # Evidence tracking interface
│ ├── CandidateList.jsx # Ghost filtering display
│ └── Ghost.jsx # Individual ghost component
└── lib/ # Utilities and data (JavaScript)
├── evidence.js # Evidence definitions
├── evidenceState.js # Evidence state constants
└── ghost_data_map.json # Ghost evidence mappings
next.config.mjs- Next.js configuration for static exporteslint.config.mjs- ESLint configuration.prettierrc.json- Prettier formatting rules.claude/CLAUDE.md- Project memory for AI assistants
Development server:
npm run devThen open: http://localhost:3000/ghostbook/
Production build:
npm startThis builds and serves the production version with the correct /ghostbook base path at http://localhost:3000/ghostbook/
When testing your changes, verify:
- Evidence buttons cycle through states correctly (Not Selected → Selected → Ruled Out)
- Ghost list updates based on selected evidence
- Impossible evidence is disabled appropriately
- Reset button clears all evidence
- UI is responsive on mobile and desktop
- No console errors or warnings
- App works at
/ghostbook/path (matches GitHub Pages)
Always verify the build succeeds before submitting a PR:
npm run buildThe build should complete without errors or warnings.
Evidence states are managed using JavaScript Maps and React class component state. Each evidence type can be in one of four states:
NOT_SELECTED- Default stateSELECTED- User has confirmed this evidenceRULED_OUT- User has confirmed this evidence is NOT presentDISABLED- Evidence is impossible based on current ghost candidates
Ghosts are scored based on evidence:
- +10 points - Each matching primary evidence
- +5 points - Each matching fake evidence
- -10 points - Contradictory evidence (elimination)
- Uses Next.js
output: 'export'for static builds - Base path:
/ghostbookfor GitHub Pages deployment - Build output:
build/directory - Images are unoptimized for static compatibility
- Issues: Check existing issues or create a new one
- Discussions: Use GitHub Discussions for questions
- Documentation: See README.md and .claude/CLAUDE.md
By contributing, you agree that your contributions will be licensed under the MIT License.
Thank you for contributing to Ghostbook! 👻