Skip to content
Yuva
Version 0.0.1 is outOpen source · Self-hosted · Pre-alpha

One inbox for every product you run.

Yuva brings support e-mail, live chat and in-app conversations from all of your products into one shared inbox for your team. It is open source, you host it yourself, and it runs as one Go binary with Postgres.

AGPL-3.0 server, MIT SDKs. Your conversations stay on your servers.

The Yuva panel: conversations from three products in one list, an in-app conversation with an internal note and a reply, and the contact's details sent by the host app.

Why Yuva

Several products means answering people in several places.

Small teams rarely run just one product. There is an app, its website, a side project and the tool that pays the bills, and each one collects messages somewhere else.

Support mail is scattered

Every product has its own support address, forwarded into someone's personal mailbox. Nobody can see who answered, threads break, and auto-replies bounce back and forth.

Live chat only where someone paid for it

One site has a chat widget on a per-seat plan, the others only a contact form. Visitors who leave before anyone answers are simply gone.

In-app messages sit in a closed box

Feedback from the mobile apps goes to a third-party SDK, an e-mail form or nowhere at all. Your users' conversations live in someone else's cloud.

Yuva gives all of it one home: every product is an inbox, every channel lands in the same conversation model, and the whole team answers from one panel on servers you control.

How it works

Messages come in on any channel. Your team answers in one place.

Each message becomes part of a conversation in an inbox, and members answer from the panel. Yuva tells your backend what happened through signed webhooks, so your own apps can send their push notifications.

How messages move through YuvaE-mail, live chat, API requests and in-app messages arrive at Yuva, one Go binary with Postgres, which keeps inboxes, conversations and contacts. The team answers from the panel. Yuva sends signed webhooks to your backend, which sends push notifications through APNs or FCM with its own keys, so the reply reaches the app.E-mailWorker or any MTALive chat<yuva-chat> widgetAPIForms and scriptsIn-appiOS and Android SDKsYuvaOne Go binaryInboxes · conversations · contactsPostgresrealtimewebhooksTeam panelAnswer, assign, notifyYour backendSigned webhooksAPNs / FCMYour own push keysYour appShows the reply
  1. Connect your products

    Create one inbox per product and give it channels: a support address, a chat widget, an app key, an API.

  2. Answer from one panel

    Conversations from every channel share one list, one thread view and one set of tools. Members see only the inboxes they were given.

  3. Let your backend react

    Signed webhooks tell your backend about new messages, so it can push a reply to a closed app with the keys it already has.

Channels

Every channel, one conversation model.

Live chat and asynchronous messaging differ only in settings. Whatever channel a conversation starts on, it looks and works the same in the panel, and each inbox chooses live or async.

E-mailE-mail done properly

Point a support address at Yuva through a Cloudflare Email Worker, any MTA or a signed HTTP request. Replies go out through each channel's own SMTP account: SES, Postmark or your own relay.

  • Threads follow In-Reply-To and References, and replies find their conversation even when a mail client drops the headers.
  • Quotes and signatures are stripped from what you read; the full text, sanitized HTML and the original message are kept.
  • Catch-all addresses per domain, and local+tag addresses that reach their channel.
  • Loop protection: auto-replies, bulk mail and Yuva's own messages never trigger another automatic message.
  • Bounces from delivery reports and Amazon SES mark an address undeliverable.
E-mail guide

Live chatLive chat and embedded threads

One web component loaded by one script tag. Use it as a floating launcher on a website, or embed a conversation thread inside your own product's panel.

  • Shadow DOM: your styles stay out, the widget's styles stay in.
  • Presence, typing and read receipts in live inboxes; an expected reply time in async ones.
  • When the visitor has left, unread replies follow them by e-mail, and their answer continues the same conversation.
  • Anonymous visitors, or signed-in users through an identity token from your backend.
  • English and Turkish, left-to-right and right-to-left.
Widget guide
The Yuva chat widget open on a newsletter tool's website: the visitor's question and a member's reply, with the member shown online.

In-appIn-app messaging and feedback

Native SDKs for iOS (YuvaKit, SwiftUI) and Android (Kotlin, Jetpack Compose) give your app a conversation list, threads with attachments and a feedback form, or a headless client for your own interface.

  • Feedback with a category (bug, idea, praise, other), screenshots and device details: app version, build, system, device and screen.
  • The panel filters feedback by category and counts what is still open.
  • Users write as themselves through a short-lived token signed by your backend; Yuva never sees your user database.
  • Push stays yours: Yuva sends a webhook, your backend sends the notification through APNs or FCM.
Mobile SDK guide
A bug report in the panel with the app version, device, system and screen it came from.
The messages screen of the iOS SDK in a sample app, with a feedback thread and a conversation.

And an API for everything else

A feedback form rendered by your own backend posts to /v1/feedback with a workspace API key. Scripts create inboxes, channels and keys, and host backends look up or delete contacts by their own user id.

The team panel

Built for the people who answer.

The panel ships inside the binary. It is fast, made for the keyboard, and works on phones as an installable app.

Shared inbox
All, mine, unassigned, per inbox and per label; open, pending, snoozed and closed.
Assignment
Assign conversations, set priority and hand over; every change is recorded in the thread.
Internal notes
Notes sit next to the replies and never reach the contact.
Labels and canned replies
Label conversations and insert saved answers by typing / in the composer.
Search
Full-text search across conversations, built on Postgres.
Realtime
New messages, typing and teammates' changes appear live over WebSocket.
Notifications
Install the panel as an app and get Web Push on phones and desktops, with e-mail as a fallback.
Keyboard first
Move through the list, reply, write notes and search without reaching for the mouse.
Contact context
Name, addresses, your own user id, attributes such as plan or app version, and earlier conversations.
No passwords
Sign in with an e-mailed code or a passkey. There is no open sign-up; everyone is invited.
Roles and access
Owners, admins and agents; agents see only the inboxes they were given.
Turkish and English
The panel, widget and SDKs speak both, and every member picks their own language.
The panel on a phone: the conversation list with labels, priorities and assignees.

For developers

Made to be embedded in your products.

Yuva is built for teams that make their own software. Every surface has a typed contract and a small, documented integration.

OpenAPI 3.1 contract

openapi/openapi.yaml is the source of truth: the server and the clients are generated from it, and you can generate yours in any language.

Identity tokens

Your backend signs a short-lived HS256 token for the signed-in user. sdk/go does it in one call; any JWT library works.

Standard Webhooks

Conversation, message, feedback and contact events, signed and retried for about a day, with a delivery log and redelivery.

Your users stay yours

Contacts are found by your own user id. When a user deletes their account, one API call removes them with everything they wrote.

Website: the chat widget

<script src="https://support.example.com/yuva.js" defer></script>
<yuva-chat channel="yuva_pk_xxxxxxxxxxxxxxxx"></yuva-chat>

Web widgetIdentity tokensMobile SDKsWebhooksOpenAPI

Self-hosting

Yours to run, on one small server.

Yuva is one Go binary and a Postgres database. The job queue, realtime events and search all live in Postgres, so there is nothing else to operate.

One Docker image

Server, panel and widget scripts in one image that runs as a non-root user. Every operator command runs from it too.

Postgres 16 or newer

Everything lives in the database, the job queue and realtime fan-out included. No Redis, no separate workers.

Files where you want them

Attachments and original e-mails on a local volume or in any S3-compatible storage: S3, R2, MinIO.

Easy to watch

JSON logs, Prometheus metrics, and health and readiness endpoints for your monitoring.
  1. Pull the image

    Pull the published image from GitHub Container Registry; it is built for linux/amd64 and linux/arm64.

    docker pull ghcr.io/productdevbook/yuva:0.0.1
  2. Write compose.yaml and .env

    Copy both files from the install guide: Postgres, your public URL, a master key, an ingress secret and an SMTP account.

    Open the install guide
  3. Start it

    Add a Web Push key pair, start the stack, and check that it is ready. Migrations run on start.

    docker run --rm ghcr.io/productdevbook/yuva:0.0.1 vapid-keys >> .env
    docker compose up -d
    curl -s http://127.0.0.1:8080/readyz     # {"status":"ok"}
  4. Create the first owner

    There is no open sign-up. Create the workspace and its owner, sign in with the code that arrives by e-mail, and invite your team.

    docker compose exec yuva /yuva bootstrap --email you@example.com --workspace "Example" --name "Your Name"

Put it behind a TLS reverse proxy that passes WebSockets; Caddy works as it is. The install guide also covers nginx, backups, upgrades and every setting. Operations guide

Security and privacy

Careful with what it holds.

A support inbox holds other people's words. Yuva is built with that in mind, and says plainly that it has not had an independent security audit yet.

Untrusted mail stays inert

Incoming HTML is sanitized and shown in a sandboxed frame under a strict Content Security Policy; remote images wait until a member loads them.

Signed ingress

Inbound mail must carry an HMAC signature with a fresh timestamp, and Amazon SNS notifications are checked against AWS's signing certificate.

No requests into your network

Webhook URLs, SMTP hosts and push endpoints are resolved and refused when they point at private, loopback or cloud metadata addresses.

Origin checks

Panel requests that change data must come from the panel's own origin, and the widget answers only the origins a chat channel allows.

Passkeys and encrypted secrets

One-time codes with attempt limits, and passkeys. SMTP passwords and signing secrets are encrypted with AES-256-GCM under your master key.

Data you can delete

Delete a contact, from the panel or by your own user id, and their conversations, messages and files go with them. Nothing goes to third parties except what a channel is set up to send.

Found a vulnerability? Report it privately through GitHub, not in a public issue. Security policy

Open source and licensing

Open source, and meant to stay that way.

Yuva uses a split license: the server stays open, and the pieces you embed in your own apps carry no copyleft obligations.

AGPL-3.0

Server and panel

Use it, change it, run it. If you run a modified Yuva as a network service for other people, you offer them its source.
MIT

SDKs and API contract

The widget, the Swift, Kotlin and Go SDKs and the OpenAPI contract are MIT, so they ship inside closed-source apps and store builds without obligations.
CLA

Contributor License Agreement

Contributions are made under a CLA, so the project can also offer a commercial license to organisations that cannot use the AGPL. Code published under the AGPL never moves to a more restrictive license.
™

The name and logo

The licenses cover the code, not the name. Say that you use or build on Yuva; give a fork you publish or host for others its own name.

Why this split?

A copyleft core keeps improvements to the server in the open. Permissive SDKs remove friction for every app that embeds them. And the CLA leaves a way to pay for development without ever closing the code, so the project can stay open and keep going.

Status and roadmap

Where it stands today.

Yuva is pre-alpha and built in the open. Versions start at 0.0.1, there is no 1.0 until the project is ready, and the first release, 0.0.1, is out now.

  1. Done

    Foundation

    Go server, OpenAPI contract, migrations, job queue and CI.

  2. Done

    Core model and sign-in

    Workspaces, roles, inboxes, channels, contacts, conversations, API keys, codes and passkeys.

  3. Done

    Team panel

    List, search, threads, notes, labels, canned replies, realtime updates, Turkish and English.

  4. Done

    E-mail

    Inbound through a Worker or any MTA, threading, quote stripping, SMTP, loop protection and bounces.

  5. Done

    Web widget

    Live chat, embedded threads, identity tokens, presence and e-mail continuity.

  6. Done

    Mobile SDKs, feedback and webhooks

    iOS and Android, feedback with device details, Standard Webhooks.

  7. Done

    Member notifications

    Installable panel, Web Push, preferences per event and inbox, e-mail fallback.

  8. Done

    First public release, 0.0.1

    Tagged v0.0.1 with its Docker image on GitHub Container Registry, after hardening sign-in, client sessions, ingress and attachment handling.

  9. In progress

    First real use

    Running real support for a set of products on Yuva alone.

Later: a Helm chart and optional push sent by Yuva itself. Not planned for now: a CRM, marketing e-mail, a public knowledge base or social-media channels. Full roadmap

FAQ

Questions people ask.

Something missing? Open an issue on GitHub.

Give every product's users a way to reach you.

Read the code, run 0.0.1 on your machine, and follow along as it grows.