本文へ移動
cccskills
無料GitHub で公開

openui-forge-go

OpenUI generative UI with Go (net/http) backend. Direct OpenAI API streaming via HTTP.

インストール方法を見る

含まれるファイル(1)

  • SKILL.md6.3 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

OpenUI Forge — Go

Build generative UI apps with a React frontend + Go backend. Streams OpenAI API responses directly via net/http.

Activation Triggers

  • "openui go", "openui golang", "openui go backend"
  • "generative ui go", "go streaming ui backend"

Prerequisites

  • Node.js >= 22 (24 LTS recommended) + React >= 18.3.1 (19+ recommended) (frontend)
  • Go >= 1.24 (backend; 1.23 and older are out of security support as of Go 1.26)
  • OPENAI_API_KEY environment variable set

Quick Start

  1. Create the React frontend and install OpenUI deps:
npm install @openuidev/react-ui @openuidev/react-headless @openuidev/react-lang lucide-react zod
  1. Generate the system prompt:
npx @openuidev/cli generate ./src/lib/library.ts --out backend/system-prompt.txt
  1. Create the Go backend (see Full Code below)
  2. Run: go run main.go on :8080, frontend on :3000

Full Code

Backend: backend/go.mod

module openui-backend

go 1.24

require (
    github.com/joho/godotenv v1.5.1
)

Backend: backend/main.go

package 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)))
}

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="http://localhost:8080/api/chat"
    />
  );
}

The Go backend forwards OpenAI's SSE stream line-by-line with a bufio.Scanner loop, flushing after each line (no io.Copy), so the client sees tokens as they arrive. Pair it with openAIAdapter() on the frontend. openAIReadableStreamAdapter() is for NDJSON (no data: prefix) and will silently produce no output here.

An official OpenAI Go SDK exists (github.com/openai/openai-go/v3, ~v3.41.0, requires Go 1.22+) as an alternative to hand-rolling the HTTP call. This skill keeps raw net/http as the dependency-free default. Note the SDK still ships small, limited breaking changes between releases (per its own README, some backwards-incompatible changes land in minor versions), so pin a version if you adopt it.

System Prompt Generation

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

Validation Checklist

  • system-prompt.txt exists in the Go backend directory
  • OPENAI_API_KEY is set in environment or .env
  • CORS middleware allows the frontend origin
  • Response streams SSE directly from OpenAI API (passthrough)
  • Frontend apiUrl points to http://localhost:8080/api/chat
  • Frontend uses streamProtocol={openAIAdapter()} and openAIMessageFormat
  • componentLibrary={openuiChatLibrary} prop passed to FullScreen
  • CSS import in root layout (@openuidev/react-ui/components.css)

Error Patterns

ErrorCauseFix
CORS blockedOrigin mismatchUpdate Access-Control-Allow-Origin in middleware
system-prompt.txt not foundFile missing from backend dirRun CLI generate command
502 Bad GatewayOpenAI API unreachable or key invalidCheck OPENAI_API_KEY and network
Stream not flushingMissing http.FlusherEnsure handler calls flusher.Flush()
Empty responseBody not forwardedVerify the bufio.Scanner loop writes and flushes each line

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

同じリポジトリのスキル

概要と使いどころ

Build generative UI with OpenUI — any LLM provider, any backend language. Scaffold, integrate, validate.

日本語の概要は準備中です。原文の説明を表示しています。

OthmanAdi/openui-forge222026年8月3日 更新

OpenUI generative UI with Anthropic Claude SDK backend. Stream conversion to OpenAI NDJSON format.

日本語の概要は準備中です。原文の説明を表示しています。

OthmanAdi/openui-forge222026年8月3日 更新

OpenUI generative UI with C# ASP.NET Core Minimal API backend. Direct OpenAI API SSE streaming via HttpClient on .NET 10.

日本語の概要は準備中です。原文の説明を表示しています。

OthmanAdi/openui-forge222026年8月3日 更新

OpenUI generative UI with Elixir Phoenix backend. Chunked SSE streaming via Plug.Conn and Req.

日本語の概要は準備中です。原文の説明を表示しています。

OthmanAdi/openui-forge222026年8月3日 更新

OpenUI generative UI with a Java Spring Boot (WebFlux) backend. Streams the OpenAI API directly via WebClient as SSE.

日本語の概要は準備中です。原文の説明を表示しています。

OthmanAdi/openui-forge222026年8月3日 更新

OpenUI generative UI with LangChain/LangGraph backend. Supports ChatOpenAI and ChatAnthropic.

日本語の概要は準備中です。原文の説明を表示しています。

OthmanAdi/openui-forge222026年8月3日 更新

OthmanAdi のスキルをすべて見る

このスキルの問題を報告する