diff --git a/.github/workflows/test-registry-installations.yml b/.github/workflows/test-registry-installations.yml deleted file mode 100644 index dd3061b6..00000000 --- a/.github/workflows/test-registry-installations.yml +++ /dev/null @@ -1,98 +0,0 @@ -name: Test Registry Installations - -on: - push: - branches: [main] - paths: - - 'registry/**' - - 'registry.json' - - 'public/r/**' - pull_request: - branches: [main] - paths: - - 'registry/**' - - 'registry.json' - - 'public/r/**' - workflow_dispatch: - -jobs: - test-installations: - runs-on: ubuntu-latest - - steps: - - name: Checkout registry repo - uses: actions/checkout@v4 - with: - path: registry-repo - - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - node-version: '20' - - - name: Install pnpm - uses: pnpm/action-setup@v2 - with: - version: 8 - - - name: Create test Next.js app - run: | - echo -e "Y\nNo\n" | npx create-next-app@latest test-app --typescript --tailwind --app --no-src-dir --import-alias "@/*" --use-pnpm --no-install --no-eslint - cd test-app - pnpm install - echo -e "Y\n\n\n\n\n\n\n\n" | pnpm dlx shadcn@latest init - - - name: Test component installations - run: | - cd test-app - - # Extract component names from registry.json - COMPONENTS=$(node -e " - const registry = require('../registry-repo/registry.json'); - const components = registry.items.map(item => item.name); - console.log(components.join(' ')); - ") - - echo "Testing installation of components: $COMPONENTS" - - # Track failed installations - FAILED="" - SUCCESS_COUNT=0 - TOTAL_COUNT=0 - - # Test each component installation - for component in $COMPONENTS; do - echo "" - echo "Testing: $component" - echo "----------------------------------------" - - TOTAL_COUNT=$((TOTAL_COUNT + 1)) - - # Run shadcn add command with timeout - if timeout 60 pnpm dlx shadcn@latest add "https://hellno-mini-app-ui.vercel.app/r/${component}.json" --yes --overwrite; then - echo "✅ $component installed successfully" - SUCCESS_COUNT=$((SUCCESS_COUNT + 1)) - else - echo "❌ $component installation failed" - FAILED="$FAILED $component" - fi - done - - # Report results - echo "" - echo "========================================" - echo "Installation Summary:" - echo "✅ Successful: $SUCCESS_COUNT/$TOTAL_COUNT" - if [ -z "$FAILED" ]; then - echo "🎉 All components installed successfully!" - else - echo "❌ Failed installations:$FAILED" - exit 1 - fi - - - name: Check installed files - if: success() - run: | - cd test-app - echo "Installed component files:" - find components lib hooks -type f -name "*.tsx" -o -name "*.ts" 2>/dev/null | sort || true \ No newline at end of file diff --git a/.gitignore b/.gitignore index 6436d77f..47420862 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ # dependencies /node_modules +**/node_modules /.pnp .pnp.* .yarn/* @@ -40,3 +41,7 @@ yarn-error.log* *.tsbuildinfo next-env.d.ts .aider* +/test-shadcn-install +/tmp-test-* +/test-minimal-* +/test-registry-* diff --git a/CLAUDE.md b/CLAUDE.md index c73aa5f4..0571f3c0 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -185,7 +185,7 @@ The repository uses Husky to run `pnpm lint` and `pnpm registry:build` before ea **Key Technologies:** - Next.js 15 with React 19 -- Farcaster Frame SDK (@farcaster/frame-sdk, @farcaster/frame-core) +- Farcaster MiniApp SDK (@farcaster/miniapp-sdk, @farcaster/miniapp-core) - Daimo Pay integration (@daimo/pay, @daimo/contract) - Wagmi for Ethereum interaction - Tailwind CSS for styling @@ -199,8 +199,9 @@ Components can depend on other registry items via `registryDependencies` field i When adding new components: 1. Create component files in `registry/mini-app/blocks//` 2. Add registry entry to `registry.json` with proper metadata -3. The pre-commit hook will automatically run `registry:build` to generate public files -4. Deploy triggers automatic Vercel deployment +3. Add the component to `lib/components-config.tsx` so it appears on the homepage for users to test (components only, not hooks or utils) +4. The pre-commit hook will automatically run `registry:build` to generate public files +5. Deploy triggers automatic Vercel deployment ## Important Notes @@ -304,4 +305,41 @@ The shadcn CLI sometimes adds extra quotes around string literals during install if (typeof x === "object") {} ``` -3. **Test registry output** - After running `pnpm registry:build`, check the generated JSON files in `public/r/` to ensure no transformation issues \ No newline at end of file +3. **Test registry output** - After running `pnpm registry:build`, check the generated JSON files in `public/r/` to ensure no transformation issues + +### Critical: TypeScript typeof Comparisons + +The shadcn CLI has a bug where it adds extra quotes around string literals in typeof comparisons, breaking TypeScript builds: + +```typescript +// BEFORE installation (in registry): +if (typeof width === "string") { } + +// AFTER installation (broken - extra quotes): +if (typeof width === "'string'") { } +``` + +**Solution: Always use double quotes for typeof comparisons and test after installation:** + +```typescript +// ✅ REQUIRED: Use double quotes consistently +if (typeof value === "string") { } +if (typeof value === "number") { } +if (typeof value === "bigint") { } +if (typeof value === "object") { } +if (typeof value === "boolean") { } +if (typeof value === "undefined") { } +if (typeof value === "function") { } +if (typeof value === "symbol") { } + +// ❌ NEVER: Don't use single quotes +if (typeof value === 'string') { } // Will break during installation +``` + +**Common locations where this occurs:** +- Width/height checks: `typeof width === "string"` +- Data validation: `typeof data !== "object"` +- Number checks: `typeof value === "number"` +- BigInt validation: `typeof id !== "bigint"` + +**Always run `pnpm registry:build` and test installation before committing!** \ No newline at end of file diff --git a/README.md b/README.md index 0032449f..52f6d51c 100644 --- a/README.md +++ b/README.md @@ -20,21 +20,54 @@ Website: [https://hellno-mini-app-ui.vercel.app](https://hellno-mini-app-ui.verc Website: [https://hellno-mini-app-ui.vercel.app](https://hellno-mini-app-ui.vercel.app) -### Install a component +### Quick Start (Recommended) -Example to install simple token transfer button: +Install the most popular components: ```bash +# NFT display and minting +pnpm dlx shadcn@latest add https://hellno-mini-app-ui.vercel.app/r/nft-card.json +pnpm dlx shadcn@latest add https://hellno-mini-app-ui.vercel.app/r/nft-mint-flow.json + +# User search (Farcaster, ENS, addresses) +pnpm dlx shadcn@latest add https://hellno-mini-app-ui.vercel.app/r/onchain-user-search.json + +# Payment button pnpm dlx shadcn@latest add https://hellno-mini-app-ui.vercel.app/r/daimo-pay-transfer-button.json ``` +### Install individual components + +```bash +pnpm dlx shadcn@latest add https://hellno-mini-app-ui.vercel.app/r/[component-name].json +``` + ### Install all components +Install all components with a single command: + ```bash -pnpm dlx shadcn@latest add https://hellno-mini-app-ui.vercel.app/r/all-components.json +# Default: Skip existing files +curl -sSL https://hellno-mini-app-ui.vercel.app/r/install-all.sh | bash + +# Force overwrite existing files +curl -sSL https://hellno-mini-app-ui.vercel.app/r/install-all-overwrite.sh | bash ``` -This will install all available components and their dependencies at once. +### Local Development + +When developing the registry locally: + +```bash +# Start the registry locally first (in mini-app-ui repo) +pnpm dev + +# Install individual components from localhost +pnpm dlx shadcn@latest add http://localhost:3000/r/nft-card.json --yes + +# Note: install-all.sh may reference production URLs in dependencies +# For local development, install components individually +``` ## Component Development Guide diff --git a/app/component/onchain-user-search/page.tsx b/app/component/onchain-user-search/page.tsx new file mode 100644 index 00000000..592ec2bf --- /dev/null +++ b/app/component/onchain-user-search/page.tsx @@ -0,0 +1,63 @@ +"use client"; + +import { OnchainUserSearch } from "@/registry/mini-app/blocks/onchain-user-search/onchain-user-search"; + +export default function OnchainUserSearchDemo() { + const neynarApiKey = process.env.NEXT_PUBLIC_NEYNAR_API_KEY || ""; + + return ( +
+
+
+

Onchain User Search

+

+ Search for users by Farcaster username, ENS name, or Ethereum + address. All results are unified with the onchain address as the + primary identifier. +

+
+ +
+

Try searching for:

+
    +
  • Farcaster username: "vitalik", "dwr"
  • +
  • ENS name: "vitalik.eth", "nick.eth"
  • +
  • + Ethereum address: 0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045 +
  • +
+
+ + { + // Example: Navigate to Farcaster profile + if (user.farcaster) { + window.open(`https://farcaster.xyz/${user.farcaster.username}`, "_blank"); + } else if (user.ensName) { + window.open(`https://app.ens.domains/${user.ensName}`, "_blank"); + } else { + window.open(`https://etherscan.io/address/${user.primaryAddress}`, "_blank"); + } + }} + /> + +
+

Features:

+
    +
  • Auto-detects input type (username, ENS, or address)
  • +
  • Resolves ENS names to addresses and vice versa
  • +
  • Finds Farcaster accounts associated with addresses
  • +
  • Shows all identities in unified cards
  • +
  • Supports pagination for username searches
  • +
+
+
+
+ ); +} diff --git a/app/component/share-bottom-sheet/page.tsx b/app/component/share-bottom-sheet/page.tsx new file mode 100644 index 00000000..3fd095a4 --- /dev/null +++ b/app/component/share-bottom-sheet/page.tsx @@ -0,0 +1,103 @@ +"use client"; + +import { useState } from "react"; +import { ShareBottomSheet } from "@/registry/mini-app/blocks/share-bottom-sheet/share-bottom-sheet"; +import { Button } from "@/registry/mini-app/ui/button"; + +export default function ShareBottomSheetDemo() { + const [open, setOpen] = useState(false); + const [customText, setCustomText] = useState( + "I just donated to help support Roman Storm's legal defense fund. Join me in defending the right to privacy and the right to publish code!" + ); + + const examples = [ + { + title: "Legal Defense Fund", + text: "I just donated to help support Roman Storm's legal defense fund. Join me in defending the right to privacy and the right to publish code!", + url: "https://www.justiceforstorm.com", + }, + { + title: "Project Launch", + text: "Just launched my new Farcaster mini app! 🚀 It's a game-changer for the community. Check it out and let me know what you think! This is a longer text that will be truncated after 4 lines to maintain a clean UI design while still conveying the essential message.", + url: "https://mini-app-ui.vercel.app", + }, + { + title: "Simple Share", + text: "Building in public is the way! 🛠️", + }, + ]; + + return ( +
+
+
+

Share Bottom Sheet

+

+ A bottom sheet component for sharing content to Farcaster with a + customizable message. Text is automatically truncated to 4 lines + for optimal readability. +

+
+ +
+

Examples

+ +
+ {examples.map((example, index) => ( +
+

{example.title}

+

+ {example.text} +

+ +
+ ))} +
+
+ +
+

Custom Text

+