From 385b61f29ba54fe5e0c398c899fa0b18e2f15c5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Enes=20K=C3=B6ksal?= <182091242+koksalenes@users.noreply.github.com> Date: Fri, 17 Apr 2026 22:54:05 +0300 Subject: [PATCH] chore: add husky, commitlint, lint-staged, editorconfig and prettier --- .editorconfig | 32 +++++++++++ .husky/commit-msg | 1 + .husky/pre-commit | 1 + .prettierrc | 13 +++++ commitlint.config.js | 133 +++++++++++++++++++++++++++++++++++++++++++ package.json | 17 ++++++ 6 files changed, 197 insertions(+) create mode 100644 .editorconfig create mode 100644 .husky/commit-msg create mode 100644 .husky/pre-commit create mode 100644 .prettierrc create mode 100644 commitlint.config.js diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..1f7580f --- /dev/null +++ b/.editorconfig @@ -0,0 +1,32 @@ +# EditorConfig — https://editorconfig.org + +root = true + +# All files +[*] +indent_style = space +indent_size = 2 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +# Markdown +[*.md] +trim_trailing_whitespace = false + +# YAML +[*.{yml,yaml}] +indent_size = 2 + +# JSON +[*.json] +indent_size = 2 + +# SQL +[*.sql] +indent_size = 4 + +# Shell scripts +[*.sh] +indent_size = 4 diff --git a/.husky/commit-msg b/.husky/commit-msg new file mode 100644 index 0000000..0ee8c65 --- /dev/null +++ b/.husky/commit-msg @@ -0,0 +1 @@ +bunx --bun commitlint --edit "$1" diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100644 index 0000000..f2d66f6 --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1 @@ +bun run lint-staged diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..075c59e --- /dev/null +++ b/.prettierrc @@ -0,0 +1,13 @@ +{ + "semi": true, + "singleQuote": false, + "tabWidth": 2, + "useTabs": false, + "trailingComma": "es5", + "printWidth": 100, + "bracketSpacing": true, + "bracketSameLine": false, + "arrowParens": "always", + "endOfLine": "lf", + "plugins": [] +} diff --git a/commitlint.config.js b/commitlint.config.js new file mode 100644 index 0000000..38bf623 --- /dev/null +++ b/commitlint.config.js @@ -0,0 +1,133 @@ +// commitlint.config.js +// Conventional Commits — https://www.conventionalcommits.org/en/v1.0.0/ +// +// FORMAT: +// (): +// +// [optional body] +// +// [optional footer(s)] +// +// EXAMPLES: +// feat(auth): add OAuth2 login with GitHub +// fix(video): resolve HLS buffering on mobile Safari +// docs: update self-hosting guide in README +// chore(deps): bump next from 16.1 to 16.2 +// refactor(api): extract pagination helper into lib/utils +// perf(db): add index on Project.createdAt for dashboard query +// ci: configure GitHub Actions matrix for Node 20 and 22 +// revert: revert "feat(billing): add yearly plan toggle" + +/** @type {import('@commitlint/types').UserConfig} */ +const config = { + extends: ["@commitlint/config-conventional"], + + // ── Rules ────────────────────────────────────────────────────────────────── + // Each rule is [severity, applicable, value] + // severity 0 = off, 1 = warn, 2 = error + // applicable 'always' | 'never' + rules: { + // ── Type ──────────────────────────────────────────────────────────────── + + // Must be lowercase (e.g. "feat" not "Feat") + "type-case": [2, "always", "lower-case"], + + // Must not be empty + "type-empty": [2, "never"], + + // Allowed commit types + "type-enum": [ + 2, + "always", + [ + "feat", // ✨ New feature or user-facing capability + "fix", // 🐛 Bug fix + "docs", // 📝 Documentation only (README, comments, JSDoc) + "style", // 💄 Formatting, whitespace — no logic change + "refactor", // ♻️ Code restructure — no new feature, no bug fix + "perf", // ⚡️ Performance improvement + "test", // 🧪 Adding or correcting tests + "build", // 🏗️ Build system, bundler, or external dependencies + "ci", // 👷 CI/CD pipeline changes (GitHub Actions, Docker, etc.) + "chore", // 🔧 Maintenance tasks not fitting other types + "revert", // ⏪ Reverts a previous commit + "security", // 🔒 Security fix or hardening (not in base config) + "i18n", // 🌐 Internationalisation / translation (not in base) + "dx", // 🛠️ Developer experience (tooling, scripts, configs) + ], + ], + + // ── Scope ─────────────────────────────────────────────────────────────── + + // Scope must be lowercase when provided (e.g. "auth" not "Auth") + "scope-case": [2, "always", "lower-case"], + + // Scope is optional — no rule enforced for "scope-empty" + // Suggested scopes (not enforced): + // auth, api, db, video, billing, admin, ci, deps, ui, email, + // invitations, workspace, project, storage, notifications, onboarding + + // ── Subject (short description) ───────────────────────────────────────── + + // Must not be empty + "subject-empty": [2, "never"], + + // Must NOT start with an uppercase letter + // Good: "add retry logic for upload" + // Bad: "Add retry logic for upload" + "subject-case": [2, "never", ["sentence-case", "start-case", "pascal-case", "upper-case"]], + + // Must NOT end with a period + "subject-full-stop": [2, "never", "."], + + // Max 100 chars for the subject line (type + scope + description) + "header-max-length": [2, "always", 100], + + // Min 10 chars to prevent meaningless one-word subjects + "subject-min-length": [2, "always", 10], + + // ── Body ──────────────────────────────────────────────────────────────── + + // Body lines should be wrapped at 120 chars + "body-max-line-length": [2, "always", 120], + + // Blank line required between subject and body + "body-leading-blank": [2, "always"], + + // ── Footer ────────────────────────────────────────────────────────────── + + // Blank line required between body and footer + "footer-leading-blank": [1, "always"], + + // Footer lines should be wrapped at 120 chars + "footer-max-line-length": [2, "always", 120], + }, + + // ── Prompt (interactive `bun run commit`) ────────────────────────────────── + // Shown when using @commitlint/prompt-cli or czg + prompt: { + questions: { + type: { + description: "Select the type of change you are committing", + enum: { + feat: { description: "A new feature", title: "Features", emoji: "✨" }, + fix: { description: "A bug fix", title: "Bug Fixes", emoji: "🐛" }, + docs: { description: "Documentation only changes", title: "Documentation", emoji: "📝" }, + style: { description: "Formatting, missing semicolons, etc.", title: "Styles", emoji: "💄" }, + refactor: { description: "A code change without feature or fix", title: "Refactors", emoji: "♻️" }, + perf: { description: "A performance improvement", title: "Performance", emoji: "⚡️" }, + test: { description: "Adding or correcting tests", title: "Tests", emoji: "🧪" }, + build: { description: "Build system or dependency changes", title: "Builds", emoji: "🏗️" }, + ci: { description: "CI/CD configuration changes", title: "CI", emoji: "👷" }, + chore: { description: "Other changes (tooling, maintenance)", title: "Chores", emoji: "🔧" }, + revert: { description: "Reverts a previous commit", title: "Reverts", emoji: "⏪" }, + security: { description: "A security fix or hardening", title: "Security", emoji: "🔒" }, + i18n: { description: "Internationalisation / translation", title: "i18n", emoji: "🌐" }, + dx: { description: "Developer experience improvements", title: "DX", emoji: "🛠️" }, + }, + }, + }, + }, +}; + +export default config; diff --git a/package.json b/package.json index e7c766c..07fe2dd 100644 --- a/package.json +++ b/package.json @@ -9,8 +9,11 @@ "start": "next start", "start:docker": "sh ./scripts/docker-entrypoint.sh", "lint": "eslint --max-warnings=0", + "format": "prettier --write .", + "format:check": "prettier --check .", "typecheck": "tsc --noEmit", "check": "bun run lint && bun run typecheck", + "prepare": "husky", "postinstall": "prisma generate", "db:generate": "prisma generate", "db:push": "prisma db push", @@ -62,10 +65,24 @@ "@types/react-dom": "^19", "eslint": "^9", "eslint-config-next": "16.1.6", + "@commitlint/cli": "^19.8.1", + "@commitlint/config-conventional": "^19.8.1", + "husky": "^9.1.7", + "lint-staged": "^15.5.1", + "prettier": "^3.5.3", "shadcn": "^3.8.3", "tailwindcss": "^4", "typescript": "^5" }, + "lint-staged": { + "*.{js,jsx,ts,tsx}": [ + "eslint --max-warnings=0 --fix", + "prettier --write" + ], + "*.{json,css,md,yml,yaml,mdx}": [ + "prettier --write" + ] + }, "ignoreScripts": [ "sharp", "unrs-resolver"