{% extends "dashboard_base.html" %} {% block title %}Admin — calrs{% endblock %} {% block dashboard_content %}

Admin dashboard

{% if error_message %}
Action refused: {{ error_message }}
{% endif %}

Company logo

Displayed on public booking pages. Recommended: PNG or SVG, max 2 MB.

{% if has_logo %}
Company logo
{% endif %}
{% if has_logo %}
{% endif %}
Logo links to this URL on public booking pages. Leave empty for no link.

Theme

Choose a color theme for all pages. The dark/light toggle is separate — themes adapt to both modes.

{% set themes = [ {"id": "default", "label": "Default", "desc": "Clean blue", "colors": ["#2563eb", "#eff6ff", "#f4f4f5", "#18181b"]}, {"id": "nord", "label": "Nord", "desc": "Arctic frost", "colors": ["#5e81ac", "#e8eef5", "#eceff4", "#2e3440"]}, {"id": "dracula", "label": "Dracula", "desc": "Dark purple", "colors": ["#bd93f9", "#f3eefe", "#f0edf5", "#282a36"]}, {"id": "gruvbox", "label": "Gruvbox", "desc": "Retro warm", "colors": ["#d65d0e", "#fabd2f", "#f9f5d7", "#282828"]}, {"id": "solarized", "label": "Solarized", "desc": "Ethan's classic", "colors": ["#268bd2", "#859900", "#fdf6e3", "#002b36"]}, {"id": "tokyo-night", "label": "Tokyo Night", "desc": "Neon cityscape", "colors": ["#7a5af5", "#7aa2f7", "#f0f0f5", "#1a1b26"]}, {"id": "vates", "label": "Vates", "desc": "Rouge & Bleu Spatial", "colors": ["#be1621", "#ef7f18", "#1a1b38", "#2ca878"]}, {"id": "custom", "label": "Custom", "desc": "Your colors", "colors": []} ] %} {% for t in themes %} {% endfor %}
Custom colors

Users ({{ user_count }})

{% if users %}
{% for u in users %}
{{ u.name }} {{ u.email }} {% if u.role == "admin" %}admin{% endif %} {% if not u.enabled %}disabled{% endif %} {{ u.auth_provider }}
{% if u.groups %}
{% for g in u.groups %} {{ g }} {% endfor %}
{% endif %}
{% if u.id != current_user_id %} {% else %}
(you)
{% endif %}
{% endfor %}
{% else %}

No users yet.

{% endif %}

Groups ({{ group_count }})

{% if groups %}
{% for g in groups %} {% endfor %}
Group name Members
{{ g.name }} {% if g.members %}
{% for m in g.members %}
5 %} class="group-member-extra" data-group="{{ g.id }}" style="display: none; align-items: center; gap: 0.5rem;"{% else %} style="display: flex; align-items: center; gap: 0.5rem;"{% endif %}> {{ m.name }}
{% endfor %} {% if g.members | length > 5 %} {% endif %}
{% else %} {{ g.member_count }} {% endif %}
{% else %}

No groups synced yet. Groups are automatically synced from your OIDC provider.

{% endif %}

Auth settings

OIDC settings

Status: {% if oidc_enabled %}enabled{% else %}disabled{% endif %} {% if oidc_issuer_url %}· Issuer: {{ oidc_issuer_url }}{% endif %} {% if oidc_client_id %}· Client ID: {{ oidc_client_id }}{% endif %}

Google Calendar (OAuth2)

Status: {% if google_oauth2_configured %}configured{% else %}not configured{% endif %} {% if google_oauth2_client_id %}· Client ID: {{ google_oauth2_client_id }}{% endif %}

To enable Google Calendar integration, create OAuth2 credentials at Google Cloud Console. Enable the Google Calendar API, then add {{ base_url }}/dashboard/sources/google/callback as an authorized redirect URI.

Captcha

Status: {% if captcha_configured %}enabled{% else %}disabled{% endif %} {% if captcha_instance_url %}· Instance: {{ captcha_instance_url }}{% endif %}
Override if the CDN is blocked. Changes take effect immediately after saving.

Leave instance URL, site key and secret empty to disable captcha on booking pages.

Jitsi (auto-generated meeting links)

Status: {% if jitsi_configured %}enabled{% else %}disabled{% endif %} {% if jitsi_base_url %}· Base URL: {{ jitsi_base_url }}{% endif %}

When an event type's location is set to "Jitsi (auto-generated room)", calrs builds a fresh room URL per booking by appending the pattern below to your Jitsi base URL. No external API call is needed.

Shown to guests on the slot picker and booking form. Defaults to "Video call" if empty.
Available tokens: {username} (host), {event} (event type slug), {date} (YYYYMMDD), {random} (8 chars). Default: {{ jitsi_default_pattern }}.

Leave the base URL empty to disable Jitsi auto-generation.

Meeting webhook (bring-your-own provider)

Status: {% if meeting_webhook_configured %}enabled{% else %}disabled{% endif %} {% if meeting_webhook_url %}· URL: {{ meeting_webhook_url }}{% endif %}

When an event type's location is set to "Webhook (custom provider)", calrs POSTs the booking payload to this URL on confirmation and expects a JSON body {"url": "https://..."} back.

Shown to guests instead of the generic "Video call" badge.
With HMAC, calrs sends X-Calrs-Signature: sha256=<hex> over the raw request body.

Leave the URL empty to disable the meeting webhook.

SMTP settings

{% if smtp_error %}

SMTP environment configuration error: {{ smtp_error }}

{% elif smtp_configured %}
Status: configured{% if not smtp_enabled %} (disabled){% endif %}{% if smtp_from_env %} (via environment){% endif %}
Host: {{ smtp_host }}:{{ smtp_port }}
From: {{ smtp_from_email }}
{% else %}

SMTP is not configured.

{% endif %}

Configure via environment variables: CALRS_SMTP_HOST, CALRS_SMTP_PORT, CALRS_SMTP_TLS_MODE (starttls or tls), CALRS_SMTP_USERNAME, CALRS_SMTP_PASSWORD, CALRS_SMTP_FROM_EMAIL, CALRS_SMTP_FROM_NAME.

{% endblock dashboard_content %}