Skip to content
Back to skills

Browser Llm Demo

ASecurity

Build single-HTML browser demos that call cloud LLM APIs directly (no backend required). Covers the 4-step pattern: API-style auto-detection (OpenAI Chat Completions vs Anthropic Messages), local CORS proxy for cloud LLMs that don't expose browser CORS, local vendor/ for big deps to avoid CDN flake, multi-step progress status to catch silent failures.

  • 2 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 6, 2026
ai-agentsjavascriptpythongojavanodefastapiapibackend

Works with

  • api

Security analysis

A92/100
  • mediumUses curl or wget to download content

Pro shows the line behind each finding and how to fix it

Scanned October 6, 2026

npx -y skills add Kairos-ai-agent/kairos-code --skill browser-llm-demo --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Browser Llm Demo?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Browser Llm Demo
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/kairos-ai-agent-browser-llm-demo/badge)](https://www.skillsdirectory.com/skills/kairos-ai-agent-browser-llm-demo)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: "browser-llm-demo"
description: "Build single-HTML browser demos that call cloud LLM APIs directly (no backend required). Covers the 4-step pattern: API-style auto-detection (OpenAI Chat Completions vs Anthropic Messages), local CORS proxy for cloud LLMs that don't expose browser CORS, local vendor/ for big deps to avoid CDN flake, multi-step progress status to catch silent failures."
priority: 0.5
imported-from: "hermes"
source-path: "hermes/skills/.archive/browser-llm-demo/SKILL.md"
---
# Browser-based LLM Demo

## When to use this skill

Trigger phrases: "build me a demo that calls [LLM]", "single HTML that uses the API", "browser can't
reach the LLM", "Failed to fetch on LLM call", "stuck on initializing", "wait until loaded forever".

Don't trigger for: a normal web app with a backend, an LLM evaluation harness, server-side tooling.

## The 4-step pattern (proven on storyboard-previs 2026-08)

### Step 1: Detect API style from URL

```javascript
const isAnthropic = /\/anthropic/i.test(baseUrl) || /anthropic\.com/i.test(baseUrl);

const url = isAnthropic
  ? `${baseUrl.replace(/\/+$/, '')}/v1/messages`
  : `${baseUrl.replace(/\/+$/, '')}/v1/chat/completions`;

const headers = { 'Content-Type':': 'application/json' };
let body;
if (isAnthropic) {
  headers['x-api-key'] = cfg.api_key;
  headers['anthropic-version'] = '2023-06-01';
  body = JSON.stringify({ model, max_tokens: 4096, messages: [{ role: 'user', content: prompt }] });
} else {
  headers['Authorization'] = `Bearer ${cfg.api_key}`;
  body = JSON.stringify({ model, messages: [{ role: 'user', content: prompt }] });
}
```

Response parsing:
- Anthropic: `data.content?.map(c => c.text || '').join('')`
- OpenAI:    `data.choices?.[0]?.message?.content`

### Step 2: Local CORS proxy for cloud LLMs

Most cloud LLM APIs don't expose `Access-Control-Allow-Origin` for browsers. Fix: 10-line FastAPI
proxy on `localhost:8765` that forwards `/v1/...` → upstream with permissive CORS.

See `scripts/local_proxy.py` for the template.

User experience: demo base_url is `http://localhost:8765`, user starts proxy with
`python proxy.py` then opens the HTML. Curl test against the real cloud URL still works for
verification; browser path goes through localhost.

### Step 3: Local `vendor/` instead of CDN

`importmap` + ES module + `https://unpkg.com/...` fails silently in 3 common scenarios:
- Headless browsers (browserbase etc.) — ES module on file:// may not execute
- China networks — unpkg.com frequently times out
- Offline machines

Reliable pattern:
```
project/
├── index.html
├── vendor/
│   └── three.min.js        # downloaded once via curl
└── proxy.py
```
Reference: `<script src="./vendor/three.min.js"></script>` — UMD, no module system needed.

### Step 4: Progress checkpoints at every step

Status `<div>` updated by every step. When "stuck on initializing" hits, you know exactly which step failed:

```javascript
const _step = (msg) => {
  const el = document.getElementById('status');
  if (el) el.textContent = msg;
};
_step('loading engine…');
const THREE = window.THREE;
_step('engine ready');
_step('init scene');
init();
_step('loading sample');
loadSample();
_step('▶ playing');
```

Wrap the whole thing in try/catch that paints the status red with the error message. Don't let
silent failures leave a user staring at "initializing…" for 30 seconds.

## Pitfalls (load-bearing — re-read before every new demo)

### ❌ Backticks in template literals silently break scripts

WRONG:
```javascript
const SYSTEM_PROMPT = `...don't use \`\`\`json blocks...`;
//                                                          ^^^^^^^^
// Browser parses first \` as end of template literal, "json" as identifier → SyntaxError
// ENTIRE <script> block is skipped — no console error, just frozen UI
```

RIGHT (describe in prose):
```javascript
const SYSTEM_PROMPT = `...don't use triple-backtick + json + triple-backtick blocks...`;
```

RIGHT (escape):
```javascript
const SYSTEM_PROMPT = `...don't use \`\`\`json\`\`\` blocks...`;
```

**Symptom**: status stays on HTML default value forever. Adding `console.log` inside the script
shows nothing logged. Browser DevTools → Console shows nothing (it's a parse error, not runtime).

**Detection before shipping**: extract the inline `<script>` content to a `.js` file, run
`node -c file.js`. Node is strict; browser is forgiving but execution stops silently.

### ❌ Headless browser screenshots ≠ real-browser validation

browserbase (and most cloud browser tools) have inconsistent ES module / importmap / file:// CORS
handling. A demo that "looks broken" in headless may work fine in Chrome on the user's laptop,
and vice versa. Don't conclude a bug from headless alone — always also `node -c` for syntax,
and ask user to test in their actual browser.

### ❌ importmap + ES module on file:// is fragile

Just use plain `<script src="./vendor/lib.umd.min.js">` and read `window.Lib`. Saves hours.

### ❌ "等待加载" as initial status reads as a bug

User feedback (2026-08-14): a page that opens to "等待加载" / "Waiting for input" looks broken
even when it isn't. Either:
- Auto-trigger something on load (load sample + auto-play), OR
- Show actionable instructions ("点「示例」体验 / 「LLM 解析」处理你的分镜")

### ❌ Don't conflate different LLM API styles by URL

Mistakes observed (2026-08):
- `/v1/chat/completions` for MiniMax → 404 (MiniMax only does Anthropic-compatible)
- `/anthropic/v1/chat/completions` → 404 (mixed style — Anthropic path with OpenAI resource)
- Only `/anthropic/v1/messages` works for MiniMax
- Hermes's `~/.hermes/.env` shows `MINIMAX_CN_BASE_URL=https://api.minimaxi.com/v1` — the SDK
  internally rewrites this to `/anthropic/v1/messages`. Don't copy the bare URL into a browser
  config; copy the SDK path convention.

## Verification checklist (run before declaring done)

- [ ] `node -c` on extracted inline script content → syntax OK
- [ ] Test "test connection" button reports HTTP status (not `Failed to fetch`)
- [ ] Error messages show: URL, HTTP status, response body snippet, detected API style
- [ ] LLM call surfaces a clear error if JSON parse fails (position + context window)
- [ ] No `unpkg.com` / `cdn.jsdelivr.net` references in shipped HTML
- [ ] Auto-loads sample on page open (or shows clear instructions)
- [ ] Progress status updates visible at each step
- [ ] CORS proxy starts cleanly: `curl http://localhost:8765/` returns the proxy's status JSON

## File layout that works

```
project/
├── index.html              # main app (single file)
├── proxy.py                # CORS proxy on 8765
└── vendor/
    └── three.min.js        # ~655KB, downloaded once via curl
```

## Related skills

- `agentic-coding` — for the surrounding dev workflow / acceptance criteria
- `debug-pro` — for when "stuck on initializing" turns into a deeper investigation
- `using-superpowers` — meta, but read first

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…