Skip to content

Conversation

@MananTank
Copy link
Member

@MananTank MananTank commented Sep 19, 2025


PR-Codex overview

This PR primarily focuses on refactoring the handling of widget properties across various components and introducing utility functions for code generation, enhancing readability and maintainability.

Detailed summary

  • Changed lockedWidget to widget in multiple components (CheckoutPlayground, TransactionPlayground, BuyPlayground, RightSection, LeftSection).
  • Introduced new utility functions in code-gen.ts for handling props and imports.
  • Updated CodeGen components to utilize the new widget prop.
  • Simplified import statements and code generation logic in CodeGen components.
  • Removed obsolete code related to stringifying props and imports.

✨ Ask PR-Codex anything about this PR by commenting with /codex {your question}

Summary by CodeRabbit

  • New Features

    • Code generator supports explicit widget selection (buy/checkout/transaction) and emits unified, props-driven snippets.
    • Generated snippets gain improved theming support (dark/light with overrides).
  • Refactor

    • Centralized code-gen utilities now power import and props formatting across playgrounds.
    • Widget selection removed from options and passed as an explicit prop.
    • Removed the “Sponsor gas fees” section from Payments UI.
  • Style

    • Code snippet formatting width increased for cleaner output.

@vercel
Copy link

vercel bot commented Sep 19, 2025

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

Project Deployment Preview Comments Updated (UTC)
docs-v2 Ready Ready Preview Comment Sep 19, 2025 10:22am
thirdweb_playground Ready Ready Preview Comment Sep 19, 2025 10:22am
thirdweb-www Ready Ready Preview Comment Sep 19, 2025 10:22am
2 Skipped Deployments
Project Deployment Preview Comments Updated (UTC)
nebula Skipped Skipped Sep 19, 2025 10:22am
wallet-ui Skipped Skipped Sep 19, 2025 10:22am

@vercel vercel bot temporarily deployed to Preview – nebula September 19, 2025 09:52 Inactive
@vercel vercel bot temporarily deployed to Preview – wallet-ui September 19, 2025 09:52 Inactive
@changeset-bot
Copy link

changeset-bot bot commented Sep 19, 2025

⚠️ No Changeset found

Latest commit: fddb791

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

This PR includes no changesets

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

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

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

@MananTank MananTank marked this pull request as ready for review September 19, 2025 09:52
@MananTank MananTank requested review from a team as code owners September 19, 2025 09:52
@github-actions github-actions bot added Playground Changes involving the Playground codebase. packages labels Sep 19, 2025
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Sep 19, 2025

Walkthrough

Adds a shared code-generation utility and updates multiple CodeGen components to use it. Moves widget selection out of payOptions into an explicit widget prop across payments playground components. Refactors import assembly, props emission, and theming logic for generated code. Adjusts Prettier print width for code formatting.

Changes

Cohort / File(s) Summary
Introduce code-gen utilities
apps/playground-web/src/lib/code-gen.ts
Adds stringifyProps, quotes, stringifyImports, and stringifyIgnoreFalsy to centralize code-generation string assembly.
Adopt centralized code-gen in generators
apps/playground-web/src/app/bridge/swap-widget/components/code.tsx, apps/playground-web/src/app/wallets/sign-in/components/CodeGen.tsx, apps/playground-web/src/app/payments/components/CodeGen.tsx
Replace manual import/prop string assembly with shared code-gen utilities; change imports map to module paths like "thirdweb/react", "thirdweb/chains", "thirdweb/wallets", and "thirdweb"; emit component via stringifyImports and stringifyProps; payments CodeGen now accepts widget and derives componentName, theme handling, and transaction props from that.
Widget prop refactor in payments playground
apps/playground-web/src/app/payments/components/LeftSection.tsx, apps/playground-web/src/app/payments/components/RightSection.tsx, apps/playground-web/src/app/payments/components/types.ts, apps/playground-web/src/app/payments/commerce/CheckoutPlayground.tsx, apps/playground-web/src/app/payments/fund-wallet/BuyPlayground.tsx, apps/playground-web/src/app/payments/transactions/TransactionPlayground.tsx
Remove payOptions.widget; rename lockedWidget prop to widget on Left/Right sections and update callers; gating logic now uses props.widget exclusively.
Adopt code-gen in bridge swap widget
apps/playground-web/src/app/bridge/swap-widget/components/code.tsx
Switch to quotes, stringifyImports, stringifyProps from lib/code-gen; update import groups to "thirdweb" and "thirdweb/react" for createThirdwebClient and SwapWidget; inline props via stringifyProps.
Adopt code-gen in wallets sign-in generator
apps/playground-web/src/app/wallets/sign-in/components/CodeGen.tsx
Replace hand-rolled import and prop formatting with stringifyImports, stringifyProps, stringifyIgnoreFalsy, and quotes; reorganize imports to module-path keys.
Formatting width adjustment
packages/ui/src/components/code/getCodeHtml.tsx
Change Prettier printWidth from 60 to 80 for code formatting output.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant UI as Playground UI
  participant LS as LeftSection
  participant RS as RightSection
  participant CG as CodeGen (payments)
  participant Lib as code-gen utils

  UI->>LS: render(widget, options)
  UI->>RS: render(widget, options)
  RS->>CG: render({ widget, options })
  CG->>Lib: stringifyImports(imports)
  CG->>Lib: stringifyProps(props)
  CG-->>RS: code string with imports + <Component {...props} />
  RS-->>UI: display Code tab
Loading
sequenceDiagram
  autonumber
  participant SW as SwapWidget CodeGen
  participant WS as Wallet Sign-In CodeGen
  participant Lib as code-gen utils

  SW->>Lib: stringifyImports + stringifyProps + quotes
  WS->>Lib: stringifyImports + stringifyProps + stringifyIgnoreFalsy + quotes
  Note over SW,WS: Both generators emit imports via a centralized imports map and produce final JSX with shared helpers
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested reviewers

  • joaquim-verges

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Description Check ⚠️ Warning The PR description contains the repository template commented out and a PR-Codex overview, but the required template sections ("title", "Notes for the reviewer", and "How to test") are not populated with actionable content. While the PR-Codex gives a helpful summary, it does not provide explicit testing steps or migration notes for breaking API changes such as removal of payOptions.widget and the lockedWidget→widget prop rename. Because the template's required sections and testing instructions are missing, the description does not meet the repository's template requirements. Please populate the PR template: add a one-line title following the repo convention, fill "Notes for the reviewer" calling out breaking API changes and key files, and add a "How to test" section with clear manual steps to run the playground, expected behavior for buy/checkout/transaction widgets, relevant unit/integration commands to run, and any migration steps consumers must take.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (1 passed)
Check name Status Explanation
Title Check ✅ Passed The title "Playground: Fix Pay components incomplete code gen, cleanup" is concise and accurately reflects the primary change set—fixes to payments-related playground components and cleanup of code-generation logic—as shown in the PR summary and file diffs. It is specific enough for a teammate scanning history and avoids noisy details. Consider aligning with the repository's title convention (e.g., adding a bracketed area prefix) but the current title is acceptable.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch 09-19-playground_fix_pay_components_incomplete_code_gen_cleanup

Warning

Review ran into problems

🔥 Problems

Errors were encountered while retrieving linked issues.

Errors (1)
  • TEAM-0000: Entity not found: Issue - Could not find referenced Issue.

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

Copy link
Member Author

MananTank commented Sep 19, 2025


How to use the Graphite Merge Queue

Add either label to this PR to merge it via the merge queue:

  • merge-queue - adds this PR to the back of the merge queue
  • hotfix - for urgent hot fixes, skip the queue and merge this PR next

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.

@codecov
Copy link

codecov bot commented Sep 19, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 56.34%. Comparing base (1732e63) to head (fddb791).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #8078   +/-   ##
=======================================
  Coverage   56.34%   56.34%           
=======================================
  Files         906      906           
  Lines       59171    59171           
  Branches     4175     4175           
=======================================
  Hits        33342    33342           
  Misses      25723    25723           
  Partials      106      106           
Flag Coverage Δ
packages 56.34% <ø> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@github-actions
Copy link
Contributor

github-actions bot commented Sep 19, 2025

size-limit report 📦

Path Size Loading time (3g) Running time (snapdragon) Total time
thirdweb (esm) 63.96 KB (0%) 1.3 s (0%) 356 ms (+117.44% 🔺) 1.7 s
thirdweb (cjs) 361.44 KB (0%) 7.3 s (0%) 1.8 s (+3.67% 🔺) 9 s
thirdweb (minimal + tree-shaking) 5.73 KB (0%) 115 ms (0%) 97 ms (+916.43% 🔺) 212 ms
thirdweb/chains (tree-shaking) 526 B (0%) 11 ms (0%) 57 ms (+969.78% 🔺) 67 ms
thirdweb/react (minimal + tree-shaking) 19.14 KB (0%) 383 ms (0%) 106 ms (+715.68% 🔺) 489 ms

@graphite-app
Copy link
Contributor

graphite-app bot commented Sep 19, 2025

Merge activity

<!--

## title your PR with this format: "[SDK/Dashboard/Portal] Feature/Fix: Concise title for the changes"

If you did not copy the branch name from Linear, paste the issue tag here (format is TEAM-0000):

## Notes for the reviewer

Anything important to call out? Be sure to also clarify these in your comments.

## How to test

Unit tests, playground, etc.

-->

<!-- start pr-codex -->

---

## PR-Codex overview
This PR primarily focuses on refactoring the payment components in the `playground-web` application, updating widget properties and enhancing code generation functions for better modularity and readability.

### Detailed summary
- Changed `lockedWidget` to `widget` in multiple components: `CheckoutPlayground`, `TransactionPlayground`, `BuyPlayground`, `LeftSection`, and `RightSection`.
- Added new functions in `code-gen.ts` for `stringifyProps`, `quotes`, `stringifyImports`, and `stringifyIgnoreFalsy`.
- Updated `CodeGen` components to accept `widget` as a prop.
- Refactored `getCode` function in `CodeGen` to use the new `widget` parameter.
- Removed unused imports and functions from `CodeGen` and `LeftSection`.

> ✨ Ask PR-Codex anything about this PR by commenting with `/codex {your question}`

<!-- end pr-codex -->

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

## Summary by CodeRabbit

- New Features
  - Code generator now supports explicit widget selection (buy, checkout, transaction) with unified, props-driven output.
  - Enhanced theming in generated snippets, including dark/light themes with overrides.

- Refactor
  - Migrated playground code generation to centralized utilities for imports and props.
  - Simplified widget configuration by removing it from options and passing it as a direct prop.
  - Streamlined Payments UI; removed “Sponsor gas fees” section.

- Style
  - Improved code snippet formatting with wider line wrap for cleaner display.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
@graphite-app graphite-app bot merged commit fddb791 into main Sep 19, 2025
24 checks passed
@graphite-app graphite-app bot deleted the 09-19-playground_fix_pay_components_incomplete_code_gen_cleanup branch September 19, 2025 10:22
@vercel vercel bot temporarily deployed to Production – wallet-ui September 19, 2025 10:23 Inactive
@vercel vercel bot temporarily deployed to Production – nebula September 19, 2025 10:23 Inactive
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

Caution

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

⚠️ Outside diff range comments (1)
apps/playground-web/src/app/wallets/sign-in/components/CodeGen.tsx (1)

108-116: Bug: wrong casing and negation flips showThirdwebBranding default.

Using ShowThirdwebBranding (capital S) and ! means the snippet will often hide branding unintentionally.

Apply this diff:

-      showThirdwebBranding: !connectOptions.ShowThirdwebBranding
-        ? false
-        : undefined,
+      showThirdwebBranding:
+        connectOptions.showThirdwebBranding === false ? false : undefined,
🧹 Nitpick comments (15)
apps/playground-web/src/app/bridge/swap-widget/components/code.tsx (1)

30-34: Import map + inline prop emission LGTM.

  • Module split into "thirdweb" and "thirdweb/react" is accurate.
  • Using stringifyImports and stringifyProps keeps output predictable.

If imports ever grow, consider ensuring deterministic ordering/dedup in the library-level stringifyImports to avoid cosmetic diffs across runs.

Also applies to: 74-74, 82-82

apps/playground-web/src/app/payments/components/RightSection.tsx (1)

114-119: Avoid empty-string fallback for transaction “to” address.

claimTo with to: "" risks invalid address errors. Prefer the zero address or gate until account exists.

Apply one of:

-          to: account?.address || "",
+          to: account?.address || "0x0000000000000000000000000000000000000000",

or render TransactionWidget only when account?.address is present.

apps/playground-web/src/lib/code-gen.ts (4)

12-15: Stable prop order for cleaner diffs.

Sort props alphabetically before joining to keep generated output stable:

-  return Object.entries(_props)
-    .map(([key, value]) => `${key}={${value}}`)
-    .join("\n");
+  return Object.entries(_props)
+    .sort(([a], [b]) => a.localeCompare(b))
+    .map(([key, value]) => `${key}={${value}}`)
+    .join("\n");

17-19: Escape strings via JSON.stringify.

Protects against embedded quotes/newlines without changing call sites.

-export function quotes(value: string) {
-  return `"${value}"`;
-}
+export function quotes(value: string) {
+  return JSON.stringify(value);
+}

21-29: Deterministic, de-duplicated imports.

Prevents import churn across runs and envs.

-export function stringifyImports(imports: Record<string, string[]>) {
-  let code = "";
-  for (const key in imports) {
-    if (imports[key].length > 0) {
-      code += `import { ${imports[key].join(", ")} } from "${key}";\n`;
-    }
-  }
-  return code;
-}
+export function stringifyImports(imports: Record<string, string[]>) {
+  let code = "";
+  for (const key of Object.keys(imports).sort()) {
+    const names = Array.from(new Set(imports[key])).sort();
+    if (names.length > 0) {
+      code += `import { ${names.join(", ")} } from "${key}";\n`;
+    }
+  }
+  return code;
+}

42-43: Prettier-friendly JSON for object literals.

Indented output reads better in the Code tab.

-  return JSON.stringify(_value);
+  return JSON.stringify(_value, null, 2);
apps/playground-web/src/app/payments/components/LeftSection.tsx (2)

125-155: Gating by props.widget is correct; UI logic reads clearly.

Buy/Checkout shared selectors and mode-specific blocks are cleanly separated.

The “Payment Methods” checkbox group is duplicated in Buy/Checkout blocks. Consider extracting a tiny PaymentMethods section or a toggle helper to reduce repetition.

Also applies to: 159-237, 241-339, 343-354


347-351: Minor copy tweak: “an ERC1155”.

Grammar nit in user-facing text.

-                    This demo uses a ERC1155 NFT claim transaction. Check the
+                    This demo uses an ERC1155 NFT claim transaction. Check the
apps/playground-web/src/app/wallets/sign-in/components/CodeGen.tsx (2)

17-23: Add explicit return types per TS guidelines.

Tighten types for clarity and editor tooling.

-function CodeLoading() {
+function CodeLoading(): JSX.Element {
   ...
 }
 
-export function CodeGen(props: { connectOptions: ConnectPlaygroundOptions }) {
+export function CodeGen(
+  props: { connectOptions: ConnectPlaygroundOptions },
+): JSX.Element {
   ...
 }
 
-function getCode(connectOptions: ConnectPlaygroundOptions) {
+function getCode(connectOptions: ConnectPlaygroundOptions): string {
   ...
 }

Also applies to: 25-38, 40-41


11-15: Optional: prefer next/dynamic over React.lazy in app router.

next/dynamic avoids server-component pitfalls and lets you set ssr: false and a built-in loading fallback.

-const CodeClient = lazy(() =>
-  import("../../../../components/code/code.client").then((m) => ({
-    default: m.CodeClient,
-  })),
-);
+import dynamic from "next/dynamic";
+const CodeClient = dynamic(
+  () => import("../../../../components/code/code.client").then((m) => m.CodeClient),
+  { ssr: false, loading: () => <CodeLoading /> },
+);
apps/playground-web/src/app/payments/components/CodeGen.tsx (5)

41-44: Annotate return type for getCode.

-function getCode(
+function getCode(
   widget: "buy" | "checkout" | "transaction",
   options: BridgeComponentsPlaygroundOptions,
-)
+) : string
 {

45-53: Prefer exhaustive switch for componentName mapping.

Avoid an empty-string fallback; enforce compile-time exhaustiveness.

-  const componentName =
-    widget === "buy"
-      ? "BuyWidget"
-      : widget === "checkout"
-        ? "CheckoutWidget"
-        : widget === "transaction"
-          ? "TransactionWidget"
-          : "";
+  const componentName = (() => {
+    switch (widget) {
+      case "buy":
+        return "BuyWidget";
+      case "checkout":
+        return "CheckoutWidget";
+      case "transaction":
+        return "TransactionWidget";
+      default: {
+        const _exhaustive: never = widget;
+        return _exhaustive;
+      }
+    }
+  })();

55-59: Unused import in generated snippet.

"thirdweb/wallets": ["createWallet"] isn’t used anywhere in the emitted code; it will produce dead imports.

   const imports = {
     "thirdweb/chains": [] as string[],
     "thirdweb/react": [componentName] as string[],
     thirdweb: ["createThirdwebClient", "defineChain"] as string[],
-    "thirdweb/wallets": ["createWallet"] as string[],
   };

16-23: Add explicit return types to exported/local functions.

-function CodeLoading() {
+function CodeLoading(): JSX.Element {
   ...
 }
 
-export function CodeGen(props: {
-  widget: "buy" | "checkout" | "transaction";
-  options: BridgeComponentsPlaygroundOptions;
-}) {
+export function CodeGen(props: {
+  widget: "buy" | "checkout" | "transaction";
+  options: BridgeComponentsPlaygroundOptions;
+}): JSX.Element {
   ...
 }
 
-function getCode(
+function getCode(
   widget: "buy" | "checkout" | "transaction",
   options: BridgeComponentsPlaygroundOptions,
-)
+) : string
 {

Also applies to: 24-27, 41-44


130-142: Optional: extract getCode to shared lib to reduce duplication.

Both CodeGen files follow near‑identical patterns; consider moving getCode templates to apps/playground-web/src/lib/code-gen.* with widget‑specific hooks.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 1732e63 and fddb791.

📒 Files selected for processing (11)
  • apps/playground-web/src/app/bridge/swap-widget/components/code.tsx (4 hunks)
  • apps/playground-web/src/app/payments/commerce/CheckoutPlayground.tsx (1 hunks)
  • apps/playground-web/src/app/payments/components/CodeGen.tsx (2 hunks)
  • apps/playground-web/src/app/payments/components/LeftSection.tsx (6 hunks)
  • apps/playground-web/src/app/payments/components/RightSection.tsx (5 hunks)
  • apps/playground-web/src/app/payments/components/types.ts (0 hunks)
  • apps/playground-web/src/app/payments/fund-wallet/BuyPlayground.tsx (1 hunks)
  • apps/playground-web/src/app/payments/transactions/TransactionPlayground.tsx (1 hunks)
  • apps/playground-web/src/app/wallets/sign-in/components/CodeGen.tsx (6 hunks)
  • apps/playground-web/src/lib/code-gen.ts (1 hunks)
  • packages/ui/src/components/code/getCodeHtml.tsx (1 hunks)
💤 Files with no reviewable changes (1)
  • apps/playground-web/src/app/payments/components/types.ts
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: Write idiomatic TypeScript with explicit function declarations and return types
Limit each file to one stateless, single-responsibility function for clarity
Re-use shared types from @/types or local types.ts barrels
Prefer type aliases over interface except for nominal shapes
Avoid any and unknown unless unavoidable; narrow generics when possible
Choose composition over inheritance; leverage utility types (Partial, Pick, etc.)
Comment only ambiguous logic; avoid restating TypeScript in prose

**/*.{ts,tsx}: Use explicit function declarations and explicit return types in TypeScript
Limit each file to one stateless, single‑responsibility function
Re‑use shared types from @/types where applicable
Prefer type aliases over interface except for nominal shapes
Avoid any and unknown unless unavoidable; narrow generics when possible
Prefer composition over inheritance; use utility types (Partial, Pick, etc.)
Lazy‑import optional features and avoid top‑level side‑effects to reduce bundle size

Files:

  • apps/playground-web/src/app/payments/fund-wallet/BuyPlayground.tsx
  • apps/playground-web/src/app/wallets/sign-in/components/CodeGen.tsx
  • apps/playground-web/src/app/payments/commerce/CheckoutPlayground.tsx
  • apps/playground-web/src/lib/code-gen.ts
  • apps/playground-web/src/app/payments/components/CodeGen.tsx
  • packages/ui/src/components/code/getCodeHtml.tsx
  • apps/playground-web/src/app/payments/transactions/TransactionPlayground.tsx
  • apps/playground-web/src/app/payments/components/LeftSection.tsx
  • apps/playground-web/src/app/bridge/swap-widget/components/code.tsx
  • apps/playground-web/src/app/payments/components/RightSection.tsx
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Load heavy dependencies inside async paths to keep initial bundle lean (lazy loading)

Files:

  • apps/playground-web/src/app/payments/fund-wallet/BuyPlayground.tsx
  • apps/playground-web/src/app/wallets/sign-in/components/CodeGen.tsx
  • apps/playground-web/src/app/payments/commerce/CheckoutPlayground.tsx
  • apps/playground-web/src/lib/code-gen.ts
  • apps/playground-web/src/app/payments/components/CodeGen.tsx
  • packages/ui/src/components/code/getCodeHtml.tsx
  • apps/playground-web/src/app/payments/transactions/TransactionPlayground.tsx
  • apps/playground-web/src/app/payments/components/LeftSection.tsx
  • apps/playground-web/src/app/bridge/swap-widget/components/code.tsx
  • apps/playground-web/src/app/payments/components/RightSection.tsx
apps/{dashboard,playground-web}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

apps/{dashboard,playground-web}/**/*.{ts,tsx}: Import UI primitives from @/components/ui/* (Button, Input, Select, Tabs, Card, Sidebar, Badge, Separator) in dashboard and playground apps
Use NavLink for internal navigation with automatic active states in dashboard and playground apps
Use Tailwind CSS only – no inline styles or CSS modules
Use cn() from @/lib/utils for conditional class logic
Use design system tokens (e.g., bg-card, border-border, text-muted-foreground)
Server Components (Node edge): Start files with import "server-only";
Client Components (browser): Begin files with 'use client';
Always call getAuthToken() to retrieve JWT from cookies on server side
Use Authorization: Bearer header – never embed tokens in URLs
Return typed results (e.g., Project[], User[]) – avoid any
Wrap client-side data fetching calls in React Query (@tanstack/react-query)
Use descriptive, stable queryKeys for React Query cache hits
Configure staleTime/cacheTime in React Query based on freshness (default ≥ 60s)
Keep tokens secret via internal API routes or server actions
Never import posthog-js in server components

Files:

  • apps/playground-web/src/app/payments/fund-wallet/BuyPlayground.tsx
  • apps/playground-web/src/app/wallets/sign-in/components/CodeGen.tsx
  • apps/playground-web/src/app/payments/commerce/CheckoutPlayground.tsx
  • apps/playground-web/src/lib/code-gen.ts
  • apps/playground-web/src/app/payments/components/CodeGen.tsx
  • apps/playground-web/src/app/payments/transactions/TransactionPlayground.tsx
  • apps/playground-web/src/app/payments/components/LeftSection.tsx
  • apps/playground-web/src/app/bridge/swap-widget/components/code.tsx
  • apps/playground-web/src/app/payments/components/RightSection.tsx
🧠 Learnings (10)
📚 Learning: 2025-09-18T20:09:57.064Z
Learnt from: MananTank
PR: thirdweb-dev/js#8069
File: apps/playground-web/src/app/bridge/swap-widget/components/types.ts:3-12
Timestamp: 2025-09-18T20:09:57.064Z
Learning: The SwapWidgetPlaygroundOptions type should not include persistTokenSelections - the playground intentionally hardcodes persistTokenSelections={false} and doesn't expose it as a configurable option to users.

Applied to files:

  • apps/playground-web/src/app/payments/fund-wallet/BuyPlayground.tsx
📚 Learning: 2025-08-29T15:37:38.513Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: AGENTS.md:0-0
Timestamp: 2025-08-29T15:37:38.513Z
Learning: Applies to **/*.{ts,tsx} : Lazy‑import optional features and avoid top‑level side‑effects to reduce bundle size

Applied to files:

  • apps/playground-web/src/app/wallets/sign-in/components/CodeGen.tsx
📚 Learning: 2025-05-30T17:14:25.332Z
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.

Applied to files:

  • apps/playground-web/src/app/wallets/sign-in/components/CodeGen.tsx
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/components/*.client.tsx : Client components must start with `'use client';` before imports.

Applied to files:

  • apps/playground-web/src/app/wallets/sign-in/components/CodeGen.tsx
📚 Learning: 2025-08-29T15:37:38.513Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: AGENTS.md:0-0
Timestamp: 2025-08-29T15:37:38.513Z
Learning: Applies to apps/{dashboard,playground}/**/*.{ts,tsx} : Client Components must start with `'use client'`; handle interactivity with hooks and browser APIs

Applied to files:

  • apps/playground-web/src/app/payments/components/CodeGen.tsx
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/*client.tsx : Interactive UI that relies on hooks (`useState`, `useEffect`, React Query, wallet hooks).

Applied to files:

  • apps/playground-web/src/app/payments/components/LeftSection.tsx
📚 Learning: 2025-07-31T16:17:42.753Z
Learnt from: MananTank
PR: thirdweb-dev/js#7768
File: apps/playground-web/src/app/navLinks.ts:1-1
Timestamp: 2025-07-31T16:17:42.753Z
Learning: Configuration files that import and reference React components (like icon components from lucide-react) need the "use client" directive, even if they primarily export static data, because the referenced components need to be executed in a client context when used by other client components.

Applied to files:

  • apps/playground-web/src/app/payments/components/LeftSection.tsx
📚 Learning: 2025-07-07T21:21:47.488Z
Learnt from: saminacodes
PR: thirdweb-dev/js#7543
File: apps/portal/src/app/pay/page.mdx:4-4
Timestamp: 2025-07-07T21:21:47.488Z
Learning: In the thirdweb-dev/js repository, lucide-react icons must be imported with the "Icon" suffix (e.g., ExternalLinkIcon, RocketIcon) as required by the new linting rule, contrary to the typical lucide-react convention of importing without the suffix.

Applied to files:

  • apps/playground-web/src/app/payments/components/LeftSection.tsx
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/*.{tsx,jsx} : Icons come from `lucide-react` or the project-specific `…/icons` exports – never embed raw SVG.

Applied to files:

  • apps/playground-web/src/app/payments/components/LeftSection.tsx
📚 Learning: 2025-09-17T11:14:35.659Z
Learnt from: MananTank
PR: thirdweb-dev/js#8044
File: packages/thirdweb/src/react/web/ui/Bridge/swap-widget/swap-ui.tsx:919-930
Timestamp: 2025-09-17T11:14:35.659Z
Learning: In the thirdweb codebase, useCustomTheme() hook can be used inside styled-components callbacks, contrary to the general React Rules of Hooks. This is a valid pattern in their implementation.

Applied to files:

  • apps/playground-web/src/app/bridge/swap-widget/components/code.tsx
🧬 Code graph analysis (7)
apps/playground-web/src/app/payments/fund-wallet/BuyPlayground.tsx (2)
apps/playground-web/src/app/payments/components/LeftSection.tsx (1)
  • LeftSection (21-492)
apps/playground-web/src/app/payments/components/RightSection.tsx (1)
  • RightSection (29-162)
apps/playground-web/src/app/wallets/sign-in/components/CodeGen.tsx (1)
apps/playground-web/src/lib/code-gen.ts (2)
  • quotes (17-19)
  • stringifyImports (21-29)
apps/playground-web/src/app/payments/commerce/CheckoutPlayground.tsx (1)
apps/playground-web/src/app/payments/components/RightSection.tsx (1)
  • RightSection (29-162)
apps/playground-web/src/app/payments/components/CodeGen.tsx (2)
apps/playground-web/src/app/payments/components/types.ts (1)
  • BridgeComponentsPlaygroundOptions (33-61)
apps/playground-web/src/lib/code-gen.ts (3)
  • quotes (17-19)
  • stringifyImports (21-29)
  • stringifyProps (1-15)
apps/playground-web/src/app/payments/transactions/TransactionPlayground.tsx (1)
apps/playground-web/src/app/payments/components/RightSection.tsx (1)
  • RightSection (29-162)
apps/playground-web/src/app/bridge/swap-widget/components/code.tsx (1)
apps/playground-web/src/lib/code-gen.ts (2)
  • stringifyImports (21-29)
  • stringifyProps (1-15)
apps/playground-web/src/app/payments/components/RightSection.tsx (1)
apps/playground-web/src/app/payments/components/CodeGen.tsx (1)
  • CodeGen (24-39)
🔇 Additional comments (17)
packages/ui/src/components/code/getCodeHtml.tsx (1)

28-28: Wider Prettier wrap looks good.

printWidth: 80 is fine and should improve readability in the preview.

Please sanity-check that long prop lists in Code tabs don’t overflow their container at common widths (e.g., 360–768px).

apps/playground-web/src/app/payments/transactions/TransactionPlayground.tsx (1)

39-45: Good migration to widget prop.

Usage is consistent with the new RightSection/LeftSection contract.

apps/playground-web/src/app/bridge/swap-widget/components/code.tsx (1)

3-3: Centralizing code-gen helpers is the right call.

Importing quotes/stringifyImports/stringifyProps reduces duplication and keeps formatting consistent across generators.

apps/playground-web/src/app/payments/components/RightSection.tsx (1)

32-33: Widget-driven rendering is clean and explicit.

Direct branching on props.widget and passing it to CodeGen removes hidden coupling.

Also applies to: 56-75, 77-103, 105-127, 156-158

apps/playground-web/src/app/payments/commerce/CheckoutPlayground.tsx (1)

39-45: Consistent widget prop usage.

Matches the new Left/Right section contracts; defaults are intact.

apps/playground-web/src/app/payments/fund-wallet/BuyPlayground.tsx (1)

38-41: Prop rename to widget is correct and consistent — verification incomplete

Change passing widget="buy" looks correct; automated search errored (rg PCRE). Run the fixed check below and paste the output.

#!/bin/bash
set -euo pipefail
root="apps/playground-web/src/app"
echo "Scanning $root for LeftSection/RightSection without widget, lockedWidget, and payOptions.widget..."

python3 - <<'PY'
import os
root="apps/playground-web/src/app"
exts=('.tsx','.ts','.jsx','.js','.md','.mdx')
tags=("LeftSection","RightSection")
missing=[]
locked=[]
payopts=[]
for dirpath,dirnames,filenames in os.walk(root):
    for fname in filenames:
        if not fname.endswith(exts):
            continue
        path=os.path.join(dirpath,fname)
        try:
            txt=open(path,encoding='utf-8',errors='ignore').read()
        except Exception:
            continue
        for tag in tags:
            start=0
            while True:
                idx=txt.find(f"<{tag}", start)
                if idx==-1:
                    break
                gt=txt.find(">", idx)
                if gt==-1:
                    break
                opening=txt[idx:gt+1]
                if "widget=" not in opening and "widget =" not in opening:
                    lineno = txt.count("\n",0,idx)+1
                    missing.append(f"{path}:{lineno}: {tag} opening missing widget -> {opening.strip()[:200]}")
                start=gt+1
        if "lockedWidget" in txt:
            for i,line in enumerate(txt.splitlines(),1):
                if "lockedWidget" in line:
                    locked.append(f"{path}:{i}: {line.strip()}")
        if "payOptions.widget" in txt:
            for i,line in enumerate(txt.splitlines(),1):
                if "payOptions.widget" in line:
                    payopts.append(f"{path}:{i}: {line.strip()}")
print("Missing widget attributes for LeftSection/RightSection:")
print("\\n".join(missing) if missing else "None found.")
print("\\nlockedWidget occurrences:")
print("\\n".join(locked) if locked else "None found.")
print("\\npayOptions.widget occurrences:")
print("\\n".join(payopts) if payopts else "None found.")
PY
apps/playground-web/src/app/wallets/sign-in/components/CodeGen.tsx (6)

2-7: Good move: centralized code‑gen helpers.

Switching to quotes/stringifyProps/stringifyImports/stringifyIgnoreFalsy from "@/lib/code-gen" reduces duplication and keeps output consistent.


43-47: Imports map re-org looks correct.

New module paths for chains/react/wallets align with the broader refactor.


58-66: Conditional wallet imports — LGTM.

Importing inAppWallet/createWallet only when used keeps snippets minimal.


77-88: Theme import logic — LGTM; verify default for dark theme.

Emitting lightTheme only when needed and falling back to "light" is fine. For dark theme without overrides, you omit the prop; confirm the widget defaults to dark so the preview matches the UI controls.


93-95: Correct: add ethereum only when AA is enabled.


127-127: Imports emission via stringifyImports — nice.

Keeps ordering stable and skips empty groups.

apps/playground-web/src/app/payments/components/CodeGen.tsx (5)

3-7: Good: unified code‑gen helpers.


24-27: API change to accept explicit widget — LGTM.

Clearer than inferring from options; narrows code paths.


61-81: Theme logic — verify defaults.

For dark with no overrides you omit theme, while for light you emit "light". Confirm the widgets default to dark so UI and code match.


131-139: Shared imports/props emission — LGTM.

stringifyImports + stringifyProps produces clean, copy‑pastable snippets.


93-128: Emit a Chain object — don't pass only an ID to defineChain

Widgets expect a Chain object: use a predefined chain export (e.g., import { sepolia } from "thirdweb/chains") or call defineChain({ id: , rpc: "...", ... }) (import { defineChain } from "thirdweb/chains"). File apps/playground-web/src/app/payments/components/CodeGen.tsx (lines 93–128) currently emits defineChain(${options.payOptions.buyTokenChain.id}) — update the codegen to output either the chain constant for built‑in chains or defineChain({ id: ..., ... }) for custom chains.

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

@@ -1,5 +1,10 @@
import { lazy, Suspense } from "react";
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Add 'use client' — this file uses React.lazy/Suspense patterns.

Mark as a Client Component to avoid Next.js app router errors.

+ 'use client';
  import { lazy, Suspense } from "react";
📝 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.

Suggested change
import { lazy, Suspense } from "react";
'use client';
import { lazy, Suspense } from "react";
🤖 Prompt for AI Agents
In apps/playground-web/src/app/payments/components/CodeGen.tsx around line 1,
the file uses React.lazy and Suspense and must be marked as a Next.js Client
Component; add the directive 'use client' as the very first line in the file
(before any imports) so the app router treats it as a client component and avoid
server-side rendering errors, then save and run/typecheck to verify no other
client-only hooks are used.

Comment on lines +83 to +91
const transaction =
widget === "transaction"
? `claimTo({
contract: nftContract,
quantity: 1n,
to: account?.address || "",
tokenId: 2n,
})`
: undefined;
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Broken snippet: references undefined vars (nftContract, account).

The generated transaction value will not compile as-is. Gate it on provided data or emit a self-contained example with required imports/variables.

Minimal safe fix using the existing options field:

-  const transaction =
-    widget === "transaction"
-      ? `claimTo({
-contract: nftContract,
-quantity: 1n,
-to: account?.address || "",
-tokenId: 2n,
-})`
-      : undefined;
+  const transaction =
+    widget === "transaction" && options.payOptions.transactionData
+      ? options.payOptions.transactionData
+      : undefined;
📝 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.

Suggested change
const transaction =
widget === "transaction"
? `claimTo({
contract: nftContract,
quantity: 1n,
to: account?.address || "",
tokenId: 2n,
})`
: undefined;
const transaction =
widget === "transaction" && options.payOptions.transactionData
? options.payOptions.transactionData
: undefined;
🤖 Prompt for AI Agents
In apps/playground-web/src/app/payments/components/CodeGen.tsx around lines 83
to 91, the generated transaction snippet references undefined variables
(nftContract, account) and will not compile; update the code to only emit the
claimTo(...) snippet when the required values exist by gating on provided data
(e.g., options.nftContract and options.account?.address) or replace it with a
self-contained example using local placeholders and required imports; the
minimal safe fix is to conditionally set transaction to undefined unless
options.nftContract and options.account?.address are present, otherwise produce
a complete example string that defines necessary variables/imports so the
snippet compiles.

Comment on lines +156 to +158
{previewTab === "code" && (
<CodeGen widget={props.widget} options={props.options} />
)}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

🧩 Analysis chain

Verify all CodeGen usages pass widget.

Prevents regressions after the prop rename.


🏁 Script executed:

#!/bin/bash
set -euo pipefail
echo "CodeGen usages missing widget prop:"
rg -nP '<CodeGen\b(?![^>]*\bwidget=)' apps | sed -n '1,200p' || true

Length of output: 119


🏁 Script executed:

#!/bin/bash
set -euo pipefail
echo "Searching for <CodeGen ...> usages under apps/ and checking if the opening tag contains 'widget=' (captures +40 lines after match):"
matches=$(rg -nS '<CodeGen' apps || true)
if [[ -z "$matches" ]]; then
  echo "No <CodeGen ...> occurrences found under apps/."
  exit 0
fi
echo "Found occurrences:"
echo "$matches"
echo
echo "Checking each occurrence for 'widget' prop in nearby lines:"
missing_count=0
while IFS=: read -r file line rest; do
  start=$(( line > 3 ? line-2 : 1 ))
  snippet=$(sed -n "${start},$((line+40))p" "$file" || true)
  if ! printf '%s' "$snippet" | rg -q 'widget\s*='; then
    missing_count=$((missing_count+1))
    echo "---- Missing widget prop: $file:$line ----"
    printf '%s\n' "$snippet"
    echo "-------------------------------------------"
    echo
  fi
done <<< "$matches"
if [[ "$missing_count" -eq 0 ]]; then
  echo "No CodeGen usages missing 'widget' prop found."
else
  echo "Total occurrences missing 'widget' prop: $missing_count"
fi

Length of output: 819


Add missing widget prop to CodeGen usages

Two CodeGen usages do not pass the widget prop — update them to include widget to avoid regressions after the prop rename:

  • apps/playground-web/src/app/wallets/sign-in/button/RightSection.tsx:227
    Current: {previewTab === "code" && }
    Change: add widget (e.g. )

  • apps/playground-web/src/app/bridge/swap-widget/components/right-section.tsx:67
    Current: {previewTab === "code" && }
    Change: add widget (e.g. )

Note: apps/playground-web/src/app/payments/components/RightSection.tsx:157 already passes widget.

🤖 Prompt for AI Agents
In apps/playground-web/src/app/payments/components/RightSection.tsx (lines
156-158), apps/playground-web/src/app/wallets/sign-in/button/RightSection.tsx
(line 227), and
apps/playground-web/src/app/bridge/swap-widget/components/right-section.tsx
(line 67), the CodeGen component usages must include the renamed widget prop;
update the two missing usages to pass the widget from the component's props
while keeping their existing props (e.g. add the widget prop sourced from
props.widget to the CodeGen calls that currently only pass connectOptions or
options).

@@ -1,4 +1,10 @@
import { lazy, Suspense } from "react";
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Add 'use client' — React.lazy requires a Client Component in Next.js app router.

This file uses React.lazy/Suspense; without 'use client' it will error at runtime/compile-time.

Apply this diff at the very top:

+ 'use client';
  import { lazy, Suspense } from "react";
📝 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.

Suggested change
import { lazy, Suspense } from "react";
'use client';
import { lazy, Suspense } from "react";
🤖 Prompt for AI Agents
In apps/playground-web/src/app/wallets/sign-in/components/CodeGen.tsx around
line 1, this file uses React.lazy and Suspense which require a Next.js Client
Component; add the directive 'use client' as the very first line of the file
(above all imports) so the file is treated as a Client Component and avoids
runtime/compile errors.

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

Labels

packages Playground Changes involving the Playground codebase.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants