Ember Chat: VPS Migration, Features & Tool Integrations
Architectural transformation guide for deploying NYLLON Ember on a self-hosted Hetzner Linux VPS using the open-source workerd runtime. Details complete Slack-grade feature coverage and 5 direct system integrations with SuperBot, DevVault, Store Poller, and Meetnotes.
The Cloudflare-to-VPS Architecture Transformation
Originally, Ember is authored to run on Cloudflare Workers edge network with proprietary Cloudflare bindings (remote Durable Objects, D1, R2, and Workers AI). In our internal stack, we execute Ember on a self-hosted Hetzner Linux VPS using Cloudflare's open-source workerd native C++ binary. This guarantees total data sovereignty, zero cloud egress costs, and ultra-low latency loopback IPC for autonomous bot daemons.
(Proprietary Cloud)"] CF_DO["Remote Durable Objects
(Cloud DO SQLite)"] CF_R2["Remote Cloudflare R2
(Public Cloud Bucket)"] CF_AUTH["Cloudflare Access / Turnstile
(Proprietary Proxy)"] CF_EDGE --> CF_DO CF_EDGE --> CF_R2 CF_AUTH --> CF_EDGE end subgraph VPS["TARGET: TECHMERO SOVEREIGN VPS (ZERO LOCK-IN)"] direction TB NGINX["Nginx Reverse Proxy
(SSL + Rate Limit :443)"] WORKERD["Self-Hosted workerd Binary
(Local apps/worker :8080)"] LOCAL_DO["Local DO SQLite Files
(/var/lib/ember/storage/)"] LOCAL_MINIO["Local MinIO S3 / NVMe
(Internal Attachments)"] SUPERBOT["SuperBot Daemon
(Local IPC ws://127.0.0.1:8080)"] NGINX -->|HTTP & WebSockets| WORKERD WORKERD -->|Persistent SQLite| LOCAL_DO WORKERD -->|Object Storage| LOCAL_MINIO SUPERBOT <-->|Microsecond Loopback IPC| WORKERD end
| Architectural Component | Original Cloudflare Cloud | Techmero Transformed VPS (`workerd`) | Agency Advantage |
|---|---|---|---|
| Runtime Environment | Cloudflare Workers Edge Network | Native workerd systemd daemon on Linux VPS |
100% self-hosted, no execution time limits, no cold starts |
| ChatRoom Durable Objects | Cloudflare Distributed DO infrastructure | Local DO SQLite database instances on NVMe SSD | Direct database backup via standard tools (litestream/rsync) |
| File & Media Storage | Cloudflare R2 Bucket (Cloud billing) | Local MinIO S3 daemon or VPS filesystem storage | Zero per-gigabyte cloud egress or storage costs |
| Bot & Daemon Connectivity | Public internet webhooks over TLS | Direct loopback IPC (ws://127.0.0.1:8080) |
Sub-millisecond roundtrips, zero external network hops |
| Search Engine | SearchIndex DO on Cloudflare SQLite FTS5 | SearchIndex DO running locally with SQLite FTS5 | Instant full-text query matching across all agency projects |
| Security & TLS | Cloudflare SSL Edge & Turnstile | Nginx Let's Encrypt SSL + Tailscale WireGuard | Chat dashboard can be strictly bound to private Tailscale VPN |
Ember Core Features (Slack & Discord Grade)
Ember delivers the full operational ergonomics of modern commercial team communication platforms without per-seat licensing fees. Every feature runs on top of React 19, Tailwind CSS v4, shadcn/ui, and SQLite-backed Durable Objects.
Dedicated spaces for agency operations (#general, #announcements), private client rooms, and auto-provisioned #project-[slug] rooms. Quiet rooms hibernate automatically to conserve CPU memory.
Side-by-side thread view keeps channels clean and focused. Includes the essential "Also send to room" checkbox so critical resolutions remain visible to the entire development team.
1-on-1 private messaging and multi-user ad-hoc group DMs. Used by SuperBot for automated EOD standup prompts, private blocker escalation, and project manager 1-on-1 check-ins.
Low-overhead presence tracking using Durable Objects WebSocket Hibernation API. Live "is typing..." indicators, online/away statuses, and instant disconnect cleanup.
Built-in Markdown parsing, multi-language code snippets with syntax highlighting, bulleted task lists, blockquotes, user @mentions, and full emoji reaction picker.
Drag-and-drop file upload up to 250 MB per asset. Images display with inline previews, video and audio clips play in-stream, and design assets stream from local MinIO S3 storage.
Hit โF or Ctrl+F to search every conversation, thread reply, and file attachment across the agency. Powered by SQLite FTS5 with query highlighting and filter chips.
Standard Web Push API with VAPID key pairs. Delivers instant desktop and mobile notifications for urgent app store rejections, direct @mentions, and assigned bug tickets.
Every room exposes a Slack-compatible incoming webhook URL accepting Block Kit cards, attachments, and buttons. Any tool that speaks Slack works out of the box with Ember.
SuperBot Autonomous Chat Stream Listener
SuperBot operates as a continuous background daemon on the Hetzner Linux VPS. It connects directly to Ember's WebSocket loopback endpoint (ws://127.0.0.1:8080/api/internal/bot-stream) to listen to project discussions in real-time. When developers discuss features, bugs, or blockers, SuperBot evaluates the conversation with Gemini 2.5 Flash and updates DevVault automatically.
'I will finish Stripe checkout by 4pm'"] EMBER_WS["๐ฌ Ember ChatRoom DO
(Broadcasts WebSocket Frame)"] SUPERBOT["๐ค SuperBot Daemon
(Loopback ws://127.0.0.1:8080)"] GEMINI["๐ง Gemini 2.5 Flash API
(Structured Intent Extraction)"] DEVVAULT["๐ DevVault Project Manager
(Creates Task #108 in Drizzle)"] CONFIRM["๐ฌ Ember Thread Reply
'๐ค Created Task #108 (Due: 4 PM)'"] DEV -->|Send Message| EMBER_WS EMBER_WS -->|Loopback Stream| SUPERBOT SUPERBOT -->|Prompt Conversation Context| GEMINI GEMINI -->|Return JSON Action| SUPERBOT SUPERBOT -->|INSERT Task & Assignee| DEVVAULT SUPERBOT -->|Post Block Kit Confirmation| CONFIRM
{
"project_id": "proj_alpha_99",
"room_slug": "project-alpha",
"extracted_action": "CREATE_OR_UPDATE_TASK",
"task": {
"title": "Stripe Webhook Signature Verification",
"assignee_handle": "@rahul",
"priority": "HIGH",
"due_date": "2026-11-15T16:00:00Z",
"confidence_score": 0.94,
"context_snippet": "Rahul: I will implement Stripe webhook verification before 4 PM today."
},
"feedback_required": false
}
Automated Daily EOD & Half-Day Accountability Bot
Eliminates chaotic end-of-day Slack status chasing. SuperBot executes a strict chronological standup workflow, querying developers in private DMs, handling half-day early sign-offs, and publishing a consolidated executive briefing to agency leadership.
Half-Day Trigger
(/halfday or Leave DM)"] T2["โฐ 05:30 PM
Automated EOD DM
(3 Structured Questions)"] T3["โฐ 06:00 PM
Devs Submit Replies
(Logged in PostgreSQL)"] T4["โฐ 06:15 PM
AI Batch Synthesis
(Gemini 2.5 Flash)"] T5["โฐ 06:30 PM
Executive Report
(#agency-daily-standup)"] T1 -->|Suppresses 5:30 PM DM| T3 T2 -->|Pings Active Devs| T3 T3 -->|Aggregates Responses| T4 T4 -->|Generates Leadership Card| T5
Hey @developer! Please reply to this DM with your daily update:
- What tasks did you finish today?
- Are there any active blockers or dependencies?
- What is your priority target for tomorrow?
Tip: If leaving early on half-day, type /halfday anytime before 2 PM.
App Store & Play Store Poller Alerting
Every 30 minutes, an automated store status poller contacts Apple's App Store Connect API and Google Play Developer API. If a build status changes to Rejected, Action Required, or Metadata Rejected, an immediate high-priority alert is broadcast to the project's Ember channel and an urgent bug ticket is created in DevVault.
(Store Poller Daemon)"] STORES["๐ App Store Connect
๐ค Google Play Console"] DETECT{"Status ==
'REJECTED'?"} EMBER_POST["๐จ Post Red Alert Card
(Ember #project-alpha)"] DEVVAULT_BUG["๐ Create Urgent Bug
(DevVault Kanban Board)"] PUSH_DEV["๐ Web Push Notification
(Pings Lead Developer)"] POLL -->|Query Build Status| STORES STORES -->|Return State| DETECT DETECT -->|Yes| EMBER_POST DETECT -->|Yes| DEVVAULT_BUG DETECT -->|Yes| PUSH_DEV DETECT -->|No (Approved)| OK["โ Post Green Celebration Card
in #project-alpha"]
App Store Review: Guideline 4.2 - Minimum Functionality
Apple review team rejected Build 44: "The app crashed upon tapping 'Export PDF' on iPad OS 18.1. Please resolve crash log attachment and resubmit."
/storage/rejections/app-alpha-build-44.crashProject Manager (DevVault) 1-Click Provisioning Sync
Ember does not require manual room creation. When an agency project manager provisions a new client project in DevVault (Next.js 16 + Drizzle), an automated API webhook synchronously creates the matching channel in Ember and binds the team.
-
โ
Create Room: Invokes Ember Workspace DO to instantiate
#project-[slug]. - โ Assign Roster: Auto-invites assigned agency developers & project managers.
- โ Pin Kick-off Card: Pins repository URL, Figma links, and deadline to the room header.
- โ Bi-directional Status: Moving tasks in Kanban posts live status updates to the room thread.
POST http://127.0.0.1:8080/api/rooms
Authorization: Bearer $INTERNAL_WORKER_KEY
Content-Type: application/json
{
"name": "project-quickfood",
"topic": "QuickFood Mobile App // Client: Nexus LLC",
"is_private": false,
"members": ["user_alex", "user_rahul", "user_priya"],
"pinned_message": "๐ Welcome to QuickFood! Repo: git@github.com:techmero/quickfood.git | Figma: figma.com/file/quickfood-v1"
}
Meetnotes AI Post-Meeting Synthesis Pipeline
When client or team sprint meetings conclude, Meetnotes AI (running on the office Apple Silicon Mac Mini GPU node) transcribes audio locally via WhisperKit and MLX. It packages an executive summary and numbered action items, then dispatches them directly into the relevant Ember project room over the secure Tailscale tunnel.
(Recorded via Meetnotes)"] GPU["๐ Mac Mini M2 Pro
(WhisperKit + MLX Diarization)"] ACTION["๐ Action Item Extractor
(Llama-3-8B / Qwen-2.5 local)"] TUNNEL["๐ Tailscale WireGuard
(Encrypted Inter-Host)"] EMBER_POST["๐ฌ Ember #project-[slug]
(Slack Block Kit Meeting Summary)"] SUPERBOT_SYNC["๐ค SuperBot Sync
(Converts Items to DevVault Tasks)"] MIC -->|Raw Audio WAV| GPU GPU -->|Clean Transcript| ACTION ACTION -->|Structured JSON| TUNNEL TUNNEL -->|POST /api/webhooks/incoming| EMBER_POST EMBER_POST -->|Parsed Actions| SUPERBOT_SYNC
Production Configuration & Runbook
To run Ember entirely on the Hetzner Linux VPS, workerd is managed as a standard Linux systemd service, with Nginx reverse proxying TLS traffic on port 443.
[Unit]
Description=Ember Team Chat (workerd engine)
After=network.target
[Service]
Type=simple
User=techmero
WorkingDirectory=/opt/ember
ExecStart=/usr/local/bin/workerd serve config.capnp --verbose
Restart=always
RestartSec=3
Environment=NODE_ENV=production
Environment=STORAGE_PATH=/var/lib/ember/storage
Environment=PORT=8080
[Install]
WantedBy=multi-user.target
server {
server_name chat.internal.techmero.com;
listen 443 ssl http2;
ssl_certificate /etc/letsencrypt/live/chat.internal/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/chat.internal/privkey.pem;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_read_timeout 86400s;
proxy_send_timeout 86400s;
}
}
Run pnpm build to compile Vite React client and bundle Worker scripts into apps/web/dist.
Run pnpm seed to provision the agency workspace, create admin credentials, and default project rooms.
Start SuperBot daemon connected to loopback ws://127.0.0.1:8080 for real-time task extraction.