diff --git a/README.md b/README.md
index 0328dd0..20a42c0 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
# @neboai/app-sdk
-SDK for building [Nebo](https://neboloop.com) apps. Mirrors native browser APIs (`fetch`, `WebSocket`, `localStorage`) while adding agent invocation, LLM completions, and real-time state management.
+SDK for building [Nebo](https://neboai.com) apps. Mirrors native browser APIs (`fetch`, `WebSocket`, `localStorage`) while adding agent invocation, LLM completions, and real-time state management.
## Install
@@ -8,12 +8,17 @@ SDK for building [Nebo](https://neboloop.com) apps. Mirrors native browser APIs
pnpm add @neboai/app-sdk
```
-Or use the global build via CDN:
+Or, for a page without a build step, load the copy Nebo serves to every app page:
```html
-
+
+
```
+An unbundled page cannot `import` a bare package name; use the served global.
+
## Quick Start
```typescript
@@ -59,57 +64,70 @@ nebo.surfaces.on('state_snapshot', (e) => {
### `nebo.fetch(input, init?)`
Auto-routed fetch. Relative URLs go to your sidecar. Absolute URLs go through Nebo's CORS-free proxy.
-### `nebo.WebSocket(path?)`
-Auto-reconnecting WebSocket with exponential backoff (1s–30s).
+### `new nebo.WebSocket()`
+Auto-reconnecting WebSocket to the app's own channel, with exponential backoff (1 s up to 30 s). It takes no path: any argument is ignored. To reach your own server (a game server, for example), open a plain `new WebSocket('wss://...')` from the page.
### `nebo.storage`
Server-persisted async key-value store: `getItem`, `setItem`, `removeItem`, `clear`, `keys`.
### `nebo.agents`
-- `invoke(message, options?)` — One-shot agent call, returns `{ text, tools? }`
-- `stream(message, options?)` — Streaming agent call, yields `{ text, done }`
+- `invoke(message, options?)`: one-shot agent call, returns `{ text, tools? }`
+- `stream(message, options?)`: streaming agent call, yields `{ text, done }`
### `nebo.janus`
-- `complete(options)` — Direct LLM completion
-- `stream(options)` — Streaming LLM completion
+- `complete(options)`: Direct LLM completion
+- `stream(options)`: Streaming LLM completion
### `nebo.chat`
-- `mount(element, options?)` — Embed chat UI
-- `unmount()` — Remove chat UI
-- `send(message)` — Programmatically send a message
-- `onMessage(handler)` — Listen for chat events
-- `setContext(context)` — Update app context for the agent
-- `newThread()` — Start a new conversation
+- `mount(element, options?)`: Embed chat UI
+- `unmount()`: Remove chat UI
+- `send(message)`: Programmatically send a message
+- `onMessage(handler)`: Listen for chat events
+- `setContext(context)`: Update app context for the agent
+- `newThread()`: Start a new conversation
### `nebo.surfaces`
Real-time agent-to-app event system with typed events:
- `connect()` / `disconnect()`
-- `on(type, handler)` — Subscribe to events (returns unsubscribe fn)
-- `send(name, payload?)` — Send action to agent
-- `requestState()` — Request full state snapshot
+- `on(type, handler)`: Subscribe to events (returns unsubscribe fn)
+- `send(name, payload?)`: Send action to agent
+- `requestState()`: Request full state snapshot
Events: `run_started`, `run_finished`, `run_error`, `text_start`, `text_content`, `text_end`, `tool_call_start`, `tool_call_end`, `state_snapshot`, `state_delta`, `surface_create`, `surface_update`, `surface_delete`, `data_update`, `custom`.
### `nebo.identity`
-- `get()` — Returns agent metadata (id, name, skills, model, etc.)
-- `invalidate()` — Clear cached identity
+- `get()`: Returns agent metadata (id, name, skills, model, etc.)
+- `invalidate()`: Clear cached identity
### `nebo.a2ui`
A2UI v0.9 message bridge for agent-driven UI components.
-- `init(processor)` — Initialize with `@a2ui/web_core` MessageProcessor
-- `sendAction(surfaceId, action)` — Send UI action to agent
-- `sendError(surfaceId, code, message)` — Report error to agent
+- `init(processor)`: Initialize with `@a2ui/web_core` MessageProcessor
+- `sendAction(surfaceId, action)`: Send UI action to agent
+- `sendError(surfaceId, code, message)`: Report error to agent
### `nebo.configure(options)`
Set `appId` and `baseUrl` manually (auto-detected by default).
+## What the page gets from Nebo (no SDK call needed)
+
+Some app features come from the app's `manifest.json` and standard browser APIs rather than from the SDK:
+
+| Want | How |
+|------|-----|
+| Full screen, landscape | `"window": { "fullscreen": true, "orientation": "landscape" }` (`orientation`: `portrait` default, `landscape`, `any`). Pad with `env(safe-area-inset-*)` and `viewport-fit=cover`. |
+| Tilt (gyroscope, accelerometer) | Add `"device:motion"` to `permissions`, then listen for `devicemotion` / `deviceorientation`. On iPhone call `DeviceMotionEvent.requestPermission()` from a tap. |
+| Video and sound | Ship the files in `ui/`. They are served with their real content types and answer range requests, so `