JavaScript Templates
This templating system IS NOT the same that Home Assistant implements. It is basically a JavaScript code block in which you can use certain client-side objects, variables and methods. To set a property as a JavaScript template block, include the code between three square brackets [[[ JavaScript code ]]]. If you don‘t use the square brackets, the property will be interpreted as a regular string.
Custom Sidebar uses Home Assistant Javascript Templates for the JavaScript templating system. To know all the objects, variables and methods available in the JavaScript templates, consult the proper section in the repository.
If the JavaScript code is used in an option, it will be taken as something that you want to return, but if you have a more complex logic, you can create your own variables and return the desired result at the end.
The entities used in the templates will be stored, so if the state of an stored entity changes, all the templates that use this entity will be reevaluated and rerendered.
JavaScript templates can make use of Reactive JavaScript Variables. If you use a reactive variable in some templates and you modify it in the javascript action of an on_click parameter of an item, all the templates in which the variable was used will be reevaluated in the device in which the action was performed.
On top of all the variables and methods provided by Home Assistant Javascript Templates, the next methods will be available in the templates:
The next methods depend on the locale that the user has configured in Home Assistant, so the result of these methods is not deterministic. For the examples, a specific locale has been used.
When you open Home Assistant and it is loading, it is possible that the locale data is not ready yet until the system finished to load all the resources. If you try to render a template using these methods at the beginning of this loading process, it is possible that the formatting wouldn't follow your language settings. This will be corrected if the template is reevaluated later, but to avoid any wrong formatting at the beginning, it is recommended to delay the formatting in the first rendering using a Promise or to force a re-rendering of the template using JavaScript reactive variables or any other technique that mitigates this issue.
formatDate
This method formats a date using the Home Assistant locale. It accepts a date, a string ISO 8601 representation of a date or a number representing the timestamp in milliseconds.
// The result of all this examples will be "December 14, 2025"
// Using a date string
formatDate('2025-12-14');
// Using an ISO 8601 date string
formatDate('2025-12-14T00:00:00');
// Using a timestamp number
formatDate(1765715953817);
// Using a date
formatDate(new Date(2025, 11, 14));
formatDateTime
This method formats a date with time using the Home Assistant locale. It accepts a date, a string ISO 8601 representation of a date or a number representing the timestamp in milliseconds.
// The result of all this examples will be "December 14, 2025 at 12:00 AM"
// Using an ISO 8601 date string
formatDateTime('2025-12-14T00:00:00');
// Using a timestamp number
formatDateTime(1765666800000);
// Using a date
formatDateTime(new Date(2025, 11, 14, 0, 0, 0));
formatTime
This method formats a time using the Home Assistant locale. It accepts a date, a string ISO 8601 representation of a date, a number representing the timestamp in milliseconds, or a string representation of a time in the format HH:MM or HH:MM:SS.
// The result of all this examples will be "12:00 AM"
// Using a time string
formatTime('00:00'); // It could also include seconds 00:00:00
// Using an ISO 8601 date string
formatTime('2025-12-14T00:00:00');
// Using a timestamp number
formatTime(1765666800000);
// Using a date
formatTime(new Date(2025, 11, 14, 0, 0, 0));
getRelativeTime
This method get the relative time of a date using the Home Assistant locale. It accepts a date, a string ISO 8601 representation of a date or a number representing the timestamp in milliseconds. This method also accepts a secondary optional boolean parameter to define if the result should be capitalized or not (by default it is false).
// The result of all this examples will be "in 2 weeks"
// Assuming that the current date is December 1st, 2025 at 12:00 AM
// Using an ISO 8601 date string
getRelativeTime('2025-12-14T00:00:00');
// Using a timestamp number
getRelativeTime(1765666800000);
// Using a date
getRelativeTime(new Date(2025, 11, 14, 0, 0, 0));
The next methods will be available in every JavaScript template, but they should not be used in the templates of regular options. They are intended to be used in the javascript action of an on_click property.
openAlertDialog
This method will open an alert dialog. It accepts only one parameter wich is an object with the next properties: the title and the text of the alert dialog and two optional properties with a confirmText (text of the confirm button) and a confirm action that will be executed when the confirm button is clicked.
- YAML
- JSON
order:
- new_item: true
item: 'admin'
icon: 'mdi:account-key'
on_click:
action: 'javascript'
code: |
if (user_is_admin) {
// Execute some code only for admins
} else {
openAlertDialog({
title: 'Error',
text: 'Only admin users can execute this',
confirmText: 'Close',
confirm: () => {
console.log('The close button was clicked');
}
});
}
{
"new_item": true,
"item": "admin",
"icon": "mdi:account-key",
"on_click": {
"action": "javascript",
"code": "if (user_is_admin) { // Execute some code only for admins } else { openAlertDialog({ title: 'Error', text: 'Only admin users can execute this', confirmText: 'Close', confirm: () => { console.log('The close button was clicked'); } }); }"
}
}
openConfirmDialog
This method will open a confirmation dialog that allow one to accept or decline what it states. It also accepts only one parameter which is an object with the same properties as the openAlertDialog method and on top of them it will also accept a dismissText property to indicate the text of the dismiss button, a destructive property to indicate if the confirmation dialog will execute a destructive action, and a cancel action that will be executed when the dismiss button is clicked.
- YAML
- JSON
order:
- new_item: true
item: 'execute'
icon: 'mdi:script-text-outline'
on_click:
action: 'javascript'
code: |
openConfirmDialog({
title: 'Execute the script',
text: 'Do you want to execute the script?',
confirm: () => {
// execute the script
},
cancel: () => {
// do not execute the script
}
});
{
"new_item": true,
"item": "execute",
"icon": "mdi:script-text-outline",
"on_click": {
"action": "javascript",
"code": "openConfirmDialog({ title: 'Execute the script', text: 'Do you want to execute the script?', confirm: () => { // execute the script }, cancel: () => { // do not execute the script } })"
}
}
openMoreInfoDialog
This method will open a more info dialog of the specified entity. It requires an entityId parameter which is the entity that will be open in the more info dialog.
- YAML
- JSON
order:
- new_item: true
item: 'Living-room lights'
icon: 'mdi:lightbulb-group'
on_click:
action: 'javascript'
code: |
openMoreInfoDialog('light.living_room');
{
"new_item": true,
"item": "Living-room lights",
"icon": "mdi:lightbulb-group",
"on_click": {
"action": "javascript",
"code": "openMoreInfoDialog('light.living_room');"
}
}
openRestartDialog
Take into account that even if every user can open the restart dialog, only admin users are authorized to restart Home Assistant.
This method will open the dialog to restart Home Assistant.
- YAML
- JSON
order:
- new_item: true
item: 'Restart'
icon: 'mdi:restart'
on_click:
action: 'javascript'
code: |
openRestartDialog();
{
"new_item": true,
"item": "Restart",
"icon": "mdi:restart",
"on_click": {
"action": "javascript",
"code": "openRestartDialog();"
}
}
checkConfig
This method can be executed only by admin users.
This method allows one to validate the Home Assistant configuration. It returns a promise which resolves in an object with a result property. The result property can have two values, valid or invalid. This object will also have two optional properties, errors and warnings that will be filled with the corresponding errors or warnings coming from the Home Assistant configuration check.
- YAML
- JSON
order:
- new_item: true
item: 'check config'
icon: 'mdi:check-circle-outline'
on_click:
action: 'javascript'
code: |
checkConfig()
.then((response) => {
if (response.result === 'valid') {
openAlertDialog({
title: 'Configuration valid',
text: response.warnings
? `The configuration is valid but with warnings: ${response.warnings}`
: 'The configuration is valid'
});
} else {
openAlertDialog({
title: 'Configuration with errors',
text: response.errors
});
}
});
{
"new_item": true,
"item": "check config",
"icon": "mdi:check-circle-outline",
"on_click": {
"action": "javascript",
"code": "checkConfig().then((response) => { if (response.result === 'valid') { openAlertDialog({ title: 'Configuration valid', text: response.warnings ? `The configuration is valid but with warnings: ${response.warnings}` : : 'The configuration is valid' }); } else { openAlertDialog({ title: 'Configuration with errors', text: response.errors }); } }"
}
}
renderTemplate
This method can be executed only by admin users.
This method accepts a Jinja template string as a parameter and it will return a promise which resolves in the result of the template.
- YAML
- JSON
order:
- new_item: true
item: 'date'
icon: 'mdi:clock-time-eight'
on_click:
action: 'javascript'
code: |
renderTemplate(
"The date is {{ as_timestamp(now()) | timestamp_custom('%Y-%m-%d') }}"
).then((result) => {
openAlertDialog({
title: 'Date of today',
text: result
});
});
{
"new_item": true,
"item": "date",
"icon": "mdi:clock-time-eight",
"on_click": {
"action": "javascript",
"code": "renderTemplate(\"The date is {{ as_timestamp(now()) | timestamp_custom('%Y-%m-%d') }}\").then((result) => { openAlertDialog({ title: 'Date of today', text: result }); });"
}
}
callService
Some services can be executed only by admin users, for example, restarting Home Assistant.
This method will call a Home Assistant service (renamed some time ago to actions). It allows one to call a service from a JavaScript template. This method needs three parameters, the first one is the domain, the second the type of service and the third an object with the data needed by the service.
- YAML
- JSON
order:
- new_item: true
item: 'lights'
icon: 'mdi:lightbulb-on'
on_click:
action: 'javascript'
code: |
callService(
'light',
'toggle',
{
entity_id: user_name === 'Miriam'
? 'light.miriam_room'
: 'light.my_room'
}
);
{
"new_item": true,
"item": "lights",
"icon": "mdi:lightbulb-on",
"on_click": {
"action": "javascript",
"code": "callService('light', 'toggle', { entity_id: user_name === 'Miriam' ? 'light.miriam_room' : 'light.my_room' });"
}
}
Complex Example
The next example will create the next things:
- Sets the title of the sidebar as "My Home" followed by the current time.
- Sets the background of the sidebar
redwhen the panel config is selected andgreenotherwise. - Adds the number of
HACSupdates as a notification in theHACSitem in the sidebar. In case that there are no updates, an empty string is returned and in these cases the notification will not be displayed. - Creates a new item that redirects to the
Home Assistantinfo page with a dynamic text with the word "Info" followed by the installed Supervisor version between parentheses and the Operating System version in the info text. - Creates a new item that when clicked opens the
Home Assistantrestart dialog, but if the user is not an admin, then it will open an alert with the title "Error", the text "Non-admin users cannot restart Home Assistant" and the text "Close" in the confirm button.
- YAML
- JSON
title: '[[[ "My Home " + formatTime(states("sensor.date_time_iso")) ]]]'
sidebar_background: |
[[[
return panel_url === '/config/dashboard'
? 'red'
: 'green';
]]]
order:
- item: hacs
notification: |
[[[
const outdatedHacsEntities = Object.values(entities.update).filter(
(entity) => entity.platform === 'hacs' && is_state(entity.entity_id, 'on')
);
return outdatedHacsEntities.length || '';
]]]
- new_item: true
item: info
name: |
[[[
return 'Info (' + state_attr('update.home_assistant_supervisor_update', 'latest_version') + ')';
]]]
info: |
[[[
return 'OS ' + state_attr('update.home_assistant_operating_system_update', 'latest_version');
]]]
href: '/config/info'
icon: 'mdi:information-outline'
- new_item: true
item: 'restart'
icon: 'mdi:restart'
on_click:
action: 'javascript'
code: |
if (user_is_admin) {
openRestartDialog();
} else {
openAlertDialog({
title: 'Error',
text: 'Non-admin users cannot restart Home Assistant',
confirmText: 'Close'
});
}
{
"title": "[[[ 'My Home ' + formatTime(states('sensor.date_time_iso')) ]]]",
"sidebar_background": "[[[ return panel_url === '/config/dashboard' ? 'red' : 'green' ]]]",
"order": [
{
"item": "hacs",
"notification": "[[[ return Object.values(entities.update).filter((entity) => entity.platform === 'hacs' && is_state(entity.entity_id, 'on')).length || '' ]]]"
},
{
"new_item": true,
"item": "info",
"icon": "mdi:information-outline",
"href": "/config/info",
"name": "[[[ return 'Info (' + state_attr('update.home_assistant_supervisor_update', 'latest_version') + ')'; ]]]",
"info": "[[[ return 'OS ' + state_attr('update.home_assistant_operating_system_update', 'latest_version'); ]]]"
},
{
"new_item": true,
"item": "restart",
"icon": "mdi:information-outline",
"on_click": {
"action": "javascript",
"code": "if (user_is_admin) { openRestartDialog(); } else { openAlertDialog({ title: 'Error', text: 'Non-admin users cannot restart Home Assistant', confirmText: 'Close' }); }"
}
}
]
}