Now liveThe Skillselion MCP - thousands of ranked skills, loaded into your agent mid-task. No install.Get it →
othmanadi avatar

Openui Forge Langchain

  • 11 installs
  • 20 repo stars
  • Updated August 3, 2026
  • othmanadi/openui-forge

Helps with ai & agent building tasks during AI-assisted development.

About

openui-forge-langchain is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted coding.

  • openui-forge-langchain
  • AI & Agent Building
  • AI-coding skill

Openui Forge Langchain by the numbers

  • 11 all-time installs (skills.sh)
  • +1 installs in the week ending Aug 4, 2026 (Skillselion tracking)
  • Ranked #11,740 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
  • Data as of Aug 4, 2026 (Skillselion catalog sync)
npx skills add https://github.com/othmanadi/openui-forge --skill openui-forge-langchain

Add your badge

Show developers this skill is listed on Skillselion. Paste this into your README.

Listed on Skillselion
Installs11
repo stars20
Last updatedAugust 3, 2026
Repositoryothmanadi/openui-forge

What it does

Helps with ai & agent building tasks during AI-assisted development.

Files

SKILL.mdMarkdownGitHub ↗

OpenUI Forge — LangChain

Build generative UI apps with OpenUI + LangChain. Stream from ChatOpenAI or ChatAnthropic, convert to OpenAI NDJSON.

Activation Triggers

  • "openui langchain", "openui langgraph", "openui langsmith"
  • "generative ui langchain", "langchain streaming ui"

Prerequisites

  • Node.js >= 22 (24 LTS recommended), React >= 18.3.1 (19+ recommended)
  • OPENAI_API_KEY or ANTHROPIC_API_KEY set
  • Next.js project (App Router recommended)

Quick Start

1. Install dependencies (pick one or both LLM providers):

npm install @openuidev/react-ui @openuidev/react-headless @openuidev/react-lang lucide-react zod @langchain/openai @langchain/core
# For Anthropic: npm install @langchain/anthropic

2. Add the CSS import to app/layout.tsx:

import "@openuidev/react-ui/components.css";

3. Create the API route and frontend page below 4. Run npm run dev and test

Full Code

Backend (OpenAI): app/api/chat/route.ts

import { openuiChatLibrary } from "@openuidev/react-ui/genui-lib";
import { ChatOpenAI } from "@langchain/openai";
import { HumanMessage, SystemMessage, AIMessage } from "@langchain/core/messages";

const model = new ChatOpenAI({ model: process.env.OPENAI_MODEL ?? "gpt-5.5", streaming: true });

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

  const systemPrompt = openuiChatLibrary.prompt({
    preamble: "You are a helpful assistant that generates interactive UIs.",
  });

  const lcMessages = [
    new SystemMessage(systemPrompt),
    ...messages.map((m: { role: string; content: string }) =>
      m.role === "user" ? new HumanMessage(m.content) : new AIMessage(m.content)
    ),
  ];

  const stream = await model.stream(lcMessages);
  const encoder = new TextEncoder();
  const id = `chatcmpl-${Date.now()}`;

  const readableStream = new ReadableStream({
    async start(controller) {
      for await (const chunk of stream) {
        const text = typeof chunk.content === "string" ? chunk.content : "";
        if (!text) continue;
        const payload = {
          id,
          object: "chat.completion.chunk",
          choices: [{ index: 0, delta: { content: text }, finish_reason: null }],
        };
        controller.enqueue(encoder.encode(`data: ${JSON.stringify(payload)}\n\n`));
      }
      const done = {
        id,
        object: "chat.completion.chunk",
        choices: [{ index: 0, delta: {}, finish_reason: "stop" }],
      };
      controller.enqueue(encoder.encode(`data: ${JSON.stringify(done)}\n\n`));
      controller.enqueue(encoder.encode("data: [DONE]\n\n"));
      controller.close();
    },
  });

  return new Response(readableStream, {
    headers: { "Content-Type": "text/event-stream" },
  });
}

Backend (Anthropic variant): app/api/chat/route.ts

Replace the model initialization and import:

import { ChatAnthropic } from "@langchain/anthropic";

const model = new ChatAnthropic({
  model: process.env.ANTHROPIC_MODEL ?? "claude-sonnet-4-6",
  maxTokens: 4096,
  streaming: true,
});

Everything else (message mapping, stream conversion, response) stays identical.

Frontend: app/chat/page.tsx

"use client";
import { FullScreen } from "@openuidev/react-ui";
import { openuiChatLibrary } from "@openuidev/react-ui/genui-lib";
import {
  openAIAdapter,
  openAIMessageFormat,
} from "@openuidev/react-headless";

export default function ChatPage() {
  return (
    <FullScreen
      componentLibrary={openuiChatLibrary}
      streamProtocol={openAIAdapter()}
      messageFormat={openAIMessageFormat}
      apiUrl="/api/chat"
    />
  );
}
The backend emits SSE (data: {json}\n\n). Pair it with openAIAdapter() on the frontend. (langGraphAdapter is also exported from @openuidev/react-headless if you stream LangGraph events natively rather than converting to OpenAI shape.)

Component Creation

import { defineComponent } from "@openuidev/react-lang";
import { z } from "zod";

export const MetricCard = defineComponent({
  name: "MetricCard",
  description: "Displays a metric with label, value, and optional trend",
  props: z.object({
    label: z.string().describe("Metric name"),
    value: z.number().describe("Current metric value"),
    trend: z.enum(["up", "down", "flat"]).optional().describe("Trend direction"),
  }),
  component: ({ props }) => (
    <div style={{ padding: 16, border: "1px solid #e5e7eb", borderRadius: 8 }}>
      <div style={{ fontSize: 14, color: "#6b7280" }}>{props.label}</div>
      <div style={{ fontSize: 24, fontWeight: 700 }}>{props.value}</div>
      {props.trend && <span>{props.trend === "up" ? "+" : props.trend === "down" ? "-" : "="}</span>}
    </div>
  ),
});

System Prompt Generation

npx @openuidev/cli generate ./src/lib/library.ts --out src/generated/system-prompt.txt

Validation Checklist

  • [ ] LLM provider API key is set
  • [ ] @langchain/openai or @langchain/anthropic installed
  • [ ] Messages correctly mapped to LangChain message types
  • [ ] Stream chunks converted to OpenAI-compatible SSE with data: prefix
  • [ ] Final chunk has finish_reason: "stop" and ends with data: [DONE]
  • [ ] Frontend uses streamProtocol={openAIAdapter()} and openAIMessageFormat
  • [ ] CSS import in root layout

Error Patterns

ErrorCauseFix
Empty chunks in streamLangChain AIMessageChunk content may be emptySkip chunks where text is empty
Type error on messagesWrong LangChain message classMap user to HumanMessage, assistant to AIMessage
Module not foundMissing LangChain provider packageInstall @langchain/openai or @langchain/anthropic
Stream hangsMissing [DONE] sentinelAlways send final stop chunk and [DONE]
CORS errorCross-origin frontendAdd CORS headers if frontend/backend are split

Related skills

This week in AI coding

Five minutes, every Monday - the tools, releases and tactics for developers.

unsubscribe anytime.