Conversation
|
📝 WalkthroughWalkthroughIntroduces a new modular Projects UI (search, controls, cards, skeletons, dialogs), client hooks and Zod schemas for filters/queries, TRPC backend changes for project creation and unified listing, new icons and ID/audit schema updates, and removes legacy project router/schema files. All functionality is migrated to new components and hooks. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant ProjectsSearchInput
participant useProjectsFilters
participant ProjectsList
participant useProjectsListQuery
participant TRPC_Backend
User->>ProjectsSearchInput: types query
ProjectsSearchInput->>useProjectsFilters: debounce & update query param
useProjectsFilters->>useProjectsListQuery: expose updated filters
ProjectsList->>useProjectsListQuery: request projects (with filters / cursor)
useProjectsListQuery->>TRPC_Backend: call queryProjects
TRPC_Backend-->>useProjectsListQuery: paginated projects (+hostnames)
useProjectsListQuery-->>ProjectsList: return list & pagination state
ProjectsList-->>User: render cards / load more
sequenceDiagram
participant User
participant CreateProjectDialog
participant useCreateProject
participant TRPC_Backend
User->>CreateProjectDialog: open & submit form
CreateProjectDialog->>useCreateProject: call mutation
useCreateProject->>TRPC_Backend: createProject mutation
TRPC_Backend-->>useCreateProject: success (project data) / error
useCreateProject-->>CreateProjectDialog: invoke onSuccess / show error toasts
CreateProjectDialog-->>User: close dialog & show toast
Estimated code review effort🎯 4 (Complex) | ⏱️ ~40 minutes Possibly related PRs
Suggested labels
Suggested reviewers
✨ Finishing Touches
🧪 Generate unit tests
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
d7103a1 to
8b9eb98
Compare
There was a problem hiding this comment.
Actionable comments posted: 10
♻️ Duplicate comments (1)
apps/dashboard/app/(app)/projects/_components/list/index.tsx (1)
46-48: Use final documentation URL.
https://www.unkey.com/docs/introductionis a generic landing page. Point users directly to Deploy docs, e.g.https://docs.unkey.com/deploy/projects, to reduce friction.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (7)
apps/dashboard/app/(app)/projects/_components/controls/components/projects-list-search/index.tsx(1 hunks)apps/dashboard/app/(app)/projects/_components/controls/index.tsx(1 hunks)apps/dashboard/app/(app)/projects/_components/list/index.tsx(1 hunks)apps/dashboard/app/(app)/projects/_components/list/projects-card.tsx(1 hunks)apps/dashboard/app/(app)/projects/navigation.tsx(1 hunks)apps/dashboard/lib/trpc/routers/deploy/project/create.ts(1 hunks)apps/dashboard/lib/trpc/routers/deploy/project/list.ts(5 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit Inference Engine (CLAUDE.md)
**/*.{js,jsx,ts,tsx}: Use Biome for formatting and linting in TypeScript/JavaScript projects
Prefer named exports over default exports in TypeScript/JavaScript, except for Next.js pages
Files:
apps/dashboard/app/(app)/projects/navigation.tsxapps/dashboard/app/(app)/projects/_components/controls/index.tsxapps/dashboard/lib/trpc/routers/deploy/project/create.tsapps/dashboard/app/(app)/projects/_components/list/index.tsxapps/dashboard/app/(app)/projects/_components/controls/components/projects-list-search/index.tsxapps/dashboard/lib/trpc/routers/deploy/project/list.tsapps/dashboard/app/(app)/projects/_components/list/projects-card.tsx
**/*.{ts,tsx}
📄 CodeRabbit Inference Engine (CLAUDE.md)
**/*.{ts,tsx}: Follow strict TypeScript configuration
Use Zod for runtime validation in TypeScript projects
Files:
apps/dashboard/app/(app)/projects/navigation.tsxapps/dashboard/app/(app)/projects/_components/controls/index.tsxapps/dashboard/lib/trpc/routers/deploy/project/create.tsapps/dashboard/app/(app)/projects/_components/list/index.tsxapps/dashboard/app/(app)/projects/_components/controls/components/projects-list-search/index.tsxapps/dashboard/lib/trpc/routers/deploy/project/list.tsapps/dashboard/app/(app)/projects/_components/list/projects-card.tsx
**/*.{env,js,ts,go}
📄 CodeRabbit Inference Engine (CLAUDE.md)
All environment variables must follow the format: UNKEY_<SERVICE_NAME>_VARNAME
Files:
apps/dashboard/lib/trpc/routers/deploy/project/create.tsapps/dashboard/lib/trpc/routers/deploy/project/list.ts
🧠 Learnings (40)
📓 Common learnings
Learnt from: ogzhanolguncu
PR: unkeyed/unkey#2825
File: apps/dashboard/app/(app)/logs-v2/hooks/use-bookmarked-filters.ts:0-0
Timestamp: 2025-01-30T20:51:44.359Z
Learning: The user (ogzhanolguncu) prefers to handle refactoring suggestions in separate PRs to maintain focus in the current PR.
Learnt from: mcstepp
PR: unkeyed/unkey#3662
File: apps/dashboard/lib/trpc/routers/deployment/list.ts:11-11
Timestamp: 2025-07-25T19:09:43.284Z
Learning: In apps/dashboard/lib/trpc/routers/deployment/list.ts, the listDeployments procedure intentionally queries the versions table rather than a deployments table. The user mcstepp indicated that renaming the table would require a database migration, which was deferred for the current PR focused on UI features.
Learnt from: mcstepp
PR: unkeyed/unkey#3662
File: apps/dashboard/app/(app)/projects/[projectId]/diff/[...compare]/components/client.tsx:322-341
Timestamp: 2025-07-28T20:38:53.244Z
Learning: In apps/dashboard/app/(app)/projects/[projectId]/diff/[...compare]/components/client.tsx, mcstepp prefers to keep hardcoded endpoint logic in the getDiffType function during POC phases for demonstrating diff functionality, rather than implementing a generic diff algorithm. This follows the pattern of keeping simplified implementations for demonstration purposes.
Learnt from: mcstepp
PR: unkeyed/unkey#3662
File: apps/dashboard/app/(app)/projects/page.tsx:74-81
Timestamp: 2025-07-28T19:42:37.047Z
Learning: In apps/dashboard/app/(app)/projects/page.tsx, the user mcstepp prefers to keep placeholder functions like generateSlug inline during POC/demonstration phases rather than extracting them to utility modules, with plans to refactor later when the feature matures beyond the proof-of-concept stage.
Learnt from: ogzhanolguncu
PR: unkeyed/unkey#3297
File: apps/dashboard/lib/trpc/routers/authorization/roles/query.ts:210-323
Timestamp: 2025-06-04T20:13:12.060Z
Learning: The user ogzhanolguncu prefers explicit, duplicated code over abstracted helper functions when it improves readability, even if it means some duplication in filter building functions in the authorization roles query module.
Learnt from: ogzhanolguncu
PR: unkeyed/unkey#3480
File: apps/dashboard/app/new-2/hooks/use-workspace-step.tsx:47-79
Timestamp: 2025-07-09T11:35:51.724Z
Learning: In the Unkey codebase, ogzhanolguncu prefers to keep invariant checks that throw errors for cases that shouldn't happen in normal operation (like null workspace ID checks), rather than adding graceful error handling code for edge cases that would only occur if someone tampers with the actual flow.
Learnt from: ogzhanolguncu
PR: unkeyed/unkey#3375
File: apps/dashboard/app/(app)/settings/root-keys/components/table/hooks/use-root-keys-list-query.ts:0-0
Timestamp: 2025-06-25T20:32:10.471Z
Learning: In the Unkey codebase, ogzhanolguncu prefers strict validation with fail-fast error handling. When validation errors occur that shouldn't happen in normal operation (like invalid operators), throwing errors to crash the page is preferred over graceful error handling or console logging.
Learnt from: ogzhanolguncu
PR: unkeyed/unkey#3499
File: apps/dashboard/app/new/hooks/use-workspace-step.tsx:19-26
Timestamp: 2025-07-11T13:00:05.416Z
Learning: In the Unkey codebase, ogzhanolguncu prefers to keep commented code for planned future features (like slug-based workspaces) rather than removing it, as it serves as a reference for upcoming implementation.
📚 Learning: 2025-07-28T20:38:53.244Z
Learnt from: mcstepp
PR: unkeyed/unkey#3662
File: apps/dashboard/app/(app)/projects/[projectId]/diff/[...compare]/components/client.tsx:322-341
Timestamp: 2025-07-28T20:38:53.244Z
Learning: In apps/dashboard/app/(app)/projects/[projectId]/diff/[...compare]/components/client.tsx, mcstepp prefers to keep hardcoded endpoint logic in the getDiffType function during POC phases for demonstrating diff functionality, rather than implementing a generic diff algorithm. This follows the pattern of keeping simplified implementations for demonstration purposes.
Applied to files:
apps/dashboard/app/(app)/projects/navigation.tsxapps/dashboard/app/(app)/projects/_components/controls/index.tsxapps/dashboard/lib/trpc/routers/deploy/project/create.tsapps/dashboard/app/(app)/projects/_components/list/index.tsxapps/dashboard/app/(app)/projects/_components/controls/components/projects-list-search/index.tsxapps/dashboard/lib/trpc/routers/deploy/project/list.tsapps/dashboard/app/(app)/projects/_components/list/projects-card.tsx
📚 Learning: 2025-07-28T19:42:37.047Z
Learnt from: mcstepp
PR: unkeyed/unkey#3662
File: apps/dashboard/app/(app)/projects/page.tsx:74-81
Timestamp: 2025-07-28T19:42:37.047Z
Learning: In apps/dashboard/app/(app)/projects/page.tsx, the user mcstepp prefers to keep placeholder functions like generateSlug inline during POC/demonstration phases rather than extracting them to utility modules, with plans to refactor later when the feature matures beyond the proof-of-concept stage.
Applied to files:
apps/dashboard/app/(app)/projects/navigation.tsxapps/dashboard/app/(app)/projects/_components/controls/index.tsxapps/dashboard/lib/trpc/routers/deploy/project/create.tsapps/dashboard/app/(app)/projects/_components/list/index.tsxapps/dashboard/app/(app)/projects/_components/controls/components/projects-list-search/index.tsxapps/dashboard/lib/trpc/routers/deploy/project/list.tsapps/dashboard/app/(app)/projects/_components/list/projects-card.tsx
📚 Learning: 2025-05-15T16:26:08.666Z
Learnt from: ogzhanolguncu
PR: unkeyed/unkey#3242
File: apps/dashboard/app/(app)/apis/[apiId]/_overview/components/table/components/override-indicator.tsx:50-65
Timestamp: 2025-05-15T16:26:08.666Z
Learning: In the Unkey dashboard, Next.js router (router.push) should be used for client-side navigation instead of window.location.href to preserve client state and enable smoother transitions between pages.
Applied to files:
apps/dashboard/app/(app)/projects/navigation.tsxapps/dashboard/app/(app)/projects/_components/list/index.tsx
📚 Learning: 2024-10-23T16:25:33.113Z
Learnt from: p6l-richard
PR: unkeyed/unkey#2085
File: apps/www/components/glossary/terms-stepper-mobile.tsx:16-20
Timestamp: 2024-10-23T16:25:33.113Z
Learning: In the `apps/www/components/glossary/terms-stepper-mobile.tsx` file, avoid suggesting to extract the term navigation logic into a custom hook, as the user prefers to keep the component straightforward.
Applied to files:
apps/dashboard/app/(app)/projects/navigation.tsx
📚 Learning: 2024-12-03T14:07:45.173Z
Learnt from: ogzhanolguncu
PR: unkeyed/unkey#2143
File: apps/dashboard/components/ui/group-button.tsx:21-31
Timestamp: 2024-12-03T14:07:45.173Z
Learning: In the `ButtonGroup` component (`apps/dashboard/components/ui/group-button.tsx`), avoid suggesting the use of `role="group"` in ARIA attributes.
Applied to files:
apps/dashboard/app/(app)/projects/navigation.tsxapps/dashboard/app/(app)/projects/_components/controls/index.tsxapps/dashboard/app/(app)/projects/_components/list/projects-card.tsx
📚 Learning: 2024-10-08T15:33:04.290Z
Learnt from: chronark
PR: unkeyed/unkey#2180
File: apps/dashboard/lib/constants/workspace-navigations.tsx:85-88
Timestamp: 2024-10-08T15:33:04.290Z
Learning: In navigation code (e.g., `apps/dashboard/lib/constants/workspace-navigations.tsx`), prefer using `segments.at(0)` over `segments[0]` to handle cases when the `segments` array might be empty.
Applied to files:
apps/dashboard/app/(app)/projects/navigation.tsx
📚 Learning: 2024-10-23T16:21:47.395Z
Learnt from: p6l-richard
PR: unkeyed/unkey#2085
File: apps/www/components/glossary/search.tsx:16-20
Timestamp: 2024-10-23T16:21:47.395Z
Learning: For the `FilterableCommand` component in `apps/www/components/glossary/search.tsx`, refactoring type definitions into an interface is not necessary at this time.
Applied to files:
apps/dashboard/app/(app)/projects/navigation.tsxapps/dashboard/app/(app)/projects/_components/controls/index.tsxapps/dashboard/app/(app)/projects/_components/controls/components/projects-list-search/index.tsx
📚 Learning: 2024-10-23T16:20:19.324Z
Learnt from: p6l-richard
PR: unkeyed/unkey#2085
File: apps/www/components/glossary/terms-rolodex-desktop.tsx:26-37
Timestamp: 2024-10-23T16:20:19.324Z
Learning: When reviewing React components in this project, avoid suggesting manual memoization with `useMemo` for performance optimizations, as the team prefers to rely on the React compiler to handle such optimizations.
Applied to files:
apps/dashboard/app/(app)/projects/navigation.tsxapps/dashboard/app/(app)/projects/_components/controls/components/projects-list-search/index.tsx
📚 Learning: 2025-06-02T11:08:56.397Z
Learnt from: ogzhanolguncu
PR: unkeyed/unkey#3292
File: apps/dashboard/lib/vault.ts:80-97
Timestamp: 2025-06-02T11:08:56.397Z
Learning: The vault.ts file in apps/dashboard/lib/vault.ts is a duplicate of the vault package from the `api` directory and should be kept consistent with that original implementation.
Applied to files:
apps/dashboard/app/(app)/projects/navigation.tsxapps/dashboard/app/(app)/projects/_components/controls/index.tsxapps/dashboard/lib/trpc/routers/deploy/project/list.ts
📚 Learning: 2024-10-23T16:19:42.049Z
Learnt from: p6l-richard
PR: unkeyed/unkey#2085
File: apps/www/components/glossary/search.tsx:41-57
Timestamp: 2024-10-23T16:19:42.049Z
Learning: For the `FilterableCommand` component in `apps/www/components/glossary/search.tsx`, adding error handling and loading states to the results list is not necessary.
Applied to files:
apps/dashboard/app/(app)/projects/_components/controls/index.tsxapps/dashboard/app/(app)/projects/_components/list/index.tsxapps/dashboard/app/(app)/projects/_components/controls/components/projects-list-search/index.tsx
📚 Learning: 2025-08-04T07:44:39.438Z
Learnt from: CR
PR: unkeyed/unkey#0
File: CLAUDE.md:0-0
Timestamp: 2025-08-04T07:44:39.438Z
Learning: Applies to **/*.{ts,tsx} : Follow strict TypeScript configuration
Applied to files:
apps/dashboard/app/(app)/projects/_components/controls/index.tsx
📚 Learning: 2025-08-04T07:44:39.438Z
Learnt from: CR
PR: unkeyed/unkey#0
File: CLAUDE.md:0-0
Timestamp: 2025-08-04T07:44:39.438Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Prefer named exports over default exports in TypeScript/JavaScript, except for Next.js pages
Applied to files:
apps/dashboard/app/(app)/projects/_components/controls/index.tsx
📚 Learning: 2025-08-04T07:44:39.438Z
Learnt from: CR
PR: unkeyed/unkey#0
File: CLAUDE.md:0-0
Timestamp: 2025-08-04T07:44:39.438Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Use Biome for formatting and linting in TypeScript/JavaScript projects
Applied to files:
apps/dashboard/app/(app)/projects/_components/controls/index.tsx
📚 Learning: 2025-08-04T07:44:39.438Z
Learnt from: CR
PR: unkeyed/unkey#0
File: CLAUDE.md:0-0
Timestamp: 2025-08-04T07:44:39.438Z
Learning: Applies to **/*.{ts,tsx} : Use Zod for runtime validation in TypeScript projects
Applied to files:
apps/dashboard/app/(app)/projects/_components/controls/index.tsx
📚 Learning: 2025-08-04T07:44:39.438Z
Learnt from: CR
PR: unkeyed/unkey#0
File: CLAUDE.md:0-0
Timestamp: 2025-08-04T07:44:39.438Z
Learning: Applies to **/*.test.{ts,tsx} : Use Vitest for unit and integration tests in TypeScript projects
Applied to files:
apps/dashboard/app/(app)/projects/_components/controls/index.tsx
📚 Learning: 2025-07-25T19:09:43.284Z
Learnt from: mcstepp
PR: unkeyed/unkey#3662
File: apps/dashboard/lib/trpc/routers/deployment/list.ts:11-11
Timestamp: 2025-07-25T19:09:43.284Z
Learning: In apps/dashboard/lib/trpc/routers/deployment/list.ts, the listDeployments procedure intentionally queries the versions table rather than a deployments table. The user mcstepp indicated that renaming the table would require a database migration, which was deferred for the current PR focused on UI features.
Applied to files:
apps/dashboard/lib/trpc/routers/deploy/project/create.tsapps/dashboard/app/(app)/projects/_components/list/index.tsxapps/dashboard/lib/trpc/routers/deploy/project/list.ts
📚 Learning: 2025-07-28T20:36:36.865Z
Learnt from: mcstepp
PR: unkeyed/unkey#3662
File: apps/dashboard/lib/trpc/routers/branch/getByName.ts:0-0
Timestamp: 2025-07-28T20:36:36.865Z
Learning: In apps/dashboard/lib/trpc/routers/branch/getByName.ts, mcstepp prefers to keep mock data (gitCommitMessage, buildDuration, lastCommitAuthor, etc.) in the branch procedure during POC phases to demonstrate what the UI would look like with proper schema changes, rather than returning null/undefined values.
Applied to files:
apps/dashboard/lib/trpc/routers/deploy/project/create.tsapps/dashboard/lib/trpc/routers/deploy/project/list.ts
📚 Learning: 2025-07-25T19:11:00.208Z
Learnt from: mcstepp
PR: unkeyed/unkey#3662
File: apps/dashboard/lib/trpc/routers/deployment/getOpenApiDiff.ts:110-147
Timestamp: 2025-07-25T19:11:00.208Z
Learning: In apps/dashboard/lib/trpc/routers/deployment/getOpenApiDiff.ts, the user mcstepp prefers to keep mock data fallbacks in POC/demonstration code for simplicity, even if it wouldn't be production-ready. This aligns with the PR being work-in-progress for demonstration purposes.
Applied to files:
apps/dashboard/lib/trpc/routers/deploy/project/create.tsapps/dashboard/lib/trpc/routers/deploy/project/list.ts
📚 Learning: 2025-04-08T09:34:24.576Z
Learnt from: ogzhanolguncu
PR: unkeyed/unkey#2872
File: apps/dashboard/lib/trpc/routers/ratelimit/createNamespace.ts:36-39
Timestamp: 2025-04-08T09:34:24.576Z
Learning: In the Unkey dashboard, when making database queries involving workspaces, use `ctx.workspace.id` directly instead of fetching the workspace separately for better performance and security.
Applied to files:
apps/dashboard/lib/trpc/routers/deploy/project/create.tsapps/dashboard/lib/trpc/routers/deploy/project/list.ts
📚 Learning: 2024-10-04T20:44:38.489Z
Learnt from: chronark
PR: unkeyed/unkey#2180
File: apps/dashboard/lib/constants/workspace-navigations.tsx:56-118
Timestamp: 2024-10-04T20:44:38.489Z
Learning: When typing the `workspace` parameter in functions like `createWorkspaceNavigation`, prefer importing the `Workspace` type from the database module and picking the necessary keys (e.g., `features`) instead of redefining the interface.
Applied to files:
apps/dashboard/lib/trpc/routers/deploy/project/create.ts
📚 Learning: 2025-04-08T09:34:24.576Z
Learnt from: ogzhanolguncu
PR: unkeyed/unkey#2872
File: apps/dashboard/lib/trpc/routers/ratelimit/createNamespace.ts:36-39
Timestamp: 2025-04-08T09:34:24.576Z
Learning: When querying or updating namespaces in the Unkey dashboard, always scope the operations to the current workspace using `eq(table.workspaceId, ctx.workspace.id)` to prevent cross-workspace access.
Applied to files:
apps/dashboard/lib/trpc/routers/deploy/project/create.tsapps/dashboard/lib/trpc/routers/deploy/project/list.ts
📚 Learning: 2025-04-22T17:33:28.162Z
Learnt from: MichaelUnkey
PR: unkeyed/unkey#3173
File: apps/docs/security/delete-protection.mdx:32-36
Timestamp: 2025-04-22T17:33:28.162Z
Learning: In the Unkey dashboard UI for delete protection, the button/link to initiate the process is labeled "Disable Delete Protection" while the confirmation button is labeled "Disable API Delete Protection". The documentation should maintain these different labels to match the actual UI.
Applied to files:
apps/dashboard/app/(app)/projects/_components/list/index.tsx
📚 Learning: 2025-04-22T17:34:04.438Z
Learnt from: MichaelUnkey
PR: unkeyed/unkey#3173
File: apps/docs/security/delete-protection.mdx:21-24
Timestamp: 2025-04-22T17:34:04.438Z
Learning: In the Unkey dashboard UI for enabling delete protection, the button/link to initiate the process is labeled "Enable Delete Protection" while the confirmation button is labeled "Enable API Delete Protection". The documentation should maintain these different labels to match the actual UI.
Applied to files:
apps/dashboard/app/(app)/projects/_components/list/index.tsx
📚 Learning: 2025-07-21T18:05:58.236Z
Learnt from: CR
PR: unkeyed/unkey#0
File: go/deploy/CLAUDE.md:0-0
Timestamp: 2025-07-21T18:05:58.236Z
Learning: Applies to go/deploy/**/*.{go,js,ts,tsx,py,sh,md,txt,json,yaml,yml,ini,env,conf,html,css,scss,xml,c,h,cpp,java,rb,rs,php,pl,sql} : Update relevant anchors when modifying associated code.
Applied to files:
apps/dashboard/app/(app)/projects/_components/list/index.tsx
📚 Learning: 2025-07-21T18:05:58.236Z
Learnt from: CR
PR: unkeyed/unkey#0
File: go/deploy/CLAUDE.md:0-0
Timestamp: 2025-07-21T18:05:58.236Z
Learning: Applies to go/deploy/**/*.{go,js,ts,tsx,py,sh,md,txt,json,yaml,yml,ini,env,conf,html,css,scss,xml,c,h,cpp,java,rb,rs,php,pl,sql} : Use `AIDEV-NOTE:`, `AIDEV-TODO:`, `AIDEV-BUSINESS_RULE:`, or `AIDEV-QUESTION:` (all-caps prefix) as anchor comments aimed at AI and developers.
Applied to files:
apps/dashboard/app/(app)/projects/_components/list/index.tsx
📚 Learning: 2025-07-21T18:05:58.236Z
Learnt from: CR
PR: unkeyed/unkey#0
File: go/deploy/CLAUDE.md:0-0
Timestamp: 2025-07-21T18:05:58.236Z
Learning: Applies to go/deploy/deploy/*/docs/** : Documentation should be placed in `<service>/docs`.
Applied to files:
apps/dashboard/app/(app)/projects/_components/list/index.tsx
📚 Learning: 2025-07-15T14:45:18.920Z
Learnt from: ogzhanolguncu
PR: unkeyed/unkey#3564
File: go/cmd/cli/commands/deploy/flags.go:17-20
Timestamp: 2025-07-15T14:45:18.920Z
Learning: In the go/cmd/cli/commands/deploy/ directory, ogzhanolguncu prefers to keep potentially temporary features (like UNKEY_DOCKER_REGISTRY environment variable) undocumented in help text if they might be deleted in the future, to avoid documentation churn.
Applied to files:
apps/dashboard/app/(app)/projects/_components/list/index.tsx
📚 Learning: 2025-07-21T18:05:58.236Z
Learnt from: CR
PR: unkeyed/unkey#0
File: go/deploy/CLAUDE.md:0-0
Timestamp: 2025-07-21T18:05:58.236Z
Learning: Applies to go/deploy/**/*.{go,js,ts,tsx,py,sh,md,txt,json,yaml,yml,ini,env,conf,html,css,scss,xml,c,h,cpp,java,rb,rs,php,pl,sql} : Make sure to add relevant anchor comments whenever a file or piece of code is too complex, very important, confusing, or could have a bug.
Applied to files:
apps/dashboard/app/(app)/projects/_components/list/index.tsx
📚 Learning: 2025-07-03T11:57:15.263Z
Learnt from: chronark
PR: unkeyed/unkey#3324
File: apps/dashboard/app/(app)/authorization/roles/components/upsert-role/components/warning-callout.tsx:22-27
Timestamp: 2025-07-03T11:57:15.263Z
Learning: The `target` prop on `InlineLink` components in the unkey/ui package is a boolean prop, not a string. When `target` is truthy, it automatically sets `target="_blank"` and `rel="noopener noreferrer"` on the underlying anchor element. Using just `target` (equivalent to `target={true}`) is the correct way to make the link open in a new tab.
Applied to files:
apps/dashboard/app/(app)/projects/_components/list/index.tsx
📚 Learning: 2024-12-03T14:17:08.016Z
Learnt from: ogzhanolguncu
PR: unkeyed/unkey#2143
File: apps/dashboard/app/(app)/logs/logs-page.tsx:77-83
Timestamp: 2024-12-03T14:17:08.016Z
Learning: The `<LogsTable />` component already implements virtualization to handle large datasets efficiently.
Applied to files:
apps/dashboard/app/(app)/projects/_components/list/index.tsx
📚 Learning: 2024-12-03T14:23:07.189Z
Learnt from: ogzhanolguncu
PR: unkeyed/unkey#2143
File: apps/dashboard/app/(app)/logs/components/log-details/resizable-panel.tsx:37-49
Timestamp: 2024-12-03T14:23:07.189Z
Learning: In `apps/dashboard/app/(app)/logs/components/log-details/resizable-panel.tsx`, the resize handler is already debounced.
Applied to files:
apps/dashboard/app/(app)/projects/_components/controls/components/projects-list-search/index.tsxapps/dashboard/app/(app)/projects/_components/list/projects-card.tsx
📚 Learning: 2024-10-04T17:27:09.821Z
Learnt from: chronark
PR: unkeyed/unkey#2146
File: apps/dashboard/app/(app)/apis/[apiId]/settings/default-prefix.tsx:74-75
Timestamp: 2024-10-04T17:27:09.821Z
Learning: In `apps/dashboard/app/(app)/apis/[apiId]/settings/default-prefix.tsx`, the hidden `<input>` elements for `workspaceId` and `keyAuthId` work correctly without being registered with React Hook Form.
Applied to files:
apps/dashboard/app/(app)/projects/_components/controls/components/projects-list-search/index.tsx
📚 Learning: 2025-04-24T14:34:30.621Z
Learnt from: ogzhanolguncu
PR: unkeyed/unkey#3115
File: apps/dashboard/components/logs/checkbox/filters-popover.tsx:33-55
Timestamp: 2025-04-24T14:34:30.621Z
Learning: In the ShortcutActivator component within filters-popover.tsx, the purpose is to track keys separately for each filter item, providing a registration mechanism for shortcuts passed to it rather than enforcing specific key combinations like option+shift+key.
Applied to files:
apps/dashboard/app/(app)/projects/_components/controls/components/projects-list-search/index.tsx
📚 Learning: 2025-06-24T13:29:10.129Z
Learnt from: ogzhanolguncu
PR: unkeyed/unkey#3401
File: apps/dashboard/app/(app)/logs/filters.query-params.ts:10-0
Timestamp: 2025-06-24T13:29:10.129Z
Learning: The `buildQueryParams` function in `apps/dashboard/app/(app)/logs/filters.query-params.ts` calls `useFilters()` hook inside it, but this is valid because the function is only called from within other React hooks, maintaining the Rules of Hooks compliance.
Applied to files:
apps/dashboard/app/(app)/projects/_components/controls/components/projects-list-search/index.tsx
📚 Learning: 2024-10-23T16:19:59.657Z
Learnt from: p6l-richard
PR: unkeyed/unkey#2085
File: apps/www/components/glossary/terms-rolodex-desktop.tsx:39-50
Timestamp: 2024-10-23T16:19:59.657Z
Learning: Debouncing of the scroll handler is not needed yet in the function `TermsRolodexDesktop` in `apps/www/components/glossary/terms-rolodex-desktop.tsx`.
Applied to files:
apps/dashboard/app/(app)/projects/_components/controls/components/projects-list-search/index.tsx
📚 Learning: 2025-02-21T11:15:16.185Z
Learnt from: ogzhanolguncu
PR: unkeyed/unkey#2896
File: internal/clickhouse/src/ratelimits.ts:468-592
Timestamp: 2025-02-21T11:15:16.185Z
Learning: The cursor logic in getRatelimitOverviewLogs query uses (time, request_id) < (cursorTime, cursorRequestId) comparison which works well with descending order but may need adjustment for ascending sorts based on real usage patterns.
Applied to files:
apps/dashboard/lib/trpc/routers/deploy/project/list.ts
📚 Learning: 2025-06-19T11:48:05.070Z
Learnt from: ogzhanolguncu
PR: unkeyed/unkey#3324
File: apps/dashboard/app/(app)/authorization/roles/components/table/components/actions/keys-table-action.popover.constants.tsx:17-18
Timestamp: 2025-06-19T11:48:05.070Z
Learning: In the authorization roles refactor, the RoleBasic type uses `roleId` as the property name for the role identifier, not `id`. This is consistent throughout the codebase in apps/dashboard/lib/trpc/routers/authorization/roles/query.ts.
Applied to files:
apps/dashboard/lib/trpc/routers/deploy/project/list.ts
📚 Learning: 2025-06-02T11:09:05.843Z
Learnt from: ogzhanolguncu
PR: unkeyed/unkey#3292
File: apps/dashboard/lib/vault.ts:60-78
Timestamp: 2025-06-02T11:09:05.843Z
Learning: The vault implementation in `apps/dashboard/lib/vault.ts` is a duplicate of the vault package from `api` and should be kept consistent with the original implementation.
Applied to files:
apps/dashboard/lib/trpc/routers/deploy/project/list.ts
📚 Learning: 2025-07-30T10:46:56.453Z
Learnt from: Flo4604
PR: unkeyed/unkey#3677
File: go/pkg/db/queries/ratelimit_override_list_by_namespace_id.sql:7-8
Timestamp: 2025-07-30T10:46:56.453Z
Learning: In the Unkey codebase, cursor pagination uses a "limit + 1" approach where queries fetch one extra record beyond the requested limit. The cursor is set to the ID of this extra record (which is not returned to the client), so using `>=` in the WHERE clause is correct because the next page should start from that cursor ID.
Applied to files:
apps/dashboard/lib/trpc/routers/deploy/project/list.ts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
- GitHub Check: Build / Build
- GitHub Check: Test API / API Test Local
- GitHub Check: Test Packages / Test
- GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (5)
apps/dashboard/app/(app)/projects/navigation.tsx (2)
1-1: Client component marker is correct."use client" is appropriate here given the dialog/hook usage downstream.
8-15: Component structure LGTM.Named export, Navbar + Breadcrumbs + CreateProjectDialog composition reads clean and matches our conventions.
apps/dashboard/lib/trpc/routers/deploy/project/create.ts (1)
19-21: Verify column namedeletedAtM.
deletedAtMlooks unusual—convention elsewhere isdeletedAt. If the column is actuallydeletedAt, the current check will silently skip valid workspaces.apps/dashboard/app/(app)/projects/_components/controls/components/projects-list-search/index.tsx (1)
64-66:crypto.randomUUIDbrowser support.
crypto.randomUUID()isn’t available in Safari ≤ 14 and some older Chromium versions. If broad browser support is required, fall back to a polyfill or a small UUID lib.apps/dashboard/app/(app)/projects/_components/controls/index.tsx (1)
1-2: Import path fix looks good.The earlier
.tsextension issue is gone; the import now resolves correctly to the JSX component.
.../dashboard/app/(app)/projects/_components/controls/components/projects-list-search/index.tsx
Show resolved
Hide resolved
apps/dashboard/app/(app)/projects/_components/list/projects-card.tsx
Outdated
Show resolved
Hide resolved
apps/dashboard/app/(app)/projects/_components/list/projects-card.tsx
Outdated
Show resolved
Hide resolved
apps/dashboard/app/(app)/projects/_components/list/projects-card.tsx
Outdated
Show resolved
Hide resolved
|
@ogzhanolguncu here is what I found: The icon is weirdly different than every other icon we have in the product.
Secondly clicking the 3 dot menu pushes the user into the project CleanShot.2025-08-11.at.08.26.47.mp4Not sure if this is related to this change or another but adding a repository causes this double external link. I think this is not related to you but flagging.
|
|
|
okay should be all good now |
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (1)
apps/dashboard/app/(app)/projects/_components/list/projects-card.tsx (1)
73-80: Same issue with placeholder link.Similar to the project name, the commit title link uses
href="#". Consider using a span instead for consistency and to avoid confusion.- <InfoTooltip content={commitTitle} asChild position={{ align: "start", side: "top" }}> - <Link - href="#" - className="text-[13px] font-medium text-accent-12 leading-5 min-w-0 truncate cursor-pointer hover:underline" - > - {commitTitle} - </Link> - </InfoTooltip> + <InfoTooltip content={commitTitle} asChild position={{ align: "start", side: "top" }}> + <span className="text-[13px] font-medium text-accent-12 leading-5 min-w-0 truncate cursor-pointer"> + {commitTitle} + </span> + </InfoTooltip>
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (2)
apps/dashboard/app/(app)/projects/_components/list/projects-card.tsx(1 hunks)apps/dashboard/components/navigation/sidebar/workspace-navigations.tsx(2 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit Inference Engine (CLAUDE.md)
**/*.{js,jsx,ts,tsx}: Use Biome for formatting and linting in TypeScript/JavaScript projects
Prefer named exports over default exports in TypeScript/JavaScript, except for Next.js pages
Files:
apps/dashboard/components/navigation/sidebar/workspace-navigations.tsxapps/dashboard/app/(app)/projects/_components/list/projects-card.tsx
**/*.{ts,tsx}
📄 CodeRabbit Inference Engine (CLAUDE.md)
**/*.{ts,tsx}: Follow strict TypeScript configuration
Use Zod for runtime validation in TypeScript projects
Files:
apps/dashboard/components/navigation/sidebar/workspace-navigations.tsxapps/dashboard/app/(app)/projects/_components/list/projects-card.tsx
🧠 Learnings (3)
📚 Learning: 2024-10-04T20:44:38.489Z
Learnt from: chronark
PR: unkeyed/unkey#2180
File: apps/dashboard/lib/constants/workspace-navigations.tsx:56-118
Timestamp: 2024-10-04T20:44:38.489Z
Learning: When typing the `workspace` parameter in functions like `createWorkspaceNavigation`, prefer importing the `Workspace` type from the database module and picking the necessary keys (e.g., `features`) instead of redefining the interface.
Applied to files:
apps/dashboard/components/navigation/sidebar/workspace-navigations.tsx
📚 Learning: 2025-07-28T20:38:53.244Z
Learnt from: mcstepp
PR: unkeyed/unkey#3662
File: apps/dashboard/app/(app)/projects/[projectId]/diff/[...compare]/components/client.tsx:322-341
Timestamp: 2025-07-28T20:38:53.244Z
Learning: In apps/dashboard/app/(app)/projects/[projectId]/diff/[...compare]/components/client.tsx, mcstepp prefers to keep hardcoded endpoint logic in the getDiffType function during POC phases for demonstrating diff functionality, rather than implementing a generic diff algorithm. This follows the pattern of keeping simplified implementations for demonstration purposes.
Applied to files:
apps/dashboard/app/(app)/projects/_components/list/projects-card.tsx
📚 Learning: 2024-12-03T14:07:45.173Z
Learnt from: ogzhanolguncu
PR: unkeyed/unkey#2143
File: apps/dashboard/components/ui/group-button.tsx:21-31
Timestamp: 2024-12-03T14:07:45.173Z
Learning: In the `ButtonGroup` component (`apps/dashboard/components/ui/group-button.tsx`), avoid suggesting the use of `role="group"` in ARIA attributes.
Applied to files:
apps/dashboard/app/(app)/projects/_components/list/projects-card.tsx
🧬 Code Graph Analysis (2)
apps/dashboard/components/navigation/sidebar/workspace-navigations.tsx (2)
internal/icons/src/icons/cube.tsx (1)
Cube(15-39)internal/icons/src/icons/tag.tsx (1)
Tag(15-39)
apps/dashboard/app/(app)/projects/_components/list/projects-card.tsx (4)
internal/icons/src/icons/cube.tsx (1)
Cube(15-39)internal/ui/src/components/info-tooltip.tsx (1)
InfoTooltip(63-63)internal/icons/src/icons/code-branch.tsx (1)
CodeBranch(15-41)apps/dashboard/app/(app)/projects/_components/list/region-badges.tsx (1)
RegionBadges(9-53)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
- GitHub Check: Test API / API Test Local
- GitHub Check: Test Go API Local / Test
- GitHub Check: Build / Build
- GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (7)
apps/dashboard/components/navigation/sidebar/workspace-navigations.tsx (4)
3-3: Icon import switch to Cube — looks goodMatches the new Projects theme and keeps the icon set consistent.
55-56: Projects nav icon set to Cube — LGTMConsistent with the updated Projects UI direction.
59-59: No changes needed for thebetaFeatures.deploymentsflag
Verified that thedeploymentskey is used consistently in
apps/dashboard/lib/trpc/routers/workspace/optIntoBeta.tsapps/dashboard/components/navigation/sidebar/workspace-navigations.tsxapps/dashboard/app/(app)/projects/[projectId]/deployments/[deploymentId]/page.tsxThere are no references to a singular
deploymentordeploykey, so the current plural usage is correct.
60-60: Confirmed: Parentgroupwrapper is present,group-hoverwill apply
The<SidebarMenuButton>container (viagetButtonStyles) includes thegroupclass, so yourgroup-hover:bg-gray-1on<Tag>in
apps/dashboard/components/navigation/sidebar/workspace-navigations.tsx:60
will activate as intended.Optional polish: add a smooth transition on the tag’s background color for a subtler hover effect.
- File: apps/dashboard/components/navigation/sidebar/workspace-navigations.tsx (line 60)
- tag: <Tag label="Beta" className="mr-2 group-hover:bg-gray-1" />, + tag: <Tag label="Beta" className="mr-2 transition-colors group-hover:bg-gray-1" />,apps/dashboard/app/(app)/projects/_components/list/projects-card.tsx (3)
1-18: LGTM!Clean imports and well-structured type definition. The use of
ReactNodefor actions provides good flexibility.
32-39: LGTM!Excellent solution for card-wide navigation. The invisible link layer with proper z-index management allows the entire card to be clickable while preserving individual interactive elements. The aria-label provides good accessibility context.
96-98: LGTM!Clean usage of the RegionBadges component with proper prop passing.
|
James have you checked the latest changes? |
|
I have not. Mostly because notifications don't work on GH. I will look in an hour |
Graphite Automations"Post a GIF when PR approved" took an action on this PR • (08/12/25)1 gif was posted to this PR based on Andreas Thomas's automation. |
|
lemme double check and merge 🫡 |
|
can you reapprove @perkinsjr? |
|
idk why but graphite is fucking with auto merge |
|
might need a force merge |



What does this PR do?
This PR adds new Projects list for Unkey Deploy. It also adds new project creation dialog.
Type of change
How should this be tested?
Checklist
Required
pnpm buildpnpm fmtconsole.logsgit pull origin mainAppreciated
Summary by CodeRabbit
New Features
Improvements
Bug Fixes
Chores