Riposte Setup Guide: Embedded (Attach) • PostgreSQL • Redis • Webhooks enabled • Google (Gmail)
Pre-generated Riposte setup wizard guide for embedded deployment with PostgreSQL storage. Redis queues enabled. webhooks configured. provider coverage: google (gmail). advanced: opentelemetry. Includes installation, configuration, integration code, and operational callouts..
📋 Setup Overview
Pre-generated Riposte setup instructions for a embedded deployment backed by postgresql with redis and webhooks enabled.
What you'll build
Embed Riposte directly into your existing Node.js or TypeScript service so the messaging engine runs beside the rest of your stack with minimal latency.
PostgreSQL gives you durable, production-grade storage, ready for high-volume inbox synchronization and queueing.
Authenticate Gmail inboxes with Google OAuth and reuse the same consent screen flow from the wizard in production.
Key ingredients
- Deployment Embedded
- Database PostgreSQL
- Queues Redis
- Webhooks Webhooks enabled
- Providers Google (Gmail)
- Advanced OpenTelemetry tracing and metrics
Redis is provisioned for background work queues and fan-out so long running sync jobs do not block user traffic.
Webhooks are enabled so downstream systems can respond to events such as message.received—remember to store and rotate your signing secret.
Advanced features enabled: OpenTelemetry tracing and metrics. Wire those signals into your observability stack before going live.
🚀 Installation & Bootstrap
Install the Riposte server inside your app and boot it alongside your existing framework.
import Fastify from 'fastify'
import { createRiposteServer } from '@riposte.co/server'
// Note: This example uses Fastify, but embedded mode also works with Express and Koa
const app = Fastify()
async function start() {
const riposte = await createRiposteServer({
hostServer: app,
initializeWorkspace: true,
config: {
database: {
url: process.env.DATABASE_URL!,
},
redisUrl: process.env.REDIS_URL ?? 'redis://localhost:6379',
providers: {
google: {
clientId: process.env.GOOGLE_CLIENT_ID!,
clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
redirectUri: process.env.GOOGLE_REDIRECT_URI ?? 'http://localhost:4000/riposte/providers/gmail/callback',
},
},
webhooks: {
default: {
isActive: true,
url: process.env.RIPOSTE_WEBHOOK_URL ?? 'https://example.com/webhooks/riposte',
eventTypes: ["message.received","message.sent"],
},
},
logging: {
openTelemetry: {
enabled: true,
url: process.env.OTEL_EXPORTER_OTLP_ENDPOINT!,
serviceName: process.env.OTEL_SERVICE_NAME ?? "riposte-server",
},
},
},
})
await riposte.start()
await app.listen({ port: 4000 })
console.log('Riposte ready at http://localhost:4000/riposte')
}
start()
.env (or your secrets manager) and reference them from the runtime config you pass to createRiposteServer.
http://localhost:4000/riposte. Passing adminPortal: true boots the portal with default admin/admin credentials—change them in the UI or via environment variables.
⚙️ Configuration
Drop these variables into .env (or your secrets manager) before booting the server.
Environment coverage
- 🔑 API key for SDK & REST authentication
- 🗄️ PostgreSQL database connection
- ⚡ Redis-backed queues and cron
- 🔗 Webhooks (message.received, message.sent)
- 📧 Google OAuth client credentials
- 📊 OpenTelemetry exporter endpoint & service name
RIPOSTE_API_KEY=come-up-with-your-own-secure-api-key
DATABASE_URL=postgresql://postgres:postgres@localhost:5432/riposte
REDIS_URL=redis://localhost:6379
RIPOSTE_WEBHOOK_URL=https://example.com/webhooks/riposte
GOOGLE_CLIENT_ID=your-google-oauth-client-id
GOOGLE_CLIENT_SECRET=your-google-oauth-client-secret
GOOGLE_REDIRECT_URI=http://localhost:4000/riposte/providers/gmail/callback
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317
OTEL_SERVICE_NAME=riposte-integration
.env so the new credentials load into the runtime.
📮 Providers
Console steps and environment variables for each provider you enabled.
🔍 Google Setup
Capture OAuth client credentials and drop them into your environment:
- Open Google Cloud Console and create OAuth client credentials.
- Configure the consent screen for external users if you haven't already.
- Use the scope planner to copy the Gmail + People API scopes you need.
- Set
GOOGLE_CLIENT_ID,GOOGLE_CLIENT_SECRET, andGOOGLE_REDIRECT_URIin.env, then restart Riposte.
Integration choices
- Connection mode: OAuth consent screen
- Accounts expected: 5
🔗 Integration Code
Add Fastify routes that kick off OAuth, handle the redirect, and call the API with the embedded SDK output.
// riposte + app come from the installation example
const sdk = riposte.createSdk()
app.get('/connect', async (_request, reply) => {
const { authUrl } =
await sdk.authentication.createSession({
redirectUri: 'http://localhost:4000/oauth/callback',
})
reply.redirect(authUrl)
})
app.get('/oauth/callback', async (request, reply) => {
const query = request.query as Record
if (query.error) {
reply.code(400).send({ error: query.error })
return
}
const accounts = await sdk.accounts.list()
reply.send({ connected: accounts.accounts?.length ?? 0 })
})
curl --request GET --url http://localhost:4000/riposte/api/messages --header "Authorization: Bearer $RIPOSTE_API_KEY"
riposte.createSdk() once it has started when you need a client inside the same process. For other services, keep RIPOSTE_API_KEY in env and send it as a bearer token.
http://localhost:4000/riposte.
const { authUrl } = await riposteSdk.authentication.createSession({ redirectUri: 'https://app.example.com/oauth/callback' })
⚡ Advanced Configuration
Optional features for production-ready deployments:
🔧 Enabled Features:
📊 OpenTelemetry Integration
Enable distributed tracing and metrics collection. The config snippets above already add logging.openTelemetry; just supply the exporter details:
# Add to your environment
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317
OTEL_SERVICE_NAME=riposte-integration
Optional: Type your frontend with @riposte.co/api-types
Install in your frontend project with npm install @riposte.co/api-types to add lightweight type safety. This is optional, but it keeps your
UI code aligned with the API responses shown in this guide.
import type { ApiResponse, Message } from '@riposte.co/api-types'
type ThreadResponse = ApiResponse['/accounts/{accountId}/threads/{threadId}']['get']
const ThreadList = ({ threads }: { threads: ThreadResponse }) => {
return (
<div>
{threads.map((thread) => (
<div key={thread.id}>{thread.subject}</div>
))}
</div>
)
}
const MessageItem = ({ message }: { message: Message }) => {
return (
<div>
<div>{message.subject}</div>
<div>{message.body}</div>
</div>
)
}