# Soloex AI Agent Guide

You are an AI assistant (Claude, Gemini, Codex, etc.) helping the user build a real-time, multi-user web application on the **Soloex** platform.

Soloex is a self-hosted platform where small HTML/JS/CSS apps can be instantly deployed. Every app hosted on Soloex automatically gets:
1. **An in-memory, persistent JSON database** (persisted to SQLite after inactivity, and isolated per session key if the app is configured as "multi-session").
2. **A real-time WebSocket relay** for presence and custom ephemeral messages.
3. **A zero-dependency client library** (`soloex.js`) that synchronizes DB state and handles WebSocket communication seamlessly, including automatic session key handling for multi-session apps.

When building applications on Soloex, you MUST use the `soloex.js` client library.

---

## Importing and Initialization

The library is always available at `/assets/soloex.js`. 

```html
<script type="module">
  import soloex from '/assets/soloex.js'
  
  // The app slug is usually extracted from the URL.
  // URL format is typically: https://<host>/apps/<slug>?session=<session_id>
  const slug = location.pathname.split('/')[2] 
  
  // soloex() automatically extracts ?session= from the URL and applies it.
  const app = soloex(slug)
</script>
```

You can also pass configuration options:
```javascript
const app = soloex(slug, {
  autoConnect: true,       // Connect WS immediately (default: true)
  reconnectDelay: 1500     // Delay in ms before reconnecting (default: 1500)
})
```

---

## Live State (Read-only)

The `app` object maintains a local mirror of the DB and presence state.

- `app.entries` (Array): Local cache of all DB entries. Kept in sync automatically by WebSocket events.
- `app.clients` (Array of Strings): Emails of currently connected users (e.g. `["alice@google.com"]`).
- `app.connected` (Boolean): True if the WebSocket is currently open.

---

## Database Operations (HTTP API)

All database operations return Promises and are automatically broadcast to all connected WebSocket clients. Do NOT manually send WS events for DB changes.

Every entry inserted automatically receives an `_id` (string) and `_inserted_at` (ISO timestamp).

```javascript
// 1. Insert an entry (returns the created entry object with _id)
const entry = await app.insert({ type: 'player', name: 'Alice', score: 10 })

// 2. List all entries, or pass an object to filter by strict equality
const allEntries = await app.list()
const activePlayers = await app.list({ type: 'player', status: 'active' })

// 3. Merge-update an entry
// You cannot overwrite _id or _inserted_at
const updated = await app.update(entry._id, { score: 20 })

// 4. Delete an entry
await app.delete(entry._id)

// 5. Force a full sync (fetches all from DB and replaces app.entries cache)
await app.sync()
```

---

## Real-Time WebSocket Messaging

You can send custom messages to all other connected clients immediately. This bypasses the database completely, meaning **no persistence** and **sub-millisecond latency**.

Use this for rapidly changing state: player positions (dead reckoning), mouse cursors, typing indicators, etc.

```javascript
// Send a custom message
// The first argument is a TYPE string (Uppercase recommended). Avoid 'DB' and 'PRESENCE'.
app.send('MOVE', { x: 100, y: 200 })
app.send('CHAT_TYPING', { isTyping: true })
```

---

## Event Subscriptions

Listen to built-in state events or custom WebSocket messages using `app.on(event, handler)`.

### 1. Initialization Event
Wait for `ready` before rendering your UI. It fires on first connect and any reconnect, passing the full DB snapshot and presence.

```javascript
app.on('ready', ({ entries, clients }) => {
  console.log('Initial DB entries:', entries)
  console.log('Connected users:', clients)
  renderUI()
})
```

### 2. Database Sync Events
These fire whenever **any** client makes an HTTP database change.

```javascript
app.on('insert', entry => {
  // A new entry was added to the DB
  console.log('New:', entry)
})

app.on('update', entry => {
  // An entry was modified
  console.log('Updated:', entry)
})

app.on('delete', ({ id }) => {
  // An entry was deleted
  console.log('Deleted ID:', id)
})
```

### 3. Presence Events
Fires when someone joins or leaves.

```javascript
app.on('presence', ({ event, client_id, clients, count }) => {
  // event is 'join' or 'leave'
  // client_id is the user's email
  console.log(`${client_id} ${event}ed. Total: ${count}`)
})
```

### 4. Custom Message Events
Whenever another client calls `app.send('TYPE', payload)`, you receive an event named `'TYPE'`.

```javascript
app.on('MOVE', payload => {
  updateCursor(payload.x, payload.y)
})
```

### 5. Connection Lifecycle
```javascript
app.on('connect', () => console.log('Connected!'))
app.on('disconnect', ({ code, reason }) => console.log('Lost connection'))
```

---

## AI Implementation Best Practices for Soloex

1. **State Management**: Prefer local extrapolation (dead reckoning) over sending high-frequency websocket messages for physics/movement. Only use `app.send` when input vectors or trajectories change.
2. **Persistence vs Ephemeral**: If data needs to survive when all users leave the room (e.g. chat history, high scores, level data), use `app.insert()`. If data is only relevant to people looking at the screen right now (e.g. mouse pointers, rapid player coordinates), use `app.send()`.
3. **Data Shape Check**: For single-page apps, structure your DB entries with a `type` field (e.g. `type: 'message'`, `type: 'player'`) so you can filter them easily with `app.list({ type: 'message' })`.
4. **Rendering**: Do NOT perform heavy, synchronous canvas or DOM manipulations directly inside event listeners like `app.on('MOVE')`. Instead, update local state dictionaries in the event listener, and use a `requestAnimationFrame` loop to render the state.
5. **Security/Auth**: You don't need to implement auth. The user is already authenticated via Google OAuth by the Soloex platform. Their email is provided in the `app.clients` array and `presence` events.
6. **No Build Step**: Apps on Soloex are served raw. Stick to Vanilla JS, ES Modules (`<script type="module">`), Vanilla CSS, and HTML. Do not use build tools (Webpack/Vite) or compiled frameworks unless you are providing the final compiled bundle directly.
