diff --git a/templates/assistant-ui/.cursor/rules/echo_rules.mdc b/templates/assistant-ui/.cursor/rules/echo_rules.mdc new file mode 100644 index 000000000..5bcf2c038 --- /dev/null +++ b/templates/assistant-ui/.cursor/rules/echo_rules.mdc @@ -0,0 +1,170 @@ +--- +description: Guidelines and best practices for building Echo Assistant UI applications with @assistant-ui/react, AI SDK v5, and Next.js server/client boundaries +globs: **/*.ts,**/*.tsx,**/*.js,**/*.jsx +--- + +# Echo Assistant UI Guidelines + +## Architecture + +This is a Next.js application using `@assistant-ui/react` with Vercel AI SDK v5 and Echo as the AI provider router. It provides a full-featured chat UI with streaming support. + +### Key Dependencies + +- `@assistant-ui/react` for the chat UI framework +- `@assistant-ui/react-ai-sdk` for AI SDK integration +- `@assistant-ui/react-markdown` for markdown rendering +- `@merit-systems/echo-next-sdk` for Echo AI provider integration +- `ai` (Vercel AI SDK v5) for model interaction +- `next` for the application framework + +## SDK Initialization + +### Echo Server-Side Setup + +ALWAYS initialize the Echo SDK in `echo.ts` at the project root: + +```typescript +import Echo from '@merit-systems/echo-next-sdk'; + +const echo = Echo({ + appId: process.env.NEXT_PUBLIC_ECHO_APP_ID ?? 'ECHO_APP_ID', +}); + +export const { getUser, isSignedIn, openai, anthropic, google } = echo; +export default echo.handlers; +``` + +### Echo Route Handler + +ALWAYS register Echo authentication handlers at `app/api/echo/[...path]/route.ts`: + +```typescript +import handlers from '@/echo'; +export { handlers as GET, handlers as POST }; +``` + +## Environment Variables + +ALWAYS store your Echo App ID in `.env.local`: + +```bash +NEXT_PUBLIC_ECHO_APP_ID=your_echo_app_id +``` + +NEVER hardcode API keys or app IDs directly in your code. ALWAYS use environment variables. + +## Chat API Route + +The chat API route at `app/api/chat/route.ts` connects Assistant UI to Echo models: + +```typescript +import { openai } from '@/echo'; +import { streamText } from 'ai'; + +export async function POST(req: Request) { + const { messages, model } = await req.json(); + const result = streamText({ + model: openai(model), + messages, + }); + return result.toDataStreamResponse(); +} +``` + +ALWAYS validate the `model` and `messages` parameters before processing. + +## Assistant UI Components + +### Runtime Provider + +Use `@assistant-ui/react-ai-sdk` to connect the AI SDK runtime to Assistant UI: + +```typescript +'use client'; + +import { useChat } from '@ai-sdk/react'; +import { useVercelUseChatRuntime } from '@assistant-ui/react-ai-sdk'; +import { AssistantRuntimeProvider } from '@assistant-ui/react'; + +export function ChatProvider({ children }: { children: React.ReactNode }) { + const chat = useChat({ api: '/api/chat' }); + const runtime = useVercelUseChatRuntime(chat); + return ( + + {children} + + ); +} +``` + +### Using Assistant UI Components + +Import chat components from `@assistant-ui/react`: + +```typescript +import { Thread } from '@assistant-ui/react'; + +export function ChatPage() { + return ; +} +``` + +NEVER build custom chat UIs from scratch when Assistant UI provides the component. Use the built-in `Thread`, `ThreadList`, `Composer`, and `Message` components. + +## Server/Client Boundaries + +- Server components: Echo SDK initialization, API routes, data fetching +- Client components: Assistant UI components, chat interactions, user input + +NEVER import `@merit-systems/echo-next-sdk` in a client component. Only use it in server-side code and API routes. + +## Project Structure + +Follow this structure: + +``` +app/ + api/ + chat/route.ts # Chat API endpoint + echo/[...path]/route.ts # Echo auth handlers + layout.tsx + page.tsx +components/ # Client-side UI components +echo.ts # Server-side Echo initialization +providers.tsx # Client providers +lib/ # Shared utilities +``` + +## Error Handling + +ALWAYS handle errors explicitly in API routes: + +```typescript +try { + const result = await someOperation(); + return result; +} catch (error) { + console.error('Operation failed:', error); + return new Response( + JSON.stringify({ error: 'Internal server error' }), + { status: 500, headers: { 'Content-Type': 'application/json' } } + ); +} +``` + +## TypeScript Guidelines + +- Use strict typing and avoid `any`. +- Export explicit types for shared data structures. +- Use `as const` for string literals in discriminated union types. + +## Testing + +NEVER call external services directly in unit tests. ALWAYS mock the Echo SDK and Assistant UI runtime: + +```typescript +vi.mock('@/echo', () => ({ + openai: vi.fn(() => mockModel), +})); +``` diff --git a/templates/authjs/.cursor/rules/echo_rules.mdc b/templates/authjs/.cursor/rules/echo_rules.mdc new file mode 100644 index 000000000..e7f8cb4b7 --- /dev/null +++ b/templates/authjs/.cursor/rules/echo_rules.mdc @@ -0,0 +1,218 @@ +--- +description: Guidelines and best practices for building Echo applications with Auth.js (NextAuth) integration, including authentication flows, session management, and Echo SDK usage +globs: **/*.ts,**/*.tsx,**/*.js,**/*.jsx +--- + +# Echo Auth.js Guidelines + +## Architecture + +This is a Next.js application that uses Echo as an Auth.js (NextAuth v5) provider for authentication, combined with the Echo Next SDK for AI functionality. It demonstrates OAuth-based login through Echo. + +### Key Dependencies + +- `next-auth` (v5 beta) for authentication +- `@merit-systems/echo-authjs-provider` for the Echo Auth.js provider +- `@merit-systems/echo-next-sdk` for Echo AI integration +- `@merit-systems/echo-typescript-sdk` for server-side Echo API calls +- `ai` (Vercel AI SDK) for model interaction +- `next` for the application framework + +## Authentication Setup + +### Auth Configuration + +ALWAYS configure Auth.js in `src/auth/index.ts` using the Echo provider: + +```typescript +import NextAuth from 'next-auth'; +import Echo from '@merit-systems/echo-authjs-provider'; + +export const { handlers, signIn, signOut, auth } = NextAuth({ + providers: [ + Echo({ + appId: process.env.ECHO_APP_ID!, + }), + ], + callbacks: { + async jwt({ token, account }) { + if (account) { + token.accessToken = account.access_token; + token.refreshToken = account.refresh_token; + } + return token; + }, + async session({ session, token }) { + session.accessToken = token.accessToken as string; + session.refreshToken = token.refreshToken as string; + return session; + }, + }, +}); +``` + +### Auth Route Handler + +ALWAYS register the NextAuth route handler at `src/app/api/auth/[...nextauth]/route.ts`: + +```typescript +import { handlers } from '@/auth'; +export const { GET, POST } = handlers; +``` + +### Session Type Augmentation + +ALWAYS augment the NextAuth types in `src/types/next-auth.d.ts` to include Echo tokens: + +```typescript +declare module 'next-auth' { + interface Session { + accessToken: string; + refreshToken: string; + } +} +``` + +## Echo SDK Initialization + +### Server-Side Echo Setup + +ALWAYS initialize the Echo SDK in `src/echo/index.ts`: + +```typescript +import Echo from '@merit-systems/echo-next-sdk'; + +export const { handlers, isSignedIn, openai, anthropic } = Echo({ + appId: process.env.ECHO_APP_ID!, +}); +``` + +### Echo Route Handler + +ALWAYS register Echo handlers at `src/app/api/echo/[...echo]/route.ts`: + +```typescript +import { handlers } from '@/echo'; +export const { GET, POST } = handlers; +``` + +## Environment Variables + +ALWAYS store secrets in `.env.local`: + +```bash +ECHO_APP_ID=your_echo_app_id +AUTH_SECRET=your_nextauth_secret +``` + +NEVER hardcode API keys, app IDs, or auth secrets. ALWAYS use environment variables. + +Note: `AUTH_SECRET` is required by NextAuth v5 for JWT encryption. + +## Authentication Patterns + +### Protecting Pages + +Use the `auth()` function from your auth config to check sessions: + +```typescript +import { auth } from '@/auth'; +import { redirect } from 'next/navigation'; + +export default async function DashboardPage() { + const session = await auth(); + if (!session) { + redirect('/'); + } + return
Welcome, {session.user?.name}
; +} +``` + +### Sign In / Sign Out + +Use the `signIn` and `signOut` server actions: + +```typescript +import { signIn, signOut } from '@/auth'; + +// In a server action or form +await signIn('echo'); +await signOut(); +``` + +## Server/Client Boundaries + +- Server components: Authentication checks, Echo SDK calls, data fetching +- Client components: UI interactions, sign-in buttons, session display + +NEVER import `@merit-systems/echo-next-sdk` or access `auth()` in client components. Use server components or API routes for authenticated operations. + +## Echo Client for API Calls + +Use `@merit-systems/echo-typescript-sdk` for direct Echo API calls on the server: + +```typescript +import { EchoClient } from '@merit-systems/echo-typescript-sdk'; + +const echoClient = new EchoClient({ + appId: process.env.ECHO_APP_ID!, +}); +``` + +## Project Structure + +Follow this structure: + +``` +src/ + app/ + api/ + auth/[...nextauth]/route.ts # NextAuth handlers + echo/[...echo]/route.ts # Echo handlers + dashboard/page.tsx # Protected page + layout.tsx + page.tsx + auth/ + index.ts # NextAuth configuration + echo/ + index.ts # Echo SDK initialization + lib/ + echo-client.ts # Echo TypeScript SDK client + types/ + next-auth.d.ts # Type augmentation +``` + +## Error Handling + +ALWAYS handle authentication errors gracefully: + +```typescript +try { + const session = await auth(); + if (!session) { + return new Response('Unauthorized', { status: 401 }); + } + // proceed with authenticated logic +} catch (error) { + console.error('Auth error:', error); + return new Response('Internal server error', { status: 500 }); +} +``` + +## TypeScript Guidelines + +- Use strict typing and avoid `any`. +- ALWAYS augment NextAuth types when adding custom session fields. +- Export explicit types for shared data structures. + +## Testing + +NEVER call external auth services in tests. ALWAYS mock NextAuth and the Echo SDK: + +```typescript +vi.mock('@/auth', () => ({ + auth: vi.fn(() => Promise.resolve({ user: { name: 'Test' } })), + signIn: vi.fn(), + signOut: vi.fn(), +})); +``` diff --git a/templates/echo-cli/.cursor/rules/echo_rules.mdc b/templates/echo-cli/.cursor/rules/echo_rules.mdc new file mode 100644 index 000000000..845646aed --- /dev/null +++ b/templates/echo-cli/.cursor/rules/echo_rules.mdc @@ -0,0 +1,171 @@ +--- +description: Guidelines and best practices for building the Echo CLI application, including command structure, authentication, wallet integration, and TypeScript patterns +globs: **/*.ts,**/*.js +--- + +# Echo CLI Guidelines + +## Architecture + +This is a Node.js CLI application built with Commander.js and the Echo TypeScript SDK. It provides a terminal-based chat agent with wallet-based authentication. + +### Key Dependencies + +- `commander` for CLI command parsing +- `@clack/prompts` for interactive terminal prompts +- `@merit-systems/echo-typescript-sdk` for Echo API integration +- `@merit-systems/ai-x402` for AI payment integration + +## Project Structure + +Follow this structure: + +``` +src/ + index.ts # CLI entry point and command registration + constants.ts # Shared constants (ASCII art, auth options) + print.ts # Output formatting utilities + auth/ # Authentication modules + client.ts # Echo client setup + login.ts # Login flows + logout.ts # Logout handling + wallet.ts # Wallet authentication + local-wallet.ts # Local wallet management + providers.ts # Auth provider configuration + config/ # Configuration management + index.ts # Config entry point + store.ts # Persistent storage + models.ts # Model configuration + wallet.ts # Wallet config + core/ # Core functionality + chat.ts # Chat session management + history.ts # Conversation history + model.ts # Model selection + profile.ts # User profile + utils/ # Shared utilities + auth.ts # Auth helpers + errors.ts # Error handling + spinner.ts # Loading indicators + stream.ts # Stream processing + wallet.ts # Wallet utilities + validation/ # Input validation + schemas.ts # Validation schemas + validator.ts # Validation logic +``` + +## Command Registration + +ALWAYS register commands using Commander.js in `src/index.ts`: + +```typescript +import { Command } from 'commander'; + +const program = new Command(); + +program + .name('echodex') + .description('CLI Coding Agent Powered by Echo') + .version('1.0.0'); + +program + .command('login') + .description('Authenticate with Echo or Wallet') + .action(async () => { + // handler + }); +``` + +ALWAYS call `process.exit()` with appropriate codes at the end of each command action. + +## Authentication + +### Authentication Methods + +The CLI supports multiple authentication methods: +- Echo OAuth login +- External wallet connection +- Local wallet generation + +ALWAYS check authentication state before executing protected commands: + +```typescript +import { isAuthenticated } from '@/utils'; + +const authenticated = await isAuthenticated(); +if (!authenticated) { + program.help(); + process.exit(0); +} +``` + +### Wallet Security + +NEVER log or display private keys unless the user explicitly requests it (e.g., `export-private-key` command). + +ALWAYS warn users when performing sensitive wallet operations. + +## Interactive Prompts + +Use `@clack/prompts` for all user interactions: + +```typescript +import { select, isCancel } from '@clack/prompts'; + +const choice = await select({ + message: 'Choose an option:', + options: [ + { value: 'a', label: 'Option A' }, + { value: 'b', label: 'Option B' }, + ], +}); + +if (isCancel(choice)) { + warning('Operation cancelled'); + process.exit(1); +} +``` + +ALWAYS handle cancellation by checking `isCancel()` on prompt results. + +## Path Aliases + +This project uses TypeScript path aliases. ALWAYS use `@/` imports: + +```typescript +// CORRECT +import { isAuthenticated } from '@/utils'; +import { ECHODEX_ASCII_ART } from '@/constants'; + +// INCORRECT +import { isAuthenticated } from '../../utils'; +``` + +## Error Handling + +ALWAYS handle errors explicitly and provide user-friendly output: + +```typescript +try { + const result = await someOperation(); + return result; +} catch (error) { + console.error('Operation failed:', error); + process.exit(1); +} +``` + +Use the `print.ts` utilities for consistent output formatting: +- `info()` for informational messages +- `warning()` for warnings +- `header()` for section headers + +## TypeScript Guidelines + +- Use strict typing and avoid `any`. +- Export explicit types for shared data structures. +- Use `as const` for string literals and enum-like objects. +- ALWAYS add `@types/node` to devDependencies. + +## Testing + +NEVER call external services directly in tests. ALWAYS mock the Echo SDK and wallet providers. diff --git a/templates/next-chat/.cursor/rules/echo_rules.mdc b/templates/next-chat/.cursor/rules/echo_rules.mdc new file mode 100644 index 000000000..e62f51f61 --- /dev/null +++ b/templates/next-chat/.cursor/rules/echo_rules.mdc @@ -0,0 +1,198 @@ +--- +description: Guidelines and best practices for building Echo Next.js chat applications, including SDK initialization, streaming chat, server/client boundaries, and UI component patterns +globs: **/*.ts,**/*.tsx,**/*.js,**/*.jsx +--- + +# Echo Next.js Chat Guidelines + +## Architecture + +This is a full-featured Next.js chat application using the Echo SDK for AI billing, authentication, and model routing. It includes streaming chat, user management, and a rich set of AI UI elements. + +### Key Dependencies + +- `@merit-systems/echo-next-sdk` for server-side Echo integration +- `@merit-systems/echo-react-sdk` for client-side Echo components +- `@ai-sdk/react` for React hooks (useChat) +- `ai` (Vercel AI SDK v5) for streaming and model interaction +- `next` for the application framework +- Radix UI components for the UI layer + +## SDK Initialization + +### Server-Side Echo Setup + +ALWAYS initialize the Echo SDK in `src/echo/index.ts`: + +```typescript +import Echo from '@merit-systems/echo-next-sdk'; + +export const { handlers, isSignedIn, openai, anthropic } = Echo({ + appId: process.env.ECHO_APP_ID!, +}); +``` + +### Client-Side Provider + +ALWAYS wrap the application with `EchoProvider` in `src/providers.tsx`: + +```typescript +'use client'; + +import { EchoProvider } from '@merit-systems/echo-react-sdk'; + +export function Providers({ children }: { children: React.ReactNode }) { + return ( + + {children} + + ); +} +``` + +## Environment Variables + +ALWAYS store your Echo App ID in `.env.local`: + +```bash +ECHO_APP_ID=your_echo_app_id +NEXT_PUBLIC_ECHO_APP_ID=your_echo_app_id +``` + +NEVER hardcode API keys or app IDs. ALWAYS use environment variables. + +## Streaming Chat API + +### Chat API Route + +Use the Vercel AI SDK with Echo model providers for streaming responses: + +```typescript +import { openai } from '@/echo'; +import { streamText, convertToModelMessages, type UIMessage } from 'ai'; + +export const maxDuration = 30; + +export async function POST(req: Request) { + const { messages, model }: { messages: UIMessage[]; model: string } = await req.json(); + + if (!model || !messages || !Array.isArray(messages)) { + return new Response(JSON.stringify({ error: 'Bad Request' }), { status: 400 }); + } + + const result = streamText({ + model: openai(model), + messages: convertToModelMessages(messages), + }); + + return result.toUIMessageStreamResponse(); +} +``` + +### Client-Side Chat Hook + +Use `useChat` from `@ai-sdk/react` for client-side chat state management: + +```typescript +'use client'; + +import { useChat } from '@ai-sdk/react'; + +export function Chat() { + const { messages, input, handleInputChange, handleSubmit } = useChat({ + api: '/api/chat', + }); + // render chat UI +} +``` + +## AI UI Elements + +This template includes reusable AI UI components in `src/components/ai-elements/`: + +- `conversation.tsx` - Chat conversation container +- `prompt-input.tsx` - User input with model selection +- `response.tsx` - AI response rendering +- `code-block.tsx` - Syntax-highlighted code blocks +- `sources.tsx` - Source citation display +- `suggestion.tsx` - Suggested prompts +- `task.tsx` - Task/tool execution display +- `image.tsx` - Image generation display + +ALWAYS use these existing components rather than building custom equivalents. + +## Echo UI Components + +Use the shared Echo UI components in `src/components/`: + +- `echo-button.tsx` - Echo sign-in button +- `echo-popover.tsx` - Account popover menu +- `echo-account-next.tsx` - Account management +- `balance.tsx` - Token balance display +- `money-input.tsx` - Currency input for top-ups + +## Server/Client Boundaries + +- Server components: Echo SDK initialization, API routes, authentication checks +- Client components: Chat UI, Echo provider, interactive elements + +NEVER import `@merit-systems/echo-next-sdk` in client components. Use `@merit-systems/echo-react-sdk` for client-side Echo features. + +## Project Structure + +Follow this structure: + +``` +src/ + app/ + api/ + echo/[...echo]/route.ts # Echo auth handlers + chat/route.ts # Streaming chat endpoint + layout.tsx + page.tsx + components/ + ai-elements/ # Chat UI components + echo-button.tsx # Echo integration components + echo-popover.tsx + balance.tsx + echo/ + index.ts # Server-side Echo initialization + lib/ + utils.ts # Shared utilities + currency-utils.ts # Currency formatting + providers.tsx # Client providers +``` + +## Error Handling + +ALWAYS handle errors explicitly in API routes and provide meaningful HTTP status codes: + +```typescript +try { + const result = await someOperation(); + return result; +} catch (error) { + console.error('Operation failed:', error); + return new Response( + JSON.stringify({ error: 'Internal server error' }), + { status: 500, headers: { 'Content-Type': 'application/json' } } + ); +} +``` + +## TypeScript Guidelines + +- Use strict typing and avoid `any`. +- Export explicit types for shared data structures. +- Use `as const` for string literals in discriminated union types. +- Type chat messages using `UIMessage` from the `ai` package. + +## Testing + +NEVER call external services in unit tests. ALWAYS mock the Echo SDK: + +```typescript +vi.mock('@/echo', () => ({ + openai: vi.fn(() => mockModel), +})); +``` diff --git a/templates/next-image/.cursor/rules/echo_rules.mdc b/templates/next-image/.cursor/rules/echo_rules.mdc new file mode 100644 index 000000000..1328ecc38 --- /dev/null +++ b/templates/next-image/.cursor/rules/echo_rules.mdc @@ -0,0 +1,151 @@ +--- +description: Guidelines and best practices for building Echo Next.js image generation applications, including SDK initialization, image API integration, server/client boundaries, and UI patterns +globs: **/*.ts,**/*.tsx,**/*.js,**/*.jsx +--- + +# Echo Next.js Image Generation Guidelines + +## Architecture + +This is a Next.js application for AI-powered image generation using the Echo SDK. It provides image generation through Echo's model routing with automatic billing and user management. + +### Key Dependencies + +- `@merit-systems/echo-next-sdk` for server-side Echo integration +- `@merit-systems/echo-react-sdk` for client-side Echo components +- `ai` (Vercel AI SDK) for model interaction +- `openai` for image generation API calls +- `next` for the application framework +- Radix UI components for the UI layer + +## SDK Initialization + +### Server-Side Echo Setup + +ALWAYS initialize the Echo SDK in `src/echo/index.ts`: + +```typescript +import Echo from '@merit-systems/echo-next-sdk'; + +export const { handlers, isSignedIn, openai, anthropic } = Echo({ + appId: process.env.ECHO_APP_ID!, +}); +``` + +## Environment Variables + +ALWAYS store your Echo App ID in `.env.local`: + +```bash +ECHO_APP_ID=your_echo_app_id +NEXT_PUBLIC_ECHO_APP_ID=your_echo_app_id +``` + +NEVER hardcode API keys or app IDs. ALWAYS use environment variables. + +## Image Generation + +### Server Actions + +Use Next.js server actions in `src/lib/image-actions.ts` for image generation: + +```typescript +'use server'; + +import { openai } from '@/echo'; + +export async function generateImage(prompt: string, model: string) { + // Generate image using Echo-proxied OpenAI + const response = await openai.images.generate({ + model, + prompt, + }); + return response.data; +} +``` + +ALWAYS use server actions or API routes for image generation. NEVER call the OpenAI API directly from client components. + +### Image Utilities + +Keep image processing utilities in `src/lib/image-utils.ts` and type definitions in `src/lib/types.ts`. + +Keep model and size constants in `src/lib/constants.ts`. + +## Echo UI Components + +Use the shared Echo UI components in `src/components/`: + +- `echo-button.tsx` - Echo sign-in button +- `echo-popover.tsx` - Account popover menu +- `echo-account-next.tsx` - Account management +- `echo-tokens.tsx` - Token display +- `balance.tsx` - Token balance display +- `signin.tsx` - Sign-in page component +- `image-details-dialog.tsx` - Image detail view + +## Server/Client Boundaries + +- Server components: Echo SDK initialization, image generation actions, authentication +- Client components: Image display, user input, Echo provider components + +NEVER import `@merit-systems/echo-next-sdk` in client components. Use `@merit-systems/echo-react-sdk` for client-side Echo features. + +## Project Structure + +Follow this structure: + +``` +src/ + app/ + api/ + echo/[...echo]/route.ts # Echo auth handlers + layout.tsx + page.tsx + components/ + ui/ # Reusable UI primitives + echo-button.tsx # Echo integration components + echo-tokens.tsx + image-details-dialog.tsx # Image-specific components + ai-elements/ + prompt-input.tsx # Image prompt input + echo/ + index.ts # Server-side Echo initialization + lib/ + types.ts # Image type definitions + constants.ts # Model and size constants + image-actions.ts # Server actions for generation + image-utils.ts # Image processing utilities + utils.ts # Shared utilities + currency-utils.ts # Currency formatting +``` + +## Error Handling + +ALWAYS handle image generation errors and provide user feedback: + +```typescript +try { + const result = await generateImage(prompt, model); + return result; +} catch (error) { + console.error('Image generation failed:', error); + // Return user-friendly error +} +``` + +## TypeScript Guidelines + +- Use strict typing and avoid `any`. +- Define image-related types in `src/lib/types.ts`. +- Export explicit types for shared data structures. + +## Testing + +NEVER call external services in unit tests. ALWAYS mock the Echo SDK and image generation: + +```typescript +vi.mock('@/echo', () => ({ + openai: { images: { generate: vi.fn() } }, +})); +``` diff --git a/templates/next-video-template/.cursor/rules/echo_rules.mdc b/templates/next-video-template/.cursor/rules/echo_rules.mdc new file mode 100644 index 000000000..686fc25e9 --- /dev/null +++ b/templates/next-video-template/.cursor/rules/echo_rules.mdc @@ -0,0 +1,161 @@ +--- +description: Guidelines and best practices for building Echo Next.js video generation applications, including SDK initialization, video API integration, Google GenAI usage, and UI patterns +globs: **/*.ts,**/*.tsx,**/*.js,**/*.jsx +--- + +# Echo Next.js Video Generation Guidelines + +## Architecture + +This is a Next.js application for AI-powered video generation using the Echo SDK. It integrates with Google GenAI for video generation, uses React Query for async state management, and provides automatic billing through Echo. + +### Key Dependencies + +- `@merit-systems/echo-next-sdk` for server-side Echo integration +- `@merit-systems/echo-react-sdk` for client-side Echo components +- `@google/genai` for Google AI video generation +- `@tanstack/react-query` for async state management +- `ai` (Vercel AI SDK) for model interaction +- `next` for the application framework +- Radix UI components for the UI layer + +## SDK Initialization + +### Server-Side Echo Setup + +ALWAYS initialize the Echo SDK in `src/echo/index.ts`: + +```typescript +import Echo from '@merit-systems/echo-next-sdk'; + +export const { handlers, isSignedIn, openai, anthropic } = Echo({ + appId: process.env.ECHO_APP_ID!, +}); +``` + +## Environment Variables + +ALWAYS store your Echo App ID in `.env.local`: + +```bash +ECHO_APP_ID=your_echo_app_id +NEXT_PUBLIC_ECHO_APP_ID=your_echo_app_id +``` + +NEVER hardcode API keys or app IDs. ALWAYS use environment variables. + +## Video Generation + +### API Layer + +Keep video API calls in `src/lib/api/video-api.ts`. Use server actions or API routes for all generation requests. + +ALWAYS use server-side code for video generation API calls. NEVER expose API keys to the client. + +### Video Operations + +Keep video processing logic in `src/lib/video-operations.ts` and history management in `src/lib/video-history.ts`. + +### Custom Hooks + +Use the custom hooks in `src/lib/hooks/` for video-related state management: + +- `useVideoGeneration.ts` - Video generation state and actions +- `useVideoHistory.ts` - Video history management +- `useVideoOperations.ts` - Video processing operations + +ALWAYS use React Query (`@tanstack/react-query`) for async state management in video operations. + +### Types and Constants + +Define video-related types in `src/lib/types.ts` and constants (models, sizes, durations) in `src/lib/constants.ts`. + +## Echo UI Components + +Use the shared Echo UI components in `src/components/`: + +- `echo-button.tsx` - Echo sign-in button +- `echo-popover.tsx` - Account popover menu +- `echo-account-next.tsx` - Account management +- `signin.tsx` - Sign-in page component +- `video-history.tsx` - Video generation history +- `video-details-dialog.tsx` - Video detail view +- `image-details-dialog.tsx` - Image detail view (for thumbnails) + +## Server/Client Boundaries + +- Server components: Echo SDK initialization, video generation API calls, authentication +- Client components: Video display, generation UI, Echo provider, React Query + +NEVER import `@merit-systems/echo-next-sdk` in client components. Use `@merit-systems/echo-react-sdk` for client-side Echo features. + +## Project Structure + +Follow this structure: + +``` +src/ + app/ + api/ + echo/[...echo]/route.ts # Echo auth handlers + layout.tsx + page.tsx + components/ + ui/ # Reusable UI primitives + echo-button.tsx # Echo integration components + video-history.tsx # Video-specific components + video-details-dialog.tsx + ai-elements/ + prompt-input.tsx # Generation prompt input + echo/ + index.ts # Server-side Echo initialization + lib/ + api/ + video-api.ts # Video generation API + hooks/ + useVideoGeneration.ts # Video generation hook + useVideoHistory.ts # History management hook + useVideoOperations.ts # Video operations hook + types.ts # Type definitions + constants.ts # Model and config constants + video-operations.ts # Video processing + video-history.ts # History storage + image-actions.ts # Image generation actions + utils.ts # Shared utilities + currency-utils.ts # Currency formatting +``` + +## Error Handling + +ALWAYS handle video generation errors and provide user feedback: + +```typescript +try { + const result = await generateVideo(prompt, model); + return result; +} catch (error) { + console.error('Video generation failed:', error); + // Return user-friendly error +} +``` + +## TypeScript Guidelines + +- Use strict typing and avoid `any`. +- Define video-related types in `src/lib/types.ts`. +- Export explicit types for shared data structures. +- Use `as const` for string literals in discriminated union types. + +## Testing + +NEVER call external services in unit tests. ALWAYS mock the Echo SDK and video generation APIs: + +```typescript +vi.mock('@/echo', () => ({ + openai: vi.fn(() => mockModel), +})); + +vi.mock('@google/genai', () => ({ + // mock implementation +})); +``` diff --git a/templates/next/.cursor/rules/echo_rules.mdc b/templates/next/.cursor/rules/echo_rules.mdc new file mode 100644 index 000000000..b896b19b6 --- /dev/null +++ b/templates/next/.cursor/rules/echo_rules.mdc @@ -0,0 +1,177 @@ +--- +description: Guidelines and best practices for building Echo Next.js applications, including SDK initialization, server/client boundaries, environment variables, and API routes +globs: **/*.ts,**/*.tsx,**/*.js,**/*.jsx +--- + +# Echo Next.js Guidelines + +## SDK Initialization + +### Server-Side Initialization + +ALWAYS initialize the Echo SDK in `src/echo/index.ts` for server-side usage: + +```typescript +import Echo from '@merit-systems/echo-next-sdk'; + +export const { handlers, isSignedIn, openai, anthropic } = Echo({ + appId: process.env.ECHO_APP_ID!, +}); +``` + +### Client-Side Provider + +ALWAYS wrap your application with `EchoProvider` in your providers file: + +```typescript +'use client'; + +import { EchoProvider } from '@merit-systems/echo-next-sdk/client'; + +export function Providers({ children }: { children: React.ReactNode }) { + return ( + + {children} + + ); +} +``` + +## Environment Variables + +ALWAYS store your Echo App ID in `.env.local`: + +```bash +# Server-side only +ECHO_APP_ID=your_echo_app_id + +# Client-side (public) +NEXT_PUBLIC_ECHO_APP_ID=your_echo_app_id +``` + +NEVER hardcode API keys or app IDs directly in your code. ALWAYS use environment variables. + +## Server/Client Boundaries + +### Server Components + +ALWAYS use server components for Echo AI calls that require authentication: + +```typescript +import { openai } from '@/echo'; +import { generateText } from 'ai'; + +export default async function Page() { + const { text } = await generateText({ + model: openai('gpt-4o'), + prompt: 'Hello, world!', + }); + return
{text}
; +} +``` + +### Client Components + +Use client components ONLY for UI interactions. NEVER make direct AI calls from client components with server secrets: + +```typescript +// CORRECT - Client component uses Echo UI components +'use client'; + +import { EchoTokens } from '@merit-systems/echo-next-sdk/client'; + +export function EchoButton() { + return ; +} +``` + +NEVER import `@merit-systems/echo-next-sdk` (server SDK) in a client component. Only use `@merit-systems/echo-next-sdk/client` on the client side. + +## API Routes + +### Echo Authentication Handler + +ALWAYS register Echo authentication handlers at `app/api/echo/[...echo]/route.ts`: + +```typescript +import { handlers } from '@/echo'; +export const { GET, POST } = handlers; +``` + +### Custom API Routes with AI + +Use the Vercel AI SDK (`ai` package) with Echo model providers for streaming: + +```typescript +import { openai } from '@/echo'; +import { streamText, convertToModelMessages, type UIMessage } from 'ai'; + +export const maxDuration = 30; + +export async function POST(req: Request) { + const { messages, model }: { messages: UIMessage[]; model: string } = await req.json(); + + if (!model || !messages || !Array.isArray(messages)) { + return new Response(JSON.stringify({ error: 'Bad Request' }), { status: 400 }); + } + + const result = streamText({ + model: openai(model), + messages: convertToModelMessages(messages), + }); + + return result.toUIMessageStreamResponse(); +} +``` + +## Error Handling + +ALWAYS handle errors explicitly in API routes and provide meaningful HTTP status codes: + +```typescript +try { + const result = await someOperation(); + return result; +} catch (error) { + console.error('Operation failed:', error); + return new Response( + JSON.stringify({ error: 'Internal server error', message: 'Failed to process request' }), + { status: 500, headers: { 'Content-Type': 'application/json' } } + ); +} +``` + +## Project Structure + +Follow this structure for Echo Next.js projects: + +``` +src/ + app/ + api/ + echo/[...echo]/route.ts # Echo auth handlers + chat/route.ts # Custom API routes + layout.tsx + page.tsx + components/ # Client-side components + echo/ + index.ts # Server-side Echo initialization + lib/ # Shared utilities and types + providers.tsx # Client providers including EchoProvider +``` + +## TypeScript Guidelines + +- Use strict typing and avoid `any`. +- Export explicit types for shared data structures. +- Use `as const` for string literals in discriminated union types. + +## Testing + +NEVER call external services directly in unit tests. ALWAYS mock the Echo SDK: + +```typescript +vi.mock('@/echo', () => ({ + openai: vi.fn(() => mockModel), +})); +``` diff --git a/templates/nextjs-api-key-template/.cursor/rules/echo_rules.mdc b/templates/nextjs-api-key-template/.cursor/rules/echo_rules.mdc new file mode 100644 index 000000000..5d53a71cd --- /dev/null +++ b/templates/nextjs-api-key-template/.cursor/rules/echo_rules.mdc @@ -0,0 +1,210 @@ +--- +description: Guidelines and best practices for building Echo Next.js applications with API key management, Prisma database integration, and server-side authentication +globs: **/*.ts,**/*.tsx,**/*.js,**/*.jsx,**/*.prisma +--- + +# Echo Next.js API Key Template Guidelines + +## Architecture + +This is a Next.js application demonstrating server-side API key management with Echo. It uses Prisma with PostgreSQL for database storage, Echo for AI billing and authentication, and provides a full-featured chat interface. + +### Key Dependencies + +- `@merit-systems/echo-next-sdk` for server-side Echo integration +- `@merit-systems/echo-react-sdk` for client-side Echo components +- `@merit-systems/echo-typescript-sdk` for direct Echo API calls +- `@prisma/client` for database access +- `ai` (Vercel AI SDK v5) for streaming and model interaction +- `next` for the application framework +- Docker for local PostgreSQL database + +## SDK Initialization + +### Server-Side Echo Setup + +ALWAYS initialize the Echo SDK in `src/echo/index.ts`: + +```typescript +import Echo from '@merit-systems/echo-next-sdk'; + +export const { handlers, isSignedIn, openai, anthropic } = Echo({ + appId: process.env.ECHO_APP_ID!, +}); +``` + +### Client-Side Provider + +ALWAYS wrap the application with `EchoProvider` in `src/providers.tsx`: + +```typescript +'use client'; + +import { EchoProvider } from '@merit-systems/echo-react-sdk'; + +export function Providers({ children }: { children: React.ReactNode }) { + return ( + + {children} + + ); +} +``` + +## Environment Variables + +ALWAYS store secrets in `.env.local`: + +```bash +ECHO_APP_ID=your_echo_app_id +NEXT_PUBLIC_ECHO_APP_ID=your_echo_app_id +DATABASE_URL=postgresql://user:password@localhost:5432/echo +``` + +NEVER hardcode API keys, app IDs, or database URLs. ALWAYS use environment variables. + +## Database (Prisma) + +### Schema + +The Prisma schema is defined in `prisma/schema.prisma` with PostgreSQL: + +```prisma +generator client { + provider = "prisma-client-js" + output = "../src/generated/prisma" + binaryTargets = ["native", "rhel-openssl-3.0.x"] +} + +datasource db { + provider = "postgresql" + url = env("DATABASE_URL") +} +``` + +### Prisma Client + +ALWAYS use the singleton pattern for the Prisma client in `src/lib/db.ts`: + +```typescript +import { PrismaClient } from '@/generated/prisma'; + +const globalForPrisma = globalThis as unknown as { prisma: PrismaClient }; + +export const prisma = globalForPrisma.prisma || new PrismaClient(); + +if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma; +``` + +### Database Commands + +- `prisma generate` - Generate the Prisma client +- `prisma migrate dev` - Create and apply migrations in development +- `prisma migrate deploy` - Apply migrations in production +- `prisma studio` - Open the database browser + +ALWAYS run `prisma generate` after schema changes. The generated client outputs to `src/generated/prisma`. + +### Local Development + +The project uses Docker for local PostgreSQL. Run `docker-compose -f docker-local-db.yml up -d` to start the database. + +## API Key Management + +- Store API keys in the database, associated with user records. +- NEVER expose API keys in client-side code or responses. +- ALWAYS validate API keys on the server side before processing requests. +- Use proper hashing when storing sensitive keys. + +## Streaming Chat + +Use the Vercel AI SDK with Echo for streaming chat: + +```typescript +import { openai } from '@/echo'; +import { streamText, convertToModelMessages, type UIMessage } from 'ai'; + +export async function POST(req: Request) { + const { messages, model }: { messages: UIMessage[]; model: string } = await req.json(); + const result = streamText({ + model: openai(model), + messages: convertToModelMessages(messages), + }); + return result.toUIMessageStreamResponse(); +} +``` + +## Server/Client Boundaries + +- Server components: Echo SDK, Prisma queries, API key validation, authentication +- Client components: Chat UI, Echo provider, interactive elements + +NEVER import `@merit-systems/echo-next-sdk` or `@prisma/client` in client components. NEVER expose database queries or API keys to the client. + +## Project Structure + +Follow this structure: + +``` +prisma/ + schema.prisma # Database schema + migrations/ # Database migrations +src/ + generated/ + prisma/ # Generated Prisma client + app/ + api/ + echo/[...echo]/route.ts # Echo auth handlers + chat/route.ts # Streaming chat endpoint + layout.tsx + page.tsx + components/ + ai-elements/ # Chat UI components + echo-button.tsx # Echo integration components + echo/ + index.ts # Server-side Echo initialization + lib/ + db.ts # Prisma client singleton + utils.ts # Shared utilities + providers.tsx # Client providers +``` + +## Error Handling + +ALWAYS handle errors explicitly and provide meaningful HTTP status codes: + +```typescript +try { + const result = await prisma.user.findUnique({ where: { apiKey } }); + if (!result) { + return new Response(JSON.stringify({ error: 'Invalid API key' }), { status: 401 }); + } + // proceed +} catch (error) { + console.error('Database error:', error); + return new Response( + JSON.stringify({ error: 'Internal server error' }), + { status: 500, headers: { 'Content-Type': 'application/json' } } + ); +} +``` + +## TypeScript Guidelines + +- Use strict typing and avoid `any`. +- Use Prisma-generated types for database models. +- Export explicit types for shared data structures. + +## Testing + +NEVER call external services or the real database in unit tests. ALWAYS mock Prisma and the Echo SDK: + +```typescript +vi.mock('@/lib/db', () => ({ + prisma: { user: { findUnique: vi.fn(), create: vi.fn() } }, +})); + +vi.mock('@/echo', () => ({ + openai: vi.fn(() => mockModel), +})); +``` diff --git a/templates/react-chat/.cursor/rules/echo_rules.mdc b/templates/react-chat/.cursor/rules/echo_rules.mdc new file mode 100644 index 000000000..236666262 --- /dev/null +++ b/templates/react-chat/.cursor/rules/echo_rules.mdc @@ -0,0 +1,178 @@ +--- +description: Guidelines and best practices for building Echo React chat applications with Vite, including SDK initialization, chat UI patterns, environment variables, and component architecture +globs: **/*.ts,**/*.tsx,**/*.js,**/*.jsx +--- + +# Echo React Chat (Vite) Guidelines + +## Architecture + +This is a client-side React chat application built with Vite and the Echo React SDK. It provides a streaming chat interface with AI billing and user management through Echo. + +### Key Dependencies + +- `@merit-systems/echo-react-sdk` for Echo integration (provider, auth, UI) +- `@ai-sdk/react` for React chat hooks (useChat) +- `ai` (Vercel AI SDK v5) for streaming and model interaction +- `react` and `react-dom` for the UI framework +- `vite` for the build tool +- Radix UI components for the UI layer + +## SDK Initialization + +### EchoProvider Setup + +ALWAYS wrap your application with `EchoProvider` at the root level in `src/main.tsx`: + +```typescript +import { StrictMode } from 'react'; +import { createRoot } from 'react-dom/client'; +import { EchoProvider } from '@merit-systems/echo-react-sdk'; +import App from './App.tsx'; + +createRoot(document.getElementById('root')!).render( + + + + + +); +``` + +## Environment Variables + +ALWAYS store your Echo App ID in `.env`: + +```bash +VITE_ECHO_APP_ID=your_echo_app_id +``` + +NEVER hardcode API keys or app IDs. ALWAYS use `import.meta.env.VITE_*` environment variables. + +Note: Vite only exposes variables prefixed with `VITE_` to client code. NEVER store server secrets in `VITE_` prefixed variables as they are bundled into the client. + +## Chat Implementation + +### Chat Component + +Use `useChat` from `@ai-sdk/react` for chat state management: + +```typescript +import { useChat } from '@ai-sdk/react'; + +export function Chat() { + const { messages, input, handleInputChange, handleSubmit } = useChat({ + api: '/api/chat', + }); + // render chat UI +} +``` + +### AI UI Elements + +This template includes reusable AI UI components in `src/components/ai-elements/`: + +- `conversation.tsx` - Chat conversation container +- `prompt-input.tsx` - User input with model selection +- `response.tsx` - AI response rendering +- `code-block.tsx` - Syntax-highlighted code blocks +- `sources.tsx` - Source citation display +- `suggestion.tsx` - Suggested prompts +- `task.tsx` - Task/tool execution display +- `image.tsx` - Image generation display + +ALWAYS use these existing components rather than building custom equivalents. + +## Client-Side Architecture + +This is entirely a client-side application. All Echo interactions happen through the React SDK: + +- Use `@merit-systems/echo-react-sdk` for all Echo functionality. +- The `EchoProvider` manages authentication state and token management. +- Use Echo UI components for user-facing Echo features. + +NEVER attempt to use `@merit-systems/echo-next-sdk` in this project. That package is exclusively for Next.js server-side usage. + +## Echo UI Components + +Use the shared Echo UI components in `src/components/`: + +- `echo-button.tsx` - Echo sign-in button +- `echo-popover.tsx` - Account popover menu +- `balance.tsx` - Token balance display +- `money-input.tsx` - Currency input for top-ups +- `logo.tsx` - Echo logo component + +## Component Patterns + +### Separation of Concerns + +- Keep Echo provider setup in `src/main.tsx`. +- Keep the main chat logic in `src/chat.tsx`. +- Keep the app header/navigation in `src/header.tsx`. +- Keep Echo-specific components in `src/components/`. +- Keep AI chat UI elements in `src/components/ai-elements/`. + +## Project Structure + +Follow this structure: + +``` +src/ + main.tsx # Entry point with EchoProvider + App.tsx # Root component + chat.tsx # Chat implementation + header.tsx # App header/navigation + components/ + ai-elements/ # Chat UI components + echo-button.tsx # Echo integration components + echo-popover.tsx + balance.tsx + lib/ + utils.ts # Shared utilities + currency-utils.ts # Currency formatting +``` + +## Error Handling + +ALWAYS handle errors explicitly and provide meaningful feedback: + +```typescript +try { + const result = await someOperation(); + return result; +} catch (error) { + console.error('Operation failed:', error); + // Show user-friendly error message +} +``` + +## TypeScript Guidelines + +- Use strict typing and avoid `any`. +- Export explicit types for shared data structures. +- Use `as const` for string literals in discriminated union types. + +## Vite Configuration + +Use the standard Vite React configuration with TypeScript: + +```typescript +import { defineConfig } from 'vite'; +import react from '@vitejs/plugin-react'; + +export default defineConfig({ + plugins: [react()], +}); +``` + +## Testing + +NEVER call external services in unit tests. ALWAYS mock the Echo SDK: + +```typescript +vi.mock('@merit-systems/echo-react-sdk', () => ({ + EchoProvider: ({ children }: { children: React.ReactNode }) => <>{children}, + EchoTokens: () =>
, +})); +``` diff --git a/templates/react-image/.cursor/rules/echo_rules.mdc b/templates/react-image/.cursor/rules/echo_rules.mdc new file mode 100644 index 000000000..521e2258e --- /dev/null +++ b/templates/react-image/.cursor/rules/echo_rules.mdc @@ -0,0 +1,174 @@ +--- +description: Guidelines and best practices for building Echo React image generation applications with Vite, including SDK initialization, image generation patterns, and component architecture +globs: **/*.ts,**/*.tsx,**/*.js,**/*.jsx +--- + +# Echo React Image Generation (Vite) Guidelines + +## Architecture + +This is a client-side React application built with Vite for AI-powered image generation using the Echo React SDK. It provides image generation with automatic billing and user management through Echo. + +### Key Dependencies + +- `@merit-systems/echo-react-sdk` for Echo integration (provider, auth, UI) +- `@ai-sdk/react` for React hooks +- `ai` (Vercel AI SDK v5) for model interaction +- `react` and `react-dom` for the UI framework +- `vite` for the build tool +- Radix UI components for the UI layer + +## SDK Initialization + +### EchoProvider Setup + +ALWAYS wrap your application with `EchoProvider` at the root level in `src/main.tsx`: + +```typescript +import { StrictMode } from 'react'; +import { createRoot } from 'react-dom/client'; +import { EchoProvider } from '@merit-systems/echo-react-sdk'; +import App from './App.tsx'; + +createRoot(document.getElementById('root')!).render( + + + + + +); +``` + +## Environment Variables + +ALWAYS store your Echo App ID in `.env`: + +```bash +VITE_ECHO_APP_ID=your_echo_app_id +``` + +NEVER hardcode API keys or app IDs. ALWAYS use `import.meta.env.VITE_*` environment variables. + +Note: Vite only exposes variables prefixed with `VITE_` to client code. NEVER store server secrets in `VITE_` prefixed variables as they are bundled into the client. + +## Image Generation + +### Image Generation Component + +Keep image generation logic in `src/components/ImageGeneration.tsx`: + +```typescript +export function ImageGeneration() { + // Image prompt input, model selection, and generated image display +} +``` + +ALWAYS handle loading states and errors during image generation. Display appropriate feedback while images are being generated. + +## Client-Side Architecture + +This is entirely a client-side application. All Echo interactions happen through the React SDK: + +- Use `@merit-systems/echo-react-sdk` for all Echo functionality. +- The `EchoProvider` manages authentication state and token management. +- Use Echo UI components for user-facing Echo features. + +NEVER attempt to use `@merit-systems/echo-next-sdk` in this project. That package is exclusively for Next.js server-side usage. + +## Echo UI Components + +Use the shared Echo UI components in `src/components/`: + +- `echo-button.tsx` - Echo sign-in button +- `echo-popover.tsx` - Account popover menu +- `echo-account-react.tsx` - React-specific account management +- `echo-account.tsx` - Account display +- `balance.tsx` - Token balance display +- `money-input.tsx` - Currency input for top-ups +- `top-up-button.tsx` - Quick top-up button +- `logo.tsx` - Echo logo component + +### UI Primitives + +Reusable UI primitives are in `src/components/ui/`: + +- `skeleton.tsx` - Loading skeleton placeholders +- `input.tsx` - Styled input component +- `tooltip.tsx` - Tooltip component +- `popover.tsx` - Popover component +- `avatar.tsx` - User avatar component + +## Component Patterns + +### Separation of Concerns + +- Keep Echo provider setup in `src/main.tsx`. +- Keep the main app layout in `src/App.tsx`. +- Keep image generation in `src/components/ImageGeneration.tsx`. +- Keep Echo-specific components in `src/components/`. +- Keep UI primitives in `src/components/ui/`. + +## Project Structure + +Follow this structure: + +``` +src/ + main.tsx # Entry point with EchoProvider + App.tsx # Root component with layout + components/ + ImageGeneration.tsx # Image generation component + ui/ # Reusable UI primitives + echo-button.tsx # Echo integration components + echo-popover.tsx + echo-account-react.tsx + echo-account.tsx + balance.tsx + top-up-button.tsx + lib/ + utils.ts # Shared utilities + currency-utils.ts # Currency formatting +``` + +## Error Handling + +ALWAYS handle errors explicitly and provide meaningful feedback: + +```typescript +try { + const result = await generateImage(prompt); + return result; +} catch (error) { + console.error('Image generation failed:', error); + // Show user-friendly error message +} +``` + +## TypeScript Guidelines + +- Use strict typing and avoid `any`. +- Export explicit types for shared data structures. +- Use `as const` for string literals in discriminated union types. + +## Vite Configuration + +Use the standard Vite React configuration: + +```typescript +import { defineConfig } from 'vite'; +import react from '@vitejs/plugin-react'; + +export default defineConfig({ + plugins: [react()], +}); +``` + +## Testing + +NEVER call external services in unit tests. ALWAYS mock the Echo SDK: + +```typescript +vi.mock('@merit-systems/echo-react-sdk', () => ({ + EchoProvider: ({ children }: { children: React.ReactNode }) => <>{children}, +})); +``` diff --git a/templates/react/.cursor/rules/echo_rules.mdc b/templates/react/.cursor/rules/echo_rules.mdc new file mode 100644 index 000000000..5047d43c0 --- /dev/null +++ b/templates/react/.cursor/rules/echo_rules.mdc @@ -0,0 +1,148 @@ +--- +description: Guidelines and best practices for building Echo React (Vite) applications, including SDK initialization, provider setup, environment variables, and component patterns +globs: **/*.ts,**/*.tsx,**/*.js,**/*.jsx +--- + +# Echo React (Vite) Guidelines + +## SDK Initialization + +### EchoProvider Setup + +ALWAYS wrap your application with `EchoProvider` at the root level in `main.tsx`: + +```typescript +import { StrictMode } from 'react'; +import { createRoot } from 'react-dom/client'; +import App from './App.tsx'; +import { EchoProvider } from '@merit-systems/echo-react-sdk'; + +createRoot(document.getElementById('root')!).render( + + + + + +); +``` + +### Using Echo Components + +Use the pre-built Echo UI components from `@merit-systems/echo-react-sdk`: + +```typescript +import { EchoTokens } from '@merit-systems/echo-react-sdk'; + +function App() { + return ( + <> +

Welcome to Echo

+ + + ); +} +``` + +## Environment Variables + +ALWAYS store your Echo App ID in `.env`: + +```bash +VITE_ECHO_APP_ID=your_echo_app_id +``` + +NEVER hardcode API keys or app IDs directly in your code. ALWAYS use `import.meta.env.VITE_*` environment variables. + +Note: Vite only exposes environment variables prefixed with `VITE_` to client code. NEVER store server secrets in `VITE_` prefixed variables as they are bundled into the client. + +## Client-Side Architecture + +This is a client-side React application. All Echo interactions happen through the React SDK: + +- Use `@merit-systems/echo-react-sdk` for all Echo functionality. +- The `EchoProvider` manages authentication state and token management. +- Use Echo UI components (`EchoTokens`, etc.) for user-facing Echo features. + +NEVER attempt to use `@merit-systems/echo-next-sdk` in a Vite/React project. That package is exclusively for Next.js server-side usage. + +## Component Patterns + +### Echo-Aware Components + +When building components that interact with Echo, keep Echo logic isolated: + +```typescript +// CORRECT - Echo component handles its own concerns +import { EchoTokens } from '@merit-systems/echo-react-sdk'; + +export function TokenDisplay() { + return ( +
+ +
+ ); +} +``` + +### Separation of Concerns + +- Keep Echo provider setup in `main.tsx`. +- Keep Echo-specific components in a dedicated directory (e.g., `src/components/echo/`). +- Keep UI components separate from Echo integration logic. + +## Error Handling + +ALWAYS handle errors explicitly and provide meaningful feedback to users: + +```typescript +try { + const result = await someOperation(); + return result; +} catch (error) { + console.error('Operation failed:', error); + // Show user-friendly error message +} +``` + +## Project Structure + +Follow this structure for Echo React (Vite) projects: + +``` +src/ + App.tsx # Main application component + main.tsx # Entry point with EchoProvider + components/ # UI components + lib/ # Shared utilities + assets/ # Static assets +``` + +## TypeScript Guidelines + +- Use strict typing and avoid `any`. +- Export explicit types for shared data structures. +- Use `as const` for string literals in discriminated union types. + +## Vite Configuration + +Use the standard Vite React configuration: + +```typescript +import { defineConfig } from 'vite'; +import react from '@vitejs/plugin-react'; + +export default defineConfig({ + plugins: [react()], +}); +``` + +## Testing + +NEVER call external services directly in unit tests. ALWAYS mock the Echo SDK: + +```typescript +vi.mock('@merit-systems/echo-react-sdk', () => ({ + EchoProvider: ({ children }: { children: React.ReactNode }) => <>{children}, + EchoTokens: () =>
, +})); +```