Skip to content
Open
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
17 changes: 17 additions & 0 deletions templates/list.json
Original file line number Diff line number Diff line change
Expand Up @@ -6158,6 +6158,23 @@
"Data Security"
]
},
{
"slug": "openreply",
"logo": "logo.svg",
"name": "OpenReply",
"description": "OpenReply is an open-source Instagram comment-to-DM automation tool and self-hosted ManyChat alternative. It watches Instagram post and reel comments through Meta webhooks, matches configured keywords, queues delivery jobs, and sends private replies through the official Meta API. The app includes a Next.js dashboard, campaign templates, tracked links, DM logs, role-based workspaces, email magic-link login, and a long-running worker process backed by PostgreSQL and Redis.",
"tags": [
"Instagram",
"Automation",
"Social Media",
"Marketing",
"ManyChat Alternative",
"Next.js",
"PostgreSQL",
"Redis",
"Open Source"
]
},
{
"slug": "openspeedtest",
"logo": "logo.png",
Expand Down
6 changes: 6 additions & 0 deletions templates/openreply/assets/logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added templates/openreply/assets/screenshot.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
119 changes: 119 additions & 0 deletions templates/openreply/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
import {
Output,
randomPassword,
randomString,
Services,
} from "~templates-utils";
import { Input } from "./meta";

function randomHex(length: number) {
const chars = "abcdef0123456789";
let result = "";
for (let i = 0; i < length; i++) {
result += chars[Math.floor(Math.random() * chars.length)];
}
return result;
}

export function generate(input: Input): Output {
const services: Services = [];
const databasePassword = randomPassword();
const redisPassword = randomPassword();
const nextAuthSecret = randomString(48);
const cronSecret = randomString(48);
const encryptionKey = randomHex(64);
const databaseUrl = `postgresql://postgres:${databasePassword}@$(PROJECT_NAME)_${input.appServiceName}-db:5432/$(PROJECT_NAME)`;
const redisUrl = `redis://default:${redisPassword}@$(PROJECT_NAME)_${input.appServiceName}-redis:6379`;
const appUrl = "https://$(EASYPANEL_DOMAIN)";

const commonEnv = [
`NIXPACKS_NODE_VERSION=24`,
`NEXTAUTH_URL=${appUrl}`,
`NEXTAUTH_SECRET=${nextAuthSecret}`,
`CRON_SECRET=${cronSecret}`,
`ENCRYPTION_KEY=${encryptionKey}`,
`DATABASE_URL=${databaseUrl}`,
`REDIS_URL=${redisUrl}`,
`RESEND_API_KEY=${input.resendApiKey}`,
`EMAIL_FROM=${input.emailFrom}`,
`META_GRAPH_API_VERSION=${input.metaGraphApiVersion}`,
`INSTAGRAM_APP_ID=${input.instagramAppId}`,
`INSTAGRAM_APP_SECRET=${input.instagramAppSecret}`,
`FACEBOOK_APP_SECRET=${input.facebookAppSecret}`,
`WEBHOOK_VERIFY_TOKEN=${input.webhookVerifyToken}`,
].join("\n");

const source = {
type: "github" as const,
owner: "diwenne",
repo: "openreply",
ref: input.sourceRef,
path: "/",
autoDeploy: false,
};

services.push({
type: "postgres",
data: {
serviceName: `${input.appServiceName}-db`,
image: "postgres:16",
password: databasePassword,
},
});

services.push({
type: "redis",
data: {
serviceName: `${input.appServiceName}-redis`,
password: redisPassword,
},
});

services.push({
type: "app",
data: {
serviceName: input.appServiceName,
source,
build: {
type: "nixpacks",
installCommand: "npm ci",
buildCommand: "npm run build",
startCommand: "npm run start",
},
env: commonEnv,
deploy: {
replicas: 1,
command: "npx prisma migrate deploy && npm run start",
zeroDowntime: true,
},
domains: [
{
host: "$(EASYPANEL_DOMAIN)",
port: 3000,
},
],
},
});

services.push({
type: "app",
data: {
serviceName: `${input.appServiceName}-worker`,
source,
build: {
type: "nixpacks",
installCommand: "npm ci",
buildCommand: "npm run db:generate",
startCommand: "npm run worker",
},
env: commonEnv,
deploy: {
replicas: 1,
command: "npm run worker",
zeroDowntime: false,
},
},
});

return { services };
}
126 changes: 126 additions & 0 deletions templates/openreply/meta.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
name: OpenReply
description:
OpenReply is an open-source Instagram comment-to-DM automation tool and
self-hosted ManyChat alternative. It watches Instagram post and reel comments
through Meta webhooks, matches configured keywords, queues delivery jobs, and
sends private replies through the official Meta API. The app includes a
Next.js dashboard, campaign templates, tracked links, DM logs, role-based
workspaces, email magic-link login, and a long-running worker process backed
by PostgreSQL and Redis.
instructions:
Before deploying, create a Meta developer app and a Resend account. Set the
Meta and Resend values in the template form. After deployment, configure Meta
with the OAuth redirect URL https://your-domain/api/instagram/callback and
webhook callback URL https://your-domain/api/webhook using the same webhook
verify token entered here. The web service and worker must both stay running;
the worker sends DMs from the queue.
changeLog:
- date: 2026-08-08
description: First release
links:
- label: GitHub
url: https://github.com/diwenne/openreply
- label: Documentation
url: https://github.com/diwenne/openreply/blob/main/docs/setup.md
contributors:
- name: Yahya
url: https://github.com/yahya
schema:
type: object
required:
- appServiceName
- sourceRef
- resendApiKey
- emailFrom
- instagramAppId
- instagramAppSecret
- facebookAppSecret
- webhookVerifyToken
- metaGraphApiVersion
properties:
appServiceName:
type: string
title: App Service Name
default: openreply
sourceRef:
type: string
title: Source Ref
default: main
resendApiKey:
type: string
title: Resend API Key
emailFrom:
type: string
title: Email From
default: OpenReply <login@example.com>
instagramAppId:
type: string
title: Instagram App ID
instagramAppSecret:
type: string
title: Instagram App Secret
facebookAppSecret:
type: string
title: Facebook App Secret
webhookVerifyToken:
type: string
title: Webhook Verify Token
metaGraphApiVersion:
type: string
title: Meta Graph API Version
default: v25.0
benefits:
- title: Self-Hosted Instagram Automation
description:
Run Instagram comment-to-DM automation on your own infrastructure without
seat limits, plan caps, or a managed automation subscription.
- title: Official Meta API Flow
description:
Uses Meta webhooks and Instagram private replies instead of scraping,
browser automation, or Instagram password access.
- title: Reliable Queue Processing
description:
Separates the web app from a long-running worker so webhook receipt,
keyword matching, rate limiting, retries, and DM delivery are handled
reliably.
- title: Campaign and Link Tracking
description:
Build keyword campaigns, send tracked links, monitor clicks, and inspect
send logs from the dashboard.
- title: Multi-Account Workspaces
description:
Manage multiple Instagram professional accounts with workspace roles and
invite-based team access.
features:
- title: Keyword to DM
description:
Match one or more keywords on Instagram comments and send private replies
through the official API.
- title: Public Reply Support
description:
Optionally post a public reply under the matched comment alongside the
private DM.
- title: Queue-Backed Worker
description:
Runs a separate worker process with BullMQ and Redis for delivery,
retries, polling reconciliation, and rate limiting.
- title: Email Magic-Link Login
description: Uses Auth.js and Resend for passwordless sign-in.
- title: PostgreSQL Persistence
description:
Stores workspaces, accounts, campaigns, logs, sessions, and tracked link
analytics in PostgreSQL through Prisma.
- title: Meta Webhook Endpoint
description:
Provides a webhook endpoint for Instagram comments and a callback endpoint
for Instagram OAuth connection.
tags:
- Instagram
- Automation
- Social Media
- Marketing
- ManyChat Alternative
- Next.js
- PostgreSQL
- Redis
- Open Source