feat(ntfy): add custom title and message templates for notifications#6804
Conversation
CommanderStorm
left a comment
There was a problem hiding this comment.
Contains a bunch of unrelated changes that I would like to see removed, but once they are LGTM.
db/knex_migrations/2026-01-23-0000-add-ntfy-custom-templates.js
Outdated
Show resolved
Hide resolved
| <div class="mb-2"> | ||
| <i18n-t tag="span" keypath="liquidIntroduction"> | ||
| <a href="https://liquidjs.com/" target="_blank">{{ $t("documentation") }}</a> | ||
| </i18n-t> | ||
| </div> | ||
| <div class="mb-2"> | ||
| <strong>{{ $t("templateAvailableVariables") }}:</strong> | ||
| <code v-pre>{{ status }}</code> | ||
| , | ||
| <code v-pre>{{ name }}</code> | ||
| , | ||
| <code v-pre>{{ hostnameOrURL }}</code> | ||
| , | ||
| <code v-pre>{{ msg }}</code> | ||
| , | ||
| <code v-pre>{{ monitorJSON }}</code> | ||
| , | ||
| <code v-pre>{{ heartbeatJSON }}</code> | ||
| </div> | ||
| <div class="mt-3 p-2" style="background-color: rgba(100, 100, 100, 0.1); border-radius: 4px"> | ||
| <div class="mb-1"> | ||
| <strong>{{ $t("example") }}:</strong> | ||
| </div> | ||
| <div class="mb-2"> | ||
| <code v-pre style="font-size: 0.85em; word-break: break-all"> | ||
| {% for tag in monitorJSON.tags %}{{ tag.name }}{% unless tag.value == blank %}: | ||
| {{ tag.value }}{% endunless %}{% unless forloop.last %}, {% endunless %}{% endfor %} | ||
| </code> | ||
| </div> | ||
| <div style="font-size: 0.9em"> | ||
| <strong>{{ $t("Result") }}:</strong> | ||
| <span style="opacity: 0.9">nightly, phone: fbal</span> | ||
| </div> | ||
| </div> |
There was a problem hiding this comment.
Please use the components that the other notification providers use for this
There was a problem hiding this comment.
I'm not sure if I'm suppose to respond here and "resolve conversation", but I've updated the code and the PR, so you can review it now.
Thank you for taking the time to review my PR. |
|
Tangling monitor and notification logic is very hard to maintain/reason about and I don't think this is a good idea. Notifications can still be templated differently for some monitors, just via different notification configurations, not what you are trying to add. |
Add optional custom templates for ntfy notification titles and messages using the existing LiquidJS templating system. Supports both notification-level templates (in ntfy settings) and per-monitor overrides (in monitor edit page). - Notification-level templates in ntfy notification settings - Per-monitor template overrides in monitor edit page - Uses existing renderTemplate() with LiquidJS (same as SMTP, Telegram) - Priority: monitor-level > notification-level > default format - Backward compatible: empty templates use default Uptime Kuma format - Database migration adds ntfy_custom_title and ntfy_custom_message to monitor table - Notification-level templates stored in JSON config field (no schema change needed) Related: louislam#6797
Remove per-monitor template functionality and simplify to notification-level templates only, as requested by maintainer. Changes based on maintainer feedback: - Remove database migration entirely - Remove all monitor-level template fields and logic - Change UI to checkbox approach (matching Telegram pattern) - Use standard TemplatedInput and TemplatedTextarea components - Revert ToggleSection auto-expand feature - Update translation keys for checkbox UI - Simplify ntfy.js to only use notification.ntfyUseTemplate This keeps notification and monitor logic cleanly separated. Users can create multiple ntfy notifications with different templates for different monitors. Related: louislam#6797, louislam#6804
Simplify the custom template UI based on maintainer feedback: - Replace TemplatedInput/TemplatedTextarea with plain HTML elements to avoid duplicate help text - Add shared help text explaining LiquidJS templating and available variables above both input fields - Change from v-if to v-show for better performance - Add auto-enable logic for template checkbox when fields have content This makes the UI cleaner and follows the DRY principle by showing template documentation once instead of repeating it for each field.
344c905 to
cc17d4c
Compare
If you have roughly two systems in the codebase and then they start interacting like you have shown this just is very hard to maintain long term. Notification templating yes, per monitor notification template no |
|
I see that you marked this PR as draft. Is there anything else that was required from me that I didn't do? |
|
Yes, the PR does not quite seem done. It contains a few changes which are leftover from previous versions (such as changing the toggler) and the frontend does not yet use the components we have for adding templatable inputs. It is still a draft. |
|
Ok, if you could point out what I missed, I'll fix it. |
|
I thing the unrelated changes should be clear and where to use I don't quite understand where what I posted is unclear. |
…evert ToggleSection changes - Revert ToggleSection.vue to match master (remove leftover changes) - Replace plain input/textarea with TemplatedInput/TemplatedTextarea components - Remove duplicate help text (components provide it automatically) - Matches pattern used in SMTP and other notification providers
CommanderStorm
left a comment
There was a problem hiding this comment.
LGTM now, thanks ❤️
I am fine with being a bit verbose in the UI if this checkbox is ticked.
It is not the default anyhow 👍🏻
There was a problem hiding this comment.
Pull request overview
Adds optional Liquid-based templating for ntfy notification titles and messages, configurable from the ntfy notification settings UI and applied server-side when sending ntfy notifications.
Changes:
- Updated English i18n strings for templating help text and new ntfy template UI labels.
- Added ntfy notification settings UI to enable/disable templates and edit custom title/message templates.
- Implemented server-side template rendering for ntfy title/message when templates are enabled.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| src/lang/en.json | Adds new ntfy template-related strings and adjusts the general Liquid introduction text. |
| src/components/notifications/Ntfy.vue | Adds template toggle plus custom title/message template inputs to the ntfy notification editor UI. |
| server/notification-providers/ntfy.js | Applies renderTemplate() to title/message when ntfyUseTemplate is enabled. |
| "liquidIntroduction": "Templatability is achieved via the Liquid templating language. Please refer to the {0} for usage instructions.", | ||
| "templateAvailableVariables": "Available variables", | ||
| "example": "Example", | ||
| "Result": "Result", |
There was a problem hiding this comment.
The updated liquidIntroduction string no longer introduces the variable list, but TemplatedInput.vue/TemplatedTextarea.vue still render the variables directly beneath it, which makes the UI read abruptly. Also, the newly added keys templateAvailableVariables, example, and Result are not referenced anywhere in src/ (verified via search), so they appear to be dead translations. Consider either wiring these keys into the templated input components (e.g., add headings/labels) or removing them and restoring the original introduction text.
| "liquidIntroduction": "Templatability is achieved via the Liquid templating language. Please refer to the {0} for usage instructions.", | |
| "templateAvailableVariables": "Available variables", | |
| "example": "Example", | |
| "Result": "Result", | |
| "liquidIntroduction": "Templatability is achieved via the Liquid templating language. The following variables are available; please refer to the {0} for full usage instructions.", |
| // Default values | ||
| let title = monitorJSON.name + " " + status + " [Uptime-Kuma]"; | ||
| let message = heartbeatJSON.msg; | ||
|
|
||
| // Apply custom templates from notification settings if enabled | ||
| if (notification.ntfyUseTemplate) { | ||
| const customTitle = notification.ntfyCustomTitle?.trim() || ""; | ||
| const customMessage = notification.ntfyCustomMessage?.trim() || ""; | ||
|
|
||
| if (customTitle !== "") { | ||
| title = await this.renderTemplate(customTitle, msg, monitorJSON, heartbeatJSON); | ||
| } | ||
| if (customMessage !== "") { | ||
| message = await this.renderTemplate(customMessage, msg, monitorJSON, heartbeatJSON); | ||
| } | ||
| } |
There was a problem hiding this comment.
The PR description mentions per-monitor template overrides and a database migration adding ntfy_custom_title/ntfy_custom_message, plus a precedence order (monitor-level > notification-level > default). In the current changes, only notification-level fields (ntfyUseTemplate, ntfyCustomTitle, ntfyCustomMessage) are implemented and there are no monitor-level fields/migrations in the codebase (verified via repo search). Please either implement the missing monitor-level behavior/migration or update the PR description and linked issue resolution accordingly.
| // Apply custom templates from notification settings if enabled | ||
| if (notification.ntfyUseTemplate) { | ||
| const customTitle = notification.ntfyCustomTitle?.trim() || ""; | ||
| if (customTitle !== "") { | ||
| title = await this.renderTemplate(customTitle, msg, monitorJSON, heartbeatJSON); | ||
| } | ||
|
|
||
| const customMessage = notification.ntfyCustomMessage?.trim() || ""; | ||
| if (customMessage !== "") { | ||
| message = await this.renderTemplate(customMessage, msg, monitorJSON, heartbeatJSON); | ||
| } | ||
| } |
There was a problem hiding this comment.
The custom template rendering logic is duplicated between the heartbeatJSON == null path and the normal heartbeat path. To reduce the chance of future drift (e.g., updating trimming rules or adding new context variables in only one branch), consider extracting a small helper that applies templates and returns the final title/message.
Thank you for the explanations and assistance and ofc, for the merge :) cheers |





Add optional custom templates for ntfy notification titles and messages using the existing LiquidJS templating system. Supports both notification-level templates (in ntfy settings) and per-monitor overrides (in monitor edit page).
Related: #6797
Summary
In this pull request, the following changes are made:
This adds optional custom templates for ntfy notification titles and messages. Users can set a custom title and message in the ntfy notification settings, and optionally override them per monitor on the edit monitor page. Both use the existing LiquidJS templating system, so it fits the approach in #646.
Related to feature request #6797
Please follow this checklist to avoid unnecessary back and forth (click to expand)
I understand that I am responsible for and able to explain every line of code I submit.
Screenshots for Visual Changes
Notification service edit page
Default collapsed (when both input fields are empty) toggler

Expanded toggler

Monitor type edit page
Default collapsed (when both input fields are empty) toggler

Expanded toggler

These are pretty self-explanatory I hope

To get the Group "phones" message, I used this title:
and message: