morgenruf.dev

Configuration

Most configuration happens in the web dashboard. A handful of per-user DM commands are also available.

Web Dashboard

After installing Morgenruf, visit https://<your-api-domain>/dashboard to configure your workspace. All workspace-level settings live here.

Standup channel

The channel where the daily summary is posted after responses are collected. Make sure you have also run /invite @Morgenruf in that channel so the bot can post there.

Schedule

Three settings control when standups fire:

  • Time β€” 24-hour time at which participants receive their standup DM (e.g. 09:00)
  • Timezone β€” IANA timezone for the workspace schedule (e.g. America/New_York, Europe/Berlin). Individual members can override this with the timezone DM command.
  • Days of week β€” which days to run standups (default: Mon–Fri)

Custom questions

The question list is fully editable in the dashboard under Edit Standup β†’ Questions. You can add, remove, and reorder questions. The default set is:

  1. What did you work on yesterday?
  2. What are you working on today?
  3. Any blockers or anything the team should know?
  4. How are you feeling today? 😊 😐 πŸ˜” (mood β€” always last)
ℹ️

The mood question (😊/😐/πŸ˜”) is a fixed final question and is always tracked in analytics regardless of your custom question list.

Reminder

Set a number of minutes before standup time to send a heads-up DM to each participant (e.g. 15 means "reminder 15 minutes before standup"). Set to 0 to disable reminders.

Members

The Members section in the dashboard controls who participates in standups. Add or remove team members here. Only listed members receive standup DMs and appear in analytics.

Edit window

Number of hours after submission during which a user can edit their standup answers. After this window closes, responses are locked. Default is 2 hours.

DM Commands

Open a direct message with @Morgenruf in Slack and send any of the following commands. These are per-user commands β€” they affect only you, not the whole workspace.

Command Description
standup Start your standup right now, without waiting for the scheduled time.
skip Skip today's standup β€” you won't receive a standup DM today.
timezone America/New_York Set your personal timezone override. The standup DM will arrive at the configured time in your timezone, not the workspace default. Use any IANA timezone name.
help Show available commands.
⚠️

There are no config channel, config time, config timezone, config days, or config questions DM commands. All workspace-level configuration is done in the web dashboard at /dashboard.

Example: trigger standup now

Y
You2:15 PM
standup
M
Morgenruf2:15 PM
πŸŒ… Starting your standup!

What did you work on yesterday?

Example: skip today

Y
You8:45 AM
skip
M
Morgenruf8:45 AM
βœ… Got it β€” I'll skip your standup today. See you tomorrow!

Example: set personal timezone

Y
You9:00 AM
timezone Asia/Kolkata
M
Morgenruf9:00 AM
βœ… Your personal timezone is now set to Asia/Kolkata. Your standup DM will arrive at the standup time in that timezone.

Analytics & Export

The Analytics tab in the dashboard shows a per-member participation table. Switch between a 7-day and 30-day view to see who's been submitting standups and who's been skipping.

To export standup data as a CSV, click the Export CSV button in the Analytics tab. You can optionally filter by date range before exporting.

Webhooks

Morgenruf can POST a signed payload to your endpoint whenever a standup is completed. Register webhook endpoints in the dashboard under the Webhooks tab.

Event: standup.completed

Each request includes an HMAC-SHA256 signature header:

X-Morgenruf-Signature: sha256=<hex-digest>
http

Example payload:

{
  "event": "standup.completed",
  "team_id": "T012AB3CD",
  "user_id": "U056EF7GH",
  "timestamp": "2025-01-15T09:03:42Z",
  "answers": {
    "yesterday": "Finished the auth refactor.",
    "today": "Writing tests for new API endpoints.",
    "blockers": "None.",
    "mood": "😊"
  }
}
json
πŸ’‘

Verify the signature by computing HMAC-SHA256(secret, request_body) and comparing it to the value in the header. Reject requests where the signature doesn't match.

Weekly Digest Email

Every Sunday at 6:00 PM (workspace timezone), Morgenruf sends a weekly digest email to the workspace admin. The email includes:

  • Total responses for the week
  • Overall participation percentage
  • Per-member breakdown with a 🟒 bar chart
ℹ️

Weekly digest emails require RESEND_API_KEY to be set in your environment. Without it, digest emails are silently skipped. See the Environment Variables section below.

Environment Variables

If you're self-hosting, set these environment variables in your .env file or container environment.

Variable Required Description
SLACK_CLIENT_ID βœ… Required Client ID from your Slack app's Basic Information page.
SLACK_CLIENT_SECRET βœ… Required Client Secret (32 hex chars). Keep this secret β€” never commit to source control.
SLACK_SIGNING_SECRET βœ… Required Signing Secret (32 hex chars). Different from the Client Secret. Found under Basic Information in your Slack app settings.
DATABASE_URL βœ… Required PostgreSQL connection string, e.g. postgresql://user:pass@host:5432/db
APP_URL βœ… Required Public HTTPS URL of this instance (no trailing slash), e.g. https://api.your-domain.com. Used for OAuth redirect URIs and webhook callbacks.
FLASK_SECRET_KEY βœ… Required Secret key for Flask session signing. Generate with: openssl rand -hex 32
RESEND_API_KEY Optional API key for Resend. Required for welcome emails and weekly digest emails. Emails are silently skipped if omitted.
PORT Optional HTTP port to listen on. Defaults to 3000.
LOG_LEVEL Optional Logging verbosity: DEBUG, INFO, or WARNING. Defaults to INFO.
⚠️

Keep your secrets safe. Never commit SLACK_CLIENT_SECRET, SLACK_SIGNING_SECRET, or FLASK_SECRET_KEY to source control. Use a .env file (gitignored) or a secrets manager.