
Security News
Feross on Risky Business Weekly Podcast: npm’s Ongoing Supply Chain Attacks
Socket CEO Feross Aboukhadijeh joins Risky Business Weekly to unpack recent npm phishing attacks, their limited impact, and the risks if attackers get smarter.
shadowboxin
Advanced tools
Shadowboxin: Utils for real-time streamed LLM-generated UIs.
Bring your own component registry (BYO) and let an engine render UI described by model output.
This is an active WIP, and probably unrealiable right now
shadowboxin/client
– prompt + adapter/provider wiringshadowboxin/engine
– runtime that renders model-emitted UIshadowboxin/template-models
– schema helpers/validatorsshadowboxin/template-utils
– registry helpers and component bindingsnpm install shadowboxin zod react react-dom
Assumes a React app (Vite recommended). Shadowboxin ships ESM with subpath exports only (no root entry).
Create src/sbx/registry.tsx
:
import { z } from "zod"
import type { ComponentType, ReactNode } from "react"
import { createTemplateRegistry } from "shadowboxin/template-utils"
import { templateValidatorFor, parentValidatorFor } from "shadowboxin/template-models"
/** ───────── Paragraph ───────── */
type ParagraphProps = { content: string }
const Paragraph: ComponentType<ParagraphProps> = ({ content }) => <p>{content}</p>
export const ParagraphSet = {
type: "paragraph",
component: Paragraph,
templateValidator: templateValidatorFor("paragraph", { content: z.string().min(1) }),
instructions: {
generalUsage: "Use for body copy.",
fields: { content: "The paragraph text." }
}
}
/** ───────── Container ───────── */
type ContainerProps = { children?: ReactNode }
const Container: ComponentType<ContainerProps> = ({ children }) => (
<div data-sbx="container">{children}</div>
)
export const ContainerSet = {
type: "container",
component: Container,
templateValidator: parentValidatorFor("container"),
instructions: { generalUsage: "Groups other elements." }
}
/** ───────── Button ───────── */
type ButtonProps = { label: string; onSubmit: (payloads: unknown[]) => void }
const Button: ComponentType<ButtonProps> = ({ label, onSubmit }) => (
<button type="button" onClick={() => onSubmit([])}>{label}</button>
)
export const ButtonSet = {
type: "button",
component: Button,
templateValidator: templateValidatorFor("button", { label: z.string().min(1) }),
instructions: {
generalUsage: "Simple submit button; no fields.",
fields: { label: "Button text." }
}
}
/** ───────── Registry ───────── */
export const registry = createTemplateRegistry(ContainerSet, ParagraphSet, ButtonSet)
Create src/sbx/setup.ts
:
import {
createAgentsProvider,
createEngineAdapter,
generateSystemPrompt,
type ChatMessage,
type EnginePort
} from "shadowboxin/client"
import { createEngine } from "shadowboxin/engine"
import { registry } from "./registry"
// Minimal example JSON the assistant could emit (Container → Paragraph + Button)
export const minimalExample = {
id: "container",
children: [
{ id: "paragraph", content: "Hello from Shadowboxin." },
{ id: "button", label: "Continue" }
]
} as const
// Build a system prompt using your registry instructions and the example JSON
const SYSTEM_PROMPT = generateSystemPrompt(
"You respond by emitting UI templates only.",
registry.instructions,
{ exampleJSON: minimalExample }
)
/** Local demo provider that yields one JSON response (no network). */
const provider = createAgentsProvider(async function* (_messages: ChatMessage[]) {
// In production, plug in your streamed LLM responses here and yield deltas.
yield JSON.stringify(minimalExample)
})
export async function startShadowboxin(root: HTMLElement) {
let adapter!: ReturnType<typeof createEngineAdapter>
const engine = await createEngine({
registry,
rootNode: root,
onSubmit: (payloads) => adapter.submit(payloads),
debug: false
})
const port: EnginePort = {
next: (d) => engine.push(d),
reset: () => engine.reset()
}
adapter = createEngineAdapter(port, provider, {
systemPrompt: SYSTEM_PROMPT,
initialUserMessage: "Render the minimal example."
})
await adapter.run()
}
Create src/main.tsx
:
import { StrictMode, useEffect, useRef } from "react"
import { createRoot } from "react-dom/client"
import { startShadowboxin } from "./sbx/setup"
function App() {
const ref = useRef<HTMLDivElement>(null)
useEffect(() => {
if (ref.current) startShadowboxin(ref.current)
}, [])
return <div ref={ref} id="gen-ui-root" />
}
createRoot(document.getElementById("root")!).render(
<StrictMode>
<App />
</StrictMode>
)
Create src/sbx/example.json
(optional, for reference):
{
"id": "container",
"children": [
{ "id": "paragraph", "content": "Hello from Shadowboxin." },
{ "id": "button", "label": "Continue" }
]
}
FAQs
Shadowboxin: Utils for real-time streamed LLM-generated UIs.
The npm package shadowboxin receives a total of 33 weekly downloads. As such, shadowboxin popularity was classified as not popular.
We found that shadowboxin demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Socket CEO Feross Aboukhadijeh joins Risky Business Weekly to unpack recent npm phishing attacks, their limited impact, and the risks if attackers get smarter.
Product
Socket’s new Tier 1 Reachability filters out up to 80% of irrelevant CVEs, so security teams can focus on the vulnerabilities that matter.
Research
/Security News
Ongoing npm supply chain attack spreads to DuckDB: multiple packages compromised with the same wallet-drainer malware.