diff --git a/.env.example b/.env.example index 959a0e7..4bb6db7 100644 --- a/.env.example +++ b/.env.example @@ -1,3 +1,4 @@ NEXT_PUBLIC_SUPABASE_URL=http://127.0.0.1:54321 NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY=replace-with-publishable-key NEXT_PUBLIC_SITE_URL=http://localhost:3000 +LOG_LEVEL=debug diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..a1b1156 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,43 @@ +# Code ownership for the Flack codebase. +# Each line maps a path pattern to one or more owners who are +# automatically requested for review on matching pull requests. +# Syntax: https://docs.github.com/articles/about-code-owners +# Later matching rules take precedence over earlier ones. + +# Default owner for everything not matched below. +* @factory-sam + +# Application code (Next.js App Router + React UI). +/src/ @factory-sam +/src/app/ @factory-sam +/src/components/ @factory-sam +/src/features/ @factory-sam + +# Auth, session, and Supabase access layer (security-sensitive). +/src/proxy.ts @factory-sam +/src/app/auth/ @factory-sam +/src/features/auth/ @factory-sam +/src/lib/supabase/ @factory-sam + +# Observability surface (logger, health checks). +/src/lib/logger.ts @factory-sam +/src/lib/health.ts @factory-sam +/src/app/health/ @factory-sam + +# Database schema, RLS policies, and migrations (high blast radius). +/supabase/ @factory-sam + +# CI/CD, repo automation, and tooling configuration. +/.github/ @factory-sam +/scripts/ @factory-sam +/eslint.config.mjs @factory-sam +/vitest.config.ts @factory-sam +/playwright.config.ts @factory-sam +/next.config.ts @factory-sam +/knip.json @factory-sam +/.jscpd.json @factory-sam + +# Project documentation and agent guidance. +/README.md @factory-sam +/AGENTS.md @factory-sam +/.factory/ @factory-sam diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000..09c7dfa --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,78 @@ +name: Bug report +description: Report something in Flack that is broken or behaving unexpectedly. +title: "[Bug]: " +labels: ["type: bug", "priority: p2-medium"] +body: + - type: markdown + attributes: + value: | + Thanks for taking the time to file a bug. Please fill out the sections below so the issue is reproducible and actionable for both humans and AI agents. + - type: textarea + id: summary + attributes: + label: Summary + description: A clear and concise description of the bug. + placeholder: Messages sent while offline are duplicated when the connection is restored. + validations: + required: true + - type: dropdown + id: area + attributes: + label: Affected area + description: Which part of the codebase is impacted? + options: + - auth (login/signup/invite/session) + - chat (workspace, channels) + - messages (send/edit/optimistic updates) + - realtime (Supabase subscriptions) + - supabase (schema, RLS, migrations) + - observability (logging, health) + - build/tooling/CI + - other + validations: + required: true + - type: textarea + id: reproduction + attributes: + label: Steps to reproduce + description: Numbered steps that reliably reproduce the issue. + value: | + 1. + 2. + 3. + validations: + required: true + - type: textarea + id: expected + attributes: + label: Expected behavior + description: What did you expect to happen? + validations: + required: true + - type: textarea + id: actual + attributes: + label: Actual behavior + description: What actually happened? Include error messages, screenshots, or `/health` output if relevant. + validations: + required: true + - type: textarea + id: environment + attributes: + label: Environment + description: Browser, OS, deployment (local/Vercel preview/production), and relevant commit SHA. + value: | + - Environment: (local / preview / production) + - Browser/OS: + - Commit SHA: + validations: + required: false + - type: checkboxes + id: checks + attributes: + label: Pre-submission checklist + options: + - label: I searched existing issues and this is not a duplicate. + required: true + - label: I can reproduce this on the latest `main`. + required: false diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..fa996cc --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,8 @@ +blank_issues_enabled: false +contact_links: + - name: Setup and contribution questions + url: https://github.com/factory-sam/flack/blob/main/AGENTS.md + about: Read AGENTS.md for commands, conventions, architecture, and the local Supabase workflow before opening an issue. + - name: Security report + url: https://github.com/factory-sam/flack/security/advisories/new + about: Please report suspected security vulnerabilities privately rather than via a public issue. diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 0000000..f90c72b --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,64 @@ +name: Feature request +description: Propose a new capability or enhancement for Flack. +title: "[Feature]: " +labels: ["type: feature", "priority: p3-low"] +body: + - type: markdown + attributes: + value: | + Describe the problem you want solved and your proposed solution. Clear, scoped requests are easier for both maintainers and AI agents to implement. + - type: textarea + id: problem + attributes: + label: Problem statement + description: What user or developer problem does this solve? Why now? + placeholder: Users cannot tell which messages failed to send after a network drop. + validations: + required: true + - type: textarea + id: proposal + attributes: + label: Proposed solution + description: Describe the behavior you would like. Include UI/UX or API notes where relevant. + validations: + required: true + - type: dropdown + id: area + attributes: + label: Affected area + description: Which part of the codebase would this touch? + options: + - auth (login/signup/invite/session) + - chat (workspace, channels) + - messages (send/edit/optimistic updates) + - realtime (Supabase subscriptions) + - supabase (schema, RLS, migrations) + - observability (logging, health) + - build/tooling/CI + - other + validations: + required: true + - type: textarea + id: alternatives + attributes: + label: Alternatives considered + description: Other approaches you evaluated and why you discarded them. + validations: + required: false + - type: textarea + id: acceptance + attributes: + label: Acceptance criteria + description: Concrete, testable conditions that define "done". + value: | + - [ ] + - [ ] + validations: + required: false + - type: checkboxes + id: checks + attributes: + label: Pre-submission checklist + options: + - label: I searched existing issues and this is not a duplicate. + required: true diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 1502437..a0a4928 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -1,15 +1,19 @@ ## Design Context ### Users + Flack is for one organization with power users who live in chat all day: founders, operators, engineers, sales, support, and leadership. They need channel conversation, direct messages, threads, mentions, file sharing, search, and keyboard-driven workflows that feel immediate under production pressure. ### Brand Personality + Technical, minimal, fast, and precise. The interface should feel like a professional work surface, not a branded destination: quiet, exacting, trustworthy, and optimized for repeated use. ### Aesthetic Direction + Dark-mode-first with a Linear-adjacent power-user feel, blended with a dense terminal workspace, an issue tracker, and a restrained enterprise command center. Use flat tinted near-black planes, 4-6px radii, hairline borders, compact rows, small typography, and minimal color. Avoid decorative gradients, radial glow, glass blur, pill overload, bubbly cards, cute empty-state copy, oversized avatars, and anything that reads as an AI dashboard or playful Slack clone. ### Design Principles + - Optimize for speed perception: optimistic updates, immediate feedback, and no decorative motion. - Keep density high but legible with tight grouping, stable alignment, and clear hierarchy. - Make keyboard use first-class with command search, shortcuts, visible focus states, and AA contrast. diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..286b241 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,54 @@ + + +## Description + + + +## Related issue + + + +Closes # + +## Type of change + +- [ ] Bug fix (non-breaking change that fixes an issue) +- [ ] Feature (non-breaking change that adds functionality) +- [ ] Breaking change (fix or feature that changes existing behavior) +- [ ] Refactor / tech debt (no functional change) +- [ ] Docs / tooling / CI + +## Affected area + +- [ ] auth (login/signup/invite/session) +- [ ] chat (workspace, channels) +- [ ] messages (send/edit/optimistic updates) +- [ ] realtime (Supabase subscriptions) +- [ ] supabase (schema, RLS, migrations) +- [ ] observability (logging, health) +- [ ] build / tooling / CI + +## Testing done + + + +- [ ] `pnpm lint` +- [ ] `pnpm typecheck` +- [ ] `pnpm test` +- [ ] `pnpm test:e2e` (if UI/routing changed) +- [ ] Manual verification (describe below) + + + +## Database / migrations + + + +## Checklist + +- [ ] My changes follow the conventions in `AGENTS.md`. +- [ ] I updated documentation (README/AGENTS.md) where relevant. +- [ ] No secrets, keys, or `.env` values are included in this PR. diff --git a/.github/workflows/code-quality.yml b/.github/workflows/code-quality.yml new file mode 100644 index 0000000..6079a4a --- /dev/null +++ b/.github/workflows/code-quality.yml @@ -0,0 +1,61 @@ +name: Code Quality + +on: + push: + branches: [main] + pull_request: + +jobs: + quality: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: pnpm/action-setup@v4 + with: + version: 11.5.0 + + - uses: actions/setup-node@v4 + with: + node-version: 22 + cache: pnpm + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Lint (includes complexity, max-lines, naming) + run: pnpm lint + + - name: Type check + run: pnpm typecheck + + - name: Unit tests (coverage thresholds + JUnit timing report) + run: pnpm test:ci + + - name: Upload test report (timing + flaky detection) + if: ${{ !cancelled() }} + uses: actions/upload-artifact@v4 + with: + name: test-report + path: reports/junit.xml + if-no-files-found: warn + + - name: Upload coverage report + if: ${{ !cancelled() }} + uses: actions/upload-artifact@v4 + with: + name: coverage + path: coverage/ + if-no-files-found: warn + + - name: Dead code and unused dependencies (knip) + run: pnpm knip + + - name: Duplicate code (jscpd) + run: pnpm duplication + + - name: Technical debt markers + run: pnpm tech-debt + + - name: Validate docs (AGENTS.md/README commands + links) + run: pnpm validate-docs diff --git a/.gitignore b/.gitignore index 53e2dea..50f239a 100644 --- a/.gitignore +++ b/.gitignore @@ -4,5 +4,9 @@ node_modules/ .env.local .env.*.local coverage/ +reports/ .DS_Store *.tsbuildinfo +/test-results/ +/playwright-report/ +/playwright/.cache/ diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100755 index 0000000..60b1ca9 --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1 @@ +pnpm precommit diff --git a/.impeccable.md b/.impeccable.md index 1502437..a0a4928 100644 --- a/.impeccable.md +++ b/.impeccable.md @@ -1,15 +1,19 @@ ## Design Context ### Users + Flack is for one organization with power users who live in chat all day: founders, operators, engineers, sales, support, and leadership. They need channel conversation, direct messages, threads, mentions, file sharing, search, and keyboard-driven workflows that feel immediate under production pressure. ### Brand Personality + Technical, minimal, fast, and precise. The interface should feel like a professional work surface, not a branded destination: quiet, exacting, trustworthy, and optimized for repeated use. ### Aesthetic Direction + Dark-mode-first with a Linear-adjacent power-user feel, blended with a dense terminal workspace, an issue tracker, and a restrained enterprise command center. Use flat tinted near-black planes, 4-6px radii, hairline borders, compact rows, small typography, and minimal color. Avoid decorative gradients, radial glow, glass blur, pill overload, bubbly cards, cute empty-state copy, oversized avatars, and anything that reads as an AI dashboard or playful Slack clone. ### Design Principles + - Optimize for speed perception: optimistic updates, immediate feedback, and no decorative motion. - Keep density high but legible with tight grouping, stable alignment, and clear hierarchy. - Make keyboard use first-class with command search, shortcuts, visible focus states, and AA contrast. diff --git a/.jscpd.json b/.jscpd.json new file mode 100644 index 0000000..a6d4faf --- /dev/null +++ b/.jscpd.json @@ -0,0 +1,10 @@ +{ + "threshold": 3, + "minLines": 8, + "minTokens": 60, + "reporters": ["console"], + "absolute": true, + "gitignore": true, + "path": ["src"], + "ignore": ["**/*.test.ts", "**/*.test.tsx", "**/*.d.ts"] +} diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..3ca6f5b --- /dev/null +++ b/.prettierignore @@ -0,0 +1,6 @@ +.next/ +node_modules/ +coverage/ +pnpm-lock.yaml +tsconfig.tsbuildinfo +screenshots/ diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 0000000..b6ee3b8 --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,6 @@ +{ + "printWidth": 120, + "semi": true, + "singleQuote": false, + "trailingComma": "none" +} diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..6e43498 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,100 @@ +# AGENTS.md + +Guidance for humans and AI agents working in the Flack codebase. Flack is a single-organization, real-time team chat app built on Next.js 16 (App Router, Turbopack, React Compiler) + React 19.2 + Supabase. For product/setup overview see [README.md](./README.md); for visual and UX intent see [.impeccable.md](./.impeccable.md) and [.github/copilot-instructions.md](./.github/copilot-instructions.md). + +## Setup + +```bash +pnpm install # install deps (pnpm is required; version pinned via devEngines) +supabase start # boot local Postgres/Auth/Realtime/Storage (applies migrations + seed) +cp .env.example .env.local # then fill values printed by `supabase start` +pnpm dev # start the dev server at http://localhost:3000 +``` + +Requires Node 22+, pnpm 11.5.0, the Supabase CLI, and Docker. + +## Commands + +| Task | Command | +| --------------- | ---------------------------------------------------- | +| Dev server | `pnpm dev` | +| Build | `pnpm build` | +| Lint | `pnpm lint` | +| Type-check | `pnpm typecheck` | +| Format | `pnpm format` (write) / `pnpm format:check` (verify) | +| Test | `pnpm test` | +| Test + coverage | `pnpm test:coverage` | +| Dead code/deps | `pnpm knip` | +| Duplication | `pnpm duplication` (jscpd) | +| Tech debt scan | `pnpm tech-debt` | +| Validate docs | `pnpm validate-docs` | +| Bundle analyze | `pnpm analyze` | +| Reset local DB | `supabase db reset` | + +**Before committing or finishing a task, run:** `pnpm lint && pnpm typecheck && pnpm test`. The Husky `pre-commit` hook enforces `lint-staged` (Prettier check + ESLint with `--max-warnings=0`), `pnpm typecheck`, and `pnpm tech-debt`, so commits fail on any lint warning, format drift, type error, or untracked TODO marker. The `Code Quality` GitHub Actions workflow (`.github/workflows/code-quality.yml`) additionally runs `knip`, `jscpd`, and the tech-debt scan on every push and PR. + +## Conventions + +- **Language:** TypeScript in strict mode. Do not introduce `any`; prefer precise types. JS files are not allowed (`allowJs: false`). +- **Imports:** Use the `@/*` path alias for everything under `src/` (e.g. `@/lib/supabase/server`). Do not use deep relative paths across feature boundaries. +- **Formatting (Prettier):** 120 char width, semicolons, double quotes, no trailing commas. Never hand-format; run `pnpm format`. +- **Linting:** ESLint flat config extending `next/core-web-vitals` and `next/typescript`. Code must pass with zero warnings. +- **Components:** Use shadcn/ui primitives in `src/components/ui` and the `cn()` helper from `@/lib/utils` for class merging. Match the existing new-york shadcn style; icons come from `lucide-react`. +- **Naming:** Files are kebab-case (`login-form.tsx`, `chat-workspace.tsx`). React components are PascalCase; functions/variables are camelCase; types are PascalCase. These identifier conventions are enforced by the `@typescript-eslint/naming-convention` rule in `eslint.config.mjs`. Object/type property keys may be `snake_case` to mirror the Supabase schema (e.g. `org_id`, `channel_id`); UPPER_CASE is allowed for constants. +- **Comments:** Keep code self-documenting. Add a comment only for a non-obvious constraint or workaround. +- **Complexity:** ESLint enforces `complexity: ["error", 20]` (ESLint's default ceiling) on all `.ts`/`.tsx` files. Keep cyclomatic complexity per function at or below 20; split branchy render trees into focused subcomponents and extract pure helpers rather than growing a single function. +- **File size:** ESLint enforces `max-lines` (600 code lines, blank/comment lines excluded). Split large modules: presentational chat subcomponents live in `src/features/chat/chat-parts.tsx`, the container logic in `chat-workspace.tsx`. +- **Code quality tooling:** `knip` detects unused files, exports, and dependencies; `jscpd` flags copy-paste duplication (fails over 3%); `scripts/scan-tech-debt.mjs` requires every `TODO`/`FIXME`/`HACK`/`XXX` to reference a tracked issue (e.g. `TODO(ABC-123)`, `FIXME #45`, or an issue URL); `@next/bundle-analyzer` (`pnpm analyze`) reports bundle/dependency size (it runs the Webpack builder via `next build --webpack`, since Turbopack is the default build and the analyzer hooks Webpack); `scripts/validate-docs.mjs` (`pnpm validate-docs`) keeps this file and `README.md` honest by failing if a documented `pnpm