AI-powered search with a generative UI, deployed on Render with Exa neural search and managed PostgreSQL
Morphic is an open-source AI search engine: grounded answers, cited sources, and rich inline components streamed from the model. This Render example wires Morphic for a minimal production stack (Docker web service + Postgres + Exa) without self-hosted SearXNG or Redis.
- What This App Does
- What This Demonstrates
- Architecture
- Quick Start
- Deploy to Render
- Configuration
- Troubleshooting
- Upstream Documentation
- License
Users ask research-style questions in a chat UI. Morphic searches the web via Exa, calls an LLM (Anthropic, OpenAI, Google, or others), and streams back a cited answer with optional generative UI blocks (images, grids, follow-ups).
- Ask a question — e.g. "What are the latest Postgres 17 features?"
- Pick a model — the selector shows providers you configured via API keys
- Get cited answers — sources, summaries, and structured components inline
- Return later — chat history persists in PostgreSQL (anonymous mode by default)
- Exa search — neural web search without running SearXNG yourself
- Generative UI — streamed JSON spec renders rich components beyond markdown
- Multi-provider LLMs — OpenAI, Anthropic, Google, Ollama, Vercel AI Gateway
- Quick and Adaptive search modes
- Shareable chat URLs and optional Supabase auth (disabled in this example)
- Web Service (Docker) — multi-stage Dockerfile builds Next.js 16; migrations run on container start
- Managed PostgreSQL — chat history via Drizzle ORM;
DATABASE_URLwired from the database resource - Blueprint (
render.yaml) — one project, one environment, env group for shared config - Environment groups — non-secret defaults (
SEARCH_API=exa, anonymous mode) in one place
Docker Compose upstream bundles Postgres, Redis, and SearXNG. On Render, Exa replaces SearXNG and managed Postgres replaces the local database, so you run two billable resources instead of four services.
┌─────────────────────────────────────────────────────────────┐
│ Browser │
│ Next.js 16 app (chat UI, model selector, generative UI) │
└─────────────────────────────────────────────────────────────┘
↓ HTTPS
┌─────────────────────────────────────────────────────────────┐
│ morphic — Render Web Service (Docker, Standard plan) │
│ - Next.js API routes (/api/chat, etc.) │
│ - Drizzle migrations on boot (docker-entrypoint.sh) │
└─────────────────────────────────────────────────────────────┘
↓ ↓
┌──────────────────┐ ┌──────────────────┐
│ morphic-db │ │ Exa API │
│ Postgres 17 │ │ (SEARCH_API=exa) │
│ chat history │ └──────────────────┘
└──────────────────┘ ↓
┌──────────────────┐
│ LLM provider │
│ (Anthropic, etc.)│
└──────────────────┘
| Resource | Plan | Role |
|---|---|---|
morphic |
Standard | Docker web service from ./Dockerfile |
morphic-db |
basic-256mb | PostgreSQL 17 — Drizzle migrations on startup |
morphic-render (env group) |
— | Shared non-secret config (SEARCH_API, anonymous mode) |
Default region: oregon (change in render.yaml).
Run locally with Docker Compose (includes SearXNG + Redis):
git clone https://github.com/render-examples/morphic.git
cd morphic
cp .env.local.example .env.local
# Set OPENAI_API_KEY (or another provider) in .env.local
docker compose up -dVisit http://localhost:3000.
For local development without Docker, see upstream Installation.
Before clicking deploy, have these ready:
| Key | Where to get it |
|---|---|
EXA_API_KEY |
dashboard.exa.ai |
| One LLM key | e.g. Anthropic, OpenAI, or Google AI |
You can set the LLM key at Apply or in the Dashboard after the first deploy. Do not leave placeholder values like REPLACE_ME.
Render reads render.yaml and provisions:
- PostgreSQL database (
morphic-db) - Docker web service (
morphic) in projectmorphic - Environment group
morphic-render(search provider, anonymous mode, TLS workaround for managed Postgres)
On Apply, enter EXA_API_KEY. Optionally add an LLM key now; otherwise add it on the morphic service Environment page after deploy.
First deploy typically takes 5–10 minutes (Docker build + Next.js compile + migrations).
- Open the
morphicservice URL from the Dashboard. - If the model selector is empty, add
ANTHROPIC_API_KEY,OPENAI_API_KEY, orGOOGLE_GENERATIVE_AI_API_KEYon the service and redeploy if needed. - Run a test query. Check Logs for migration success (
Migrations completed) and search errors.
| Group | Contents | Linked to |
|---|---|---|
morphic-render |
SEARCH_API=exa, ENABLE_AUTH=false, ANONYMOUS_USER_ID, NODE_TLS_REJECT_UNAUTHORIZED=0 |
morphic web service |
DATABASE_URL and DATABASE_RESTRICTED_URL are injected per-service from morphic-db (database links cannot live in env groups).
NODE_TLS_REJECT_UNAUTHORIZED=0 is required for Render's managed Postgres TLS with upstream Morphic's strict Node TLS verification. Prefer fixing verification in application code for production hardening.
| Resource | ~USD/mo |
|---|---|
morphic (Standard) |
25 |
morphic-db (basic-256mb) |
6 |
| Render subtotal | ~31 |
Exa and LLM usage are billed separately by those providers.
| Variable | Purpose |
|---|---|
EXA_API_KEY |
Exa neural search |
| One LLM key | ANTHROPIC_API_KEY, OPENAI_API_KEY, or GOOGLE_GENERATIVE_AI_API_KEY |
| Variable | Source |
|---|---|
DATABASE_URL |
morphic-db connection string |
DATABASE_RESTRICTED_URL |
Same Postgres instance |
SEARCH_API |
exa (env group) |
ENABLE_AUTH |
false — anonymous single-user mode |
ANONYMOUS_USER_ID |
anonymous-user |
See upstream CONFIGURATION.md:
- Multi-user auth:
ENABLE_AUTH=true+ Supabase env vars - Different search:
SEARCH_API=tavily+TAVILY_API_KEY - File uploads: Cloudflare R2 / S3-compatible vars
- Rate limiting:
MORPHIC_CLOUD_DEPLOYMENT=true+ Upstash Redis
| Problem | Fix |
|---|---|
| Deploy stuck / health check fails | Check logs for OOM. Starter (512 MB) is often too small; this Blueprint uses Standard. |
| "No open ports detected" | Process died before binding $PORT. Check build logs and bump plan if OOM. |
| Search errors | Confirm EXA_API_KEY and SEARCH_API=exa. |
| "We could not generate a response" | Set a real LLM API key. Remove any placeholder OPENAI_API_KEY=REPLACE_ME. |
| No chat history | Confirm morphic-db is Available and migrations completed in logs. |
| Postgres SSL errors | Ensure NODE_TLS_REJECT_UNAUTHORIZED=0 is set via the morphic-render env group. |
Report app bugs upstream: miurla/morphic issues
Report this example's deploy wiring: render-examples/morphic issues
This repo tracks miurla/morphic with Render-specific render.yaml and the example README above.
- Morphic application: Apache-2.0 (upstream)
- Render example wiring: same as upstream unless noted otherwise in this repo

