Skip to content

aietheia/ChatHTML

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

232 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

ChatHTML

ChatHTML

Beautiful AI responses, beyond plain Markdown.
Turn a prompt into a live, streaming interface that can explain, visualize, and interact.

try here


ChatHTML running an interactive poster studio

ChatHTML running an interactive color palette lab

ChatHTML running an interactive Bezier curve playground Β  ChatHTML running an interactive Pomodoro timer

ChatHTML running a playable 2048 game Β  ChatHTML running an interactive tip and split calculator


What is ChatHTML?

ChatHTML turns a normal message into a live, streaming HTML response. It progressively renders model-generated interfaces as they are written, so an answer can be explanatory, visual, interactive, or simply beautifully typeset.

It is focused on the response medium rather than reproducing a ChatGPT-style product or an app-builder workflow. The chat shell exists so any answer can become a sandboxed UI artifact.

  • Beautiful by default β€” responsive HTML, CSS, typography, and motion instead of a fenced code block.
  • Interactive β€” forms, controls, small vanilla scripts, and buttons that continue the conversation.
  • Private and contained β€” server keys stay server-side; generated artifacts run in a guarded sandbox.
  • Built for iteration β€” select, edit, regenerate, repair, copy, or export the result.
Plain Markdown vs. ChatHTML comparisons

Examples: Plain Markdown vs. ChatHTML

Each row starts from the same request; the response medium is different. The left side is the raw response from the same configured model after sending the user prompt directly to OpenRouter, rendered as a plain Markdown document with no product chrome. No system instruction or response-format instruction is sent. The right side is the actual output of this repository's /api/chat pipeline, rendered by the ChatHTML runtime. The exact submitted prompts are stored in scripts/readme-comparison-prompts.mjs. No ChatGPT screenshots or third-party product UI are used. External gallery photos come from Wikimedia Commons and are credited next to the example.

Plain Markdown ChatHTML
Prompt 1 Β· Run a Pomodoro clock

Build a working Pomodoro clock set to 25:00. Include Start/Pause, Reset, skip, Focus/Short Break/Long Break modes, four session progress dots, and a compact task field. Use a bold analog-inspired countdown with subtle motion and keyboard hints. Keep it polished and focused; no web search.
A Markdown-only response containing a complete Pomodoro clock implementation
Markdown source
A working Pomodoro clock rendered by ChatHTML
Live example Β· Generated source
Prompt 2 Β· Curate an image gallery

Create a compact editorial gallery titled β€œEvolution / I–X” celebrating the Mitsubishi Lancer Evolution. Keep the complete 2-by-2 gallery, filters, captions, and credits visible within a single viewport. Use the four provided Wikimedia Commons images and load every image eagerly. Show model generation, year, photographer, and license on each card, with filters for III, VI, IX, and X and a click-to-expand lightbox. Do not imply endorsement; no web search.
A Markdown-only response containing a complete Lancer Evolution gallery implementation
Markdown source
An image-rich Lancer Evolution gallery rendered by ChatHTML
Live example Β· Generated source
Photos: III Β· Charles Β· CC BY 2.0 Β· VI Β· Motoring Weapon R Β· CC BY-SA 3.0 Β· IX Β· FotoSleuth Β· CC BY 2.0 Β· X Β· IFCAR Β· Public domain
Prompt 3 Β· Make it playable

Build a playable 2048 mini-game with arrow-key and swipe controls, score and best counters, a new game button, and a clear visual hierarchy. The initial HTML itself must contain all 16 visible board cells and a plausible mid-game seed; JavaScript may take over for moves after load. Do not access browser storage; keep the best score only in memory for the current artifact. Keep it compact and polished; no web search.
A Markdown-only response containing a complete 2048 implementation
Markdown source
A playable seeded 2048 game rendered by ChatHTML
Live example Β· Generated source
Prompt 4 Β· Direct a visual

Build an interactive typographic poster studio. Show a bold live poster preview with the editable headline β€œMOVE / WITH / INTENT”, controls for palette, type scale, grain, alignment, and a shuffle button. Use only CSS shapes and typography; no external assets. Make it editorial, expressive, and polished; no web search.
A Markdown-only response containing a complete poster studio implementation
Markdown source
An interactive typographic poster studio rendered by ChatHTML
Live example Β· Generated source
Prompt 5 Β· Explain it interactively

Teach me how cubic Bezier curves work. Build an interactive playground with a large curve, adjustable control points, the formula, and three named easing presets. Keep it focused and polished; no web search.
A Markdown-only explanation and implementation of cubic Bezier curves
Markdown source
An interactive cubic Bezier curve playground rendered by ChatHTML
Live example Β· Generated source
Prompt 6 Β· Build a working utility

Build a tip and split calculator for a EUR 186.50 dinner shared by 4 people. Include editable bill, tip, and party-size controls, update totals live, and show the calculation clearly. Keep it compact and polished; no web search.
A Markdown-only response containing a complete tip calculator implementation
Markdown source
An interactive tip and split calculator rendered by ChatHTML
Live example Β· Generated source
Prompt 7 Β· Step through a process

Explain what happens after I type https://example.com into a browser and press Enter. Make an annotated, animated-looking pipeline from DNS through TCP and TLS, HTTP, and rendering, with controls to step through each stage. No web search.
A Markdown-only response containing a complete browser pipeline implementation
Markdown source
An interactive browser request pipeline rendered by ChatHTML
Live example Β· Generated source
Prompt 8 Β· Explore live data

Build an accessible color palette lab. Include HSL sliders, five live swatches with hex values, a foreground/background contrast checker, and AA/AAA status badges. Make it vivid, compact, and polished; no web search.
A Markdown-only response containing a complete accessibility color lab implementation
Markdown source
An interactive accessibility color lab rendered by ChatHTML
Live example Β· Generated source

Generate or refresh the stored OpenRouter responses:

node scripts/generate-readme-markdown-examples.mjs

The generator submits each stored prompt directly as the only input, without a system instruction or response-format guidance. It defaults to google/gemini-3.1-pro-preview; set CHATHTML_README_MARKDOWN_MODEL to override it. This command invokes the provider and uses provider credits. To regenerate one or more examples, pass their slugs as arguments.

Render the stored Markdown answers as plain screenshots without a provider call:

node scripts/render-readme-markdown-examples.mjs

To create or refresh a ChatHTML example while the dev server is running:

node scripts/generate-readme-example.mjs \
  "example-slug" \
  "Your prompt" \
  "docs/images/example-slug.png"

The ChatHTML generator uses the normal server prompt, provider request, streaming protocol, persistence layer, and iframe renderer. It writes the raw response to docs/examples/<slug>.chathtml.html. It defaults to google/gemini-3.1-pro-preview; set CHATHTML_README_MODEL to override it. The command invokes the provider and therefore uses provider credits.

Publish generated examples to stable hosted share links:

npx tsx scripts/share-readme-examples.ts example-slug

The publisher wraps each saved ChatHTML response in the same sandbox document used by the app, then creates or updates its stable link on https://chat.aietheia.com. Omit the slugs to publish every README example; set CHATHTML_README_SHARE_ORIGIN to use another compatible host.

Get started

Requires Node.js 22.13 or newer, npm, and an OpenRouter API key.

1. Install

git clone https://github.com/aietheia/ChatHTML.git
cd ChatHTML
npm install

2. Configure

Copy .env.example to .env (cp .env.example .env on macOS/Linux or Copy-Item .env.example .env in Windows PowerShell), then set at least:

OPENROUTER_API_KEY=your_openrouter_key_here
OPENROUTER_MODEL=google/gemini-3.5-flash
OPENROUTER_REASONING_EFFORT=low

The backend loads the root .env and an optional overriding apps/web/.env. Environment keys stay on the server and are never sent to the browser.

3. Run

npm run dev

Open http://127.0.0.1:5173. The Vite client runs on port 5173; its Express API proxy runs on http://127.0.0.1:8787.

πŸ’œ If ChatHTML is useful to you, consider giving it a star. Bugs can be reported in the app or opened directly in GitHub Issues.

Deployment notes & tutorials

Everything below covers how ChatHTML works, how to configure it, and what to check before running it beyond local development. For the shortest production path, start with Configuration, choose a persistence backend, review the security model, and then use the checked-in production operations assets.

How it works

flowchart LR
    A[User prompt] --> B[ChatHTML server]
    B --> C{Responses tool loop}
    C -->|retrieve, files, memory| C
    C --> D[NDJSON reasoning + content stream]
    D --> E[Protocol parser]
    E --> F[Partial HTML completion]
    F --> G[Sandboxed iframe]
Loading
  1. The client sends the conversation, canvas size, theme, files, and provider settings to POST /api/chat.
  2. The backend adds ChatHTML's system, canvas, theme, legibility, memory, and file context before calling a Responses-compatible model endpoint.
  3. Model tool calls are executed in the same response loop. Reasoning and content are returned to the browser as sequenced NDJSON events.
  4. The client extracts the protocol tags and feeds <streamui> content to the streaming renderer. Incomplete tags are safely completed for each preview frame.
  5. Once the stream is complete, scripts and artifact actions are enabled in a fresh sandbox document.

Capabilities

Area What is included
Rendering Progressive HTML/CSS rendering, speculative completion, light/dark theme context, responsive canvas sizing
Interaction Vanilla JavaScript, local controls, conversation actions, copy/download/open-link capability requests
Authoring Region selection, targeted artifact edits, regeneration branches, screenshot-based visual repair
Retrieval Brave, Tavily, Serper, DuckDuckGo fallback, direct URL fetching, optional Playwright browsing
Visual sources Openverse, Wikimedia-oriented search, NASA, Library of Congress, The Met, Art Institute of Chicago, plus optional Pexels, Unsplash, and Rijksmuseum providers
Files Draft image uploads, multimodal image reads, session file tools, capability URLs, saved raw artifact source
Persistence SQLite for zero-setup local use; PostgreSQL with per-user state and concurrent access for production
Export Copy source/text, standalone HTML, PNG, SVG, diagnostics, and optional hosted share links

Provider and key modes

Mode Request path Secret handling Best for
Environment Browser to ChatHTML server to provider Key remains in server environment Local development and self-hosting
Manual Browser directly to provider Key is kept in browser sessionStorage Signed-out use with a CORS-capable provider
Managed Browser to authenticated ChatHTML Service gateway Opaque service session stays in an HttpOnly cookie Hosted deployments

Manual mode never falls back through the ChatHTML server. Non-secret provider settings are kept in local storage, while the key disappears with the browser session. Plain HTTP provider URLs are rejected except for loopback development endpoints.

Configuration

The complete, annotated list lives in .env.example. The most useful settings are:

Variable Default Purpose
OPENROUTER_API_KEY none Server-side OpenRouter credential
OPENROUTER_MODEL google/gemini-3.5-flash Default generation model
OPENROUTER_REASONING_EFFORT low none, minimal, low, medium, or high
STREAMUI_RETRIEVAL true Enable the model's native retrieval tool
STREAMUI_SEARCH_PROVIDER auto Search provider selection
STREAMUI_BROWSER_ENGINE fetch Use fetch or Playwright for page retrieval
STREAMUI_SESSION_DB ./sessions/state.sqlite SQLite state file
CHATHTML_DATABASE_URL none PostgreSQL connection string for production
CHATHTML_AUTH_REQUIRED false outside production Require a hosted account

With STREAMUI_SEARCH_PROVIDER=auto, configured API providers are preferred and DuckDuckGo can be used as a fallback. Several visual and museum sources work without keys; optional provider keys expand coverage.

The retrieval policy blocks private network targets by default. Domain allow and block lists, timeouts, page limits, and context budgets are configurable in .env.

Persistence

SQLite is the zero-setup default. It uses WAL mode and a serialized write queue, which is appropriate for local development and small single-instance installs. Place the database on persistent storage if the deployment filesystem is ephemeral:

STREAMUI_SESSION_DB=/data/chathtml/state.sqlite

Use PostgreSQL for a hosted or horizontally scaled deployment:

CHATHTML_DATABASE_URL=postgresql://chathtml_app:password@127.0.0.1:5432/chathtml
CHATHTML_DATABASE_POOL_SIZE=10
CHATHTML_AUTH_REQUIRED=true

PostgreSQL stores one atomic state row per authenticated user, serializes updates for the same user with a row lock, and allows different users to read and write concurrently.

To migrate legacy SQLite data into an existing account, back up the source and run:

STREAMUI_SESSION_DB=/data/chathtml/state.sqlite \
CHATHTML_DATABASE_URL=postgresql://... \
CHATHTML_MIGRATION_USER_ID=00000000-0000-4000-8000-000000000000 \
npm run migrate:sessions

The migration is transactional and idempotent. It verifies counts and hashes, refuses to overwrite non-empty target data, and rotates stored file capabilities.

Runtime protocol

The wire protocol retains the legacy <streamui> name for compatibility with existing sessions and renderer code:

<sessiontitle>Concise history title</sessiontitle>
<chat></chat>

<streamui>
  <section class="streamui-response">
    <div class="streamui-chat">
      <p>All user-facing content lives in this artifact.</p>
    </div>
  </section>
  <script>
    // Optional small vanilla JavaScript. Runs after completion.
  </script>
</streamui>
  • <sessiontitle> becomes the hidden history title.
  • <chat> remains empty for visual responses; it is used as a fallback for non-artifact text.
  • <streamui> is rendered chunk by chunk and must remain open until the artifact is finished.
  • Built-in streamui-* classes and CSS variables provide accessible prose, buttons, muted text, actions, and theme-aware colors.
  • Scripts are ignored during streaming and run only after a complete artifact has been installed in the iframe.

If a response has no valid <streamui> block, it is displayed as a normal assistant message.

Artifact actions

Generated controls can ask the host to perform safe actions without calling sensitive browser APIs directly:

<button data-streamui-prompt="Show a simpler example">Simplify</button>
<button data-streamui-copy-target="#result">Copy result</button>
<button
  data-streamui-download-target="#result"
  data-streamui-filename="result.txt"
>Download</button>
<button data-streamui-open-url="https://example.com">Open source</button>

The host confirms capability actions and performs them outside the artifact.

Security model

  • Server-managed provider credentials are never serialized into frontend settings.
  • Artifacts render with sandbox="allow-scripts allow-same-origin allow-popups allow-popups-to-escape-sandbox".
  • The iframe CSP permits required HTTPS resources while disabling objects, forms, and base URL changes.
  • Browser storage, cookies, parent/top/opener access, permissions APIs, document.write, and clipboard reads are blocked or reported by the runtime.
  • Session files use stable IDs and unguessable capability URLs. Draft files are invisible to model file tools until the user sends the message.
  • Hosted session ownership comes from the authenticated server identity, never from a browser-supplied client ID.

The sandbox is a defense boundary for generated artifacts, not permission to run untrusted modifications to the ChatHTML host itself. Review the policy and deployment configuration before exposing a customized runtime publicly.

Sharing artifacts

Standalone HTML hosting is supplied by the separate aietheia/oops service. A production proxy should route POST /api/html-shares and /artifacts/* to that service. Share Link is hidden by default; enable it only after those routes exist:

VITE_CHATHTML_ARTIFACT_SHARE_LINKS=true

Local HTML, PNG, and SVG export works without the hosting service.

Development

This repository is an npm workspace:

Path Purpose
apps/web Full Vite/React client and Express backend
apps/webdemo Browser-local, reduced Web Demo surface
docs/cloud-api.md Hosted HTTP and native-auth contracts
ops/production Backup, monitoring, systemd, and Nginx assets

Useful commands:

npm run dev                 # full app on :5173, API on :8787
npm run dev:webdemo         # reduced web demo on :5174
npm test                    # web client and server unit tests
npm run test:webdemo        # web demo unit tests
npm run test:e2e            # Playwright browser suite
npm run build               # type-check and production build

Important implementation entry points:

Production checks

The production browser audits create disposable accounts and the full audit runs one managed generation. They modify production data and therefore require an explicit flag:

node scripts/auth-relogin-repro.mjs --confirm-production-audit
node scripts/production-alpha-audit.mjs --confirm-production-audit

Reports are written to the ignored test-results/ directory. Both scripts delete their test account before exiting and return a non-zero status if the audit is not clean. Use CHATHTML_AUDIT_APP_BASE and CHATHTML_AUDIT_SERVICE_BASE to target a non-default environment.

For hosted authentication, account, and native-wrapper integration, see the Cloud API contract. For operational assets and backup expectations, see Production operations.

License

ChatHTML is available under the MIT License.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages