Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ Built with CopilotKit React Native for iOS, Android, and web.
[![CI](https://github.com/CopilotKit/OpenMuse/actions/workflows/ci.yml/badge.svg)](https://github.com/CopilotKit/OpenMuse/actions/workflows/ci.yml)
[![MIT license](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)

[![Deploy to Render](https://render.com/images/deploy-to-render-button.svg)](https://render.com/deploy?repo=https://github.com/CopilotKit/OpenMuse)

Clone this template and customize it however you want.

**[Building on OpenMuse? Meet with the CopilotKit team →](https://www.copilotkit.ai/openmuse)**
Expand Down Expand Up @@ -91,6 +93,33 @@ Open [localhost:8081](http://localhost:8081). The API runs at [localhost:8787/ap

For iOS or Android, use `pnpm --dir apps/mobile ios` or `pnpm --dir apps/mobile android`. Xcode or Android tooling is required. The PDF reader needs an Expo development build; use [native setup](apps/mobile/README.md).

## Deploy on Render

[![Deploy to Render](https://render.com/images/deploy-to-render-button.svg)](https://render.com/deploy?repo=https://github.com/CopilotKit/OpenMuse)

[render.yaml](render.yaml) provisions two services. The API serves JSON at `/` and does not host the web bundle, so the UI is a separate static site.

| Service | Type | What it runs |
|---|---|---|
| `openmuse-api` | Node web service, Standard plan, 1 GB disk at `/var/data` | The Hono API and the in-process task worker. `DATA_DIR` is `/var/data/openmuse`. The disk holds the PGlite database, PDFs, and the signing key. |
| `openmuse-web` | Static site | The Expo web export. `EXPO_PUBLIC_API_URL` is inlined at build time, so the site rebuilds when the API URL changes. |

The API is Standard because a 512 MB instance runs out of memory before the process binds a port: PGlite loads an embedded Postgres build. The disk is required. Without it, a redeploy wipes the database and files. Chat history is stored by CopilotKit Intelligence, not on this disk, so a thread can still be there after sign-out even when the disk was missing.

Render requires binding `0.0.0.0`. OpenMuse rejects a non-loopback host in sample mode, so the Blueprint sets `WORKSPACE_MODE=live`. Live mode needs `OPENMUSE_ACCESS_KEY` and `TOKEN_ENCRYPTION_KEY`. Render generates both. You supply two secrets when the Blueprint asks:

- `CPK_INTELLIGENCE_API_KEY`: a CopilotKit Intelligence project key. Create one with `npx copilotkit@latest login` and `npx copilotkit@latest project select`. Required in every mode, and kept on the server.
- `OPENAI_API_KEY`: the provider key for the default `openai/gpt-4o-mini`. Change `MODEL` and swap the key to use Anthropic or Google.

### First run

1. Deploy with the button above. Wait until `openmuse-api` and `openmuse-web` are live.
2. On `openmuse-api`, open **Environment** and copy `OPENMUSE_ACCESS_KEY`.
3. Open the `openmuse-web` URL and sign in with that key.
4. Send a message. Chat needs both secrets from the deploy form. Workspace data, drafts, and files need the disk.

The browser worker, the Docker computer, and Google mail or calendar are not part of this Blueprint. Each needs the extra setup in the sections below.

## Configure the agent and Google

Copy the commented settings in [.env.example](.env.example) into your private `.env`:
Expand Down
68 changes: 68 additions & 0 deletions render.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
services:
- type: web
name: openmuse-api
runtime: node
# starter (512 MB) gets OOM-killed before the server binds a port, because
# the default PGlite store loads an embedded Postgres WASM build.
plan: standard
# No corepack: Render preinstalls pnpm at /usr/bin and /usr is read-only, so
# `corepack enable` dies with EROFS. Render's pnpm honors packageManager.
buildCommand: pnpm install --frozen-lockfile && pnpm build:server
startCommand: pnpm start
healthCheckPath: /api/health
disk:
name: openmuse-data
mountPath: /var/data
sizeGB: 1
envVars:
# HOST must be 0.0.0.0 on Render, and OpenMuse only allows that in live mode.
- key: HOST
value: 0.0.0.0
- key: WORKSPACE_MODE
value: live
- key: AGENT_BACKEND
value: model
- key: MODEL
value: openai/gpt-4o-mini
- key: DATA_DIR
value: /var/data/openmuse
- key: TASK_WORKER_ENABLED
value: true
- key: PUBLIC_API_URL
fromService:
name: openmuse-api
type: web
envVarKey: RENDER_EXTERNAL_URL
- key: ALLOWED_ORIGINS
fromService:
name: openmuse-web
type: web
envVarKey: RENDER_EXTERNAL_URL
- key: OPENMUSE_ACCESS_KEY
generateValue: true
- key: TOKEN_ENCRYPTION_KEY
generateValue: true
- key: OPENAI_API_KEY
sync: false
- key: CPK_INTELLIGENCE_API_KEY
sync: false

- type: web
name: openmuse-web
runtime: static
# --clear avoids a cached Metro transform keeping a stale EXPO_PUBLIC_API_URL,
# which Expo inlines into the bundle at build time.
buildCommand: >-
pnpm install --frozen-lockfile &&
pnpm --dir apps/mobile exec expo export --platform web --output-dir dist/web --clear
staticPublishPath: apps/mobile/dist/web
routes:
- type: rewrite
source: /*
destination: /index.html
envVars:
- key: EXPO_PUBLIC_API_URL
fromService:
name: openmuse-api
type: web
envVarKey: RENDER_EXTERNAL_URL