Getting Started
Mana is a Go framework for building real-time communication applications — chat, video calling, collaboration tools, and more. It provides WebSocket management, room orchestration, WebRTC signaling, E2EE key exchange, and plug-and-play SQL persistence out of the box.
Installation
go get github.com/Aswanidev-vs/mana
Requirements
- Go 1.21 or later
- No CGo required (pure Go SQLite via
modernc.org/sqlite)
Quick Start
The simplest Mana server — a fully functional WebSocket messaging backend in 15 lines:
package main
import (
"log"
mana "github.com/Aswanidev-vs/mana"
"github.com/Aswanidev-vs/mana/core"
)
func main() {
app := mana.New(core.Config{
Port: 8080,
AllowedOrigins: []string{"*"},
EnableRTC: true,
EnableE2EE: true,
})
app.OnMessage(func(msg core.Message) {
log.Printf("[%s] %s → %s", msg.RoomID, msg.SenderID, string(msg.Payload))
})
log.Fatal(app.Start())
}
Run it: go run main.go. Connect any WebSocket client to ws://localhost:8080/ws.
Architecture
Mana's architecture is modular — each concern lives in its own package, orchestrated by the central App struct in app.go.
Configuration
All settings are defined in core.Config. Use core.DefaultConfig() for sensible defaults then override what you need.
| Field | Type | Default | Description |
|---|---|---|---|
Port | int | 8080 | HTTP listen port |
Host | string | "0.0.0.0" | Bind address |
EnableAuth | bool | false | Enable JWT auth on WebSocket |
JWTSecret | string | "" | JWT signing secret (≥32 bytes for prod) |
JWTExpiry | Duration | 24h | Token validity duration |
EnableRTC | bool | false | Enable WebRTC signaling |
EnableE2EE | bool | false | Enable E2EE key exchange |
AllowedOrigins | []string | [] | WebSocket CORS origins |
MaxMessageSize | int64 | 64KB | Max WS message bytes |
RateLimitPerSecond | int | 100 | Messages/sec per connection |
DatabaseDriver | string | "sqlite" | "sqlite", "postgres", or "mysql" |
DatabaseDSN | string | "mana.db" | Connection string or file path |
DatabaseTablePrefix | string | "" | Table prefix (e.g. "mana_") |
PubSubBackend | string | "" | "memory", "redis", or "nats" |
EnableTracing | bool | false | OpenTelemetry tracing |
EnableTLS | bool | false | HTTPS/WSS mode |
Event Hooks
Mana exposes lifecycle hooks so your application logic reacts to real-time events without touching framework internals.
app.OnMessage(func(msg core.Message) {
// Fires after every message is routed and stored
})
app.OnUserJoin(func(roomID string, user core.User) {
// Fires when a user joins a room
})
app.OnUserLeave(func(roomID string, user core.User) {
// Fires when a user disconnects from a room
})
app.OnCallStart(func(event core.CallEvent) {
// Fires when a WebRTC call begins
})
app.OnCallEnd(func(event core.CallEvent) {
// Fires when a WebRTC call ends
})
app.OnSignal(core.SignalTyping, func(sig core.Signal) {
// React to any signal type (typing, presence, etc.)
})
// Logic hooks (context-aware, for business logic)
app.OnAccountCreated(func(ctx context.Context, user core.User) { })
app.OnMessageStored(func(ctx context.Context, msg core.Message) { })
Types & Signals
Core types used throughout the framework:
// Message — the fundamental unit of communication
type Message struct {
ID string `json:"id"`
Sequence uint64 `json:"sequence,omitempty"`
Type string `json:"type"`
RoomID string `json:"room_id,omitempty"`
SenderID string `json:"sender_id"`
TargetID string `json:"target_id,omitempty"`
Payload []byte `json:"payload"`
Timestamp time.Time `json:"timestamp"`
AckID string `json:"ack_id,omitempty"`
}
// Signal — WebRTC and signaling events
type Signal struct {
Type SignalType `json:"type"`
From string `json:"from"`
To string `json:"to,omitempty"`
RoomID string `json:"room_id,omitempty"`
Payload []byte `json:"payload,omitempty"`
SDP string `json:"sdp,omitempty"`
Candidate interface{} `json:"candidate,omitempty"`
}
Signal Types
Features
Messaging
1:1 and group messaging with acknowledgments, sequence tracking, cursor-based offline sync, and delivery receipts.
Advanced E2EE
Full X3DH + Double Ratchet implementation. Forward secrecy and self-healing handshakes out of the box. Learn More →
Authentication
JWT auth with RBAC, rate limiting, origin controls, and a built-in SQL account store with bcrypt hashing.
Plug-and-Play DB
Point at SQLite, PostgreSQL, or MySQL — Mana auto-creates tables for messaging, identity, social, and settings.
WebRTC
SFU-based architecture with offer/answer negotiation, ICE management, simulcast, congestion control, and jitter buffering.
E2EE
X3DH-style key exchange, Curve25519 key pairs, HKDF derivation, and AES-256-GCM encryption primitives.
Clustering
Stateless horizontal scaling via Redis or NATS pub-sub backends for multi-node signal fanout.
Rooms
Dynamic room creation, member tracking, and multi-device session management with per-device cursor sync.
Observability
Structured logging, Prometheus-style metrics, health endpoints, and OpenTelemetry tracing with in-memory inspection.
Messaging
Messages are automatically persisted, sequenced, and synced across devices. The framework handles offline delivery and cursor-based reconnect replay.
Store Interface
type MessageStore interface {
SaveMessage(ctx context.Context, msg Message, recipients []string) (Message, error)
MarkDelivered(ctx context.Context, messageID, userID string) error
PendingForUser(ctx context.Context, userID string) []Message
SyncForUserSince(ctx context.Context, userID string, since time.Time) []Message
SyncForUserAfterSequence(ctx context.Context, userID string, after uint64, limit int) ([]Message, bool)
LatestSequenceForUser(ctx context.Context, userID string) uint64
}
Client Sync Protocol
Reconnecting clients send a sync_request with their last-known cursor. Mana responds with a DeviceSyncBatch containing any new messages and a pagination cursor.
// Client → Server
{"type": "sync_request", "cursor": 42, "limit": 50}
// Server → Client
{"type": "message_sync", "cursor": 87, "has_more": false, "messages": [...]}
Rooms
The room package manages room lifecycle, member tracking, and multi-device sessions.
// Access the room manager
rm := app.RoomManager()
// Rooms are automatically created when users join via signaling
// You can also access rooms programmatically:
rooms := rm.List() // all active rooms
room, err := rm.Get(id) // get a specific room
members := room.Members() // list members
Authentication
Enable auth with EnableAuth: true. Mana provides JWT token generation/validation, RBAC, rate limiting, and a built-in SQL account store.
cfg := core.DefaultConfig()
cfg.EnableAuth = true
cfg.JWTSecret = "your-secret-key-at-least-32-bytes"
cfg.JWTIssuer = "my-app"
app := mana.New(cfg)
// Generate tokens
token, _ := app.JWTAuth().GenerateToken(userID, username, auth.RoleUser)
// Validate tokens
claims, err := app.JWTAuth().ValidateToken(token)
// Account Store (auto-created with DatabaseDSN)
app.AccountStore().CreateUser(ctx, "alice", "password123")
userID, err := app.AccountStore().Authenticate(ctx, "alice", "password123")
RBAC Roles
Database — Plug-and-Play Batteries
Mana's database layer uses standard database/sql with driver packages for SQLite, PostgreSQL, and MySQL. Point it at a DSN and the framework auto-creates all tables.
Option A: Framework-Managed DSN
cfg := core.DefaultConfig()
cfg.DatabaseDriver = db.SQLite // or db.Postgres, db.MySQL
cfg.DatabaseDSN = "data/app.db" // or your connection string
cfg.DatabaseTablePrefix = "mana_" // optional: prefix all tables
app := mana.New(cfg)
// AccountStore, MessageStore, ProfileStore, ContactStore, PreferenceStore
// are all automatically wired and ready.
Option B: Bring Your Own *sql.DB
// Connect with your own driver
db, _ := sql.Open("pgx", "postgres://user:pass@localhost/mydb")
app := mana.New(cfg)
app.WithDatabase(db, manadb.Postgres)
// Mana uses YOUR connection pool — shared transactions are possible!
Auto-Created Stores
| Store | Interface | Tables Created |
|---|---|---|
| AccountStore | core.AccountStore | accounts |
| MessageStore | core.MessageStore | messages, delivery |
| ProfileStore | core.ProfileStore | profiles |
| ContactStore | core.ContactStore | contacts, blocks |
| PreferenceStore | core.PreferenceStore | preferences |
Supported Drivers
SQLite
Pure Go via modernc.org/sqlite. No CGo. WAL mode enabled by default.
cfg.DatabaseDriver = db.SQLite
PostgreSQL
High-performance via pgx/v5. Production-ready connection pooling.
cfg.DatabaseDriver = db.Postgres
MySQL
Via go-sql-driver/mysql. Full UPSERT and transaction support.
cfg.DatabaseDriver = db.MySQL
WebRTC
Mana includes a full SFU-oriented WebRTC stack with offer/answer signaling, ICE candidate exchange, simulcast layer selection, congestion control, and jitter buffering.
cfg.EnableRTC = true
cfg.STUNServers = []string{"stun:stun.l.google.com:19302"}
cfg.TURNServers = []core.ICEServerConfig{{
URLs: []string{"turn:turn.example.com:3478"},
Username: "user",
Credential: "pass",
}}
cfg.ICETransportPolicy = "all" // or "relay"
app := mana.New(cfg)
app.OnCallStart(func(e core.CallEvent) {
log.Printf("Call started: %s → %s", e.Caller, e.Callee)
})
app.OnCallEnd(func(e core.CallEvent) {
log.Printf("Call ended in room %s", e.RoomID)
})
E2EE — End-to-End Encryption
The e2ee package provides X3DH-style key exchange, Curve25519 key generation, HKDF key derivation, and AES-256-GCM authenticated encryption.
cfg.EnableE2EE = true
app := mana.New(cfg)
// Key exchange is managed automatically via signaling
// Clients register their public keys:
app.KeyExchange().StorePublicKey("alice", alicePublicKey)
pub, ok := app.KeyExchange().GetPublicKey("alice")
Notifications
The notification hub delivers targeted alerts to specific users across all their connected devices.
app.NotificationHub().Send("user-123", core.Notification{
Title: "New Message",
Body: "You have a new message from Alice",
Data: map[string]interface{}{"room_id": "chat-room"},
})
Clustering
Scale horizontally with Redis or NATS for multi-node signal fan-out. Each node broadcasts signals to the pub-sub backend, and all subscribed nodes forward them to local peers.
// Redis
cfg.PubSubBackend = "redis"
cfg.RedisAddr = "localhost:6379"
cfg.RedisChannel = "mana.cluster"
// NATS
cfg.PubSubBackend = "nats"
cfg.NATSURL = "nats://127.0.0.1:4222"
cfg.NATSSubject = "mana.cluster"
cfg.ClusterNodeID = "node-1" // unique per instance
Observability
Built-in structured logging, metrics, health checks, and OpenTelemetry tracing.
Endpoints
| Path | Description |
|---|---|
GET /health | Health check with room/peer/session counts |
GET /metrics | Prometheus-style metrics (connections, messages, bytes) |
GET /debug/traces | In-memory OpenTelemetry trace inspection |
cfg.EnableTracing = true
cfg.TraceSampleRatio = 1.0
cfg.ServiceName = "my-chat-app"
cfg.ServiceVersion = "1.0.0"
Dependency Injection
Override any store with your own implementation using the With* setters:
app.WithMessageStore(myCustomStore)
app.WithAccountStore(myCustomAuth)
app.WithProfileStore(myCustomProfiles)
app.WithContactStore(myCustomContacts)
app.WithDeviceStore(myCustomDevices)
app.WithPreferenceStore(myCustomPrefs)
Working Examples
Explore production-grade implementations. Each example opens in a dedicated page for deep study.
examples/full
Full-featured chat server with auth, rooms, messaging, and WebRTC signaling.
examples/custom_db
Bring-your-own-database with shared ACID transactions between your app and Mana.
examples/notification
Notification hub integration for targeted user alerts.
examples/sfu
SFU-based video calling with simulcast and congestion control.
kuruvi/
A complete WhatsApp-like messaging app (backend + frontend) built on Mana.
Minimal Start
The absolute shortest path to a functional WebSocket server.
Redis Clustering
Scale horizontally across multiple nodes for millions of users.
Component Accessors
Access any framework component via the App instance:
| Method | Returns | Description |
|---|---|---|
app.Mux() | *http.ServeMux | HTTP router — add your own endpoints |
app.JWTAuth() | *auth.JWTAuth | Token generation and validation |
app.RoomManager() | *room.Manager | Room lifecycle management |
app.SignalHub() | *signaling.Hub | WebSocket signal routing |
app.RTCManager() | *rtc.Manager | WebRTC peer connection management |
app.KeyExchange() | *e2ee.HandshakeManager | E2EE public key store |
app.MessageStore() | core.MessageStore | Message persistence |
app.AccountStore() | core.AccountStore | User accounts and auth |
app.ProfileStore() | core.ProfileStore | User profiles |
app.ContactStore() | core.ContactStore | Contacts and blocking |
app.DBBackend() | *db.Backend | Raw database backend access |
app.NotificationHub() | *notification.Hub | Push notification delivery |
app.Metrics() | *observ.Metrics | Runtime metrics counters |