TeamPulse ist ein WhatsApp-basiertes Anwesenheits-Management fuer Teams. Das Projekt nutzt jetzt Evolution API v2 als WhatsApp-Provider und versendet native WhatsApp-Umfragen direkt in eine konfigurierte Gruppe.
- geschuetztes Dashboard mit Login und Passwortwechsel beim ersten Start
- einmalige und wiederkehrende Events
- automatische native WhatsApp-Polls in der Gruppe
- automatische Erinnerungen und Event-Reminder als Gruppennachricht (keine Privatnachrichten)
- Ergebnis-Post als Text, Bild oder beides
- automatische Gruppenbeschreibung
- Backend: Node.js 24 + Express 5
- Frontend: Vanilla HTML/CSS/JS
- Datenbank: SQLite via
libsql - Scheduler:
node-cron - WhatsApp: Evolution API v2
| Benutzer | Passwort |
|---|---|
admin |
admin |
Beim ersten Login muss das Passwort geaendert werden.
| Variable | Bedeutung | Beispiel |
|---|---|---|
PORT |
HTTP-Port von TeamPulse | 3000 |
SESSION_SECRET |
zufaelliger Secret-String fuer Sessions | change-me |
EVOLUTION_API_URL |
Basis-URL der Evolution API | http://10.0.0.20:8080 |
EVOLUTION_API_KEY |
globaler API-Key der Evolution API | replace-me |
EVOLUTION_INSTANCE |
Name der WhatsApp-Instanz in Evolution | teampulse |
EVOLUTION_TIMEOUT_MS |
Timeout fuer Provider-Requests | 20000 |
GROUP_CHAT_ID |
WhatsApp-Gruppen-JID | 120363xxxx@g.us |
git clone https://github.com/niklask52t/TeamPulse.git
cd TeamPulse
npm install
cp .env.example .env
npm run devapt update && apt upgrade -y
apt install -y curl git ca-certificates build-essential python3curl -fsSL https://deb.nodesource.com/setup_24.x | bash -
apt install -y nodejs
node -vuseradd -r -m -s /bin/bash teampulse
sudo -u teampulse bash -c ' cd /home/teampulse git clone https://github.com/niklask52t/TeamPulse.git app cd app npm install --omit=dev cp .env.example .env '
sudo -u teampulse nano /home/teampulse/app/.env
Beispiel:
PORT=3000 SESSION_SECRET=HIER_EINEN_LANGEN_ZUFAELLIGEN_STRING EVOLUTION_API_URL=http://EVOLUTION-VM:8080 EVOLUTION_API_KEY=DEIN_EVOLUTION_API_KEY EVOLUTION_INSTANCE=teampulse EVOLUTION_TIMEOUT_MS=20000 GROUP_CHAT_ID=120363xxxxxxxx@g.us
SESSION_SECRET kannst du so erzeugen:
openssl rand -hex 32
sudo -u teampulse bash -c 'cd /home/teampulse/app && node server.js'Erwartet:
TeamPulse running on http://0.0.0.0:3000
cat >/etc/systemd/system/teampulse.service <<'EOF' [Unit] Description=TeamPulse After=network.target [Service] Type=simple User=teampulse Group=teampulse WorkingDirectory=/home/teampulse/app ExecStart=/usr/bin/node server.js Restart=always RestartSec=5 Environment=NODE_ENV=production [Install] WantedBy=multi-user.target EOF
systemctl daemon-reload
systemctl enable teampulse
systemctl start teampulse
systemctl status teampulse
journalctl -u teampulse -fapt install -y ufw
ufw allow ssh
ufw allow 3000/tcp
ufw enableDas ist die empfohlene Variante.
apt update && apt upgrade -y
apt install -y curl ca-certificates gnupg2 lsb-release ufwinstall -m 0755 -d /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc chmod a+r /etc/apt/keyrings/docker.asc echo \ "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian \ $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \ tee /etc/apt/sources.list.d/docker.list > /dev/null apt update apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin docker --version docker compose version
mkdir -p /opt/evolution-api
cd /opt/evolution-apinano .env
Beispiel:
SERVER_TYPE=http SERVER_PORT=8080 SERVER_URL=http://YOUR-EVOLUTION-VM:8080 AUTHENTICATION_API_KEY=replace-with-a-random-secret DATABASE_ENABLED=true DATABASE_PROVIDER=postgresql DATABASE_CONNECTION_URI=postgresql://evolution:evolutionpass@postgres:5432/evolution DATABASE_CONNECTION_CLIENT_NAME=teampulse DATABASE_SAVE_DATA_INSTANCE=true DATABASE_SAVE_DATA_NEW_MESSAGE=true DATABASE_SAVE_MESSAGE_UPDATE=true DATABASE_SAVE_DATA_CONTACTS=true DATABASE_SAVE_DATA_CHATS=true DATABASE_SAVE_DATA_LABELS=true DATABASE_SAVE_DATA_HISTORIC=true CACHE_REDIS_ENABLED=true CACHE_REDIS_URI=redis://redis:6379/6 CACHE_REDIS_PREFIX_KEY=evolution CACHE_REDIS_SAVE_INSTANCES=false CACHE_LOCAL_ENABLED=false WEBSOCKET_ENABLED=false TELEMETRY=false
services: postgres: image: postgres:16-alpine restart: unless-stopped environment: POSTGRES_USER: evolution POSTGRES_PASSWORD: evolutionpass POSTGRES_DB: evolution volumes: - evolution_postgres:/var/lib/postgresql/data redis: image: redis:7-alpine restart: unless-stopped volumes: - evolution_redis:/data evolution-api: image: evoapicloud/evolution-api:v2.3.7 container_name: evolution_api restart: unless-stopped env_file: - .env ports: - "8080:8080" volumes: - evolution_instances:/evolution/instances depends_on: - postgres - redis volumes: evolution_postgres: evolution_redis: evolution_instances:
Wenn eine neuere stabile Evolution-v2-Version verfuegbar ist, ersetze v2.3.7 durch einen konkreten neuen Tag.
docker compose up -d docker compose logs -f evolution-api
ufw default deny incoming
ufw default allow outgoing
ufw allow ssh
ufw allow from APP_SERVER_IP to any port 8080 proto tcp
ufw enableIm Browser:
http://YOUR-EVOLUTION-VM:8080/manager
Login mit:
AUTHENTICATION_API_KEY
Im Manager:
- neue Instanz erstellen, z. B.
teampulse Baileysals Channel waehlen- WhatsApp-Nummer im internationalen Format ohne
+eintragen - speichern
- QR-Code scannen
Der Instanzname muss exakt mit EVOLUTION_INSTANCE in TeamPulse uebereinstimmen.
Im Evolution Manager fuer die TeamPulse-Instanz:
- URL:
http://YOUR-TEAMPULSE-IP:3000/api/webhooks/evolution - Webhook by Events:
enabled - Base64:
disabled - Events:
MESSAGES_UPSERTMESSAGES_UPDATE
Wichtig:
- Der Instanzname in Evolution muss exakt zu
EVOLUTION_INSTANCEin TeamPulse passen. - Mit
Webhook by Events = enabledhaengt Evolution die Event-Route selbst an, also z. B./messages-upsertoder/messages-update. - TeamPulse akzeptiert beide Event-Routen.
Bei Evolution API v2.3.7 kann das Speichern des Webhooks im Manager oder per normalem API-Body fehlschlagen, obwohl kurz eine Erfolgsmeldung erscheint. Typische Symptome:
- der Slider springt wieder auf
aus GET /webhook/find/{instance}zeigtenabled: falseeventsbleibt leer- ein normaler
POST /webhook/set/{instance}mit Top-Level-Feldern liefertinstance requires property "webhook"
In dem Fall den Webhook einmal direkt per API mit verschachteltem webhook-Objekt setzen:
curl --request POST \ --url "http://YOUR-EVOLUTION-VM:8080/webhook/set/teampulse" \ --header "Content-Type: application/json" \ --header "apikey: YOUR_API_KEY" \ --data '{ "webhook": { "enabled": true, "url": "http://YOUR-TEAMPULSE-IP:3000/api/webhooks/evolution", "webhookByEvents": true, "webhookBase64": false, "events": [ "MESSAGES_UPSERT", "MESSAGES_UPDATE" ] } }'
Danach immer pruefen:
curl --request GET \ --url "http://YOUR-EVOLUTION-VM:8080/webhook/find/teampulse" \ --header "apikey: YOUR_API_KEY"
Erwartet:
{
"enabled": true,
"url": "http://YOUR-TEAMPULSE-IP:3000/api/webhooks/evolution",
"events": ["MESSAGES_UPSERT", "MESSAGES_UPDATE"]
}Im Evolution Manager die Gruppenliste der verbundenen Instanz oeffnen und die Zielgruppe kopieren.
Format:
120363xxxxxxxx@g.us
Diesen Wert in TeamPulse als GROUP_CHAT_ID eintragen.
In /home/teampulse/app/.env:
EVOLUTION_API_URL=http://YOUR-EVOLUTION-VM:8080 EVOLUTION_API_KEY=YOUR_API_KEY EVOLUTION_INSTANCE=teampulse GROUP_CHAT_ID=120363xxxxxxxx@g.us
Danach TeamPulse neu starten:
systemctl restart teampulse journalctl -u teampulse -f
- TeamPulse nutzt jetzt nur noch Evolution API. WAHA wird nicht mehr benoetigt.
- Ergebnis-Bilder laufen ueber
sendMediader Evolution API. - Gruppenbeschreibung, Polls, Erinnerungen und Ergebnis-Posts laufen ueber dieselbe Evolution-Instanz.
- TeamPulse sendet keinerlei Privatnachrichten - alle Nachrichten gehen in die Gruppe.
- Der Ergebnisversand laesst sich in der UI unter
EinstellungenaufText,BildoderText + Bildumstellen. - Message Pinning/Unpinning haengt von der verfuegbaren Evolution-API-Unterstuetzung ab. Die offiziellen v2-Dokumentationsseiten zeigen dafuer derzeit keinen separaten Endpunkt.
MIT
Last reviewed: 2026年08月10日