-
Notifications
You must be signed in to change notification settings - Fork 557
self-serve infra deployment: part 1 #7456
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
|
WalkthroughThis update introduces a new "Scale" tab and a suite of React components for a blockchain infrastructure deployment and checkout flow within the dashboard's team area. It adds service selection, payment frequency options, and order summary features. Several biome.json files across the monorepo are also updated to reference schema version 2.0.4. Changes
Sequence Diagram(s)Infrastructure Deployment and Checkout FlowsequenceDiagram
participant User
participant Layout
participant InfrastructureCheckout
participant ServiceSelector
participant PaymentFrequencySelector
participant OrderSummary
User->>Layout: Access /team/[team_slug]/~/scale/deploy
Layout->>InfrastructureCheckout: Render with client prop
InfrastructureCheckout->>ServiceSelector: Render with available services
InfrastructureCheckout->>PaymentFrequencySelector: Render with options
InfrastructureCheckout->>OrderSummary: Render with selected chain, services, payment frequency
User->>ServiceSelector: Select/deselect services
ServiceSelector-->>InfrastructureCheckout: Update selectedServices
User->>PaymentFrequencySelector: Change payment frequency
PaymentFrequencySelector-->>InfrastructureCheckout: Update paymentFrequency
InfrastructureCheckout->>OrderSummary: Update summary on changes
User->>OrderSummary: Click Checkout (if enabled)
Team Layout with "Scale" TabsequenceDiagram
participant User
participant TeamLayout
participant Badge
User->>TeamLayout: Access team dashboard
TeamLayout->>Badge: Render "New" badge for "Scale" tab
TeamLayout->>User: Display navigation with "Scale" tab and badge
✨ Finishing Touches
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
How to use the Graphite Merge QueueAdd either label to this PR to merge it via the merge queue:
You must have a Graphite account in order to use the merge queue. Sign up using this link. An organization admin has enabled the Graphite Merge Queue in this repository. Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue. This stack of pull requests is managed by Graphite. Learn more about stacking. |
size-limit report 📦
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
🧹 Nitpick comments (6)
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/page.tsx (1)
1-3
: Consider enhancing the infrastructure overview page.While this minimal implementation works as a placeholder, consider adding more meaningful content such as:
- Infrastructure service status overview
- Quick access links to deploy new services
- Summary of existing infrastructure
This would provide better user experience compared to the current basic text display.
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/order-summary.tsx (2)
8-12
: Consider exposing className prop for better composability.Following the coding guidelines, components should expose a
className
prop when useful for styling flexibility.export function OrderSummary(props: { selectedChainId: number; selectedServices: ServiceConfig[]; paymentFrequency: PaymentFrequency; + className?: string; }) {
And apply it to the root div:
- <div className="space-y-4"> + <div className={cn("space-y-4", props.className)}>
93-93
: Consider making discount percentages configurable.The discount percentages (15% annual, 10-15% bundle) are hardcoded, which reduces flexibility for business logic changes.
Consider extracting these into configuration constants or props:
+const DISCOUNT_CONFIG = { + annual: 0.15, + bundle: { + twoServices: 0.1, + threeServices: 0.15, + }, +} as const; // Then use in calculations: - const annualDiscount = paymentFrequency === "annual" ? 0.15 : 0; + const annualDiscount = paymentFrequency === "annual" ? DISCOUNT_CONFIG.annual : 0;Also applies to: 162-166, 169-169
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/service-selector.tsx (3)
22-26
: Consider exposing className prop for better composability.Following the coding guidelines, components should expose a
className
prop for styling flexibility.export function ServiceSelector(props: { services: ServiceConfig[]; selectedServices: ServiceConfig[]; setSelectedServices: (services: ServiceConfig[]) => void; + className?: string; }) {
113-116
: Break down complex className for better readability.The className string is very long and hard to read. Consider breaking it into multiple lines or extracting parts into variables.
<Label className={cn( - "hover:bg-accent/50 flex gap-6 rounded-lg border px-6 py-4 has-[[aria-checked=true]]:border-primary has-[[aria-checked=true]]:bg-primary/10 cursor-pointer items-center", + "flex items-center gap-6 rounded-lg border px-6 py-4 cursor-pointer", + "hover:bg-accent/50", + "has-[[aria-checked=true]]:border-primary has-[[aria-checked=true]]:bg-primary/10", props.service.required && "cursor-not-allowed", )} >
146-153
: Consider responsive design for feature list.The features are completely hidden on mobile (
hidden lg:grid
). Consider showing a subset or using a different layout for better mobile experience.- <div className="grid-cols-2 gap-2 hidden lg:grid"> + <div className="grid grid-cols-1 lg:grid-cols-2 gap-2"> {props.service.features.map((feature) => ( <div className="flex items-center space-x-1 text-sm" key={feature}> <CheckIcon className="w-3 h-3 shrink-0 text-success-text" /> <span>{feature}</span> </div> ))} </div>Or limit features shown on mobile:
+ <div className="grid grid-cols-1 lg:grid-cols-2 gap-2"> + {props.service.features.slice(0, 2).map((feature) => ( + <div className="flex items-center space-x-1 text-sm" key={feature}> + <CheckIcon className="w-3 h-3 shrink-0 text-success-text" /> + <span>{feature}</span> + </div> + ))} + {props.service.features.length > 2 && ( + <div className="text-sm text-muted-foreground lg:hidden"> + +{props.service.features.length - 2} more features + </div> + )} + </div>
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (26)
apps/dashboard/biome.json
(1 hunks)apps/dashboard/src/@/components/blocks/NetworkSelectors.tsx
(2 hunks)apps/dashboard/src/@/components/blocks/UpsellBannerCard.tsx
(2 hunks)apps/dashboard/src/@/icons/ChainIcon.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/layout.tsx
(2 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/[chain_id]/page.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/checkout.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/order-summary.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/payment-frequency-selector.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/service-selector.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/page.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/layout.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/page.tsx
(1 hunks)apps/nebula/biome.json
(1 hunks)apps/playground-web/biome.json
(1 hunks)apps/portal/biome.json
(1 hunks)apps/wallet-ui/biome.json
(1 hunks)biome.json
(1 hunks)packages/engine/biome.json
(1 hunks)packages/insight/biome.json
(1 hunks)packages/nebula/biome.json
(1 hunks)packages/react-native-adapter/biome.json
(1 hunks)packages/service-utils/biome.json
(1 hunks)packages/thirdweb/biome.json
(1 hunks)packages/vault-sdk/biome.json
(1 hunks)packages/wagmi-adapter/biome.json
(1 hunks)
🧰 Additional context used
📓 Path-based instructions (11)
`apps/dashboard/*`: The dashboard app is a web-based developer console built wit...
apps/dashboard/*
: The dashboard app is a web-based developer console built with Next.js and Chakra UI.
Use Tailwind CSS only for styling; no inline styles or CSS modules.
Use cn() from @/lib/utils for conditional class merging.
Use design system tokens for backgrounds (bg-card), borders (border-border), and muted text (text-muted-foreground).
Expose className prop on the root element of components for overrides.
Use NavLink for internal navigation with automatic active states.
Server components should start files with import "server-only"; client components should begin files with 'use client';.
Never import posthog-js in server components; analytics events are client-side only.
📄 Source: CodeRabbit Inference Engine (CLAUDE.md)
List of files the instruction was applied to:
apps/dashboard/biome.json
`packages/thirdweb/*`: Every public symbol in the SDK must have comprehensive TS...
packages/thirdweb/*
: Every public symbol in the SDK must have comprehensive TSDoc with at least one @example block that compiles and custom annotation tags (@beta, @internal, @experimental).
Export everything via the exports/ directory, grouped by feature.
Place tests alongside code: foo.ts ↔ foo.test.ts.
Use real function invocations with stub data in tests; avoid brittle mocks.
Use Mock Service Worker (MSW) for fetch/HTTP call interception in tests.
Keep tests deterministic and side-effect free.
📄 Source: CodeRabbit Inference Engine (CLAUDE.md)
List of files the instruction was applied to:
packages/thirdweb/biome.json
`apps/wallet-ui/*`: The wallet-ui app is for wallet interface and testing.
apps/wallet-ui/*
: The wallet-ui app is for wallet interface and testing.
📄 Source: CodeRabbit Inference Engine (CLAUDE.md)
List of files the instruction was applied to:
apps/wallet-ui/biome.json
`biome.json`: Biome is the primary linter/formatter; rules are defined in biome.json.
biome.json
: Biome is the primary linter/formatter; rules are defined in biome.json.
📄 Source: CodeRabbit Inference Engine (CLAUDE.md)
List of files the instruction was applied to:
biome.json
`packages/wagmi-adapter/*`: Wagmi ecosystem integration is located in packages/wagmi-adapter/.
packages/wagmi-adapter/*
: Wagmi ecosystem integration is located in packages/wagmi-adapter/.
📄 Source: CodeRabbit Inference Engine (CLAUDE.md)
List of files the instruction was applied to:
packages/wagmi-adapter/biome.json
`apps/portal/*`: The portal app is a documentation site with MDX.
apps/portal/*
: The portal app is a documentation site with MDX.
📄 Source: CodeRabbit Inference Engine (CLAUDE.md)
List of files the instruction was applied to:
apps/portal/biome.json
`packages/react-native-adapter/*`: Mobile platform shims are located in packages/react-native-adapter/.
packages/react-native-adapter/*
: Mobile platform shims are located in packages/react-native-adapter/.
📄 Source: CodeRabbit Inference Engine (CLAUDE.md)
List of files the instruction was applied to:
packages/react-native-adapter/biome.json
`**/icons/*`: Icons come from 'lucide-react' or the project-specific '../icons' exports – never embed raw SVG.
**/icons/*
: Icons come from 'lucide-react' or the project-specific '../icons' exports – never embed raw SVG.
📄 Source: CodeRabbit Inference Engine (.cursor/rules/dashboard.mdc)
List of files the instruction was applied to:
apps/dashboard/src/@/icons/ChainIcon.tsx
`**/*.@(ts|tsx)`: Accept a typed 'props' object and export a named function (e.g...
**/*.@(ts|tsx)
: Accept a typed 'props' object and export a named function (e.g., export function MyComponent()).
Combine class names via 'cn', expose 'className' prop if useful.
Reuse core UI primitives; avoid re-implementing buttons, cards, modals.
Local state or effects live inside; data fetching happens in hooks.
Merge class names with 'cn' from '@/lib/utils' to keep conditional logic readable.
Stick to design-tokens: background ('bg-card'), borders ('border-border'), muted text ('text-muted-foreground') etc.
Use the 'container' class with a 'max-w-7xl' cap for page width consistency.
Spacing utilities ('px-', 'py-', 'gap-*') are preferred over custom margins.
Responsive helpers follow mobile-first ('max-sm', 'md', 'lg', 'xl').
Never hard-code colors – always go through Tailwind variables.
Tailwind CSS is the styling system – avoid inline styles or CSS modules.
Prefix files with 'import "server-only";' so they never end up in the client bundle (for server-only code).
📄 Source: CodeRabbit Inference Engine (.cursor/rules/dashboard.mdc)
List of files the instruction was applied to:
apps/dashboard/src/@/icons/ChainIcon.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/layout.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/page.tsx
apps/dashboard/src/@/components/blocks/NetworkSelectors.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/[chain_id]/page.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/payment-frequency-selector.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/checkout.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/page.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/layout.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/order-summary.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/service-selector.tsx
apps/dashboard/src/@/components/blocks/UpsellBannerCard.tsx
`apps/nebula/*`: The nebula app is for account abstraction and smart wallet management.
apps/nebula/*
: The nebula app is for account abstraction and smart wallet management.
📄 Source: CodeRabbit Inference Engine (CLAUDE.md)
List of files the instruction was applied to:
apps/nebula/biome.json
`apps/playground-web/*`: The playground-web app is an interactive SDK testing environment.
apps/playground-web/*
: The playground-web app is an interactive SDK testing environment.
📄 Source: CodeRabbit Inference Engine (CLAUDE.md)
List of files the instruction was applied to:
apps/playground-web/biome.json
🧠 Learnings (13)
📓 Common learnings
Learnt from: MananTank
PR: thirdweb-dev/js#7315
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx:155-160
Timestamp: 2025-06-10T00:46:58.580Z
Learning: In the dashboard application, the route structure for team and project navigation is `/team/[team_slug]/[project_slug]/...` without a `/project/` segment. Contract links should be formatted as `/team/${teamSlug}/${projectSlug}/contract/${chainId}/${contractAddress}`.
Learnt from: MananTank
PR: thirdweb-dev/js#7315
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx:153-226
Timestamp: 2025-06-10T00:50:20.795Z
Learning: In apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx, the updateStatus function correctly expects a complete MultiStepState["status"] object. For pending states, { type: "pending" } is the entire status object. For error states, { type: "error", message: React.ReactNode } is the entire status object. The current code incorrectly spreads the entire step object instead of passing just the status object.
apps/dashboard/src/@/icons/ChainIcon.tsx (2)
Learnt from: jnsdls
PR: thirdweb-dev/js#7188
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/accounts/components/accounts-count.tsx:15-15
Timestamp: 2025-05-29T00:46:09.063Z
Learning: In the accounts component at apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/accounts/components/accounts-count.tsx, the 3-column grid layout (md:grid-cols-3) is intentionally maintained even when rendering only one StatCard, as part of the design structure for this component.
Learnt from: MananTank
PR: thirdweb-dev/js#7177
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/public-pages/erc20/_components/ContractHeader.tsx:26-43
Timestamp: 2025-05-29T10:49:52.981Z
Learning: In React image components, conditional rendering of the entire image container (e.g., `{props.image && <Img />}`) serves a different purpose than fallback handling. The conditional prevents rendering any image UI when no image metadata exists, while the fallback prop handles cases where image metadata exists but the image fails to load. This pattern is intentional to distinguish between "no image intended" vs "image intended but failed to load".
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/layout.tsx (13)
Learnt from: MananTank
PR: thirdweb-dev/js#7315
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx:155-160
Timestamp: 2025-06-10T00:46:58.580Z
Learning: In the dashboard application, the route structure for team and project navigation is `/team/[team_slug]/[project_slug]/...` without a `/project/` segment. Contract links should be formatted as `/team/${teamSlug}/${projectSlug}/contract/${chainId}/${contractAddress}`.
Learnt from: jnsdls
PR: thirdweb-dev/js#6929
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/insight/webhooks/page.tsx:14-19
Timestamp: 2025-05-21T05:17:31.283Z
Learning: In Next.js server components, the `params` object can sometimes be a Promise that needs to be awaited, despite type annotations suggesting otherwise. In apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/insight/webhooks/page.tsx, it's necessary to await the params object before accessing its properties.
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-25T02:13:08.257Z
Learning: UI primitives should be imported from @/components/ui/*.
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-23T13:49:58.951Z
Learning: Always import reusable UI components from a central library (e.g., '@/components/ui/*') to ensure consistency and avoid duplication.
Learnt from: MananTank
PR: thirdweb-dev/js#7227
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/OpenEditionMetadata.tsx:26-26
Timestamp: 2025-05-30T17:14:25.332Z
Learning: The ModuleCardUIProps interface already includes a client prop of type ThirdwebClient, so when components use `Omit<ModuleCardUIProps, "children" | "updateButton">`, they inherit the client prop without needing to add it explicitly.
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-23T13:49:58.951Z
Learning: Client components must begin with 'use client'; before imports to ensure correct rendering behavior in Next.js.
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-23T13:49:58.951Z
Learning: Prefer composable UI primitives (Button, Input, Select, Tabs, Card, Sidebar, Separator, Badge) over custom markup for maintainability and design consistency.
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-25T02:13:08.257Z
Learning: Client components should begin files with 'use client' and use React hooks for interactivity.
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-23T13:49:58.951Z
Learning: Use client components for interactive UI, components that rely on hooks, browser APIs, or require fast transitions.
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-23T13:49:58.951Z
Learning: Files for components should be named in PascalCase and use the '.client.tsx' suffix if interactive.
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-23T13:49:58.951Z
Learning: Reuse core UI primitives and avoid re-implementing common elements like buttons, cards, or modals.
Learnt from: MananTank
PR: thirdweb-dev/js#7356
File: apps/nebula/src/app/not-found.tsx:1-1
Timestamp: 2025-06-17T18:30:52.976Z
Learning: In the thirdweb/js project, the React namespace is available for type annotations (like React.FC) without needing to explicitly import React. This is project-specific configuration that differs from typical TypeScript/React setups.
Learnt from: MananTank
PR: thirdweb-dev/js#7152
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/nfts/page.tsx:20-20
Timestamp: 2025-05-26T16:26:58.068Z
Learning: In team/project contract pages under routes like `/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/*`, users are always logged in by design. The hardcoded `isLoggedIn={true}` prop in these pages is intentional and correct, not a bug to be fixed.
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/page.tsx (5)
Learnt from: jnsdls
PR: thirdweb-dev/js#6929
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/insight/webhooks/page.tsx:14-19
Timestamp: 2025-05-21T05:17:31.283Z
Learning: In Next.js server components, the `params` object can sometimes be a Promise that needs to be awaited, despite type annotations suggesting otherwise. In apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/insight/webhooks/page.tsx, it's necessary to await the params object before accessing its properties.
Learnt from: jnsdls
PR: thirdweb-dev/js#7363
File: apps/dashboard/src/app/(app)/layout.tsx:63-74
Timestamp: 2025-06-18T02:01:06.006Z
Learning: In Next.js applications, instrumentation files (instrumentation.ts or instrumentation-client.ts) placed in the src/ directory are automatically handled by the framework and included in the client/server bundles without requiring manual imports. The framework injects these files as part of the build process.
Learnt from: MananTank
PR: thirdweb-dev/js#7315
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx:153-226
Timestamp: 2025-06-10T00:50:20.795Z
Learning: In apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx, the updateStatus function correctly expects a complete MultiStepState["status"] object. For pending states, { type: "pending" } is the entire status object. For error states, { type: "error", message: React.ReactNode } is the entire status object. The current code incorrectly spreads the entire step object instead of passing just the status object.
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-25T02:13:08.257Z
Learning: For new UI components, add Storybook stories (*.stories.tsx) alongside the code.
Learnt from: jnsdls
PR: thirdweb-dev/js#7188
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/accounts/components/accounts-count.tsx:15-15
Timestamp: 2025-05-29T00:46:09.063Z
Learning: In the accounts component at apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/accounts/components/accounts-count.tsx, the 3-column grid layout (md:grid-cols-3) is intentionally maintained even when rendering only one StatCard, as part of the design structure for this component.
apps/dashboard/src/@/components/blocks/NetworkSelectors.tsx (2)
Learnt from: MananTank
PR: thirdweb-dev/js#7227
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/OpenEditionMetadata.tsx:26-26
Timestamp: 2025-05-30T17:14:25.332Z
Learning: The ModuleCardUIProps interface already includes a client prop of type ThirdwebClient, so when components use `Omit<ModuleCardUIProps, "children" | "updateButton">`, they inherit the client prop without needing to add it explicitly.
Learnt from: MananTank
PR: thirdweb-dev/js#7298
File: apps/dashboard/src/app/nebula-app/move-funds/move-funds.tsx:424-424
Timestamp: 2025-06-06T23:46:08.795Z
Learning: The thirdweb project has an ESLint rule that restricts direct usage of `defineChain`. When it's necessary to use `defineChain` directly, it's acceptable to disable the rule with `// eslint-disable-next-line no-restricted-syntax`.
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/[chain_id]/page.tsx (7)
Learnt from: jnsdls
PR: thirdweb-dev/js#6929
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/insight/webhooks/page.tsx:14-19
Timestamp: 2025-05-21T05:17:31.283Z
Learning: In Next.js server components, the `params` object can sometimes be a Promise that needs to be awaited, despite type annotations suggesting otherwise. In apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/insight/webhooks/page.tsx, it's necessary to await the params object before accessing its properties.
Learnt from: MananTank
PR: thirdweb-dev/js#7152
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/accounts/page.tsx:2-10
Timestamp: 2025-05-26T16:28:10.079Z
Learning: In Next.js 14+, the `params` object in page components is always a Promise that needs to be awaited, so the correct typing is `params: Promise<ParamsType>` rather than `params: ParamsType`.
Learnt from: MananTank
PR: thirdweb-dev/js#7315
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx:155-160
Timestamp: 2025-06-10T00:46:58.580Z
Learning: In the dashboard application, the route structure for team and project navigation is `/team/[team_slug]/[project_slug]/...` without a `/project/` segment. Contract links should be formatted as `/team/${teamSlug}/${projectSlug}/contract/${chainId}/${contractAddress}`.
Learnt from: jnsdls
PR: thirdweb-dev/js#7188
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/accounts/components/accounts-count.tsx:15-15
Timestamp: 2025-05-29T00:46:09.063Z
Learning: In the accounts component at apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/accounts/components/accounts-count.tsx, the 3-column grid layout (md:grid-cols-3) is intentionally maintained even when rendering only one StatCard, as part of the design structure for this component.
Learnt from: MananTank
PR: thirdweb-dev/js#7152
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/nfts/page.tsx:20-20
Timestamp: 2025-05-26T16:26:58.068Z
Learning: In team/project contract pages under routes like `/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/*`, users are always logged in by design. The hardcoded `isLoggedIn={true}` prop in these pages is intentional and correct, not a bug to be fixed.
Learnt from: MananTank
PR: thirdweb-dev/js#7434
File: apps/dashboard/src/app/(app)/team/~/~/contract/[chain]/[contractAddress]/components/project-selector.tsx:62-76
Timestamp: 2025-06-24T21:38:03.155Z
Learning: In the project-selector.tsx component for contract imports, the addToProject.mutate() call is intentionally not awaited (fire-and-forget pattern) to allow immediate navigation to the contract page while the import happens in the background. This is a deliberate design choice to prioritize user experience.
Learnt from: MananTank
PR: thirdweb-dev/js#7152
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/tokens/shared-page.tsx:41-48
Timestamp: 2025-05-26T16:28:50.772Z
Learning: The `projectMeta` prop is not required for the server-rendered `ContractTokensPage` component in the tokens shared page, unlike some other shared pages where it's needed for consistency.
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/payment-frequency-selector.tsx (3)
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-23T13:49:58.951Z
Learning: Files for components should be named in PascalCase and use the '.client.tsx' suffix if interactive.
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-25T02:13:08.257Z
Learning: For new UI components, add Storybook stories (*.stories.tsx) alongside the code.
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-23T13:49:58.951Z
Learning: Prefer composable UI primitives (Button, Input, Select, Tabs, Card, Sidebar, Separator, Badge) over custom markup for maintainability and design consistency.
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/checkout.tsx (9)
Learnt from: MananTank
PR: thirdweb-dev/js#7315
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx:153-226
Timestamp: 2025-06-10T00:50:20.795Z
Learning: In apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx, the updateStatus function correctly expects a complete MultiStepState["status"] object. For pending states, { type: "pending" } is the entire status object. For error states, { type: "error", message: React.ReactNode } is the entire status object. The current code incorrectly spreads the entire step object instead of passing just the status object.
Learnt from: jnsdls
PR: thirdweb-dev/js#6929
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/insight/webhooks/page.tsx:14-19
Timestamp: 2025-05-21T05:17:31.283Z
Learning: In Next.js server components, the `params` object can sometimes be a Promise that needs to be awaited, despite type annotations suggesting otherwise. In apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/insight/webhooks/page.tsx, it's necessary to await the params object before accessing its properties.
Learnt from: jnsdls
PR: thirdweb-dev/js#7188
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/accounts/components/accounts-count.tsx:15-15
Timestamp: 2025-05-29T00:46:09.063Z
Learning: In the accounts component at apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/accounts/components/accounts-count.tsx, the 3-column grid layout (md:grid-cols-3) is intentionally maintained even when rendering only one StatCard, as part of the design structure for this component.
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-25T02:13:08.257Z
Learning: Client components should begin files with 'use client' and use React hooks for interactivity.
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-23T13:49:58.951Z
Learning: Files for components should be named in PascalCase and use the '.client.tsx' suffix if interactive.
Learnt from: MananTank
PR: thirdweb-dev/js#7434
File: apps/dashboard/src/app/(app)/team/~/~/contract/[chain]/[contractAddress]/components/project-selector.tsx:62-76
Timestamp: 2025-06-24T21:38:03.155Z
Learning: In the project-selector.tsx component for contract imports, the addToProject.mutate() call is intentionally not awaited (fire-and-forget pattern) to allow immediate navigation to the contract page while the import happens in the background. This is a deliberate design choice to prioritize user experience.
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-25T02:13:08.257Z
Learning: For new UI components, add Storybook stories (*.stories.tsx) alongside the code.
Learnt from: jnsdls
PR: thirdweb-dev/js#7364
File: apps/dashboard/src/app/(app)/account/components/AccountHeader.tsx:36-41
Timestamp: 2025-06-18T02:13:34.500Z
Learning: In the logout flow in apps/dashboard/src/app/(app)/account/components/AccountHeader.tsx, when `doLogout()` fails, the cleanup steps (resetAnalytics(), wallet disconnect, router refresh) should NOT execute. This is intentional to maintain consistency - if server-side logout fails, client-side cleanup should not occur.
Learnt from: MananTank
PR: thirdweb-dev/js#7227
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/OpenEditionMetadata.tsx:26-26
Timestamp: 2025-05-30T17:14:25.332Z
Learning: The ModuleCardUIProps interface already includes a client prop of type ThirdwebClient, so when components use `Omit<ModuleCardUIProps, "children" | "updateButton">`, they inherit the client prop without needing to add it explicitly.
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/page.tsx (12)
Learnt from: jnsdls
PR: thirdweb-dev/js#6929
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/insight/webhooks/page.tsx:14-19
Timestamp: 2025-05-21T05:17:31.283Z
Learning: In Next.js server components, the `params` object can sometimes be a Promise that needs to be awaited, despite type annotations suggesting otherwise. In apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/insight/webhooks/page.tsx, it's necessary to await the params object before accessing its properties.
Learnt from: jnsdls
PR: thirdweb-dev/js#7363
File: apps/dashboard/src/app/(app)/layout.tsx:63-74
Timestamp: 2025-06-18T02:01:06.006Z
Learning: In Next.js applications, instrumentation files (instrumentation.ts or instrumentation-client.ts) placed in the src/ directory are automatically handled by the framework and included in the client/server bundles without requiring manual imports. The framework injects these files as part of the build process.
Learnt from: MananTank
PR: thirdweb-dev/js#7315
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx:153-226
Timestamp: 2025-06-10T00:50:20.795Z
Learning: In apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx, the updateStatus function correctly expects a complete MultiStepState["status"] object. For pending states, { type: "pending" } is the entire status object. For error states, { type: "error", message: React.ReactNode } is the entire status object. The current code incorrectly spreads the entire step object instead of passing just the status object.
Learnt from: MananTank
PR: thirdweb-dev/js#7152
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/(marketplace)/direct-listings/shared-direct-listings-page.tsx:47-52
Timestamp: 2025-05-26T16:29:54.317Z
Learning: The `projectMeta` prop is not required for the server-rendered `ContractDirectListingsPage` component in the direct listings shared page, following the same pattern as other server components in the codebase where `projectMeta` is only needed for client components.
Learnt from: MananTank
PR: thirdweb-dev/js#7434
File: apps/dashboard/src/app/(app)/team/~/~/contract/[chain]/[contractAddress]/components/project-selector.tsx:62-76
Timestamp: 2025-06-24T21:38:03.155Z
Learning: In the project-selector.tsx component for contract imports, the addToProject.mutate() call is intentionally not awaited (fire-and-forget pattern) to allow immediate navigation to the contract page while the import happens in the background. This is a deliberate design choice to prioritize user experience.
Learnt from: MananTank
PR: thirdweb-dev/js#7152
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/tokens/shared-page.tsx:41-48
Timestamp: 2025-05-26T16:28:50.772Z
Learning: The `projectMeta` prop is not required for the server-rendered `ContractTokensPage` component in the tokens shared page, unlike some other shared pages where it's needed for consistency.
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-23T13:49:58.951Z
Learning: Files for components should be named in PascalCase and use the '.client.tsx' suffix if interactive.
Learnt from: MananTank
PR: thirdweb-dev/js#7227
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/OpenEditionMetadata.tsx:26-26
Timestamp: 2025-05-30T17:14:25.332Z
Learning: The ModuleCardUIProps interface already includes a client prop of type ThirdwebClient, so when components use `Omit<ModuleCardUIProps, "children" | "updateButton">`, they inherit the client prop without needing to add it explicitly.
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-23T13:49:58.951Z
Learning: Client components must begin with 'use client'; before imports to ensure correct rendering behavior in Next.js.
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-25T02:13:08.257Z
Learning: Client components should begin files with 'use client' and use React hooks for interactivity.
Learnt from: MananTank
PR: thirdweb-dev/js#7152
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/analytics/shared-analytics-page.tsx:33-39
Timestamp: 2025-05-26T16:30:24.965Z
Learning: In the thirdweb dashboard codebase, redirectToContractLandingPage function already handles execution termination internally (likely using Next.js redirect() which throws an exception), so no explicit return statement is needed after calling it.
Learnt from: MananTank
PR: thirdweb-dev/js#7152
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/claim-conditions/shared-claim-conditions-page.tsx:43-49
Timestamp: 2025-05-26T16:31:02.480Z
Learning: In the thirdweb dashboard codebase, when `redirectToContractLandingPage()` is called, an explicit return statement is not required afterward because the function internally calls Next.js's `redirect()` which throws an error to halt execution.
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/layout.tsx (8)
Learnt from: jnsdls
PR: thirdweb-dev/js#6929
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/insight/webhooks/page.tsx:14-19
Timestamp: 2025-05-21T05:17:31.283Z
Learning: In Next.js server components, the `params` object can sometimes be a Promise that needs to be awaited, despite type annotations suggesting otherwise. In apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/insight/webhooks/page.tsx, it's necessary to await the params object before accessing its properties.
Learnt from: jnsdls
PR: thirdweb-dev/js#7188
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/accounts/components/accounts-count.tsx:15-15
Timestamp: 2025-05-29T00:46:09.063Z
Learning: In the accounts component at apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/accounts/components/accounts-count.tsx, the 3-column grid layout (md:grid-cols-3) is intentionally maintained even when rendering only one StatCard, as part of the design structure for this component.
Learnt from: MananTank
PR: thirdweb-dev/js#7315
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx:155-160
Timestamp: 2025-06-10T00:46:58.580Z
Learning: In the dashboard application, the route structure for team and project navigation is `/team/[team_slug]/[project_slug]/...` without a `/project/` segment. Contract links should be formatted as `/team/${teamSlug}/${projectSlug}/contract/${chainId}/${contractAddress}`.
Learnt from: MananTank
PR: thirdweb-dev/js#7315
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx:153-226
Timestamp: 2025-06-10T00:50:20.795Z
Learning: In apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx, the updateStatus function correctly expects a complete MultiStepState["status"] object. For pending states, { type: "pending" } is the entire status object. For error states, { type: "error", message: React.ReactNode } is the entire status object. The current code incorrectly spreads the entire step object instead of passing just the status object.
Learnt from: MananTank
PR: thirdweb-dev/js#7152
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/accounts/page.tsx:2-10
Timestamp: 2025-05-26T16:28:10.079Z
Learning: In Next.js 14+, the `params` object in page components is always a Promise that needs to be awaited, so the correct typing is `params: Promise<ParamsType>` rather than `params: ParamsType`.
Learnt from: MananTank
PR: thirdweb-dev/js#7152
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/nfts/page.tsx:20-20
Timestamp: 2025-05-26T16:26:58.068Z
Learning: In team/project contract pages under routes like `/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/*`, users are always logged in by design. The hardcoded `isLoggedIn={true}` prop in these pages is intentional and correct, not a bug to be fixed.
Learnt from: MananTank
PR: thirdweb-dev/js#7434
File: apps/dashboard/src/app/(app)/team/~/~/contract/[chain]/[contractAddress]/components/project-selector.tsx:62-76
Timestamp: 2025-06-24T21:38:03.155Z
Learning: In the project-selector.tsx component for contract imports, the addToProject.mutate() call is intentionally not awaited (fire-and-forget pattern) to allow immediate navigation to the contract page while the import happens in the background. This is a deliberate design choice to prioritize user experience.
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-23T13:49:58.951Z
Learning: Client components must begin with 'use client'; before imports to ensure correct rendering behavior in Next.js.
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/order-summary.tsx (2)
Learnt from: jnsdls
PR: thirdweb-dev/js#7188
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/accounts/components/accounts-count.tsx:15-15
Timestamp: 2025-05-29T00:46:09.063Z
Learning: In the accounts component at apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/accounts/components/accounts-count.tsx, the 3-column grid layout (md:grid-cols-3) is intentionally maintained even when rendering only one StatCard, as part of the design structure for this component.
Learnt from: MananTank
PR: thirdweb-dev/js#7315
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx:153-226
Timestamp: 2025-06-10T00:50:20.795Z
Learning: In apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx, the updateStatus function correctly expects a complete MultiStepState["status"] object. For pending states, { type: "pending" } is the entire status object. For error states, { type: "error", message: React.ReactNode } is the entire status object. The current code incorrectly spreads the entire step object instead of passing just the status object.
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/service-selector.tsx (5)
Learnt from: MananTank
PR: thirdweb-dev/js#7315
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx:153-226
Timestamp: 2025-06-10T00:50:20.795Z
Learning: In apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx, the updateStatus function correctly expects a complete MultiStepState["status"] object. For pending states, { type: "pending" } is the entire status object. For error states, { type: "error", message: React.ReactNode } is the entire status object. The current code incorrectly spreads the entire step object instead of passing just the status object.
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-25T02:13:08.257Z
Learning: For new UI components, add Storybook stories (*.stories.tsx) alongside the code.
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-23T13:49:58.951Z
Learning: Files for components should be named in PascalCase and use the '.client.tsx' suffix if interactive.
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-25T02:13:08.257Z
Learning: Group feature-specific components under feature/components/* with a barrel index.ts.
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-23T13:49:58.951Z
Learning: Prefer composable UI primitives (Button, Input, Select, Tabs, Card, Sidebar, Separator, Badge) over custom markup for maintainability and design consistency.
apps/dashboard/src/@/components/blocks/UpsellBannerCard.tsx (5)
Learnt from: MananTank
PR: thirdweb-dev/js#7227
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/OpenEditionMetadata.tsx:26-26
Timestamp: 2025-05-30T17:14:25.332Z
Learning: The ModuleCardUIProps interface already includes a client prop of type ThirdwebClient, so when components use `Omit<ModuleCardUIProps, "children" | "updateButton">`, they inherit the client prop without needing to add it explicitly.
Learnt from: MananTank
PR: thirdweb-dev/js#7315
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx:153-226
Timestamp: 2025-06-10T00:50:20.795Z
Learning: In apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx, the updateStatus function correctly expects a complete MultiStepState["status"] object. For pending states, { type: "pending" } is the entire status object. For error states, { type: "error", message: React.ReactNode } is the entire status object. The current code incorrectly spreads the entire step object instead of passing just the status object.
Learnt from: jnsdls
PR: thirdweb-dev/js#7365
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/ProjectFTUX.tsx:16-17
Timestamp: 2025-06-18T04:30:04.326Z
Learning: Next.js Link component fully supports both internal and external URLs and works appropriately with all standard anchor attributes including target="_blank", rel="noopener noreferrer", etc. Using Link for external URLs is completely appropriate and recommended.
Learnt from: jnsdls
PR: thirdweb-dev/js#7365
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/ProjectFTUX.tsx:16-17
Timestamp: 2025-06-18T04:27:16.172Z
Learning: Next.js Link component supports external URLs without throwing errors. When used with absolute URLs (like https://...), it behaves like a regular anchor tag without client-side routing, but does not cause runtime crashes or errors as previously believed.
Learnt from: MananTank
PR: thirdweb-dev/js#7177
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/public-pages/erc20/_components/ContractHeader.tsx:26-43
Timestamp: 2025-05-29T10:49:52.981Z
Learning: In React image components, conditional rendering of the entire image container (e.g., `{props.image && <Img />}`) serves a different purpose than fallback handling. The conditional prevents rendering any image UI when no image metadata exists, while the fallback prop handles cases where image metadata exists but the image fails to load. This pattern is intentional to distinguish between "no image intended" vs "image intended but failed to load".
🧬 Code Graph Analysis (3)
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/page.tsx (1)
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/[chain_id]/page.tsx (1)
InfrastructurePage
(3-12)
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/payment-frequency-selector.tsx (1)
apps/dashboard/src/@/components/ui/radio-group.tsx (1)
RadioGroupItemButton
(75-75)
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/layout.tsx (2)
apps/dashboard/src/@/api/team.ts (1)
getTeamBySlug
(13-32)apps/dashboard/src/@/components/blocks/upsell-wrapper.tsx (1)
UpsellWrapper
(34-74)
⏰ Context from checks skipped due to timeout of 90000ms (8)
- GitHub Check: Size
- GitHub Check: Unit Tests
- GitHub Check: E2E Tests (pnpm, esbuild)
- GitHub Check: E2E Tests (pnpm, vite)
- GitHub Check: E2E Tests (pnpm, webpack)
- GitHub Check: Build Packages
- GitHub Check: Lint Packages
- GitHub Check: Analyze (javascript)
🔇 Additional comments (27)
biome.json (1)
2-2
: Ensure the toolchain is upgraded to Biome 2.0.4+The schema bump is fine, but editors/CI will complain if the locally installed
@biomejs/biome
CLI is still on 2.0.0.
Please verify the rootpackage.json
(or each workspace) pins@biomejs/biome
≥ 2.0.4 before this lands.packages/insight/biome.json (1)
2-2
: Same schema bump as the root file; handled by the earlier comment. No further feedback.packages/service-utils/biome.json (1)
2-2
: Same schema bump as the root file; handled by the earlier comment. No further feedback.packages/nebula/biome.json (1)
2-2
: Same schema bump as the root file; handled by the earlier comment. No further feedback.packages/engine/biome.json (1)
2-2
: Same schema bump as the root file; handled by the earlier comment. No further feedback.apps/wallet-ui/biome.json (1)
2-2
: Verify Biome CLI/tooling is on ≥ 2.0.4 before mergingThe schema bump is harmless, but config validation will fail locally/CI if any environment is still pinned to 2.0.0. Double-check the version in
package.json
/ lockfiles or CI images.apps/portal/biome.json (1)
2-2
: Confirm portal build pipeline uses Biome 2.0.4Same note as other apps: ensure the CLI version matches the new schema to avoid lint/format errors in CI.
packages/thirdweb/biome.json (1)
2-2
: SDK package also needs Biome 2.0.4 in dev-depsUpdating the schema without bumping the dev dependency may break
pnpm lint
for package authors. Verify the root workspace has the correct version.apps/dashboard/biome.json (1)
2-2
: Dashboard app: check Docker/CI image for Biome version driftIf the dashboard is built inside a container, ensure the image was rebuilt with Biome 2.0.4; otherwise schema validation will complain.
apps/playground-web/biome.json (1)
2-2
: Playground-web: sync local VSCode extension + CI to Biome 2.0.4Developers’ editors and CI must understand the new schema; confirm extension/update is applied.
packages/vault-sdk/biome.json (1)
2-2
: Schema version bump looks goodThe config now references the 2.0.4 schema, matching the rest of the repo. No further action required as long as the CI environment is already running Biome ≥ 2.0.4.
packages/wagmi-adapter/biome.json (1)
2-2
: Consistent schema upgradeUpgrade to 2.0.4 keeps the wagmi-adapter package aligned with the global tooling.
packages/react-native-adapter/biome.json (1)
2-2
: LGTM – schema reference updatedNothing else changed; integration with the React-Native adapter remains unaffected.
apps/nebula/biome.json (1)
2-2
: Nebula biome.json updated correctlyThe schema URL now points to 2.0.4, in sync with other apps.
apps/dashboard/src/@/icons/ChainIcon.tsx (1)
33-33
: LGTM! Semantic improvement for skeleton placeholder.The change from
<div>
to<span>
is appropriate since spans are inline elements better suited for icon placeholders while maintaining the same styling and animation behavior.apps/dashboard/src/@/components/blocks/NetworkSelectors.tsx (3)
155-155
: LGTM! Proper prop addition.The optional
disableDeprecated
prop is well-typed and follows the established pattern of other boolean filter props in this component.
173-175
: LGTM! Correct filtering implementation.The filtering logic properly excludes chains with deprecated status, using the standard filtering pattern consistent with other conditional filters in this component.
178-183
: LGTM! Proper dependency array update.The dependency array correctly includes
disableDeprecated
to ensure the memoizedchainsToShow
recalculates when the filter option changes.apps/dashboard/src/app/(app)/team/[team_slug]/(team)/layout.tsx (2)
9-9
: LGTM! Proper UI primitive import.Badge component correctly imported from the central UI library, following established coding guidelines.
90-97
: LGTM! Well-structured tab addition.The Infrastructure tab implementation follows the established pattern with proper JSX structure for the name prop containing the Badge component. The routing path is consistent with other team navigation tabs.
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/page.tsx (1)
4-8
: LGTM! Proper server component pattern.The implementation correctly follows the established server component pattern by initializing the client on the server side and passing it to the client component.
Verify team context handling.
Since this page is in the team route structure (
/team/[team_slug]/...
), ensure that theInfrastructureCheckout
component can access the necessary team context. If team information is required, consider extracting the team_slug from params.#!/bin/bash # Description: Check if InfrastructureCheckout component needs team context # Expected: Find usage of team context or team_slug in the checkout component ast-grep --pattern $'function InfrastructureCheckout($$$) { $$$ }' # Also check for any team-related props or usage rg -A 10 -B 5 "team" apps/dashboard/src/app/\(app\)/team/\[team_slug\]/\(team\)/~/infrastructure/deploy/_components/checkout.tsxapps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/[chain_id]/page.tsx (1)
3-12
: LGTM! Clean implementation following Next.js 14+ patterns.The component correctly awaits the params Promise and uses the existing
getChain
utility. The implementation is straightforward and follows the established patterns in the codebase.apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/layout.tsx (1)
8-46
: LGTM! Well-structured layout with proper access control.The component correctly:
- Awaits params following Next.js 14+ patterns
- Fetches team data and handles missing teams gracefully
- Implements proper billing plan access control via
UpsellWrapper
- Uses consistent team route structure for the deploy button link
- Follows the established UI component patterns
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/payment-frequency-selector.tsx (1)
4-47
: LGTM! Clean and well-structured payment frequency selector.The component effectively uses UI primitives and follows good practices:
- Clear type definitions with
PaymentFrequency
export- Responsive grid layout for different screen sizes
- Proper use of
RadioGroup
with controlled state- Good visual hierarchy with discount badge for annual option
- Consistent styling patterns with data attributes
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/checkout.tsx (1)
1-206
: LGTM! Comprehensive and well-structured checkout flow.This is an excellent implementation of a multi-step infrastructure deployment checkout:
Strengths:
- Correct use of
"use client"
directive and React hooks- Well-organized service configuration with clear pricing and features
- Proper state management for chain, services, and payment frequency
- Good responsive design with logical grid layout
- Appropriate use of
ClientOnly
wrapper for client-side components- Clear step-by-step UI with badges and descriptions
- Comprehensive order summary with chain details and fallback states
- Follows established patterns from the codebase
Architecture:
- Clean separation of concerns with imported child components
- Good use of existing UI primitives (Card, Badge, etc.)
- Proper handling of derived state with
useMemo
- RPC service correctly marked as required and pre-selected
apps/dashboard/src/@/components/blocks/UpsellBannerCard.tsx (1)
41-136
: LGTM! Well-implemented discriminated union for CTA variants.The update effectively supports both link-based and callback-based CTAs:
Good practices:
- Clean discriminated union type definition using presence of
target
vsonClick
- Proper conditional rendering logic to distinguish between variants
- Correct security attributes (
rel="noopener noreferrer"
) for external links- Consistent styling and icon handling across both variants
- Follows established component patterns in the codebase
The type-safe approach ensures proper usage of each CTA variant while maintaining backward compatibility.
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/order-summary.tsx (1)
156-158
: Add null safety for service access.The code uses optional chaining for
service?.monthlyPrice
but doesn't handle the case whereservice
itself might be null/undefined in the filter.const baseMonthlyTotal = selectedServices.reduce((total, service) => { - return total + (service?.monthlyPrice || 0); + return total + (service?.monthlyPrice ?? 0); - }, 0); + }, 0);Consider filtering out null services before the reduce operation:
const baseMonthlyTotal = selectedServices + .filter(Boolean) + .reduce((total, service) => { - return total + (service?.monthlyPrice || 0); + return total + service.monthlyPrice; }, 0);⛔ Skipped due to learnings
Learnt from: MananTank PR: thirdweb-dev/js#7177 File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/public-pages/erc20/_hooks/useTokenPriceData.ts:49-49 Timestamp: 2025-05-27T19:55:25.056Z Learning: In the ERC20 public pages token price data hook (`useTokenPriceData.ts`), direct array access on `json.data[0]` without optional chaining is intentionally correct and should not be changed to use safety checks.
{service.monthlyPrice.toLocaleString("en-US", { | ||
maximumFractionDigits: 2, | ||
minimumFractionDigits: 2, | ||
})} | ||
/mo |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Extract repeated currency formatting logic into a utility function.
The same currency formatting pattern is repeated multiple times throughout the component, making it harder to maintain and potentially inconsistent.
+const formatCurrency = (amount: number) =>
+ amount.toLocaleString("en-US", {
+ maximumFractionDigits: 2,
+ minimumFractionDigits: 2,
+ });
// Then replace all instances like:
- {service.monthlyPrice.toLocaleString("en-US", {
- maximumFractionDigits: 2,
- minimumFractionDigits: 2,
- })}
+ {formatCurrency(service.monthlyPrice)}
Also applies to: 62-70, 80-87, 96-103, 113-117, 124-127
🤖 Prompt for AI Agents
In
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/order-summary.tsx
around lines 38 to 42 and similarly at lines 62-70, 80-87, 96-103, 113-117, and
124-127, the currency formatting logic using toLocaleString with fixed fraction
digits is repeated multiple times. Extract this repeated formatting logic into a
single reusable utility function that takes a number and returns the formatted
currency string, then replace all instances with calls to this utility function
to improve maintainability and consistency.
<div className="flex flex-col gap-8"> | ||
<div className="grid gap-4"> | ||
{props.services.map((service) => { | ||
const isSelected = props.selectedServices.includes(service); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use ID-based comparison instead of object reference equality.
The current implementation uses includes()
which relies on reference equality. This may fail if service objects are recreated with the same data but different references.
- const isSelected = props.selectedServices.includes(service);
+ const isSelected = props.selectedServices.some(s => s.id === service.id);
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
const isSelected = props.selectedServices.includes(service); | |
const isSelected = props.selectedServices.some(s => s.id === service.id); |
🤖 Prompt for AI Agents
In
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/service-selector.tsx
at line 53, replace the use of includes() for checking if a service is selected
with an ID-based comparison. Instead of checking if the service object is
included by reference, check if the selectedServices array contains a service
with the same unique ID as the current service. This ensures correct selection
even if service objects are recreated with identical data but different
references.
onClick: () => { | ||
if (nextServiceToAdd) { | ||
props.setSelectedServices([ | ||
...props.selectedServices, | ||
nextServiceToAdd, | ||
]); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Remove redundant null check.
The nextServiceToAdd
is already checked to be truthy in the ternary condition on line 82, making the inner null check redundant.
onClick: () => {
- if (nextServiceToAdd) {
props.setSelectedServices([
...props.selectedServices,
nextServiceToAdd,
]);
- }
},
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
onClick: () => { | |
if (nextServiceToAdd) { | |
props.setSelectedServices([ | |
...props.selectedServices, | |
nextServiceToAdd, | |
]); | |
} | |
onClick: () => { | |
props.setSelectedServices([ | |
...props.selectedServices, | |
nextServiceToAdd, | |
]); | |
}, |
🤖 Prompt for AI Agents
In
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/service-selector.tsx
around lines 84 to 90, remove the redundant null check for nextServiceToAdd
inside the onClick handler since it is already verified as truthy in the ternary
condition on line 82. Simplify the code by directly using nextServiceToAdd
without the additional if check.
71255ca
to
f9d44a0
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
♻️ Duplicate comments (2)
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/service-selector.tsx (2)
53-53
: Use ID-based comparison instead of object reference equality.The current implementation uses
includes()
which relies on reference equality. This may fail if service objects are recreated with the same data but different references.- const isSelected = props.selectedServices.includes(service); + const isSelected = props.selectedServices.some(s => s.id === service.id);
84-90
: Remove redundant null check.The
nextServiceToAdd
is already checked to be truthy in the ternary condition on line 82, making the inner null check redundant.onClick: () => { - if (nextServiceToAdd) { props.setSelectedServices([ ...props.selectedServices, nextServiceToAdd, ]); - } },
🧹 Nitpick comments (1)
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/service-selector.tsx (1)
138-138
: Consider edge case handling for zero pricing.While unlikely in this context, the pricing display doesn't handle edge cases where
monthlyPrice
might be 0. Consider if this scenario needs special handling or messaging.- ${props.service.monthlyPrice.toLocaleString()} + {props.service.monthlyPrice === 0 ? 'Free' : `$${props.service.monthlyPrice.toLocaleString()}`}
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (26)
apps/dashboard/biome.json
(1 hunks)apps/dashboard/src/@/components/blocks/NetworkSelectors.tsx
(2 hunks)apps/dashboard/src/@/components/blocks/UpsellBannerCard.tsx
(2 hunks)apps/dashboard/src/@/icons/ChainIcon.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/layout.tsx
(2 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/[chain_id]/page.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/checkout.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/order-summary.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/payment-frequency-selector.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/service-selector.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/page.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/layout.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/page.tsx
(1 hunks)apps/nebula/biome.json
(1 hunks)apps/playground-web/biome.json
(1 hunks)apps/portal/biome.json
(1 hunks)apps/wallet-ui/biome.json
(1 hunks)biome.json
(1 hunks)packages/engine/biome.json
(1 hunks)packages/insight/biome.json
(1 hunks)packages/nebula/biome.json
(1 hunks)packages/react-native-adapter/biome.json
(1 hunks)packages/service-utils/biome.json
(1 hunks)packages/thirdweb/biome.json
(1 hunks)packages/vault-sdk/biome.json
(1 hunks)packages/wagmi-adapter/biome.json
(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (25)
- apps/dashboard/biome.json
- packages/wagmi-adapter/biome.json
- biome.json
- apps/portal/biome.json
- packages/service-utils/biome.json
- packages/thirdweb/biome.json
- packages/engine/biome.json
- packages/insight/biome.json
- apps/wallet-ui/biome.json
- packages/vault-sdk/biome.json
- packages/nebula/biome.json
- packages/react-native-adapter/biome.json
- apps/nebula/biome.json
- apps/dashboard/src/app/(app)/team/[team_slug]/(team)/layout.tsx
- apps/playground-web/biome.json
- apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/page.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/page.tsx
- apps/dashboard/src/@/components/blocks/NetworkSelectors.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/[chain_id]/page.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/payment-frequency-selector.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/checkout.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/layout.tsx
- apps/dashboard/src/@/icons/ChainIcon.tsx
- apps/dashboard/src/@/components/blocks/UpsellBannerCard.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/order-summary.tsx
🧰 Additional context used
📓 Path-based instructions (1)
`**/*.@(ts|tsx)`: Accept a typed 'props' object and export a named function (e.g...
**/*.@(ts|tsx)
: Accept a typed 'props' object and export a named function (e.g., export function MyComponent()).
Combine class names via 'cn', expose 'className' prop if useful.
Reuse core UI primitives; avoid re-implementing buttons, cards, modals.
Local state or effects live inside; data fetching happens in hooks.
Merge class names with 'cn' from '@/lib/utils' to keep conditional logic readable.
Stick to design-tokens: background ('bg-card'), borders ('border-border'), muted text ('text-muted-foreground') etc.
Use the 'container' class with a 'max-w-7xl' cap for page width consistency.
Spacing utilities ('px-', 'py-', 'gap-*') are preferred over custom margins.
Responsive helpers follow mobile-first ('max-sm', 'md', 'lg', 'xl').
Never hard-code colors – always go through Tailwind variables.
Tailwind CSS is the styling system – avoid inline styles or CSS modules.
Prefix files with 'import "server-only";' so they never end up in the client bundle (for server-only code).
📄 Source: CodeRabbit Inference Engine (.cursor/rules/dashboard.mdc)
List of files the instruction was applied to:
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/service-selector.tsx
🧠 Learnings (2)
📓 Common learnings
Learnt from: MananTank
PR: thirdweb-dev/js#7315
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx:155-160
Timestamp: 2025-06-10T00:46:58.580Z
Learning: In the dashboard application, the route structure for team and project navigation is `/team/[team_slug]/[project_slug]/...` without a `/project/` segment. Contract links should be formatted as `/team/${teamSlug}/${projectSlug}/contract/${chainId}/${contractAddress}`.
Learnt from: MananTank
PR: thirdweb-dev/js#7315
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx:153-226
Timestamp: 2025-06-10T00:50:20.795Z
Learning: In apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx, the updateStatus function correctly expects a complete MultiStepState["status"] object. For pending states, { type: "pending" } is the entire status object. For error states, { type: "error", message: React.ReactNode } is the entire status object. The current code incorrectly spreads the entire step object instead of passing just the status object.
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/service-selector.tsx (5)
Learnt from: MananTank
PR: thirdweb-dev/js#7315
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx:153-226
Timestamp: 2025-06-10T00:50:20.795Z
Learning: In apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx, the updateStatus function correctly expects a complete MultiStepState["status"] object. For pending states, { type: "pending" } is the entire status object. For error states, { type: "error", message: React.ReactNode } is the entire status object. The current code incorrectly spreads the entire step object instead of passing just the status object.
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-25T02:13:08.257Z
Learning: For new UI components, add Storybook stories (*.stories.tsx) alongside the code.
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-23T13:49:58.951Z
Learning: Files for components should be named in PascalCase and use the '.client.tsx' suffix if interactive.
Learnt from: jnsdls
PR: thirdweb-dev/js#6929
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/insight/webhooks/page.tsx:14-19
Timestamp: 2025-05-21T05:17:31.283Z
Learning: In Next.js server components, the `params` object can sometimes be a Promise that needs to be awaited, despite type annotations suggesting otherwise. In apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/insight/webhooks/page.tsx, it's necessary to await the params object before accessing its properties.
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-23T13:49:58.951Z
Learning: Prefer composable UI primitives (Button, Input, Select, Tabs, Card, Sidebar, Separator, Badge) over custom markup for maintainability and design consistency.
🧬 Code Graph Analysis (1)
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/service-selector.tsx (1)
apps/dashboard/src/@/components/blocks/UpsellBannerCard.tsx (1)
UpsellBannerCard
(57-140)
⏰ Context from checks skipped due to timeout of 90000ms (7)
- GitHub Check: E2E Tests (pnpm, esbuild)
- GitHub Check: E2E Tests (pnpm, vite)
- GitHub Check: E2E Tests (pnpm, webpack)
- GitHub Check: Size
- GitHub Check: Unit Tests
- GitHub Check: Build Packages
- GitHub Check: Analyze (javascript)
🔇 Additional comments (3)
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/service-selector.tsx (3)
9-20
: Type definitions look well-structured.The
Service
union type andServiceConfig
interface are properly defined and provide good type safety. The interface covers all necessary service metadata including pricing, features, and UI elements.
27-32
: Good use of useMemo for performance optimization.The
nextServiceToAdd
computation correctly uses ID-based comparison and is properly memoized with appropriate dependencies.
106-157
: ServiceCheckboxCard component follows best practices.The component properly:
- Uses semantic HTML with Label for accessibility
- Implements conditional styling with
cn()
utility- Handles required services appropriately by disabling interaction
- Uses design system components (Checkbox, Badge)
- Applies responsive design patterns with
lg:
prefixes
f9d44a0
to
4bd0809
Compare
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## main #7456 +/- ##
==========================================
- Coverage 51.92% 51.92% -0.01%
==========================================
Files 947 947
Lines 63875 63932 +57
Branches 4214 4219 +5
==========================================
+ Hits 33166 33194 +28
- Misses 30603 30632 +29
Partials 106 106
🚀 New features to boost your workflow:
|
4bd0809
to
ae2e3de
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
🧹 Nitpick comments (3)
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/scale/deploy/_components/checkout.tsx (1)
159-162
: Consider making the annual discount configurable.The 15% discount is hardcoded here and in the description. Consider extracting this to a constant for maintainability.
+const ANNUAL_DISCOUNT_PERCENT = 15; + // ... - <PaymentFrequencySelector - annualDiscountPercent={15} + <PaymentFrequencySelector + annualDiscountPercent={ANNUAL_DISCOUNT_PERCENT}Also update line 155 to use the same constant:
- Choose your billing frequency. Save 15% with annual payment. + Choose your billing frequency. Save {ANNUAL_DISCOUNT_PERCENT}% with annual payment.apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/scale/deploy/_components/service-selector.tsx (2)
84-91
: Remove redundant conditional check.The
nextServiceToAdd
is already checked in the ternary operator above, making the inner check redundant.onClick: () => { - if (nextServiceToAdd) { props.setSelectedServices([ ...props.selectedServices, nextServiceToAdd, ]); - } },
22-26
: Consider adding Storybook stories for the new component.Based on the coding guidelines, new UI components should include Storybook stories for better documentation and testing.
Would you like me to generate a Storybook story file for this component to demonstrate its various states and configurations?
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (26)
apps/dashboard/biome.json
(1 hunks)apps/dashboard/src/@/components/blocks/NetworkSelectors.tsx
(2 hunks)apps/dashboard/src/@/components/blocks/UpsellBannerCard.tsx
(2 hunks)apps/dashboard/src/@/icons/ChainIcon.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/layout.tsx
(2 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/scale/[chain_id]/page.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/scale/deploy/_components/checkout.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/scale/deploy/_components/order-summary.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/scale/deploy/_components/payment-frequency-selector.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/scale/deploy/_components/service-selector.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/scale/deploy/page.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/scale/layout.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/scale/page.tsx
(1 hunks)apps/nebula/biome.json
(1 hunks)apps/playground-web/biome.json
(1 hunks)apps/portal/biome.json
(1 hunks)apps/wallet-ui/biome.json
(1 hunks)biome.json
(1 hunks)packages/engine/biome.json
(1 hunks)packages/insight/biome.json
(1 hunks)packages/nebula/biome.json
(1 hunks)packages/react-native-adapter/biome.json
(1 hunks)packages/service-utils/biome.json
(1 hunks)packages/thirdweb/biome.json
(1 hunks)packages/vault-sdk/biome.json
(1 hunks)packages/wagmi-adapter/biome.json
(1 hunks)
✅ Files skipped from review due to trivial changes (2)
- apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/scale/page.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/scale/deploy/page.tsx
🚧 Files skipped from review as they are similar to previous changes (18)
- apps/wallet-ui/biome.json
- apps/portal/biome.json
- apps/dashboard/biome.json
- packages/react-native-adapter/biome.json
- packages/wagmi-adapter/biome.json
- packages/thirdweb/biome.json
- packages/vault-sdk/biome.json
- packages/nebula/biome.json
- apps/nebula/biome.json
- biome.json
- apps/playground-web/biome.json
- packages/engine/biome.json
- packages/insight/biome.json
- packages/service-utils/biome.json
- apps/dashboard/src/@/icons/ChainIcon.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/(team)/layout.tsx
- apps/dashboard/src/@/components/blocks/NetworkSelectors.tsx
- apps/dashboard/src/@/components/blocks/UpsellBannerCard.tsx
🧰 Additional context used
📓 Path-based instructions (1)
`**/*.@(ts|tsx)`: Accept a typed 'props' object and export a named function (e.g...
**/*.@(ts|tsx)
: Accept a typed 'props' object and export a named function (e.g., export function MyComponent()).
Combine class names via 'cn', expose 'className' prop if useful.
Reuse core UI primitives; avoid re-implementing buttons, cards, modals.
Local state or effects live inside; data fetching happens in hooks.
Merge class names with 'cn' from '@/lib/utils' to keep conditional logic readable.
Stick to design-tokens: background ('bg-card'), borders ('border-border'), muted text ('text-muted-foreground') etc.
Use the 'container' class with a 'max-w-7xl' cap for page width consistency.
Spacing utilities ('px-', 'py-', 'gap-*') are preferred over custom margins.
Responsive helpers follow mobile-first ('max-sm', 'md', 'lg', 'xl').
Never hard-code colors – always go through Tailwind variables.
Tailwind CSS is the styling system – avoid inline styles or CSS modules.
Prefix files with 'import "server-only";' so they never end up in the client bundle (for server-only code).
📄 Source: CodeRabbit Inference Engine (.cursor/rules/dashboard.mdc)
List of files the instruction was applied to:
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/scale/deploy/_components/payment-frequency-selector.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/scale/[chain_id]/page.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/scale/deploy/_components/checkout.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/scale/layout.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/scale/deploy/_components/order-summary.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/scale/deploy/_components/service-selector.tsx
🧠 Learnings (7)
📓 Common learnings
Learnt from: MananTank
PR: thirdweb-dev/js#7315
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx:153-226
Timestamp: 2025-06-10T00:50:20.795Z
Learning: In apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx, the updateStatus function correctly expects a complete MultiStepState["status"] object. For pending states, { type: "pending" } is the entire status object. For error states, { type: "error", message: React.ReactNode } is the entire status object. The current code incorrectly spreads the entire step object instead of passing just the status object.
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/scale/deploy/_components/payment-frequency-selector.tsx (1)
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-23T13:49:58.951Z
Learning: Prefer composable UI primitives (Button, Input, Select, Tabs, Card, Sidebar, Separator, Badge) over custom markup for maintainability and design consistency.
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/scale/[chain_id]/page.tsx (10)
Learnt from: jnsdls
PR: thirdweb-dev/js#6929
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/insight/webhooks/page.tsx:14-19
Timestamp: 2025-05-21T05:17:31.283Z
Learning: In Next.js server components, the `params` object can sometimes be a Promise that needs to be awaited, despite type annotations suggesting otherwise. In apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/insight/webhooks/page.tsx, it's necessary to await the params object before accessing its properties.
Learnt from: jnsdls
PR: thirdweb-dev/js#7188
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/accounts/components/accounts-count.tsx:15-15
Timestamp: 2025-05-29T00:46:09.063Z
Learning: In the accounts component at apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/accounts/components/accounts-count.tsx, the 3-column grid layout (md:grid-cols-3) is intentionally maintained even when rendering only one StatCard, as part of the design structure for this component.
Learnt from: MananTank
PR: thirdweb-dev/js#7315
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx:155-160
Timestamp: 2025-06-10T00:46:58.580Z
Learning: In the dashboard application, the route structure for team and project navigation is `/team/[team_slug]/[project_slug]/...` without a `/project/` segment. Contract links should be formatted as `/team/${teamSlug}/${projectSlug}/contract/${chainId}/${contractAddress}`.
Learnt from: MananTank
PR: thirdweb-dev/js#7152
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/accounts/page.tsx:2-10
Timestamp: 2025-05-26T16:28:10.079Z
Learning: In Next.js 14+, the `params` object in page components is always a Promise that needs to be awaited, so the correct typing is `params: Promise<ParamsType>` rather than `params: ParamsType`.
Learnt from: MananTank
PR: thirdweb-dev/js#7152
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/tokens/shared-page.tsx:41-48
Timestamp: 2025-05-26T16:28:50.772Z
Learning: The `projectMeta` prop is not required for the server-rendered `ContractTokensPage` component in the tokens shared page, unlike some other shared pages where it's needed for consistency.
Learnt from: MananTank
PR: thirdweb-dev/js#7152
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/nfts/page.tsx:20-20
Timestamp: 2025-05-26T16:26:58.068Z
Learning: In team/project contract pages under routes like `/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/*`, users are always logged in by design. The hardcoded `isLoggedIn={true}` prop in these pages is intentional and correct, not a bug to be fixed.
Learnt from: MananTank
PR: thirdweb-dev/js#7315
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx:153-226
Timestamp: 2025-06-10T00:50:20.795Z
Learning: In apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx, the updateStatus function correctly expects a complete MultiStepState["status"] object. For pending states, { type: "pending" } is the entire status object. For error states, { type: "error", message: React.ReactNode } is the entire status object. The current code incorrectly spreads the entire step object instead of passing just the status object.
Learnt from: jnsdls
PR: thirdweb-dev/js#7363
File: apps/dashboard/src/app/(app)/layout.tsx:63-74
Timestamp: 2025-06-18T02:01:06.006Z
Learning: In Next.js applications, instrumentation files (instrumentation.ts or instrumentation-client.ts) placed in the src/ directory are automatically handled by the framework and included in the client/server bundles without requiring manual imports. The framework injects these files as part of the build process.
Learnt from: MananTank
PR: thirdweb-dev/js#7152
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/(marketplace)/direct-listings/shared-direct-listings-page.tsx:47-52
Timestamp: 2025-05-26T16:29:54.317Z
Learning: The `projectMeta` prop is not required for the server-rendered `ContractDirectListingsPage` component in the direct listings shared page, following the same pattern as other server components in the codebase where `projectMeta` is only needed for client components.
Learnt from: MananTank
PR: thirdweb-dev/js#7434
File: apps/dashboard/src/app/(app)/team/~/~/contract/[chain]/[contractAddress]/components/project-selector.tsx:62-76
Timestamp: 2025-06-24T21:38:03.155Z
Learning: In the project-selector.tsx component for contract imports, the addToProject.mutate() call is intentionally not awaited (fire-and-forget pattern) to allow immediate navigation to the contract page while the import happens in the background. This is a deliberate design choice to prioritize user experience.
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/scale/deploy/_components/checkout.tsx (11)
Learnt from: MananTank
PR: thirdweb-dev/js#7315
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx:153-226
Timestamp: 2025-06-10T00:50:20.795Z
Learning: In apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx, the updateStatus function correctly expects a complete MultiStepState["status"] object. For pending states, { type: "pending" } is the entire status object. For error states, { type: "error", message: React.ReactNode } is the entire status object. The current code incorrectly spreads the entire step object instead of passing just the status object.
Learnt from: jnsdls
PR: thirdweb-dev/js#7188
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/accounts/components/accounts-count.tsx:15-15
Timestamp: 2025-05-29T00:46:09.063Z
Learning: In the accounts component at apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/accounts/components/accounts-count.tsx, the 3-column grid layout (md:grid-cols-3) is intentionally maintained even when rendering only one StatCard, as part of the design structure for this component.
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-25T02:13:08.257Z
Learning: Client components should begin files with 'use client' and use React hooks for interactivity.
Learnt from: jnsdls
PR: thirdweb-dev/js#6929
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/insight/webhooks/page.tsx:14-19
Timestamp: 2025-05-21T05:17:31.283Z
Learning: In Next.js server components, the `params` object can sometimes be a Promise that needs to be awaited, despite type annotations suggesting otherwise. In apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/insight/webhooks/page.tsx, it's necessary to await the params object before accessing its properties.
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-23T13:49:58.951Z
Learning: Files for components should be named in PascalCase and use the '.client.tsx' suffix if interactive.
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-25T02:13:08.257Z
Learning: For new UI components, add Storybook stories (*.stories.tsx) alongside the code.
Learnt from: MananTank
PR: thirdweb-dev/js#7434
File: apps/dashboard/src/app/(app)/team/~/~/contract/[chain]/[contractAddress]/components/project-selector.tsx:62-76
Timestamp: 2025-06-24T21:38:03.155Z
Learning: In the project-selector.tsx component for contract imports, the addToProject.mutate() call is intentionally not awaited (fire-and-forget pattern) to allow immediate navigation to the contract page while the import happens in the background. This is a deliberate design choice to prioritize user experience.
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-23T13:49:58.951Z
Learning: Use client components for interactive UI, components that rely on hooks, browser APIs, or require fast transitions.
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-23T13:49:58.951Z
Learning: Client components must begin with 'use client'; before imports to ensure correct rendering behavior in Next.js.
Learnt from: jnsdls
PR: thirdweb-dev/js#7364
File: apps/dashboard/src/app/(app)/account/components/AccountHeader.tsx:36-41
Timestamp: 2025-06-18T02:13:34.500Z
Learning: In the logout flow in apps/dashboard/src/app/(app)/account/components/AccountHeader.tsx, when `doLogout()` fails, the cleanup steps (resetAnalytics(), wallet disconnect, router refresh) should NOT execute. This is intentional to maintain consistency - if server-side logout fails, client-side cleanup should not occur.
Learnt from: MananTank
PR: thirdweb-dev/js#7227
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/OpenEditionMetadata.tsx:26-26
Timestamp: 2025-05-30T17:14:25.332Z
Learning: The ModuleCardUIProps interface already includes a client prop of type ThirdwebClient, so when components use `Omit<ModuleCardUIProps, "children" | "updateButton">`, they inherit the client prop without needing to add it explicitly.
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/scale/layout.tsx (7)
Learnt from: jnsdls
PR: thirdweb-dev/js#6929
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/insight/webhooks/page.tsx:14-19
Timestamp: 2025-05-21T05:17:31.283Z
Learning: In Next.js server components, the `params` object can sometimes be a Promise that needs to be awaited, despite type annotations suggesting otherwise. In apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/insight/webhooks/page.tsx, it's necessary to await the params object before accessing its properties.
Learnt from: jnsdls
PR: thirdweb-dev/js#7188
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/accounts/components/accounts-count.tsx:15-15
Timestamp: 2025-05-29T00:46:09.063Z
Learning: In the accounts component at apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/accounts/components/accounts-count.tsx, the 3-column grid layout (md:grid-cols-3) is intentionally maintained even when rendering only one StatCard, as part of the design structure for this component.
Learnt from: MananTank
PR: thirdweb-dev/js#7315
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx:155-160
Timestamp: 2025-06-10T00:46:58.580Z
Learning: In the dashboard application, the route structure for team and project navigation is `/team/[team_slug]/[project_slug]/...` without a `/project/` segment. Contract links should be formatted as `/team/${teamSlug}/${projectSlug}/contract/${chainId}/${contractAddress}`.
Learnt from: MananTank
PR: thirdweb-dev/js#7315
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx:153-226
Timestamp: 2025-06-10T00:50:20.795Z
Learning: In apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx, the updateStatus function correctly expects a complete MultiStepState["status"] object. For pending states, { type: "pending" } is the entire status object. For error states, { type: "error", message: React.ReactNode } is the entire status object. The current code incorrectly spreads the entire step object instead of passing just the status object.
Learnt from: MananTank
PR: thirdweb-dev/js#7152
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/nfts/page.tsx:20-20
Timestamp: 2025-05-26T16:26:58.068Z
Learning: In team/project contract pages under routes like `/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/*`, users are always logged in by design. The hardcoded `isLoggedIn={true}` prop in these pages is intentional and correct, not a bug to be fixed.
Learnt from: jnsdls
PR: thirdweb-dev/js#7364
File: apps/dashboard/src/app/(app)/account/components/AccountHeader.tsx:36-41
Timestamp: 2025-06-18T02:13:34.500Z
Learning: In the logout flow in apps/dashboard/src/app/(app)/account/components/AccountHeader.tsx, when `doLogout()` fails, the cleanup steps (resetAnalytics(), wallet disconnect, router refresh) should NOT execute. This is intentional to maintain consistency - if server-side logout fails, client-side cleanup should not occur.
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-23T13:49:58.951Z
Learning: Client components must begin with 'use client'; before imports to ensure correct rendering behavior in Next.js.
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/scale/deploy/_components/order-summary.tsx (2)
Learnt from: jnsdls
PR: thirdweb-dev/js#7188
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/accounts/components/accounts-count.tsx:15-15
Timestamp: 2025-05-29T00:46:09.063Z
Learning: In the accounts component at apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/accounts/components/accounts-count.tsx, the 3-column grid layout (md:grid-cols-3) is intentionally maintained even when rendering only one StatCard, as part of the design structure for this component.
Learnt from: MananTank
PR: thirdweb-dev/js#7315
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx:153-226
Timestamp: 2025-06-10T00:50:20.795Z
Learning: In apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx, the updateStatus function correctly expects a complete MultiStepState["status"] object. For pending states, { type: "pending" } is the entire status object. For error states, { type: "error", message: React.ReactNode } is the entire status object. The current code incorrectly spreads the entire step object instead of passing just the status object.
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/scale/deploy/_components/service-selector.tsx (3)
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-23T13:49:58.951Z
Learning: Files for components should be named in PascalCase and use the '.client.tsx' suffix if interactive.
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-25T02:13:08.257Z
Learning: For new UI components, add Storybook stories (*.stories.tsx) alongside the code.
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-23T13:49:58.951Z
Learning: Prefer composable UI primitives (Button, Input, Select, Tabs, Card, Sidebar, Separator, Badge) over custom markup for maintainability and design consistency.
⏰ Context from checks skipped due to timeout of 90000ms (8)
- GitHub Check: Size
- GitHub Check: E2E Tests (pnpm, esbuild)
- GitHub Check: E2E Tests (pnpm, webpack)
- GitHub Check: E2E Tests (pnpm, vite)
- GitHub Check: Unit Tests
- GitHub Check: Lint Packages
- GitHub Check: Build Packages
- GitHub Check: Analyze (javascript)
🔇 Additional comments (5)
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/scale/[chain_id]/page.tsx (1)
3-12
: LGTM! Clean server component implementation.The component correctly handles async params, fetches chain data, and renders appropriately. The implementation follows Next.js server component patterns properly.
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/scale/deploy/_components/payment-frequency-selector.tsx (1)
4-47
: LGTM! Well-structured payment frequency selector.The component properly uses UI primitives, has clean TypeScript definitions, and follows the coding guidelines for component composition and styling.
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/scale/deploy/_components/checkout.tsx (1)
77-206
: LGTM! Well-structured checkout component.The component properly uses client-side hooks, manages state effectively, and composes UI components correctly. The responsive grid layout and step-by-step flow provide good UX.
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/scale/deploy/_components/order-summary.tsx (1)
8-191
: LGTM! Comprehensive order summary with proper pricing logic.The component handles complex pricing calculations correctly, uses proper currency formatting, and provides clear visual feedback for discounts and savings. The conditional rendering and UI composition are well implemented.
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/scale/deploy/_components/service-selector.tsx (1)
9-20
: Overall implementation follows coding guidelines well.The component properly:
- Uses typed props objects and exports named functions
- Leverages UI primitives (Checkbox, Badge, Label, UpsellBannerCard)
- Uses
cn
for class name merging- Follows design tokens and responsive patterns
- Implements proper spacing utilities
The service selection logic and upsell calculations are well-structured and the component provides good user experience with bundle discount incentives.
Also applies to: 22-104, 106-157
<Button asChild> | ||
<Link href={`/team/${params.team_slug}/~/infrastructure/deploy`}> | ||
Deploy Infrastructure | ||
<RocketIcon className="size-4 ml-2" /> | ||
</Link> | ||
</Button> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix the incorrect deployment route.
The link points to /team/${params.team_slug}/~/infrastructure/deploy
but based on the file structure, it should be /team/${params.team_slug}/~/scale/deploy
.
- <Link href={`/team/${params.team_slug}/~/infrastructure/deploy`}>
+ <Link href={`/team/${params.team_slug}/~/scale/deploy`}>
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
<Button asChild> | |
<Link href={`/team/${params.team_slug}/~/infrastructure/deploy`}> | |
Deploy Infrastructure | |
<RocketIcon className="size-4 ml-2" /> | |
</Link> | |
</Button> | |
<Button asChild> | |
<Link href={`/team/${params.team_slug}/~/scale/deploy`}> | |
Deploy Infrastructure | |
<RocketIcon className="size-4 ml-2" /> | |
</Link> | |
</Button> |
🤖 Prompt for AI Agents
In apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/scale/layout.tsx
between lines 40 and 45, the Link component's href incorrectly points to the
deployment route under "infrastructure" instead of "scale". Update the href to
`/team/${params.team_slug}/~/scale/deploy` to match the correct route based on
the file structure.
import { CheckIcon } from "lucide-react"; | ||
import { useMemo } from "react"; | ||
import { UpsellBannerCard } from "@/components/blocks/UpsellBannerCard"; | ||
import { Badge } from "@/components/ui/badge"; | ||
import { Checkbox } from "@/components/ui/checkbox"; | ||
import { Label } from "@/components/ui/label"; | ||
import { cn } from "@/lib/utils"; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Consider adding 'use client' directive for interactive component.
This component uses interactive elements (Checkbox, onClick handlers) and should likely include the 'use client' directive at the top since it's not server-only code.
+import 'use client';
import { CheckIcon } from "lucide-react";
Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/scale/deploy/_components/service-selector.tsx
at the top of the file (lines 1 to 8), add the 'use client' directive as the
very first line. This is necessary because the component uses interactive
elements like Checkbox and onClick handlers, indicating it should be treated as
a client component rather than a server-only one.
<Label | ||
className={cn( | ||
"hover:bg-accent/50 flex gap-6 rounded-lg border px-6 py-4 has-[[aria-checked=true]]:border-primary has-[[aria-checked=true]]:bg-primary/10 cursor-pointer items-center", | ||
props.service.required && "cursor-not-allowed", | ||
)} | ||
> | ||
<Checkbox | ||
checked={props.isSelected} | ||
onCheckedChange={() => props.onToggle(props.service)} | ||
/> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Improve accessibility for disabled required services.
The current implementation shows cursor-not-allowed
but doesn't actually disable the checkbox for required services, which could confuse users.
<Checkbox
checked={props.isSelected}
+ disabled={props.service.required}
onCheckedChange={() => props.onToggle(props.service)}
/>
Also consider updating the Label styling:
className={cn(
"hover:bg-accent/50 flex gap-6 rounded-lg border px-6 py-4 has-[[aria-checked=true]]:border-primary has-[[aria-checked=true]]:bg-primary/10 cursor-pointer items-center",
- props.service.required && "cursor-not-allowed",
+ props.service.required && "cursor-not-allowed opacity-60",
)}
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
<Label | |
className={cn( | |
"hover:bg-accent/50 flex gap-6 rounded-lg border px-6 py-4 has-[[aria-checked=true]]:border-primary has-[[aria-checked=true]]:bg-primary/10 cursor-pointer items-center", | |
props.service.required && "cursor-not-allowed", | |
)} | |
> | |
<Checkbox | |
checked={props.isSelected} | |
onCheckedChange={() => props.onToggle(props.service)} | |
/> | |
<Label | |
className={cn( | |
"hover:bg-accent/50 flex gap-6 rounded-lg border px-6 py-4 has-[[aria-checked=true]]:border-primary has-[[aria-checked=true]]:bg-primary/10 cursor-pointer items-center", | |
props.service.required && "cursor-not-allowed opacity-60", | |
)} | |
> | |
<Checkbox | |
checked={props.isSelected} | |
disabled={props.service.required} | |
onCheckedChange={() => props.onToggle(props.service)} | |
/> |
🤖 Prompt for AI Agents
In
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/scale/deploy/_components/service-selector.tsx
around lines 112 to 121, the checkbox for required services is not disabled,
causing accessibility issues despite showing a 'cursor-not-allowed' style. Fix
this by adding the 'disabled' attribute to the Checkbox component when the
service is required, and update the Label styling to visually indicate the
disabled state appropriately.
Add Infrastructure Section to Team Dashboard
This PR adds a new "Infrastructure" section to the team dashboard, allowing users to deploy and manage blockchain infrastructure services. Key changes include:
UpsellBannerCard
component to support onClick handlersdisableDeprecated
option toSingleNetworkSelector
componentThe infrastructure deployment UI includes detailed pricing information, bundle discounts, and a complete checkout experience for teams to easily deploy blockchain infrastructure services.
Summary by CodeRabbit
New Features
Improvements
Chores
PR-Codex overview
This PR primarily updates the
$schema
version in multiplebiome.json
files and introduces new components and features related to infrastructure management in the dashboard application, enhancing the user experience for deploying and managing services.Detailed summary
$schema
inbiome.json
files from version2.0.0
to2.0.4
across multiple applications and packages.InfrastructurePage
component inpage.tsx
.DeployInfrastructurePage
withInfrastructureCheckout
indeploy/page.tsx
.NetworkSelectors
to filter deprecated chains.PaymentFrequencySelector
andServiceSelector
components for service management.OrderSummary
to calculate and display pricing with discounts.InfrastructureCheckout
for selecting chains and services.