From 3799c224d8d574de339c7ff48b656f8be9cfb5f5 Mon Sep 17 00:00:00 2001 From: Arnas Donauskas Date: Mon, 20 Apr 2026 21:16:21 +0300 Subject: [PATCH] =?UTF-8?q?chore:=20contributor=20experience=20=E2=80=94?= =?UTF-8?q?=20CoC,=20templates,=20Dependabot,=20editor=20configs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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) --- .editorconfig | 13 +++ .github/CODE_OF_CONDUCT.md | 28 +++++++ .github/ISSUE_TEMPLATE/bug_report.yml | 76 +++++++++++++++++ .github/ISSUE_TEMPLATE/config.yml | 8 ++ .github/ISSUE_TEMPLATE/feature_request.yml | 52 ++++++++++++ .github/dependabot.yml | 53 ++++++++++++ .github/pull_request_template.md | 35 ++++++++ .prettierignore | 9 ++ .prettierrc | 10 +++ CONTRIBUTING.md | 76 +++++++++++++++++ package-lock.json | 97 ++++++++++++++++++++++ package.json | 6 +- 12 files changed, 462 insertions(+), 1 deletion(-) create mode 100644 .editorconfig create mode 100644 .github/CODE_OF_CONDUCT.md create mode 100644 .github/ISSUE_TEMPLATE/bug_report.yml create mode 100644 .github/ISSUE_TEMPLATE/config.yml create mode 100644 .github/ISSUE_TEMPLATE/feature_request.yml create mode 100644 .github/dependabot.yml create mode 100644 .github/pull_request_template.md create mode 100644 .prettierignore create mode 100644 .prettierrc create mode 100644 CONTRIBUTING.md diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..d23bfb6 --- /dev/null +++ b/.editorconfig @@ -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 diff --git a/.github/CODE_OF_CONDUCT.md b/.github/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..a3427b1 --- /dev/null +++ b/.github/CODE_OF_CONDUCT.md @@ -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 diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000..82ed93d --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -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 diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..7c38ac2 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -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. diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 0000000..b5b843e --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -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 diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..6416ee5 --- /dev/null +++ b/.github/dependabot.yml @@ -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 diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..a01bb9e --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,35 @@ + + +## Summary + + + +## What changed + + + +## Test plan + + + +- [ ] `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 + + + + diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..1b713ae --- /dev/null +++ b/.prettierignore @@ -0,0 +1,9 @@ +node_modules +.next +out +build +coverage +next-env.d.ts +package-lock.json +# Generated / vendored +supabase/migrations diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..c03564e --- /dev/null +++ b/.prettierrc @@ -0,0 +1,10 @@ +{ + "semi": true, + "singleQuote": true, + "trailingComma": "es5", + "printWidth": 80, + "tabWidth": 2, + "arrowParens": "always", + "endOfLine": "lf", + "plugins": ["prettier-plugin-tailwindcss"] +} diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..ba4b5ab --- /dev/null +++ b/CONTRIBUTING.md @@ -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//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. diff --git a/package-lock.json b/package-lock.json index 04bc56f..721299c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -35,6 +35,8 @@ "@types/react-dom": "^19", "eslint": "^9", "eslint-config-next": "16.2.4", + "prettier": "^3.8.3", + "prettier-plugin-tailwindcss": "^0.7.2", "tailwindcss": "^4", "typescript": "^5" }, @@ -7939,6 +7941,101 @@ "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": { "version": "9.3.0", "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-9.3.0.tgz", diff --git a/package.json b/package.json index df41fb2..a742e06 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,9 @@ "build": "next build", "start": "next start", "lint": "eslint", - "typecheck": "tsc --noEmit" + "typecheck": "tsc --noEmit", + "format": "prettier --write .", + "format:check": "prettier --check ." }, "dependencies": { "@base-ui/react": "^1.4.0", @@ -61,6 +63,8 @@ "@types/react-dom": "^19", "eslint": "^9", "eslint-config-next": "16.2.4", + "prettier": "^3.8.3", + "prettier-plugin-tailwindcss": "^0.7.2", "tailwindcss": "^4", "typescript": "^5" }