diff --git a/AGENTS.md b/AGENTS.md index 8bd0e39..643577d 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,5 +1,9 @@ + # This is NOT the Next.js you know -This version has breaking changes β€” APIs, conventions, and file structure may all differ from your training data. Read the relevant guide in `node_modules/next/dist/docs/` before writing any code. Heed deprecation notices. +This version has breaking changes β€” APIs, conventions, and file structure may all differ from your training data. Read the relevant guide in `node_modules/next/dist/docs/` (resolved from this file's directory; in monorepos the `next` package may not be visible from the repo root) before writing any code. Heed deprecation notices. + +This block is written and re-added by `next dev` β€” verify at `node_modules/next/dist/server/lib/generate-agent-files.js`. Removing it from a diff only re-creates the uncommitted change; committing it with your work keeps the tree clean. + diff --git a/README.md b/README.md index 104fd1d..e3add83 100644 --- a/README.md +++ b/README.md @@ -1,162 +1,62 @@ # OpenIssue.dev -> Discover open-source contribution opportunities by technology, not by endless searching. +[OpenIssue.dev](https://openissue-dev.vercel.app/) helps developers find active, contributor-friendly GitHub issues by technology. -OpenIssue.dev helps developers find active GitHub issues that are actually looking for contributors. Search by technology stack, filter contributor-friendly labels, and quickly identify issues that match your skills. +## What it does -Whether you're making your first open-source contribution or looking for a new project to contribute to, OpenIssue.dev makes issue discovery simple and efficient. +- Searches live GitHub issues by language or ecosystem topic +- Filters by contributor-friendly label, linked pull requests, and Hacktoberfest readiness +- Sorts and ranks results using activity, repository, assignment, and discussion signals +- Supports reusable saved searches without requiring an account +- Adds GitHub sign-in for cloud-backed saved searches that survive cleared browser storage +- Provides light, dark, and system themes with a responsive interface ---- +## Quick start -## ✨ Features +Requirements: Node.js 22+, npm, a GitHub token, and a Turso database. -### πŸ” Search by Technology +```bash +npm install +cp .env.example .env.local +npm run dev +``` -Find issues related to: +Open [http://localhost:3000](http://localhost:3000). GitHub OAuth and database persistence require the additional configuration described in [Setup and deployment](doc/setup.md). -* Java -* Spring Boot -* React -* Angular -* Vue -* Python -* Django -* FastAPI -* Go -* Rust -* Kubernetes -* Docker -* Terraform -* AWS -* Azure -* GCP -* And many more... +## Low-level design -### 🏷️ Contributor-Friendly Labels +```mermaid +flowchart LR + UI[Issue Finder UI] --> SearchRoute["GET /api/search"] + SearchRoute --> SearchService[Search and ranking] + SearchService <--> GitHubAPI[GitHub APIs] + SearchService --> UI -Discover issues tagged with: + UI <--> Local[(Local storage)] + UI --> AuthRoute["/api/auth/*"] + AuthRoute --> BetterAuth[Better Auth] + BetterAuth <--> GitHubOAuth[GitHub OAuth] -* `help wanted` -* `good first issue` -* `up-for-grabs` -* `first-timers-only` -* `documentation` -* `bug` -* `enhancement` + Local --> SyncClient[Saved-search sync] + SyncClient --> SavedRoute["/api/saved-searches"] + SavedRoute --> BetterAuth + SavedRoute --> Drizzle[Drizzle ORM] + BetterAuth --> Drizzle + Drizzle <--> Turso[(Turso / libSQL)] +``` -### πŸ“Š Smart Filtering +See [Architecture and data flow](doc/architecture.md) for the expanded request flows, persistence model, and component relationships. -Filter results by: +## Documentation -* Technology -* Labels -* Repository popularity -* Last updated date -* Number of comments -* Issue activity +- [Setup and deployment](doc/setup.md) +- [Architecture and data flow](doc/architecture.md) +- [Development and contributing](doc/contributing.md) -### ⚑ Fast & Lightweight +## Tech stack -* Serverless architecture -* Powered by GitHub APIs -* No installation required -* Optimized for Vercel deployment +Next.js 16, React 19, TypeScript, Tailwind CSS, Better Auth, Drizzle ORM, Turso/libSQL, GitHub APIs, Vitest, Vercel, and SonarQube Cloud. ---- +## License -## 🎯 Why OpenIssue.dev? - -Finding a suitable open-source issue can be frustrating: - -* Thousands of repositories -* Inconsistent labels -* Outdated issue lists -* Endless GitHub searches - -OpenIssue.dev brings contributor-friendly issues into one place and helps developers focus on contributing instead of searching. - ---- - -## πŸš€ Use Cases - -### First-Time Contributors - -Find beginner-friendly issues and start contributing to open source with confidence. - -### Experienced Developers - -Discover challenging issues in technologies already used professionally. - -### Students - -Build real-world experience by contributing to active projects. - -### Open Source Enthusiasts - -Explore projects across multiple ecosystems and communities. - ---- - -## πŸ—οΈ How It Works - -1. Select a technology stack. -2. Choose one or more contribution labels. -3. Browse active GitHub issues. -4. Open the issue directly on GitHub. -5. Start contributing. - ---- - -## πŸ“ˆ Roadmap - -### MVP - -* [x] Technology-based issue discovery -* [x] Help Wanted filtering -* [x] Good First Issue filtering -* [x] GitHub issue links -* [x] Repository metadata - -### Future Enhancements - -* [ ] GitHub authentication -* [ ] Personalized recommendations -* [ ] Saved searches -* [ ] Email alerts -* [ ] Trending opportunities -* [ ] Repository health scoring -* [ ] Contribution history tracking -* [ ] Weekly digest - ---- - -## πŸ› οΈ Tech Stack - -* Next.js -* React -* TypeScript -* Tailwind CSS -* GitHub Search API -* Vercel - ---- - -## 🀝 Contributing - -Contributions, feature requests, and bug reports are welcome. - -If you have ideas to make open-source discovery easier, feel free to open an issue or submit a pull request. - ---- - -## 🌟 Mission - -OpenIssue.dev exists to reduce the gap between developers who want to contribute and open-source projects that need help. - -**Less searching. More contributing.** πŸš€ - ---- - -## πŸ“„ License - -Apache 2.0 License. +Licensed under the [Apache License 2.0](LICENSE). diff --git a/doc/architecture.md b/doc/architecture.md new file mode 100644 index 0000000..a10851d --- /dev/null +++ b/doc/architecture.md @@ -0,0 +1,82 @@ +# Architecture and data flow + +## Application overview + +OpenIssue.dev uses the Next.js App Router. The main interface is a client component backed by route handlers for GitHub search, authentication, and saved-search persistence. + +```mermaid +flowchart LR + subgraph Client[Browser] + UI[Issue Finder UI] + Local[(Local storage)] + UI <--> Local + end + + subgraph App[Next.js application] + SearchAPI["GET /api/search"] + SearchService[Search and ranking] + AuthAPI["/api/auth/*"] + BetterAuth[Better Auth] + SavedAPI["/api/saved-searches"] + Drizzle[Drizzle ORM] + end + + subgraph External[External services] + GitHubAPI[GitHub Search and REST APIs] + GitHubOAuth[GitHub OAuth] + Turso[(Turso / libSQL)] + end + + UI -->|Search filters| SearchAPI + SearchAPI --> SearchService + SearchService -->|Issues and repository metadata| GitHubAPI + SearchService -->|Ranked results| UI + + UI -->|Sign in or sign out| AuthAPI + AuthAPI --> BetterAuth + BetterAuth <--> GitHubOAuth + BetterAuth --> Drizzle + + Local -->|Signed-in synchronization| SavedAPI + SavedAPI -->|Validate session| BetterAuth + SavedAPI --> Drizzle + Drizzle <--> Turso +``` + +## Issue discovery + +`GET /api/search` validates and rate-limits requests before querying GitHub. Languages use GitHub language qualifiers; framework and ecosystem terms such as React, Next.js, Spring Boot, and Kubernetes use repository topics. + +Candidate issues are enriched where possible with repository metadata, recent discussion, assignment state, linked pull requests, and Hacktoberfest signals. The application ranks them for contributor relevance and returns paginated results to the browser. + +Search filters currently include: + +- Technology or ecosystem +- Contributor-friendly label +- Recently updated, most commented, or newest sorting +- Any, present, or absent linked pull request +- All issues or Hacktoberfest-ready issues + +## Authentication + +Better Auth handles GitHub OAuth and stores users, provider accounts, and sessions in Turso through Drizzle. Authentication is optional for discovery and local saved searches. + +Production uses `https://openissue-dev.vercel.app` as the OAuth proxy target. Allowed hosts include localhost, the production domain, and Vercel preview subdomains. + +## Saved searches + +Saved searches use a hybrid persistence model: + +- Guests read and write browser `localStorage`. +- Signed-in users retain the same local behavior and synchronize with Turso. +- Existing local searches migrate after sign-in in batches of at most 100. +- Server records restore the local cache after browser data is cleared. +- Deletion is performed in Turso before the local record is removed. +- API queries and deletes are scoped to the authenticated user ID. +- Local data remains usable if cloud synchronization is temporarily unavailable. + +## Data model + +The database contains Better Auth's `user`, `session`, `account`, and `verification` tables plus `saved_search`. Saved searches reference `user.id` with cascading deletion and store the selected filter values and creation timestamp. + +Schema definitions live in `src/lib/auth-schema.ts`; executable SQL is versioned under `db/migrations/`. diff --git a/doc/contributing.md b/doc/contributing.md new file mode 100644 index 0000000..b199e3b --- /dev/null +++ b/doc/contributing.md @@ -0,0 +1,49 @@ +# Development and contributing + +## Workflow + +Create a focused branch from the latest default branch and keep unrelated changes out of the pull request. The repository commonly uses names such as: + +```text +feature/descriptiveFeatureName +bugfix/descriptiveBugName +fix/descriptiveFixName +``` + +Before submitting a change, run: + +```bash +npm run lint +npm test +npm run test:coverage +npm run build +``` + +The test suite uses Vitest. Coverage thresholds are configured in `vitest.config.ts`, and SonarQube Cloud consumes `coverage/lcov.info`. + +## Project structure + +| Path | Responsibility | +| --- | --- | +| `src/app/` | App Router pages, metadata, and API routes | +| `src/components/` | Shared application and UI components | +| `src/features/issues/` | Issue-search UI, ranking, persistence, types, and GitHub integration | +| `src/lib/` | Authentication, database client, and database schema | +| `db/migrations/` | Ordered Turso SQL migrations | +| `tests/` | Unit, component, and route-handler tests | + +## Database changes + +Database changes must update both the Drizzle schema and a new ordered SQL migration. Migrations may be public because they describe structure, not credentials. Never include tokens, secrets, or production records in them. + +## Testing guidance + +Test meaningful behavior: validation, authorization, data transformation, error handling, and user actions. Exclude only declarative framework wiring or generated code that contains no application decisions. Keep Vitest and Sonar coverage exclusions aligned. + +## Pull requests + +Use a concise summary, list behavior and database changes, include verification results, and link the relevant issue with `Closes #` when appropriate. Signed and SSH/GPG-verified commits can be created with: + +```bash +git commit -s -S -m "type: concise description" +``` diff --git a/doc/setup.md b/doc/setup.md new file mode 100644 index 0000000..f55fa33 --- /dev/null +++ b/doc/setup.md @@ -0,0 +1,62 @@ +# Setup and deployment + +## Prerequisites + +- Node.js 22 or newer +- npm +- A GitHub personal access token for issue search +- A Turso database and authentication token +- A GitHub OAuth app for sign-in + +## Local configuration + +Install dependencies and copy the environment template: + +```bash +npm install +cp .env.example .env.local +``` + +Configure these values in `.env.local`: + +| Variable | Purpose | +| --- | --- | +| `GITHUB_TOKEN` | Raises GitHub API limits and enables repository, comment, and linked-PR enrichment | +| `TURSO_DATABASE_URL` | libSQL URL for the Turso database | +| `TURSO_AUTH_TOKEN` | Turso database authentication token | +| `BETTER_AUTH_SECRET` | Secret used to protect authentication state; use at least 32 random characters | +| `BETTER_AUTH_URL` | Application origin, such as `http://localhost:3000` | +| `OAUTH_PROXY_SECRET` | Shared secret used by Better Auth's OAuth proxy for preview deployments | +| `GITHUB_CLIENT_ID` | GitHub OAuth app client ID | +| `GITHUB_CLIENT_SECRET` | GitHub OAuth app client secret | + +Never commit `.env.local` or paste real tokens into issues, pull requests, or logs. + +## Database + +Run the SQL migrations in filename order against the Turso database: + +1. `db/migrations/0001_better_auth.sql` +2. `db/migrations/0002_saved_search.sql` + +The first migration creates Better Auth's user, session, account, and verification tables. The second creates user-owned saved searches. Migration files intentionally contain structure onlyβ€”never credentials or production data. + +## GitHub OAuth + +Create a GitHub OAuth app and configure these callback URLs: + +- Production: `https://openissue-dev.vercel.app/api/auth/callback/github` +- Local: `http://localhost:3000/api/auth/callback/github` + +The application uses Better Auth's OAuth proxy so dynamic Vercel preview deployments can complete authentication through the stable production callback. Keep `OAUTH_PROXY_SECRET` identical across the relevant Vercel environments. + +## Vercel + +Add all variables from `.env.example` in the Vercel project settings. Use the production application URL for `BETTER_AUTH_URL` in Production. Preview URLs are allowed by the application and authenticate through the OAuth proxy. + +After deploying, verify: + +1. Issue search returns live results. +2. GitHub sign-in returns to the application. +3. A signed-in saved search is restored after clearing local storage. +4. Removing that search prevents it from returning after refresh. diff --git a/src/features/issues/components/issue-finder.tsx b/src/features/issues/components/issue-finder.tsx index d567d1e..46a8601 100644 --- a/src/features/issues/components/issue-finder.tsx +++ b/src/features/issues/components/issue-finder.tsx @@ -474,7 +474,7 @@ export function IssueFinder() {
-