create-fedi-app
Modules

ai-chat-gated

Optional module — streaming AI chat where each message costs sats. Invoice, WebLN payment, then Vercel AI SDK streamText.

Metered AI without subscriptions. Each user message triggers a Lightning invoice; after WebLN payment and preimage verification, the server streams an LLM response.

Files added

FilePurpose
lib/chat-payment.tsInvoice creation, payment verification
lib/ai/providers.tsVercel AI SDK provider factory
components/ai/PaymentGate.tsxPay-to-send wrapper
components/ai/GatedChat.tsxChat UI with payment gate
components/ai/ChatMessage.tsxMessage bubble component
app/api/chat/route.tsPOST — stream AI after payment check
app/api/chat/invoice/route.tsPOST — create per-message invoice
app/demo/ai-chat/page.tsxDemo page

Dependencies

  • ai, @ai-sdk/react, react-markdown
  • @ai-sdk/anthropic, @ai-sdk/openai, @ai-sdk/groq, ollama-ai-provider

Environment variables

KeyRequiredDescription
AI_PROVIDERyesanthropic | openai | groq | ollama
AI_API_KEYyes*Provider API key (*not for Ollama)
AI_MODELnoModel name override
AI_BASE_URLnoOllama/self-hosted endpoint
AI_SATS_PER_MESSAGEnoServer-side price (default from env)
NEXT_PUBLIC_SATS_PER_MESSAGEnoClient UI display price

Flow

1. User types message in GatedChat
2. PaymentGate fetches POST /api/chat/invoice
3. User pays invoice via WebLN
4. Client sends POST /api/chat with messages + payment proof
5. Server verifies payment, calls streamText(), returns SSE stream
6. GatedChat renders streaming response via @ai-sdk/react useChat

API routes

POST /api/chat/invoice

Returns a BOLT11 for one message at AI_SATS_PER_MESSAGE sats.

POST /api/chat

Accepts chat messages and payment verification headers. Returns streaming AI response on valid payment.

PaymentGate

Wraps message submission:

<PaymentGate onPaid={(proof) => submitMessage(proof)}>
  {(requestPayment, isPaying) => (
    <ChatInput onSubmit={requestPayment} disabled={isPaying} />
  )}
</PaymentGate>

Dev bypass

x-mock-preimage header in development skips WebLN for API testing.

See also

On this page