원클릭으로
openui-forge-go
// OpenUI generative UI with Go (net/http) backend. Direct OpenAI API streaming via HTTP.
// OpenUI generative UI with Go (net/http) backend. Direct OpenAI API streaming via HTTP.
OpenUI generative UI with Anthropic Claude SDK backend. Stream conversion to OpenAI NDJSON format.
OpenUI generative UI with LangChain/LangGraph backend. Supports ChatOpenAI and ChatAnthropic.
OpenUI generative UI with OpenAI SDK backend. Streaming chat completions with gpt-5.5 (or any current OpenAI-compatible model).
OpenUI generative UI with Python FastAPI backend. OpenAI and Anthropic SDK variants.
OpenUI generative UI with Rust Axum backend. Async SSE streaming with reqwest and async-stream.
Build generative UI with OpenUI — any LLM provider, any backend language. Scaffold, integrate, validate.
| name | openui-forge-go |
| description | OpenUI generative UI with Go (net/http) backend. Direct OpenAI API streaming via HTTP. |
| version | 1.0.0 |
| author | OthmanAdi |
Build generative UI apps with a React frontend + Go backend. Streams OpenAI API responses directly via net/http.
OPENAI_API_KEY environment variable setnpm install @openuidev/react-ui @openuidev/react-headless @openuidev/react-lang lucide-react zod
npx @openuidev/cli generate ./src/lib/library.ts --out backend/system-prompt.txt
go run main.go on :8080, frontend on :3000backend/go.modmodule openui-backend
go 1.23
require (
github.com/joho/godotenv v1.5.1
)
backend/main.gopackage main
import (
"bufio"
"bytes"
"encoding/json"
"fmt"
"log"
"net/http"
"os"
_ "github.com/joho/godotenv/autoload"
)
var systemPrompt string
func init() {
data, err := os.ReadFile("system-prompt.txt")
if err != nil {
log.Fatal("system-prompt.txt not found: ", err)
}
systemPrompt = string(data)
}
func corsMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", "http://localhost:3000")
w.Header().Set("Vary", "Origin")
w.Header().Set("Access-Control-Allow-Methods", "POST, OPTIONS")
w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization")
if r.Method == "OPTIONS" {
w.WriteHeader(204)
return
}
next.ServeHTTP(w, r)
})
}
type Message struct {
Role string `json:"role"`
Content string `json:"content"`
}
type ChatRequest struct {
Messages []Message `json:"messages"`
}
func chatHandler(w http.ResponseWriter, r *http.Request) {
if r.Method != "POST" {
http.Error(w, "Method not allowed", 405)
return
}
var req ChatRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
http.Error(w, "Bad request", 400)
return
}
messages := append([]Message{{Role: "system", Content: systemPrompt}}, req.Messages...)
model := os.Getenv("OPENAI_MODEL")
if model == "" {
model = "gpt-5.5"
}
body, _ := json.Marshal(map[string]interface{}{
"model": model, "stream": true, "messages": messages,
})
apiReq, _ := http.NewRequest("POST", "https://api.openai.com/v1/chat/completions", bytes.NewReader(body))
apiReq.Header.Set("Content-Type", "application/json")
apiReq.Header.Set("Authorization", "Bearer "+os.Getenv("OPENAI_API_KEY"))
resp, err := http.DefaultClient.Do(apiReq)
if err != nil {
http.Error(w, "OpenAI request failed", 502)
return
}
defer resp.Body.Close()
w.Header().Set("Content-Type", "text/event-stream")
w.Header().Set("Cache-Control", "no-cache")
w.Header().Set("Connection", "keep-alive")
flusher, ok := w.(http.Flusher)
if !ok {
http.Error(w, "Streaming not supported", 500)
return
}
// Forward upstream SSE line-by-line so the client sees tokens as they
// arrive instead of waiting for the whole stream to complete.
scanner := bufio.NewScanner(resp.Body)
scanner.Buffer(make([]byte, 0, 64*1024), 1024*1024)
for scanner.Scan() {
line := scanner.Bytes()
if _, err := w.Write(line); err != nil {
return
}
if _, err := w.Write([]byte("\n")); err != nil {
return
}
flusher.Flush()
}
}
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/api/chat", chatHandler)
fmt.Println("Go backend listening on :8080")
log.Fatal(http.ListenAndServe(":8080", corsMiddleware(mux)))
}
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="http://localhost:8080/api/chat"
/>
);
}
The Go backend forwards OpenAI's SSE stream verbatim (
io.Copy). Pair it withopenAIAdapter()on the frontend.openAIReadableStreamAdapter()is for NDJSON (nodata:prefix) and will silently produce no output here.
npx @openuidev/cli generate ./src/lib/library.ts --out backend/system-prompt.txt
system-prompt.txt exists in the Go backend directoryOPENAI_API_KEY is set in environment or .envapiUrl points to http://localhost:8080/api/chatstreamProtocol={openAIAdapter()} and openAIMessageFormatcomponentLibrary={openuiChatLibrary} prop passed to FullScreen@openuidev/react-ui/components.css)| Error | Cause | Fix |
|---|---|---|
| CORS blocked | Origin mismatch | Update Access-Control-Allow-Origin in middleware |
system-prompt.txt not found | File missing from backend dir | Run CLI generate command |
| 502 Bad Gateway | OpenAI API unreachable or key invalid | Check OPENAI_API_KEY and network |
| Stream not flushing | Missing http.Flusher | Ensure handler calls flusher.Flush() |
| Empty response | Body not forwarded | Verify io.Copy pipes OpenAI response to client |