Thank you for your interest in contributing to PPCollection! This guide will help you get up and running quickly and make sure your contributions fit smoothly into the project.
Check the GitHub Issues page for open tasks. Issues tagged good first issue are a great starting point if you're new to the codebase.
# 1. Fork and clone the repository
git clone https://github.com/YOUR_USERNAME/PPCollection.git
cd PPCollection
# 2. Install dependencies
npm install
# 3. Set environment variables and start the app
# The session secret is generated into ./data/session-secret on first run —
# export SESSION_SECRET only if you want to pin it yourself.
export PORT=3000
# Leave ADMIN_PASSWORD unset to exercise the first-run setup page; the code is
# printed to the terminal on startup. Export it instead to seed an account.
export DATABASE_PATH="$PWD/data/app.db"
npm startThen open http://localhost:3000 in your browser.
PPCollection follows a strict layered architecture. Please respect these boundaries when making changes:
src/
├── app/
│ ├── createApp.js # App factory — wires all layers together
│ ├── middleware/ # Express middleware (auth, etc.)
│ └── routes/ # Route registration
├── features/
│ └── <feature>/
│ ├── <feature>.controller.js # HTTP layer — req/res only
│ ├── <feature>.routes.js # Route definitions
│ ├── <feature>.service.js # Business logic
│ └── <feature>.validators.js # Input sanitization
├── infra/
│ ├── config/ # Environment variable config
│ └── db/
│ ├── client.js # SQLite connection
│ ├── migrate.js # Migration runner
│ ├── migrations/ # SQL migration files (numbered, e.g. 001_*.sql)
│ └── repositories/ # Database access layer
├── public/
│ ├── css/ # Stylesheets (styles.css)
│ └── js/ # Client-side JavaScript
├── shared/ # Shared utilities
└── views/ # EJS templates
Key rules:
- Controllers handle HTTP only — no business logic
- Services contain business logic — no direct database queries
- Repositories handle database access — SQL only, no business logic
- Do not add inline styles to EJS templates — use
src/public/css/styles.css
Run the full test suite before opening a PR:
npm testTest structure:
tests/unit/— unit tests for services and repositoriestests/integration/— integration tests for routes and controllers
When adding a new feature, please include unit tests for any new service or repository functions. Integration tests are expected for new routes.
- All styles belong in
src/public/css/styles.css— do not add inline styles to EJS templates - All mobile overrides must be added inside the existing
@media (max-width: 640px)block at the bottom ofstyles.css— do not create additional media query blocks - Always verify style changes in both dark and light mode
- There is no frontend build step — do not introduce bundlers or transpilers
- All schema changes must be a new numbered SQL file in
src/infra/db/migrations/(e.g.002_my_change.sql) - Never modify an existing migration file
- Never add columns via
ensureLegacyColumnsinmigrate.js— this pattern is being phased out
- Fork the repository
- Create a feature branch from
main - Make your changes
- Add or update tests as needed
- Commit using conventional commit messages (see below)
- Push to your fork
- Open a Pull Request
This project uses Conventional Commits for automated versioning and changelog generation.
<type>(<optional scope>): <short description>
| Type | Release | Use for |
|---|---|---|
feat |
minor | New features |
fix |
patch | Bug fixes |
style |
patch | CSS / formatting changes |
refactor |
patch | Code restructuring without behaviour change |
test |
patch | Adding or updating tests |
docs |
patch | Documentation only |
perf |
patch | Performance improvements |
ci |
patch | CI/CD changes |
chore |
none | Maintenance tasks with no release impact |
feat(firearms): add status badge column to inventory table
fix(auth): redirect to login on expired session
style(mobile): stack action bar buttons on small viewports
refactor(migrate): move legacy columns to sql migration file
test(firearms): add unit tests for firearms serviceAdd BREAKING CHANGE: in the commit footer to trigger a major release:
feat!: remove legacy API
BREAKING CHANGE: the /api/v1 endpoint has been removed- Ensure your code follows the project's coding standards
- Add or update tests for any behaviour changes
- Update
README.mdif your change affects installation, configuration, or usage - Use conventional commit messages
- Keep PRs focused — one logical change per PR
- Wait for CI checks to pass
- Reference any related issues in the PR description
The repository uses .github/CODEOWNERS to request owner review automatically. The default owner reviews all changes, with explicit ownership for high-blast-radius files and directories such as GitHub Actions configuration, Docker runtime files, semantic-release configuration, and database migrations.
Maintainers should pair this file with a branch-protection rule on
main that requires Code Owner review before merge.
Releases are automated using semantic-release:
- Merges to
maintrigger the release workflow - Version numbers are determined from commit messages
- Changelogs are auto-generated — do not edit
CHANGELOG.mdmanually - Docker containers are built and published to GitHub Container Registry
Every merge to main triggers:
- Build: Docker image is built using the latest code
- Tag: Image is tagged with multiple identifiers:
- Semantic version (e.g.,
v1.0.0,1.0.0,1.0,1) - Git SHA (e.g.,
sha-abc123) - Branch name (
main) latesttag
- Semantic version (e.g.,
- Push: Container is published to
ghcr.io/gogorichielab/ppcollection
This project uses Dependabot to keep dependencies up to date:
- npm packages: Checked weekly on Mondays
- GitHub Actions: Checked weekly on Mondays
- Docker base images: Checked weekly on Mondays
Dependabot will automatically create pull requests for updates. Review and merge these PRs to keep dependencies current.
Feel free to open an issue for any questions or concerns!