From 082c0ecb118cde44278816f2ef11023d456f658e Mon Sep 17 00:00:00 2001 From: johnsmccain Date: Sun, 26 Jul 2026 14:35:10 +0100 Subject: [PATCH 1/2] ci: add stale assignment policy, PR auto-labeling, docs index, and funding config - Add stale-assignment workflow (#454) to reclaim abandoned issue assignments after 14 days - Add PR auto-labeler (#453) based on changed file paths using actions/labeler - Add docs/README.md index (#451) for documentation discoverability - Add .github/FUNDING.yml (#450) linking to Drips Wave funding page - Document stale assignment policy in CONTRIBUTING.md - Link docs index from main README.md --- .github/FUNDING.yml | 6 + .github/labeler.yml | 66 ++++++++++ .github/workflows/pr-labeler.yml | 26 ++++ .github/workflows/stale-assignments.yml | 155 ++++++++++++++++++++++++ CONTRIBUTING.md | 38 ++++++ README.md | 1 + docs/README.md | 35 ++++++ 7 files changed, 327 insertions(+) create mode 100644 .github/FUNDING.yml create mode 100644 .github/labeler.yml create mode 100644 .github/workflows/pr-labeler.yml create mode 100644 .github/workflows/stale-assignments.yml create mode 100644 docs/README.md diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..e25469f --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,6 @@ +# These organizations support the ILN Frontend project +github: [Invoice-Liquidity-Network] + +# Drips Network Wave funding +custom: + - https://drips.network/waves diff --git a/.github/labeler.yml b/.github/labeler.yml new file mode 100644 index 0000000..bdff9f9 --- /dev/null +++ b/.github/labeler.yml @@ -0,0 +1,66 @@ +# Automatic PR labeling based on changed file paths +# Labels are applied when a PR touches files in the specified paths + +ci: + - .github/workflows/**/* + - .github/labeler.yml + - .github/dependabot.yml + - .github/CODEOWNERS + - .husky/**/* + - .gitcliff.toml + - eslint.config.mjs + - prettierrc + - vitest.config.ts + - playwright.config.ts + - stryker.conf.json + - .lighthouserc.json + +documentation: + - docs/**/* + - README.md + - CONTRIBUTING.md + - DESIGN.md + - SECURITY.md + - CHANGELOG.md + - PR_NEW.md + +testing: + - __tests__/**/* + - e2e/**/* + - vitest.setup.ts + - vitest.shims.d.ts + +ui: + - src/components/**/* + - src/app/**/page.tsx + - src/app/**/layout.tsx + - styles/**/* + +hooks: + - src/hooks/**/* + - src/context/**/* + +contracts: + - src/lib/soroban.ts + - src/lib/horizon.ts + - src/lib/indexer-websocket.ts + - src/lib/contract/**/* + - src/lib/invoice-nft.ts + +api: + - app/api/**/* + +utils: + - src/utils/**/* + - src/lib/**/* # (excluding contract-specific files above) + +types: + - src/types/**/* + - src/constants.ts + +dependencies: + - package.json + - pnpm-lock.yaml + - tsconfig.json + - next.config.ts + - postcss.config.mjs diff --git a/.github/workflows/pr-labeler.yml b/.github/workflows/pr-labeler.yml new file mode 100644 index 0000000..db13c22 --- /dev/null +++ b/.github/workflows/pr-labeler.yml @@ -0,0 +1,26 @@ +name: Pull Request Labeler + +on: + pull_request_target: + types: [opened, edited, synchronize, reopened] + +permissions: + contents: read + pull-requests: write + +jobs: + labeler: + name: Apply labels based on changed files + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.sha }} + + - name: Run Labeler + uses: actions/labeler@v5 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + configuration-path: .github/labeler.yml + sync-labels: true diff --git a/.github/workflows/stale-assignments.yml b/.github/workflows/stale-assignments.yml new file mode 100644 index 0000000..40a741f --- /dev/null +++ b/.github/workflows/stale-assignments.yml @@ -0,0 +1,155 @@ +name: Stale Assignment Reclaimer + +on: + schedule: + # Run daily at 00:00 UTC + - cron: '0 0 * * *' + workflow_dispatch: + +permissions: + issues: write + pull-requests: write + +jobs: + stale-assignments: + name: Reclaim abandoned issue assignments + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Reclaim stale assignments + uses: actions/github-script@v7 + with: + script: | + const { Octokit } = require('@octokit/rest'); + const octokit = new Octokit({ auth: github.token }); + + // Configuration (can be adjusted here) + const WARNING_DAYS = 7; // Days before warning comment + const RECLAIM_DAYS = 14; // Days before unassignment + const WARNING_LABEL = 'stale-assignment-warning'; + const RECLAIM_LABEL = 'assignment-reclaimed'; + + const owner = context.repo.owner; + const repo = context.repo.repo; + + // Get all open issues with assignees + const issues = await octokit.rest.issues.listForRepo({ + owner, + repo, + state: 'open', + assignee: '*', + per_page: 100 + }); + + const now = new Date(); + + for (const issue of issues.data) { + const assignees = issue.assignees.map(a => a.login); + if (assignees.length === 0) continue; + + const assignedAt = new Date(issue.created_at); + const updatedAt = new Date(issue.updated_at); + const daysSinceUpdate = Math.floor((now - updatedAt) / (1000 * 60 * 60 * 24)); + const daysSinceAssignment = Math.floor((now - assignedAt) / (1000 * 60 * 60 * 24)); + + // Check if there's a linked PR + const hasLinkedPR = issue.body?.includes('Closes') || + issue.body?.includes('Fixes') || + issue.body?.includes('Resolves') || + issue.body?.includes('#'); + + // Check if there are open PRs referencing this issue + const prs = await octokit.rest.pulls.list({ + owner, + repo, + state: 'open', + per_page: 100 + }); + + const linkedPR = prs.data.find(pr => + pr.body?.includes(`#${issue.number}`) || + pr.title.includes(`#${issue.number}`) + ); + + // Skip if there's active PR activity + if (linkedPR) { + console.log(`Issue #${issue.number} has active PR #${linkedPR.number} - skipping`); + continue; + } + + // Check for existing labels + const hasWarningLabel = issue.labels.some(l => l.name === WARNING_LABEL); + const hasReclaimLabel = issue.labels.some(l => l.name === RECLAIM_LABEL); + + // Stage 1: Warning comment + if (daysSinceUpdate >= WARNING_DAYS && !hasWarningLabel && !hasReclaimLabel) { + const warningComment = "⚠️ **Stale Assignment Warning**\n\n" + + "This issue has been assigned to @" + assignees.join(', @') + " for " + daysSinceAssignment + " days with no linked PR activity for " + daysSinceUpdate + " days.\n\n" + + "To keep this assignment active, please:\n" + + "1. Open a draft PR if you're working on it\n" + + "2. Comment with an update on your progress\n" + + "3. Unassign yourself if you're no longer working on it\n\n" + + "If no activity is detected within " + (RECLAIM_DAYS - WARNING_DAYS) + " days, the assignment will be automatically removed to allow others to claim this issue.\n\n" + + "---\n" + + "*This is an automated message. Contact maintainers if you believe this is an error.*"; + + await octokit.rest.issues.createComment({ + owner, + repo, + issue_number: issue.number, + body: warningComment + }); + + await octokit.rest.issues.addLabels({ + owner, + repo, + issue_number: issue.number, + labels: [WARNING_LABEL] + }); + + console.log("Added warning to issue #" + issue.number); + } + + // Stage 2: Reclaim assignment + if (daysSinceUpdate >= RECLAIM_DAYS && !hasReclaimLabel) { + const reclaimComment = "🔄 **Assignment Reclaimed**\n\n" + + "This issue was previously assigned to @" + assignees.join(', @') + " but has shown no activity for " + daysSinceUpdate + " days.\n\n" + + "The assignment has been automatically removed to allow other contributors to claim this issue. If you were still working on it, please re-assign yourself and open a PR promptly.\n\n" + + "---\n" + + "*This is an automated message. Contact maintainers if you believe this is an error.*"; + + await octokit.rest.issues.createComment({ + owner, + repo, + issue_number: issue.number, + body: reclaimComment + }); + + // Remove all assignees + await octokit.rest.issues.removeAssignees({ + owner, + repo, + issue_number: issue.number, + assignees: assignees + }); + + // Update labels + await octokit.rest.issues.removeLabel({ + owner, + repo, + issue_number: issue.number, + name: WARNING_LABEL + }).catch(() => {}); // Ignore if label doesn't exist + + await octokit.rest.issues.addLabels({ + owner, + repo, + issue_number: issue.number, + labels: [RECLAIM_LABEL] + }); + + console.log("Reclaimed assignment for issue #" + issue.number); + } + } diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d524752..9493a08 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -775,6 +775,44 @@ When you open a PR, GitHub will automatically suggest reviewers based on the fil If you become a regular contributor to a specific area of the codebase, you can request to be added as a code owner. Contact a maintainer to discuss this. +## Stale Assignment Policy + +To maintain effective Wave throughput and ensure issues don't get claimed and abandoned, this repository uses an automated stale assignment reclaimer. + +### How It Works + +The stale assignment bot runs daily and monitors assigned issues: + +1. **Warning Stage (7 days of inactivity)** + - If an issue has been assigned for 7+ days with no linked PR activity, a warning comment is added + - The issue is labeled with `stale-assignment-warning` + - The assignee is notified with instructions to either: + - Open a draft PR + - Comment with a progress update + - Unassign themselves if no longer working on it + +2. **Reclaim Stage (14 days of inactivity)** + - If no activity is detected for 14+ days, the assignment is automatically removed + - The issue is labeled with `assignment-reclaimed` + - Other contributors can then claim the issue + +### Configuration + +The timeout periods are configurable in `.github/workflows/stale-assignments.yml`: +- `WARNING_DAYS`: Days before warning comment (default: 7) +- `RECLAIM_DAYS`: Days before unassignment (default: 14) + +### For Contributors + +- **When claiming an issue**: Open a draft PR within 7 days to show active work +- **If you need more time**: Comment on the issue with a progress update to reset the timer +- **If you can't complete it**: Unassign yourself promptly so others can claim it +- **After reclamation**: If your assignment was reclaimed but you're still working on it, re-assign yourself and open a PR promptly + +### Exemptions + +Issues with linked open PRs are automatically exempt from the stale assignment check. + ## Code of Conduct Please be respectful and constructive in all interactions. We aim to create a welcoming environment for all contributors. diff --git a/README.md b/README.md index 32770b3..7ac1bbe 100644 --- a/README.md +++ b/README.md @@ -207,6 +207,7 @@ A central marketplace listing all active open invoices waiting for funding, deta ## 🔗 Useful Links & Documentation +- **Documentation Index**: Browse all project documentation in [docs/README.md](docs/README.md). - **Getting Started Guide**: Refer to the [Quick Start](#-quick-start) section. - **Component Library (Storybook)**: Browse the full component library with interactive controls, variants, and a11y checks at the [published Storybook](https://invoice-liquidity-network.github.io/ILN-Frontend) (deployed from `main`). - **Frontend Architecture Overview**: Learn about our architecture design and libraries in [docs/architecture.md](docs/architecture.md). diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..180e6c7 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,35 @@ +# Documentation Index + +This directory contains comprehensive documentation for the ILN Frontend project. + +## Core Documentation + +- **[architecture.md](architecture.md)** - Frontend architecture overview covering design decisions, folder structure, data flow patterns, and architectural trade-offs. Essential for understanding the codebase structure and development conventions. + +- **[developer-quickstart.md](developer-quickstart.md)** - Step-by-step guide from fresh clone to running local development environment. Covers prerequisites, installation, and initial setup for all platforms. + +## Testing & Quality Assurance + +- **[testing.md](testing.md)** - Comprehensive testing guide covering unit tests (Vitest), end-to-end tests (Playwright), and testing best practices. + +- **[VISUAL_REGRESSION_WORKFLOW.md](VISUAL_REGRESSION_WORKFLOW.md)** - Explains the Chromatic visual regression testing workflow, including how to approve/reject UI changes and add new Storybook stories. + +- **[LIGHTHOUSE_CI.md](LIGHTHOUSE_CI.md)** - Documentation for Lighthouse CI performance budget tests, including performance thresholds, tested pages, and how to review reports. + +## CI/CD & Infrastructure + +- **[ci-cd.md](ci-cd.md)** - CI/CD pipeline documentation covering GitHub Actions workflows, deployment processes, and self-hosted runner configuration. + +## Domain-Specific Documentation + +- **[contract-fixtures.md](contract-fixtures.md)** - Documentation for contract test fixtures used in integration testing with Stellar smart contracts. + +- **[repo-size-audit.md](repo-size-audit.md)** - Repository size analysis and optimization recommendations for maintaining a lean codebase. + +## Hooks Documentation + +- **[hooks/](hooks/)** - Detailed documentation for custom React hooks, including usage examples and API references. + +--- + +**Note**: This index should be updated whenever new documentation is added to the `docs/` directory to maintain discoverability. From 0c6d6defccc57a84eaef3563950f1b6fad28b8c6 Mon Sep 17 00:00:00 2001 From: johnsmichael150 Date: Mon, 27 Jul 2026 22:54:23 +0100 Subject: [PATCH 2/2] ci: add stale-assignment reclaim policy and docs index updates --- .github/labeler.yml | 1 + .github/workflows/stale-assignments.yml | 185 +++++++++++------------- CONTRIBUTING.md | 6 + docs/README.md | 46 +++--- 4 files changed, 117 insertions(+), 121 deletions(-) diff --git a/.github/labeler.yml b/.github/labeler.yml index bdff9f9..07154bd 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -26,6 +26,7 @@ documentation: testing: - __tests__/**/* + - __tests__/**/e2e/**/* - e2e/**/* - vitest.setup.ts - vitest.shims.d.ts diff --git a/.github/workflows/stale-assignments.yml b/.github/workflows/stale-assignments.yml index 40a741f..8585f14 100644 --- a/.github/workflows/stale-assignments.yml +++ b/.github/workflows/stale-assignments.yml @@ -2,154 +2,141 @@ name: Stale Assignment Reclaimer on: schedule: - # Run daily at 00:00 UTC - cron: '0 0 * * *' workflow_dispatch: + inputs: + warning_days: + description: 'Days before the warning comment is posted' + required: false + default: '7' + reclaim_days: + description: 'Days before the assignee is removed' + required: false + default: '14' permissions: issues: write - pull-requests: write + pull-requests: read + +env: + WARNING_DAYS: ${{ github.event.inputs.warning_days || vars.STALE_ASSIGNMENT_WARNING_DAYS || '7' }} + RECLAIM_DAYS: ${{ github.event.inputs.reclaim_days || vars.STALE_ASSIGNMENT_RECLAIM_DAYS || '14' }} + WARNING_LABEL: ${{ vars.STALE_ASSIGNMENT_WARNING_LABEL || 'stale-assignment-warning' }} + RECLAIM_LABEL: ${{ vars.STALE_ASSIGNMENT_RECLAIM_LABEL || 'assignment-reclaimed' }} + WARNING_MESSAGE: ${{ vars.STALE_ASSIGNMENT_WARNING_MESSAGE || '⚠️ **Stale Assignment Warning**\n\nThis issue has been assigned to @assignees for X days without linked PR activity. Please keep the assignment active by opening or updating a linked PR, or unassign yourself if you are no longer working on it.\n\nIf no activity is detected within Y days, the assignment will be automatically removed.' }} + RECLAIM_MESSAGE: ${{ vars.STALE_ASSIGNMENT_RECLAIM_MESSAGE || '🔄 **Assignment Reclaimed**\n\nThis issue had been assigned without linked PR activity for X days, so the assignment has been automatically removed. If you were still working on it, please re-assign yourself and keep the PR in motion.' }} jobs: stale-assignments: name: Reclaim abandoned issue assignments runs-on: ubuntu-latest steps: - - name: Checkout repository - uses: actions/checkout@v4 - - name: Reclaim stale assignments uses: actions/github-script@v7 with: script: | - const { Octokit } = require('@octokit/rest'); - const octokit = new Octokit({ auth: github.token }); - - // Configuration (can be adjusted here) - const WARNING_DAYS = 7; // Days before warning comment - const RECLAIM_DAYS = 14; // Days before unassignment - const WARNING_LABEL = 'stale-assignment-warning'; - const RECLAIM_LABEL = 'assignment-reclaimed'; - const owner = context.repo.owner; const repo = context.repo.repo; - - // Get all open issues with assignees - const issues = await octokit.rest.issues.listForRepo({ + const now = Date.now(); + const warningDays = Number(process.env.WARNING_DAYS || '7'); + const reclaimDays = Number(process.env.RECLAIM_DAYS || '14'); + const warningLabel = process.env.WARNING_LABEL || 'stale-assignment-warning'; + const reclaimLabel = process.env.RECLAIM_LABEL || 'assignment-reclaimed'; + const warningTemplate = (process.env.WARNING_MESSAGE || '').trim(); + const reclaimTemplate = (process.env.RECLAIM_MESSAGE || '').trim(); + + const issues = await github.paginate(github.rest.issues.listForRepo, { owner, repo, state: 'open', assignee: '*', per_page: 100 }); - - const now = new Date(); - - for (const issue of issues.data) { - const assignees = issue.assignees.map(a => a.login); + + const allPullRequests = await github.paginate(github.rest.pulls.list, { + owner, + repo, + state: 'all', + per_page: 100 + }); + + for (const issue of issues) { + const assignees = issue.assignees.map((assignee) => assignee.login); if (assignees.length === 0) continue; - - const assignedAt = new Date(issue.created_at); - const updatedAt = new Date(issue.updated_at); - const daysSinceUpdate = Math.floor((now - updatedAt) / (1000 * 60 * 60 * 24)); - const daysSinceAssignment = Math.floor((now - assignedAt) / (1000 * 60 * 60 * 24)); - - // Check if there's a linked PR - const hasLinkedPR = issue.body?.includes('Closes') || - issue.body?.includes('Fixes') || - issue.body?.includes('Resolves') || - issue.body?.includes('#'); - - // Check if there are open PRs referencing this issue - const prs = await octokit.rest.pulls.list({ - owner, - repo, - state: 'open', - per_page: 100 + + const linkedPullRequests = allPullRequests.filter((pullRequest) => { + const bodyText = `${pullRequest.title ?? ''}\n${pullRequest.body ?? ''}`; + return bodyText.includes(`#${issue.number}`); }); - - const linkedPR = prs.data.find(pr => - pr.body?.includes(`#${issue.number}`) || - pr.title.includes(`#${issue.number}`) + + const lastLinkedActivity = linkedPullRequests.length + ? linkedPullRequests.reduce((latestTimestamp, pullRequest) => { + const updatedAt = new Date(pullRequest.updated_at ?? pullRequest.created_at ?? 0).getTime(); + return updatedAt > latestTimestamp ? updatedAt : latestTimestamp; + }, 0) + : 0; + + const lastActivityAt = Math.max( + new Date(issue.updated_at ?? issue.created_at ?? 0).getTime(), + lastLinkedActivity ); - - // Skip if there's active PR activity - if (linkedPR) { - console.log(`Issue #${issue.number} has active PR #${linkedPR.number} - skipping`); - continue; - } - - // Check for existing labels - const hasWarningLabel = issue.labels.some(l => l.name === WARNING_LABEL); - const hasReclaimLabel = issue.labels.some(l => l.name === RECLAIM_LABEL); - - // Stage 1: Warning comment - if (daysSinceUpdate >= WARNING_DAYS && !hasWarningLabel && !hasReclaimLabel) { - const warningComment = "⚠️ **Stale Assignment Warning**\n\n" + - "This issue has been assigned to @" + assignees.join(', @') + " for " + daysSinceAssignment + " days with no linked PR activity for " + daysSinceUpdate + " days.\n\n" + - "To keep this assignment active, please:\n" + - "1. Open a draft PR if you're working on it\n" + - "2. Comment with an update on your progress\n" + - "3. Unassign yourself if you're no longer working on it\n\n" + - "If no activity is detected within " + (RECLAIM_DAYS - WARNING_DAYS) + " days, the assignment will be automatically removed to allow others to claim this issue.\n\n" + - "---\n" + - "*This is an automated message. Contact maintainers if you believe this is an error.*"; - - await octokit.rest.issues.createComment({ + const daysSinceLastActivity = Math.floor((now - lastActivityAt) / (1000 * 60 * 60 * 24)); + + const hasWarningLabel = issue.labels.some((label) => label.name === warningLabel); + const hasReclaimLabel = issue.labels.some((label) => label.name === reclaimLabel); + + if (daysSinceLastActivity >= warningDays && !hasWarningLabel && !hasReclaimLabel) { + const warningBody = warningTemplate + .replace(/@assignees/g, assignees.map((login) => `@${login}`).join(', ')) + .replace(/X days/g, `${daysSinceLastActivity} days`) + .replace(/Y days/g, `${Math.max(reclaimDays - warningDays, 0)} days`); + + await github.rest.issues.createComment({ owner, repo, issue_number: issue.number, - body: warningComment + body: warningBody }); - - await octokit.rest.issues.addLabels({ + + await github.rest.issues.addLabels({ owner, repo, issue_number: issue.number, - labels: [WARNING_LABEL] + labels: [warningLabel] }); - - console.log("Added warning to issue #" + issue.number); } - - // Stage 2: Reclaim assignment - if (daysSinceUpdate >= RECLAIM_DAYS && !hasReclaimLabel) { - const reclaimComment = "🔄 **Assignment Reclaimed**\n\n" + - "This issue was previously assigned to @" + assignees.join(', @') + " but has shown no activity for " + daysSinceUpdate + " days.\n\n" + - "The assignment has been automatically removed to allow other contributors to claim this issue. If you were still working on it, please re-assign yourself and open a PR promptly.\n\n" + - "---\n" + - "*This is an automated message. Contact maintainers if you believe this is an error.*"; - - await octokit.rest.issues.createComment({ + + if (daysSinceLastActivity >= reclaimDays && !hasReclaimLabel) { + const reclaimBody = reclaimTemplate + .replace(/@assignees/g, assignees.map((login) => `@${login}`).join(', ')) + .replace(/X days/g, `${daysSinceLastActivity} days`); + + await github.rest.issues.createComment({ owner, repo, issue_number: issue.number, - body: reclaimComment + body: reclaimBody }); - - // Remove all assignees - await octokit.rest.issues.removeAssignees({ + + await github.rest.issues.removeAssignees({ owner, repo, issue_number: issue.number, - assignees: assignees + assignees }); - - // Update labels - await octokit.rest.issues.removeLabel({ + + await github.rest.issues.removeLabel({ owner, repo, issue_number: issue.number, - name: WARNING_LABEL - }).catch(() => {}); // Ignore if label doesn't exist - - await octokit.rest.issues.addLabels({ + name: warningLabel + }).catch(() => {}); + + await github.rest.issues.addLabels({ owner, repo, issue_number: issue.number, - labels: [RECLAIM_LABEL] + labels: [reclaimLabel] }); - - console.log("Reclaimed assignment for issue #" + issue.number); } } diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1d1b2fc..4acbadb 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -157,6 +157,12 @@ pnpm run verify This runs the same checks as CI, in the same order, in a single command: `lint` → `env:check` → `format:check` → `tsc --noEmit` → `test`. A passing `pnpm run verify` locally means the CI `lint` and `tests` jobs will pass too, so use it instead of running each check separately to avoid round-trips on avoidable CI failures. +### Issue and PR Assignment Policy + +Issues that are assigned to a contributor are expected to move forward promptly. If an issue remains assigned without a linked PR update for 7 days, the repository automation will post a reminder comment. If the issue still shows no linked PR activity after 14 days, the assignee is automatically removed so the issue can be claimed by someone else. + +The thresholds and message text are configurable through the workflow inputs and repository variables used by [.github/workflows/stale-assignments.yml](.github/workflows/stale-assignments.yml). Contributors should keep assignments current, open or update a linked PR early, and unassign themselves if they can no longer work on the issue. + ### Code Style and Formatting We use **ESLint** and **Prettier** to maintain consistent code quality. diff --git a/docs/README.md b/docs/README.md index 180e6c7..774da36 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,35 +1,37 @@ # Documentation Index -This directory contains comprehensive documentation for the ILN Frontend project. +This directory contains the main contributor and operations documentation for the ILN Frontend project. Use this page as the starting point when you need context on architecture, testing, CI, accessibility, or implementation details. -## Core Documentation +## Core Guides -- **[architecture.md](architecture.md)** - Frontend architecture overview covering design decisions, folder structure, data flow patterns, and architectural trade-offs. Essential for understanding the codebase structure and development conventions. +- **[architecture.md](architecture.md)** - Frontend architecture overview covering design decisions, folder structure, and major data-flow patterns. +- **[developer-quickstart.md](developer-quickstart.md)** - End-to-end setup guide from a fresh clone through local development and initial verification. +- **[testing.md](testing.md)** - Testing strategy and conventions for Vitest, Playwright, and other quality checks. +- **[ci-cd.md](ci-cd.md)** - GitHub Actions, deployment flow, and CI/CD runner guidance. -- **[developer-quickstart.md](developer-quickstart.md)** - Step-by-step guide from fresh clone to running local development environment. Covers prerequisites, installation, and initial setup for all platforms. +## Quality and Performance -## Testing & Quality Assurance +- **[LIGHTHOUSE_CI.md](LIGHTHOUSE_CI.md)** - Lighthouse CI performance budgets, thresholds, and report review guidance. +- **[VISUAL_REGRESSION_WORKFLOW.md](VISUAL_REGRESSION_WORKFLOW.md)** - Chromatic visual regression workflow and approval process. +- **[accessibility-audit-toast-notifications.md](accessibility-audit-toast-notifications.md)** - Accessibility audit notes for toast and notification flows. +- **[accessibility-implementation-summary.md](accessibility-implementation-summary.md)** - Summary of accessibility implementation work and supporting details. +- **[screen-reader-testing-guide.md](screen-reader-testing-guide.md)** - Manual testing checklist for screen-reader and keyboard accessibility. -- **[testing.md](testing.md)** - Comprehensive testing guide covering unit tests (Vitest), end-to-end tests (Playwright), and testing best practices. +## Product and Domain Documentation -- **[VISUAL_REGRESSION_WORKFLOW.md](VISUAL_REGRESSION_WORKFLOW.md)** - Explains the Chromatic visual regression testing workflow, including how to approve/reject UI changes and add new Storybook stories. +- **[api-routes.md](api-routes.md)** - Reference for the API routes that power the frontend experience. +- **[contract-fixtures.md](contract-fixtures.md)** - Fixture and integration-test context for Stellar contract interactions. +- **[error-codes.md](error-codes.md)** - Error code catalog and troubleshooting notes. +- **[feature-flags.md](feature-flags.md)** - Overview of feature flags and current rollout settings. +- **[i18n.md](i18n.md)** - Internationalization setup and translation workflow details. +- **[repo-size-audit.md](repo-size-audit.md)** - Repository size analysis and optimization recommendations. +- **[supabase-setup.md](supabase-setup.md)** - Supabase configuration and local setup notes. -- **[LIGHTHOUSE_CI.md](LIGHTHOUSE_CI.md)** - Documentation for Lighthouse CI performance budget tests, including performance thresholds, tested pages, and how to review reports. +## Hooks and Examples -## CI/CD & Infrastructure - -- **[ci-cd.md](ci-cd.md)** - CI/CD pipeline documentation covering GitHub Actions workflows, deployment processes, and self-hosted runner configuration. - -## Domain-Specific Documentation - -- **[contract-fixtures.md](contract-fixtures.md)** - Documentation for contract test fixtures used in integration testing with Stellar smart contracts. - -- **[repo-size-audit.md](repo-size-audit.md)** - Repository size analysis and optimization recommendations for maintaining a lean codebase. - -## Hooks Documentation - -- **[hooks/](hooks/)** - Detailed documentation for custom React hooks, including usage examples and API references. +- **[hooks/](hooks/)** - Detailed documentation for custom React hooks, including the authenticated-wallet hook reference. +- **[examples/](examples/)** - Example assets and snippets used across the documentation set. --- -**Note**: This index should be updated whenever new documentation is added to the `docs/` directory to maintain discoverability. +Keep this index updated whenever new documentation is added to the docs directory so contributors can find it quickly.