Echo
Getting Started

Next.js

Use Echo to make monetized AI Next.js apps.

Getting Started with Next.js

Install the Echo Next SDK

npm i @merit-systems/echo-next-sdk
yarn add @merit-systems/echo-next-sdk
pnpm add @merit-systems/echo-next-sdk
bun add @merit-systems/echo-next-sdk

Install Vercel AI SDK

npm i ai
yarn add ai
pnpm add ai
bun add ai

Add Echo configuration file

index.ts
src/echo/index.ts
import Echo from "@merit-systems/echo-next-sdk";

export const { handlers, isSignedIn, openai, anthropic } = Echo({
    appId: "YOUR_ECHO_APP_ID", // from previous step
});

Add Echo Routes

route.ts
src/app/api/echo/[...echo]/route.ts
import { handlers } from "@/echo";
export const { GET, POST } = handlers;

Sign In From Client

Create an action in the front-end that redirects users to authorize your application with echo.merit.systems.

app/page.tsx
import { signIn, isSignedIn } from "@merit-systems/echo-next-sdk/client";

export default Home() {
    if (!isSignedIn()) {
        return <button onClick={() => signIn()}>Sign In</button>
    }
    return (
        <div>
            <p>Monetization Activated 📈</p> 
        </div>
    )
}

Sign in will hit the route we setup in Step 4 and redirect from the server.

Use generateText / streamText from the server

Echo is a standard Vercel AI SDK provider.

route.ts

Add Vercel AI SDK server routes with Echo providers.

app/api/completion/route.ts
import { openai } from "@/echo";
import { convertToModelMessages, streamText } from "ai";

export async function POST(req: Request) {
    const { messages } = await req.json();

    const result = streamText({
        model: openai("gpt-5"), 
        messages: convertToModelMessages(messages),
    });

    return result.toUIMessageStreamResponse();
}

useChat() from the client

app/components/chat.tsx
"use client";

import { useChat } from "@ai-sdk/react";
import { useState } from "react";

export default function Chat() {
    const [input, setInput] = useState("");
    const { messages, sendMessage } = useChat();
    return (
        <div>
			{messages.map((message) => (
				<div>{JSON.stringify(message)}</div>
			))}
			<input value={input} onChange={(e) => setInput(e.currentTarget.value)} />
			<button type="submit" onClick={() => sendMessage({ text: input })}>Send</button>
        </div>
    );
}

Then add use it on the authenticated page.

app/page.tsx
import Chat from "./components/chat";
import { signIn, isSignedIn } from "@merit-systems/echo-next-sdk/client";


export default Home() {
    if (!isSignedIn()) {
        return <button onClick={() => signIn()}>Sign In</button>
    }
    return <Chat />;
    return (
        <div> Monetization Activated 📈</div>
    )
    
}

Next Steps

For detailed documentation and advanced features, see the Next.js SDK overview.