Skip to content
cccskills
FreePublished on GitHub

openui-forge-rust

OpenUI generative UI with Rust Axum backend. Async SSE streaming with reqwest and async-stream.

The English summary is being prepared. Showing the original description.

Works withOpenAI
See how to install

Files included (1)

  • SKILL.md6.5 KB

SKILL.md (original)

Review the instructions the agent will receive before you install.

OpenUI Forge — Rust

Build generative UI apps with a React frontend + Rust Axum backend. Async SSE streaming to OpenAI-compatible NDJSON.

Activation Triggers

  • "openui rust", "openui axum", "openui rust backend"
  • "generative ui rust", "rust streaming ui backend"

Prerequisites

  • Node.js >= 22 (24 LTS recommended) + React >= 18.3.1 (19+ recommended) (frontend)
  • Rust >= 1.75 with Cargo (backend)
  • 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 Rust backend (see Full Code below)
  2. Run: cargo run on :3001, frontend on :3000

Full Code

Backend: backend/Cargo.toml

[package]
name = "openui-backend"
version = "0.1.0"
edition = "2021"

[dependencies]
axum = "0.8"
http = "1"
tokio = { version = "1", features = ["full"] }
reqwest = { version = "0.13", features = ["json", "stream"] }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
async-stream = "0.3"
futures = "0.3"
tower-http = { version = "0.6", features = ["cors"] }
dotenvy = "0.15"

Backend: backend/src/main.rs

use axum::{
    extract::{Json, State},
    response::sse::{Event, Sse},
    routing::post,
    Router,
};
use futures::stream::Stream;
use http::HeaderValue;
use reqwest::Client;
use serde::{Deserialize, Serialize};
use std::{convert::Infallible, fs, net::SocketAddr, sync::Arc};
use tower_http::cors::{Any, CorsLayer};

#[derive(Deserialize)]
struct ChatRequest {
    messages: Vec<Message>,
}

#[derive(Serialize, Deserialize, Clone)]
struct Message {
    role: String,
    content: String,
}

#[derive(Clone)]
struct AppState {
    system_prompt: String,
}

#[tokio::main]
async fn main() {
    dotenvy::dotenv().ok();
    let system_prompt = fs::read_to_string("system-prompt.txt")
        .expect("system-prompt.txt not found");
    let state = Arc::new(AppState { system_prompt });

    let cors = CorsLayer::new()
        .allow_origin("http://localhost:3000".parse::<HeaderValue>().unwrap())
        .allow_methods([http::Method::POST])
        .allow_headers(Any);

    let app = Router::new()
        .route("/api/chat", post(chat_handler))
        .layer(cors)
        .with_state(state);

    let addr = SocketAddr::from(([0, 0, 0, 0], 3001));
    println!("Rust backend listening on {addr}");
    let listener = tokio::net::TcpListener::bind(addr).await.unwrap();
    axum::serve(listener, app).await.unwrap();
}

async fn chat_handler(
    State(state): State<Arc<AppState>>,
    Json(req): Json<ChatRequest>,
) -> Sse<impl Stream<Item = Result<Event, Infallible>>> {
    let mut messages = vec![Message { role: "system".into(), content: state.system_prompt.clone() }];
    messages.extend(req.messages);

    let api_key = std::env::var("OPENAI_API_KEY").expect("OPENAI_API_KEY not set");
    let client = Client::new();

    let stream = async_stream::stream! {
        let resp = client
            .post("https://api.openai.com/v1/chat/completions")
            .bearer_auth(&api_key)
            .json(&serde_json::json!({
                "model": std::env::var("OPENAI_MODEL").unwrap_or_else(|_| "gpt-5.5".into()),
                "stream": true,
                "messages": messages,
            }))
            .send()
            .await;

        if let Ok(resp) = resp {
            let mut bytes_stream = resp.bytes_stream();
            use futures::StreamExt;
            let mut buffer = String::new();
            while let Some(Ok(chunk)) = bytes_stream.next().await {
                buffer.push_str(&String::from_utf8_lossy(&chunk));
                while let Some(pos) = buffer.find("\n\n") {
                    let line = buffer[..pos].to_string();
                    buffer = buffer[pos + 2..].to_string();
                    if line.starts_with("data: ") {
                        yield Ok(Event::default().data(&line[6..]));
                    }
                }
            }
        }
    };

    Sse::new(stream)
}

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:3001/api/chat"
    />
  );
}

The Rust backend re-emits SSE via Axum's Sse<...> response (Axum wraps each Event::default().data(...) with the data: prefix). Pair it with openAIAdapter() on the frontend. openAIReadableStreamAdapter() is for NDJSON and will silently produce no output here.

System Prompt Generation

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

Validation Checklist

  • system-prompt.txt exists in the Rust backend directory
  • OPENAI_API_KEY is set in environment or .env
  • CORS layer allows the frontend origin
  • SSE events forward OpenAI stream chunks correctly
  • Buffer parsing handles partial SSE lines across chunk boundaries
  • Frontend apiUrl points to http://localhost:3001/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
system-prompt.txt not foundFile missingRun CLI generate command
CORS blockedOrigin not in CorsLayerUpdate .allow_origin()
Partial SSE eventsChunk boundary splittingBuffer and split on \n\n boundaries (handled in code)
Compile error on http::HeaderValueMissing http crateAdd http = "1" to Cargo.toml (already in the example) or import from axum::http
static_mut_refs warning on static mutRust 2024 deprecates raw static mut accessUse OnceLock<String> or carry state in State<Arc<AppState>> (this example uses the latter)
Connection resetTokio runtime panicCheck .await on all async calls, verify features = ["full"]

Reviews

No reviews yet. Tell others what you thought.

Comments

No login needed. Share how it worked for you, ask a question, or note where it did not run.

No comments yet. Be the first to write one.

Comments are published right away. Do not include personal information such as email addresses or phone numbers. Up to 2 URLs.

0 / 1,000 characters

This form is protected by reCAPTCHA, and the Google Privacy Policy and Terms of Service apply.

More skills from this repository

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

The English summary is being prepared. Showing the original description.

OthmanAdi/openui-forge22Updated Aug 3, 2026

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

The English summary is being prepared. Showing the original description.

OthmanAdi/openui-forge22Updated Aug 3, 2026

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

The English summary is being prepared. Showing the original description.

OthmanAdi/openui-forge22Updated Aug 3, 2026

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

The English summary is being prepared. Showing the original description.

OthmanAdi/openui-forge22Updated Aug 3, 2026

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

The English summary is being prepared. Showing the original description.

OthmanAdi/openui-forge22Updated Aug 3, 2026

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

The English summary is being prepared. Showing the original description.

OthmanAdi/openui-forge22Updated Aug 3, 2026

See all skills by OthmanAdi

Report a problem with this skill