Thank you for your interest in contributing to PinchPad! This guide covers everything you need to get started.
Click to expand
Be respectful, collaborative, and constructive. Criticism should be directed at code, not people.
# 1. Fork the repository on GitHub, then clone your fork
git clone https://github.com/YOUR_USERNAME/PinchPad.git
cd PinchPad
# 2. Install dependencies
npm install
# 3. Copy the environment config
cp .env.example .env.local
# Add your GEMINI_API_KEY to .env.local
# 4. Start the frontend and backend servers together
npm run scuttle:dev-start
# → Frontend: http://localhost:8282
# → Backend: http://localhost:8383/api/health| Branch | Purpose |
|---|---|
main |
Stable, production-ready code |
dev |
Active development integration (if used) |
feat/<name> |
New features (branch from main) |
fix/<name> |
Bug fixes (branch from main) |
docs/<name> |
Documentation-only updates |
# Create a feature branch
git checkout main
git pull origin main
git checkout -b feat/my-new-featureTypeScript & React standards
- TypeScript strict mode is enabled — no
anyunless justified with a comment explaining why. - Use
import typefor type-only imports. - Use named exports, not default exports (exception: React page-level components).
- All React components use function syntax with hooks.
- State variables use descriptive names — avoid
data,result,val. - Errors must be typed and handled explicitly. No silent
catchblocks.
File & naming standards
- Component files:
PascalCase.tsx - Utility / service files:
camelCase.ts - Type definition files:
camelCase.tsinsidetypes/ - One component per file — no bundling multiple unrelated components.
- CSS via Tailwind utility classes only. No raw CSS files unless for global resets.
These are non-negotiable constraints that maintain the project's long-term maintainability.
- Separation of Concerns — Components display. Services fetch/persist. Middleware gates auth.
- Use the REST architecture — All data operations go through the Express REST API, never direct database imports.
- No monolith files — Files growing beyond ~150 lines are a signal to refactor into sub-modules.
- Auth stays client-side — Never send
hu-*identity keys to the server. Onlyapi-andlb-tokens are server-side artifacts. - Feature-first directories — New component groups go inside a named feature folder (
components/myfeature/), not flat in the components root. - No direct database imports in tests — Always use
createTestApp()factory. This ensures in-memory SQLite isolation and zero test pollution. - Immutable Middleware Stack — Auth gates are immutable:
requireAuth→requirePermission→requireHuman. Never reorder or remove.
All code changes must pass the test suite. PinchPad uses Vitest 4.1.0 with 140 tests across 9 files.
View testing discipline
- All test files:
*.lobster.test.ts(CrustCode™ brand) - Path mirrors src:
test/[domain]/[file].lobster.test.ts - Example:
src/lib/crypto.ts→test/lib/crypto.lobster.test.ts
# Run all tests — all 140 must pass
npm test
# Check coverage — required minimums:
# - Middleware: 100% statements
# - Routes: >75% statements
# - Overall: >56% statements
npm run test:coverage- Use
createTestApp()factory for all backend tests (provides{ app, db }) - Each test file gets its own
:memory:SQLite database (zero pollution) - Write HTTP tests via supertest, not mocks
- Test error cases (401, 403, 404, 500) not just happy path
- Verify database state after operations (was the token deleted? permission set?)
- Never import
src/server/dbdirectly in tests — usecreateTestApp()instead - Never remove working tests or use
.skip/.onlywithout removing before commit - Never mock the database — integration tests hit real (in-memory) SQLite
- Never use
setTimeoutor fake timers (sync better-sqlite3 doesn't need it) - Never hard-code API keys or secrets in tests
- Run
npm run lint— must show zero TypeScript errors. - Run
npm test— all 140 tests must pass. - Run
npm run test:coverage— all coverage minimums must be met. - Update BLUEPRINT.md if you added or moved files.
- Update ROADMAP.md if your change completes or introduces a roadmap item.
- Write a clear PR description: what changed, why, and how to test.
- Link any related GitHub Issues.
Important
Tests are a gate — no test failures = no merge. GitHub Actions will run tests again. If Actions fails, fix locally and push again (don't force push).
Open a GitHub Issue with:
- Steps to reproduce (minimal reproduction preferred)
- Expected vs actual behaviour
- Browser + OS version
- Any console errors (screenshot or paste)
- Port numbers and environment (dev vs prod Docker)
For security vulnerabilities, see SECURITY.md — do not open a public issue.
Maintained by CrustAgent©™