chore: contributor experience — CoC, templates, Dependabot, editor configs

Nine paperwork files + one devDep. All support work for a repo that's
about to be public; zero runtime behaviour change.

- CONTRIBUTING.md at root. Dev loop, script reference, PR style, code
  style, review process. Short on prose, long on specifics.
- .github/CODE_OF_CONDUCT.md adopts Contributor Covenant 2.1 by
  reference (no inlined text). Points reports to the maintainer's
  email and GitHub's private flow.
- .github/ISSUE_TEMPLATE/ — structured YAML forms for bug and feature
  reports, plus config.yml that disables blank issues and surfaces
  the security-disclosure + docs links. The bug form asks for
  version, runtime, and logs up front so triage doesn't start with
  a round of "where is it running?".
- .github/pull_request_template.md — short checklist; nudges toward
  typecheck / lint / build before submit without being long enough
  to skip.
- .github/dependabot.yml — weekly npm + github-actions scans,
  grouped so Supabase / @types / dev-only patches batch into single
  PRs instead of six per week. Next / React / Tailwind / eslint-
  config-next are ignored so majors stay manual.
- .editorconfig — LF, UTF-8, 2 spaces, final newline, strip trailing
  whitespace (except in Markdown where trailing spaces are line
  breaks).
- .prettierrc — single quotes + trailing-comma es5, matches the
  plurality quote style in the codebase (336 single vs 236 double
  in imports). Tailwind plugin sorts class names.
- .prettierignore — node_modules, build output, lockfile, migrations.
- package.json adds "format" / "format:check" scripts and pins
  prettier + prettier-plugin-tailwindcss as devDeps.
- package-lock.json refreshed for the new devDeps.

Important: existing source files are NOT reformatted in this PR. 153
files would change if we ran `npm run format`, which would balloon
the diff and make review impossible. The reformat pass is a separate,
deliberate PR.

Typecheck clean; `npx prettier --check` on the new config files
passes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Arnas Donauskas 2026-04-20 21:16:21 +03:00
parent 1965075ea2
commit 3799c224d8
No known key found for this signature in database
12 changed files with 462 additions and 1 deletions

13
.editorconfig Normal file
View File

@ -0,0 +1,13 @@
root = true
[*]
charset = utf-8
end_of_line = lf
indent_style = space
indent_size = 2
insert_final_newline = true
trim_trailing_whitespace = true
[*.md]
# Markdown line breaks come from trailing spaces; don't strip them.
trim_trailing_whitespace = false

28
.github/CODE_OF_CONDUCT.md vendored Normal file
View File

@ -0,0 +1,28 @@
# Code of Conduct
This project adopts the **[Contributor Covenant, version 2.1][covenant]**.
By participating in this project — filing an issue, opening a PR, commenting
on one, or interacting in any other community space — you agree to uphold
that standard.
## Reporting
If you witness or experience behaviour that violates the Code, please
report it privately to the project maintainer:
- Email: **a.donauskas@hostinger.com** with `[WaCRM conduct]` in the
subject.
Reports are handled confidentially. Expect an acknowledgement within
72 hours and a decision on next steps within a week.
## Enforcement
The maintainer is responsible for enforcement and will apply the community
impact guidelines described in the [Contributor Covenant][covenant-enforce]
— ranging from a private correction to a permanent ban, proportional to the
behaviour.
[covenant]: https://www.contributor-covenant.org/version/2/1/code_of_conduct/
[covenant-enforce]: https://www.contributor-covenant.org/version/2/1/code_of_conduct/#enforcement-guidelines

76
.github/ISSUE_TEMPLATE/bug_report.yml vendored Normal file
View File

@ -0,0 +1,76 @@
name: Bug report
description: Something in WaCRM isn't working the way the docs say it should.
title: "[bug] "
labels: ["bug", "triage"]
body:
- type: markdown
attributes:
value: |
Thanks for reporting! The more specific you can be, the faster we
can land a fix.
**Not a bug in the code?** If this is a security issue, close this
form and follow [SECURITY.md](https://github.com/ArnasDon/wacrm/blob/main/.github/SECURITY.md)
instead.
- type: textarea
id: summary
attributes:
label: What happened?
description: One or two sentences describing the symptom.
placeholder: Clicking a conversation leaves the thread stuck on "No messages yet".
validations:
required: true
- type: textarea
id: steps
attributes:
label: Steps to reproduce
description: The minimum steps we need to trigger the bug on our side.
placeholder: |
1. Sign in, go to /inbox.
2. Click any conversation that has past messages.
3. Thread pane shows "No messages yet" until hard refresh.
validations:
required: true
- type: textarea
id: expected
attributes:
label: What did you expect?
placeholder: Messages load the first time, every time.
validations:
required: true
- type: input
id: version
attributes:
label: Commit / version
description: |
The commit SHA or release you're on. `git rev-parse --short HEAD`
in the fork works.
placeholder: "e.g. d6a4677 or v0.2.0"
validations:
required: false
- type: dropdown
id: runtime
attributes:
label: Where is it running?
options:
- Local dev (npm run dev)
- Hostinger Managed Node.js
- Hostinger VPS
- Vercel
- Other Node host
validations:
required: false
- type: textarea
id: logs
attributes:
label: Logs / screenshots
description: Server logs, browser console errors, network tab — anything that looks suspicious. Scrub tokens before pasting.
render: text
validations:
required: false

8
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@ -0,0 +1,8 @@
blank_issues_enabled: false
contact_links:
- name: Security vulnerability (private)
url: https://github.com/ArnasDon/wacrm/security/advisories/new
about: Do not file security issues in public. Follow the private disclosure flow.
- name: Setup / "how do I..." questions
url: https://github.com/ArnasDon/wacrm/blob/main/docs/README.md
about: Check the docs first — setup, deploy, troubleshooting are all covered.

View File

@ -0,0 +1,52 @@
name: Feature request
description: Propose a new feature or a meaningful enhancement.
title: "[feat] "
labels: ["enhancement", "triage"]
body:
- type: markdown
attributes:
value: |
Thanks for the idea. Features with a clear user story and a couple
of alternatives considered tend to move the fastest.
- type: textarea
id: problem
attributes:
label: What's the problem?
description: What are you trying to do today that WaCRM makes harder than it should?
placeholder: |
When a broadcast ends I have no way to see which recipients
didn't reply so I can follow up manually.
validations:
required: true
- type: textarea
id: proposal
attributes:
label: What would you like to see?
description: Describe the feature from the user's perspective, not the implementation.
placeholder: |
On the broadcast detail page, a "No reply" filter that lists
recipients who received but didn't reply within 24 hours.
validations:
required: true
- type: textarea
id: alternatives
attributes:
label: Alternatives you considered
description: Things that kinda work today, workarounds, related features in other tools.
validations:
required: false
- type: dropdown
id: scope
attributes:
label: Scope
description: Your guess — we'll re-scope if needed.
options:
- Small (a couple of hours)
- Medium (a couple of days)
- Large (a couple of weeks, probably breaks into multiple PRs)
validations:
required: false

53
.github/dependabot.yml vendored Normal file
View File

@ -0,0 +1,53 @@
version: 2
updates:
# Runtime + dev dependencies. Weekly on Mondays — keeps the noise
# predictable and aligns with a normal review cycle.
- package-ecosystem: npm
directory: "/"
schedule:
interval: weekly
day: monday
open-pull-requests-limit: 5
reviewers:
- ArnasDon
labels:
- dependencies
groups:
# Batch related upgrades into one PR so we're not closing six
# independent Supabase-bumps per week.
supabase:
patterns:
- "@supabase/*"
types:
patterns:
- "@types/*"
update-types:
- minor
- patch
dev-dependencies:
dependency-type: development
update-types:
- minor
- patch
ignore:
# Next + React + Tailwind are pinned exactly on purpose. Let
# them flow through manual major bumps when we're ready.
- dependency-name: next
- dependency-name: react
- dependency-name: react-dom
- dependency-name: tailwindcss
- dependency-name: eslint-config-next
# GitHub Actions in .github/workflows/. Catches setup-node /
# checkout version bumps that keep the CI matrix healthy.
- package-ecosystem: github-actions
directory: "/"
schedule:
interval: weekly
day: monday
open-pull-requests-limit: 3
reviewers:
- ArnasDon
labels:
- dependencies
- github-actions

35
.github/pull_request_template.md vendored Normal file
View File

@ -0,0 +1,35 @@
<!--
Keep this short and specific. The commit message is where the "why"
lives; this is where the reviewer gets the "what" and "how to try it".
-->
## Summary
<!-- One or two sentences. What does this PR do? -->
## What changed
<!-- Bullet list of the actual changes. Link file paths when useful. -->
## Test plan
<!--
How did you verify this works? How should the reviewer verify it?
Tick the boxes as you go.
-->
- [ ] `npm run typecheck` clean.
- [ ] `npm run lint` — no new errors beyond the pre-existing backlog.
- [ ] `npm run build` succeeds.
- [ ] Feature / fix manually exercised in the browser (or the reason it can't be).
## Related
<!-- Link the issue this closes, or "Part of #N" for multi-PR work. -->
<!--
Heads up:
- Security issues: do not disclose here; see .github/SECURITY.md.
- New deps: please justify briefly in the commit message or PR body.
- Runtime behaviour changes affecting forkers: update docs/*.
-->

9
.prettierignore Normal file
View File

@ -0,0 +1,9 @@
node_modules
.next
out
build
coverage
next-env.d.ts
package-lock.json
# Generated / vendored
supabase/migrations

10
.prettierrc Normal file
View File

@ -0,0 +1,10 @@
{
"semi": true,
"singleQuote": true,
"trailingComma": "es5",
"printWidth": 80,
"tabWidth": 2,
"arrowParens": "always",
"endOfLine": "lf",
"plugins": ["prettier-plugin-tailwindcss"]
}

76
CONTRIBUTING.md Normal file
View File

@ -0,0 +1,76 @@
# Contributing to WaCRM
Thanks for the interest. This document is the short version; anything not
answered here, open a draft PR or an issue and we'll figure it out together.
## Before you start
- **Security issues do not belong in public issues** — see
[SECURITY.md](./.github/SECURITY.md) for the private disclosure flow.
- For anything non-trivial, open an issue first so we can agree on the
approach before you write the code. Small fixes and typo-level PRs can
skip this step.
## Dev loop
```bash
git clone https://github.com/<your-fork>/wacrm.git
cd wacrm
cp .env.local.example .env.local # fill in your Supabase + Meta creds
npm install
npm run dev
```
Full setup (Supabase migrations, WhatsApp Business API, deploy) lives in
[`docs/`](./docs/README.md).
### Scripts you'll use
| Command | What it does |
| --- | --- |
| `npm run dev` | Turbopack dev server on port 3000. |
| `npm run build` | Production build. Next also runs its own typecheck here. |
| `npm run typecheck` | `tsc --noEmit`. Fast TS-only pass. |
| `npm run lint` | ESLint. |
| `npm run format` | Prettier write. Run before committing. |
CI on every PR runs lint (non-blocking today), typecheck, and build.
## PR style
- **One logical change per PR.** A bug fix and a refactor in the same PR
makes review harder and rollback riskier.
- Branch off the latest `main`. Don't push new commits to a merged branch —
they end up orphaned.
- Commit messages: first line is a short, imperative summary (`fix(inbox):
drop messages on URL change`). Body explains the *why*; the diff shows the
*what*.
- Run `npm run typecheck` and `npm run format` locally before opening the
PR — saves a round trip on CI.
- Fill in the [pull-request template](./.github/pull_request_template.md). A
"Test plan" section the reviewer can actually tick off goes a long way.
- Update relevant docs in [`docs/`](./docs/README.md) when you change
behaviour a forker needs to know about.
## Code style
- TypeScript, strict. No `any` unless there's a good reason + a comment.
- Prefer server components; mark client components with `"use client"` only
when they genuinely need interactivity, state, or browser APIs.
- `@/` alias for every internal import. Relative imports are used only
inside the same subfolder.
- No new dependencies without a note in the PR body explaining why; we try
to keep the install lean.
## Review process
- @ArnasDon is the sole code owner today (see
[.github/CODEOWNERS](./.github/CODEOWNERS)) and reviews every PR.
- Expect a response within a few days. Friendly ping after a week.
- Reviews are collaborative — "this looks wrong" means "let's talk about
it", not "we're not merging this".
## Licensing
By contributing, you agree your contribution is licensed under the
[MIT License](./LICENSE), the same license as the rest of the project.

97
package-lock.json generated
View File

@ -35,6 +35,8 @@
"@types/react-dom": "^19", "@types/react-dom": "^19",
"eslint": "^9", "eslint": "^9",
"eslint-config-next": "16.2.4", "eslint-config-next": "16.2.4",
"prettier": "^3.8.3",
"prettier-plugin-tailwindcss": "^0.7.2",
"tailwindcss": "^4", "tailwindcss": "^4",
"typescript": "^5" "typescript": "^5"
}, },
@ -7939,6 +7941,101 @@
"node": ">= 0.8.0" "node": ">= 0.8.0"
} }
}, },
"node_modules/prettier": {
"version": "3.8.3",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.3.tgz",
"integrity": "sha512-7igPTM53cGHMW8xWuVTydi2KO233VFiTNyF5hLJqpilHfmn8C8gPf+PS7dUT64YcXFbiMGZxS9pCSxL/Dxm/Jw==",
"dev": true,
"license": "MIT",
"bin": {
"prettier": "bin/prettier.cjs"
},
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/prettier/prettier?sponsor=1"
}
},
"node_modules/prettier-plugin-tailwindcss": {
"version": "0.7.2",
"resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.7.2.tgz",
"integrity": "sha512-LkphyK3Fw+q2HdMOoiEHWf93fNtYJwfamoKPl7UwtjFQdei/iIBoX11G6j706FzN3ymX9mPVi97qIY8328vdnA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=20.19"
},
"peerDependencies": {
"@ianvs/prettier-plugin-sort-imports": "*",
"@prettier/plugin-hermes": "*",
"@prettier/plugin-oxc": "*",
"@prettier/plugin-pug": "*",
"@shopify/prettier-plugin-liquid": "*",
"@trivago/prettier-plugin-sort-imports": "*",
"@zackad/prettier-plugin-twig": "*",
"prettier": "^3.0",
"prettier-plugin-astro": "*",
"prettier-plugin-css-order": "*",
"prettier-plugin-jsdoc": "*",
"prettier-plugin-marko": "*",
"prettier-plugin-multiline-arrays": "*",
"prettier-plugin-organize-attributes": "*",
"prettier-plugin-organize-imports": "*",
"prettier-plugin-sort-imports": "*",
"prettier-plugin-svelte": "*"
},
"peerDependenciesMeta": {
"@ianvs/prettier-plugin-sort-imports": {
"optional": true
},
"@prettier/plugin-hermes": {
"optional": true
},
"@prettier/plugin-oxc": {
"optional": true
},
"@prettier/plugin-pug": {
"optional": true
},
"@shopify/prettier-plugin-liquid": {
"optional": true
},
"@trivago/prettier-plugin-sort-imports": {
"optional": true
},
"@zackad/prettier-plugin-twig": {
"optional": true
},
"prettier-plugin-astro": {
"optional": true
},
"prettier-plugin-css-order": {
"optional": true
},
"prettier-plugin-jsdoc": {
"optional": true
},
"prettier-plugin-marko": {
"optional": true
},
"prettier-plugin-multiline-arrays": {
"optional": true
},
"prettier-plugin-organize-attributes": {
"optional": true
},
"prettier-plugin-organize-imports": {
"optional": true
},
"prettier-plugin-sort-imports": {
"optional": true
},
"prettier-plugin-svelte": {
"optional": true
}
}
},
"node_modules/pretty-ms": { "node_modules/pretty-ms": {
"version": "9.3.0", "version": "9.3.0",
"resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-9.3.0.tgz", "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-9.3.0.tgz",

View File

@ -32,7 +32,9 @@
"build": "next build", "build": "next build",
"start": "next start", "start": "next start",
"lint": "eslint", "lint": "eslint",
"typecheck": "tsc --noEmit" "typecheck": "tsc --noEmit",
"format": "prettier --write .",
"format:check": "prettier --check ."
}, },
"dependencies": { "dependencies": {
"@base-ui/react": "^1.4.0", "@base-ui/react": "^1.4.0",
@ -61,6 +63,8 @@
"@types/react-dom": "^19", "@types/react-dom": "^19",
"eslint": "^9", "eslint": "^9",
"eslint-config-next": "16.2.4", "eslint-config-next": "16.2.4",
"prettier": "^3.8.3",
"prettier-plugin-tailwindcss": "^0.7.2",
"tailwindcss": "^4", "tailwindcss": "^4",
"typescript": "^5" "typescript": "^5"
} }