Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions templates/next-chat-x402/.env.local
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
ECHO_APP_ID="your-echo-app-id"
NEXT_PUBLIC_ECHO_APP_ID="your-echo-app-id"
NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID="your-walletconnect-project-id"
ECHO_ROUTER_URL="http://localhost:3070"
41 changes: 41 additions & 0 deletions templates/next-chat-x402/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.*
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/versions

# testing
/coverage

# next.js
/.next/
/out/

# production
/build

# misc
.DS_Store
*.pem

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*

# env files (can opt-in for committing if needed)
.env

# vercel
.vercel

# typescript
*.tsbuildinfo
next-env.d.ts
107 changes: 107 additions & 0 deletions templates/next-chat-x402/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
# Echo Chat x402 Template

A Next.js chat template with a dual-auth switcher — users can choose to pay with **Echo credits** or **USDC via x402**.

## Quick Start

Use the Echo CLI to create a new project with this template:

```bash
npx echo-start@latest --template next-chat-x402
```

You'll be prompted for your Echo App ID. Don't have one? Get it at [echo.merit.systems/new](https://echo.merit.systems/new).

## Features

- **Auth Switcher** — Sign in with Echo (credits) or connect a wallet (USDC via x402)
- **AI Chat Interface** — Interactive chat with GPT-4o and GPT-5 models
- **x402 Payments** — Pay per message with USDC through the [x402 protocol](https://www.x402.org/)
- **Echo Credits** — Alternative billing through Echo's credit system
- **Wallet Integration** — RainbowKit + wagmi for seamless wallet connection
- **Streaming Responses** — Real-time AI response streaming with reasoning display

## Setup

### Prerequisites

- Node.js 18+
- An Echo account ([echo.merit.systems](https://echo.merit.systems))
- A WalletConnect project ID ([cloud.walletconnect.com](https://cloud.walletconnect.com))

### Environment Variables

Copy `.env.local` and fill in your values:

```env
ECHO_APP_ID="your-echo-app-id"
NEXT_PUBLIC_ECHO_APP_ID="your-echo-app-id"
NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID="your-walletconnect-project-id"
ECHO_ROUTER_URL="http://localhost:3070"
```

### Install & Run

```bash
npm install
npm run dev
```

Open [http://localhost:3000](http://localhost:3000).

## How It Works

### Authentication Flow

Users are presented with two authentication options on the login screen:

1. **Sign in with Echo** — Uses Echo credentials; chat is billed via Echo credits
2. **Connect Wallet** — Connects an EVM wallet (via RainbowKit); chat is billed with USDC via x402

### Payment Routing

The chat API route (`/api/chat`) automatically detects the payment method:

- **Echo credits**: Standard Echo billing flow (no `x-payment` header)
- **x402 USDC**: When the client includes an `x-payment` header with x402 payment authorization, the API routes through the x402 protocol

### Architecture

```
src/
├── app/
│ ├── _components/
│ │ ├── chat.tsx # Chat UI with dual payment mode
│ │ ├── header.tsx # Header with wallet/echo account switcher
│ │ └── echo/
│ │ └── sign-in-button.tsx
│ ├── api/
│ │ ├── chat/route.ts # Chat endpoint (x402 + Echo)
│ │ └── echo/[...echo]/route.ts
│ ├── layout.tsx
│ └── page.tsx # Auth guard with dual auth
├── components/
│ ├── wallet/ # Wallet components (RainbowKit + wagmi)
│ │ ├── auth-guard.tsx # Dual auth guard (Echo OR wallet)
│ │ ├── config.ts # Wagmi chain config
│ │ ├── connect-button.tsx # RainbowKit connect button
│ │ ├── header-account.tsx # Shows wallet or Echo account
│ │ ├── wallet-provider.tsx # WagmiProvider + RainbowKit
│ │ └── wallet-status.tsx # Wallet connection status
│ ├── ai-elements/ # Reusable AI chat UI components
│ ├── echo-account-next.tsx
│ └── ui/ # shadcn/ui components
├── echo/index.ts # Echo SDK setup
├── lib/
│ ├── x402.ts # x402 payment types & helpers
│ ├── currency-utils.ts
│ └── utils.ts
└── providers.tsx # EchoProvider + WalletProvider
```

## Learn More

- [Echo Platform](https://echo.merit.systems)
- [x402 Protocol](https://www.x402.org/)
- [RainbowKit](https://www.rainbowkit.com/)
- [Vercel AI SDK](https://sdk.vercel.ai/)
22 changes: 22 additions & 0 deletions templates/next-chat-x402/components.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "new-york",
"rsc": true,
"tsx": true,
"tailwind": {
"config": "",
"css": "src/app/globals.css",
"baseColor": "neutral",
"cssVariables": true,
"prefix": ""
},
"iconLibrary": "lucide",
"aliases": {
"components": "@/components",
"utils": "@/lib/utils",
"ui": "@/components/ui",
"lib": "@/lib",
"hooks": "@/hooks"
},
"registries": {}
}
19 changes: 19 additions & 0 deletions templates/next-chat-x402/eslint.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { FlatCompat } from '@eslint/eslintrc'

const compat = new FlatCompat({
// import.meta.dirname is available after Node.js v20.11.0
baseDirectory: import.meta.dirname,
})

const eslintConfig = [
...compat.config({
extends: ['next'],
settings: {
next: {
rootDir: 'examples/nextjs-chatbot/',
},
},
}),
]

export default eslintConfig
10 changes: 10 additions & 0 deletions templates/next-chat-x402/next.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import type { NextConfig } from 'next';

const nextConfig: NextConfig = {
/* config options here */
turbopack: {
root: '.',
},
};

export default nextConfig;
75 changes: 75 additions & 0 deletions templates/next-chat-x402/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
{
"name": "next-chat-x402",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev --turbopack",
"build": "next build --turbopack",
"start": "next start",
"lint": "biome check --write",
"postinstall": "npm dedupe || true"
},
"dependencies": {
"@ai-sdk/openai": "2.0.16",
"@ai-sdk/react": "2.0.17",
"@coinbase/cdp-sdk": "^1.34.0",
"@merit-systems/ai-x402": "latest",
"@merit-systems/echo-next-sdk": "latest",
"@merit-systems/echo-react-sdk": "latest",
"@radix-ui/react-avatar": "^1.1.10",
"@radix-ui/react-collapsible": "^1.1.12",
"@radix-ui/react-hover-card": "^1.1.15",
"@radix-ui/react-popover": "^1.1.15",
"@radix-ui/react-scroll-area": "^1.2.10",
"@radix-ui/react-select": "^2.2.6",
"@radix-ui/react-slot": "^1.2.3",
"@radix-ui/react-tooltip": "^1.2.8",
"@radix-ui/react-use-controllable-state": "^1.2.2",
"@rainbow-me/rainbowkit": "^2.2.8",
"@tanstack/react-query": "^5.90.2",
"ai": "5.0.19",
"autonumeric": "^4.10.9",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"dotenv": "^17.2.3",
"embla-carousel-react": "^8.6.0",
"lucide-react": "^0.542.0",
"next": "15.5.9",
"react": "19.1.0",
"react-dom": "19.1.0",
"react-syntax-highlighter": "^15.6.6",
"shiki": "^3.12.2",
"streamdown": "^1.2.0",
"tailwind-merge": "^3.3.1",
"use-stick-to-bottom": "^1.1.1",
"viem": "2.x",
"wagmi": "^2.17.5",
"x402": "^0.6.5",
"zod": "^4.1.5"
},
"devDependencies": {
"@eslint/eslintrc": "^3",
"@next/eslint-plugin-next": "^15.5.3",
"@tailwindcss/postcss": "^4",
"@types/node": "^20",
"@types/react": "^19",
"@types/react-dom": "^19",
"@types/react-syntax-highlighter": "^15.5.13",
"tailwindcss": "^4",
"tw-animate-css": "^1.3.8",
"typescript": "^5"
},
"overrides": {
"ai": "5.0.19",
"@ai-sdk/react": "2.0.17",
"@ai-sdk/openai": "2.0.16",
"@merit-systems/echo-react-sdk": {
"ai": "5.0.19",
"@ai-sdk/react": "2.0.17"
},
"@merit-systems/echo-next-sdk": {
"ai": "5.0.19",
"@ai-sdk/openai": "2.0.16"
}
}
}
5 changes: 5 additions & 0 deletions templates/next-chat-x402/postcss.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const config = {
plugins: ["@tailwindcss/postcss"],
};

export default config;
1 change: 1 addition & 0 deletions templates/next-chat-x402/public/file.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions templates/next-chat-x402/public/globe.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
66 changes: 66 additions & 0 deletions templates/next-chat-x402/public/logo/dark.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading