docs: open project to public contributions with CLA

Add full contribution infrastructure: CLA with broad sublicensing
rights for dual-licensing, CONTRIBUTING.md with scope rules and dev
setup, CLA Assistant workflow, CODEOWNERS, SUPPORT.md, PR template,
updated issue templates with contribution prompts, and declarative
label config.
This commit is contained in:
SnapOtter
2026-05-16 16:05:08 +08:00
parent 92b85d3506
commit 29d959e7c1
12 changed files with 433 additions and 26 deletions
+10 -1
View File
@@ -51,7 +51,7 @@ body:
attributes:
label: Image tag
description: Which Docker image tag are you using?
placeholder: "e.g. latest, 1.11.0"
placeholder: "e.g. latest, 1.17.0"
validations:
required: true
@@ -83,3 +83,12 @@ body:
attributes:
label: Screenshots
description: If applicable, add screenshots to help explain the problem.
- type: dropdown
id: willing-to-fix
attributes:
label: Would you like to contribute a fix?
description: If yes, we can assign this issue to you. See CONTRIBUTING.md for the PR process.
options:
- "Yes, I'd like to submit a PR"
- "No, just reporting"
+3
View File
@@ -3,6 +3,9 @@ contact_links:
- name: Documentation
url: https://docs.snapotter.com/
about: Check the docs for setup guides, configuration, and API reference.
- name: Discord
url: https://discord.gg/hr3s7HPUsr
about: Ask questions, get help, and chat with the community.
- name: Security vulnerability
url: https://github.com/snapotter-hq/snapotter/security/advisories/new
about: Report security issues privately through GitHub Security Advisories.
@@ -43,3 +43,12 @@ body:
attributes:
label: Additional context
description: Screenshots, links, examples, or anything else that helps explain the request.
- type: dropdown
id: willing-to-implement
attributes:
label: Would you like to implement this?
description: Feature PRs require issue approval first. If approved, we can assign this to you.
options:
- "Yes, I'd like to submit a PR if approved"
- "No, just suggesting"
+97
View File
@@ -0,0 +1,97 @@
# Bug & Issue Types
- name: bug
color: "d73a4a"
description: Something isn't working
- name: enhancement
color: "a2eeef"
description: New feature or improvement
- name: documentation
color: "0075ca"
description: Documentation improvements
- name: translation
color: "7057ff"
description: New or updated translation
# Contribution Flow
- name: good first issue
color: "7057ff"
description: Good for newcomers
- name: help wanted
color: "008672"
description: Extra attention is needed
- name: approved
color: "0e8a16"
description: Feature approved for implementation
- name: needs discussion
color: "fbca04"
description: Requires maintainer input before proceeding
# PR Status
- name: awaiting review
color: "f9d0c4"
description: PR is ready for maintainer review
- name: changes requested
color: "e11d48"
description: PR needs changes before merge
- name: cla-signed
color: "0e8a16"
description: Contributor has signed the CLA
- name: cla-needed
color: "b60205"
description: CLA signature required
# Scope
- name: "area: frontend"
color: "bfdadc"
description: Changes to apps/web
- name: "area: backend"
color: "c5def5"
description: Changes to apps/api
- name: "area: image-engine"
color: "d4c5f9"
description: Changes to packages/image-engine
- name: "area: i18n"
color: "e99695"
description: Changes to packages/shared/src/i18n
- name: "area: docs"
color: "0075ca"
description: Changes to apps/docs
# Priority
- name: "priority: critical"
color: "b60205"
description: Must be fixed immediately
- name: "priority: high"
color: "d93f0b"
description: Important, fix soon
- name: "priority: low"
color: "c2e0c6"
description: Nice to have, no rush
# Meta
- name: duplicate
color: "cfd3d7"
description: This issue or PR already exists
- name: wontfix
color: "ffffff"
description: This will not be worked on
- name: invalid
color: "e4e669"
description: Not a valid issue or doesn't apply
+25 -8
View File
@@ -1,12 +1,29 @@
<!--
Thanks for your interest in SnapOtter.
## What does this PR do?
We don't accept pull requests. All development is handled internally to maintain architectural consistency and code quality.
<!-- 1-2 sentences. Link to the related issue if applicable. -->
If you've found a bug or have a feature idea, please open an issue instead:
https://github.com/snapotter-hq/snapotter/issues
Fixes #
Your feedback is valuable and directly shapes the project.
-->
## Type of change
**This project does not accept pull requests.** Please close this PR and [open an issue](https://github.com/snapotter-hq/snapotter/issues/new/choose) instead. See [CONTRIBUTING.md](CONTRIBUTING.md) for details.
- [ ] Bug fix (non-breaking change that fixes an issue)
- [ ] New feature (non-breaking change that adds functionality)
- [ ] New translation or i18n update
- [ ] Documentation update
- [ ] Test improvement
- [ ] Refactor (no functional change)
## Checklist
- [ ] I have read [CONTRIBUTING.md](../CONTRIBUTING.md)
- [ ] I have signed the [CLA](../CLA.md) (the bot will prompt you if not)
- [ ] My changes follow the project's code style (Biome passes)
- [ ] I have added or updated tests for my changes
- [ ] All existing tests pass locally (`pnpm test`)
- [ ] TypeScript compiles without errors (`pnpm typecheck`)
- [ ] My PR is focused on a single concern (under 400 lines of change)
- [ ] I have not modified CI, release, or linter configuration files
## Screenshots (if applicable)
<!-- For UI changes, include before/after screenshots. -->
+45
View File
@@ -0,0 +1,45 @@
name: CLA Assistant
on:
issue_comment:
types: [created]
pull_request_target:
types: [opened, synchronize, reopened]
permissions:
actions: write
contents: read
pull-requests: write
statuses: write
jobs:
cla:
if: |
(github.event_name == 'pull_request_target') ||
(github.event_name == 'issue_comment' && github.event.comment.body == 'recheck')
runs-on: ubuntu-latest
steps:
- name: CLA Assistant
uses: contributor-assistant/github-action@ca4a40a7d1004f18d9960b404b97e5f30a505a08 # v2.6.1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PERSONAL_ACCESS_TOKEN: ${{ secrets.CLA_TOKEN }}
with:
path-to-signatures: "signatures/cla.json"
path-to-document: "https://github.com/snapotter-hq/snapotter/blob/main/CLA.md"
branch: "main"
allowlist: "dependabot[bot],renovate[bot],github-actions[bot],snapotter-bot"
custom-notsigned-prcomment: |
Thank you for your contribution! Before we can merge this PR, you need to sign our [Contributor License Agreement](https://github.com/snapotter-hq/snapotter/blob/main/CLA.md).
**What the CLA does:** You keep ownership of your code. You grant SnapOtter a license to use your contribution under any license (including our commercial license). [Read the plain-language summary](https://github.com/snapotter-hq/snapotter/blob/main/CLA.md#plain-language-summary).
**How to sign:** Comment on this PR with the following text:
> I have read the CLA Document and I hereby sign the CLA
You only need to do this once. It applies to all future contributions.
custom-pr-sign-comment: "I have read the CLA Document and I hereby sign the CLA"
custom-allsigned-prcomment: "All contributors have signed the CLA. Thank you!"
lock-pullrequest-aftermerge: false
use-dco-flag: false
+70
View File
@@ -0,0 +1,70 @@
# SnapOtter Individual Contributor License Agreement
## Plain-Language Summary
This is not legal advice. Read the full agreement below.
- You keep ownership of your code. You are granting SnapOtter a license, not transferring copyright.
- You give SnapOtter permission to use, modify, and distribute your contribution under any license, including the commercial license we sell.
- You grant a patent license covering any patents your contribution necessarily infringes.
- You confirm the work is yours (or you have permission from your employer).
- This grant is irrevocable. Once signed, you cannot revoke it for past contributions.
- SnapOtter has no obligation to use your contribution.
---
## Full Agreement
By signing this Contributor License Agreement ("Agreement"), you accept and agree to the following terms for your present and future Contributions submitted to SnapOtter. This Agreement is effective as of the date you first sign it.
### 1. Definitions
**"You" (or "Your")** means the individual signing this Agreement.
**"Contribution"** means any original work of authorship, including any modifications or additions to existing work, that you intentionally submit to SnapOtter for inclusion in the project. "Submit" means any form of electronic or written communication sent to SnapOtter or its representatives, including pull requests, patches, issues, comments, and messages on project communication channels.
**"SnapOtter"** means the SnapOtter project and its maintainers, operating under snapotter-hq on GitHub.
### 2. Grant of Copyright License
You hereby grant to SnapOtter a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, sublicense, and distribute your Contributions and any derivative works thereof under any license terms, including without limitation any open-source license or proprietary/commercial license.
### 3. Grant of Patent License
You hereby grant to SnapOtter a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer your Contributions, where such license applies only to those patent claims licensable by you that are necessarily infringed by your Contributions alone or by combination of your Contributions with the project to which the Contributions were submitted.
If any entity institutes patent litigation against you or any other entity (including a cross-claim or counterclaim in a lawsuit) alleging that your Contribution constitutes patent infringement, then any patent licenses granted to that entity under this Agreement for that Contribution shall terminate as of the date such litigation is filed.
### 4. Representations
You represent that:
(a) You are legally entitled to grant the above licenses. If your employer has rights to intellectual property that you create, you represent that you have received permission to make Contributions on behalf of that employer, or that your employer has waived such rights for your Contributions to SnapOtter.
(b) Each of your Contributions is your original creation. You represent that your Contributions include complete details of any third-party license or other restriction of which you are aware that is associated with any part of your Contributions.
(c) Your Contribution does not knowingly violate any third party's intellectual property rights.
### 5. No Obligation
You understand that the decision to include your Contribution in any project or product is entirely at the discretion of SnapOtter, and this Agreement does not create an obligation to use your Contribution.
### 6. Support
You are not expected to provide support for your Contributions, except to the extent you desire to provide support. You may provide support for free, for a fee, or not at all. Your Contributions are provided "AS IS" without warranty of any kind.
### 7. Notification
You agree to notify SnapOtter if any of your representations in this Agreement become inaccurate.
### 8. Governing Law
This Agreement shall be governed by and construed in accordance with the laws of India, without regard to its conflict of law provisions.
---
## How to Sign
When you open your first pull request, the CLA Assistant bot will post a comment with a signing link. Click the link and authenticate with your GitHub account. Your signature is recorded and applies to all future contributions.
If you have questions about the CLA, contact contact@snapotter.com.
+23
View File
@@ -0,0 +1,23 @@
# Default owner for everything
* @snapotter-hq/maintainers
# CI/CD and release (restricted, no external PRs accepted)
.github/workflows/ @snapotter-hq/maintainers
.releaserc.json @snapotter-hq/maintainers
scripts/ @snapotter-hq/maintainers
# Config files (protected by hooks, no external changes)
biome.json @snapotter-hq/maintainers
tsconfig*.json @snapotter-hq/maintainers
# AI sidecar (requires prior discussion)
packages/ai/ @snapotter-hq/maintainers
# Auth and permissions (security-sensitive)
apps/api/src/routes/auth*.ts @snapotter-hq/maintainers
apps/api/src/lib/auth*.ts @snapotter-hq/maintainers
packages/shared/src/permissions.ts @snapotter-hq/maintainers
# Database schema and migrations
apps/api/src/db/schema.ts @snapotter-hq/maintainers
apps/api/drizzle/ @snapotter-hq/maintainers
+118 -13
View File
@@ -1,25 +1,130 @@
# Contributing to SnapOtter
Thanks for your interest in the project. Community feedback helps shape SnapOtter, and there are several ways to get involved.
Thanks for your interest in contributing. This guide covers how to participate, what we accept, and how to set up your development environment.
## How to contribute
## Ways to Contribute
The best way to contribute is through [GitHub Issues](https://github.com/snapotter-hq/snapotter/issues):
### Issues (no setup required)
- **Bug reports** - Found something broken? Open a bug report with steps to reproduce, your Docker setup, and what you expected to happen.
- **Feature requests** - Have an idea for a new tool or improvement? Describe the problem you want solved and why it matters to you.
- **Feedback** - Thoughts on the UI, workflow, documentation, or anything else? We want to hear it.
- **Bug reports** - Something broken? Open a [bug report](https://github.com/snapotter-hq/snapotter/issues/new?template=bug_report.yml) with reproduction steps.
- **Feature requests** - Have an idea? Open a [feature request](https://github.com/snapotter-hq/snapotter/issues/new?template=feature_request.yml) describing the problem it solves.
## Pull requests
### Code (requires CLA)
We do not accept pull requests. All development is handled internally to maintain architectural consistency and code quality across the project.
We accept pull requests for:
If you've found a bug, please open an issue describing it rather than submitting a fix. If you have a suggestion for how something should work, describe it in a feature request. Your input is valuable even without a code contribution.
| Type | Process |
|------|---------|
| Bug fixes | Open a PR directly (link the issue if one exists) |
| New translations | Open a PR directly (see [Translation Guide](https://docs.snapotter.com/guide/translations)) |
| Documentation improvements | Open a PR directly |
| Test coverage improvements | Open a PR directly |
| New tools or features | Open an issue first, wait for approval before writing code |
| Refactors or architecture changes | Open an issue first, wait for approval before writing code |
## Forking
### What We Will Not Accept
You're welcome to fork the project for your own use under the terms of the [AGPLv3 license](LICENSE). The [Developer Guide](https://docs.snapotter.com/guide/developer) covers setup, architecture, and how to add new tools.
- Changes to CI/CD workflows, release config, or linter/compiler config
- PRs without a signed [Contributor License Agreement](#contributor-license-agreement)
- PRs over 400 lines of change (break large work into smaller PRs)
- Features that were not discussed and approved in an issue first
- Changes to `packages/ai/` without prior discussion
## Security
## Contributor License Agreement
If you discover a security vulnerability, please report it privately through [GitHub Security Advisories](https://github.com/snapotter-hq/snapotter/security/advisories/new) rather than opening a public issue.
Before we can merge your first PR, you must sign our [Individual CLA](CLA.md). This is a one-time requirement.
**Why:** SnapOtter is dual-licensed (AGPLv3 + commercial). The CLA grants us the right to distribute your contributions under both licenses. You retain full copyright ownership of your work.
**How:** When you open your first PR, the CLA Assistant bot will comment with a link. Click it, review the agreement, and sign with your GitHub account. Takes 30 seconds.
If you are contributing on behalf of your employer, your employer must sign the Corporate CLA. Contact contact@snapotter.com for details.
## Development Setup
### Prerequisites
- Node.js 22+
- pnpm 9+
- Python 3.11+ (only for AI tools)
- Docker (optional, for full integration testing)
### Getting Started
```bash
# Fork and clone
git clone https://github.com/<your-username>/snapotter.git
cd snapotter
# Install dependencies
pnpm install
# Start dev servers (web on :1349, API on :13490)
pnpm dev
```
### Running Checks
Before submitting a PR, ensure all checks pass locally:
```bash
pnpm lint # Biome lint + format check
pnpm typecheck # TypeScript across monorepo
pnpm test # Vitest unit + integration tests
```
To run a single test file:
```bash
pnpm vitest run tests/unit/my-test.test.ts
pnpm vitest run tests/integration/my-test.test.ts
```
### Code Style
- Biome handles formatting and linting (double quotes, semicolons, 2-space indent)
- Pre-commit hook runs `biome check --write` on staged files automatically
- If the linter complains, fix the code (do not modify Biome config)
- ES modules everywhere (`import`/`export`, `.js` extensions on relative imports)
- Conventional commits: `feat:`, `fix:`, `refactor:`, `docs:`, `test:`, `chore:`
### Architecture Quick Reference
A tool lives in three places sharing a `toolId` string:
1. **Shared metadata** - `packages/shared/src/constants.ts` (TOOLS array)
2. **API route** - `apps/api/src/routes/tools/<toolId>.ts` (uses `createToolRoute` factory)
3. **Frontend settings** - `apps/web/src/components/tools/<toolId>-settings.tsx`
For full architecture details, see the [Developer Guide](https://docs.snapotter.com/guide/developer).
## Pull Request Process
1. Fork the repo and create a branch from `main` (`feat/my-feature` or `fix/issue-123`)
2. Make your changes in focused, reviewable commits using [conventional commits](https://www.conventionalcommits.org/)
3. Add or update tests for your changes
4. Run `pnpm lint && pnpm typecheck && pnpm test` locally
5. Open a PR against `main` and fill out the template
6. Sign the CLA if prompted
7. Wait for CI to pass and a maintainer to review
### Review Expectations
- We aim to respond to PRs within 7 days
- Small, focused PRs get reviewed faster
- If you have not heard back in 7 days, leave a comment pinging the thread
- We may request changes, suggest a different approach, or close the PR if it does not align with project direction
### After Your PR is Merged
Your contribution will be included in the next release and credited in the changelog.
## Security Vulnerabilities
**Do not open a public PR or issue for security vulnerabilities.** Report them privately through [GitHub Security Advisories](https://github.com/snapotter-hq/snapotter/security/advisories/new) or email contact@snapotter.com. See [SECURITY.md](SECURITY.md) for full details.
## Questions?
- [Documentation](https://docs.snapotter.com/)
- [Discord](https://discord.gg/hr3s7HPUsr) - for help and discussion
- [GitHub Discussions](https://github.com/snapotter-hq/snapotter/discussions) - for longer-form questions
+5 -3
View File
@@ -74,11 +74,13 @@ For Docker Compose, persistent storage, and other setup options, see the [Gettin
- [Contributing](https://docs.snapotter.com/guide/contributing)
- [Translation Guide](https://docs.snapotter.com/guide/translations)
## Feedback
## Contributing
Found a bug or have a feature idea? Open a [GitHub Issue](https://github.com/snapotter-hq/snapotter/issues). We don't accept pull requests, but your feedback directly shapes the project. See [CONTRIBUTING.md](CONTRIBUTING.md) for details.
We welcome bug reports, feature ideas, and pull requests. See [CONTRIBUTING.md](CONTRIBUTING.md) for the full guide, or jump in:
Join our [Discord](https://discord.gg/hr3s7HPUsr) for help, discussion, and community updates.
- [Open an issue](https://github.com/snapotter-hq/snapotter/issues)
- [Submit a PR](CONTRIBUTING.md#code-requires-cla) (requires signing our CLA)
- [Join Discord](https://discord.gg/hr3s7HPUsr) for help and discussion
## License
+1 -1
View File
@@ -13,7 +13,7 @@ Self-hosted deployments should subscribe to [GitHub release notifications](https
## Reporting a Vulnerability
**Do not open a public GitHub issue for security vulnerabilities.**
**Do not open a public GitHub issue or pull request for security vulnerabilities.**
To report a vulnerability, email **contact@snapotter.com** with:
+27
View File
@@ -0,0 +1,27 @@
# Support
## Getting Help
| Channel | Use for |
|---------|---------|
| [Documentation](https://docs.snapotter.com/) | Setup guides, configuration, API reference, tool usage |
| [Discord](https://discord.gg/hr3s7HPUsr) | Quick questions, troubleshooting, community discussion |
| [GitHub Discussions](https://github.com/snapotter-hq/snapotter/discussions) | Longer-form questions, ideas, show-and-tell |
## Reporting Problems
| Problem | Where to report |
|---------|----------------|
| Bug (something is broken) | [GitHub Issues](https://github.com/snapotter-hq/snapotter/issues/new?template=bug_report.yml) |
| Feature request | [GitHub Issues](https://github.com/snapotter-hq/snapotter/issues/new?template=feature_request.yml) |
| Security vulnerability | [Private advisory](https://github.com/snapotter-hq/snapotter/security/advisories/new) (never a public issue) |
## Before Opening an Issue
1. Check the [documentation](https://docs.snapotter.com/) for your question
2. Search [existing issues](https://github.com/snapotter-hq/snapotter/issues) for duplicates
3. Make sure you are running the latest version
## Response Times
We are a small team. Expect responses within 7 days for issues. Discord is faster for quick questions but not guaranteed.