OpenUI generative UI with Go (net/http) backend. Direct OpenAI API streaming via HTTP.
Scanned 9/6/2026
Install to Claude Code
npx -y skills add OthmanAdi/openui-forge --skill openui-forge-go --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Openui Forge Go?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/othmanadi-openui-forge-go-d4db5bcc)More formats (shields.io, HTML) on the badges page.
---
name: openui-forge-go
description: OpenUI generative UI with Go (net/http) backend. Direct OpenAI API streaming via HTTP.
version: 1.2.0
author: OthmanAdi
---
# 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:
```bash
npm install @openuidev/react-ui @openuidev/react-headless @openuidev/react-lang lucide-react zod
```
2. Generate the system prompt:
```bash
npx @openuidev/cli generate ./src/lib/library.ts --out backend/system-prompt.txt
```
3. Create the Go backend (see Full Code below)
4. 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`
```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`
```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
```bash
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
| 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 the `bufio.Scanner` loop writes and flushes each line |
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!