Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
22823da
breaking: 2026 full-stack modernization
codeGlaze Feb 17, 2026
026b031
docs: add migration documentation for 2026 stack modernization
codeGlaze Feb 17, 2026
6249565
consolidate dev tooling into user.clj, overhaul README
codeGlaze Feb 17, 2026
d163ca9
polish: UI fixes, zero-warning builds, dev-mode CSP, user tooling
codeGlaze Feb 18, 2026
c2290ca
fix: eliminate subscribe-outside-reactive-context warnings
codeGlaze Feb 18, 2026
b96b1b6
test: add CLJS test infrastructure and pure function tests
codeGlaze Feb 18, 2026
263f290
fix: replace :class-name with :class for Reagent 2.x compatibility
codeGlaze Feb 18, 2026
9cbc25a
replace prereq-fn subscribes with pure character fns
codeGlaze Feb 18, 2026
3249f88
replace multiclass/wizard prereq subscribes with pure fns in classes.…
codeGlaze Feb 18, 2026
09d7e4c
fix: eliminate remaining subscribe-outside-reactive-context warnings
codeGlaze Feb 18, 2026
6124d9f
test: add tests for compute-all-weapons-map, feat-prereqs, pdf_spec
codeGlaze Feb 18, 2026
d108134
refactor: move input debounce from component to entity/build subscrip…
codeGlaze Feb 18, 2026
f578cdb
fix: convert def+partial with subscribe to defn for reactive context
codeGlaze Feb 19, 2026
1d50782
merge: integrate develop (folders, weapons, docker) into breaking branch
codeGlaze Feb 19, 2026
f28f58f
harden: folder CRUD safety, validation, docs
codeGlaze Feb 19, 2026
bb2400d
cleanup: remove 11 orphaned subscriptions, add changelog
codeGlaze Feb 19, 2026
792fe3c
fix: resolve clj-kondo forward-reference error in on-folder-failure
codeGlaze Feb 19, 2026
29c9f28
merge: integrate lint fixes (if→when) from fix/lint-missing-else
codeGlaze Feb 19, 2026
7476f10
config: consolidate lint config, expand scope, bump clj-kondo
codeGlaze Feb 19, 2026
6bbcd9a
lint: dead code + redundant expressions in shared .cljc files
codeGlaze Feb 19, 2026
b68b917
lint: dead code + redundant expressions in frontend .cljs files
codeGlaze Feb 19, 2026
24df45b
lint: fixes in native, web, test, registration + docs
codeGlaze Feb 19, 2026
0359f32
merge: integrate error handling + import validation from feature branch
codeGlaze Feb 21, 2026
69958f5
fix: add missing kw-base and traverse-nested to common.cljc
codeGlaze Feb 21, 2026
0d8b277
fix: restore incorrectly discarded template and summary-map subscript…
codeGlaze Feb 21, 2026
f307609
fix: flyout menu flickering + dropdown duplicate React keys
codeGlaze Feb 21, 2026
79a6a54
feat: prevent and dedup duplicate selection options in homebrew
codeGlaze Feb 21, 2026
90a83d3
fix: guard combat tracker against nil-state localStorage corruption
codeGlaze Feb 21, 2026
0a9b5c7
fix: restore equipment map subs + template cache timing race
codeGlaze Feb 21, 2026
1971239
fix: subscribe-outside-reactive regression + missing content false po…
codeGlaze Feb 21, 2026
dce1863
fix: content reconciliation accuracy + subscribe warning elimination
codeGlaze Feb 21, 2026
302f603
fix: feat detection matched grandchildren instead of direct children
codeGlaze Feb 21, 2026
906ef46
refactor: replace generic tree walk with direct entity extraction
codeGlaze Feb 21, 2026
f46b956
fix: template cache subscribe guard + auth error diagnostics
codeGlaze Feb 22, 2026
22e48cc
docs: getting started guide, env var docs, dev SIGNATURE default
codeGlaze Feb 22, 2026
4133dd1
fix: party creation page crash from eager JS reload
codeGlaze Feb 22, 2026
364d971
feat: auto-generate character names + fix grappler SRD detection
codeGlaze Feb 22, 2026
103fc84
ci: dual-stack detection for Java 8 and Java 21 branches
codeGlaze Feb 22, 2026
beac09a
Merge pull request #22 from codeGlaze/ci/dual-stack-workflow
codeGlaze Feb 22, 2026
7a5d04e
merge: integrate dual-stack CI from develop
codeGlaze Feb 22, 2026
39155a4
fix: resolve all lint errors and warnings
codeGlaze Feb 22, 2026
8ca47ab
fix: clean up noisy CI log output
codeGlaze Feb 22, 2026
14af98d
fix: Docker tag pin, CI fork-PR tolerance, redundant str removal
codeGlaze Feb 22, 2026
4d7284c
fix: upgrade Docker stack to Java 21 + Datomic Pro, fix healthchecks
codeGlaze Feb 22, 2026
55e9f49
fix: Alpine compatibility for Docker images
codeGlaze Feb 22, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 58 additions & 9 deletions .clj-kondo/config.edn
Original file line number Diff line number Diff line change
@@ -1,8 +1,47 @@
{:output {:exclude-files [".*resources/public/js/compiled.*"
{;; Prevent analysis of compiled CLJS output -- source copies live there
;; and cause "redefined var" when IDE analyzes both src/ and compiled/.
:exclude-files "resources/public/js/compiled"
:output {:exclude-files [".*resources/public/js/compiled.*"
".*docker/scripts/.*"]}
:linters {:shadowed-fn-param {:level :off}
:shadowed-var {:level :off}
:linters {;; Enabled at :warning so NEW accidental shadows are caught.
;; :exclude covers established patterns: core vars used as param names
;; (name, key, type, etc.) and domain terms used as both defs and params
;; (level, ability, armor, etc.) across modifier/option/character code.
:shadowed-fn-param {:level :warning
:exclude [source character]}
:shadowed-var {:level :warning
:exclude [;; clojure.core / cljs.core vars used as parameter names
name key type val num first last next ns fn comp
int char chars bytes str time atom ref set class
list map range min max mod count filter flatten
keys vals identity ancestors comparator cond
list? sequential? set?
;; re-frame.core/path — used as param in route handlers
path
;; Domain terms used as both ns-level defs and fn params
;; in modifiers.cljc, options.cljc, character.cljc, etc.
level levels level-key ability abilities armor weapon weapons
action alignment cls equipment size subclass-name
skill-options skill-expertise tool-options weapon-proficiency-options
spellcasting-template feat-selections cantrip-selections
sorted-items selected-plugin-options built-template
;; One-off project-var shadows — established code patterns
;; where a fn/let binding intentionally shadows its ns def
actual-path all-armor-inventory app-header
available-selections builder-page character-summary
children critical-hit-values custom-equipment entity
first-class? following-usernames i instant item-adder
languages levels-selection message mod-cfg mod-key
name-result parties party-owner prepared-spells-by-class
prepares-spells query-map search-results source speed
spells-known style view]}
;; 213 warnings. Many namespaces are required purely for side effects:
;; re-frame event/sub registrations, modifier macros, spec loading.
;; Remaining are test cleanup debt (genuinely unused test requires).
:unused-namespace {:level :off}
;; 567 warnings. Destructured map bindings used for documentation or
;; structure (e.g. {:keys [name level key]} where only some are used
;; in the body). Renaming to _ would lose semantic readability.
:unused-binding {:level :off}
:missing-else-branch {:level :warning}
:clojure-lsp/unused-public-var
Expand All @@ -14,17 +53,17 @@
orcpub.dnd.e5.options/spell-tags
orcpub.dnd.e5.options/potent-spellcasting
;; Live callers exist but LSP can't trace them
orcpub.common/dissoc-in ; events.cljs
orcpub.common/dissoc-in ; events.cljs:2976
orcpub.dnd.e5.character/add-ability-namespaces ; test
;; Cross-file refs: used in template.cljc but defined in spell_subs.cljs
orcpub.dnd.e5.spell-subs/sunlight-sensitivity
orcpub.dnd.e5.spell-subs/mask-of-the-wild-mod]
;; re-frame event handlers are dispatched via keyword, not var reference.
;; LSP can't connect reg-event-db registration to (dispatch [:keyword]).
:exclude-when-defined-by #{re-frame.core/reg-event-db
re-frame.core/reg-event-fx
re-frame.core/reg-sub
re-frame.core/reg-sub-raw}}
re-frame.core/reg-event-fx
re-frame.core/reg-sub
re-frame.core/reg-sub-raw}}
;; garden.selectors vars are generated by macros (defselector,
;; defpseudoclass, gen-pseudo-class-defs, etc.) at compile time.
;; clj-kondo can't resolve macro-generated vars statically and
Expand All @@ -34,8 +73,9 @@
;; errors.cljc macros behind #?(:clj) reader conditional —
;; one kondo instance can't resolve them
orcpub.errors]}
;; read-string is a valid cljs.core symbol that clj-kondo
;; doesn't recognize in its ClojureScript analysis data.
;; Macros that introduce bindings kondo can't resolve statically.
;; Each (ns/macro) entry suppresses unresolved symbols inside that
;; macro's body. Modifier macros use defmacro with gensym bindings.
:unresolved-symbol
{:exclude
[read-string
Expand Down Expand Up @@ -66,7 +106,16 @@
(orcpub.entity-spec/make-entity)
(orcpub.routes-test/with-conn)
(orcpub.routes.folder-test/with-conn)
(orcpub.email-change-test/with-conn)
(user/with-db)]}}
;; native/cljs and web/cljs are separate source roots; kondo doesn't know
;; about them so ns names appear to mismatch their file paths.
:config-in-ns {orcpub.core {:linters {:namespace-name-mismatch {:level :off}}}
orcpub.views {:linters {:namespace-name-mismatch {:level :off}}}
orcpub.dnd.e5.native-views {:linters {:namespace-name-mismatch {:level :off}}}}
;; with-conn macros use bare symbol bindings — handled via
;; :unresolved-symbol :exclude above (macroexpand hooks can't find
;; the test namespaces and produce noisy warnings).
:lint-as {reagent.core/with-let clojure.core/let
hiccup.def/defhtml clojure.core/defn
user/with-db clojure.core/let
Expand Down
77 changes: 77 additions & 0 deletions .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
FROM clojure:temurin-21-lein

# Install useful dev tools (including unzip for Datomic Pro)
RUN apt-get update \
&& apt-get install -y --no-install-recommends rlwrap git curl tmux make git-lfs lsof iproute2 unzip rsync maven \
libfreetype6 fontconfig fonts-dejavu-core fonts-liberation libxrender1 libxext6 libxi6 libxrandr2 \
&& rm -rf /var/lib/apt/lists/*

# Ensure git-lfs is configured system-wide so LFS files are available in Codespaces
RUN git lfs install --system || true

# Install Leiningen so `lein` is available for LSP and project tasks
RUN curl -fsSL https://raw.githubusercontent.com/technomancy/leiningen/stable/bin/lein -o /usr/local/bin/lein \
&& chmod +x /usr/local/bin/lein \
&& /usr/local/bin/lein --version || true

WORKDIR /workspace

# Copy project.clj first (needed to know version)
COPY project.clj /workspace/

# Copy existing lib/ directory first (preserves pdfbox and other vendor deps)
# Create lib/ directory - COPY will handle copying if lib/ exists in build context
RUN mkdir -p /workspace/lib/
COPY lib/ /workspace/lib/

# Download and install Datomic Pro to lib/ using existing file:lib repository pattern
# Latest version: https://docs.datomic.com/releases-pro.html
ARG DATOMIC_VERSION=1.0.7482
RUN echo "[DOCKER BUILD] Starting Datomic Pro ${DATOMIC_VERSION} installation..." && \
mkdir -p lib/com/datomic/datomic-pro/${DATOMIC_VERSION} && \
echo "[DOCKER BUILD] Downloading Datomic Pro zip..." && \
curl -L -o /tmp/datomic-pro-${DATOMIC_VERSION}.zip \
"https://datomic-pro-downloads.s3.amazonaws.com/${DATOMIC_VERSION}/datomic-pro-${DATOMIC_VERSION}.zip" && \
echo "[DOCKER BUILD] Extracting zip..." && \
unzip -q /tmp/datomic-pro-${DATOMIC_VERSION}.zip -d /tmp/datomic-extract && \
echo "[DOCKER BUILD] Listing extracted contents..." && \
find /tmp/datomic-extract -type f -name "*.jar" | head -5 && \
# Copy entire distribution into vendor layout so POMs and support files are available
EXTRACTED_DIR=$(find /tmp/datomic-extract -maxdepth 1 -type d ! -name . | head -1) && \
mkdir -p lib/com/datomic/datomic-pro/${DATOMIC_VERSION} && \
if [ -n "${EXTRACTED_DIR}" ]; then \
echo "[DOCKER BUILD] Copying extracted distribution from ${EXTRACTED_DIR} -> lib/com/datomic/datomic-pro/${DATOMIC_VERSION}" && \
cp -r "${EXTRACTED_DIR}"/* "lib/com/datomic/datomic-pro/${DATOMIC_VERSION}/" && \
# If a peer jar exists in the distribution, also ensure datomic-pro-<version>.jar exists for vendor layout
if [ -f "lib/com/datomic/datomic-pro/${DATOMIC_VERSION}/peer-${DATOMIC_VERSION}.jar" ]; then \
cp "lib/com/datomic/datomic-pro/${DATOMIC_VERSION}/peer-${DATOMIC_VERSION}.jar" "lib/com/datomic/datomic-pro/${DATOMIC_VERSION}/datomic-pro-${DATOMIC_VERSION}.jar"; \
fi; \
else \
# Fallback to copying a single jar if extraction produced unexpected layout
DATOMIC_POTENTIAL_JAR=$(find /tmp/datomic-extract -type f -name 'peer*.jar' -print -quit || true) && \
if [ -z "${DATOMIC_POTENTIAL_JAR}" ]; then DATOMIC_POTENTIAL_JAR=$(find /tmp/datomic-extract -type f -name 'datomic-pro-*.jar' -print -quit || true); fi && \
if [ -z "${DATOMIC_POTENTIAL_JAR}" ]; then echo "[DOCKER BUILD] ERROR: No Datomic JAR found in extracted zip" && find /tmp/datomic-extract -type f | head -20 && exit 1; fi && \
cp "${DATOMIC_POTENTIAL_JAR}" "lib/com/datomic/datomic-pro/${DATOMIC_VERSION}/datomic-pro-${DATOMIC_VERSION}.jar"; \
fi && \
echo "[DOCKER BUILD] Verifying vendor path contents..." && \
ls -lh "lib/com/datomic/datomic-pro/${DATOMIC_VERSION}/" && \
rm -rf /tmp/datomic-pro-${DATOMIC_VERSION}.zip /tmp/datomic-extract && \
echo "[DOCKER BUILD] ✅ Datomic Pro installed to lib/ (file:lib repository pattern)"

# Copy the rest of the source (exclude lib/ since we've already set it up)
# Use .dockerignore or copy selectively to avoid overwriting lib/
COPY . /workspace
# Ensure Datomic Pro JAR is still present after COPY
RUN test -f lib/com/datomic/datomic-pro/${DATOMIC_VERSION}/datomic-pro-${DATOMIC_VERSION}.jar || \
(echo "[DOCKER BUILD] ⚠️ Datomic Pro JAR missing after COPY, re-downloading..." && \
mkdir -p lib/com/datomic/datomic-pro/${DATOMIC_VERSION} && \
curl -L -o /tmp/datomic-pro-${DATOMIC_VERSION}.zip \
"https://datomic-pro-downloads.s3.amazonaws.com/${DATOMIC_VERSION}/datomic-pro-${DATOMIC_VERSION}.zip" && \
unzip -q /tmp/datomic-pro-${DATOMIC_VERSION}.zip -d /tmp/datomic-extract && \
DATOMIC_JAR=$(find /tmp/datomic-extract -name "datomic-pro-*.jar" -type f | head -1) && \
cp "${DATOMIC_JAR}" "lib/com/datomic/datomic-pro/${DATOMIC_VERSION}/datomic-pro-${DATOMIC_VERSION}.jar" && \
rm -rf /tmp/datomic-pro-${DATOMIC_VERSION}.zip /tmp/datomic-extract && \
echo "[DOCKER BUILD] ✅ Datomic Pro JAR restored")

# Default shell to bash for VS Code terminal
SHELL ["/bin/bash", "-c"]
45 changes: 45 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
{
"name": "ClojureScript Lein-Figwheel Dev",
"build": {
"dockerfile": "Dockerfile",
"context": ".."
},
"features": {
"ghcr.io/devcontainers/features/sshd:1": {
"version": "latest"
}
},
"forwardPorts": [8890, 3449, 4334],
"portsAttributes": {
"8890": {
"label": "Backend Server",
"onAutoForward": "notify"
},
"3449": {
"label": "Figwheel",
"onAutoForward": "silent"
},
"4334": {
"label": "Datomic",
"onAutoForward": "silent"
}
},
"postCreateCommand": [
"bash",
"./.devcontainer/post-create.sh"
],
"containerEnv": {
"POST_CREATE_VERBOSE": "1",
"DATOMIC_VERSION": "1.0.7482",
"DATOMIC_URL": "datomic:dev://localhost:4334/orcpub"
},
"customizations": {
"vscode": {
"extensions": [
"betterthantomorrow.calva",
"borkdude.clj-kondo"
],
"settings": {}
}
}
}
114 changes: 114 additions & 0 deletions .devcontainer/post-create.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
#!/usr/bin/env bash
#
# Datomic Pro install script for devcontainer
#
# 1. Always remove lib/com/datomic/datomic-{type}/<version> if it exists
# 2. Unzip the Datomic zip (from /lib or /tmp, download if missing) into target dir
# 3. Flatten top-level subdir if present (some zips nest contents)
# 4. Run vendor maven-install from bin/
#
# This script does NOT cherry-pick, rename, or check for specific files before extraction.
# All contents of the zip are placed in the target directory, overwriting any previous install.
#

set -euo pipefail

# Source .env from repo root if present (authoritative config)
REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
if [ -f "$REPO_ROOT/.env" ]; then
set -a
# shellcheck disable=SC1090
. "$REPO_ROOT/.env"
set +a
fi

# Redirect all output to persistent logs for visibility during Codespace creation
LOG="/tmp/orcpub-post-create.log"
WORKSPACE_LOG="$REPO_ROOT/.devcontainer/post-create.log"
# Ensure workspace log exists and is writable (best-effort)
mkdir -p "$(dirname "$WORKSPACE_LOG")" 2>/dev/null || true
touch "$WORKSPACE_LOG" 2>/dev/null || true
# Tee to both /tmp and workspace log so it's inspectable in Codespaces UI
exec > >(tee -a "$LOG" "$WORKSPACE_LOG") 2>&1

# Optional verbose tracing: set POST_CREATE_VERBOSE=1 to enable `set -x`
if [ "${POST_CREATE_VERBOSE:-0}" = "1" ]; then
echo "[POST-CREATE] Verbose tracing enabled"
set -x
fi

# Timestamp helper
ts() { date -u +"%Y-%m-%dT%H:%M:%SZ"; }
log() { echo "$(ts) [POST-CREATE] $*"; }

log "Starting postCreateCommand... (logging to $LOG and $WORKSPACE_LOG)"

# Configuration with defaults
DATOMIC_TYPE="${DATOMIC_TYPE:-pro}"
RAW_DATOMIC_VERSION="${DATOMIC_VERSION:-1.0.7482}"
# basename in case a path was provided (e.g., /tmp/datomic-pro-1.0.7482.zip)
RAW_DATOMIC_VERSION="$(basename "$RAW_DATOMIC_VERSION")"
# strip leading prefix and trailing .zip if present
DATOMIC_VERSION="${RAW_DATOMIC_VERSION#datomic-${DATOMIC_TYPE}-}"
DATOMIC_VERSION="${DATOMIC_VERSION%.zip}"

log "Using DATOMIC_TYPE=$DATOMIC_TYPE, DATOMIC_VERSION=$DATOMIC_VERSION"

# Paths
TARGET_DIR="lib/com/datomic/datomic-${DATOMIC_TYPE}/${DATOMIC_VERSION}"
ZIP_NAME="datomic-${DATOMIC_TYPE}-${DATOMIC_VERSION}.zip"
DOWNLOAD_URL="https://datomic-pro-downloads.s3.amazonaws.com/${DATOMIC_VERSION}/${ZIP_NAME}"

# Clean and prepare target directory
if [ -d "${TARGET_DIR}" ]; then
log "Removing existing installation at ${TARGET_DIR}"
rm -rf "${TARGET_DIR}"
fi
mkdir -p "${TARGET_DIR}"

# Find Datomic zip in /lib/ or /tmp/, download if missing
ZIP_PATH="/lib/${ZIP_NAME}"
if [ ! -f "$ZIP_PATH" ]; then
ZIP_PATH="/tmp/${ZIP_NAME}"
if [ ! -f "$ZIP_PATH" ]; then
log "Downloading Datomic from $DOWNLOAD_URL"
curl --fail --location --progress-bar -o "$ZIP_PATH" "$DOWNLOAD_URL"
fi
fi

# Verify zip integrity (handles corrupt/incomplete downloads)
if ! unzip -t "$ZIP_PATH" >/dev/null 2>&1; then
log "Corrupt or incomplete zip detected, removing and re-downloading..."
rm -f "$ZIP_PATH"
curl --fail --location --progress-bar -o "$ZIP_PATH" "$DOWNLOAD_URL"

# Verify the re-download
if ! unzip -t "$ZIP_PATH" >/dev/null 2>&1; then
log "ERROR: Re-downloaded zip is still corrupt. Check network connection or URL."
log "URL: $DOWNLOAD_URL"
exit 1
fi
fi

# Unzip Datomic distribution into target dir
log "Extracting $ZIP_PATH to $TARGET_DIR"
unzip -q "$ZIP_PATH" -d "${TARGET_DIR}"

# Flatten if needed (some zips nest contents in a subdirectory)
TOP_SUBDIR=$(find "${TARGET_DIR}" -mindepth 1 -maxdepth 1 -type d -print -quit || true)
if [ -n "${TOP_SUBDIR}" ] && [ -z "$(find "${TARGET_DIR}" -maxdepth 1 -type f -print -quit)" ]; then
log "Flattening nested directory structure"
mv "${TOP_SUBDIR}"/* "${TARGET_DIR}/"
rmdir "${TOP_SUBDIR}"
fi

# Run vendor maven-install
if [ -x "${TARGET_DIR}/bin/maven-install" ]; then
log "Running maven-install..."
(cd "${TARGET_DIR}" && bash bin/maven-install)
else
log "ERROR: bin/maven-install not found or not executable in ${TARGET_DIR}/bin"
exit 1
fi

log "Datomic ${DATOMIC_TYPE} ${DATOMIC_VERSION} installed successfully to ${TARGET_DIR}"
17 changes: 15 additions & 2 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,30 @@
PORT=8890

# --- Datomic Database ---
# Datomic Pro with dev storage protocol (required for Java 21 support)
# ADMIN_PASSWORD secures the Datomic admin interface
# DATOMIC_PASSWORD is used by the application to connect to Datomic
# The password in DATOMIC_URL must match DATOMIC_PASSWORD
ADMIN_PASSWORD=change-me-admin
DATOMIC_PASSWORD=change-me-datomic
DATOMIC_URL=datomic:free://datomic:4334/orcpub?password=change-me-datomic
DATOMIC_URL=datomic:dev://datomic:4334/orcpub?password=change-me-datomic

# --- Security ---
# Secret used to sign JWT tokens (20+ characters recommended)
# REQUIRED: JWT signing secret. Authentication will fail without this.
# 20+ random characters recommended (e.g., openssl rand -hex 16)
SIGNATURE=change-me-to-something-unique-and-long

# Content Security Policy (strict|permissive|none)
CSP_POLICY=strict

# Dev mode: CSP violations are logged (Report-Only) instead of blocked,
# allowing Figwheel hot-reload scripts to execute.
DEV_MODE=true

# --- Logs ---
# Defaults to project logs/ if unset
LOG_DIR=

# --- Email (SMTP) ---
# Leave EMAIL_SERVER_URL empty to disable email functionality
EMAIL_SERVER_URL=
Expand Down
Loading
Loading