Files
when/docs/when.example.yaml
eleith e11ef0d16f
ci/woodpecker/pr/calendar Pipeline was successful
ci/woodpecker/pr/cli Pipeline was successful
ci/woodpecker/pr/config Pipeline was successful
ci/woodpecker/pr/db Pipeline was successful
ci/woodpecker/pr/jobs Pipeline was successful
ci/woodpecker/pr/video-chat Pipeline was successful
ci/woodpecker/pr/web Pipeline was successful
ci/woodpecker/pr/worker Pipeline was successful
ci/woodpecker/push/calendar Pipeline was successful
ci/woodpecker/push/cli Pipeline was successful
ci/woodpecker/push/config Pipeline was successful
ci/woodpecker/push/db Pipeline was successful
ci/woodpecker/push/jobs Pipeline was successful
ci/woodpecker/push/video-chat Pipeline was successful
ci/woodpecker/push/web Pipeline was successful
ci/woodpecker/push/worker Pipeline was successful
feat(config): make Docker onboarding YAML-first
2026-11-01 19:04:16 -08:00

182 lines
7.5 KiB
YAML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# yaml-language-server: $schema=http://localhost:3000/schema.json
# Copy to config/when.yaml and replace the placeholders.
# The schema comes from the running app; adjust its URL if you use another address.
# Edit this file with your real URL, account details and passwords before starting.
# No .env file is required. Keep this file private when it contains secrets.
# Optional fields and defaults are commented below. Any string can use ${ENV_VAR}
# from an optional .env file beside compose.yaml instead of a literal value.
# Shape of this file. Defaults to 1 and only changes if the config layout does.
# version: 1
# --- Your public URL: must match the trusted reverse proxy's public origin ---
url:
app: 'https://when.example.com'
# internal: 'http://when-app:3000' # worker → web; supplied by the worker image
# worker: 'http://when-worker:9000' # web → worker; default private Compose address
# --- Admin sign-in: exactly one of `credentials` or `oidc` ---
auth:
credentials:
username: admin
password: '' # required: set your own password before starting
# Or single sign-on instead of credentials:
# oidc:
# issuer: 'https://accounts.example.com'
# client_id: 'when'
# client_secret: '' # required: your provider's client secret
# # name defaults to 'Single Sign-On'
# # name: 'Single Sign-On'
# Omit secret to generate a secure session key at startup; restarts sign you out.
# To keep sessions across restarts, generate a value once: openssl rand -base64 32
# secret: '${AUTH_SECRET}' # or put the generated value directly here
# --- The schedule owner ---
user:
name: 'Your Name'
email: 'you@example.com'
# timezone defaults to the ${TZ} env var, or UTC
# timezone: 'America/New_York'
# appearance is optional — every field below shows its default:
# appearance:
# title: 'if not now, when?'
# description: 'find some time and we can meet'
# app_icon_path: '/assets/images/app-icon.svg'
# avatar_path: '/assets/images/avatar.svg'
# favicon_path: '/assets/images/favicon.svg'
# opengraph_path: '/assets/images/opengraph.png'
# font_name: 'Noto Sans' # bundled: Noto Sans, Lato, Outfit, Inter
# font_path: '/public/my-font.woff2' # a woff2 you serve, for a non-bundled font_name
# primary_light_color: '#166534'
# primary_dark_color: '#34d399'
# background_light_color: '#f5f5f5'
# background_dark_color: '#0a0a0a'
# text_light_color: '#171717'
# text_dark_color: '#ededed'
# --- SMTP, used to send appointment emails (required) ---
smtp:
host: 'smtp.example.com'
username: 'you@example.com'
password: '' # required: your SMTP password
# port defaults to 587
# port: 465
# from defaults to noreply@<your url.app domain>
# from: 'bookings@example.com'
# --- Providers and the calendars they serve ---
# Each provider is named by its key. Calendars are conflict sources (busy times)
# and booking destinations; their keys must be unique across every provider,
# since meetings reference them by name alone.
providers:
caldav-service:
type: 'caldav'
url: 'https://caldav.example.com/dav/' # DAV base URL
username: 'you'
password: '' # required: your CalDAV password
calendars:
main:
href: 'calendars/you/main/' # joined to the provider url, or give a full URL instead
# sync:
# refresh_every_minutes: 10 # busy-time refresh cadence (default 10)
# Google (connect it from /admin, which shows the refresh token to save):
# google-service:
# type: 'google'
# client_id: '...apps.googleusercontent.com'
# client_secret: '' # required: your Google client secret
# # Optional — omit it and the provider reads as not connected. Connect from
# # /admin, then save the supplied token here (or use optional interpolation).
# refresh_token: ''
# calendars:
# personal:
# id: 'primary'
# Nextcloud (a CalDAV-compatible provider, also usable for Talk video links):
# nextcloud-service:
# type: 'nextcloud'
# url: 'https://cloud.example.com'
# username: 'you'
# password: '' # required: your Nextcloud password
# calendars:
# shared:
# href: 'calendars/you/shared/'
# --- Weekly availability (times are in user.timezone) ---
# `weekly` is a list of rules; availability is the union of all rules.
schedules:
standard:
weekly:
- days: [mon, tue, wed, thu, fri]
from: '09:00'
to: '17:00'
# For multiple windows in a day (e.g. a lunch break), repeat the days:
# - days: [fri]
# from: '09:00'
# to: '13:00'
# - days: [fri]
# from: '14:00'
# to: '17:00'
# A day named by no rule is unavailable (here: sat, sun).
# weekly may be omitted entirely = Monday–Friday 09:00–17:00
# --- Bookable meeting types ---
# The key is the URL slug: /schedule/30-min-chat
meetings:
30-min-chat:
title: '30-minute chat'
duration_minutes: 30 # the default length offered (default 30)
# additional_duration_minutes: [15, 60] # further lengths the guest may pick
require_approval: true # true (host approves each booking) or false (instant)
# description: 'A quick introductory call.'
# visibility: 'public' # 'public' (listed) or 'unlisted' (off the homepage; the link still works)
schedule: 'standard'
booking_calendar: 'main'
# additional_busy_calendars: ['personal'] # further calendars to check; booking_calendar is always checked
# location: 'Suite 200, 123 Main St' # a static address, phone, or link
# video_chat:
# provider: 'nextcloud-service' # configure the provider above first
# attach:
# auto: true # or false for host-only generation; use auto OR when, not both
# # when: # instead of auto, match the form below
# # - field: 'topic'
# # equals: 'Support'
# Google Meet requires a Google booking calendar.
# note: 'Please add an agenda when you book.'
# notice_minutes: 120 # minimum lead time (default 120)
# booking_window_days: 60 # how far ahead bookings open (default 60)
# padding_before_minutes: 0
# padding_after_minutes: 0
# daily_booking_limit: null # null = unlimited
# show_slots: false # true draws the slots as buttons; false is a bare drag timeline
# start_times_every_minutes: 15 # slot step (default 30; independent of the lengths offered)
# form_fields: # replaces the default form; include a required guest_name
# - name: 'name'
# type: 'guest_name'
# label: 'Your name'
# required: true
# - name: 'email'
# type: 'guest_email'
# label: 'Your email'
# required: true
# - name: 'topic'
# type: 'choice' # guest_name | guest_email | event_location | text | number | phone | paragraph | choice
# label: 'What would you like to discuss?'
# required: false
# choices: ['Sales', 'Support'] # only for choice or event_location
# - name: 'phone'
# type: 'phone'
# label: 'Your phone number'
# required: true # required only while shown
# show_when: # show only when every condition holds (AND)
# - field: 'topic' # references an earlier field by name
# equals: 'Sales' # value or list to match; omit to mean "filled at all"
# --- On-disk SQLite paths (relative to the deployment root); defaults shown ---
# database:
# app: './data/when.sqlite'
# queue: './data/openworkflow.sqlite'
# --- Prometheus metrics (off by default) ---
# prometheus:
# enabled: false
# token: '${WHEN_METRICS_TOKEN}' # bearer token for scraping /metrics