Skip to content

feat: project details UI#3853

Merged
chronark merged 25 commits intomainfrom
project-details-ui
Sep 1, 2025
Merged

feat: project details UI#3853
chronark merged 25 commits intomainfrom
project-details-ui

Conversation

@ogzhanolguncu
Copy link
Contributor

@ogzhanolguncu ogzhanolguncu commented Aug 26, 2025

What does this PR do?

This PR adds new UI for project details, which includes active production deployment details with logs, a drawer for more details about the active deployment. The environment section is rough currently, it doesn't handle CRUD fully and just lists data directly. Most of the hardcoded data is coming from tRPC, so if we happen to go to production with deployment, anyone can change the data source and get the deployment UI ready.

Edit: Environment Variable section is very very very rough. I'll do a proper refactor when I return. This one should give us some insight about our actual logic.

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • Chore (refactoring code, technical debt, workflow improvements)
  • Enhancement (small improvements)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • This change requires a documentation update

How should this be tested?

  • Create a project
  • Go into details of it
  • Voilà

Checklist

Required

  • Filled out the "How to test" section in this PR
  • Read Contributing Guide
  • Self-reviewed my own code
  • Commented on my code in hard-to-understand areas
  • Ran pnpm build
  • Ran pnpm fmt
  • Checked for warnings, there are none
  • Removed all console.logs
  • Merged the latest changes from main onto my branch with git pull origin main
  • My changes don't cause any responsiveness issues

Appreciated

  • If a UI change was made: Added a screen recording or screenshots to this PR
  • Updated the Unkey Docs if changes were necessary

Summary by CodeRabbit

  • New Features

    • Project Details page: Active Deployment card, Domains, and Environment Variables sections.
    • Build logs viewer: expand/collapse, filters (all/errors/warnings), search, and copy.
    • Slide-in details panel with rich deployment info.
    • Environment variables editor with add/edit/delete flows.
    • Expanded icon set for richer UI.
  • Refactor

    • Navigation revamped (new actions, renamed ProjectNavigation) and sub-navigation with Overview/Deployments/Logs.
    • Deployment listing/search now project-scoped for more relevant results.

@changeset-bot
Copy link

changeset-bot bot commented Aug 26, 2025

⚠️ No Changeset found

Latest commit: 20aa3f4

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@vercel
Copy link

vercel bot commented Aug 26, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
dashboard Ready Ready Preview Comment Aug 31, 2025 7:51pm
1 Skipped Deployment
Project Deployment Preview Comments Updated (UTC)
engineering Ignored Ignored Preview Aug 31, 2025 7:51pm

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Aug 26, 2025

📝 Walkthrough

Walkthrough

Switches deployment queries to project-scoped TRPC routes; adds a project layout/context and sub-navigation; introduces Active Deployment card with build logs and a right-side details panel; implements environment variables UI and local edit flow; adds project TRPC endpoints (details, logs, envs); and expands the internal icons library.

Changes

Cohort / File(s) Summary
TRPC: project-scoped deployment calls
apps/dashboard/app/(app)/projects/[projectId]/deployments/components/controls/components/deployment-list-search/index.tsx, apps/dashboard/app/(app)/projects/[projectId]/deployments/components/table/hooks/use-deployments-list-query.ts
Switched TRPC calls from trpc.deploy.deployment.* to trpc.deploy.project.deployment.* (search and list). Logic around success/error handling and pagination unchanged.
Layout & navigation
apps/dashboard/app/(app)/projects/[projectId]/layout.tsx, .../layout-provider.tsx, .../navigations/project-navigation.tsx, .../navigations/project-sub-navigation.tsx
Added ProjectLayoutWrapper, ProjectLayoutContext/useProjectLayout, prefetch behavior, renamed/refactored top navigation to ProjectNavigation, and added ProjectSubNavigation with tabs and details trigger.
Pages
apps/dashboard/app/(app)/projects/[projectId]/page.tsx, apps/dashboard/app/(app)/projects/[projectId]/deployments/page.tsx, apps/dashboard/app/(app)/projects/[projectId]/logs/page.tsx, apps/dashboard/app/(app)/projects/[projectId]/deployments/components/control-cloud.tsx
Added ProjectDetails as root page, created Deployments and Logs client pages/placeholders, and added deployments page wrapper components.
Active deployment card & logs
apps/dashboard/app/(app)/projects/[projectId]/details/active-deployment-card/index.tsx, .../card.tsx, .../filter-button.tsx, .../info-chip.tsx, .../status-indicator.tsx, .../skeleton.tsx, .../hooks/use-deployment-logs.tsx
New ActiveDeploymentCard and supporting components; hook useDeploymentLogs queries build logs, formats entries, provides filtering/search/scroll behavior, and exposes UI state and handlers.
Project details expandable panel
apps/dashboard/app/(app)/projects/[projectId]/details/project-details-expandables/index.tsx, .../detail-section.tsx, .../sections.tsx, .../collapsible-row.tsx, .../domain-row.tsx
Added right-side ProjectDetailsExpandable panel, DetailSection/DetailRow builder, createDetailSections mapping from DeploymentDetails, CollapsibleRow and DomainRow presentational components.
Environment variables UI & hooks
apps/dashboard/app/(app)/projects/[projectId]/details/env-variables-section/index.tsx, .../hooks/use-env-var.tsx, .../env-var-row.tsx, .../add-env-var-row.tsx
New EnvironmentVariablesSection with useEnvVars hook: fetches envs via TRPC, local edit/add/delete state and actions (client-side placeholders for server mutations), and row components for display/edit/add.
TRPC: project endpoints (details, logs, envs)
apps/dashboard/lib/trpc/routers/index.ts, .../deploy/project/active-deployment/getDetails.ts, .../active-deployment/getBuildLogs.ts, .../envs/list.ts
Added deploy.project.activeDeployment.details, deploy.project.activeDeployment.buildLogs, and deploy.project.envs.getEnvs procedures with Zod schemas and mock/static data; wired into main router.
Icons: additions & sizing updates
internal/icons/src/icons/*.tsx (many new), internal/icons/src/index.ts, internal/icons/src/icons/bolt.tsx, .../chevron-down.tsx, .../code-commit.tsx, .../connections.tsx, .../triangle-warning-2.tsx
Added many new icon components and re-exported them in the barrel; updated icons to use sizeMap for pixel size/strokeWidth and rewrote visuals for some icons (no public API surface removals).

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant Layout as ProjectLayoutWrapper
  participant Ctx as ProjectLayoutContext
  participant SubNav as ProjectSubNavigation
  participant TRPC as tRPC
  participant Panel as ProjectDetailsExpandable
  participant Card as ActiveDeploymentCard
  participant LogsHook as useDeploymentLogs

  User->>Layout: Navigate to /projects/[projectId]
  Layout->>TRPC: prefetch(envs.getEnvs { projectId })
  Layout->>Ctx: provide { projectId, activeDeploymentId, isDetailsOpen }
  SubNav->>Layout: onMount(distanceToTop)
  Layout->>TRPC: prefetch(activeDeployment.details { deploymentId })
  TRPC-->>Layout: details prefetched
  Layout->>Panel: open with activeDeploymentId

  Card->>Ctx: read activeDeploymentId
  Card->>TRPC: getData(activeDeployment.details { deploymentId })
  alt details present
    Card->>User: render header & metadata
    User->>Card: Expand logs
    Card->>LogsHook: init(deploymentId)
    LogsHook->>TRPC: query(buildLogs { deploymentId })
    TRPC-->>LogsHook: { logs }
    LogsHook-->>Card: filteredLogs + counts
    Card->>User: show logs, filters, search, copy
  else
    Card->>User: render skeleton
  end
Loading
sequenceDiagram
  autonumber
  actor User
  participant EnvSec as EnvironmentVariablesSection
  participant Hook as useEnvVars
  participant TRPC as tRPC

  EnvSec->>Hook: init({ projectId, environment })
  Hook->>TRPC: getEnvs { projectId }
  TRPC-->>Hook: { production, preview, development }
  Hook-->>EnvSec: envVars

  User->>EnvSec: Click "Add"
  EnvSec->>Hook: startAdding / setNewVar
  User->>EnvSec: Enter key/value, Save
  EnvSec->>Hook: addVariable (client-side)
  Note right of Hook: server mutations are TODO
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested labels

Feature, Dashboard

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch project-details-ui

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore or @coderabbit ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@github-actions
Copy link
Contributor

github-actions bot commented Aug 29, 2025

Thank you for following the naming conventions for pull request titles! 🙏

@ogzhanolguncu ogzhanolguncu changed the title Project details UI feat: project details UI Aug 29, 2025
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: 107

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (7)
internal/icons/src/icons/chevron-down.tsx (1)

19-25: Standardize SVG prop spread: put {...props} after height/width
Update all icons in this PR (e.g. chevron-down.tsx, bolt.tsx, circle-xmark.tsx, triangle-warning-2.tsx, etc.) so that {...props} appears last in the <svg> tag, ensuring consumer-specified height/width aren’t overridden.

internal/icons/src/icons/triangle-warning-2.tsx (1)

20-26: Align SVG prop spread order with the chosen convention

This file places {...props} after height/width (allowing overrides). Ensure this matches the convention you select across the icon set to avoid inconsistent behavior.

apps/dashboard/app/(app)/projects/[projectId]/deployments/components/controls/components/deployment-list-search/index.tsx (1)

52-56: Guard empty queries before calling the LLM endpoint

Trim and short-circuit on empty input to avoid noisy toasts from the backend and unnecessary requests.

-      onSearch={(query) =>
-        queryLLMForStructuredOutput.mutateAsync({
-          query,
-        })
-      }
+      onSearch={(query) => {
+        const q = query.trim();
+        if (q.length === 0) {
+          toast.error("Please enter a search query.", { position: "top-right", duration: 5000 });
+          return;
+        }
+        return queryLLMForStructuredOutput.mutateAsync({ query: q });
+      }}
apps/dashboard/app/(app)/projects/[projectId]/deployments/components/table/hooks/use-deployments-list-query.ts (2)

37-39: Don’t throw inside a hook for filter operator mismatches; fail-soft.

Throwing here will crash the page on any malformed filter. Prefer skipping invalid filters.

Apply:

-          if (!validOperators.includes(filter.operator)) {
-            throw new Error("Invalid operator");
-          }
+          if (!validOperators.includes(filter.operator)) {
+            return;
+          }

And similarly for the "branch" case:

-          if (!validOperators.includes(filter.operator)) {
-            throw new Error("Invalid operator");
-          }
+          if (!validOperators.includes(filter.operator)) {
+            return;
+          }

Also applies to: 54-56


100-113: Map rebuild logic is fine; consider preserving total from the last page.

Minor: you read total from pages[0]. If the API ever changes this per page, prefer the last page (or an explicit meta). Not blocking.

-      if (deploymentData.pages.length > 0) {
-        setTotalCount(deploymentData.pages[0].total);
-      }
+      const first = deploymentData.pages[0];
+      if (first) setTotalCount(first.total);
apps/dashboard/app/(app)/projects/[projectId]/navigations/project-navigation.tsx (1)

41-43: Avoid throwing in UI for missing project; render a fallback.

Throwing crashes the page. Show Not Found or redirect.

-  if (!activeProject) {
-    throw new Error(`Project with id "${projectId}" not found`);
-  }
+  if (!activeProject) {
+    return (
+      <Navbar>
+        <Navbar.Breadcrumbs icon={<Cube />}>
+          <Navbar.Breadcrumbs.Link href="/projects">Projects</Navbar.Breadcrumbs.Link>
+          <Navbar.Breadcrumbs.Link href="#" isIdentifier noop>
+            Project not found
+          </Navbar.Breadcrumbs.Link>
+        </Navbar.Breadcrumbs>
+      </Navbar>
+    );
+  }
internal/icons/src/index.ts (1)

1-131: Optional: keep exports alphabetized for scanability

If there’s no enforced order, consider alphabetizing within the barrel to simplify diffs.

♻️ Duplicate comments (3)
internal/icons/src/icons/heart.tsx (1)

1-11: Same licensing concern as in double-chevron-left.

Please address the Nucleo redistribution restriction here as well.

internal/icons/src/icons/list-radio.tsx (1)

1-11: Same licensing concern as in double-chevron-left.

Please address the Nucleo redistribution restriction here as well.

internal/icons/src/icons/grid-circle.tsx (1)

1-11: Same licensing concern as in double-chevron-left.

Please address the Nucleo redistribution restriction here as well.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 45e6e76 and 294d449.

📒 Files selected for processing (47)
  • apps/dashboard/app/(app)/projects/[projectId]/deployments/components/controls/components/deployment-list-search/index.tsx (1 hunks)
  • apps/dashboard/app/(app)/projects/[projectId]/deployments/components/table/hooks/use-deployments-list-query.ts (1 hunks)
  • apps/dashboard/app/(app)/projects/[projectId]/deployments/page.tsx (1 hunks)
  • apps/dashboard/app/(app)/projects/[projectId]/details/active-deployment-card/card.tsx (1 hunks)
  • apps/dashboard/app/(app)/projects/[projectId]/details/active-deployment-card/filter-button.tsx (1 hunks)
  • apps/dashboard/app/(app)/projects/[projectId]/details/active-deployment-card/hooks/use-deployment-logs.tsx (1 hunks)
  • apps/dashboard/app/(app)/projects/[projectId]/details/active-deployment-card/index.tsx (1 hunks)
  • apps/dashboard/app/(app)/projects/[projectId]/details/active-deployment-card/info-chip.tsx (1 hunks)
  • apps/dashboard/app/(app)/projects/[projectId]/details/active-deployment-card/skeleton.tsx (1 hunks)
  • apps/dashboard/app/(app)/projects/[projectId]/details/active-deployment-card/status-indicator.tsx (1 hunks)
  • apps/dashboard/app/(app)/projects/[projectId]/details/collapsible-row.tsx (1 hunks)
  • apps/dashboard/app/(app)/projects/[projectId]/details/domain-row.tsx (1 hunks)
  • apps/dashboard/app/(app)/projects/[projectId]/details/env-variables-section/add-env-var-row.tsx (1 hunks)
  • apps/dashboard/app/(app)/projects/[projectId]/details/env-variables-section/env-var-row.tsx (1 hunks)
  • apps/dashboard/app/(app)/projects/[projectId]/details/env-variables-section/hooks/use-env-var.tsx (1 hunks)
  • apps/dashboard/app/(app)/projects/[projectId]/details/env-variables-section/index.tsx (1 hunks)
  • apps/dashboard/app/(app)/projects/[projectId]/details/project-details-expandables/detail-section.tsx (1 hunks)
  • apps/dashboard/app/(app)/projects/[projectId]/details/project-details-expandables/index.tsx (1 hunks)
  • apps/dashboard/app/(app)/projects/[projectId]/details/project-details-expandables/sections.tsx (1 hunks)
  • apps/dashboard/app/(app)/projects/[projectId]/layout-provider.tsx (1 hunks)
  • apps/dashboard/app/(app)/projects/[projectId]/layout.tsx (1 hunks)
  • apps/dashboard/app/(app)/projects/[projectId]/logs/page.tsx (1 hunks)
  • apps/dashboard/app/(app)/projects/[projectId]/navigations/project-navigation.tsx (2 hunks)
  • apps/dashboard/app/(app)/projects/[projectId]/navigations/project-sub-navigation.tsx (1 hunks)
  • apps/dashboard/app/(app)/projects/[projectId]/page.tsx (1 hunks)
  • apps/dashboard/lib/trpc/routers/deploy/project/active-deployment/getBuildLogs.ts (1 hunks)
  • apps/dashboard/lib/trpc/routers/deploy/project/active-deployment/getDetails.ts (1 hunks)
  • apps/dashboard/lib/trpc/routers/deploy/project/envs/list.ts (1 hunks)
  • apps/dashboard/lib/trpc/routers/index.ts (2 hunks)
  • internal/icons/src/icons/bolt.tsx (1 hunks)
  • internal/icons/src/icons/chart-activity.tsx (1 hunks)
  • internal/icons/src/icons/chevron-down.tsx (2 hunks)
  • internal/icons/src/icons/circle-xmark.tsx (1 hunks)
  • internal/icons/src/icons/code-commit.tsx (1 hunks)
  • internal/icons/src/icons/connections.tsx (1 hunks)
  • internal/icons/src/icons/double-chevron-left.tsx (1 hunks)
  • internal/icons/src/icons/double-chevron-right.tsx (1 hunks)
  • internal/icons/src/icons/grid-circle.tsx (1 hunks)
  • internal/icons/src/icons/hard-drive.tsx (1 hunks)
  • internal/icons/src/icons/heart.tsx (1 hunks)
  • internal/icons/src/icons/list-radio.tsx (1 hunks)
  • internal/icons/src/icons/location2.tsx (1 hunks)
  • internal/icons/src/icons/message-writing.tsx (1 hunks)
  • internal/icons/src/icons/paperclip-2.tsx (1 hunks)
  • internal/icons/src/icons/share-up-right.tsx (1 hunks)
  • internal/icons/src/icons/triangle-warning-2.tsx (2 hunks)
  • internal/icons/src/index.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/[projectId]/details/active-deployment-card/card.tsx
  • internal/icons/src/icons/heart.tsx
  • internal/icons/src/icons/list-radio.tsx
  • apps/dashboard/app/(app)/projects/[projectId]/details/active-deployment-card/status-indicator.tsx
  • internal/icons/src/icons/double-chevron-right.tsx
  • internal/icons/src/icons/location2.tsx
  • apps/dashboard/app/(app)/projects/[projectId]/details/env-variables-section/env-var-row.tsx
  • internal/icons/src/icons/circle-xmark.tsx
  • internal/icons/src/icons/triangle-warning-2.tsx
  • apps/dashboard/app/(app)/projects/[projectId]/deployments/page.tsx
  • internal/icons/src/icons/paperclip-2.tsx
  • apps/dashboard/app/(app)/projects/[projectId]/details/active-deployment-card/filter-button.tsx
  • apps/dashboard/app/(app)/projects/[projectId]/deployments/components/controls/components/deployment-list-search/index.tsx
  • apps/dashboard/lib/trpc/routers/deploy/project/active-deployment/getBuildLogs.ts
  • apps/dashboard/app/(app)/projects/[projectId]/details/env-variables-section/add-env-var-row.tsx
  • internal/icons/src/icons/share-up-right.tsx
  • internal/icons/src/icons/chevron-down.tsx
  • apps/dashboard/app/(app)/projects/[projectId]/details/domain-row.tsx
  • apps/dashboard/app/(app)/projects/[projectId]/details/active-deployment-card/skeleton.tsx
  • internal/icons/src/icons/double-chevron-left.tsx
  • apps/dashboard/app/(app)/projects/[projectId]/details/active-deployment-card/hooks/use-deployment-logs.tsx
  • apps/dashboard/app/(app)/projects/[projectId]/details/collapsible-row.tsx
  • apps/dashboard/app/(app)/projects/[projectId]/details/active-deployment-card/info-chip.tsx
  • internal/icons/src/icons/grid-circle.tsx
  • internal/icons/src/icons/code-commit.tsx
  • internal/icons/src/icons/chart-activity.tsx
  • apps/dashboard/app/(app)/projects/[projectId]/details/project-details-expandables/index.tsx
  • apps/dashboard/app/(app)/projects/[projectId]/logs/page.tsx
  • apps/dashboard/app/(app)/projects/[projectId]/details/env-variables-section/hooks/use-env-var.tsx
  • apps/dashboard/app/(app)/projects/[projectId]/details/project-details-expandables/sections.tsx
  • apps/dashboard/app/(app)/projects/[projectId]/navigations/project-sub-navigation.tsx
  • apps/dashboard/app/(app)/projects/[projectId]/deployments/components/table/hooks/use-deployments-list-query.ts
  • apps/dashboard/app/(app)/projects/[projectId]/details/project-details-expandables/detail-section.tsx
  • internal/icons/src/icons/hard-drive.tsx
  • apps/dashboard/app/(app)/projects/[projectId]/details/env-variables-section/index.tsx
  • apps/dashboard/lib/trpc/routers/deploy/project/active-deployment/getDetails.ts
  • apps/dashboard/app/(app)/projects/[projectId]/layout.tsx
  • internal/icons/src/icons/bolt.tsx
  • apps/dashboard/app/(app)/projects/[projectId]/details/active-deployment-card/index.tsx
  • apps/dashboard/app/(app)/projects/[projectId]/layout-provider.tsx
  • apps/dashboard/app/(app)/projects/[projectId]/page.tsx
  • apps/dashboard/lib/trpc/routers/deploy/project/envs/list.ts
  • internal/icons/src/icons/message-writing.tsx
  • apps/dashboard/lib/trpc/routers/index.ts
  • internal/icons/src/icons/connections.tsx
  • apps/dashboard/app/(app)/projects/[projectId]/navigations/project-navigation.tsx
  • internal/icons/src/index.ts
**/*.{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/[projectId]/details/active-deployment-card/card.tsx
  • internal/icons/src/icons/heart.tsx
  • internal/icons/src/icons/list-radio.tsx
  • apps/dashboard/app/(app)/projects/[projectId]/details/active-deployment-card/status-indicator.tsx
  • internal/icons/src/icons/double-chevron-right.tsx
  • internal/icons/src/icons/location2.tsx
  • apps/dashboard/app/(app)/projects/[projectId]/details/env-variables-section/env-var-row.tsx
  • internal/icons/src/icons/circle-xmark.tsx
  • internal/icons/src/icons/triangle-warning-2.tsx
  • apps/dashboard/app/(app)/projects/[projectId]/deployments/page.tsx
  • internal/icons/src/icons/paperclip-2.tsx
  • apps/dashboard/app/(app)/projects/[projectId]/details/active-deployment-card/filter-button.tsx
  • apps/dashboard/app/(app)/projects/[projectId]/deployments/components/controls/components/deployment-list-search/index.tsx
  • apps/dashboard/lib/trpc/routers/deploy/project/active-deployment/getBuildLogs.ts
  • apps/dashboard/app/(app)/projects/[projectId]/details/env-variables-section/add-env-var-row.tsx
  • internal/icons/src/icons/share-up-right.tsx
  • internal/icons/src/icons/chevron-down.tsx
  • apps/dashboard/app/(app)/projects/[projectId]/details/domain-row.tsx
  • apps/dashboard/app/(app)/projects/[projectId]/details/active-deployment-card/skeleton.tsx
  • internal/icons/src/icons/double-chevron-left.tsx
  • apps/dashboard/app/(app)/projects/[projectId]/details/active-deployment-card/hooks/use-deployment-logs.tsx
  • apps/dashboard/app/(app)/projects/[projectId]/details/collapsible-row.tsx
  • apps/dashboard/app/(app)/projects/[projectId]/details/active-deployment-card/info-chip.tsx
  • internal/icons/src/icons/grid-circle.tsx
  • internal/icons/src/icons/code-commit.tsx
  • internal/icons/src/icons/chart-activity.tsx
  • apps/dashboard/app/(app)/projects/[projectId]/details/project-details-expandables/index.tsx
  • apps/dashboard/app/(app)/projects/[projectId]/logs/page.tsx
  • apps/dashboard/app/(app)/projects/[projectId]/details/env-variables-section/hooks/use-env-var.tsx
  • apps/dashboard/app/(app)/projects/[projectId]/details/project-details-expandables/sections.tsx
  • apps/dashboard/app/(app)/projects/[projectId]/navigations/project-sub-navigation.tsx
  • apps/dashboard/app/(app)/projects/[projectId]/deployments/components/table/hooks/use-deployments-list-query.ts
  • apps/dashboard/app/(app)/projects/[projectId]/details/project-details-expandables/detail-section.tsx
  • internal/icons/src/icons/hard-drive.tsx
  • apps/dashboard/app/(app)/projects/[projectId]/details/env-variables-section/index.tsx
  • apps/dashboard/lib/trpc/routers/deploy/project/active-deployment/getDetails.ts
  • apps/dashboard/app/(app)/projects/[projectId]/layout.tsx
  • internal/icons/src/icons/bolt.tsx
  • apps/dashboard/app/(app)/projects/[projectId]/details/active-deployment-card/index.tsx
  • apps/dashboard/app/(app)/projects/[projectId]/layout-provider.tsx
  • apps/dashboard/app/(app)/projects/[projectId]/page.tsx
  • apps/dashboard/lib/trpc/routers/deploy/project/envs/list.ts
  • internal/icons/src/icons/message-writing.tsx
  • apps/dashboard/lib/trpc/routers/index.ts
  • internal/icons/src/icons/connections.tsx
  • apps/dashboard/app/(app)/projects/[projectId]/navigations/project-navigation.tsx
  • internal/icons/src/index.ts
**/*.{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/active-deployment/getBuildLogs.ts
  • apps/dashboard/app/(app)/projects/[projectId]/deployments/components/table/hooks/use-deployments-list-query.ts
  • apps/dashboard/lib/trpc/routers/deploy/project/active-deployment/getDetails.ts
  • apps/dashboard/lib/trpc/routers/deploy/project/envs/list.ts
  • apps/dashboard/lib/trpc/routers/index.ts
  • internal/icons/src/index.ts
🧠 Learnings (9)
📓 Common learnings
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.
📚 Learning: 2025-08-25T13:05:22.441Z
Learnt from: ogzhanolguncu
PR: unkeyed/unkey#3834
File: internal/ui/src/components/form/input.tsx:130-131
Timestamp: 2025-08-25T13:05:22.441Z
Learning: The Input component in internal/ui/src/components/form/input.tsx is designed to support interactive right icons (like X buttons for deletion) by enabling pointer events on the right icon container, allowing clicks to be handled by the icon rather than passed through to the input.

Applied to files:

  • internal/icons/src/icons/double-chevron-right.tsx
  • internal/icons/src/icons/share-up-right.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/app/(app)/projects/[projectId]/deployments/page.tsx
  • apps/dashboard/app/(app)/projects/[projectId]/deployments/components/controls/components/deployment-list-search/index.tsx
  • apps/dashboard/lib/trpc/routers/deploy/project/active-deployment/getBuildLogs.ts
  • apps/dashboard/app/(app)/projects/[projectId]/deployments/components/table/hooks/use-deployments-list-query.ts
  • apps/dashboard/lib/trpc/routers/deploy/project/active-deployment/getDetails.ts
  • apps/dashboard/lib/trpc/routers/deploy/project/envs/list.ts
  • apps/dashboard/lib/trpc/routers/index.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/active-deployment/getBuildLogs.ts
  • apps/dashboard/lib/trpc/routers/deploy/project/active-deployment/getDetails.ts
  • apps/dashboard/lib/trpc/routers/index.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/active-deployment/getBuildLogs.ts
📚 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/[projectId]/logs/page.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/[projectId]/logs/page.tsx
  • apps/dashboard/app/(app)/projects/[projectId]/layout.tsx
📚 Learning: 2025-08-18T10:28:47.391Z
Learnt from: ogzhanolguncu
PR: unkeyed/unkey#3797
File: apps/dashboard/app/(app)/projects/[projectId]/deployments/components/control-cloud/index.tsx:1-4
Timestamp: 2025-08-18T10:28:47.391Z
Learning: In Next.js App Router, components that use React hooks don't need their own "use client" directive if they are rendered within a client component that already has the directive. The client boundary propagates to child components.

Applied to files:

  • apps/dashboard/app/(app)/projects/[projectId]/logs/page.tsx
📚 Learning: 2025-06-02T11:09:58.791Z
Learnt from: ogzhanolguncu
PR: unkeyed/unkey#3292
File: apps/dashboard/lib/trpc/routers/key/create.ts:11-14
Timestamp: 2025-06-02T11:09:58.791Z
Learning: In the unkey codebase, TypeScript and the env() function implementation already provide sufficient validation for environment variables, so additional runtime error handling for missing env vars is not needed.

Applied to files:

  • apps/dashboard/lib/trpc/routers/deploy/project/envs/list.ts
🧬 Code graph analysis (32)
internal/icons/src/icons/heart.tsx (1)
internal/icons/src/props.ts (2)
  • IconProps (30-36)
  • sizeMap (7-28)
internal/icons/src/icons/list-radio.tsx (1)
internal/icons/src/props.ts (2)
  • IconProps (30-36)
  • sizeMap (7-28)
internal/icons/src/icons/double-chevron-right.tsx (1)
internal/icons/src/props.ts (2)
  • IconProps (30-36)
  • sizeMap (7-28)
internal/icons/src/icons/location2.tsx (1)
internal/icons/src/props.ts (2)
  • IconProps (30-36)
  • sizeMap (7-28)
apps/dashboard/app/(app)/projects/[projectId]/details/env-variables-section/env-var-row.tsx (5)
apps/dashboard/lib/trpc/routers/deploy/project/envs/list.ts (1)
  • EnvVar (18-18)
internal/icons/src/icons/eye-slash.tsx (1)
  • EyeSlash (15-64)
internal/icons/src/icons/eye.tsx (1)
  • Eye (15-47)
internal/icons/src/icons/pen-writing-3.tsx (1)
  • PenWriting3 (15-45)
internal/icons/src/icons/trash.tsx (1)
  • Trash (16-57)
internal/icons/src/icons/circle-xmark.tsx (1)
internal/icons/src/props.ts (2)
  • IconProps (30-36)
  • sizeMap (7-28)
internal/icons/src/icons/paperclip-2.tsx (1)
internal/icons/src/props.ts (2)
  • IconProps (30-36)
  • sizeMap (7-28)
apps/dashboard/app/(app)/projects/[projectId]/details/active-deployment-card/filter-button.tsx (1)
internal/icons/src/props.ts (1)
  • IconProps (30-36)
apps/dashboard/lib/trpc/routers/deploy/project/active-deployment/getBuildLogs.ts (1)
apps/dashboard/lib/trpc/trpc.ts (4)
  • t (8-8)
  • requireUser (10-21)
  • requireWorkspace (23-36)
  • withRatelimit (122-138)
internal/icons/src/icons/share-up-right.tsx (1)
internal/icons/src/props.ts (2)
  • IconProps (30-36)
  • sizeMap (7-28)
internal/icons/src/icons/chevron-down.tsx (1)
internal/icons/src/props.ts (1)
  • sizeMap (7-28)
internal/icons/src/icons/double-chevron-left.tsx (1)
internal/icons/src/props.ts (2)
  • IconProps (30-36)
  • sizeMap (7-28)
apps/dashboard/app/(app)/projects/[projectId]/details/active-deployment-card/hooks/use-deployment-logs.tsx (1)
internal/clickhouse/src/logs.ts (1)
  • log (24-38)
apps/dashboard/app/(app)/projects/[projectId]/details/active-deployment-card/info-chip.tsx (1)
internal/icons/src/props.ts (1)
  • IconProps (30-36)
internal/icons/src/icons/grid-circle.tsx (1)
internal/icons/src/props.ts (2)
  • IconProps (30-36)
  • sizeMap (7-28)
internal/icons/src/icons/chart-activity.tsx (1)
internal/icons/src/props.ts (2)
  • IconProps (30-36)
  • sizeMap (7-28)
apps/dashboard/app/(app)/projects/[projectId]/details/project-details-expandables/index.tsx (3)
apps/dashboard/lib/trpc/server.ts (1)
  • trpc (7-14)
apps/dashboard/app/(app)/projects/[projectId]/details/project-details-expandables/sections.tsx (2)
  • createDetailSections (35-271)
  • DetailSection (30-33)
apps/dashboard/app/(app)/projects/[projectId]/details/project-details-expandables/detail-section.tsx (1)
  • DetailSection (33-55)
apps/dashboard/app/(app)/projects/[projectId]/details/env-variables-section/hooks/use-env-var.tsx (2)
apps/dashboard/lib/trpc/server.ts (1)
  • trpc (7-14)
apps/dashboard/lib/trpc/routers/deploy/project/envs/list.ts (1)
  • EnvVar (18-18)
apps/dashboard/app/(app)/projects/[projectId]/details/project-details-expandables/sections.tsx (2)
apps/dashboard/app/(app)/projects/[projectId]/details/project-details-expandables/detail-section.tsx (1)
  • DetailSection (33-55)
apps/dashboard/lib/trpc/routers/deploy/project/active-deployment/getDetails.ts (1)
  • DeploymentDetails (46-46)
apps/dashboard/app/(app)/projects/[projectId]/navigations/project-sub-navigation.tsx (4)
internal/icons/src/props.ts (1)
  • IconProps (30-36)
internal/icons/src/icons/grid-circle.tsx (1)
  • GridCircle (15-69)
internal/icons/src/icons/cloud.tsx (1)
  • Cloud (15-38)
internal/icons/src/icons/layers-3.tsx (1)
  • Layers3 (16-54)
apps/dashboard/app/(app)/projects/[projectId]/details/project-details-expandables/detail-section.tsx (1)
apps/dashboard/app/(app)/projects/[projectId]/details/project-details-expandables/sections.tsx (2)
  • DetailItem (23-28)
  • DetailSection (30-33)
internal/icons/src/icons/hard-drive.tsx (1)
internal/icons/src/props.ts (2)
  • IconProps (30-36)
  • sizeMap (7-28)
apps/dashboard/app/(app)/projects/[projectId]/details/env-variables-section/index.tsx (3)
apps/dashboard/app/(app)/projects/[projectId]/details/env-variables-section/hooks/use-env-var.tsx (1)
  • useEnvVars (10-91)
apps/dashboard/app/(app)/projects/[projectId]/details/env-variables-section/env-var-row.tsx (1)
  • EnvVarRow (15-120)
apps/dashboard/app/(app)/projects/[projectId]/details/env-variables-section/add-env-var-row.tsx (1)
  • AddEnvVarRow (11-71)
apps/dashboard/lib/trpc/routers/deploy/project/active-deployment/getDetails.ts (1)
apps/dashboard/lib/trpc/trpc.ts (4)
  • t (8-8)
  • requireUser (10-21)
  • requireWorkspace (23-36)
  • withRatelimit (122-138)
apps/dashboard/app/(app)/projects/[projectId]/layout.tsx (5)
apps/dashboard/lib/trpc/server.ts (1)
  • trpc (7-14)
apps/dashboard/app/(app)/projects/[projectId]/layout-provider.tsx (1)
  • ProjectLayoutContext (14-14)
apps/dashboard/app/(app)/projects/[projectId]/navigations/project-navigation.tsx (1)
  • ProjectNavigation (14-96)
apps/dashboard/app/(app)/projects/[projectId]/navigations/project-sub-navigation.tsx (1)
  • ProjectSubNavigation (16-111)
apps/dashboard/app/(app)/projects/[projectId]/details/project-details-expandables/index.tsx (1)
  • ProjectDetailsExpandable (15-157)
internal/icons/src/icons/bolt.tsx (1)
internal/icons/src/props.ts (2)
  • IconProps (30-36)
  • sizeMap (7-28)
apps/dashboard/app/(app)/projects/[projectId]/details/active-deployment-card/index.tsx (5)
apps/dashboard/app/(app)/projects/[projectId]/layout-provider.tsx (1)
  • useProjectLayout (16-22)
apps/dashboard/app/(app)/projects/[projectId]/details/active-deployment-card/hooks/use-deployment-logs.tsx (1)
  • useDeploymentLogs (52-171)
apps/dashboard/app/(app)/projects/[projectId]/details/active-deployment-card/info-chip.tsx (1)
  • InfoChip (8-13)
apps/dashboard/app/(app)/projects/[projectId]/details/active-deployment-card/filter-button.tsx (1)
  • FilterButton (13-34)
internal/ui/src/components/buttons/copy-button.tsx (1)
  • CopyButton (27-81)
apps/dashboard/app/(app)/projects/[projectId]/page.tsx (6)
apps/dashboard/app/(app)/projects/[projectId]/layout-provider.tsx (1)
  • useProjectLayout (16-22)
internal/icons/src/icons/cloud.tsx (1)
  • Cloud (15-38)
internal/icons/src/icons/earth.tsx (1)
  • Earth (15-40)
internal/icons/src/icons/folder-cloud.tsx (1)
  • FolderCloud (16-47)
apps/dashboard/app/(app)/projects/[projectId]/details/env-variables-section/index.tsx (1)
  • EnvironmentVariablesSection (21-168)
internal/icons/src/icons/page-2.tsx (1)
  • Page2 (15-76)
apps/dashboard/lib/trpc/routers/deploy/project/envs/list.ts (1)
apps/dashboard/lib/trpc/trpc.ts (4)
  • t (8-8)
  • requireUser (10-21)
  • requireWorkspace (23-36)
  • withRatelimit (122-138)
internal/icons/src/icons/message-writing.tsx (1)
internal/icons/src/props.ts (2)
  • IconProps (30-36)
  • sizeMap (7-28)
apps/dashboard/lib/trpc/routers/index.ts (5)
apps/dashboard/lib/trpc/trpc.ts (1)
  • t (8-8)
apps/dashboard/lib/trpc/routers/deploy/project/active-deployment/getDetails.ts (1)
  • getDeploymentDetails (48-99)
apps/dashboard/lib/trpc/routers/deploy/project/active-deployment/getBuildLogs.ts (1)
  • getDeploymentBuildLogs (217-230)
apps/dashboard/lib/trpc/routers/deploy/project/deployment/list.ts (1)
  • queryDeployments (70-253)
apps/dashboard/lib/trpc/routers/deploy/project/deployment/llm-search/index.ts (1)
  • deploymentListLlmSearch (13-20)
apps/dashboard/app/(app)/projects/[projectId]/navigations/project-navigation.tsx (6)
internal/icons/src/icons/refresh-3.tsx (1)
  • Refresh3 (15-46)
apps/dashboard/app/(app)/projects/_components/list/repo-display.tsx (1)
  • RepoDisplay (12-34)
apps/dashboard/components/navigation/action-button.tsx (1)
  • NavbarActionButton (22-53)
internal/icons/src/icons/list-radio.tsx (1)
  • ListRadio (15-72)
internal/icons/src/icons/arrow-dotted-rotate-anticlockwise.tsx (1)
  • ArrowDottedRotateAnticlockwise (15-57)
internal/icons/src/icons/dots.tsx (1)
  • Dots (15-60)
⏰ 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: Test Packages / Test
  • GitHub Check: Build / Build
🔇 Additional comments (23)
apps/dashboard/app/(app)/projects/[projectId]/layout-provider.tsx (1)

16-22: Hook error message is clear; LGTM.

internal/icons/src/icons/connections.tsx (1)

18-51: LGTM — consistent with icon system (sizeMap, per-shape stroke, prop forwarding).

internal/icons/src/icons/share-up-right.tsx (1)

15-56: New icon looks good; follows sizeMap + strokeWidth pattern

Component API, sizing, and strokes are consistent with the icon system.

apps/dashboard/app/(app)/projects/[projectId]/deployments/components/controls/components/deployment-list-search/index.tsx (1)

9-10: Verified: trpc.deploy.project.deployment.search exists and client types are up-to-date
The search procedure is implemented in apps/dashboard/lib/trpc/routers/deploy/project/deployment/llm-search/index.ts and wired into the root router at apps/dashboard/lib/trpc/routers/index.ts, matching the client call in deployment-list-search/index.tsx.

internal/icons/src/icons/location2.tsx (1)

15-59: Solid addition; matches icon system patterns

Sized via sizeMap, uses strokeWidth consistently, and forwards props. Looks good.

apps/dashboard/app/(app)/projects/[projectId]/deployments/components/table/hooks/use-deployments-list-query.ts (2)

93-98: Good migration to project-scoped TRPC endpoint.

The switch to trpc.deploy.project.deployment.list.useInfiniteQuery with sane query options looks correct and aligns with the PR’s project scoping.


1-3: Remove verification note—Deployment type and project.deployment.list route confirmed available.

internal/icons/src/icons/hard-drive.tsx (1)

1-11: Ensure Nucleo-licensed icons aren’t publicly distributed
No “files” field in package.json and no .npmignore present, so internal/icons/ will be bundled on publish. The Nucleo license forbids redistribution—either exclude this folder from your npm package (via a files entry or .npmignore) or replace these icons with an OSS or custom alternative.

apps/dashboard/lib/trpc/routers/index.ts (1)

319-322: LGTM: scoped active deployment routes

Adding activeDeployment.details and activeDeployment.buildLogs under deploy.project scopes routes cleanly and avoids top-level bloat.

internal/icons/src/icons/bolt.tsx (1)

15-35: LGTM: sizeMap integration

Binding height/width and strokeWidth to sizeMap aligns with the new icon system.

apps/dashboard/app/(app)/projects/[projectId]/details/active-deployment-card/filter-button.tsx (2)

13-19: LGTM overall.

Clear API and styling; props are well-typed and usage of composition via icon prop is solid.


1-3: Prefer public barrels over deep imports

Avoid coupling to internal paths—import IconProps and cn directly from the package root (assuming they’re publicly exported; otherwise add them to the exports):

-import type { IconProps } from "@unkey/icons/src/props";
-import { Button } from "@unkey/ui";
-import { cn } from "@unkey/ui/src/lib/utils";
+import type { IconProps } from "@unkey/icons";
+import { Button, cn } from "@unkey/ui";

Verify that IconProps and cn are exposed in the respective package barrels; if not, re-export them at the top level.

apps/dashboard/app/(app)/projects/[projectId]/details/active-deployment-card/hooks/use-deployment-logs.tsx (1)

61-65: Verify API shape of build logs (timestamp units, level values).

Confirm tRPC endpoint returns timestamp in ms (or s), and level strictly in "info" | "warning" | "error". If different, adjust formatter and filters accordingly.

Would you like me to scan the PR for getBuildLogs.ts and validate the Zod schema and return types?

Also applies to: 72-77

apps/dashboard/app/(app)/projects/[projectId]/details/active-deployment-card/skeleton.tsx (1)

7-67: LGTM for UX.

Skeleton is cohesive and mirrors the final layout well.

internal/icons/src/icons/code-commit.tsx (1)

22-58: LGTM: Icon matches library conventions.

Consistent viewBox, stroke handling, and props usage. No issues.

apps/dashboard/app/(app)/projects/[projectId]/page.tsx (1)

3-3: Confirm cn re-export in @unkey/ui
Could not locate an entry-point export for cn—please verify that @unkey/ui’s root (e.g. src/index.ts) re-exports cn (for example, export { cn } from './lib/utils'). If it isn’t exported, add that re-export or maintain a local wrapper.

apps/dashboard/app/(app)/projects/[projectId]/navigations/project-navigation.tsx (1)

15-23: Use project.get instead of listing all projects

Replace the infinite query on trpc.deploy.project.list (lines 15–23 and 25–27) with a trpc.deploy.project.get({ id: projectId }).useQuery() to fetch only the needed project and reduce payload.

apps/dashboard/app/(app)/projects/[projectId]/details/project-details-expandables/index.tsx (1)

21-29: Render a lightweight skeleton when details aren’t cached yet, not null.

null makes the drawer silently disappear on first open. Add a simple loader so UX remains coherent.

⛔ Skipped due to learnings
Learnt from: ogzhanolguncu
PR: unkeyed/unkey#3380
File: apps/dashboard/app/(app)/ratelimits/[namespaceId]/namespace-navbar.tsx:40-66
Timestamp: 2025-06-19T10:39:29.388Z
Learning: tRPC has built-in caching that prevents skeleton flashing during component re-renders and navigation, so concerns about `!data || isLoading` conditions causing loading state flashes are generally not needed.
apps/dashboard/app/(app)/projects/[projectId]/details/active-deployment-card/index.tsx (3)

41-42: Guard against missing activeDeploymentId

Avoid firing queries with undefined id and show skeleton early.

 export function ActiveDeploymentCard() {
   const { activeDeploymentId } = useProjectLayout();
+  if (!activeDeploymentId) return <ActiveDeploymentCardSkeleton />;

191-236: Potential performance issue rendering many log rows

Consider windowing (e.g., react-virtualized/react-window) for large logs to avoid heavy DOM/animation costs.

⛔ Skipped due to learnings
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.

74-74: Verify StatusIndicator props
Confirm whether <StatusIndicator> requires a status prop—if so, supply it here or update the component to handle missing props.

internal/icons/src/index.ts (2)

27-27: Barrel re-exports look good; additive and consistent

No functional risk; names match the icon file slugs.

Also applies to: 49-49, 65-66, 77-81, 91-92, 95-95, 101-101, 107-107, 112-116, 117-131


27-27: No missing or duplicate exports found – all icon modules referenced in internal/icons/src/index.ts exist and no duplicate entries were detected.

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.

Review continued from previous batch...

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.

Review continued from previous batch...

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: 9

♻️ Duplicate comments (7)
apps/dashboard/app/(app)/projects/[projectId]/details/active-deployment-card/hooks/use-deployment-logs.tsx (5)

53-55: Guard the query with enabled; consider sensible fetch options.

Prevents accidental fires on empty deploymentId and reduces UI jitter from refetches.

-  const { data: logsData, isLoading } = trpc.deploy.project.activeDeployment.buildLogs.useQuery({
-    deploymentId,
-  });
+  const { data: logsData, isLoading } =
+    trpc.deploy.project.activeDeployment.buildLogs.useQuery(
+      { deploymentId },
+      {
+        enabled: Boolean(deploymentId),
+        staleTime: 5_000,
+        refetchOnWindowFocus: false,
+      },
+    );

63-68: Normalize timestamps (s vs ms) and sort before mapping to avoid janky ordering.

Handles seconds vs milliseconds and ensures chronological order.

-    return logsData.logs.map((log) => ({
-      timestamp: format(new Date(log.timestamp), "HH:mm:ss.SSS"),
-      level: log.level,
-      message: log.message,
-    }));
+    return [...logsData.logs]
+      .sort((a, b) => Number(a.timestamp) - Number(b.timestamp))
+      .map((log) => ({
+        timestamp: formatTimestamp(log.timestamp),
+        level: log.level,
+        message: log.message,
+      }));

Add this helper near the top of the file:

// Helper: format number/string/Date -> "HH:mm:ss.SSS"; accepts seconds or milliseconds
const formatTimestamp = (timestamp: number | string | Date): string => {
  let ms: number;
  if (timestamp instanceof Date) {
    ms = timestamp.getTime();
  } else if (typeof timestamp === "string") {
    const n = Number(timestamp);
    ms = Number.isFinite(n) ? n : Date.parse(timestamp);
  } else {
    ms = timestamp;
  }
  if (ms < 1_000_000_000_000) ms *= 1000; // treat as seconds
  return format(new Date(ms), "HH:mm:ss.SSS");
};

78-85: Compute log counts in one pass.

Reduces work from multiple filters to a single O(n) reduce.

-  const logCounts = useMemo(
-    () => ({
-      total: logs.length,
-      errors: logs.filter((log) => log.level === "error").length,
-      warnings: logs.filter((log) => log.level === "warning").length,
-    }),
-    [logs],
-  );
+  const logCounts = useMemo(() => {
+    return logs.reduce(
+      (acc, l) => {
+        acc.total += 1;
+        if (l.level === "error") acc.errors += 1;
+        else if (l.level === "warning") acc.warnings += 1;
+        return acc;
+      },
+      { total: 0, errors: 0, warnings: 0 },
+    );
+  }, [logs]);

98-106: Precompute lowercased search term once.

Avoids repeated allocations and clarifies intent.

-    if (searchTerm.trim()) {
-      filtered = filtered.filter(
-        (log) =>
-          log.message.toLowerCase().includes(searchTerm.toLowerCase()) ||
-          log.timestamp.includes(searchTerm) ||
-          log.level?.toLowerCase().includes(searchTerm.toLowerCase()),
-      );
-    }
+    const term = searchTerm.trim().toLowerCase();
+    if (term) {
+      filtered = filtered.filter(
+        (log) =>
+          log.message.toLowerCase().includes(term) ||
+          log.timestamp.includes(term) ||
+          log.level?.toLowerCase().includes(term),
+      );
+    }

118-123: Use requestAnimationFrame instead of magic timeout.

rAF syncs with layout and avoids flakiness.

   const setExpanded = (expanded: boolean) => {
     setIsExpanded(expanded);
     if (!expanded) {
-      setTimeout(resetScroll, 50);
+      requestAnimationFrame(() => resetScroll());
     }
   };
apps/dashboard/app/(app)/projects/[projectId]/details/project-details-expandables/sections.tsx (2)

30-33: Rename the exported type to avoid colliding with the DetailSection component.

This name collides with apps/dashboard/app/(app)/projects/[projectId]/details/project-details-expandables/detail-section.tsx’s exported component name and causes confusing imports.

-export type DetailSection = {
+export type DetailSectionData = {
   title: string;
   items: DetailItem[];
 };

Outside this range, update the return type accordingly:

-export const createDetailSections = (details: DeploymentDetails): DetailSection[] => [
+export const createDetailSections = (details: DeploymentDetails): DetailSectionData[] => [

146-148: Use “MB” (uppercase) for units.

Keep unit casing consistent.

-            <span className="text-gray-12 font-medium">{details.memory}</span>mb
+            <span className="text-gray-12 font-medium">{details.memory}</span> MB
-            <span className="text-gray-12 font-medium">{details.imageSize}</span>
-            mb
+            <span className="text-gray-12 font-medium">{details.imageSize}</span> MB

Also applies to: 214-216

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 294d449 and 20aa3f4.

📒 Files selected for processing (2)
  • apps/dashboard/app/(app)/projects/[projectId]/details/active-deployment-card/hooks/use-deployment-logs.tsx (1 hunks)
  • apps/dashboard/app/(app)/projects/[projectId]/details/project-details-expandables/sections.tsx (1 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/app/(app)/projects/[projectId]/details/project-details-expandables/sections.tsx
  • apps/dashboard/app/(app)/projects/[projectId]/details/active-deployment-card/hooks/use-deployment-logs.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/[projectId]/details/project-details-expandables/sections.tsx
  • apps/dashboard/app/(app)/projects/[projectId]/details/active-deployment-card/hooks/use-deployment-logs.tsx
🧠 Learnings (3)
📓 Common learnings
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.
📚 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/[projectId]/details/active-deployment-card/hooks/use-deployment-logs.tsx
📚 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/app/(app)/projects/[projectId]/details/active-deployment-card/hooks/use-deployment-logs.tsx
🧬 Code graph analysis (2)
apps/dashboard/app/(app)/projects/[projectId]/details/project-details-expandables/sections.tsx (2)
apps/dashboard/app/(app)/projects/[projectId]/details/project-details-expandables/detail-section.tsx (1)
  • DetailSection (33-55)
apps/dashboard/lib/trpc/routers/deploy/project/active-deployment/getDetails.ts (1)
  • DeploymentDetails (46-46)
apps/dashboard/app/(app)/projects/[projectId]/details/active-deployment-card/hooks/use-deployment-logs.tsx (1)
apps/dashboard/lib/trpc/server.ts (1)
  • trpc (7-14)
⏰ 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). (5)
  • GitHub Check: Test Go API Local / Test
  • GitHub Check: Test API / API Test Local
  • GitHub Check: Test Packages / Test
  • GitHub Check: Build / Build
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (3)
apps/dashboard/app/(app)/projects/[projectId]/details/active-deployment-card/hooks/use-deployment-logs.tsx (1)

43-51: Verified useDeploymentLogs is only used in Client Components. All callers (e.g. apps/dashboard/app/(app)/projects/[projectId]/details/active-deployment-card/index.tsx) include the "use client" directive.

apps/dashboard/app/(app)/projects/[projectId]/details/project-details-expandables/sections.tsx (2)

172-176: Regex fix looks good.

Now only leading slashes are removed.


82-86: Configure Next.js Image Domains
No images.domains or remotePatterns entries were found in apps/dashboard/next.config.js. You must add your avatar host (e.g. avatars.example.com) under images.domains or define a matching remotePatterns entry so the <Image> component can load it.

@Flo4604 Flo4604 added this pull request to the merge queue Sep 1, 2025
@graphite-app
Copy link

graphite-app bot commented Sep 1, 2025

Not available (Added via Giphy)

@chronark chronark removed this pull request from the merge queue due to a manual request Sep 1, 2025
@chronark chronark merged commit 6b51ec2 into main Sep 1, 2025
19 checks passed
@chronark chronark deleted the project-details-ui branch September 1, 2025 10:13
@graphite-app
Copy link

graphite-app bot commented Sep 1, 2025

Graphite Automations

"Post a GIF when PR approved" took an action on this PR • (09/01/25)

1 gif was posted to this PR based on Andreas Thomas's automation.

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.

3 participants