Skip to content

Conversation

@Lucifer-0612
Copy link
Contributor

@Lucifer-0612 Lucifer-0612 commented Dec 18, 2025

Description

This PR resolves #292 by implementing a complete developer experience (DX) overhaul that enables single-command project bootstrap for new contributors.

Problem

The current setup process was complicated and error-prone:

  • ❌ Incomplete Docker documentation
  • ❌ Too many manual steps (DB setup, migrations, env files)
  • ❌ Silent failures that are hard to debug
  • ❌ Authentication issues due to misconfiguration
  • ❌ Even following the official video guide resulted in errors

Solution

This PR introduces automated setup with Docker orchestration:

  • Single command setup: make setup (Mac/Linux) or .\setup.ps1 (Windows)
  • Automatic environment generation: Creates .env files from templates
  • Secure secret generation: Auto-generates JWT and NextAuth secrets
  • Full-stack orchestration: Docker Compose manages PostgreSQL, API, and Web
  • Database automation: Migrations and seeding run automatically
  • Clear documentation: Simplified README with troubleshooting guide

Changes Made

New Files

  • docker-compose.yml - Full-stack orchestration (PostgreSQL, API, Web)
  • Dockerfile.dev - Development containers with hot-reload support
  • Makefile - 15+ automation targets (setup, start, stop, logs, reset, etc.)
  • setup.ps1 - Windows PowerShell setup script
  • scripts/setup.sh - Interactive Bash setup wizard
  • apps/web/.env.example - Web environment template with OAuth instructions
  • apps/api/prisma/seed.ts - Automated database seeding

Modified Files

  • README.md - Replaced manual setup with Docker Quick Start guide
  • apps/api/src/index.ts - Added /health endpoint for Docker healthchecks
  • apps/api/package.json - Added Prisma seed configuration
  • apps/api/tsconfig.json - Excluded prisma/ and dist/ folders
  • apps/web/.gitignore - Added exception for .env.example

How to Test

1. Fresh Setup Test

# Clone the PR branch
git clone -b main [https://github.com/Lucifer-0612/opensox.git](https://github.com/Lucifer-0612/opensox.git)
cd opensox

# Run setup (Mac/Linux)
make setup

# OR Windows
.\setup.ps1

# Check all services are running
docker compose ps

# View logs
docker compose logs

# Test endpoints
curl http://localhost:8080/health
curl http://localhost:3000

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

* **New Features**
  * Saved Repos: save/unsave projects, Save column, Saved Projects button with count badge, panel to view/manage items, import/export, clear-all, 100-item cap
  * Optional cross-device sync (feature-flag controlled) with server-side merge/conflict resolution
  * Health check endpoint

* **Developer Experience**
  * Docker-first local dev: docker-compose, multi-stage dev Dockerfile, comprehensive Makefile, setup scripts (shell & PowerShell)

* **Documentation**
  * Saved Repos guides, quickstart, and updated local setup docs

<sub>✏️ Tip: You can customize this high-level summary in your review settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

- Create SavedRepo type definition
- Add SavedReposAction and SavedReposUpdateInput types
- Export from shared package index
- Create Zustand store with persist middleware
- Implement actions: add, remove, toggle, clear, setAll, isSaved
- Configure localStorage persistence with key 'oss_saved_repos_v1'
- Add duplicate prevention logic
- Enforce maximum 100 repos limit
- Create star icon toggle button for each repo row
- Implement filled/outline star states
- Prevent event propagation to row click
- Add accessibility attributes (ARIA labels)
- Create side panel for managing saved repos
- Implement export to JSON functionality
- Implement import from JSON functionality
- Add clear all with confirmation (3-second timeout)
- Add empty state and list view
- Include responsive design
- Add 'Save' column as first column in table
- Render SaveToggle component in each row
- Add 'Saved Projects' button with count badge in header
- Add SavedProjectsPanel component
- Manage panel open/close state
- Add saved_repos JSONB column with default '[]'
- Non-breaking change (additive only)
- Supports up to 100 repos per user
- Create getSavedRepos function
- Create mergeSavedRepos with conflict resolution (newer savedAt wins)
- Create updateSavedRepos with add/remove/replace actions
- Enforce maximum 100 repos limit
- Add validation and error handling
- Add getSavedRepos query (protected, feature flag)
- Add updateSavedRepos mutation (protected, feature flag)
- Implement merge logic for sync
- Add Zod validation schemas
- Feature flag: FEATURE_SAVED_REPOS_DB
- Fix z.record() type arguments for Zod compatibility
- Create CHANGELOG entry with feature details
- Create comprehensive feature documentation (SAVED_REPOS.md)
- Add PR plan with commit strategy (PR_PLAN_SAVED_REPOS.md)
- Include quickstart guide (QUICKSTART_SAVED_REPOS.md)
- Add usage guide, API reference, architecture details
- Include troubleshooting and rollout strategy
- Fix import issues in SavedProjectsPanel (add ChangeEvent type import, remove unused SavedRepo, reorder imports)
- Add block scope to switch cases in savedRepos.service to prevent variable leaking
- Fix invalid Tailwind class hover:bg-white-500 to hover:bg-ox-purple/80 in ProjectsContainer
- Add keyboard accessibility (Enter/Space) and aria-labels to buttons
- Add importAndValidate method to store for safe data validation and deduplication
- Replace unsafe popularity type assertion with proper validation in SaveToggle
- Remove nested interactive elements (move onClick to button from div)
- Remove unused Checkbox import from SaveToggle
- Update PR plan with correct issue number (apsinghdev#219)
- Replace hardcoded Windows path with cross-platform placeholder in docs

All changes improve code quality, type safety, accessibility, and documentation.
- Remove unused setAll from store destructuring
- Keep only used hooks: savedProjects, clearAllSaved, removeProject, importAndValidate
…hdev#292)

- Add docker-compose.yml for full-stack orchestration (PostgreSQL, API, Web)
- Add Dockerfile.dev with hot-reload support for development
- Add Makefile with automation targets (setup, start, stop, logs, etc.)
- Add setup.ps1 for Windows users without Make
- Add scripts/setup.sh interactive setup wizard
- Add apps/web/.env.example environment template
- Add apps/api/prisma/seed.ts for database seeding
- Add /health endpoint to API for Docker healthchecks
- Update README.md with simplified Quick Start guide
- Update tsconfig.json to exclude prisma/dist folders
- Update .gitignore to allow .env.example files

Resolves apsinghdev#292
@vercel
Copy link

vercel bot commented Dec 18, 2025

@Lucifer-0612 is attempting to deploy a commit to the AJEET PRATAP SINGH's projects Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 18, 2025

Walkthrough

Adds a Saved Repos feature spanning frontend, backend, shared types, DB migration, docs, and dev tooling. Frontend provides a Zustand localStorage store, UI components (save toggle, panel, import/export), and optional server sync behind FEATURE_SAVED_REPOS_DB with tRPC endpoints and timestamp-based merge logic.

Changes

Cohort / File(s) Summary
Shared types
packages/shared/types/index.ts, packages/shared/types/savedRepos.ts
New types: SavedRepo, SavedReposAction (`'add'
Frontend — store
apps/web/src/store/useSavedProjectsStore.ts
New Zustand store persisted to localStorage (oss_saved_repos_v1) with add/remove/toggle/clear/set/importAndValidate/isSaved, 100-item cap, dedupe and JSON import validation.
Frontend — UI
apps/web/src/components/dashboard/SaveToggle.tsx, apps/web/src/components/dashboard/SavedProjectsPanel.tsx, apps/web/src/components/dashboard/ProjectsContainer.tsx
SaveToggle button per row; SavedProjectsPanel for list, export/import/clear/remove with confirmations; ProjectsContainer adds Save column, Saved Projects button with count badge and panel integration.
Backend — service & API
apps/api/src/services/savedRepos.service.ts, apps/api/src/routers/user.ts, apps/api/src/index.ts
New savedReposService with getSavedRepos, mergeSavedRepos (prefer newer savedAt), updateSavedRepos (add/remove/replace, max 100). New tRPC endpoints getSavedRepos, updateSavedRepos (feature-flag gated). Added GET /health.
Database & migration
apps/api/prisma/schema.prisma, migration add_saved_repos
Added saved_repos Json @default("[]") field to User model; migration to add the column.
Prisma seed & package config
apps/api/prisma/seed.ts, apps/api/package.json
Minor formatting in seed; added top-level prisma.seed entry in package.json.
Docker & dev tooling
Dockerfile.dev, docker-compose.yml, Makefile
New multi-stage Dockerfile.dev, docker-compose.yml for postgres/api/web, and Makefile targets for setup, start/stop, migrate, seed, logs, health, reset, etc.
Setup automation
scripts/setup.sh, setup.ps1
New setup scripts (shell & PowerShell): preflight checks, env file generation, secret generation, start services, run migrations/seeding, and user guidance.
Web env & ignore
apps/web/.env.example, apps/web/.gitignore
New .env.example template; .gitignore adjusted to track .env.example while ignoring other .env*.
Build / config tweaks
apps/api/tsconfig.json, apps/web/tailwind.config.ts
Removed some TS compiler options; tailwind status colors refactored to nested {DEFAULT, bg, text, border} tokens.
Docs & planning
README.md, CHANGELOG.md, docs/SAVED_REPOS.md, docs/PR_PLAN_SAVED_REPOS.md, docs/QUICKSTART_SAVED_REPOS.md
README rewritten Docker-first; added CHANGELOG entry and comprehensive Saved Repos docs, quickstart, and PR plan.
Misc
package.json, small edits
Other minor formatting and manifest adjustments across repo (exports, newline fixes).

Sequence Diagram(s)

sequenceDiagram
    participant Browser as Client (Browser)
    participant UI as Frontend UI
    participant Store as Zustand (localStorage)
    participant API as tRPC Backend
    participant DB as Postgres (User.saved_repos JSONB)

    Browser->>UI: Click save/unsave
    UI->>Store: toggleProject(id) → update local state & localStorage

    alt FEATURE_SAVED_REPOS_DB = true (sync)
      UI->>API: updateSavedRepos(action, repos, localRepos?)
      API->>DB: SELECT saved_repos FROM users WHERE id=…
      DB-->>API: serverSavedRepos
      API->>API: if localRepos and action=replace → mergeSavedRepos(local, server)
      API->>DB: UPDATE users SET saved_repos = merged/updated
      DB-->>API: ack
      API-->>UI: return updated saved_repos
      UI->>Store: setAll(updatedSavedRepos)
    else
      UI->>Store: no server sync (client-only)
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

  • Review focus:
    • merge/conflict resolution in savedReposService.mergeSavedRepos() (timestamp logic, stable dedupe, sort).
    • Feature flag gating and error handling in apps/api/src/routers/user.ts.
    • Validation, deduplication, import flow and 100-item cap in useSavedProjectsStore.
    • UI event handling: stopPropagation usage in SaveToggle and accessibility attributes.
    • Cross-platform shell/PowerShell scripts (secret generation, sed differences, migration automation).
    • Dockerfile.dev and docker-compose health/dependency ordering.

Possibly related PRs

Poem

🐰 I hop and stash each shining repo star,
Timestamps decide which wins the spar,
Local store hums, Docker starts the show,
Merge and sync when flags allow, we go —
Happy hopper, saved repos afar.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'fix: Improve DX with automated setup and Docker orchestration' directly summarizes the main change—providing automated Docker-based setup to improve developer experience.
Linked Issues check ✅ Passed The PR fully addresses issue #292 objectives: automated setup scripts (setup.sh, setup.ps1), Docker orchestration (docker-compose.yml, Dockerfile.dev), Makefile automation, secret generation, migrations/seeding, and improved documentation with troubleshooting.
Out of Scope Changes check ✅ Passed All changes directly support the automated setup and Docker orchestration objectives. Minor out-of-scope modifications (tsconfig.json compiler flags, tailwind.config.ts color structure) are tangential but reasonable housekeeping within a DX improvement PR.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b203d25 and df645b8.

📒 Files selected for processing (1)
  • apps/web/src/components/dashboard/SavedProjectsPanel.tsx (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/web/src/components/dashboard/SavedProjectsPanel.tsx

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@cla-assistant
Copy link

cla-assistant bot commented Dec 18, 2025

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

- Resolved seed.ts: Combined comprehensive upstream seed with QueryCount
- Resolved tsconfig.json: Added include and node_modules to exclude
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (18)
apps/web/src/data/blogs.ts (1)

15-15: Consider using UPPER_SNAKE_CASE for the constant.

As per coding guidelines, constants should use UPPER_SNAKE_CASE. Renaming blogs to BLOGS would align with the project's naming conventions.

🔎 Apply this diff to follow the naming convention:
-export const blogs: BlogPost[] = [
+export const BLOGS: BlogPost[] = [

Note: This change will require updating all imports and usages of blogs to BLOGS throughout the codebase.

Dockerfile.dev (1)

26-26: Minor: trailing whitespace.

Line 26 has trailing whitespace after packages/ui/package.json.

🔎 Suggested fix
-COPY packages/ui/package.json ./packages/ui/ 
+COPY packages/ui/package.json ./packages/ui/
setup.ps1 (2)

107-119: Fixed sleep for DB readiness is brittle.

Using Start-Sleep -Seconds 10 (line 109) assumes the database will be ready within 10 seconds, but startup time varies by system load. Consider polling the database health endpoint or using a retry loop for more reliable behavior.

🔎 Suggested improvement
 Write-Host ""
 Write-Host "Waiting for database to be ready..." -ForegroundColor Yellow
-Start-Sleep -Seconds 10
+$maxRetries = 30
+$retryCount = 0
+while ($retryCount -lt $maxRetries) {
+    try {
+        docker compose exec -T db pg_isready -U postgres | Out-Null
+        Write-Host "   [OK] Database is ready" -ForegroundColor Green
+        break
+    } catch {
+        $retryCount++
+        Start-Sleep -Seconds 1
+    }
+}
+if ($retryCount -eq $maxRetries) {
+    Write-Host "   [WARN] Database may not be fully ready" -ForegroundColor Yellow
+}

60-64: Consider disposing the crypto provider.

RNGCryptoServiceProvider implements IDisposable. While PowerShell's garbage collector will eventually clean it up, explicit disposal is cleaner for security-sensitive objects.

🔎 Suggested fix
 function Generate-Secret {
     $bytes = New-Object byte[] 32
-    [Security.Cryptography.RNGCryptoServiceProvider]::Create().GetBytes($bytes)
+    $rng = [Security.Cryptography.RNGCryptoServiceProvider]::Create()
+    try {
+        $rng.GetBytes($bytes)
+    } finally {
+        $rng.Dispose()
+    }
     return [Convert]::ToBase64String($bytes)
 }
README.md (2)

79-86: Markdown formatting improvements.

A few markdown lint issues:

  • Line 80: Code block lacks a language specifier
  • Line 86: Bare URL should use markdown link syntax
🔎 Suggested fixes
 6. Copy credentials to `apps/web/.env.local`:
-   ```
+   ```env
    GOOGLE_CLIENT_ID="your-client-id"
    GOOGLE_CLIENT_SECRET="your-client-secret"
    ```
 7. Restart: `make restart`

-**Done! 🎉** Visit http://localhost:3000
+**Done! 🎉** Visit [http://localhost:3000](http://localhost:3000)

197-197: Bare URLs in manual setup section.

Consider using markdown link syntax for consistency.

🔎 Suggested fix
-Frontend: http://localhost:3000 | API: http://localhost:8080
+Frontend: [http://localhost:3000](http://localhost:3000) | API: [http://localhost:8080](http://localhost:8080)
scripts/setup.sh (1)

112-124: Fixed sleep for DB readiness is brittle.

Similar to the PowerShell script, using sleep 8 (line 114) assumes database startup time. Consider a health-check loop for more reliable behavior across different systems.

🔎 Suggested improvement
 echo ""
 echo -e "${YELLOW}Waiting for database to be ready...${NC}"
-sleep 8
+max_retries=30
+retry_count=0
+while [ $retry_count -lt $max_retries ]; do
+    if docker compose exec -T db pg_isready -U postgres &>/dev/null; then
+        echo -e "${GREEN}   [OK] Database is ready${NC}"
+        break
+    fi
+    retry_count=$((retry_count + 1))
+    sleep 1
+done
+if [ $retry_count -eq $max_retries ]; then
+    echo -e "${YELLOW}   [WARN] Database may not be fully ready${NC}"
+fi
docs/PR_PLAN_SAVED_REPOS.md (1)

4-6: Add language specifier to fenced code block.

The code block is missing a language specifier. Since it's a PR title (plain text), you can use text or omit the fence entirely.

🔎 Suggested fix:
 ## PR Title
-```
+```text
 feat: Saved Projects — local persistence + optional DB sync
</details>

</blockquote></details>
<details>
<summary>docker-compose.yml (2)</summary><blockquote>

`49-50`: **Seed failures are silently ignored.**

The `|| true` suppresses seed script failures, which could mask issues during development. If the seed is required for the app to function (as noted in the seed script comment), consider removing `|| true` or logging the failure more explicitly.



<details>
<summary>🔎 Suggested fix:</summary>

```diff
     command: >
-      sh -c "pnpm exec prisma migrate deploy && pnpm exec prisma db seed || true && pnpm run dev"
+      sh -c "pnpm exec prisma migrate deploy && pnpm exec prisma db seed && pnpm run dev"

Alternatively, if you want to allow seed failures but still log them:

    command: >
      sh -c "pnpm exec prisma migrate deploy && (pnpm exec prisma db seed || echo 'Warning: Seed failed') && pnpm run dev"

69-70: Consider waiting for api health before starting web.

The web service starts as soon as the api container starts, not when it's healthy. This may cause initial connection errors if web tries to reach the api before it's ready.

🔎 Suggested fix:
     depends_on:
-      - api
+      api:
+        condition: service_healthy
packages/shared/types/savedRepos.ts (1)

9-9: Prefer unknown over any for extensible metadata.

Per coding guidelines, avoid any type. Using Record<string, unknown> maintains flexibility while requiring type narrowing when accessing values.

🔎 Suggested fix:
-  meta?: Record<string, any>; // Extensible metadata
+  meta?: Record<string, unknown>; // extensible metadata
apps/web/src/components/dashboard/SaveToggle.tsx (2)

13-13: Use arrow function declaration per coding guidelines.

Per project guidelines, prefer const with arrow functions over function declarations.

🔎 Suggested fix:
-export default function SaveToggle({ project }: SaveToggleProps) {
+const SaveToggle = ({ project }: SaveToggleProps) => {
     const { toggleProject, isSaved } = useSavedProjectsStore();
     // ... rest of component
-}
+};
+
+export default SaveToggle;

3-7: Reorganize imports per coding guidelines.

Per guidelines, organize imports as: react → third-party → local components → utils → types.

🔎 Suggested fix:
 "use client";

+import { StarIcon } from "@heroicons/react/24/solid";
+import { StarIcon as StarOutlineIcon } from "@heroicons/react/24/outline";
+import { SavedRepo } from "@opensox/shared";
+
 import { useSavedProjectsStore } from "@/store/useSavedProjectsStore";
 import { DashboardProjectsProps } from "@/types";
-import { SavedRepo } from "@opensox/shared";
-import { StarIcon } from "@heroicons/react/24/solid";
-import { StarIcon as StarOutlineIcon } from "@heroicons/react/24/outline";
apps/api/src/routers/user.ts (2)

40-47: Add error logging with context for debugging.

Per coding guidelines, errors should be logged with context (userId, endpoint, timestamp). Consider wrapping the service call in try-catch to log errors before they propagate to the tRPC error handler.

🔎 Apply this diff to add error logging:
  getSavedRepos: protectedProcedure.query(async ({ ctx }: any) => {
    if (process.env.FEATURE_SAVED_REPOS_DB !== "true") {
      return [];
    }
    const userId = ctx.user.id;
-   return await savedReposService.getSavedRepos(ctx.db.prisma, userId);
+   try {
+     return await savedReposService.getSavedRepos(ctx.db.prisma, userId);
+   } catch (error) {
+     console.error('getSavedRepos failed', { userId, error, timestamp: new Date().toISOString() });
+     throw error;
+   }
  }),

82-114: Add error logging with context for debugging.

Per coding guidelines, critical operations should be logged with context. Consider adding try-catch with error logging for the mutation.

🔎 Apply this diff to add error logging:
    .mutation(async ({ ctx, input }: any) => {
      if (process.env.FEATURE_SAVED_REPOS_DB !== "true") {
        throw new Error("Saved repos sync is not enabled");
      }

      const userId = ctx.user.id;
+     try {
        // If localRepos provided, merge with server repos
        if (input.localRepos && input.action === "replace") {
          const serverRepos = await savedReposService.getSavedRepos(
            ctx.db.prisma,
            userId
          );
          const merged = savedReposService.mergeSavedRepos(
            input.localRepos,
            serverRepos
          );
          return await savedReposService.updateSavedRepos(
            ctx.db.prisma,
            userId,
            "replace",
            merged
          );
        }

        // Otherwise, perform the requested action
        return await savedReposService.updateSavedRepos(
          ctx.db.prisma,
          userId,
          input.action,
          input.repos
        );
+     } catch (error) {
+       console.error('updateSavedRepos failed', { userId, action: input.action, error, timestamp: new Date().toISOString() });
+       throw error;
+     }
    }),
apps/api/src/services/savedRepos.service.ts (1)

9-24: Include userId in error messages for better debugging.

The error messages "User not found" on lines 19 and 67 don't include the userId, making debugging harder. Per coding guidelines, errors should be logged with context.

🔎 Apply this diff to improve error messages:
        if (!user) {
-           throw new Error("User not found");
+           throw new Error(`User not found: ${userId}`);
        }

Apply the same change on line 67 in updateSavedRepos.

Also applies to: 55-68

apps/web/src/components/dashboard/SavedProjectsPanel.tsx (1)

42-68: Replace alert() with toast notifications for better UX.

Lines 53, 55, and 59 use alert() for user feedback. This provides a poor user experience compared to modern toast notifications. Consider using a toast library (e.g., react-hot-toast, sonner) for non-blocking feedback.

The JSON parsing is properly wrapped in try-catch and the validation logic through importAndValidate is correct.

docs/QUICKSTART_SAVED_REPOS.md (1)

41-87: Clarify package manager consistency in Quick Start instructions.

The Quick Start mixes npm run build (line 56) with pnpm run build (line 57) and uses pnpm commands thereafter (lines 65, 76, 86). This could confuse users unfamiliar with monorepo setups. Commit to one package manager or clearly indicate both are interchangeable.

Additionally, the migration command on line 82 assumes add_saved_repos is a new migration name, but if this migration has already been created in the PR, the command will fail. Clarify the expected state.

🔎 Suggested clarification:
-# or
-pnpm run build

Add a note above Step 2:

+**Note:** These examples use `pnpm`. If you prefer `npm`, substitute `npm` for `pnpm` in all commands below.

For the migration step, add:

-# Run migration
-npx prisma migrate dev --name add_saved_repos
+# Run migration (skip if already applied)
+npx prisma migrate dev
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 571fb83 and abbe479.

📒 Files selected for processing (26)
  • CHANGELOG.md (1 hunks)
  • Dockerfile.dev (1 hunks)
  • Makefile (1 hunks)
  • README.md (1 hunks)
  • apps/api/package.json (2 hunks)
  • apps/api/prisma/schema.prisma (1 hunks)
  • apps/api/prisma/seed.ts (1 hunks)
  • apps/api/src/index.ts (1 hunks)
  • apps/api/src/routers/user.ts (2 hunks)
  • apps/api/src/services/savedRepos.service.ts (1 hunks)
  • apps/api/tsconfig.json (1 hunks)
  • apps/web/.env.example (1 hunks)
  • apps/web/.gitignore (1 hunks)
  • apps/web/src/components/dashboard/ProjectsContainer.tsx (6 hunks)
  • apps/web/src/components/dashboard/SaveToggle.tsx (1 hunks)
  • apps/web/src/components/dashboard/SavedProjectsPanel.tsx (1 hunks)
  • apps/web/src/data/blogs.ts (4 hunks)
  • apps/web/src/store/useSavedProjectsStore.ts (1 hunks)
  • docker-compose.yml (1 hunks)
  • docs/PR_PLAN_SAVED_REPOS.md (1 hunks)
  • docs/QUICKSTART_SAVED_REPOS.md (1 hunks)
  • docs/SAVED_REPOS.md (1 hunks)
  • packages/shared/types/index.ts (1 hunks)
  • packages/shared/types/savedRepos.ts (1 hunks)
  • scripts/setup.sh (1 hunks)
  • setup.ps1 (1 hunks)
🧰 Additional context used
📓 Path-based instructions (23)
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.cursorrules)

**/*.{ts,tsx,js,jsx}: Always use lowercase when writing comments
Avoid unnecessary comments; code should be self-documenting when possible
Use comments to explain 'why', not 'what'
Remove unused imports
Use UPPER_SNAKE_CASE for constants
Use camelCase for functions and variables

Files:

  • apps/api/src/index.ts
  • apps/web/src/components/dashboard/SaveToggle.tsx
  • packages/shared/types/savedRepos.ts
  • apps/web/src/data/blogs.ts
  • apps/api/prisma/seed.ts
  • apps/api/src/routers/user.ts
  • packages/shared/types/index.ts
  • apps/web/src/store/useSavedProjectsStore.ts
  • apps/web/src/components/dashboard/SavedProjectsPanel.tsx
  • apps/api/src/services/savedRepos.service.ts
  • apps/web/src/components/dashboard/ProjectsContainer.tsx
**/*.{tsx,ts}

📄 CodeRabbit inference engine (.cursorrules)

**/*.{tsx,ts}: Prefer functional components with TypeScript and use proper TypeScript types, avoid any
Extract reusable logic into custom hooks
Use descriptive prop names and define prop types using TypeScript interfaces or types
Prefer controlled components over uncontrolled
Use zustand for global state (located in src/store/)
Use absolute imports from @/ prefix when available
Include proper aria labels for accessibility
Ensure keyboard navigation works
Maintain proper heading hierarchy
Provide alt text for images
Avoid unnecessary re-renders

Files:

  • apps/api/src/index.ts
  • apps/web/src/components/dashboard/SaveToggle.tsx
  • packages/shared/types/savedRepos.ts
  • apps/web/src/data/blogs.ts
  • apps/api/prisma/seed.ts
  • apps/api/src/routers/user.ts
  • packages/shared/types/index.ts
  • apps/web/src/store/useSavedProjectsStore.ts
  • apps/web/src/components/dashboard/SavedProjectsPanel.tsx
  • apps/api/src/services/savedRepos.service.ts
  • apps/web/src/components/dashboard/ProjectsContainer.tsx
**/*.{tsx,ts,jsx,js}

📄 CodeRabbit inference engine (.cursorrules)

Organize imports: react → third-party → local components → utils → types

Files:

  • apps/api/src/index.ts
  • apps/web/src/components/dashboard/SaveToggle.tsx
  • packages/shared/types/savedRepos.ts
  • apps/web/src/data/blogs.ts
  • apps/api/prisma/seed.ts
  • apps/api/src/routers/user.ts
  • packages/shared/types/index.ts
  • apps/web/src/store/useSavedProjectsStore.ts
  • apps/web/src/components/dashboard/SavedProjectsPanel.tsx
  • apps/api/src/services/savedRepos.service.ts
  • apps/web/src/components/dashboard/ProjectsContainer.tsx
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursorrules)

**/*.{ts,tsx}: Use PascalCase for types and interfaces with descriptive names
Use dynamic imports for code splitting when appropriate
Memoize expensive computations

Files:

  • apps/api/src/index.ts
  • apps/web/src/components/dashboard/SaveToggle.tsx
  • packages/shared/types/savedRepos.ts
  • apps/web/src/data/blogs.ts
  • apps/api/prisma/seed.ts
  • apps/api/src/routers/user.ts
  • packages/shared/types/index.ts
  • apps/web/src/store/useSavedProjectsStore.ts
  • apps/web/src/components/dashboard/SavedProjectsPanel.tsx
  • apps/api/src/services/savedRepos.service.ts
  • apps/web/src/components/dashboard/ProjectsContainer.tsx
**/*.{js,jsx,ts,tsx,py,java,go,rb,php}

📄 CodeRabbit inference engine (.cursor/rules/general_rules.mdc)

**/*.{js,jsx,ts,tsx,py,java,go,rb,php}: Always use lowercase when writing comments
Avoid unnecessary comments; code should be self-documenting when possible
Use comments to explain 'why', not 'what'

Files:

  • apps/api/src/index.ts
  • apps/web/src/components/dashboard/SaveToggle.tsx
  • packages/shared/types/savedRepos.ts
  • apps/web/src/data/blogs.ts
  • apps/api/prisma/seed.ts
  • apps/api/src/routers/user.ts
  • packages/shared/types/index.ts
  • apps/web/src/store/useSavedProjectsStore.ts
  • apps/web/src/components/dashboard/SavedProjectsPanel.tsx
  • apps/api/src/services/savedRepos.service.ts
  • apps/web/src/components/dashboard/ProjectsContainer.tsx
apps/api/src/**/*.{js,ts}

📄 CodeRabbit inference engine (apps/api/.cursor/rules/backend_rules.mdc)

apps/api/src/**/*.{js,ts}: Log errors with context (userId, endpoint, timestamp) for debugging
Always await async operations; never forget to handle promise rejections
Never log sensitive information (passwords, tokens, credit card numbers)

Files:

  • apps/api/src/index.ts
  • apps/api/src/routers/user.ts
  • apps/api/src/services/savedRepos.service.ts
apps/api/src/**/*.ts

📄 CodeRabbit inference engine (apps/api/.cursor/rules/backend_rules.mdc)

Avoid any type; use unknown for truly dynamic data and narrow with type guards

Files:

  • apps/api/src/index.ts
  • apps/api/src/routers/user.ts
  • apps/api/src/services/savedRepos.service.ts
apps/api/src/{index,main,app,server}.{js,ts}

📄 CodeRabbit inference engine (apps/api/.cursor/rules/backend_rules.mdc)

Validate required environment variables on startup; fail fast if missing

Files:

  • apps/api/src/index.ts
apps/web/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursorrules)

apps/web/src/**/*.{ts,tsx}: Always follow the design system defined in apps/web/src/lib/design-tokens.ts and apps/web/tailwind.config.ts
NEVER use hardcoded hex values (e.g., #5519f7) directly in components; ALWAYS reference colors from the design token system using Tailwind classes
Use semantic color names that describe purpose, not appearance
Use font-sans for standard UI text (Geist Sans) and font-mono for code, technical content, or monospace needs (DM Mono)
Follow Tailwind's spacing scale (0.25rem increments); for section padding use mobile p-4 (1rem) and desktop p-[60px]
Use appropriate border radius: small elements rounded-lg, medium rounded-xl, large rounded-2xl, buttons rounded-[16px]
Use animation durations: fast duration-100 (0.1s), normal duration-300 (0.3s), slow duration-600 (0.6s)

Files:

  • apps/web/src/components/dashboard/SaveToggle.tsx
  • apps/web/src/data/blogs.ts
  • apps/web/src/store/useSavedProjectsStore.ts
  • apps/web/src/components/dashboard/SavedProjectsPanel.tsx
  • apps/web/src/components/dashboard/ProjectsContainer.tsx
**/*[A-Z]*.{tsx,ts}

📄 CodeRabbit inference engine (.cursorrules)

Use PascalCase for component file names (e.g., UserProfile.tsx)

Files:

  • apps/web/src/components/dashboard/SaveToggle.tsx
  • packages/shared/types/savedRepos.ts
  • apps/web/src/store/useSavedProjectsStore.ts
  • apps/web/src/components/dashboard/SavedProjectsPanel.tsx
  • apps/api/src/services/savedRepos.service.ts
  • apps/web/src/components/dashboard/ProjectsContainer.tsx
apps/web/src/**/*.{tsx,ts}

📄 CodeRabbit inference engine (.cursorrules)

Optimize images using next/image

apps/web/src/**/*.{tsx,ts}: Use Zustand for global state, located in src/store/
Use PascalCase for types and interfaces with descriptive names
Use dynamic imports for code splitting when appropriate
Optimize images using next/image
Memoize expensive computations
Define a type when defining const functions

Files:

  • apps/web/src/components/dashboard/SaveToggle.tsx
  • apps/web/src/data/blogs.ts
  • apps/web/src/store/useSavedProjectsStore.ts
  • apps/web/src/components/dashboard/SavedProjectsPanel.tsx
  • apps/web/src/components/dashboard/ProjectsContainer.tsx
apps/web/src/components/**/*.{tsx,ts,jsx,js}

📄 CodeRabbit inference engine (apps/web/.cursor/rules/frontend_rules.mdc)

apps/web/src/components/**/*.{tsx,ts,jsx,js}: Never use hardcoded hex values directly in components; always reference colors from the design token system using Tailwind classes
Use semantic color names from the design token system that describe purpose, not appearance (e.g., bg-brand-purple, bg-surface-primary, text-text-primary)
Use font-sans for standard UI text (Geist Sans) and font-mono for code, technical content, or monospace needs (DM Mono)
Follow Tailwind's spacing scale for section padding: p-4 (1rem) on mobile, p-[60px] on desktop
Use rounded-lg (0.5rem) for small elements, rounded-xl (1rem) for medium elements, rounded-2xl (1.5rem) for large elements, and rounded-[16px] for buttons
Use duration-100 (0.1s) for fast transitions, duration-300 (0.3s) for normal transitions, and duration-600 (0.6s) for slow transitions
Use available custom animations: animate-accordion-down, animate-accordion-up, animate-scrollRight, animate-scrollLeft, animate-customspin, animate-spin-slow, animate-spin-slow-reverse, animate-marquee, animate-marquee-vertical, animate-shine
Prefer functional components with TypeScript
Extract reusable logic into custom hooks
Prefer controlled components over uncontrolled
Include proper aria labels for accessibility
Ensure keyboard navigation works in interactive components
Maintain proper heading hierarchy in page components
Provide alt text for images
Use 'class:' instead of the ternary operator in class tags whenever possible
Implement accessibility features on interactive elements (e.g., tabindex='0', aria-label, onClick, onKeyDown)
Always follow the design system defined in apps/web/src/lib/design-tokens.ts and apps/web/tailwind.config.ts

Files:

  • apps/web/src/components/dashboard/SaveToggle.tsx
  • apps/web/src/components/dashboard/SavedProjectsPanel.tsx
  • apps/web/src/components/dashboard/ProjectsContainer.tsx
apps/web/src/components/**/*.{tsx,ts}

📄 CodeRabbit inference engine (apps/web/.cursor/rules/frontend_rules.mdc)

apps/web/src/components/**/*.{tsx,ts}: Use proper TypeScript types and avoid using any type
Use descriptive prop names and define prop types using TypeScript interfaces or types
Name components using PascalCase (e.g., UserProfile.tsx)

Files:

  • apps/web/src/components/dashboard/SaveToggle.tsx
  • apps/web/src/components/dashboard/SavedProjectsPanel.tsx
  • apps/web/src/components/dashboard/ProjectsContainer.tsx
apps/web/src/**/*.{tsx,ts,jsx,js}

📄 CodeRabbit inference engine (apps/web/.cursor/rules/frontend_rules.mdc)

apps/web/src/**/*.{tsx,ts,jsx,js}: Organize imports in order: React → third-party → local components → utils → types
Use absolute imports from @/ prefix when available
Remove unused imports
Use UPPER_SNAKE_CASE for constants
Use camelCase for functions and variables
Always use Tailwind classes for styling HTML elements; avoid using CSS or style tags
Use descriptive variable and function names; name event functions with a 'handle' prefix (e.g., handleClick, handleKeyDown)
Use const with arrow functions instead of function declarations (e.g., 'const toggle = () =>')

Files:

  • apps/web/src/components/dashboard/SaveToggle.tsx
  • apps/web/src/data/blogs.ts
  • apps/web/src/store/useSavedProjectsStore.ts
  • apps/web/src/components/dashboard/SavedProjectsPanel.tsx
  • apps/web/src/components/dashboard/ProjectsContainer.tsx
apps/api/src/**/{services,models,database}/*.{js,ts}

📄 CodeRabbit inference engine (apps/api/.cursor/rules/backend_rules.mdc)

Encrypt sensitive data (passwords, tokens, API keys) before storing in database

Files:

  • apps/api/src/services/savedRepos.service.ts
apps/api/src/**/{database,services}/*.{js,ts}

📄 CodeRabbit inference engine (apps/api/.cursor/rules/backend_rules.mdc)

Handle database connection failures gracefully with retry logic

Files:

  • apps/api/src/services/savedRepos.service.ts
apps/api/src/**/{database,models,services}/*.{js,ts}

📄 CodeRabbit inference engine (apps/api/.cursor/rules/backend_rules.mdc)

Always use parameterized queries or ORM methods to prevent SQL injection

Files:

  • apps/api/src/services/savedRepos.service.ts
apps/api/src/**/{services,database}/*.{js,ts}

📄 CodeRabbit inference engine (apps/api/.cursor/rules/backend_rules.mdc)

Wrap database transactions in try-catch blocks with proper rollback on failure

Files:

  • apps/api/src/services/savedRepos.service.ts
apps/api/src/**/{services,repositories}/*.{js,ts}

📄 CodeRabbit inference engine (apps/api/.cursor/rules/backend_rules.mdc)

Avoid N+1 queries; use eager loading or batch queries when fetching related data

Files:

  • apps/api/src/services/savedRepos.service.ts
apps/api/src/**/{services,models}/*.{js,ts}

📄 CodeRabbit inference engine (apps/api/.cursor/rules/backend_rules.mdc)

Validate data against schema before database operations

Files:

  • apps/api/src/services/savedRepos.service.ts
apps/api/src/**/{database,clients,services}/*.{js,ts}

📄 CodeRabbit inference engine (apps/api/.cursor/rules/backend_rules.mdc)

Use connection pooling for database and external service clients

Files:

  • apps/api/src/services/savedRepos.service.ts
apps/api/src/**/{services,clients,handlers}/*.{js,ts}

📄 CodeRabbit inference engine (apps/api/.cursor/rules/backend_rules.mdc)

Implement timeouts for external API calls to prevent hanging requests

Files:

  • apps/api/src/services/savedRepos.service.ts
apps/api/src/**/{middleware,services,routes,controllers}/*.{js,ts}

📄 CodeRabbit inference engine (apps/api/.cursor/rules/backend_rules.mdc)

Log all critical operations (auth attempts, payment processing, data mutations)

Files:

  • apps/api/src/services/savedRepos.service.ts
🧠 Learnings (22)
📚 Learning: 2025-11-25T07:34:58.984Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/api/.cursor/rules/backend_rules.mdc:0-0
Timestamp: 2025-11-25T07:34:58.984Z
Learning: Applies to apps/api/src/**/{routes,middleware}/*.{js,ts} : Implement rate limiting on all public endpoints to prevent abuse

Applied to files:

  • apps/api/src/index.ts
📚 Learning: 2025-11-25T07:34:58.984Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/api/.cursor/rules/backend_rules.mdc:0-0
Timestamp: 2025-11-25T07:34:58.984Z
Learning: Applies to apps/api/src/**/{routes,controllers,handlers}/*.{js,ts} : Return appropriate HTTP status codes (400 for validation, 401 for auth, 500 for server errors)

Applied to files:

  • apps/api/src/index.ts
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/**/*.{tsx,ts,jsx,js} : Use const with arrow functions instead of function declarations (e.g., 'const toggle = () =>')

Applied to files:

  • apps/web/src/components/dashboard/SaveToggle.tsx
📚 Learning: 2025-12-17T12:39:29.991Z
Learnt from: huamanraj
Repo: apsinghdev/opensox PR: 262
File: apps/web/src/components/checkout/CheckoutWrapper.tsx:5-5
Timestamp: 2025-12-17T12:39:29.991Z
Learning: In Next.js apps, avoid using redirect() from next/navigation inside Client Components during render. It should not be used in event handlers like onClick or onSubmit; for those cases, use useRouter().push() or router.replace() instead. This guidance applies to TSX files (React components) across the codebase; implement in client components to handle conditional redirects during render, and use router-based navigation in handlers.

Applied to files:

  • apps/web/src/components/dashboard/SaveToggle.tsx
  • apps/web/src/components/dashboard/SavedProjectsPanel.tsx
  • apps/web/src/components/dashboard/ProjectsContainer.tsx
📚 Learning: 2025-11-25T07:34:58.984Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/api/.cursor/rules/backend_rules.mdc:0-0
Timestamp: 2025-11-25T07:34:58.984Z
Learning: Applies to apps/api/src/**/database/**/*.{js,ts} : Index frequently queried fields for performance optimization

Applied to files:

  • apps/api/prisma/seed.ts
📚 Learning: 2025-11-25T07:34:58.984Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/api/.cursor/rules/backend_rules.mdc:0-0
Timestamp: 2025-11-25T07:34:58.984Z
Learning: Applies to apps/api/src/**/{database,clients,services}/*.{js,ts} : Use connection pooling for database and external service clients

Applied to files:

  • apps/api/prisma/seed.ts
📚 Learning: 2025-11-25T07:34:58.984Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/api/.cursor/rules/backend_rules.mdc:0-0
Timestamp: 2025-11-25T07:34:58.984Z
Learning: Document all required environment variables in `.env.example`

Applied to files:

  • apps/web/.env.example
  • apps/web/.gitignore
📚 Learning: 2025-11-25T07:34:58.984Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/api/.cursor/rules/backend_rules.mdc:0-0
Timestamp: 2025-11-25T07:34:58.984Z
Learning: Applies to apps/api/src/**/{config,environment,setup}/*.{js,ts} : Use type-safe environment variable access with proper defaults

Applied to files:

  • apps/web/.env.example
  • apps/api/tsconfig.json
📚 Learning: 2025-11-25T07:34:58.984Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/api/.cursor/rules/backend_rules.mdc:0-0
Timestamp: 2025-11-25T07:34:58.984Z
Learning: Applies to apps/api/src/**/{routes,controllers,handlers,middleware}/*.{js,ts} : Always validate user authentication before processing protected routes

Applied to files:

  • apps/api/src/routers/user.ts
📚 Learning: 2025-11-25T07:34:58.984Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/api/.cursor/rules/backend_rules.mdc:0-0
Timestamp: 2025-11-25T07:34:58.984Z
Learning: Applies to apps/api/src/**/{routes,controllers,handlers,middleware}/*.{js,ts} : Use zod or similar for runtime validation of incoming data

Applied to files:

  • apps/api/package.json
📚 Learning: 2025-11-25T07:34:58.984Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/api/.cursor/rules/backend_rules.mdc:0-0
Timestamp: 2025-11-25T07:34:58.984Z
Learning: Export types from shared package for consistency across apps

Applied to files:

  • packages/shared/types/index.ts
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/**/*.{tsx,ts,jsx,js} : Remove unused imports

Applied to files:

  • packages/shared/types/index.ts
  • apps/web/src/components/dashboard/SavedProjectsPanel.tsx
  • apps/api/tsconfig.json
📚 Learning: 2025-11-25T07:34:58.984Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/api/.cursor/rules/backend_rules.mdc:0-0
Timestamp: 2025-11-25T07:34:58.984Z
Learning: Never commit `.env` files or hardcode secrets in code

Applied to files:

  • apps/web/.gitignore
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/**/*.{tsx,ts} : Use Zustand for global state, located in `src/store/`

Applied to files:

  • apps/web/src/store/useSavedProjectsStore.ts
📚 Learning: 2025-11-25T07:34:30.473Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T07:34:30.473Z
Learning: Applies to **/*.{tsx,ts} : Use zustand for global state (located in `src/store/`)

Applied to files:

  • apps/web/src/store/useSavedProjectsStore.ts
📚 Learning: 2025-11-25T07:34:58.984Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/api/.cursor/rules/backend_rules.mdc:0-0
Timestamp: 2025-11-25T07:34:58.984Z
Learning: Applies to apps/api/src/**/{services,repositories}/*.{js,ts} : Avoid N+1 queries; use eager loading or batch queries when fetching related data

Applied to files:

  • apps/api/src/services/savedRepos.service.ts
📚 Learning: 2025-11-25T07:34:58.984Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/api/.cursor/rules/backend_rules.mdc:0-0
Timestamp: 2025-11-25T07:34:58.984Z
Learning: Applies to apps/api/src/**/*.ts : Avoid `any` type; use `unknown` for truly dynamic data and narrow with type guards

Applied to files:

  • apps/api/tsconfig.json
📚 Learning: 2025-11-25T07:34:58.984Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/api/.cursor/rules/backend_rules.mdc:0-0
Timestamp: 2025-11-25T07:34:58.984Z
Learning: Applies to apps/api/src/**/{routes,controllers,handlers,types}/*.ts : Define strict TypeScript interfaces for request/response bodies

Applied to files:

  • apps/api/tsconfig.json
📚 Learning: 2025-11-25T07:34:30.473Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T07:34:30.473Z
Learning: Applies to **/*.{tsx,ts,jsx,js} : Organize imports: react → third-party → local components → utils → types

Applied to files:

  • apps/api/tsconfig.json
📚 Learning: 2025-11-25T07:34:30.473Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T07:34:30.473Z
Learning: Applies to **/*.{tsx,ts} : Use descriptive prop names and define prop types using TypeScript interfaces or types

Applied to files:

  • apps/api/tsconfig.json
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/**/*.{tsx,ts,jsx,js} : Organize imports in order: React → third-party → local components → utils → types

Applied to files:

  • apps/api/tsconfig.json
📚 Learning: 2025-11-25T07:34:30.473Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T07:34:30.473Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Remove unused imports

Applied to files:

  • apps/api/tsconfig.json
🧬 Code graph analysis (2)
apps/web/src/components/dashboard/SaveToggle.tsx (3)
apps/web/src/types/projects.ts (1)
  • DashboardProjectsProps (1-13)
apps/web/src/store/useSavedProjectsStore.ts (1)
  • useSavedProjectsStore (16-123)
packages/shared/types/savedRepos.ts (1)
  • SavedRepo (1-10)
apps/web/src/components/dashboard/SavedProjectsPanel.tsx (1)
apps/web/src/store/useSavedProjectsStore.ts (1)
  • useSavedProjectsStore (16-123)
🪛 checkmake (0.2.2)
Makefile

[warning] 4-4: Target body for "help" exceeds allowed length of 5 (32).

(maxbodylength)


[warning] 45-45: Target body for "start" exceeds allowed length of 5 (8).

(maxbodylength)


[warning] 1-1: Missing required phony target "all"

(minphony)

🪛 Checkov (3.2.334)
docker-compose.yml

[medium] 32-33: Basic Auth Credentials

(CKV_SECRET_4)

🪛 dotenv-linter (4.0.0)
apps/web/.env.example

[warning] 8-8: [QuoteCharacter] The value has quote characters (', ")

(QuoteCharacter)


[warning] 12-12: [QuoteCharacter] The value has quote characters (', ")

(QuoteCharacter)


[warning] 13-13: [QuoteCharacter] The value has quote characters (', ")

(QuoteCharacter)


[warning] 21-21: [QuoteCharacter] The value has quote characters (', ")

(QuoteCharacter)


[warning] 22-22: [QuoteCharacter] The value has quote characters (', ")

(QuoteCharacter)

🪛 LanguageTool
docs/PR_PLAN_SAVED_REPOS.md

[style] ~330-~330: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...ecently Saved" section on dashboard? 3. Should we implement folders/tags in this PR or...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)


[style] ~331-~331: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...nt folders/tags in this PR or later? 4. Should we add a limit warning when approaching...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)


[style] ~332-~332: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ... warning when approaching 100 repos? 5. Should we add a "Share saved repos" feature? ...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)

🪛 markdownlint-cli2 (0.18.1)
docs/PR_PLAN_SAVED_REPOS.md

4-4: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

README.md

80-80: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


86-86: Bare URL used

(MD034, no-bare-urls)


197-197: Bare URL used

(MD034, no-bare-urls)


197-197: Bare URL used

(MD034, no-bare-urls)

docs/QUICKSTART_SAVED_REPOS.md

62-62: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


69-69: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)

🔇 Additional comments (32)
apps/web/src/data/blogs.ts (1)

18-78: LGTM! Text corrections improve content quality.

All typo fixes, grammar improvements, and formatting consistency changes are accurate and enhance the user-facing content.

apps/web/.gitignore (1)

33-34: LGTM!

The pattern correctly ignores all .env* files while explicitly tracking .env.example as a template. This aligns with best practices for documenting required environment variables without committing actual secrets. Based on learnings, this is the recommended approach.

apps/api/tsconfig.json (1)

38-41: LGTM with minor consideration.

Excluding dist is correct. Excluding prisma prevents TypeScript from checking generated Prisma client types, which is appropriate. However, note that prisma/seed.ts will also be excluded from type-checking—ensure the seed script is validated separately (e.g., via pnpm exec prisma db seed which handles its own compilation).

packages/shared/types/index.ts (1)

1-3: LGTM!

Barrel export pattern correctly re-exports types from the new savedRepos module, maintaining consistency with existing exports. Based on learnings, exporting types from the shared package ensures consistency across apps.

apps/web/.env.example (1)

1-27: Well-documented environment template.

The file clearly documents all required environment variables with helpful setup instructions. The structure with REQUIRED and OPTIONAL sections improves developer experience. Based on learnings, this follows the guideline to document all required environment variables in .env.example.

The static analysis warnings about quote characters can be safely ignored—quotes are acceptable in .env files and are helpful here to indicate placeholder values.

README.md (1)

41-101: Excellent documentation overhaul.

The Docker Quick Start section is well-structured with clear steps, visual indicators (✅), and a helpful commands table. The troubleshooting section with collapsible details is a great UX improvement for new contributors. This directly addresses the PR objective of simplifying setup.

scripts/setup.sh (2)

69-88: Good cross-platform secret generation.

The OS-specific sed handling for macOS vs Linux is correct, and the fallback to /dev/urandom when openssl is unavailable ensures the script works in minimal environments.


1-27: Well-structured preflight checks.

The Docker validation (both command existence and daemon status) provides clear, actionable error messages. The colored output improves the developer experience significantly.

Dockerfile.dev (1)

21-32: Web stage must build the shared package before running dev, just like the API stage does.

The web stage copies the shared package source code (lines 23-25, 28) but never builds it. Since the shared package's package.json exports dist/index.js as the main entry point, the web app will fail at runtime when trying to import @opensox/shared. Add RUN pnpm run build in the shared package directory before starting the web dev server (after copying packages but before CMD), similar to how the API stage handles it.

apps/api/src/index.ts (1)

101-104: LGTM!

The health check endpoint is appropriately simple and stateless, returning only status and timestamp. Not applying rate limiting here is correct since container orchestrators need unrestricted access for health probes.

apps/api/prisma/schema.prisma (1)

42-42: Schema addition looks good.

The Json type with default "[]" is appropriate for storing saved repositories. Since the current implementation reads/writes the entire field rather than querying inside the JSON structure, an index isn't required now. If you later add queries filtering by JSON properties (e.g., saved_repos @> '[{"language": "TypeScript"}]'), consider adding a GIN index.

apps/api/package.json (1)

17-19: LGTM!

Standard Prisma seed configuration using tsx which is already available in devDependencies.

apps/api/prisma/seed.ts (1)

1-28: LGTM!

The seed script is well-structured:

  • Idempotent via upsert (safe for repeated runs during development)
  • Proper error handling with exit code 1 on failure
  • Clean disconnection in finally block
packages/shared/types/savedRepos.ts (1)

1-17: Type definitions are well-structured.

The types provide a clear contract between frontend and backend. The union type for SavedReposAction and structured SavedReposUpdateInput enable type-safe API interactions.

apps/web/src/components/dashboard/SaveToggle.tsx (1)

17-64: Well-implemented component with good accessibility.

Good implementation choices:

  • Type guard isValidPopularity ensures type safety
  • e.stopPropagation() prevents row click conflicts
  • aria-label and aria-pressed provide proper accessibility
  • parseFloat(...) || 0 handles invalid competition values gracefully
CHANGELOG.md (1)

1-85: LGTM! Comprehensive feature documentation.

The CHANGELOG entry clearly documents the Saved Repos feature across all layers (frontend, backend, shared types, configuration). The code examples accurately reflect the API implementation and the feature flag behavior is well documented.

apps/web/src/components/dashboard/ProjectsContainer.tsx (2)

19-22: LGTM! Clean integration of new components.

The imports are well-organized following the coding guidelines (React → third-party → local components → utils), and the "Save" column addition is straightforward.

Also applies to: 49-49


152-154: LGTM! Clean component integration.

The SaveToggle and SavedProjectsPanel components are properly integrated with correct props and state management.

Also applies to: 216-219

docs/SAVED_REPOS.md (1)

1-214: LGTM! Excellent comprehensive documentation.

The documentation is thorough, well-structured, and covers all aspects of the feature including usage, architecture, API endpoints, troubleshooting, and rollout strategy. The examples accurately reflect the implementation.

apps/api/src/services/savedRepos.service.ts (3)

30-50: LGTM! Efficient merge algorithm with correct conflict resolution.

The merge logic correctly uses a Map for O(n+m) complexity and resolves conflicts based on the savedAt timestamp. The sorting ensures newest repos appear first.


73-97: LGTM! Efficient action handlers with proper validation.

The switch statement correctly handles add, remove, and replace actions with efficient Set-based filtering. The default case properly throws for invalid actions.


99-102: LGTM! Proper enforcement of repository limits.

The 100 repository limit is correctly enforced and aligned with the documentation.

apps/web/src/components/dashboard/SavedProjectsPanel.tsx (3)

29-40: LGTM! Clean export implementation.

The export functionality correctly serializes saved projects to JSON and triggers a download with a timestamped filename. The cleanup with URL.revokeObjectURL is properly handled.


70-78: LGTM! Good confirmation pattern for destructive action.

The two-step confirmation with a 3-second timeout provides a good safety mechanism for the Clear All action.


82-209: LGTM! Well-structured accessible UI.

The component properly implements:

  • Backdrop click to close
  • Accessible buttons with aria-labels
  • Proper keyboard navigation support
  • Disabled states for empty conditions
  • Secure external links with rel="noopener noreferrer"
  • Clean responsive layout
Makefile (1)

1-128: LGTM! Well-structured development automation.

The Makefile provides comprehensive development workflow automation with clear help text, proper error handling, and safety confirmations for destructive operations.

The checkmake warnings are stylistic preferences:

  • The help target exceeds 5 lines because it provides comprehensive user guidance (intentional)
  • The missing all target is not needed since help is the appropriate default
  • The body length warnings don't indicate functional issues

The Docker Compose commands, Prisma operations, and interactive prompts are all correctly implemented.

apps/web/src/store/useSavedProjectsStore.ts (3)

21-30: LGTM! Proper duplicate prevention.

The addProject method correctly checks for existing projects by ID before adding, preventing duplicates.


37-51: LGTM! Correct toggle logic.

The toggleProject method properly checks existence and toggles the saved state accordingly.


117-122: LGTM! Proper persistence configuration.

The persist middleware is correctly configured with:

  • Versioned storage key for future migrations
  • localStorage as the storage backend
  • Partial state persistence (only savedProjects)
docs/QUICKSTART_SAVED_REPOS.md (3)

1-40: ⚠️ Major discrepancy: PR scope mismatch.

The PR objectives state this PR addresses #292 ("Improve DX with automated setup and Docker orchestration"), emphasizing single-command setup (make setup/setup.ps1), Docker Compose orchestration, automatic .env generation, and secret management. However, this document and the AI summary describe an entirely different feature: a "Saved Repos" capability for saving/syncing repositories.

Please clarify: Is this PR about Docker/DX automation, or about the Saved Repos feature? The file provided doesn't align with the stated PR objectives.


104-107: Verify cross-device sync testing instructions are actionable.

Line 106 suggests verifying saved repos "in the database (Prisma Studio)", but Prisma Studio requires a running server context. Clarify the exact steps: e.g., "Run npx prisma studio in a separate terminal" or provide a SQL query to inspect the data directly. This ensures users can actually complete this advanced test.


111-116: Verify referenced documentation files exist.

The document references docs/SAVED_REPOS.md, docs/PR_PLAN_SAVED_REPOS.md, and CHANGELOG.md (lines 113–115), and mentions "artifacts in conversation" (line 116). Confirm these files:

  1. Actually exist in the PR branch
  2. Are consistent with the quick start instructions provided here
  3. Are up-to-date with feature implementation details

Broken or outdated references undermine user confidence and cause frustration during onboarding.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between abbe479 and 86df19f.

📒 Files selected for processing (4)
  • apps/api/package.json (2 hunks)
  • apps/api/prisma/seed.ts (1 hunks)
  • apps/api/tsconfig.json (1 hunks)
  • apps/web/.gitignore (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • apps/api/prisma/seed.ts
  • apps/api/tsconfig.json
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-11-25T07:34:58.984Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/api/.cursor/rules/backend_rules.mdc:0-0
Timestamp: 2025-11-25T07:34:58.984Z
Learning: Never commit `.env` files or hardcode secrets in code

Applied to files:

  • apps/web/.gitignore
📚 Learning: 2025-11-25T07:34:58.984Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/api/.cursor/rules/backend_rules.mdc:0-0
Timestamp: 2025-11-25T07:34:58.984Z
Learning: Document all required environment variables in `.env.example`

Applied to files:

  • apps/web/.gitignore
🪛 Biome (2.1.2)
apps/api/package.json

[error] 17-17: The key prisma was already declared.

This where a duplicated key was declared again.

If a key is defined multiple times, only the last definition takes effect. Previous definitions are ignored.

(lint/suspicious/noDuplicateObjectKeys)

🔇 Additional comments (1)
apps/web/.gitignore (1)

33-34: ✓ Correct pattern for environment template management.

The negation pattern !.env.example correctly preserves the example configuration in version control while keeping actual secrets ignored. The .env.example file is properly documented with all required environment variables and setup instructions, supporting the PR's goal to simplify onboarding for new contributors.

- Replace z.any() with z.unknown() in user router meta fields
- Update SavedRepo type to use unknown instead of any
- Add proper type narrowing in isValidSavedRepo type guard
- Replace hardcoded Tailwind colors with semantic design tokens
  - Use bg-info/text-info for language badges
  - Use bg-success/text-success for popularity badges
  - Replace ox-purple with brand-purple across components
- Flatten status colors in Tailwind config for proper utilities
- Fix markdown semantics in QUICKSTART_SAVED_REPOS.md
- Remove duplicate prisma key from package.json

Type safety improvements prevent runtime errors and improve maintainability.
Design token migration ensures consistent theming and accessibility.
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
apps/web/src/store/useSavedProjectsStore.ts (1)

57-114: LGTM! Robust validation with proper type narrowing.

The importAndValidate method correctly uses unknown for the input parameter (addressing the previous review concern), implements thorough validation with a type guard, deduplicates by ID, enforces a sensible 100-item limit, and provides helpful feedback.

Note: The previous review comment about using unknown instead of any has been resolved - line 67 correctly uses (item: unknown): item is SavedRepo.

🧹 Nitpick comments (5)
apps/web/tailwind.config.ts (1)

70-93: The status color DEFAULT mapping is intentional but unnecessarily verbose for developer experience.

The .cursorrules file documents that status colors must use full modifier syntax (bg-success-bg, text-success-text, border-success-border), which is working as designed. However, since the DEFAULT key in Tailwind means "no modifier", setting DEFAULT to the text color requires developers to always use redundant compound selectors like bg-success-bg.

This pattern works but creates unnecessary cognitive overhead. Consider adopting separate top-level tokens for cleaner semantics:

-        success: {
-          DEFAULT: colors.status.success.text,
-          bg: colors.status.success.bg,
-          text: colors.status.success.text,
-          border: colors.status.success.border,
-        },
+        "success-bg": colors.status.success.bg,
+        "success-text": colors.status.success.text,
+        "success-border": colors.status.success.border,

This would allow intuitive usage (bg-success-bgbg-success-bg remains the same, but text-success-text is now unambiguous) while eliminating the confusing DEFAULT fallback. Apply this pattern consistently across success, error, warning, and info.

apps/api/src/routers/user.ts (2)

41-47: Consider consistent feature flag behavior.

When the feature flag is disabled, getSavedRepos silently returns an empty array while updateSavedRepos throws an error. This inconsistency could confuse clients - they might see an empty list and attempt to save, only to get an error.

Consider either:

  1. Having getSavedRepos also throw when the flag is disabled
  2. Having updateSavedRepos silently no-op (less recommended)

54-79: Consider extracting the duplicated repo schema.

The Zod schema for a single repo object is duplicated between repos and localRepos arrays. Extracting it improves maintainability.

🔎 Apply this diff to reduce duplication:
+const savedRepoSchema = z.object({
+  id: z.string(),
+  name: z.string(),
+  url: z.string(),
+  language: z.string().optional(),
+  popularity: z.enum(["low", "medium", "high"]).optional(),
+  competitionScore: z.number().optional(),
+  savedAt: z.string(),
+  meta: z.record(z.string(), z.unknown()).optional(),
+});
+
 updateSavedRepos: protectedProcedure
   .input(
     z.object({
       action: z.enum(["add", "remove", "replace"]),
-      repos: z.array(
-        z.object({
-          id: z.string(),
-          name: z.string(),
-          url: z.string(),
-          language: z.string().optional(),
-          popularity: z.enum(["low", "medium", "high"]).optional(),
-          competitionScore: z.number().optional(),
-          savedAt: z.string(),
-          meta: z.record(z.string(), z.unknown()).optional(),
-        })
-      ),
-      localRepos: z
-        .array(
-          z.object({
-            id: z.string(),
-            name: z.string(),
-            url: z.string(),
-            language: z.string().optional(),
-            popularity: z.enum(["low", "medium", "high"]).optional(),
-            competitionScore: z.number().optional(),
-            savedAt: z.string(),
-            meta: z.record(z.string(), z.unknown()).optional(),
-          })
-        )
-        .optional(),
+      repos: z.array(savedRepoSchema),
+      localRepos: z.array(savedRepoSchema).optional(),
     })
   )
apps/web/src/components/dashboard/ProjectsContainer.tsx (1)

19-22: Reorganize imports to follow guidelines.

Per coding guidelines, imports should be organized: React → third-party → local components → utils → types. The useState import from React should be at the top.

🔎 Apply this diff to fix import order:
 "use client";

+import { useState } from "react";
 import { Badge } from "@/components/ui/badge";
 import { Button } from "@/components/ui/button";
 import {
   Table,
   TableBody,
   TableCell,
   TableHead,
   TableHeader,
   TableRow,
 } from "@/components/ui/table";
 import { useProjectTitleStore } from "@/store/useProjectTitleStore";
 import { DashboardProjectsProps } from "@/types";
 import Image from "next/image";
 import { useFilterStore } from "@/store/useFilterStore";
 import { usePathname } from "next/navigation";
 import { MagnifyingGlassIcon } from "@heroicons/react/24/outline";
 import SaveToggle from "./SaveToggle";
 import SavedProjectsPanel from "./SavedProjectsPanel";
 import { useSavedProjectsStore } from "@/store/useSavedProjectsStore";
-import { useState } from "react";

As per coding guidelines for import organization.

apps/web/src/components/dashboard/SavedProjectsPanel.tsx (1)

29-78: Solid handler implementations with good UX patterns.

The export handler properly cleans up blob URLs, the import handler includes error handling and input reset, and the clear-all implements a nice two-step confirmation pattern.

Optional: Consider using toast notifications instead of alert()

Lines 53, 55, and 59 use alert() which blocks the UI. Consider using a toast notification library (like sonner or react-hot-toast) for better UX:

- alert(result.error || "Projects imported successfully!");
+ toast.success(result.error || "Projects imported successfully!");

This is purely a UX enhancement and not a blocker.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 86df19f and b203d25.

📒 Files selected for processing (9)
  • apps/api/package.json (2 hunks)
  • apps/api/src/routers/user.ts (2 hunks)
  • apps/api/src/services/savedRepos.service.ts (1 hunks)
  • apps/web/src/components/dashboard/ProjectsContainer.tsx (6 hunks)
  • apps/web/src/components/dashboard/SavedProjectsPanel.tsx (1 hunks)
  • apps/web/src/store/useSavedProjectsStore.ts (1 hunks)
  • apps/web/tailwind.config.ts (1 hunks)
  • docs/QUICKSTART_SAVED_REPOS.md (1 hunks)
  • packages/shared/types/savedRepos.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/api/src/services/savedRepos.service.ts
🧰 Additional context used
📓 Path-based instructions (13)
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.cursorrules)

**/*.{ts,tsx,js,jsx}: Always use lowercase when writing comments
Avoid unnecessary comments; code should be self-documenting when possible
Use comments to explain 'why', not 'what'
Remove unused imports
Use UPPER_SNAKE_CASE for constants
Use camelCase for functions and variables

Files:

  • apps/web/src/components/dashboard/SavedProjectsPanel.tsx
  • apps/web/src/components/dashboard/ProjectsContainer.tsx
  • apps/api/src/routers/user.ts
  • apps/web/tailwind.config.ts
  • packages/shared/types/savedRepos.ts
  • apps/web/src/store/useSavedProjectsStore.ts
apps/web/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursorrules)

apps/web/src/**/*.{ts,tsx}: Always follow the design system defined in apps/web/src/lib/design-tokens.ts and apps/web/tailwind.config.ts
NEVER use hardcoded hex values (e.g., #5519f7) directly in components; ALWAYS reference colors from the design token system using Tailwind classes
Use semantic color names that describe purpose, not appearance
Use font-sans for standard UI text (Geist Sans) and font-mono for code, technical content, or monospace needs (DM Mono)
Follow Tailwind's spacing scale (0.25rem increments); for section padding use mobile p-4 (1rem) and desktop p-[60px]
Use appropriate border radius: small elements rounded-lg, medium rounded-xl, large rounded-2xl, buttons rounded-[16px]
Use animation durations: fast duration-100 (0.1s), normal duration-300 (0.3s), slow duration-600 (0.6s)

Files:

  • apps/web/src/components/dashboard/SavedProjectsPanel.tsx
  • apps/web/src/components/dashboard/ProjectsContainer.tsx
  • apps/web/src/store/useSavedProjectsStore.ts
**/*.{tsx,ts}

📄 CodeRabbit inference engine (.cursorrules)

**/*.{tsx,ts}: Prefer functional components with TypeScript and use proper TypeScript types, avoid any
Extract reusable logic into custom hooks
Use descriptive prop names and define prop types using TypeScript interfaces or types
Prefer controlled components over uncontrolled
Use zustand for global state (located in src/store/)
Use absolute imports from @/ prefix when available
Include proper aria labels for accessibility
Ensure keyboard navigation works
Maintain proper heading hierarchy
Provide alt text for images
Avoid unnecessary re-renders

Files:

  • apps/web/src/components/dashboard/SavedProjectsPanel.tsx
  • apps/web/src/components/dashboard/ProjectsContainer.tsx
  • apps/api/src/routers/user.ts
  • apps/web/tailwind.config.ts
  • packages/shared/types/savedRepos.ts
  • apps/web/src/store/useSavedProjectsStore.ts
**/*.{tsx,ts,jsx,js}

📄 CodeRabbit inference engine (.cursorrules)

Organize imports: react → third-party → local components → utils → types

Files:

  • apps/web/src/components/dashboard/SavedProjectsPanel.tsx
  • apps/web/src/components/dashboard/ProjectsContainer.tsx
  • apps/api/src/routers/user.ts
  • apps/web/tailwind.config.ts
  • packages/shared/types/savedRepos.ts
  • apps/web/src/store/useSavedProjectsStore.ts
**/*[A-Z]*.{tsx,ts}

📄 CodeRabbit inference engine (.cursorrules)

Use PascalCase for component file names (e.g., UserProfile.tsx)

Files:

  • apps/web/src/components/dashboard/SavedProjectsPanel.tsx
  • apps/web/src/components/dashboard/ProjectsContainer.tsx
  • packages/shared/types/savedRepos.ts
  • apps/web/src/store/useSavedProjectsStore.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursorrules)

**/*.{ts,tsx}: Use PascalCase for types and interfaces with descriptive names
Use dynamic imports for code splitting when appropriate
Memoize expensive computations

Files:

  • apps/web/src/components/dashboard/SavedProjectsPanel.tsx
  • apps/web/src/components/dashboard/ProjectsContainer.tsx
  • apps/api/src/routers/user.ts
  • apps/web/tailwind.config.ts
  • packages/shared/types/savedRepos.ts
  • apps/web/src/store/useSavedProjectsStore.ts
apps/web/src/**/*.{tsx,ts}

📄 CodeRabbit inference engine (.cursorrules)

Optimize images using next/image

apps/web/src/**/*.{tsx,ts}: Use Zustand for global state, located in src/store/
Use PascalCase for types and interfaces with descriptive names
Use dynamic imports for code splitting when appropriate
Optimize images using next/image
Memoize expensive computations
Define a type when defining const functions

Files:

  • apps/web/src/components/dashboard/SavedProjectsPanel.tsx
  • apps/web/src/components/dashboard/ProjectsContainer.tsx
  • apps/web/src/store/useSavedProjectsStore.ts
**/*.{js,jsx,ts,tsx,py,java,go,rb,php}

📄 CodeRabbit inference engine (.cursor/rules/general_rules.mdc)

**/*.{js,jsx,ts,tsx,py,java,go,rb,php}: Always use lowercase when writing comments
Avoid unnecessary comments; code should be self-documenting when possible
Use comments to explain 'why', not 'what'

Files:

  • apps/web/src/components/dashboard/SavedProjectsPanel.tsx
  • apps/web/src/components/dashboard/ProjectsContainer.tsx
  • apps/api/src/routers/user.ts
  • apps/web/tailwind.config.ts
  • packages/shared/types/savedRepos.ts
  • apps/web/src/store/useSavedProjectsStore.ts
apps/web/src/components/**/*.{tsx,ts,jsx,js}

📄 CodeRabbit inference engine (apps/web/.cursor/rules/frontend_rules.mdc)

apps/web/src/components/**/*.{tsx,ts,jsx,js}: Never use hardcoded hex values directly in components; always reference colors from the design token system using Tailwind classes
Use semantic color names from the design token system that describe purpose, not appearance (e.g., bg-brand-purple, bg-surface-primary, text-text-primary)
Use font-sans for standard UI text (Geist Sans) and font-mono for code, technical content, or monospace needs (DM Mono)
Follow Tailwind's spacing scale for section padding: p-4 (1rem) on mobile, p-[60px] on desktop
Use rounded-lg (0.5rem) for small elements, rounded-xl (1rem) for medium elements, rounded-2xl (1.5rem) for large elements, and rounded-[16px] for buttons
Use duration-100 (0.1s) for fast transitions, duration-300 (0.3s) for normal transitions, and duration-600 (0.6s) for slow transitions
Use available custom animations: animate-accordion-down, animate-accordion-up, animate-scrollRight, animate-scrollLeft, animate-customspin, animate-spin-slow, animate-spin-slow-reverse, animate-marquee, animate-marquee-vertical, animate-shine
Prefer functional components with TypeScript
Extract reusable logic into custom hooks
Prefer controlled components over uncontrolled
Include proper aria labels for accessibility
Ensure keyboard navigation works in interactive components
Maintain proper heading hierarchy in page components
Provide alt text for images
Use 'class:' instead of the ternary operator in class tags whenever possible
Implement accessibility features on interactive elements (e.g., tabindex='0', aria-label, onClick, onKeyDown)
Always follow the design system defined in apps/web/src/lib/design-tokens.ts and apps/web/tailwind.config.ts

Files:

  • apps/web/src/components/dashboard/SavedProjectsPanel.tsx
  • apps/web/src/components/dashboard/ProjectsContainer.tsx
apps/web/src/components/**/*.{tsx,ts}

📄 CodeRabbit inference engine (apps/web/.cursor/rules/frontend_rules.mdc)

apps/web/src/components/**/*.{tsx,ts}: Use proper TypeScript types and avoid using any type
Use descriptive prop names and define prop types using TypeScript interfaces or types
Name components using PascalCase (e.g., UserProfile.tsx)

Files:

  • apps/web/src/components/dashboard/SavedProjectsPanel.tsx
  • apps/web/src/components/dashboard/ProjectsContainer.tsx
apps/web/src/**/*.{tsx,ts,jsx,js}

📄 CodeRabbit inference engine (apps/web/.cursor/rules/frontend_rules.mdc)

apps/web/src/**/*.{tsx,ts,jsx,js}: Organize imports in order: React → third-party → local components → utils → types
Use absolute imports from @/ prefix when available
Remove unused imports
Use UPPER_SNAKE_CASE for constants
Use camelCase for functions and variables
Always use Tailwind classes for styling HTML elements; avoid using CSS or style tags
Use descriptive variable and function names; name event functions with a 'handle' prefix (e.g., handleClick, handleKeyDown)
Use const with arrow functions instead of function declarations (e.g., 'const toggle = () =>')

Files:

  • apps/web/src/components/dashboard/SavedProjectsPanel.tsx
  • apps/web/src/components/dashboard/ProjectsContainer.tsx
  • apps/web/src/store/useSavedProjectsStore.ts
apps/api/src/**/*.{js,ts}

📄 CodeRabbit inference engine (apps/api/.cursor/rules/backend_rules.mdc)

apps/api/src/**/*.{js,ts}: Log errors with context (userId, endpoint, timestamp) for debugging
Always await async operations; never forget to handle promise rejections
Never log sensitive information (passwords, tokens, credit card numbers)

Files:

  • apps/api/src/routers/user.ts
apps/api/src/**/*.ts

📄 CodeRabbit inference engine (apps/api/.cursor/rules/backend_rules.mdc)

Avoid any type; use unknown for truly dynamic data and narrow with type guards

Files:

  • apps/api/src/routers/user.ts
🧠 Learnings (24)
📓 Common learnings
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/**/*.{tsx,ts} : Use Zustand for global state, located in `src/store/`
📚 Learning: 2025-11-25T07:34:30.473Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T07:34:30.473Z
Learning: Applies to apps/web/src/**/*.{ts,tsx} : NEVER use hardcoded hex values (e.g., `#5519f7`) directly in components; ALWAYS reference colors from the design token system using Tailwind classes

Applied to files:

  • apps/web/src/components/dashboard/SavedProjectsPanel.tsx
  • apps/web/src/components/dashboard/ProjectsContainer.tsx
  • apps/web/tailwind.config.ts
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/components/**/*.{tsx,ts,jsx,js} : Never use hardcoded hex values directly in components; always reference colors from the design token system using Tailwind classes

Applied to files:

  • apps/web/src/components/dashboard/SavedProjectsPanel.tsx
  • apps/web/src/components/dashboard/ProjectsContainer.tsx
  • apps/web/tailwind.config.ts
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/components/**/*.{tsx,ts,jsx,js} : Use semantic color names from the design token system that describe purpose, not appearance (e.g., bg-brand-purple, bg-surface-primary, text-text-primary)

Applied to files:

  • apps/web/src/components/dashboard/SavedProjectsPanel.tsx
  • apps/web/src/components/dashboard/ProjectsContainer.tsx
  • apps/web/tailwind.config.ts
📚 Learning: 2025-11-25T07:34:30.473Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T07:34:30.473Z
Learning: Applies to apps/web/src/**/*.{ts,tsx} : Use semantic color names that describe purpose, not appearance

Applied to files:

  • apps/web/src/components/dashboard/SavedProjectsPanel.tsx
  • apps/web/src/components/dashboard/ProjectsContainer.tsx
  • apps/web/tailwind.config.ts
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/components/**/*.{tsx,ts,jsx,js} : Always follow the design system defined in `apps/web/src/lib/design-tokens.ts` and `apps/web/tailwind.config.ts`

Applied to files:

  • apps/web/src/components/dashboard/SavedProjectsPanel.tsx
  • apps/web/src/components/dashboard/ProjectsContainer.tsx
  • apps/web/tailwind.config.ts
📚 Learning: 2025-11-25T07:34:30.473Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T07:34:30.473Z
Learning: Applies to apps/web/src/**/*.{ts,tsx} : Always follow the design system defined in `apps/web/src/lib/design-tokens.ts` and `apps/web/tailwind.config.ts`

Applied to files:

  • apps/web/src/components/dashboard/SavedProjectsPanel.tsx
  • apps/web/src/components/dashboard/ProjectsContainer.tsx
  • apps/web/tailwind.config.ts
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/**/*.{tsx,ts,jsx,js} : Always use Tailwind classes for styling HTML elements; avoid using CSS or style tags

Applied to files:

  • apps/web/src/components/dashboard/SavedProjectsPanel.tsx
  • apps/web/tailwind.config.ts
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/components/**/*.{tsx,ts,jsx,js} : Use 'class:' instead of the ternary operator in class tags whenever possible

Applied to files:

  • apps/web/src/components/dashboard/SavedProjectsPanel.tsx
📚 Learning: 2025-11-25T07:34:30.473Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T07:34:30.473Z
Learning: Applies to apps/web/src/**/*.{ts,tsx} : Use appropriate border radius: small elements `rounded-lg`, medium `rounded-xl`, large `rounded-2xl`, buttons `rounded-[16px]`

Applied to files:

  • apps/web/src/components/dashboard/SavedProjectsPanel.tsx
📚 Learning: 2025-12-17T12:39:29.991Z
Learnt from: huamanraj
Repo: apsinghdev/opensox PR: 262
File: apps/web/src/components/checkout/CheckoutWrapper.tsx:5-5
Timestamp: 2025-12-17T12:39:29.991Z
Learning: In Next.js apps, avoid using redirect() from next/navigation inside Client Components during render. It should not be used in event handlers like onClick or onSubmit; for those cases, use useRouter().push() or router.replace() instead. This guidance applies to TSX files (React components) across the codebase; implement in client components to handle conditional redirects during render, and use router-based navigation in handlers.

Applied to files:

  • apps/web/src/components/dashboard/SavedProjectsPanel.tsx
  • apps/web/src/components/dashboard/ProjectsContainer.tsx
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/components/**/*.{tsx,ts,jsx,js} : Implement accessibility features on interactive elements (e.g., tabindex='0', aria-label, onClick, onKeyDown)

Applied to files:

  • apps/web/src/components/dashboard/ProjectsContainer.tsx
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/components/**/*.{tsx,ts,jsx,js} : Include proper aria labels for accessibility

Applied to files:

  • apps/web/src/components/dashboard/ProjectsContainer.tsx
📚 Learning: 2025-11-25T07:34:30.473Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T07:34:30.473Z
Learning: Applies to **/*.{tsx,ts} : Include proper aria labels for accessibility

Applied to files:

  • apps/web/src/components/dashboard/ProjectsContainer.tsx
📚 Learning: 2025-11-25T07:34:58.984Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/api/.cursor/rules/backend_rules.mdc:0-0
Timestamp: 2025-11-25T07:34:58.984Z
Learning: Applies to apps/api/src/**/*.ts : Avoid `any` type; use `unknown` for truly dynamic data and narrow with type guards

Applied to files:

  • apps/api/src/routers/user.ts
  • apps/web/src/store/useSavedProjectsStore.ts
📚 Learning: 2025-11-25T07:34:58.984Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/api/.cursor/rules/backend_rules.mdc:0-0
Timestamp: 2025-11-25T07:34:58.984Z
Learning: Applies to apps/api/src/**/{routes,controllers,handlers,middleware}/*.{js,ts} : Use zod or similar for runtime validation of incoming data

Applied to files:

  • apps/api/src/routers/user.ts
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/components/**/*.{tsx,ts} : Use proper TypeScript types and avoid using `any` type

Applied to files:

  • apps/api/src/routers/user.ts
📚 Learning: 2025-11-25T07:34:58.984Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/api/.cursor/rules/backend_rules.mdc:0-0
Timestamp: 2025-11-25T07:34:58.984Z
Learning: Applies to apps/api/src/**/{services,models}/*.{js,ts} : Validate data against schema before database operations

Applied to files:

  • apps/api/src/routers/user.ts
📚 Learning: 2025-11-25T07:34:58.984Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/api/.cursor/rules/backend_rules.mdc:0-0
Timestamp: 2025-11-25T07:34:58.984Z
Learning: Applies to apps/api/src/**/{routes,controllers,handlers,middleware}/*.{js,ts} : Always validate user authentication before processing protected routes

Applied to files:

  • apps/api/src/routers/user.ts
📚 Learning: 2025-11-25T07:34:30.473Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T07:34:30.473Z
Learning: Applies to apps/web/src/**/*.{ts,tsx} : Follow Tailwind's spacing scale (0.25rem increments); for section padding use mobile `p-4` (1rem) and desktop `p-[60px]`

Applied to files:

  • apps/web/tailwind.config.ts
📚 Learning: 2025-11-25T07:34:30.473Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T07:34:30.473Z
Learning: Applies to **/*.{tsx,ts} : Maintain proper heading hierarchy

Applied to files:

  • docs/QUICKSTART_SAVED_REPOS.md
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/components/**/*.{tsx,ts,jsx,js} : Maintain proper heading hierarchy in page components

Applied to files:

  • docs/QUICKSTART_SAVED_REPOS.md
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/**/*.{tsx,ts} : Use Zustand for global state, located in `src/store/`

Applied to files:

  • apps/web/src/store/useSavedProjectsStore.ts
📚 Learning: 2025-11-25T07:34:30.473Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T07:34:30.473Z
Learning: Applies to **/*.{tsx,ts} : Use zustand for global state (located in `src/store/`)

Applied to files:

  • apps/web/src/store/useSavedProjectsStore.ts
🧬 Code graph analysis (5)
apps/web/src/components/dashboard/SavedProjectsPanel.tsx (2)
apps/web/src/store/useSavedProjectsStore.ts (1)
  • useSavedProjectsStore (16-126)
apps/web/src/components/ui/badge.tsx (1)
  • Badge (36-36)
apps/web/src/components/dashboard/ProjectsContainer.tsx (3)
apps/web/src/store/useSavedProjectsStore.ts (1)
  • useSavedProjectsStore (16-126)
apps/web/src/components/dashboard/SaveToggle.tsx (1)
  • SaveToggle (13-65)
apps/web/src/components/dashboard/SavedProjectsPanel.tsx (1)
  • SavedProjectsPanel (20-211)
apps/api/src/routers/user.ts (2)
apps/api/src/trpc.ts (1)
  • protectedProcedure (40-40)
apps/api/src/services/savedRepos.service.ts (1)
  • savedReposService (5-115)
apps/web/tailwind.config.ts (1)
apps/web/src/lib/design-tokens.ts (1)
  • colors (8-118)
apps/web/src/store/useSavedProjectsStore.ts (1)
packages/shared/types/savedRepos.ts (1)
  • SavedRepo (1-10)
🔇 Additional comments (13)
apps/api/package.json (1)

17-19: LGTM! Prisma seed configuration is correctly placed.

The prisma.seed script using tsx prisma/seed.ts properly integrates with the automated setup workflow described in the PR objectives.

packages/shared/types/savedRepos.ts (1)

1-17: LGTM! Well-structured type definitions.

The types are properly defined with appropriate use of Record<string, unknown> for extensible metadata (avoiding any). The union type for popularity and the action types provide good type safety across the stack.

apps/api/src/routers/user.ts (1)

89-114: LGTM! Merge logic is well-implemented.

The conditional merge when localRepos is provided with a replace action correctly delegates to the service's mergeSavedRepos function, enabling proper client-server sync with conflict resolution.

docs/QUICKSTART_SAVED_REPOS.md (1)

1-224: LGTM! Comprehensive quick start documentation.

The guide provides clear setup instructions, testing checklists, and troubleshooting guidance. The markdown structure properly uses headings for section organization.

apps/web/src/components/dashboard/ProjectsContainer.tsx (2)

76-108: LGTM! Excellent accessibility implementation.

The buttons correctly implement keyboard navigation with Enter/Space handling, include proper aria-label attributes, and use the design system's bg-brand-purple token. The saved projects count badge provides good visual feedback.


152-154: LGTM! Clean component integration.

The SaveToggle and SavedProjectsPanel components are well-integrated with appropriate prop passing and state management using the Zustand store, consistent with the coding guidelines.

Also applies to: 216-219

apps/web/src/components/dashboard/SavedProjectsPanel.tsx (4)

1-18: LGTM! Clean imports and type definitions.

The imports are properly organized following the coding guidelines (React → third-party → local → types), and the props interface is well-typed.


82-110: LGTM! Proper accessibility and semantic colors.

The backdrop and header implementation follows accessibility best practices with aria-hidden on the backdrop and aria-label on the close button. The color usage follows the design token system with semantic names like bg-brand-purple.


112-147: LGTM! Well-structured action buttons.

The action buttons properly handle disabled states, use semantic color tokens, and follow the design system guidelines for button styling. The hidden file input pattern is a standard accessible approach.


175-190: Previous color concerns resolved - now using semantic tokens.

The code now correctly uses semantic color tokens (bg-info/15 text-info and bg-success/15 text-success) instead of the hardcoded values mentioned in previous reviews. Well done!

apps/web/src/store/useSavedProjectsStore.ts (3)

1-14: LGTM! Clean imports and well-typed interface.

The imports are minimal and necessary, and the SavedProjectsState interface provides a clear contract with proper TypeScript types throughout.


21-55: LGTM! Solid state management methods.

The store methods follow Zustand best practices with immutable updates, proper deduplication in addProject, and clean toggle logic. All methods use efficient patterns appropriate for the use case.


116-126: LGTM! Proper persistence configuration.

The isSaved helper is clean, and the persist middleware is correctly configured with localStorage, appropriate partialization (only persisting data, not methods), and a versioned storage key that will facilitate future migrations.

- Replace text-red-500 with text-error in remove button icon
- Replace hover:bg-red-500/20 with hover:bg-error/20 for hover state
- Maintains all existing behavior (opacity, transitions, rounded)
- Improves consistency with design system and accessibility
@Lucifer-0612
Copy link
Contributor Author

please review it :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[ISSUE] Local setup process is complicated and documentation is incomplete

1 participant