TeamChat 💬
A modern, self-hosted team chat Progressive Web App (PWA) — similar to Google Messages / Facebook Messenger for teams.
Features
- 🔐 Authentication — Login, remember me, forced password change on first login
- 💬 Real-time messaging — WebSocket (Socket.io) powered chat
- 👥 Public channels — Admin-created, all users auto-joined
- 🔒 Private groups — User-created, owner-managed
- 📷 Image uploads — Attach images to messages
- 💬 Message quoting — Reply to any message with preview
- 😎 Emoji reactions — Quick reactions + full emoji picker
- @Mentions — @mention users with autocomplete, they get notified
- 🔗 Link previews — Auto-fetches OG metadata for URLs
- 📱 PWA — Install to home screen, works offline
- 👤 Profiles — Custom avatars, display names, about me
- ⚙️ Admin settings — Custom logo, app name
- 👨💼 User management — Create, reset password, suspend, delete, bulk CSV import
- 📢 Read-only channels — Announcement-style public channels
Quick Start
Prerequisites
- Docker & Docker Compose
1. Build a versioned image
# Build and tag as v1.0.0 (also tags :latest)
./build.sh 1.0.0
# Build latest only
./build.sh
2. Deploy with Docker Compose
cp .env.example .env
# Edit .env — set TEAMCHAT_VERSION, admin credentials, JWT_SECRET
nano .env
docker compose up -d
# View logs
docker compose logs -f
App will be available at http://localhost:3000
Release Workflow
TeamChat uses a build-then-run pattern. You build the image once on your build machine (or CI), then the compose file just runs the pre-built image — no build step at deploy time.
┌─────────────────────┐ ┌──────────────────────────┐
│ Build machine / CI │ │ Server / Portainer │
│ │ │ │
│ ./build.sh 1.2.0 │─────▶│ TEAMCHAT_VERSION=1.2.0 │
│ (or push to │ │ docker compose up -d │
│ registry first) │ │ │
└─────────────────────┘ └──────────────────────────┘
Build script usage
# Build locally (image stays on this machine)
./build.sh 1.0.0
# Build and push to Docker Hub
REGISTRY=yourdockerhubuser ./build.sh 1.0.0 push
# Build and push to GHCR
REGISTRY=ghcr.io/yourorg ./build.sh 1.0.0 push
Deploying a specific version
Set TEAMCHAT_VERSION in your .env before running compose:
# .env
TEAMCHAT_VERSION=1.2.0
docker compose pull # if pulling from a registry
docker compose up -d
Rolling back
# .env
TEAMCHAT_VERSION=1.1.0
docker compose up -d # instantly rolls back to previous image
Data volumes are unaffected by version changes.
Environment Variables
| Variable | Default | Description |
|---|---|---|
ADMIN_NAME |
Admin User |
Default admin display name |
ADMIN_EMAIL |
admin@teamchat.local |
Default admin email (login) |
ADMIN_PASS |
Admin@1234 |
Default admin password (first run only) |
PW_RESET |
false |
If true, resets admin password to ADMIN_PASS on every restart |
JWT_SECRET |
(insecure default) | Change this! Used to sign auth tokens |
PORT |
3000 |
HTTP port to listen on |
APP_NAME |
TeamChat |
Initial app name (can be changed in Settings) |
Important:
ADMIN_EMAILandADMIN_PASSare only used on the very first run to create the admin account. After the admin changes their password, these variables are ignored — unlessPW_RESET=true.
First Login
- Navigate to
http://localhost:3000 - Login with
ADMIN_EMAIL/ADMIN_PASS - You'll be prompted to change your password immediately
- You're in! The default TeamChat public channel is ready
PW_RESET Warning
If you set PW_RESET=true:
- The admin password resets to
ADMIN_PASSon every container restart - A ⚠️ warning banner appears on the login page
- This is intentional for emergency access recovery
- Always set back to
falseafter recovering access
User Management
Admins can access User Manager from the bottom menu:
- Create single user — Name, email, temp password, role
- Bulk import via CSV — Format:
name,email,password,role - Reset password — User is forced to change on next login
- Suspend / Activate — Suspended users cannot login
- Delete — Soft delete; messages remain, sessions invalidated
- Elevate / Demote — Change member ↔ admin role
Group Types
| Public Channels | Private Groups | |
|---|---|---|
| Creator | Admin only | Any user |
| Members | All users (auto) | Invited by owner |
| Visible to admins | ✅ Yes | ❌ No (unless admin takes ownership) |
| Leave | ❌ Not allowed | ✅ Yes |
| Rename | Admin only | Owner only |
| Read-only mode | ✅ Optional | ❌ N/A |
| Default group | TeamChat (permanent) | — |
CSV Import Format
name,email,password,role
John Doe,john@example.com,TempPass123,member
Jane Admin,jane@example.com,Admin@456,admin
rolecan bememberoradminpassworddefaults toTempPass@123if omitted- All imported users must change password on first login
Data Persistence
All data is stored in Docker volumes:
teamchat_db— SQLite databaseteamchat_uploads— User avatars, logos, message images
Data survives container restarts and redeployments.
PWA Installation
On mobile: Share → Add to Home Screen
On desktop (Chrome): Click the install icon in the address bar
Portainer / Dockhand Deployment
Use the docker-compose.yaml directly in Portainer's Stack editor. Set environment variables in the .env section or directly in the compose file.
Development
# Backend
cd backend && npm install && npm run dev
# Frontend (in another terminal)
cd frontend && npm install && npm run dev
Frontend dev server proxies API calls to localhost:3000.