Skip to content

fix: ui inconsistencies#5167

Merged
ogzhanolguncu merged 27 commits intomainfrom
improve-deployment-page
Mar 3, 2026
Merged

fix: ui inconsistencies#5167
ogzhanolguncu merged 27 commits intomainfrom
improve-deployment-page

Conversation

@ogzhanolguncu
Copy link
Contributor

@ogzhanolguncu ogzhanolguncu commented Mar 2, 2026

What does this PR do?

This PR implements a comprehensive redesign of the deployment progress experience and enhances GitHub integration for the onboarding flow.

Type of change

  • Enhancement (small improvements)
  • New feature (non-breaking change which adds functionality)

Key Changes

Deployment Progress Redesign

  • Redesigned deployment progress UI with animated step cards and improved visual feedback
  • Added real-time deployment monitoring with automatic redirection when complete
  • Enhanced build steps table with expandable logs, virtualization, and skeleton loading states
  • Improved deployment info display with CPU/memory formatting and resource allocation details

GitHub Integration Enhancements

  • Added language detection and icons for repositories in the onboarding flow
  • Implemented virtualized repository list for better performance with large repo counts
  • Enhanced GitHub app configuration with proper environment variable handling
  • Added support for skipping GitHub connection step when installations already exist

UI/UX Improvements

  • Updated card styling with consistent 14px border radius across components
  • Enhanced deployment domains display with popover for multiple URLs
  • Improved resource formatting (CPU/memory) with separate value and unit display
  • Added glow effects and animations for active deployment states
  • Redesigned project overview to redirect to deployments page

Infrastructure Updates

  • Updated Kubernetes manifests with proper GitHub app credentials configuration
  • Enhanced deployment build steps query to include step logs
  • Improved error handling and loading states throughout the application

How should this be tested?

  • Test the complete onboarding flow from project creation through deployment
  • Verify GitHub repository selection with language icons and search functionality
  • Test deployment progress monitoring and automatic redirection
  • Check build steps expansion and log viewing functionality
  • Verify resource allocation display and formatting
  • Test deployment domains popover with multiple URLs

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
  • Ran make fmt on /go directory
  • 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

@vercel
Copy link

vercel bot commented Mar 2, 2026

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

Project Deployment Actions Updated (UTC)
dashboard Ready Ready Preview, Comment Mar 3, 2026 4:47pm

Request Review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 2, 2026

📝 Walkthrough

Walkthrough

Infrastructure configuration and dashboard UI refactoring for deployment management. Adds GitHub App credential configuration in Kubernetes manifests, restructures deployment progress and information components, introduces skeleton loaders and expanded log views, updates column sizing in tables, adds multiple new language icons and utilities, and extends onboarding flows with virtualization and deployment tracking.

Changes

Cohort / File(s) Summary
Kubernetes Infrastructure
dev/k8s/manifests/ctrl-worker.yaml
Added GitHub App ID and unauthenticated deployment configuration parameters to ConfigMap and Deployment, replacing hardcoded values with environment variable references.
Deployment Progress Refactoring
web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/(overview)/deployments/[deploymentId]/(deployment-progress)/*
Renamed DeploymentProgressSection to DeploymentProgress with significant control flow changes including router navigation, domain integration via DeploymentDomainsCard, and auto-navigation on network completion. Added new DeploymentInfo component displaying CPU, memory, region flags, and status. Added DeploymentStep component for expandable status displays. Introduced DeploymentLiveStep for onboarding with countdown-based auto-redirect (15s).
Build Steps Table & Logs
web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/(overview)/deployments/[deploymentId]/(deployment-progress)/build-steps-table/*
Added BuildStepLogsExpanded component for displaying detailed step logs. Created four skeleton components (StartedAtColumnSkeleton, StatusColumnSkeleton, NameColumnSkeleton, DurationColumnSkeleton). Adjusted column widths (expand 32→25px, started_at 180→85px, duration 10%→115px) and styling. Updated deployment-build-steps-table to integrate skeleton rendering and reorganized imports.
Removed Deployment Sections
web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/(overview)/deployments/[deploymentId]/(overview)/components/sections/*
Removed DeploymentInfoSection and DeploymentDomainsSection components (previously rendered in overview, now consolidated into deployment-progress layout).
Removed Overview Components
web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/(overview)/deployments/[deploymentId]/(overview)/components/table/*
Removed BuildStepLogsExpanded and useDeploymentBuildStepsQuery hook from overview table components (relocated to deployment-progress directory).
Deployment Layout & Provider Updates
web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/(overview)/deployments/[deploymentId]/*
Updated layout-provider to accept optional deploymentId prop. Modified deployment-network-view zoom from 1 to 0.75 and removed locked prop. Updated page.tsx to replace old sections with new DeploymentInfo and DeploymentProgress components with conditional rendering based on deployment readiness.
Metric Formatting Refactoring
web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/(overview)/deployments/[deploymentId]/network/unkey-flow/components/nodes/components/*, web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/(overview)/details/project-details-expandables/sections.tsx, web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/(overview)/settings/components/runtime-settings/*, web/apps/dashboard/lib/utils/deployment-formatters.ts
Changed CPU/memory formatting from string-returning functions (formatCpu, formatMemory) to parts-returning functions (formatCpuParts, formatMemoryParts) that provide separate value and unit fields. Updated MetricPillProps.value type from string | number to React.ReactNode. Modified multiple components to use new formatters and render separated value/unit styling.
Column Sizing & Border Styling
web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/(overview)/deployments/components/table/deployments-list.tsx, web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/(overview)/deployments/[deploymentId]/(overview)/components/metrics/metric-card.tsx, web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/components/active-deployment-card/*, web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/components/deployment-domains-card.tsx
Adjusted multiple border-radius values from rounded-xl to rounded-[14px]. Updated deployment list column widths (Deployment ID 15%→12%, Status 15%→10%, Domains 25%→20%, Instances 10%→8%, Size 15%→14%, Source 15%→12%, Created 10%→8%, Author 10%→8%, Action 5%→4%). Replaced Cube icon with Connections3, added Bolt and ScanCode icons for resources. Updated deployment card border color from border-grayA-5 to border-grayA-4.
Deployment Domains Card
web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/components/deployment-domains-card.tsx
New component rendering deployment domains with primary domain display, additional domains in popover, copy-to-clipboard support, and optional glow state. Fetches domains via useProjectData and supports filtering.
Onboarding Flow Updates
web/apps/dashboard/app/(app)/[workspaceSlug]/projects/onboarding/*
Modified onboarding wizard to conditionally show GitHub connection step only when no installation exists (via trpc hasInstallations check). Added deployment tracking state (deploymentId) and DeploymentLiveStep. Updated ConfigureDeploymentStep to accept onDeploymentCreated callback and use step wizard navigation instead of router. Introduced LanguageIcon component for repository language display. Added repository virtualization via useVirtualizer with max-height constraints.
Select Repo Enhancements
web/apps/dashboard/app/(app)/[workspaceSlug]/projects/onboarding/steps/select-repo/*
Added virtualization for repository lists using useVirtualizer. Created LanguageIcon component mapping language strings to icon components. Updated RepoListItem to accept language property and render LanguageIcon. Updated skeleton styling with ring and shadow.
Icon Library Expansion
web/internal/icons/src/icons/hammer-2.tsx, web/internal/icons/src/icons/lang-*.tsx, web/internal/icons/src/icons/layer-front.tsx, web/internal/icons/src/index.ts
Added 11 new icon components: Hammer2, LangElixir, LangGo, LangJava, LangJavascript, LangPhp, LangPython, LangRuby, LangRust, LangTypescript, LayerFront. All follow standard IconProps pattern with sizeMap-based sizing.
Virtual Table & Config Updates
web/apps/dashboard/components/virtual-table/*
Added optional className to TableConfig for container styling. Updated virtual table rendering to conditionally render headers only when hasHeaders is true, consolidate spacer rows, and use optional chaining for renderExpanded. Added config.className merging with padding classes.
Settings & UI Components
web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/(overview)/settings/components/shared/settings-group.tsx, web/internal/ui/src/components/settings-card.tsx, web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/components/section.tsx
Updated SettingsGroup to accept hideChevron prop and changed title type to React.ReactNode. Updated SettingCard with iconClassName prop, adjusted border-radius to 14px, reduced padding (px-6→px-4), added dark ring and shadow styling. Changed Section header padding from py-1.5 px-2 to mb-4 px-2, removed gap-1 from container.
GitHub & TRPC Integration
web/apps/dashboard/lib/github.ts, web/apps/dashboard/lib/trpc/routers/github.ts
Added nullable language field to GitHubRepository type. Added hasInstallations query endpoint returning boolean for GitHub App installation status. Extended listRepositories to include language field from repository data.
Styling & Minor Updates
web/apps/dashboard/app/(app)/[workspaceSlug]/layout.tsx, web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/page.tsx, web/apps/dashboard/app/(app)/[workspaceSlug]/projects/_components/list/projects-card*.tsx, web/apps/dashboard/components/loading-state.tsx, web/apps/dashboard/components/stats-card/index.tsx, web/apps/dashboard/tailwind.config.js, web/apps/dashboard/app/(app)/integrations/github/callback/page.tsx
Text color updates (text-gray-600→text-gray-11), border color updates (border-gray-6→border-gray-4), gradient and shadow adjustments in card skeletons. Replaced PageLoading with LoadingState component. Updated project page to async redirect to deployments. Added comprehensive Tailwind configuration with theme customization, color palette, animations, and merge utility function. Adjusted spacing in project content wrapper (mt-4→mt-6) and removed breadcrumb Overview entry.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant DeploymentProgress
    participant DeploymentLiveStep
    participant DeploymentService
    participant Router

    User->>DeploymentProgress: View deployment progress
    DeploymentProgress->>DeploymentService: Query build steps & network status
    DeploymentService-->>DeploymentProgress: Return progress data
    DeploymentProgress->>DeploymentProgress: Monitor network completion
    
    alt Network Not Ready
        DeploymentProgress->>User: Display DeploymentProgress component
        User->>User: View step indicators
    else Network Ready
        DeploymentProgress->>DeploymentLiveStep: Navigate with deploymentId
        DeploymentLiveStep->>DeploymentService: Check deployment ready state
        DeploymentService-->>DeploymentLiveStep: Return ready status
        DeploymentLiveStep->>DeploymentLiveStep: Start 15s countdown timer
        User->>User: View countdown
        DeploymentLiveStep->>Router: Auto-navigate to deployment overview (on countdown=0)
        Router-->>User: Display deployment page
    end
Loading
sequenceDiagram
    participant User
    participant OnboardingWizard
    participant GitHubCheck
    participant ConfigureDeployment
    participant DeploymentMonitor
    participant Router

    User->>OnboardingWizard: Start onboarding
    OnboardingWizard->>OnboardingWizard: Render Create Project step
    User->>OnboardingWizard: Proceed
    OnboardingWizard->>OnboardingWizard: Render Select Repository step
    User->>OnboardingWizard: Choose repository
    OnboardingWizard->>GitHubCheck: Check hasInstallations
    GitHubCheck-->>OnboardingWizard: Installation status
    
    alt No GitHub Installation
        OnboardingWizard->>User: Show Connect GitHub step
        User->>User: Authorize app
    end
    
    OnboardingWizard->>ConfigureDeployment: Render Configure Deployment step
    User->>ConfigureDeployment: Create deployment
    ConfigureDeployment->>DeploymentMonitor: Trigger onDeploymentCreated callback
    DeploymentMonitor->>OnboardingWizard: Advance wizard to Deploying
    OnboardingWizard->>DeploymentMonitor: Render DeploymentLiveStep with deploymentId
    DeploymentMonitor->>Router: Auto-redirect on ready
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • PR #4804: Overlapping changes to deployment overview components (DeploymentProgress, DeploymentInfo, ActiveDeploymentCard, domain components) and layout-provider updates in similar deployment-related directories.
  • PR #4881: Shared changes to deployment network UI components (deployment-network-view, node components, metric formatting utilities) affecting visualization and metrics display.
🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'fix: ui inconsistencies' is vague and generic, using a non-specific term 'ui inconsistencies' that doesn't clearly convey the main changes in this substantial PR. Consider a more specific title that reflects the primary change, such as 'feat: redesign deployment progress experience and GitHub integration' or similar, to better summarize the core work.
✅ Passed checks (1 passed)
Check name Status Explanation
Description check ✅ Passed The PR description is comprehensive and well-structured, following the template with clear sections covering objectives, key changes, testing instructions, and a completed checklist.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch improve-deployment-page

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

@ogzhanolguncu ogzhanolguncu mentioned this pull request Mar 2, 2026
19 tasks
@ogzhanolguncu ogzhanolguncu marked this pull request as ready for review March 2, 2026 17:18
@ogzhanolguncu ogzhanolguncu force-pushed the improve-deployment-page branch from af7d63e to 6093231 Compare March 2, 2026 17:49
@ogzhanolguncu ogzhanolguncu force-pushed the improve-deployment-page branch from 83f6cea to 80aa9da Compare March 2, 2026 17:55
@ogzhanolguncu ogzhanolguncu force-pushed the improve-deployment-page branch from 80aa9da to f594f77 Compare March 2, 2026 18:03
@ogzhanolguncu ogzhanolguncu force-pushed the improve-deployment-page branch from f594f77 to f2a0604 Compare March 2, 2026 18:09
Copy link
Collaborator

@chronark chronark left a comment

Choose a reason for hiding this comment

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

see slack

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

🧹 Nitpick comments (4)
web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/(overview)/settings/components/shared/settings-group.tsx (1)

30-48: Empty button rendered when hideChevron is true.

When hideChevron is true, the button is still rendered but contains no content. This creates an invisible clickable element that:

  1. Still toggles the expanded state on click
  2. Has hover styles applied to empty space
  3. Presents an accessibility concern (screen readers announce an empty button)

If the intent is to fully disable collapse/expand functionality, consider hiding the button entirely. Alternatively, if only the visual toggle indicator should be hidden while keeping the section permanently expanded, you may want to skip rendering the button and lock expanded to true.

♻️ Suggested fix: conditionally render the button
-        <button
-          type="button"
-          onClick={() => setExpanded((prev) => !prev)}
-          className="flex items-center gap-1 text-xs text-gray-10 hover:text-gray-11 transition-colors group duration-300"
-        >
-          {!hideChevron && (
-            <>
-              {expanded ? "Hide" : "Show"}
-              <ChevronRight
-                className="text-gray-10 group-hover:text-gray-11 transition-all duration-300 flex-shrink-0"
-                iconSize="sm-medium"
-                style={{
-                  transitionTimingFunction: "cubic-bezier(.62,.16,.13,1.01)",
-                  transform: expanded ? "rotate(270deg)" : "rotate(90deg)",
-                }}
-              />
-            </>
-          )}
-        </button>
+        {!hideChevron && (
+          <button
+            type="button"
+            onClick={() => setExpanded((prev) => !prev)}
+            className="flex items-center gap-1 text-xs text-gray-10 hover:text-gray-11 transition-colors group duration-300"
+          >
+            {expanded ? "Hide" : "Show"}
+            <ChevronRight
+              className="text-gray-10 group-hover:text-gray-11 transition-all duration-300 flex-shrink-0"
+              iconSize="sm-medium"
+              style={{
+                transitionTimingFunction: "cubic-bezier(.62,.16,.13,1.01)",
+                transform: expanded ? "rotate(270deg)" : "rotate(90deg)",
+              }}
+            />
+          </button>
+        )}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@web/apps/dashboard/app/`(app)/[workspaceSlug]/projects/[projectId]/(overview)/settings/components/shared/settings-group.tsx
around lines 30 - 48, The button currently renders even when hideChevron is true
which creates an empty, interactive element; change the JSX to conditionally
render the entire button only when !hideChevron (so remove the <button>
including onClick and children when hideChevron is true) and, if the intended
behavior is to lock the section open when hideChevron is true, ensure the
expanded state (expanded/setExpanded) is set to true by default or forced when
hideChevron is true; also ensure accessibility by keeping or adding
aria-expanded on the rendered button to reflect the expanded state (references:
hideChevron, expanded, setExpanded, ChevronRight).
web/apps/dashboard/tailwind.config.js (2)

4-4: Unused import.

This import has no effect—tailwindcss/plugin is imported for side effects only but nothing is bound. If you intended to use the plugin API, bind it (e.g., import plugin from "tailwindcss/plugin"); otherwise, remove this line.

Suggested fix
-import "tailwindcss/plugin";
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@web/apps/dashboard/tailwind.config.js` at line 4, Remove the no-op
side-effect import of "tailwindcss/plugin" or convert it to a bound import if
you plan to use the plugin API; specifically either delete the line import
"tailwindcss/plugin" from the tailwind.config.js, or change it to a bound import
(e.g., import plugin from "tailwindcss/plugin") and then reference the plugin
identifier when registering plugins in the configuration.

157-172: merge mutates its first argument and mishandles null.

Two concerns:

  1. In-place mutation: merge(defaultTheme.theme, {...}) mutates the imported defaultTheme.theme object. If the module is cached and reused elsewhere, this could cause subtle cross-contamination. Consider cloning obj1 before merging or using a non-mutating approach.

  2. null handling: typeof null === "object" in JavaScript, so null values in obj2 enter the object-merge branch and are silently ignored instead of overwriting.

For a Tailwind config that runs once at build time, the practical risk is low—this is a recommended cleanup rather than a blocker.

Non-mutating alternative
-export function merge(obj1, obj2) {
-  for (const key in obj2) {
-    // biome-ignore lint/suspicious/noPrototypeBuiltins: don't tell me what to do
-    if (obj2.hasOwnProperty(key)) {
-      if (typeof obj2[key] === "object" && !Array.isArray(obj2[key])) {
-        if (!obj1[key]) {
-          obj1[key] = {};
-        }
-        obj1[key] = merge(obj1[key], obj2[key]);
-      } else {
-        obj1[key] = obj2[key];
-      }
-    }
-  }
-  return obj1;
-}
+export function merge(obj1, obj2) {
+  const result = { ...obj1 };
+  for (const key in obj2) {
+    if (Object.hasOwn(obj2, key)) {
+      const val = obj2[key];
+      if (val !== null && typeof val === "object" && !Array.isArray(val)) {
+        result[key] = merge(result[key] ?? {}, val);
+      } else {
+        result[key] = val;
+      }
+    }
+  }
+  return result;
+}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@web/apps/dashboard/tailwind.config.js` around lines 157 - 172, The merge
function mutates its first argument and treats null as an object; update
merge(obj1, obj2) to be non-mutating (create a cloned result from obj1, e.g., a
shallow or deep clone before merging) and change the recursive branch to only
recurse when obj2[key] is a non-null object (e.g., obj2[key] !== null && typeof
obj2[key] === "object" && !Array.isArray(obj2[key])); ensure arrays and null
values in obj2 overwrite the result rather than being recursed into, and return
the new merged object instead of modifying obj1.
web/internal/icons/src/icons/lang-php.tsx (1)

46-49: Consider using camelCase for SVG attributes.

The stop-color attribute should be stopColor in React/JSX for consistency with React's DOM property naming conventions. While browsers handle kebab-case SVG attributes, React prefers camelCase.

Suggested fix
-          <stop stop-color="#AEB2D5" />
-          <stop offset=".3" stop-color="#AEB2D5" />
-          <stop offset=".75" stop-color="#484C89" />
-          <stop offset="1" stop-color="#484C89" />
+          <stop stopColor="#AEB2D5" />
+          <stop offset=".3" stopColor="#AEB2D5" />
+          <stop offset=".75" stopColor="#484C89" />
+          <stop offset="1" stopColor="#484C89" />
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@web/internal/icons/src/icons/lang-php.tsx` around lines 46 - 49, In the
lang-php.tsx SVG, replace kebab-case SVG props on the <stop> elements (e.g.,
"stop-color") with React/JSX camelCase props ("stopColor") so the <stop ... />
elements use stopColor attributes; update every occurrence in the SVG fragment
inside the LangPhp component or exported JSX to ensure consistency with React
DOM property naming conventions.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@dev/k8s/manifests/ctrl-worker.yaml`:
- Around line 51-56: Change the GitHub secrets in the Kubernetes manifest to be
required by setting optional: false for the env entries that provide
UNKEY_GITHUB_APP_ID / UNKEY_GITHUB_PRIVATE_KEY_PEM /
UNKEY_ALLOW_UNAUTHENTICATED_DEPLOYMENTS so os.ExpandEnv does not leave "${VAR}"
literals in the TOML, and then prevent a nil deref by either adding a nil guard
before accessing cfg.GitHub.AllowUnauthenticatedDeployments (e.g., if cfg.GitHub
!= nil && cfg.GitHub.AllowUnauthenticatedDeployments ...) or by enforcing
presence of cfg.GitHub in Config.Validate() (reject config when GitHub section
is missing); update the manifest and validation logic accordingly so startup
cannot hit a nil pointer or TOML parse errors.

In `@web/apps/dashboard/app/`(app)/[workspaceSlug]/layout.tsx:
- Line 15: Replace the visible typo in the loading paragraph text inside the
layout component: locate the JSX paragraph element with className "text-sm
text-gray-600 dark:text-gray-400" that currently reads "Lasdasdoading
workspace..." and change the copy to the intended user-facing string (e.g.,
"Loading workspace...") so the UI shows the correct message.

In
`@web/apps/dashboard/app/`(app)/[workspaceSlug]/projects/[projectId]/(overview)/deployments/[deploymentId]/(deployment-progress)/build-steps-table/build-step-logs-expanded.tsx:
- Around line 18-25: The spacer rows only render a single <td> in a table that
has six columns, causing layout issues; update both spacer rows (the standalone
one before the map and the per-log spacer inside the step.logs.map in
build-step-logs-expanded.tsx) to render a single <td> with colSpan set to the
full column count (e.g., colSpan={6}) and preserve the existing classes/style so
the spacer visually matches other rows.

In
`@web/apps/dashboard/app/`(app)/[workspaceSlug]/projects/[projectId]/(overview)/deployments/[deploymentId]/(deployment-progress)/build-steps-table/deployment-build-steps-table.tsx:
- Around line 39-43: The first-skeleton cell's left padding is being cancelled
because column.cellClassName (e.g., the expand column's "p-0") is appended after
the conditional "pl-[18px]"; change the class composition so the desired padding
wins — either move the idx === 0 ? "pl-[18px]" conditional to be appended after
column.cellClassName, or apply an explicit override like "!pl-[18px]" when idx
=== 0; update the className construction in the component that uses cn(...)
(referencing cn, className, idx, and column.cellClassName) so the first cell
keeps its left padding.

In
`@web/apps/dashboard/app/`(app)/[workspaceSlug]/projects/[projectId]/(overview)/deployments/[deploymentId]/(deployment-progress)/deployment-info.tsx:
- Around line 51-55: The icon-only Button used for toggling details (onClick
calls projectLayout.setIsDetailsOpen and reads projectLayout.isDetailsOpen)
lacks an accessible name and has a tiny hit target; add an explicit accessible
label (e.g., aria-label or aria-pressed that reflects the current state like
"Open details" / "Close details") and increase the clickable area by changing
the sizing classes (remove or replace the small "size-3" class and/or add
padding such as "p-2" or a larger size class so the hit target meets touch
guidelines) while keeping the existing onClick logic intact.

In
`@web/apps/dashboard/app/`(app)/[workspaceSlug]/projects/[projectId]/(overview)/deployments/[deploymentId]/(deployment-progress)/deployment-progress.tsx:
- Around line 30-37: The buildSteps query is currently polling full step logs
every second (trpc.deploy.deployment.buildSteps.useQuery with includeStepLogs:
true and refetchInterval: 1000); change polling to request metadata-only (set
includeStepLogs: false) and either increase refetchInterval to a sane value
(e.g., 10s) or remove polling, and implement a separate on-demand query (e.g.,
buildStepLogs or same buildSteps with includeStepLogs: true) that is triggered
when a step is expanded to fetch logs. Update any UI expansion handler to call
the new on-demand query and keep the polling query limited to metadata by
referencing the same deploymentId parameter.
- Around line 17-19: Do not force-cast route params; instead remove the `as
string` casts on `workspaceSlug` and `projectId`, validate that `params`
contains those keys, and handle the missing case explicitly (e.g., call Next.js
notFound()/redirect() or render an error/loader) before using the values. Update
the code around `params`, `workspaceSlug`, and `projectId` to derive typed
values only after checking they are present (throw/return early or invoke
notFound/redirect) so subsequent URL construction uses guaranteed strings rather
than unsafe casts.

In
`@web/apps/dashboard/app/`(app)/[workspaceSlug]/projects/[projectId]/(overview)/deployments/[deploymentId]/(deployment-progress)/deployment-step.tsx:
- Line 73: The JSX currently treats duration as falsy so a zero value is hidden;
update the conditional in the span that renders the duration (the JSX containing
duration and the ms() call) to use a null/undefined check (e.g., check duration
!= null or duration !== null && duration !== undefined) instead of a truthy
check so that duration = 0 renders as ms(0).

In `@web/apps/dashboard/app/`(app)/[workspaceSlug]/projects/onboarding/index.tsx:
- Line 30: The install-query condition currently treats a falsy/undefined
installationData as resolved which causes the "connect-github" step to mount and
then disappear; update the trpc.github.hasInstallations.useQuery call to
destructure the loading state (e.g., const { data: installationData, isLoading }
= trpc.github.hasInstallations.useQuery()) and only render or include the
"connect-github" step when the query is finished and data indicates the
appropriate state (e.g., !isLoading && installationData !== undefined && /* your
existing check */). Apply the same pattern to other checks in the file that rely
on installationData (the block around lines 51-70) so steps are not
mounted/removed while the query is loading.
- Around line 103-107: The deploying StepWizard.Step currently renders null when
projectId or deploymentId are missing; change the render branch inside the
StepWizard.Step with id="deploying" so it shows a non-empty fallback UI instead
of null (for example a centered message, placeholder card, and/or a Spinner with
a retry button) whenever projectId or deploymentId are falsy; keep the existing
happy-path that renders DeploymentLiveStep(projectId, deploymentId) and ensure
the fallback references the same props/state names (projectId, deploymentId) so
users aren’t left with a blank screen if deployment state is lost.

In `@web/apps/dashboard/components/virtual-table/index.tsx`:
- Around line 399-400: The expanded content returned by renderExpanded
(renderExpanded?.(typedItem)) can produce non-<tr> nodes directly under <tbody>;
change the rendering so that whenever isExpanded and renderExpanded produces
content you wrap it in a table row and cell: renderExpanded?.(typedItem) should
be placed inside <tr><td colSpan={columns.length}>...</td></tr> (use the
existing columns array length for colSpan), ensuring this replacement is applied
wherever renderExpanded?.(typedItem) is rendered (the blocks that reference
isExpanded and renderExpanded), or alternatively narrow the renderExpanded type
to only accept a function that returns a table row element.

In `@web/internal/icons/src/icons/lang-elixir.tsx`:
- Around line 23-24: The SVG attributes in the JSX of lang-elixir.tsx are using
hyphenated names (e.g., stop-color, stop-opacity, fill-rule, clip-rule,
fill-opacity) which trigger React warnings; update every hyphenated SVG
attribute in the component's JSX to their camelCase equivalents (stopColor,
stopOpacity, fillRule, clipRule, fillOpacity) — e.g., in all <stop .../> and
<path .../> elements inside the exported component (the SVG/React component in
this file), replace each hyphenated prop with the camelCase name and verify the
JSX/TSX compiles cleanly.

In `@web/internal/icons/src/icons/lang-go.tsx`:
- Around line 14-19: Change the SVG attribute names to React JSX camelCase:
replace the fill-rule attributes on the <g> element and the <path> with fillRule
(e.g., update the fill-rule="evenodd" on the <g> and fill-rule="nonzero" on the
<path>), ensuring you edit the SVG markup inside the lang-go component (the <g>
and corresponding <path> elements) in icons/lang-go.tsx so they use fillRule
instead of fill-rule.

In `@web/internal/icons/src/icons/lang-python.tsx`:
- Around line 23-24: In lang-python.tsx update the SVG <stop> attributes to use
React camelCase names: replace any occurrences of stop-color and stop-opacity on
the <stop> elements with stopColor and stopOpacity respectively (look for the
<stop ... /> elements in the component) so the JSX uses valid React attribute
names.

---

Nitpick comments:
In
`@web/apps/dashboard/app/`(app)/[workspaceSlug]/projects/[projectId]/(overview)/settings/components/shared/settings-group.tsx:
- Around line 30-48: The button currently renders even when hideChevron is true
which creates an empty, interactive element; change the JSX to conditionally
render the entire button only when !hideChevron (so remove the <button>
including onClick and children when hideChevron is true) and, if the intended
behavior is to lock the section open when hideChevron is true, ensure the
expanded state (expanded/setExpanded) is set to true by default or forced when
hideChevron is true; also ensure accessibility by keeping or adding
aria-expanded on the rendered button to reflect the expanded state (references:
hideChevron, expanded, setExpanded, ChevronRight).

In `@web/apps/dashboard/tailwind.config.js`:
- Line 4: Remove the no-op side-effect import of "tailwindcss/plugin" or convert
it to a bound import if you plan to use the plugin API; specifically either
delete the line import "tailwindcss/plugin" from the tailwind.config.js, or
change it to a bound import (e.g., import plugin from "tailwindcss/plugin") and
then reference the plugin identifier when registering plugins in the
configuration.
- Around line 157-172: The merge function mutates its first argument and treats
null as an object; update merge(obj1, obj2) to be non-mutating (create a cloned
result from obj1, e.g., a shallow or deep clone before merging) and change the
recursive branch to only recurse when obj2[key] is a non-null object (e.g.,
obj2[key] !== null && typeof obj2[key] === "object" &&
!Array.isArray(obj2[key])); ensure arrays and null values in obj2 overwrite the
result rather than being recursed into, and return the new merged object instead
of modifying obj1.

In `@web/internal/icons/src/icons/lang-php.tsx`:
- Around line 46-49: In the lang-php.tsx SVG, replace kebab-case SVG props on
the <stop> elements (e.g., "stop-color") with React/JSX camelCase props
("stopColor") so the <stop ... /> elements use stopColor attributes; update
every occurrence in the SVG fragment inside the LangPhp component or exported
JSX to ensure consistency with React DOM property naming conventions.

ℹ️ Review info

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cc6078a and 0f9faa1.

📒 Files selected for processing (72)
  • dev/k8s/manifests/ctrl-worker.yaml
  • web/apps/dashboard/app/(app)/[workspaceSlug]/layout.tsx
  • web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/(overview)/components/card.tsx
  • web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/(overview)/deployments/[deploymentId]/(deployment-progress)/build-steps-table/build-step-logs-expanded.tsx
  • web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/(overview)/deployments/[deploymentId]/(deployment-progress)/build-steps-table/columns.tsx
  • web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/(overview)/deployments/[deploymentId]/(deployment-progress)/build-steps-table/deployment-build-steps-table.tsx
  • web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/(overview)/deployments/[deploymentId]/(deployment-progress)/build-steps-table/get-row-class.ts
  • web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/(overview)/deployments/[deploymentId]/(deployment-progress)/build-steps-table/skeletons.tsx
  • web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/(overview)/deployments/[deploymentId]/(deployment-progress)/deployment-info.tsx
  • web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/(overview)/deployments/[deploymentId]/(deployment-progress)/deployment-progress.tsx
  • web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/(overview)/deployments/[deploymentId]/(deployment-progress)/deployment-step.tsx
  • web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/(overview)/deployments/[deploymentId]/(overview)/components/metrics/metric-card.tsx
  • web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/(overview)/deployments/[deploymentId]/(overview)/components/sections/deployment-domains-section.tsx
  • web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/(overview)/deployments/[deploymentId]/(overview)/components/sections/deployment-info-section.tsx
  • web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/(overview)/deployments/[deploymentId]/(overview)/components/sections/deployment-network-section.tsx
  • web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/(overview)/deployments/[deploymentId]/(overview)/components/table/build-step-logs-expanded.tsx
  • web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/(overview)/deployments/[deploymentId]/(overview)/components/table/hooks/use-deployment-build-steps-query.ts
  • web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/(overview)/deployments/[deploymentId]/layout-provider.tsx
  • web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/(overview)/deployments/[deploymentId]/network/deployment-network-view.tsx
  • web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/(overview)/deployments/[deploymentId]/network/unkey-flow/components/nodes/components/card-footer.tsx
  • web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/(overview)/deployments/[deploymentId]/network/unkey-flow/components/nodes/components/metric-pill.tsx
  • web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/(overview)/deployments/[deploymentId]/network/unkey-flow/components/overlay/node-details-panel/region-node/sentinel-instances.tsx
  • web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/(overview)/deployments/[deploymentId]/page.tsx
  • web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/(overview)/deployments/components/table/components/actions/components/deployment-card.tsx
  • web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/(overview)/deployments/components/table/deployments-list.tsx
  • web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/(overview)/details/project-details-expandables/sections.tsx
  • web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/(overview)/layout-provider.tsx
  • web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/(overview)/navigations/use-breadcrumb-config.ts
  • web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/(overview)/openapi-diff/page.tsx
  • web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/(overview)/settings/components/runtime-settings/cpu.tsx
  • web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/(overview)/settings/components/runtime-settings/memory.tsx
  • web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/(overview)/settings/components/runtime-settings/storage.tsx
  • web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/(overview)/settings/components/shared/settings-group.tsx
  • web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/components/active-deployment-card/components/skeleton.tsx
  • web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/components/active-deployment-card/index.tsx
  • web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/components/deployment-domains-card.tsx
  • web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/components/project-content-wrapper.tsx
  • web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/components/section.tsx
  • web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/page.tsx
  • web/apps/dashboard/app/(app)/[workspaceSlug]/projects/_components/list/projects-card-skeleton.tsx
  • web/apps/dashboard/app/(app)/[workspaceSlug]/projects/_components/list/projects-card.tsx
  • web/apps/dashboard/app/(app)/[workspaceSlug]/projects/onboarding/index.tsx
  • web/apps/dashboard/app/(app)/[workspaceSlug]/projects/onboarding/onboarding-step-header.tsx
  • web/apps/dashboard/app/(app)/[workspaceSlug]/projects/onboarding/steps/configure-deployment.tsx
  • web/apps/dashboard/app/(app)/[workspaceSlug]/projects/onboarding/steps/deployment-live.tsx
  • web/apps/dashboard/app/(app)/[workspaceSlug]/projects/onboarding/steps/select-repo/index.tsx
  • web/apps/dashboard/app/(app)/[workspaceSlug]/projects/onboarding/steps/select-repo/language-icon.tsx
  • web/apps/dashboard/app/(app)/[workspaceSlug]/projects/onboarding/steps/select-repo/repo-list-item.tsx
  • web/apps/dashboard/app/(app)/[workspaceSlug]/projects/onboarding/steps/select-repo/skeleton.tsx
  • web/apps/dashboard/app/(app)/integrations/github/callback/page.tsx
  • web/apps/dashboard/components/loading-state.tsx
  • web/apps/dashboard/components/stats-card/index.tsx
  • web/apps/dashboard/components/virtual-table/constants.ts
  • web/apps/dashboard/components/virtual-table/index.tsx
  • web/apps/dashboard/components/virtual-table/types.ts
  • web/apps/dashboard/lib/github.ts
  • web/apps/dashboard/lib/trpc/routers/github.ts
  • web/apps/dashboard/lib/utils/deployment-formatters.ts
  • web/apps/dashboard/tailwind.config.js
  • web/internal/icons/src/icons/hammer-2.tsx
  • web/internal/icons/src/icons/lang-elixir.tsx
  • web/internal/icons/src/icons/lang-go.tsx
  • web/internal/icons/src/icons/lang-java.tsx
  • web/internal/icons/src/icons/lang-javascript.tsx
  • web/internal/icons/src/icons/lang-php.tsx
  • web/internal/icons/src/icons/lang-python.tsx
  • web/internal/icons/src/icons/lang-ruby.tsx
  • web/internal/icons/src/icons/lang-rust.tsx
  • web/internal/icons/src/icons/lang-typescript.tsx
  • web/internal/icons/src/icons/layer-front.tsx
  • web/internal/icons/src/index.ts
  • web/internal/ui/src/components/settings-card.tsx
💤 Files with no reviewable changes (5)
  • web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/(overview)/deployments/[deploymentId]/(overview)/components/sections/deployment-domains-section.tsx
  • web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/(overview)/deployments/[deploymentId]/(overview)/components/sections/deployment-info-section.tsx
  • web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/(overview)/deployments/[deploymentId]/(overview)/components/table/hooks/use-deployment-build-steps-query.ts
  • web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/(overview)/deployments/[deploymentId]/(overview)/components/table/build-step-logs-expanded.tsx
  • web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/(overview)/navigations/use-breadcrumb-config.ts

Copy link
Member

@perkinsjr perkinsjr left a comment

Choose a reason for hiding this comment

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

I saw a spelling mistake on the loader.

Functionally it works

@ogzhanolguncu ogzhanolguncu added this pull request to the merge queue Mar 3, 2026
Merged via the queue into main with commit 603ae99 Mar 3, 2026
19 checks passed
@ogzhanolguncu ogzhanolguncu deleted the improve-deployment-page branch March 3, 2026 17:06
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