mirror of
https://github.com/gethomepage/homepage.git
synced 2026-09-12 15:15:58 -07:00
Compare commits
406 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 233721cc90 | |||
| d294a25145 | |||
| 0ff9af4c3c | |||
| a6c753c8aa | |||
| 5d71c3aa65 | |||
| 1cc4608d72 | |||
| d65e5447e4 | |||
| d3256596d8 | |||
| 5bfe18b3e5 | |||
| 1ac5012c94 | |||
| 27b1c3f5f4 | |||
| bb765a6747 | |||
| aab4f5125b | |||
| 6d1e56bca0 | |||
| 4603e0ee57 | |||
| 9a983a5be1 | |||
| 23e66a265d | |||
| ce8f020b7b | |||
| 72b0e493d0 | |||
| ffb264cead | |||
| cd6e708af2 | |||
| 4e621aee8f | |||
| 93364b6a27 | |||
| 3dffc38462 | |||
| b2a52ff2a9 | |||
| 081b9ec8c3 | |||
| 977be863c7 | |||
| 77c9ac4a2c | |||
| b6b00aab86 | |||
| c3b4fc17c4 | |||
| 9b8e771268 | |||
| 44c1e8393e | |||
| 7ed1260f0d | |||
| 96f4777637 | |||
| f762135eb3 | |||
| d721bb661f | |||
| bf55e8acab | |||
| f82e0d9519 | |||
| 8322dd9016 | |||
| 10ade1d32f | |||
| a0f9fbf614 | |||
| 0c8fd6904e | |||
| b2b299d634 | |||
| b8672ddc9b | |||
| 03dd54ee2e | |||
| 92ec6ccefc | |||
| 463e94d933 | |||
| a7bab17f97 | |||
| 1accddf29a | |||
| 636d62106c | |||
| d048888d99 | |||
| 24804f39fc | |||
| 70f8c67d3c | |||
| 038f5c3b9f | |||
| ade4c733c7 | |||
| bdbd2e6ff0 | |||
| 5f4b0b4e33 | |||
| a56a05b553 | |||
| 11d1ceb755 | |||
| 6df1cfdeba | |||
| d64fbae776 | |||
| 5f7e5430c4 | |||
| 3cc3986ec3 | |||
| 5af0ab1686 | |||
| f0f5c3c15c | |||
| 2ed1da4411 | |||
| e1023466b1 | |||
| 9fe5ad62f1 | |||
| 173883000f | |||
| d6e7e7e790 | |||
| 24cb274e03 | |||
| af852e748a | |||
| 0ea5c3fb68 | |||
| 5ede96d6ce | |||
| c50bc8601d | |||
| 463bb4e306 | |||
| 4c3c4805c8 | |||
| a81ac47be9 | |||
| 36b909d4a4 | |||
| a7fe80a399 | |||
| 0b61b6c1b8 | |||
| 02989a4366 | |||
| bc6acf7fd1 | |||
| 7b552f5080 | |||
| 0f767d14bb | |||
| ff4eaa2cd9 | |||
| b37645b8d0 | |||
| 45af25d6ce | |||
| ea9fca02d3 | |||
| 3fb2dcbc47 | |||
| 96e3c7ac45 | |||
| f261879fcb | |||
| 495065a6fa | |||
| d18bdb011a | |||
| 2b65a0df04 | |||
| 311f232686 | |||
| 9893c5e846 | |||
| f70dcd6a03 | |||
| 657dc917b4 | |||
| de0c8558fb | |||
| daa1c27d9b | |||
| 6e850bfed8 | |||
| 02309211ac | |||
| 3d1be51ed4 | |||
| 75b01bec9a | |||
| fadb03ad27 | |||
| 6bdea294c1 | |||
| 11de525fc0 | |||
| ca67ba2e49 | |||
| c069cb3333 | |||
| 34be817eb2 | |||
| 0598a27d60 | |||
| be5ef3448e | |||
| a4e29bc7a7 | |||
| a7982bda06 | |||
| f7c12ad642 | |||
| a6639b04b9 | |||
| 6b3bff1f1d | |||
| 597059045f | |||
| b676424d98 | |||
| e87b62f3ac | |||
| 776f190aed | |||
| 71a524da89 | |||
| 9dea3a4d4f | |||
| adc042fa8a | |||
| f16878bca9 | |||
| 01b951f3ba | |||
| 94122ba078 | |||
| fb88da5a5a | |||
| de7e730283 | |||
| b5b502b433 | |||
| db9b2d0245 | |||
| 51d718a21a | |||
| 29e2502d74 | |||
| d529f81cb4 | |||
| 1645c1b8a1 | |||
| e3ca0adf11 | |||
| 614a87d768 | |||
| 862c5d9f38 | |||
| d3374dc461 | |||
| 795e2505ca | |||
| cb8421df0b | |||
| 152888d611 | |||
| ea527e4fb1 | |||
| 09bab7637e | |||
| 597f6ecf16 | |||
| fe0b214334 | |||
| cdc96438cd | |||
| ca7dfb56c8 | |||
| 95852d23c2 | |||
| 84231a1754 | |||
| f4f54cea60 | |||
| 06595ef107 | |||
| 91b9aa479a | |||
| 08cde2f597 | |||
| d62404f164 | |||
| 0ce175cda5 | |||
| 7f1de58e71 | |||
| f729290e96 | |||
| 4974cd96b6 | |||
| 4450a6e1d0 | |||
| ac11efc5c7 | |||
| 3c005d239e | |||
| c4e77d4b1d | |||
| 9d415ac45d | |||
| 8b9720ca93 | |||
| ad4ac465ae | |||
| 872a3600aa | |||
| 7d019185a3 | |||
| 99f1540d8c | |||
| 97e909ebf4 | |||
| 4d4fab391c | |||
| 1233b5e803 | |||
| 7e3fa97679 | |||
| 64c81615ec | |||
| 5c15466ac4 | |||
| 9cdb70527b | |||
| 062b1bcfbb | |||
| 4ebc24a1b4 | |||
| 79b63e4099 | |||
| c86a007ed0 | |||
| ca9506e485 | |||
| 1aec61811f | |||
| 6c945d6573 | |||
| 09893343a9 | |||
| 6b6090e303 | |||
| d3f1832f70 | |||
| f524531a13 | |||
| d6dde5fc41 | |||
| a08d79b5a9 | |||
| f6584fda41 | |||
| 1c504bc350 | |||
| 4349f30169 | |||
| 9076cfd7e7 | |||
| f9d920a8fb | |||
| a2697bfec0 | |||
| 82d4d15622 | |||
| b0bc9b6b2e | |||
| 3330954a44 | |||
| 392ff3833e | |||
| 03dfc964f1 | |||
| e7acd66c6e | |||
| 77e67b34c4 | |||
| a4ad00e27c | |||
| 0515f891ab | |||
| 08da8e66fd | |||
| 682e0cbc82 | |||
| f7ad322d4c | |||
| 2b31c23b9e | |||
| ae258b8276 | |||
| ff296be4a4 | |||
| 51ae55e25e | |||
| 31da9ee417 | |||
| be7a00d631 | |||
| 0d99a8766f | |||
| e66b58dc53 | |||
| 1b32cbbbfd | |||
| 681a8a828b | |||
| f8009a7067 | |||
| 1ed2f16cbf | |||
| ba2b3eeb9e | |||
| 45ca94eb6d | |||
| a07cc25441 | |||
| 0dcd25d5ad | |||
| cd34796b9d | |||
| 0d788e3d06 | |||
| ed1dafadde | |||
| 96ac9046b3 | |||
| 6d5f35f07e | |||
| c77dfa4c64 | |||
| 307d7f4b2d | |||
| fb9927ab0c | |||
| d13165699b | |||
| 65ff248ee7 | |||
| 87e5643892 | |||
| 8887281246 | |||
| 5b50e8ff81 | |||
| c36c6a9012 | |||
| cf990063b9 | |||
| 610f1bd974 | |||
| 4031178831 | |||
| b65c8399d8 | |||
| 6b63cfd491 | |||
| 196c51bf73 | |||
| 17c9b2631e | |||
| 1a21189643 | |||
| b6b428363c | |||
| e707fa46cf | |||
| 3d040362cb | |||
| 57b193b037 | |||
| 8a75c9b6e3 | |||
| 0dafc792f7 | |||
| afc0fe29ee | |||
| 817a9bbce5 | |||
| 3ef7031eb0 | |||
| 6faf32eae9 | |||
| 455e86571a | |||
| 7d1e0c087a | |||
| d48ef4c038 | |||
| 4a2eeaa8b9 | |||
| faa2e6bb36 | |||
| 438543d8cd | |||
| 5a350cc9ce | |||
| 529814cf03 | |||
| 9b5275a854 | |||
| e623196ac0 | |||
| 973b1f7aaf | |||
| 81a322cc99 | |||
| 36e82a8b90 | |||
| 1383e22acd | |||
| a756a01d63 | |||
| 937efc9f1b | |||
| fe6f32f072 | |||
| 226603770c | |||
| 2f48d21bfd | |||
| 4457baffa5 | |||
| 91d12c401c | |||
| 3f8da51aeb | |||
| 837717461f | |||
| effedc28ed | |||
| 76b477572e | |||
| 6c6660b91b | |||
| 6886040798 | |||
| 1fb4850bef | |||
| 06cf76d724 | |||
| 7aeda56af4 | |||
| 2058b7fcae | |||
| 1e06e93e47 | |||
| 8f756d4084 | |||
| 02089a35ee | |||
| f7a6b7dbf4 | |||
| 4028194830 | |||
| 4c04a7a45f | |||
| ce344a9db5 | |||
| 8e90ece498 | |||
| 151ad552ca | |||
| 251cb65e12 | |||
| 8ebd0d0b2e | |||
| c20f71738b | |||
| 78b73e8166 | |||
| 547ef0c4c5 | |||
| 11d148fff0 | |||
| eb61d69626 | |||
| 876304cda5 | |||
| 65dce6d387 | |||
| 7b60a60d4e | |||
| 8d37cad871 | |||
| cd25ae3258 | |||
| a27cdbc284 | |||
| e772ef0ad1 | |||
| 8cc00ae09a | |||
| f4efc71350 | |||
| b663e56174 | |||
| 5fe5a3869e | |||
| a9ec5aa1e7 | |||
| 44405b4aae | |||
| 842cec2fee | |||
| c6ad937619 | |||
| a6ab095ff9 | |||
| 9a085bcb17 | |||
| 6d7be1c7f2 | |||
| 25cd51cee9 | |||
| 495de204d1 | |||
| 8e5f4d55c9 | |||
| 184fd65c76 | |||
| 15817f9b27 | |||
| 79671ac30e | |||
| 1d5db612fd | |||
| d30016304b | |||
| f0fd125e37 | |||
| 9ed4b85d5a | |||
| f607d806d0 | |||
| c0ddb5f816 | |||
| fc563532e1 | |||
| 98248903c6 | |||
| 5870111d11 | |||
| bb23c25690 | |||
| 4084c8dafc | |||
| cb1dde1b79 | |||
| 1691711a52 | |||
| b5d8f6c01c | |||
| db86b5408a | |||
| 4be2c2868b | |||
| c6197a9f92 | |||
| dd861d7d1c | |||
| e65f8c46f9 | |||
| 082e1316c1 | |||
| a4b5e72d82 | |||
| 0e79501ddc | |||
| 4814ee48ef | |||
| 5b7a36666c | |||
| 75b27a644b | |||
| b3bde11e3a | |||
| 8fdf2b074c | |||
| 20c4400a9b | |||
| 1a7e57bfb6 | |||
| 07f70a79be | |||
| a2e3aa7085 | |||
| 085d91b3f7 | |||
| 9417929c99 | |||
| 6bc5f0f499 | |||
| fa2efb1ac9 | |||
| 8c4e73e122 | |||
| 0c000c1ecd | |||
| bbb013e0ce | |||
| d581d70d1a | |||
| 612d05fd4d | |||
| 0d6ecae51b | |||
| c48cf71d59 | |||
| 7f630fd77f | |||
| aa942dbd73 | |||
| 7426a12cdf | |||
| cbf2e1a509 | |||
| d0165326a6 | |||
| dba3a1f893 | |||
| f5ecd6d787 | |||
| 1d990ef7c7 | |||
| 767e7c58b4 | |||
| c393982e84 | |||
| 927b943fa4 | |||
| 50f6d5f0e7 | |||
| 0482bf7b17 | |||
| e215e7d70e | |||
| 0a44a2dade | |||
| 0fe76b5af8 | |||
| e51db24418 | |||
| 1a1039194c | |||
| 00bb1a3f37 | |||
| 73aa2018a8 | |||
| 8ce9e57ed8 | |||
| 6e16adc460 | |||
| 352c54ecc4 | |||
| a64c83209a | |||
| 1147fc858f | |||
| fcfb9c2237 | |||
| 34bffe980a | |||
| 5759596a37 | |||
| 30abf4e422 | |||
| 0e96778740 | |||
| fc99a0d1db | |||
| 417d69d39d | |||
| 8f4013012a | |||
| 0c6c40dae7 | |||
| 1a46baae69 | |||
| 0fa3d7e57b | |||
| be7e1115cc |
@@ -0,0 +1,21 @@
|
|||||||
|
codecov:
|
||||||
|
require_ci_to_pass: true
|
||||||
|
|
||||||
|
coverage:
|
||||||
|
precision: 2
|
||||||
|
round: down
|
||||||
|
range: "0...100"
|
||||||
|
status:
|
||||||
|
project:
|
||||||
|
default:
|
||||||
|
target: 100%
|
||||||
|
threshold: 15%
|
||||||
|
patch:
|
||||||
|
default:
|
||||||
|
target: 100%
|
||||||
|
threshold: 10%
|
||||||
|
|
||||||
|
comment:
|
||||||
|
layout: "reach,diff,flags,files"
|
||||||
|
behavior: default
|
||||||
|
require_changes: false
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
{
|
|
||||||
"extends": [
|
|
||||||
"next/core-web-vitals",
|
|
||||||
"prettier",
|
|
||||||
"plugin:react-hooks/recommended"
|
|
||||||
],
|
|
||||||
"plugins": ["prettier"],
|
|
||||||
"rules": {
|
|
||||||
"import/no-cycle": [
|
|
||||||
"error",
|
|
||||||
{
|
|
||||||
"maxDepth": 1
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"import/order": [
|
|
||||||
"error",
|
|
||||||
{
|
|
||||||
"newlines-between": "always"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"no-else-return": [
|
|
||||||
"error",
|
|
||||||
{
|
|
||||||
"allowElseIf": true
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"settings": {
|
|
||||||
"import/resolver": {
|
|
||||||
"node": {
|
|
||||||
"paths": ["src"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"parserOptions": {
|
|
||||||
"ecmaVersion": 6,
|
|
||||||
"sourceType": "module",
|
|
||||||
"ecmaFeatures": {
|
|
||||||
"modules": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,10 @@
|
|||||||
title: "[Feature Request] "
|
title: "[Feature Request] "
|
||||||
labels: ["enhancement"]
|
labels: ["enhancement"]
|
||||||
body:
|
body:
|
||||||
|
- type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |
|
||||||
|
#### ⚠️ Don't forget to search [existing issues](https://github.com/gethomepage/homepage/search?q=&type=issues) and [discussions](https://github.com/gethomepage/homepage/search?q=&type=discussions) (including closed ones!).
|
||||||
- type: textarea
|
- type: textarea
|
||||||
id: description
|
id: description
|
||||||
attributes:
|
attributes:
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ body:
|
|||||||
id: troubleshooting
|
id: troubleshooting
|
||||||
attributes:
|
attributes:
|
||||||
label: Troubleshooting
|
label: Troubleshooting
|
||||||
description: Please include output from your [troubleshooting steps](https://gethomepage.dev/more/troubleshooting/#service-widget-errors), if relevant.
|
description: Please include output from your [troubleshooting steps](https://gethomepage.dev/troubleshooting/#service-widget-errors), if relevant.
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
- type: markdown
|
- type: markdown
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ body:
|
|||||||
options:
|
options:
|
||||||
- label: I confirm this was discussed, and the maintainers asked that I open an issue.
|
- label: I confirm this was discussed, and the maintainers asked that I open an issue.
|
||||||
required: true
|
required: true
|
||||||
- label: I am aware that if I create this issue without a discussion, it will be removed without a response.
|
- label: I am aware that if I create this issue without a discussion, it will be closed without a response.
|
||||||
required: true
|
required: true
|
||||||
- type: input
|
- type: input
|
||||||
id: discussion
|
id: discussion
|
||||||
|
|||||||
@@ -35,6 +35,8 @@ What type of change does your PR introduce to Homepage?
|
|||||||
## Checklist:
|
## Checklist:
|
||||||
|
|
||||||
- [ ] If applicable, I have added corresponding documentation changes.
|
- [ ] If applicable, I have added corresponding documentation changes.
|
||||||
- [ ] If applicable, I have reviewed the [feature / enhancement](https://gethomepage.dev/more/development/#new-feature-guidelines) and / or [service widget guidelines](https://gethomepage.dev/more/development/#service-widget-guidelines).
|
- [ ] If applicable, I have added or updated tests for new features and bug fixes (see [testing](https://gethomepage.dev/widgets/authoring/getting-started/#testing)).
|
||||||
- [ ] I have checked that all code style checks pass using [pre-commit hooks](https://gethomepage.dev/more/development/#code-formatting-with-pre-commit-hooks) and [linting checks](https://gethomepage.dev/more/development/#code-linting).
|
- [ ] If applicable, I have reviewed the [feature / enhancement](https://gethomepage.dev/widgets/authoring/getting-started/#new-feature-guidelines) and / or [service widget guidelines](https://gethomepage.dev/widgets/authoring/getting-started/#service-widget-guidelines).
|
||||||
|
- [ ] I have checked that all code style checks pass using [pre-commit hooks](https://gethomepage.dev/widgets/authoring/getting-started/#code-formatting-with-pre-commit-hooks) and [linting checks](https://gethomepage.dev/widgets/authoring/getting-started/#code-linting).
|
||||||
- [ ] If applicable, I have tested my code for new features & regressions on both mobile & desktop devices, using the latest version of major browsers.
|
- [ ] If applicable, I have tested my code for new features & regressions on both mobile & desktop devices, using the latest version of major browsers.
|
||||||
|
- [ ] In the description above I have disclosed the use of AI tools in the coding of this PR.
|
||||||
|
|||||||
@@ -8,8 +8,12 @@ updates:
|
|||||||
- package-ecosystem: "github-actions"
|
- package-ecosystem: "github-actions"
|
||||||
directory: "/"
|
directory: "/"
|
||||||
schedule:
|
schedule:
|
||||||
interval: "daily"
|
interval: "weekly"
|
||||||
|
cooldown:
|
||||||
|
default-days: 7
|
||||||
- package-ecosystem: "npm"
|
- package-ecosystem: "npm"
|
||||||
directory: "/"
|
directory: "/"
|
||||||
schedule:
|
schedule:
|
||||||
interval: "monthly"
|
interval: "monthly"
|
||||||
|
cooldown:
|
||||||
|
default-days: 7
|
||||||
|
|||||||
@@ -0,0 +1,93 @@
|
|||||||
|
name-template: 'v$RESOLVED_VERSION'
|
||||||
|
tag-template: 'v$RESOLVED_VERSION'
|
||||||
|
change-template: '- $TITLE (#$NUMBER) @$AUTHOR'
|
||||||
|
change-title-escapes: '\\<*_&'
|
||||||
|
|
||||||
|
version-resolver:
|
||||||
|
major:
|
||||||
|
labels:
|
||||||
|
- 'major'
|
||||||
|
- 'breaking-change'
|
||||||
|
minor:
|
||||||
|
labels:
|
||||||
|
- 'enhancement'
|
||||||
|
- 'feature'
|
||||||
|
patch:
|
||||||
|
labels:
|
||||||
|
- 'bug'
|
||||||
|
- 'fix'
|
||||||
|
- 'dependencies'
|
||||||
|
- 'translation'
|
||||||
|
- 'documentation'
|
||||||
|
default: patch
|
||||||
|
|
||||||
|
categories:
|
||||||
|
- title: '⚠️ Breaking Changes'
|
||||||
|
labels:
|
||||||
|
- 'major'
|
||||||
|
- 'breaking-change'
|
||||||
|
- title: '🚀 Features'
|
||||||
|
labels:
|
||||||
|
- 'enhancement'
|
||||||
|
- 'feature'
|
||||||
|
- title: '🐛 Fixes'
|
||||||
|
labels:
|
||||||
|
- 'bug'
|
||||||
|
- 'fix'
|
||||||
|
- title: '🧰 Maintenance'
|
||||||
|
labels:
|
||||||
|
- 'dependencies'
|
||||||
|
- 'ci'
|
||||||
|
- 'chore'
|
||||||
|
- title: '🌐 Translations'
|
||||||
|
labels:
|
||||||
|
- 'translation'
|
||||||
|
- title: '📚 Documentation'
|
||||||
|
labels:
|
||||||
|
- 'documentation'
|
||||||
|
|
||||||
|
autolabeler:
|
||||||
|
- label: 'bug'
|
||||||
|
title:
|
||||||
|
- '/^fix(\(.+\))?:/i'
|
||||||
|
body:
|
||||||
|
- '/- \[[xX]\] Bug fix \(non-breaking change which fixes an issue\)/'
|
||||||
|
|
||||||
|
- label: 'enhancement'
|
||||||
|
title:
|
||||||
|
- '/^(feature|enhancement)(\(.+\))?:/i'
|
||||||
|
body:
|
||||||
|
- '/- \[[xX]\] New service widget/'
|
||||||
|
- '/- \[[xX]\] New feature or enhancement \(non-breaking change which adds functionality\)/'
|
||||||
|
|
||||||
|
- label: 'documentation'
|
||||||
|
title:
|
||||||
|
- '/^(documentation|docs)(\(.+\))?:/i'
|
||||||
|
body:
|
||||||
|
- '/- \[[xX]\] Documentation only/'
|
||||||
|
|
||||||
|
- label: 'chore'
|
||||||
|
body:
|
||||||
|
- '/- \[[xX]\] Other \(please explain\)/'
|
||||||
|
|
||||||
|
- label: 'ci'
|
||||||
|
branch:
|
||||||
|
- '/^(ci|workflow|actions)\//'
|
||||||
|
title:
|
||||||
|
- '/^(ci|workflow|actions)(\(.+\))?:/i'
|
||||||
|
|
||||||
|
- label: 'dependencies'
|
||||||
|
files:
|
||||||
|
- 'package.json'
|
||||||
|
- 'pnpm-lock.yaml'
|
||||||
|
- 'pyproject.toml'
|
||||||
|
- 'uv.lock'
|
||||||
|
|
||||||
|
- label: 'translation'
|
||||||
|
files:
|
||||||
|
- 'public/locales/**'
|
||||||
|
|
||||||
|
template: |
|
||||||
|
## What's Changed
|
||||||
|
|
||||||
|
$CHANGES
|
||||||
@@ -17,14 +17,15 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
||||||
- name: crowdin action
|
- name: crowdin action
|
||||||
uses: crowdin/github-action@v2
|
uses: crowdin/github-action@8868a33591d21088edfc398968173a3b98d51706 # v2
|
||||||
with:
|
with:
|
||||||
upload_translations: false
|
upload_translations: false
|
||||||
download_translations: true
|
download_translations: true
|
||||||
crowdin_branch_name: dev
|
crowdin_branch_name: dev
|
||||||
localization_branch_name: l10n_dev
|
localization_branch_name: l10n_dev
|
||||||
|
pull_request_labels: translation
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }}
|
CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }}
|
||||||
|
|||||||
@@ -7,60 +7,23 @@ on:
|
|||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
- feature/**
|
- feature/**
|
||||||
|
- fix/**
|
||||||
- dev
|
- dev
|
||||||
tags: [ 'v*.*.*' ]
|
tags: [ 'v*.*.*' ]
|
||||||
paths-ignore:
|
|
||||||
- 'docs/**'
|
|
||||||
- 'mkdocs.yml'
|
|
||||||
pull_request:
|
pull_request:
|
||||||
branches: [ "dev" ]
|
branches: [ "dev" ]
|
||||||
paths-ignore:
|
|
||||||
- 'docs/**'
|
|
||||||
- 'mkdocs.yml'
|
|
||||||
merge_group:
|
merge_group:
|
||||||
|
|
||||||
env:
|
env:
|
||||||
IMAGE_NAME: ${{ github.repository }}
|
IMAGE_NAME: ${{ github.repository }}
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
pre-commit:
|
|
||||||
name: Linting Checks
|
|
||||||
runs-on: ubuntu-22.04
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Install python
|
|
||||||
uses: actions/setup-python@v5
|
|
||||||
with:
|
|
||||||
python-version: 3.x
|
|
||||||
|
|
||||||
- name: Check files
|
|
||||||
uses: pre-commit/action@v3.0.1
|
|
||||||
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 10
|
|
||||||
run_install: false
|
|
||||||
|
|
||||||
- name: Setup Node.js
|
|
||||||
uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: 'pnpm'
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install
|
|
||||||
|
|
||||||
- name: Lint frontend
|
|
||||||
run: pnpm run lint
|
|
||||||
|
|
||||||
build:
|
build:
|
||||||
name: Docker Build & Push
|
name: Docker Build & Push
|
||||||
if: github.repository == 'gethomepage/homepage'
|
if: github.repository == 'gethomepage/homepage'
|
||||||
runs-on: self-hosted
|
runs-on: ubuntu-22.04
|
||||||
needs: [ pre-commit ]
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
packages: write
|
packages: write
|
||||||
@@ -68,11 +31,11 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
||||||
|
|
||||||
- name: Extract Docker metadata
|
- name: Extract Docker metadata
|
||||||
id: meta
|
id: meta
|
||||||
uses: docker/metadata-action@v5
|
uses: docker/metadata-action@030e881283bb7a6894de51c315a6bfe6a94e05cf # v6
|
||||||
with:
|
with:
|
||||||
images: |
|
images: |
|
||||||
${{ env.IMAGE_NAME }}
|
${{ env.IMAGE_NAME }}
|
||||||
@@ -90,7 +53,7 @@ jobs:
|
|||||||
latest=auto
|
latest=auto
|
||||||
|
|
||||||
- name: Next.js build cache
|
- name: Next.js build cache
|
||||||
uses: actions/cache@v4
|
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5
|
||||||
with:
|
with:
|
||||||
path: .next/cache
|
path: .next/cache
|
||||||
key: nextjs-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}-${{ hashFiles('**/*.js', '**/*.jsx') }}
|
key: nextjs-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}-${{ hashFiles('**/*.js', '**/*.jsx') }}
|
||||||
@@ -98,15 +61,15 @@ jobs:
|
|||||||
nextjs-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}
|
nextjs-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}
|
||||||
|
|
||||||
- name: Install pnpm
|
- name: Install pnpm
|
||||||
uses: pnpm/action-setup@v4
|
uses: pnpm/action-setup@26f6d4f2c533a43e6b5da0b4a5dd983f98f7b49a # v6.0.4
|
||||||
with:
|
with:
|
||||||
version: 10
|
version: 10
|
||||||
run_install: false
|
run_install: false
|
||||||
|
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
|
||||||
with:
|
with:
|
||||||
node-version: 20
|
node-version: 24
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
@@ -121,7 +84,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Log into registry ${{ env.REGISTRY }}
|
- name: Log into registry ${{ env.REGISTRY }}
|
||||||
if: github.event_name != 'pull_request'
|
if: github.event_name != 'pull_request'
|
||||||
uses: docker/login-action@v3
|
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4
|
||||||
with:
|
with:
|
||||||
registry: ghcr.io
|
registry: ghcr.io
|
||||||
username: ${{ github.actor }}
|
username: ${{ github.actor }}
|
||||||
@@ -129,20 +92,20 @@ jobs:
|
|||||||
|
|
||||||
- name: Login to Docker Hub
|
- name: Login to Docker Hub
|
||||||
if: github.event_name != 'pull_request'
|
if: github.event_name != 'pull_request'
|
||||||
uses: docker/login-action@v3
|
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4
|
||||||
with:
|
with:
|
||||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Setup QEMU
|
- name: Setup QEMU
|
||||||
uses: docker/setup-qemu-action@v3.6.0
|
uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4.0.0
|
||||||
|
|
||||||
- name: Setup Docker buildx
|
- name: Setup Docker buildx
|
||||||
uses: docker/setup-buildx-action@v3
|
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4
|
||||||
|
|
||||||
- name: Build and push Docker image
|
- name: Build and push Docker image
|
||||||
id: build-and-push
|
id: build-and-push
|
||||||
uses: docker/build-push-action@v6
|
uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
push: ${{ github.event_name != 'pull_request' }}
|
push: ${{ github.event_name != 'pull_request' }}
|
||||||
|
|||||||
@@ -4,81 +4,51 @@ on:
|
|||||||
push:
|
push:
|
||||||
tags: ["v*.*.*"]
|
tags: ["v*.*.*"]
|
||||||
branches: ["main"]
|
branches: ["main"]
|
||||||
paths:
|
|
||||||
- "docs/**"
|
|
||||||
- "mkdocs.yml"
|
|
||||||
pull_request:
|
pull_request:
|
||||||
paths:
|
|
||||||
- "docs/**"
|
|
||||||
- "mkdocs.yml"
|
|
||||||
merge_group:
|
merge_group:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: read
|
||||||
|
pages: write
|
||||||
|
id-token: write
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
pre-commit:
|
|
||||||
name: Linting Checks
|
|
||||||
runs-on: ubuntu-22.04
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
- name: Install python
|
|
||||||
uses: actions/setup-python@v5
|
|
||||||
with:
|
|
||||||
python-version: 3.x
|
|
||||||
- name: Check files
|
|
||||||
uses: pre-commit/action@v3.0.1
|
|
||||||
|
|
||||||
test:
|
test:
|
||||||
name: Test Build
|
name: Test Build Docs
|
||||||
if: github.repository == 'gethomepage/homepage' && github.event_name == 'pull_request'
|
if: github.repository == 'gethomepage/homepage' && github.event_name == 'pull_request'
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs:
|
|
||||||
- pre-commit
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
||||||
- uses: actions/setup-python@v5
|
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6
|
||||||
with:
|
with:
|
||||||
python-version: 3.x
|
python-version-file: ".python-version"
|
||||||
- run: echo "cache_id=$(date --utc '+%V')" >> $GITHUB_ENV
|
- name: Install uv
|
||||||
- uses: actions/cache@v4
|
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
|
||||||
with:
|
|
||||||
key: mkdocs-material-${{ env.cache_id }}
|
|
||||||
path: .cache
|
|
||||||
restore-keys: |
|
|
||||||
mkdocs-material-
|
|
||||||
- run: sudo apt-get install pngquant
|
- run: sudo apt-get install pngquant
|
||||||
- run: pip install mkdocs-material mkdocs-redirects "mkdocs-material[imaging]"
|
|
||||||
- name: Test Docs Build
|
- name: Test Docs Build
|
||||||
run: MKINSIDERS=false mkdocs build
|
run: uv run --frozen zensical build --clean
|
||||||
deploy:
|
deploy:
|
||||||
name: Build & Deploy
|
name: Build & Deploy Docs
|
||||||
if: github.repository == 'gethomepage/homepage' && github.event_name != 'pull_request' && github.ref == 'refs/heads/main'
|
if: github.repository == 'gethomepage/homepage' && github.event_name != 'pull_request' && github.ref == 'refs/heads/main'
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs:
|
environment:
|
||||||
- pre-commit
|
name: github-pages
|
||||||
|
url: ${{ steps.deployment.outputs.page_url }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/configure-pages@45bfe0192ca1faeb007ade9deae92b16b8254a0d # v6.0.0
|
||||||
- name: Configure Git Credentials
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
||||||
run: |
|
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6
|
||||||
git config user.name github-actions[bot]
|
|
||||||
git config user.email 41898282+github-actions[bot]@users.noreply.github.com
|
|
||||||
- uses: actions/setup-python@v5
|
|
||||||
with:
|
with:
|
||||||
python-version: 3.x
|
python-version-file: ".python-version"
|
||||||
- run: echo "cache_id=${{github.sha}}" >> $GITHUB_ENV
|
- name: Install uv
|
||||||
- uses: actions/cache@v4
|
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
|
||||||
with:
|
|
||||||
key: mkdocs-material-${{ env.cache_id }}
|
|
||||||
path: .cache
|
|
||||||
restore-keys: |
|
|
||||||
mkdocs-material-
|
|
||||||
- run: sudo apt-get install pngquant
|
- run: sudo apt-get install pngquant
|
||||||
- run: pip install git+https://${GH_TOKEN}@github.com/benphelps/mkdocs-material-insiders.git
|
- name: Build Docs
|
||||||
- run: pip install mkdocs-redirects "mkdocs-material[imaging]"
|
run: uv run --frozen zensical build --clean
|
||||||
- name: Docs Deploy
|
- uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5.0.0
|
||||||
run: MKINSIDERS=true mkdocs gh-deploy --force
|
with:
|
||||||
env:
|
path: site
|
||||||
GH_TOKEN: ${{ secrets.GH_TOKEN }}
|
- uses: actions/deploy-pages@cd2ce8fcbc39b97be8ca5fce6e763baed58fa128 # v5.0.0
|
||||||
|
id: deployment
|
||||||
|
|||||||
@@ -0,0 +1,43 @@
|
|||||||
|
name: Issue Triage
|
||||||
|
|
||||||
|
on:
|
||||||
|
issues:
|
||||||
|
types: [labeled]
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
issues: write
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
close-needs-discussion:
|
||||||
|
name: Issues Need Discussion
|
||||||
|
if: github.event.label.name == 'needs-discussion'
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||||||
|
with:
|
||||||
|
script: |
|
||||||
|
const issueNumber = context.payload.issue.number;
|
||||||
|
const owner = context.repo.owner;
|
||||||
|
const repo = context.repo.repo;
|
||||||
|
|
||||||
|
await github.rest.issues.createComment({
|
||||||
|
owner,
|
||||||
|
repo,
|
||||||
|
issue_number: issueNumber,
|
||||||
|
body: 'This issue is being closed because it was opened before a maintainer asked for an issue to be created. Please start with a discussion and follow the issue template; only open an issue when a maintainer asks you to do so.',
|
||||||
|
});
|
||||||
|
|
||||||
|
await github.rest.issues.update({
|
||||||
|
owner,
|
||||||
|
repo,
|
||||||
|
issue_number: issueNumber,
|
||||||
|
state: 'closed',
|
||||||
|
state_reason: 'not_planned',
|
||||||
|
});
|
||||||
|
|
||||||
|
await github.rest.issues.lock({
|
||||||
|
owner,
|
||||||
|
repo,
|
||||||
|
issue_number: issueNumber,
|
||||||
|
lock_reason: 'off-topic',
|
||||||
|
});
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
name: Lint
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
push:
|
||||||
|
workflow_dispatch:
|
||||||
|
merge_group:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
lint:
|
||||||
|
name: Linting Checks
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
||||||
|
|
||||||
|
- name: Install python
|
||||||
|
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6
|
||||||
|
with:
|
||||||
|
python-version: 3.x
|
||||||
|
|
||||||
|
- name: Check files
|
||||||
|
uses: pre-commit/action@2c7b3805fd2a0fd8c1884dcaebf91fc102a13ecd # v3.0.1
|
||||||
|
|
||||||
|
- name: Install pnpm
|
||||||
|
uses: pnpm/action-setup@26f6d4f2c533a43e6b5da0b4a5dd983f98f7b49a # v6.0.4
|
||||||
|
with:
|
||||||
|
version: 10
|
||||||
|
run_install: false
|
||||||
|
|
||||||
|
- name: Setup Node.js
|
||||||
|
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
|
||||||
|
with:
|
||||||
|
node-version: 24
|
||||||
|
cache: 'pnpm'
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install
|
||||||
|
|
||||||
|
- name: Lint frontend
|
||||||
|
run: pnpm run lint
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
name: PR Quality
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
issues: read
|
||||||
|
pull-requests: write
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request_target:
|
||||||
|
types: [opened, reopened]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
anti-slop:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: peakoss/anti-slop@57858eead489d08b255fab2af45a506c2ca6eab2 # v0
|
||||||
|
with:
|
||||||
|
max-failures: 4
|
||||||
@@ -15,4 +15,4 @@ jobs:
|
|||||||
action:
|
action:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: dessant/reaction-comments@v4
|
- uses: dessant/reaction-comments@e86d247c12bd5c043eec379a1a4453f20cadf913 # v4
|
||||||
|
|||||||
@@ -0,0 +1,54 @@
|
|||||||
|
name: Release Drafter
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- dev
|
||||||
|
pull_request_target:
|
||||||
|
types: [opened, reopened, synchronize]
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
version:
|
||||||
|
description: "Optional explicit version override (for example: 2.0.0)"
|
||||||
|
required: false
|
||||||
|
type: string
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
update_release_draft:
|
||||||
|
name: Update Release Draft
|
||||||
|
if: github.event_name == 'push' || github.event_name == 'workflow_dispatch'
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
pull-requests: read
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- if: github.event_name == 'workflow_dispatch' && github.event.inputs.version != ''
|
||||||
|
uses: release-drafter/release-drafter@563bf132657a13ded0b01fcb723c5a58cdd824e2 # v7
|
||||||
|
with:
|
||||||
|
config-name: release-drafter.yml
|
||||||
|
version: ${{ github.event.inputs.version }}
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
- if: github.event_name != 'workflow_dispatch' || github.event.inputs.version == ''
|
||||||
|
uses: release-drafter/release-drafter@563bf132657a13ded0b01fcb723c5a58cdd824e2 # v7
|
||||||
|
with:
|
||||||
|
config-name: release-drafter.yml
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
auto_label:
|
||||||
|
name: Auto Label PR
|
||||||
|
if: github.event_name == 'pull_request_target'
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
pull-requests: write
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: release-drafter/release-drafter/autolabeler@563bf132657a13ded0b01fcb723c5a58cdd824e2
|
||||||
|
with:
|
||||||
|
config-name: release-drafter.yml
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
@@ -18,7 +18,7 @@ jobs:
|
|||||||
name: 'Stale'
|
name: 'Stale'
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/stale@v9
|
- uses: actions/stale@b5d41d4e1d5dceea10e7104786b73624c18a190f # v10
|
||||||
with:
|
with:
|
||||||
days-before-stale: 7
|
days-before-stale: 7
|
||||||
days-before-close: 14
|
days-before-close: 14
|
||||||
@@ -32,7 +32,7 @@ jobs:
|
|||||||
name: 'Lock Old Threads'
|
name: 'Lock Old Threads'
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: dessant/lock-threads@v5
|
- uses: dessant/lock-threads@7266a7ce5c1df01b1c6db85bf8cd86c737dadbe7 # v6
|
||||||
with:
|
with:
|
||||||
issue-inactive-days: '30'
|
issue-inactive-days: '30'
|
||||||
pr-inactive-days: '30'
|
pr-inactive-days: '30'
|
||||||
@@ -57,7 +57,7 @@ jobs:
|
|||||||
name: 'Close Answered Discussions'
|
name: 'Close Answered Discussions'
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/github-script@v7
|
- uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||||||
with:
|
with:
|
||||||
script: |
|
script: |
|
||||||
function sleep(ms) {
|
function sleep(ms) {
|
||||||
@@ -113,7 +113,7 @@ jobs:
|
|||||||
name: 'Close Outdated Discussions'
|
name: 'Close Outdated Discussions'
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/github-script@v7
|
- uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||||||
with:
|
with:
|
||||||
script: |
|
script: |
|
||||||
function sleep(ms) {
|
function sleep(ms) {
|
||||||
@@ -204,7 +204,7 @@ jobs:
|
|||||||
name: 'Close Unsupported Feature Requests'
|
name: 'Close Unsupported Feature Requests'
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/github-script@v7
|
- uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||||||
with:
|
with:
|
||||||
script: |
|
script: |
|
||||||
function sleep(ms) {
|
function sleep(ms) {
|
||||||
@@ -212,9 +212,9 @@ jobs:
|
|||||||
}
|
}
|
||||||
|
|
||||||
const CUTOFF_1_DAYS = 180;
|
const CUTOFF_1_DAYS = 180;
|
||||||
const CUTOFF_1_COUNT = 10;
|
const CUTOFF_1_COUNT = 20;
|
||||||
const CUTOFF_2_DAYS = 365;
|
const CUTOFF_2_DAYS = 365;
|
||||||
const CUTOFF_2_COUNT = 20;
|
const CUTOFF_2_COUNT = 40;
|
||||||
|
|
||||||
const cutoff1Date = new Date();
|
const cutoff1Date = new Date();
|
||||||
cutoff1Date.setDate(cutoff1Date.getDate() - CUTOFF_1_DAYS);
|
cutoff1Date.setDate(cutoff1Date.getDate() - CUTOFF_1_DAYS);
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
name: Tests
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
push:
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
vitest:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
shard: [1, 2, 3, 4]
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
||||||
|
|
||||||
|
- uses: pnpm/action-setup@26f6d4f2c533a43e6b5da0b4a5dd983f98f7b49a # v6.0.4
|
||||||
|
with:
|
||||||
|
version: 9
|
||||||
|
|
||||||
|
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
|
||||||
|
with:
|
||||||
|
node-version: 20
|
||||||
|
cache: pnpm
|
||||||
|
|
||||||
|
- run: pnpm install --frozen-lockfile
|
||||||
|
# Run Vitest directly so `--shard` is parsed as an option
|
||||||
|
- run: pnpm -s exec vitest run --coverage --shard ${{ matrix.shard }}/4 --pool forks
|
||||||
|
- name: Upload coverage reports to Codecov
|
||||||
|
uses: codecov/codecov-action@57e3a136b779b570ffcdbf80b3bdc90e7fab3de2 # v6.0.0
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.CODECOV_TOKEN }}
|
||||||
|
files: ./coverage/lcov.info
|
||||||
|
flags: vitest,shard-${{ matrix.shard }}
|
||||||
|
name: vitest-shard-${{ matrix.shard }}
|
||||||
|
fail_ci_if_error: true
|
||||||
+1
-1
@@ -46,7 +46,7 @@ next-env.d.ts
|
|||||||
# IDEs
|
# IDEs
|
||||||
/.idea/
|
/.idea/
|
||||||
|
|
||||||
# MkDocs documentation
|
# Zensical documentation
|
||||||
site*/
|
site*/
|
||||||
.cache/
|
.cache/
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
3.13
|
||||||
Vendored
+23
-10
@@ -1,19 +1,32 @@
|
|||||||
{
|
{
|
||||||
// Use IntelliSense to learn about possible attributes.
|
|
||||||
// Hover to view descriptions of existing attributes.
|
|
||||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
|
||||||
"version": "0.2.0",
|
|
||||||
"configurations": [
|
"configurations": [
|
||||||
{
|
{
|
||||||
"name": "Next.js: debug full stack",
|
"name": "Debug homepage",
|
||||||
"type": "node",
|
"type": "node",
|
||||||
|
"preLaunchTask": "pnpm install",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"runtimeExecutable": "${workspaceFolder}/node_modules/.bin/next",
|
"runtimeExecutable": "pnpm",
|
||||||
"serverReadyAction": {
|
"runtimeArgs": ["run", "dev"],
|
||||||
"pattern": "started server on .+, url: (https?://.+)",
|
"env": {
|
||||||
"uriFormat": "%s",
|
"LOG_LEVEL": "debug"
|
||||||
"action": "debugWithChrome"
|
},
|
||||||
|
"skipFiles": ["<node_internals>/**"],
|
||||||
|
"console": "integratedTerminal",
|
||||||
|
"serverReadyAction":{
|
||||||
|
"pattern": ".*http://localhost:3000.*",
|
||||||
|
"action": "startDebugging",
|
||||||
|
"name": "Launch Chromium",
|
||||||
|
"killOnServerStop": true,
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Launch Chromium",
|
||||||
|
"type": "chrome",
|
||||||
|
"request": "launch",
|
||||||
|
"url": "http://localhost:3000",
|
||||||
|
"urlFilter": "http://localhost:3000",
|
||||||
|
"webRoot": "${workspaceFolder}",
|
||||||
|
"trace": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+21
@@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"version": "2.0.0",
|
||||||
|
"tasks": [
|
||||||
|
{
|
||||||
|
"type": "shell",
|
||||||
|
"label": "pnpm install",
|
||||||
|
"command": "pnpm install",
|
||||||
|
"group": {
|
||||||
|
"kind": "build",
|
||||||
|
"isDefault": true
|
||||||
|
},
|
||||||
|
"presentation": {
|
||||||
|
"clear": true,
|
||||||
|
"panel": "shared",
|
||||||
|
"showReuseMessage": false
|
||||||
|
},
|
||||||
|
"problemMatcher": []
|
||||||
|
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
+3
-3
@@ -38,11 +38,11 @@ People _love_ thorough bug reports. I'm not even kidding.
|
|||||||
|
|
||||||
## Development Guidelines
|
## Development Guidelines
|
||||||
|
|
||||||
Please see the [documentation regarding development](https://gethomepage.dev/more/development/) and specifically the [guidelines for new service widgets](https://gethomepage.dev/more/development/#service-widget-guidelines) if you are considering making one.
|
Please see the [documentation regarding development](https://gethomepage.dev/widgets/authoring/getting-started/#development) and specifically the [guidelines for new service widgets](https://gethomepage.dev/widgets/authoring/getting-started/#service-widget-guidelines) if you are considering making one.
|
||||||
|
|
||||||
## Use a Consistent Coding Style
|
## Use a Consistent Coding Style
|
||||||
|
|
||||||
Please see information in the docs regarding [code formatting with pre-commit hooks](https://gethomepage.dev/more/development/#code-formatting-with-pre-commit-hooks).
|
Please see information in the docs regarding [code formatting with pre-commit hooks](https://gethomepage.dev/widgets/authoring/getting-started/#code-formatting-with-pre-commit-hooks).
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
@@ -63,7 +63,7 @@ The homepage team appreciates all effort and interest from the community in fili
|
|||||||
- Issues, pull requests and discussions that are closed will be locked after 30 days of inactivity.
|
- Issues, pull requests and discussions that are closed will be locked after 30 days of inactivity.
|
||||||
- Discussions with a marked answer will be automatically closed.
|
- Discussions with a marked answer will be automatically closed.
|
||||||
- Discussions in the 'General' or 'Support' categories will be closed after 180 days of inactivity.
|
- Discussions in the 'General' or 'Support' categories will be closed after 180 days of inactivity.
|
||||||
- Feature requests that do not meet the following thresholds will be closed: 10 "up-votes" after 180 days of inactivity or 20 "up-votes" after 365 days.
|
- Feature requests that do not meet the following thresholds will be closed: 20 "up-votes" after 180 days of inactivity or 40 "up-votes" after 365 days.
|
||||||
|
|
||||||
In all cases, threads can be re-opened by project maintainers and, of course, users can always create a new discussion for related concerns.
|
In all cases, threads can be re-opened by project maintainers and, of course, users can always create a new discussion for related concerns.
|
||||||
Finally, remember that all information remains searchable and 'closed' feature requests can still serve as inspiration for new features.
|
Finally, remember that all information remains searchable and 'closed' feature requests can still serve as inspiration for new features.
|
||||||
|
|||||||
+3
-1
@@ -51,8 +51,10 @@ COPY --link --from=builder --chown=1000:1000 /app/.next/static/ ./.next/static
|
|||||||
|
|
||||||
RUN apk add --no-cache su-exec iputils-ping shadow
|
RUN apk add --no-cache su-exec iputils-ping shadow
|
||||||
|
|
||||||
|
USER root
|
||||||
|
|
||||||
ENV NODE_ENV=production
|
ENV NODE_ENV=production
|
||||||
ENV HOSTNAME=0.0.0.0
|
ENV HOSTNAME=::
|
||||||
ENV PORT=3000
|
ENV PORT=3000
|
||||||
EXPOSE $PORT
|
EXPOSE $PORT
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,8 @@
|
|||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://github.com/gethomepage/homepage/actions/workflows/docker-publish.yml"><img alt="GitHub Workflow Status (with event)" src="https://img.shields.io/github/actions/workflow/status/gethomepage/homepage/docker-publish.yml"></a>
|
<a href="https://github.com/gethomepage/homepage/actions/workflows/docker-publish.yml"><img alt="GitHub Workflow Status (with event)" src="https://img.shields.io/github/actions/workflow/status/gethomepage/homepage/docker-publish.yml"></a>
|
||||||
|
|
||||||
|
<a href="https://codecov.io/gh/gethomepage/homepage"><img src="https://codecov.io/gh/gethomepage/homepage/graph/badge.svg?token=7SKFL4D9K7"/></a>
|
||||||
|
|
||||||
<a href="https://crowdin.com/project/gethomepage" target="_blank"><img src="https://badges.crowdin.net/gethomepage/localized.svg"></a>
|
<a href="https://crowdin.com/project/gethomepage" target="_blank"><img src="https://badges.crowdin.net/gethomepage/localized.svg"></a>
|
||||||
|
|
||||||
<a href="https://discord.gg/k4ruYNrudu"><img alt="Discord" src="https://img.shields.io/discord/1019316731635834932"></a>
|
<a href="https://discord.gg/k4ruYNrudu"><img alt="Discord" src="https://img.shields.io/discord/1019316731635834932"></a>
|
||||||
@@ -25,13 +27,6 @@
|
|||||||
<a href="https://paypal.me/phelpsben" title="Donate"><img alt="GitHub Sponsors" src="https://img.shields.io/github/sponsors/benphelps"></a>
|
<a href="https://paypal.me/phelpsben" title="Donate"><img alt="GitHub Sponsors" src="https://img.shields.io/github/sponsors/benphelps"></a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p align="center">
|
|
||||||
<a href="https://www.digitalocean.com/?refcode=df14bcb7c016&utm_campaign=Referral_Invite&utm_medium=Referral_Program&utm_source=badge"><img src="https://web-platforms.sfo2.cdn.digitaloceanspaces.com/WWW/Badge%201.svg" alt="DigitalOcean Referral Badge" /></a>
|
|
||||||
</p>
|
|
||||||
<p align="center">
|
|
||||||
<em>Homepage builds are kindly powered by DigitalOcean.</em>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
# Features
|
# Features
|
||||||
|
|
||||||
With features like quick search, bookmarks, weather support, a wide range of integrations and widgets, an elegant and modern design, and a focus on performance, Homepage is your ideal start to the day and a handy companion throughout it.
|
With features like quick search, bookmarks, weather support, a wide range of integrations and widgets, an elegant and modern design, and a focus on performance, Homepage is your ideal start to the day and a handy companion throughout it.
|
||||||
@@ -68,7 +63,7 @@ For configuration options, examples and more, [please check out the homepage doc
|
|||||||
|
|
||||||
## Security Notice 🔒
|
## Security Notice 🔒
|
||||||
|
|
||||||
Please note that when using features such as widgets, Homepage can access personal information (for example from your home automation system) and Homepage currently does not (and is not planned to) include any authentication layer itself. Thus, we recommend homepage be deployed behind a reverse proxy including authentication, SSL etc, and / or behind a VPN.
|
Please note that when using features such as widgets, Homepage can access personal information (for example from your home automation system) and Homepage currently does not (and is not planned to) include any authentication layer itself. If Homepage is reachable from any untrusted network, it **must** sit behind a reverse proxy (and/or VPN) that enforces authentication, TLS, and strictly validates Host headers. The built-in host check in Homepage is a best-effort guard and should not be treated as security when exposed publicly.
|
||||||
|
|
||||||
## With Docker
|
## With Docker
|
||||||
|
|
||||||
@@ -154,16 +149,16 @@ This is a [Next.js](https://nextjs.org/) application, see their documentation fo
|
|||||||
|
|
||||||
The homepage documentation is available at [https://gethomepage.dev/](https://gethomepage.dev/).
|
The homepage documentation is available at [https://gethomepage.dev/](https://gethomepage.dev/).
|
||||||
|
|
||||||
Homepage uses Material for MkDocs for documentation. To run the documentation locally, first install the dependencies:
|
Homepage uses Zensical for documentation. To run the documentation locally, first install the dependencies:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
pip install -r requirements.txt
|
uv sync
|
||||||
```
|
```
|
||||||
|
|
||||||
Then run the development server:
|
Then run the development server:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
mkdocs serve # or build, to build the static site
|
uv run zensical serve # or build, to build the static site
|
||||||
```
|
```
|
||||||
|
|
||||||
# Support & Suggestions
|
# Support & Suggestions
|
||||||
|
|||||||
+25
-6
@@ -12,8 +12,19 @@ export PGID=${PGID:-0}
|
|||||||
|
|
||||||
export HOMEPAGE_BUILDTIME=$(date +%s)
|
export HOMEPAGE_BUILDTIME=$(date +%s)
|
||||||
|
|
||||||
|
# Try IPv6 first (dual stack when available), but fall back to IPv4 if the bind fails
|
||||||
|
export HOSTNAME=${HOSTNAME:-::}
|
||||||
|
if [ "$HOSTNAME" = "::" ]; then
|
||||||
|
if ! node -e "const server = require('http').createServer(() => {}); const host = '::'; const port = process.env.PORT || 3000; server.once('error', (err) => { console.error('IPv6 bind failed:', err.message); process.exit(1); }); server.listen(port, host, () => server.close(() => process.exit(0)));"; then
|
||||||
|
echo "Falling back to IPv4 bind at 0.0.0.0"
|
||||||
|
export HOSTNAME=0.0.0.0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
# Check ownership before chown
|
# Check ownership before chown
|
||||||
if [ -e /app/config ]; then
|
if [ "$PUID" = "0" ]; then
|
||||||
|
echo "Skipping ownership changes for /app/config"
|
||||||
|
elif [ -e /app/config ]; then
|
||||||
CURRENT_UID=$(stat -c %u /app/config)
|
CURRENT_UID=$(stat -c %u /app/config)
|
||||||
CURRENT_GID=$(stat -c %g /app/config)
|
CURRENT_GID=$(stat -c %g /app/config)
|
||||||
|
|
||||||
@@ -30,7 +41,9 @@ else
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Ensure /app/config/logs exists and is owned
|
# Ensure /app/config/logs exists and is owned
|
||||||
if [ -n "$PUID" ] && [ -n "$PGID" ]; then
|
if [ "$PUID" = "0" ]; then
|
||||||
|
echo "Skipping ownership changes for /app/config/logs"
|
||||||
|
elif [ -n "$PUID" ] && [ -n "$PGID" ]; then
|
||||||
mkdir -p /app/config/logs 2>/dev/null || true
|
mkdir -p /app/config/logs 2>/dev/null || true
|
||||||
if [ -d /app/config/logs ]; then
|
if [ -d /app/config/logs ]; then
|
||||||
LOG_UID=$(stat -c %u /app/config/logs)
|
LOG_UID=$(stat -c %u /app/config/logs)
|
||||||
@@ -44,15 +57,21 @@ fi
|
|||||||
|
|
||||||
if [ -d /app/.next ]; then
|
if [ -d /app/.next ]; then
|
||||||
CURRENT_UID=$(stat -c %u /app/.next)
|
CURRENT_UID=$(stat -c %u /app/.next)
|
||||||
if [ "$CURRENT_UID" -ne "$PUID" ]; then
|
CURRENT_GID=$(stat -c %g /app/.next)
|
||||||
|
|
||||||
|
if [ "$PUID" -ne 0 ] && ([ "$CURRENT_UID" -ne "$PUID" ] || [ "$CURRENT_GID" -ne "$PGID" ]); then
|
||||||
echo "Fixing ownership of /app/.next"
|
echo "Fixing ownership of /app/.next"
|
||||||
chown -R "$PUID:$PGID" /app/.next || echo "Warning: Could not chown /app/.next"
|
if ! chown -R "$PUID:$PGID" /app/.next 2>/dev/null; then
|
||||||
|
echo "Warning: Could not chown /app/.next; continuing anyway"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "/app/.next already owned by correct UID/GID or running as root, skipping chown"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Drop privileges (when asked to) if root, otherwise run as current user
|
# Drop privileges (when asked to) if root, otherwise run as current user
|
||||||
if [ "$(id -u)" == "0" ] && [ "${PUID}" != "0" ]; then
|
if [ "$(id -u)" = "0" ] && [ "${PUID}" != "0" ]; then
|
||||||
su-exec ${PUID}:${PGID} "$@"
|
exec su-exec ${PUID}:${PGID} "$@"
|
||||||
else
|
else
|
||||||
exec "$@"
|
exec "$@"
|
||||||
fi
|
fi
|
||||||
|
|||||||
+13
-1
@@ -177,6 +177,16 @@ labels:
|
|||||||
- homepage.widget.fields=["field1","field2"] # optional
|
- homepage.widget.fields=["field1","field2"] # optional
|
||||||
```
|
```
|
||||||
|
|
||||||
|
!!! note
|
||||||
|
|
||||||
|
If you use mapping syntax (`:`) for labels instead of list syntax (`-`), array values like `fields` must be wrapped in single quotes so they are passed as a string:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
labels:
|
||||||
|
...
|
||||||
|
homepage.widget.fields: '["field1","field2"]'
|
||||||
|
```
|
||||||
|
|
||||||
Multiple widgets can be specified by incrementing the index, e.g.
|
Multiple widgets can be specified by incrementing the index, e.g.
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
@@ -189,6 +199,8 @@ labels: ...
|
|||||||
- homepage.widgets[1].slug=youreventslughere
|
- homepage.widgets[1].slug=youreventslughere
|
||||||
```
|
```
|
||||||
|
|
||||||
|
To pass custom HTTP headers with a widget request when using labels, use the same dot-notation: `homepage.widget.headers.X-Auth-Key=secret` (or `homepage.widgets[0].headers.X-Auth-Key=secret` when multiple widgets are present).
|
||||||
|
|
||||||
You can add specify fields for e.g. the [CustomAPI](../widgets/services/customapi.md) widget by using array-style dot notation:
|
You can add specify fields for e.g. the [CustomAPI](../widgets/services/customapi.md) widget by using array-style dot notation:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
@@ -271,4 +283,4 @@ You can show the docker stats by clicking the status indicator but this can also
|
|||||||
showStats: true
|
showStats: true
|
||||||
```
|
```
|
||||||
|
|
||||||
Also see the settings for [show docker stats](settings.md#show-docker-stats).
|
Also see the settings for [show docker stats](settings.md#show-container-stats).
|
||||||
|
|||||||
@@ -94,6 +94,7 @@ metadata:
|
|||||||
gethomepage.dev/name: Emby
|
gethomepage.dev/name: Emby
|
||||||
gethomepage.dev/widget.type: "emby"
|
gethomepage.dev/widget.type: "emby"
|
||||||
gethomepage.dev/widget.url: "https://emby.example.com"
|
gethomepage.dev/widget.url: "https://emby.example.com"
|
||||||
|
gethomepage.dev/widget.headers.X-Auth-Key: "your-secret-here"
|
||||||
gethomepage.dev/pod-selector: ""
|
gethomepage.dev/pod-selector: ""
|
||||||
gethomepage.dev/weight: 10 # optional
|
gethomepage.dev/weight: 10 # optional
|
||||||
gethomepage.dev/instance: "public" # optional
|
gethomepage.dev/instance: "public" # optional
|
||||||
@@ -121,7 +122,7 @@ Use the `gethomepage.dev/pod-selector` selector to specify the pod used for the
|
|||||||
|
|
||||||
### Traefik IngressRoute support
|
### Traefik IngressRoute support
|
||||||
|
|
||||||
Homepage can also read ingresses defined using the Traefik IngressRoute custom resource definition. Due to the complex nature of Traefik routing rules, it is required for the `gethomepage.dev/href` annotation to be set:
|
If enabled (with `traefik: true` in kubernetes.yaml), homepage can also read ingresses defined using the Traefik IngressRoute custom resource definition. Due to the complex nature of Traefik routing rules, it is required for the `gethomepage.dev/href` annotation to be set:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
apiVersion: traefik.io/v1alpha1
|
apiVersion: traefik.io/v1alpha1
|
||||||
@@ -178,3 +179,32 @@ See [ClusterRole and ClusterRoleBinding](../installation/k8s.md#clusterrole-and-
|
|||||||
## Caveats
|
## Caveats
|
||||||
|
|
||||||
Similarly to Docker service discovery, there currently is no rigid ordering to discovered services and discovered services will be displayed above those specified in the `services.yaml`.
|
Similarly to Docker service discovery, there currently is no rigid ordering to discovered services and discovered services will be displayed above those specified in the `services.yaml`.
|
||||||
|
|
||||||
|
## Adding extra configuration files
|
||||||
|
|
||||||
|
Some Homepage features (for example, [Proxmox](../configs/proxmox.md)) require additional configuration files such as `proxmox.yaml`.
|
||||||
|
When running Homepage on Kubernetes, these files must be provided via a `ConfigMap` and mounted into the container at `/app/config`.
|
||||||
|
|
||||||
|
### ConfigMap example
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: homepage
|
||||||
|
data:
|
||||||
|
proxmox.yaml: |
|
||||||
|
pve:
|
||||||
|
url: https://proxmox.host.or.ip:8006
|
||||||
|
token: username@pam!Token ID
|
||||||
|
secret: secret
|
||||||
|
```
|
||||||
|
|
||||||
|
Mount the file into `/app/config` by updating the `Deployment`:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
volumeMounts:
|
||||||
|
- mountPath: /app/config/proxmox.yaml
|
||||||
|
name: homepage-config
|
||||||
|
subPath: proxmox.yaml
|
||||||
|
```
|
||||||
|
|||||||
@@ -0,0 +1,81 @@
|
|||||||
|
---
|
||||||
|
title: Proxmox
|
||||||
|
description: Proxmox Configuration
|
||||||
|
---
|
||||||
|
|
||||||
|
The Proxmox connection is configured in the `proxmox.yaml` file. See [Create token](#create-token) section below for details on how to generate the required API token.
|
||||||
|
To configure multiple nodes, ensure the key name in the `proxmox.yaml` matches the `proxmoxNode` field used in your service configuration.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
pve: # must match your actual Proxmox node name
|
||||||
|
url: https://proxmox.host.or.ip:8006
|
||||||
|
token: username@pam!Token ID
|
||||||
|
secret: secret
|
||||||
|
```
|
||||||
|
|
||||||
|
## Services
|
||||||
|
|
||||||
|
Once the Proxmox connection is configured, individual services can be configured to pull statistics of VMs or LXCs. Only CPU and Memory are currently supported.
|
||||||
|
|
||||||
|
### Configuration Options
|
||||||
|
|
||||||
|
- `proxmoxNode`: The name of the Proxmox node where your VM/LXC is running, must match with a node configured in the `proxmox.yaml`
|
||||||
|
- `proxmoxVMID`: The ID of the Proxmox VM or LXC container
|
||||||
|
- `proxmoxType`: (Optional) The type of Proxmox virtual machine. Defaults to `qemu` for VMs, but can be set to `lxc` for LXC containers
|
||||||
|
|
||||||
|
#### Examples
|
||||||
|
|
||||||
|
For a QEMU VM (default):
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- HomeAssistant:
|
||||||
|
icon: home-assistant.png
|
||||||
|
href: http://homeassistant.local/
|
||||||
|
description: Home automation
|
||||||
|
proxmoxNode: pve
|
||||||
|
proxmoxVMID: 101
|
||||||
|
# proxmoxType: qemu # This is the default, so it can be omitted
|
||||||
|
```
|
||||||
|
|
||||||
|
For an LXC container:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- Nginx:
|
||||||
|
icon: nginx.png
|
||||||
|
href: http://nginx.local/
|
||||||
|
description: Web server
|
||||||
|
proxmoxNode: pve
|
||||||
|
proxmoxVMID: 200
|
||||||
|
proxmoxType: lxc
|
||||||
|
```
|
||||||
|
|
||||||
|
## Create token
|
||||||
|
|
||||||
|
You will need to generate an API Token for new or an existing user. Here is an example of how to do this for a new user.
|
||||||
|
|
||||||
|
1. Navigate to the Proxmox portal, click on Datacenter
|
||||||
|
2. Expand Permissions, click on Groups
|
||||||
|
3. Click the Create button
|
||||||
|
4. Name the group something informative, like api-ro-users
|
||||||
|
5. Click on the Permissions "folder"
|
||||||
|
6. Click Add -> Group Permission
|
||||||
|
- Path: /
|
||||||
|
- Group: group from bullet 4 above
|
||||||
|
- Role: PVEAuditor
|
||||||
|
- Propagate: Checked
|
||||||
|
7. Expand Permissions, click on Users
|
||||||
|
8. Click the Add button
|
||||||
|
- User name: something informative like `api`
|
||||||
|
- Realm: Linux PAM standard authentication
|
||||||
|
- Group: group from bullet 4 above
|
||||||
|
9. Expand Permissions, click on API Tokens
|
||||||
|
10. Click the Add button
|
||||||
|
- User: user from bullet 8 above
|
||||||
|
- Token ID: something informative like the application or purpose like `homepage`
|
||||||
|
- Privilege Separation: Checked
|
||||||
|
11. Go back to the "Permissions" menu
|
||||||
|
12. Click Add -> API Token Permission
|
||||||
|
- Path: /
|
||||||
|
- API Token: select the Token ID created in Step 10
|
||||||
|
- Role: PVE Auditor
|
||||||
|
- Propagate: Checked
|
||||||
@@ -101,6 +101,25 @@ Each service can have multiple widgets attached to it, for example:
|
|||||||
|
|
||||||
Multiple widgets per service are not yet supported with Kubernetes ingress annotations.
|
Multiple widgets per service are not yet supported with Kubernetes ingress annotations.
|
||||||
|
|
||||||
|
#### Custom HTTP headers
|
||||||
|
|
||||||
|
Widgets that make HTTP calls support extra request headers via `headers`. This is useful when a reverse proxy expects a secret header.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- UptimeRobot:
|
||||||
|
icon: uptimekuma.png
|
||||||
|
href: https://uptimerobot.com/
|
||||||
|
widget:
|
||||||
|
type: uptimerobot
|
||||||
|
url: https://api.uptimerobot.com
|
||||||
|
key: ${UPTIMEROBOT_API_KEY}
|
||||||
|
headers:
|
||||||
|
User-Agent: homepage
|
||||||
|
X-Auth-Key: your-secret-here
|
||||||
|
```
|
||||||
|
|
||||||
|
If you define services via Docker labels or Kubernetes annotations, use the same key with dot-notation (for example `homepage.widget.headers.X-Auth-Key=secret` or `gethomepage.dev/widget.headers.X-Auth-Key: "secret"`).
|
||||||
|
|
||||||
#### Field Visibility
|
#### Field Visibility
|
||||||
|
|
||||||
Each widget can optionally provide a list of which fields should be visible via the `fields` widget property. If no fields are specified, then all fields will be displayed. The `fields` property must be a valid YAML array of strings. As an example, here is the entry for Sonarr showing only a couple of fields.
|
Each widget can optionally provide a list of which fields should be visible via the `fields` widget property. If no fields are specified, then all fields will be displayed. The `fields` property must be a valid YAML array of strings. As an example, here is the entry for Sonarr showing only a couple of fields.
|
||||||
@@ -118,6 +137,60 @@ Each widget can optionally provide a list of which fields should be visible via
|
|||||||
key: apikeyapikeyapikeyapikeyapikey
|
key: apikeyapikeyapikeyapikeyapikey
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Block Highlighting
|
||||||
|
|
||||||
|
Widgets can tint their metric block text automatically based on rules defined alongside the service. Attach a `highlight` section to the widget configuration and map each block to one or more numeric or string rules using the field key (for example, `queued`, `lan_users`).
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- Sonarr:
|
||||||
|
icon: sonarr.png
|
||||||
|
href: http://sonarr.host.or.ip
|
||||||
|
widget:
|
||||||
|
type: sonarr
|
||||||
|
url: http://sonarr.host.or.ip
|
||||||
|
key: ${SONARR_API_KEY}
|
||||||
|
highlight:
|
||||||
|
queued:
|
||||||
|
numeric:
|
||||||
|
- level: danger
|
||||||
|
when: gte
|
||||||
|
value: 20
|
||||||
|
- level: warn
|
||||||
|
when: gte
|
||||||
|
value: 5
|
||||||
|
- level: good
|
||||||
|
when: eq
|
||||||
|
value: 0
|
||||||
|
status:
|
||||||
|
string:
|
||||||
|
- level: danger
|
||||||
|
when: regex
|
||||||
|
value: "(failed|import) pending"
|
||||||
|
- level: good
|
||||||
|
when: equals
|
||||||
|
value: "All good"
|
||||||
|
status_code:
|
||||||
|
string:
|
||||||
|
- level: warn
|
||||||
|
when: regex
|
||||||
|
value: "^5\\d{2}$"
|
||||||
|
```
|
||||||
|
|
||||||
|
Supported numeric operators for the `when` property are `gt`, `gte`, `lt`, `lte`, `eq`, `ne`, `between`, and `outside`. String rules support `equals`, `includes`, `startsWith`, `endsWith`, and `regex`. Each rule can be inverted with `negate: true`, and string rules may pass `caseSensitive: true` or custom regex `flags`. The highlight engine does its best to coerce formatted values, but you will get the most reliable results when you pass plain numbers or strings into `<Block>`.
|
||||||
|
|
||||||
|
#### Value Only Highlighting
|
||||||
|
|
||||||
|
You can optionally apply highlighting only to the value portion of a block (not the label) by setting `valueOnly: true` on the field configuration. This keeps the label visible while highlighting only the metric value itself.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- Sonarr:
|
||||||
|
...
|
||||||
|
highlight:
|
||||||
|
queued:
|
||||||
|
valueOnly: true
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
## Descriptions
|
## Descriptions
|
||||||
|
|
||||||
Services may have descriptions,
|
Services may have descriptions,
|
||||||
|
|||||||
@@ -109,6 +109,72 @@ color: slate
|
|||||||
|
|
||||||
Supported colors are: `slate`, `gray`, `zinc`, `neutral`, `stone`, `amber`, `yellow`, `lime`, `green`, `emerald`, `teal`, `cyan`, `sky`, `blue`, `indigo`, `violet`, `purple`, `fuchsia`, `pink`, `rose`, `red`, `white`
|
Supported colors are: `slate`, `gray`, `zinc`, `neutral`, `stone`, `amber`, `yellow`, `lime`, `green`, `emerald`, `teal`, `cyan`, `sky`, `blue`, `indigo`, `violet`, `purple`, `fuchsia`, `pink`, `rose`, `red`, `white`
|
||||||
|
|
||||||
|
## Block Highlight Levels
|
||||||
|
|
||||||
|
You can override the default Tailwind classes applied when a widget highlight rule resolves to the `good`, `warn`, or `danger` level.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
blockHighlights:
|
||||||
|
levels:
|
||||||
|
good: "bg-emerald-500/40 text-emerald-950 dark:bg-emerald-900/60 dark:text-emerald-400"
|
||||||
|
warn: "bg-amber-300/30 text-amber-900 dark:bg-amber-900/30 dark:text-amber-200"
|
||||||
|
danger: "bg-rose-700/45 text-rose-200 dark:bg-rose-950/70 dark:text-rose-400"
|
||||||
|
```
|
||||||
|
|
||||||
|
Any unspecified level falls back to the built-in defaults.
|
||||||
|
|
||||||
|
## Progressive Web App (PWA)
|
||||||
|
|
||||||
|
A progressive web app is an app that can be installed on a device and provide user experience like a native app. Homepage comes with built-in support for PWA with some default configurations, but you can customize them.
|
||||||
|
|
||||||
|
More information on PWAs can be found in [MDN Web Docs](https://developer.mozilla.org/en-US/docs/Web/Progressive_web_apps).
|
||||||
|
|
||||||
|
### App icons
|
||||||
|
|
||||||
|
You can set custom icons for installable apps. More information about how you can set them can be found in the [MDN Web Docs](https://developer.mozilla.org/en-US/docs/Web/Progressive_web_apps/Manifest/Reference/icons).
|
||||||
|
|
||||||
|
The default value is the Homepage icon in sizes 192x192 and 512x512.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
pwa:
|
||||||
|
icons:
|
||||||
|
- src: https://developer.mozilla.org/favicon-192x192.png
|
||||||
|
type: image/png
|
||||||
|
sizes: 192x192
|
||||||
|
- src: https://developer.mozilla.org/favicon-512x512.png
|
||||||
|
type: image/png
|
||||||
|
sizes: 512x512
|
||||||
|
```
|
||||||
|
|
||||||
|
For icon `src` you can pass either full URL or a local path relative to the `/app/public` directory. See [Background Image](#background-image) for more detailed information on how to provide your own files.
|
||||||
|
|
||||||
|
### Shortcuts
|
||||||
|
|
||||||
|
Shortcuts can be used to specify links to tabs, to be preselected when the homepage is opened as an app.
|
||||||
|
More information about how you can set them can be found in the [MDN Web Docs](https://developer.mozilla.org/en-US/docs/Web/Progressive_web_apps/Manifest/Reference/shortcuts).
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
pwa:
|
||||||
|
shortcuts:
|
||||||
|
- name: First
|
||||||
|
url: "/#first" # opens the first tab
|
||||||
|
- name: Second
|
||||||
|
url: "/#second" # opens the second tab
|
||||||
|
- name: Third
|
||||||
|
url: "/#third" # opens the third tab
|
||||||
|
```
|
||||||
|
|
||||||
|
### Other PWA configurations
|
||||||
|
|
||||||
|
Homepage sets few other PWA configurations, that are based on global settings in `settings.yaml`:
|
||||||
|
|
||||||
|
- `name`, `short_name` - Both equal to the [`title`](#title) setting.
|
||||||
|
- `theme_color`, `background_color` - Both based on the [`color`](#color-palette) and [`theme`](#theme) settings.
|
||||||
|
- `display` - It is always set to "standalone".
|
||||||
|
- `start_url` - Equal to the [`startUrl`](#start-url) setting.
|
||||||
|
|
||||||
|
More information for wach of the PWA configurations can be found in the [MDN Web Docs](https://developer.mozilla.org/en-US/docs/Web/Progressive_web_apps/Manifest/Reference).
|
||||||
|
|
||||||
## Layout
|
## Layout
|
||||||
|
|
||||||
You can configure service and bookmarks sections to be either "column" or "row" based layouts, like so:
|
You can configure service and bookmarks sections to be either "column" or "row" based layouts, like so:
|
||||||
@@ -264,7 +330,7 @@ fullWidth: true
|
|||||||
|
|
||||||
### Maximum Group Columns
|
### Maximum Group Columns
|
||||||
|
|
||||||
You can set the maximum number of columns of groups on larger screen sizes (note this is only for groups with the default `style: columns`, not groups with `stle: row`) by adding:
|
You can set the maximum number of columns of groups on larger screen sizes (note this is only for groups with the default `style: columns`, not groups with `style: row`) by adding:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
maxGroupColumns: 8 # default is 4 for services, 6 for bookmarks, max 8
|
maxGroupColumns: 8 # default is 4 for services, 6 for bookmarks, max 8
|
||||||
@@ -382,7 +448,9 @@ Set your desired language using:
|
|||||||
language: fr
|
language: fr
|
||||||
```
|
```
|
||||||
|
|
||||||
Currently supported languages: ca, de, en, es, fr, he, hr, hu, it, nb-NO, nl, pt, ru, sv, vi, zh-CN, zh-Hant
|
Currently supported languages: ca, de, en, es, fr, he, hr, hu, it, nb-NO, nl, pt, ru, sv, vi, zh-Hans (Simplified), zh-Hant (Traditional)
|
||||||
|
|
||||||
|
`zh-CN` will still work and is automatically mapped to `zh-Hans` for backwards compatibility.
|
||||||
|
|
||||||
You can also specify locales e.g. for the DateTime widget, e.g. en-AU, en-GB, etc.
|
You can also specify locales e.g. for the DateTime widget, e.g. en-AU, en-GB, etc.
|
||||||
|
|
||||||
@@ -441,6 +509,7 @@ There are a few optional settings for the Quick Launch feature:
|
|||||||
- `showSearchSuggestions`: show search suggestions for the internet search. If this is not specified then the setting will be inherited from the search widget. If it is not specified there either, it will default to false. For custom providers the `suggestionUrl` needs to be set in order for this to work.
|
- `showSearchSuggestions`: show search suggestions for the internet search. If this is not specified then the setting will be inherited from the search widget. If it is not specified there either, it will default to false. For custom providers the `suggestionUrl` needs to be set in order for this to work.
|
||||||
- `provider`: search engine provider. If none is specified it will try to use the provider set for the Search Widget, if neither are present then internet search will be disabled.
|
- `provider`: search engine provider. If none is specified it will try to use the provider set for the Search Widget, if neither are present then internet search will be disabled.
|
||||||
- `hideVisitURL`: disable detecting and offering an option to open URLs. This is false by default, enabling the feature.
|
- `hideVisitURL`: disable detecting and offering an option to open URLs. This is false by default, enabling the feature.
|
||||||
|
- `mobileButtonPosition`: enables and sets the position of the mobile quicklaunch button. Options are `top-left`, `top-right`, `bottom-left`, `bottom-right`. This is empty by default, disabling the feature.
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
quicklaunch:
|
quicklaunch:
|
||||||
@@ -485,9 +554,9 @@ logpath: /logfile/path
|
|||||||
|
|
||||||
By default, logs are sent both to `stdout` and to a file at the path specified. This can be changed by setting the `LOG_TARGETS` environment variable to one of `both` (default), `stdout` or `file`.
|
By default, logs are sent both to `stdout` and to a file at the path specified. This can be changed by setting the `LOG_TARGETS` environment variable to one of `both` (default), `stdout` or `file`.
|
||||||
|
|
||||||
## Show Docker Stats
|
## Show Container Stats
|
||||||
|
|
||||||
You can show all docker stats expanded in `settings.yaml`:
|
You can show all docker or proxmox stats expanded in `settings.yaml`:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
showStats: true
|
showStats: true
|
||||||
@@ -556,3 +625,18 @@ or per service widget (`services.yaml`) with:
|
|||||||
```
|
```
|
||||||
|
|
||||||
If either value is set to true, the error message will be hidden.
|
If either value is set to true, the error message will be hidden.
|
||||||
|
|
||||||
|
## Disable Search Engine Indexing
|
||||||
|
|
||||||
|
You can request that search engines not to index your Homepage instance by enabling the `disableIndexing` setting.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
disableIndexing: true
|
||||||
|
```
|
||||||
|
|
||||||
|
When enabled, this will:
|
||||||
|
|
||||||
|
- Disallow all crawlers in `robots.txt`
|
||||||
|
- Add `<meta name="robots" content="noindex, nofollow">` tags to prevent indexing
|
||||||
|
|
||||||
|
By default this feature is disabled.
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ services:
|
|||||||
- 3000:3000
|
- 3000:3000
|
||||||
volumes:
|
volumes:
|
||||||
- /path/to/config:/app/config # Make sure your local config directory exists
|
- /path/to/config:/app/config # Make sure your local config directory exists
|
||||||
- /var/run/docker.sock:/var/run/docker.sock # (optional) For docker integrations
|
- /var/run/docker.sock:/var/run/docker.sock:ro # (optional) For docker integrations
|
||||||
environment:
|
environment:
|
||||||
HOMEPAGE_ALLOWED_HOSTS: gethomepage.dev # required, may need port. See gethomepage.dev/installation/#homepage_allowed_hosts
|
HOMEPAGE_ALLOWED_HOSTS: gethomepage.dev # required, may need port. See gethomepage.dev/installation/#homepage_allowed_hosts
|
||||||
```
|
```
|
||||||
@@ -36,7 +36,7 @@ services:
|
|||||||
- 3000:3000
|
- 3000:3000
|
||||||
volumes:
|
volumes:
|
||||||
- /path/to/config:/app/config # Make sure your local config directory exists
|
- /path/to/config:/app/config # Make sure your local config directory exists
|
||||||
- /var/run/docker.sock:/var/run/docker.sock # (optional) For docker integrations, see alternative methods
|
- /var/run/docker.sock:/var/run/docker.sock:ro # (optional) For docker integrations, see alternative methods
|
||||||
environment:
|
environment:
|
||||||
HOMEPAGE_ALLOWED_HOSTS: gethomepage.dev # required, may need port. See gethomepage.dev/installation/#homepage_allowed_hosts
|
HOMEPAGE_ALLOWED_HOSTS: gethomepage.dev # required, may need port. See gethomepage.dev/installation/#homepage_allowed_hosts
|
||||||
PUID: $PUID
|
PUID: $PUID
|
||||||
|
|||||||
@@ -37,4 +37,4 @@ The value is a comma-separated (no spaces) list of allowed hosts (sometimes with
|
|||||||
|
|
||||||
If you are seeing errors about host validation, check the homepage logs and ensure that the host exactly as output in the logs is in the `HOMEPAGE_ALLOWED_HOSTS` list.
|
If you are seeing errors about host validation, check the homepage logs and ensure that the host exactly as output in the logs is in the `HOMEPAGE_ALLOWED_HOSTS` list.
|
||||||
|
|
||||||
This can be disabled by setting `HOMEPAGE_ALLOWED_HOSTS` to `*` but this is not recommended.
|
This can be disabled by setting `HOMEPAGE_ALLOWED_HOSTS` to `*` but this is not recommended. Public deployments must rely on a reverse proxy (and/or VPN) that enforces authentication, TLS, and unexpected Host headers; the built-in host check is a best-effort guard for local setups and is not a substitute for edge protections.
|
||||||
|
|||||||
@@ -223,13 +223,33 @@ spec:
|
|||||||
- name: homepage
|
- name: homepage
|
||||||
image: "ghcr.io/gethomepage/homepage:latest"
|
image: "ghcr.io/gethomepage/homepage:latest"
|
||||||
imagePullPolicy: Always
|
imagePullPolicy: Always
|
||||||
|
securityContext:
|
||||||
|
allowPrivilegeEscalation: false
|
||||||
|
capabilities:
|
||||||
|
drop:
|
||||||
|
- ALL
|
||||||
|
runAsNonRoot: true
|
||||||
|
runAsUser: 1000
|
||||||
|
runAsGroup: 1000
|
||||||
|
seccompProfile:
|
||||||
|
type: RuntimeDefault
|
||||||
env:
|
env:
|
||||||
|
- name: MY_POD_IP
|
||||||
|
valueFrom:
|
||||||
|
fieldRef:
|
||||||
|
fieldPath: status.podIP
|
||||||
- name: HOMEPAGE_ALLOWED_HOSTS
|
- name: HOMEPAGE_ALLOWED_HOSTS
|
||||||
value: gethomepage.dev # required, may need port. See gethomepage.dev/installation/#homepage_allowed_hosts
|
value: "$(MY_POD_IP):3000,gethomepage.dev" # See gethomepage.dev/installation/#homepage_allowed_hosts . Value before the comma is required for the k8s probe
|
||||||
ports:
|
ports:
|
||||||
- name: http
|
- name: http
|
||||||
containerPort: 3000
|
containerPort: 3000
|
||||||
protocol: TCP
|
protocol: TCP
|
||||||
|
livenessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /api/healthcheck
|
||||||
|
port: http
|
||||||
|
initialDelaySeconds: 5
|
||||||
|
periodSeconds: 15
|
||||||
volumeMounts:
|
volumeMounts:
|
||||||
- mountPath: /app/config/custom.js
|
- mountPath: /app/config/custom.js
|
||||||
name: homepage-config
|
name: homepage-config
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ These companies help the Homepage project by providing services, tools, and reso
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style="margin-bottom: 16px;">
|
<div style="margin-bottom: 16px;">
|
||||||
<a href="https://crowdin.com/project/homepage"><img src="https://support.crowdin.com/assets/logos/core-logo/png/crowdin-core-logo-cWhite.png" alt="Crowdin" style="max-width: 100%; height: 64px; display: block;" /></a>
|
<a href="https://crowdin.com/project/gethomepage"><img src="https://support.crowdin.com/assets/logos/core-logo/png/crowdin-core-logo-cWhite.png" alt="Crowdin" style="max-width: 100%; height: 64px; display: block;" /></a>
|
||||||
<p>
|
<p>
|
||||||
Crowdin provides the translation platform for the project. Making it easy to translate the project into multiple languages.
|
Crowdin provides the translation platform for the project. Making it easy to translate the project into multiple languages.
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@@ -104,7 +104,7 @@
|
|||||||
|
|
||||||
body {
|
body {
|
||||||
background-color: transparent !important;
|
background-color: transparent !important;
|
||||||
background-image: url("https://raw.githubusercontent.com/gethomepage/homepage/main/docs/assets/blossom_valley.jpg");
|
background-image: url("https://raw.githubusercontent.com/gethomepage/homepage/main/docs/assets/blossom_valley_blur.jpg");
|
||||||
background-size: cover;
|
background-size: cover;
|
||||||
background-attachment: fixed;
|
background-attachment: fixed;
|
||||||
background-position: center;
|
background-position: center;
|
||||||
@@ -119,20 +119,6 @@ body[data-md-color-scheme="default"] {
|
|||||||
color: rgba(255, 255, 255, 1);
|
color: rgba(255, 255, 255, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
.blur-overlay {
|
|
||||||
z-index: -1;
|
|
||||||
position: fixed;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
background: hsl(0deg 0% 0% / 10%);
|
|
||||||
backdrop-filter: blur(128px);
|
|
||||||
-webkit-backdrop-filter: blur(128px);
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-md-color-scheme="default"] .blur-overlay {
|
|
||||||
background: hsla(0, 0%, 0%, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
.md-nav--lifted > .md-nav__list > .md-nav__item--active > .md-nav__link,
|
.md-nav--lifted > .md-nav__list > .md-nav__item--active > .md-nav__link,
|
||||||
.md-nav--secondary .md-nav__title {
|
.md-nav--secondary .md-nav__title {
|
||||||
background: none;
|
background: none;
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ hide:
|
|||||||
- Check config/logs/homepage.log, on docker simply e.g. `docker logs homepage`. This may provide some insight into the reason for an error.
|
- Check config/logs/homepage.log, on docker simply e.g. `docker logs homepage`. This may provide some insight into the reason for an error.
|
||||||
- Check the browser error console, this can also sometimes provide useful information.
|
- Check the browser error console, this can also sometimes provide useful information.
|
||||||
- Consider setting the `ENV` variable `LOG_LEVEL` to `debug`.
|
- Consider setting the `ENV` variable `LOG_LEVEL` to `debug`.
|
||||||
- If certain widgets are failing when connecting to public APIs, consider [disabling IPv6](#disabling-ipv6).
|
|
||||||
|
|
||||||
## Service Widget Errors
|
## Service Widget Errors
|
||||||
|
|
||||||
@@ -67,17 +66,3 @@ All service widgets work essentially the same, that is, homepage makes a proxied
|
|||||||
## Missing custom icons
|
## Missing custom icons
|
||||||
|
|
||||||
If, after correctly adding and mapping your custom icons via the [Icons](../configs/services.md#icons) instructions, you are still unable to see your icons please try recreating your container.
|
If, after correctly adding and mapping your custom icons via the [Icons](../configs/services.md#icons) instructions, you are still unable to see your icons please try recreating your container.
|
||||||
|
|
||||||
## Disabling IPv6
|
|
||||||
|
|
||||||
If you are having issues with certain widgets that are unable to reach public APIs (e.g. weather), in certain setups you may need to disable IPv6. You can set the environment variable `HOMEPAGE_PROXY_DISABLE_IPV6` to `true` to disable IPv6 for the homepage proxy.
|
|
||||||
|
|
||||||
Alternatively, you can use the `sysctls` option in your docker-compose file to disable IPv6 for the homepage container completely:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
services:
|
|
||||||
homepage:
|
|
||||||
...
|
|
||||||
sysctls:
|
|
||||||
- net.ipv6.conf.all.disable_ipv6=1
|
|
||||||
```
|
|
||||||
|
|||||||
@@ -33,6 +33,32 @@ Once dependencies have been installed you can lint your code with
|
|||||||
pnpm lint
|
pnpm lint
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
Homepage uses [Vitest](https://vitest.dev/) for unit and component tests.
|
||||||
|
|
||||||
|
Run the test suite:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pnpm test
|
||||||
|
```
|
||||||
|
|
||||||
|
Run the test suite with coverage:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pnpm test:coverage
|
||||||
|
```
|
||||||
|
|
||||||
|
### What tests to include
|
||||||
|
|
||||||
|
- New or updated widgets should generally include a component test near the widget component (for example `src/widgets/<widget>/component.test.jsx`) that covers realistic behavior: loading/placeholder state, error state, and a representative "happy path" render.
|
||||||
|
- If you add or change a widget definition file (`src/widgets/<widget>/widget.js`), add/update its corresponding unit test (`src/widgets/<widget>/widget.test.js`) to cover the config/mapping behavior.
|
||||||
|
- If your widget requires a custom proxy (`src/widgets/<widget>/proxy.js`), add a proxy unit test (`src/widgets/<widget>/proxy.test.js`) that validates:
|
||||||
|
- request construction (URL, query params, headers/auth)
|
||||||
|
- response mapping (what the widget consumes)
|
||||||
|
- error pathways (upstream error, unexpected payloads)
|
||||||
|
- Avoid placing test files under `src/pages/**` (Next.js treats files there as routes). Page tests should live under `src/__tests__/pages/**`.
|
||||||
|
|
||||||
## Code formatting with pre-commit hooks
|
## Code formatting with pre-commit hooks
|
||||||
|
|
||||||
To ensure a consistent style and formatting across the project source, the project utilizes Git [`pre-commit`](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks) hooks to perform some formatting and linting before a commit is allowed.
|
To ensure a consistent style and formatting across the project source, the project utilizes Git [`pre-commit`](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks) hooks to perform some formatting and linting before a commit is allowed.
|
||||||
@@ -62,3 +88,4 @@ To ensure cohesiveness of various widgets, the following should be used as a gui
|
|||||||
- Minimize the number of API calls
|
- Minimize the number of API calls
|
||||||
- Avoid the use of custom proxy unless absolutely necessary
|
- Avoid the use of custom proxy unless absolutely necessary
|
||||||
- Widgets should be 'read-only', as in they should not make write changes using the relevant tool's API. Homepage widgets are designed to surface information, not to be a (usually worse) replacement for the tool itself.
|
- Widgets should be 'read-only', as in they should not make write changes using the relevant tool's API. Homepage widgets are designed to surface information, not to be a (usually worse) replacement for the tool itself.
|
||||||
|
- Widgets should not allow manually overriding the "refresh interval" setting, as misconfigured refresh intervals can easily lead to performance issues for users.
|
||||||
|
|||||||
@@ -225,20 +225,8 @@ const widgetExample = {
|
|||||||
|
|
||||||
#### `method`
|
#### `method`
|
||||||
|
|
||||||
The `method` property is a string that represents the HTTP method that should be used to make the API request. The default value is `GET`.
|
The `method` represents the HTTP method that should be used to make the API request. The default value is `GET`. Note that `POST` requests are not allowed via the
|
||||||
|
widget API and require the use of a custom proxy.
|
||||||
```js
|
|
||||||
const widgetExample = {
|
|
||||||
api: "{url}/api/{endpoint}",
|
|
||||||
mappings: {
|
|
||||||
// `/api/stats`
|
|
||||||
stats: {
|
|
||||||
endpoint: "stats",
|
|
||||||
method: "POST",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
#### `headers`
|
#### `headers`
|
||||||
|
|
||||||
@@ -251,7 +239,6 @@ const widgetExample = {
|
|||||||
// `/api/stats`
|
// `/api/stats`
|
||||||
stats: {
|
stats: {
|
||||||
endpoint: "stats",
|
endpoint: "stats",
|
||||||
method: "POST",
|
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
},
|
},
|
||||||
@@ -271,7 +258,6 @@ const widgetExample = {
|
|||||||
// `/api/graphql`
|
// `/api/graphql`
|
||||||
stats: {
|
stats: {
|
||||||
endpoint: "graphql",
|
endpoint: "graphql",
|
||||||
method: "POST",
|
|
||||||
body: {
|
body: {
|
||||||
query: `
|
query: `
|
||||||
query {
|
query {
|
||||||
|
|||||||
@@ -201,3 +201,18 @@ export default async function customProxyHandler(req, res, map) {
|
|||||||
```
|
```
|
||||||
|
|
||||||
Proxy handlers are a complex topic and require a good understanding of JavaScript and the Homepage codebase. If you are new to Homepage, we recommend using the built-in proxy handlers.
|
Proxy handlers are a complex topic and require a good understanding of JavaScript and the Homepage codebase. If you are new to Homepage, we recommend using the built-in proxy handlers.
|
||||||
|
|
||||||
|
## Testing proxy handlers
|
||||||
|
|
||||||
|
Proxy handlers are a common source of regressions because they deal with authentication, request formatting, and sometimes odd upstream API behavior.
|
||||||
|
|
||||||
|
When you add a new proxy handler or custom widget proxy, include tests that focus on behavior:
|
||||||
|
|
||||||
|
- **Request construction:** the correct URL/path, query params, headers, and auth (and that secrets are not accidentally logged).
|
||||||
|
- **Response mapping:** the payload shape expected by the widget/component (including optional/missing fields).
|
||||||
|
- **Error handling:** upstream non-200s, invalid JSON, timeouts, and unexpected payloads should produce a predictable result.
|
||||||
|
|
||||||
|
Test locations:
|
||||||
|
|
||||||
|
- Shared handlers live in `src/utils/proxy/handlers/*.js` with tests alongside them (for example `src/utils/proxy/handlers/generic.test.js`).
|
||||||
|
- Widget-specific proxies live in `src/widgets/<widget>/proxy.js` with tests in `src/widgets/<widget>/proxy.test.js`.
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ More detail on configuring service widgets can be found in the [Service Widgets
|
|||||||
|
|
||||||
## Info Widgets
|
## Info Widgets
|
||||||
|
|
||||||
Info widgets are used to display information in the header, often about your system or environment. Info widgets are defined your `widgets.yaml` file. Here's an example:
|
Info widgets are used to display information in the header, often about your system or environment. Info widgets are defined in your `widgets.yaml` file. Here's an example:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
- openmeteo:
|
- openmeteo:
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ The Glances widget allows you to monitor the resources (CPU, memory, storage, te
|
|||||||
cpu: true # optional, enabled by default, disable by setting to false
|
cpu: true # optional, enabled by default, disable by setting to false
|
||||||
mem: true # optional, enabled by default, disable by setting to false
|
mem: true # optional, enabled by default, disable by setting to false
|
||||||
cputemp: true # disabled by default
|
cputemp: true # disabled by default
|
||||||
|
cpuSensorLabel: Package id # optional additional cputemp sensor label prefix
|
||||||
|
unit: imperial # optional for temp, default is metric
|
||||||
uptime: true # disabled by default
|
uptime: true # disabled by default
|
||||||
disk: / # disabled by default, use mount point of disk(s) in glances. Can also be a list (see below)
|
disk: / # disabled by default, use mount point of disk(s) in glances. Can also be a list (see below)
|
||||||
diskUnits: bytes # optional, bytes (default) or bbytes. Only applies to disk
|
diskUnits: bytes # optional, bytes (default) or bbytes. Only applies to disk
|
||||||
@@ -23,6 +25,8 @@ The Glances widget allows you to monitor the resources (CPU, memory, storage, te
|
|||||||
label: MyMachine # optional
|
label: MyMachine # optional
|
||||||
```
|
```
|
||||||
|
|
||||||
|
The built-in `cputemp` sensor matching already checks common prefixes such as `cpu_thermal`, `Core`, `Tctl`, and `Temperature`. Use `cpuSensorLabel` to add your own Glances sensor label prefix when your system reports CPU temperatures under a different name.
|
||||||
|
|
||||||
Multiple disks can be specified as:
|
Multiple disks can be specified as:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
@@ -31,5 +35,3 @@ disk:
|
|||||||
- /boot
|
- /boot
|
||||||
...
|
...
|
||||||
```
|
```
|
||||||
|
|
||||||
_Added in v0.4.18, updated in v0.6.11, v0.6.21_
|
|
||||||
|
|||||||
@@ -7,13 +7,17 @@ You can include all or some of the available resources. If you do not want to se
|
|||||||
|
|
||||||
The disk path is the path reported by `df` (Mounted On), or the mount point of the disk.
|
The disk path is the path reported by `df` (Mounted On), or the mount point of the disk.
|
||||||
|
|
||||||
|
!!! note
|
||||||
|
|
||||||
|
Any disk you wish to access must be mounted to your container as a volume.
|
||||||
|
|
||||||
The cpu and memory resource information are the container's usage while [glances](glances.md) displays statistics for the host machine on which it is installed.
|
The cpu and memory resource information are the container's usage while [glances](glances.md) displays statistics for the host machine on which it is installed.
|
||||||
|
|
||||||
The resources widget primarily relies on a popular tool called [systeminformation](https://systeminformation.io). Thus, any limitiations of that software apply, for example, BRTFS RAID is not supported for the disk usage. In this case users may want to use the [glances widget](glances.md) instead.
|
The resources widget primarily relies on a popular tool called [systeminformation](https://systeminformation.io). Thus, any limitiations of that software apply, for example, BRTFS RAID is not supported for the disk usage. In this case users may want to use the [glances widget](glances.md) instead.
|
||||||
|
|
||||||
_Note: unfortunately, the package used for getting CPU temp ([systeminformation](https://systeminformation.io)) is not compatible with some setups and will not report any value(s) for CPU temp._
|
!!! warning
|
||||||
|
|
||||||
**Any disk you wish to access must be mounted to your container as a volume.**
|
The package used for getting CPU temp ([systeminformation](https://systeminformation.io)) is not compatible with some setups and will not report any value(s) for CPU temp.
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
- resources:
|
- resources:
|
||||||
@@ -75,3 +79,10 @@ You can additionally supply an optional `expanded` property set to true in order
|
|||||||
```
|
```
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
To monitor a named host network interface in Docker (for example `network: eno1`), mount host `/sys` (read-only):
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
volumes:
|
||||||
|
- /sys:/sys:ro
|
||||||
|
```
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ You can display general connectivity status from your Unifi (Network) Controller
|
|||||||
|
|
||||||
An optional 'site' parameter can be supplied, if it is not the widget will use the default site for the controller.
|
An optional 'site' parameter can be supplied, if it is not the widget will use the default site for the controller.
|
||||||
|
|
||||||
!!! hint
|
!!! tip
|
||||||
|
|
||||||
If you enter e.g. incorrect credentials and receive an "API Error", you may need to recreate the container to clear the cache.
|
If you enter e.g. incorrect credentials and receive an "API Error", you may need to recreate the container to clear the cache.
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
---
|
||||||
|
title: Arcane
|
||||||
|
description: Arcane Widget Configuration
|
||||||
|
---
|
||||||
|
|
||||||
|
Learn more about [Arcane](https://github.com/getarcaneapp/arcane).
|
||||||
|
|
||||||
|
**Allowed fields** (max 4): `running`, `stopped`, `total`, `images`, `images_used`, `images_unused`, `image_updates`.
|
||||||
|
**Default fields**: `running`, `stopped`, `total`, `image_updates`.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
widget:
|
||||||
|
type: arcane
|
||||||
|
url: http://localhost:3552
|
||||||
|
env: 0 # required, 0 is Arcane default local environment
|
||||||
|
key: your-api-key
|
||||||
|
fields: ["running", "stopped", "total", "image_updates"] # optional
|
||||||
|
```
|
||||||
@@ -17,9 +17,15 @@ The account you made the API token for also needs the following **Assigned globa
|
|||||||
|
|
||||||
Allowed fields: `["users", "loginsLast24H", "failedLoginsLast24H"]`.
|
Allowed fields: `["users", "loginsLast24H", "failedLoginsLast24H"]`.
|
||||||
|
|
||||||
|
| Authentik Version | Homepage Widget Version |
|
||||||
|
| ----------------- | ----------------------- |
|
||||||
|
| < 2025.8.0 | 1 (default) |
|
||||||
|
| >= 2025.8.0 | 2 |
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
widget:
|
widget:
|
||||||
type: authentik
|
type: authentik
|
||||||
url: http://authentik.host.or.ip:port
|
url: http://authentik.host.or.ip:port
|
||||||
key: api_token
|
key: api_token
|
||||||
|
version: 2 # optional, default is 1
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
---
|
||||||
|
title: Backrest
|
||||||
|
description: Backrest Widget Configuration
|
||||||
|
---
|
||||||
|
|
||||||
|
[Backrest](https://garethgeorge.github.io/backrest/) is a web-based frontend for
|
||||||
|
the [Restic](https://restic.net/) backup tool.
|
||||||
|
|
||||||
|
**Allowed fields:** `["num_success_latest","num_failure_latest","num_success_30","num_plans","num_failure_30","bytes_added_30"]`
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
widget:
|
||||||
|
type: backrest
|
||||||
|
url: http://backrest.host.or.ip
|
||||||
|
username: admin # optional if auth is enabled in Backrest
|
||||||
|
password: admin # optional if auth is enabled in Backrest
|
||||||
|
```
|
||||||
@@ -9,7 +9,7 @@ The widget has two modes, a single system with detailed info if `systemId` is pr
|
|||||||
|
|
||||||
The `systemID` is the `id` field on the collections page of Beszel under the PocketBase admin panel. You can also use the 'nice name' from the Beszel UI.
|
The `systemID` is the `id` field on the collections page of Beszel under the PocketBase admin panel. You can also use the 'nice name' from the Beszel UI.
|
||||||
|
|
||||||
A "superuser" is currently required to access the data from tbe Beszel API.
|
A "superuser" is currently required to access the data from the Beszel API.
|
||||||
|
|
||||||
Allowed fields for 'overview' mode: `["systems", "up"]`
|
Allowed fields for 'overview' mode: `["systems", "up"]`
|
||||||
Allowed fields for a single system: `["name", "status", "updated", "cpu", "memory", "disk", "network"]`
|
Allowed fields for a single system: `["name", "status", "updated", "cpu", "memory", "disk", "network"]`
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
---
|
||||||
|
title: Booklore
|
||||||
|
description: Booklore Widget Configuration
|
||||||
|
---
|
||||||
|
|
||||||
|
Learn more about [Booklore](https://github.com/booklore-app/booklore).
|
||||||
|
|
||||||
|
The widget authenticates with your Booklore credentials to surface total libraries, books, and reading progress counts for your account.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
widget:
|
||||||
|
type: booklore
|
||||||
|
url: https://booklore.host.or.ip
|
||||||
|
username: username
|
||||||
|
password: password
|
||||||
|
```
|
||||||
@@ -22,6 +22,7 @@ widget:
|
|||||||
service_group: Media # group name where widget exists
|
service_group: Media # group name where widget exists
|
||||||
service_name: Sonarr # service name for that widget
|
service_name: Sonarr # service name for that widget
|
||||||
color: teal # optional - defaults to pre-defined color for the service (teal for sonarr)
|
color: teal # optional - defaults to pre-defined color for the service (teal for sonarr)
|
||||||
|
baseUrl: https://sonarr.domain.url # optional - adds links to sonarr/radarr pages
|
||||||
params: # optional - additional params for the service
|
params: # optional - additional params for the service
|
||||||
unmonitored: true # optional - defaults to false, used with *arr stack
|
unmonitored: true # optional - defaults to false, used with *arr stack
|
||||||
- type: ical # Show calendar events from another service
|
- type: ical # Show calendar events from another service
|
||||||
|
|||||||
@@ -8,6 +8,9 @@ Learn more about [Crowdsec](https://crowdsec.net).
|
|||||||
See the [crowdsec docs](https://docs.crowdsec.net/docs/local_api/intro/#machines) for information about registering a machine,
|
See the [crowdsec docs](https://docs.crowdsec.net/docs/local_api/intro/#machines) for information about registering a machine,
|
||||||
in most instances you can use the default credentials (`/etc/crowdsec/local_api_credentials.yaml`).
|
in most instances you can use the default credentials (`/etc/crowdsec/local_api_credentials.yaml`).
|
||||||
|
|
||||||
|
!!! note
|
||||||
|
Without the `limit24h` option, the widget will fetch all alerts which is limited to 100 by the API to avoid performance issues.
|
||||||
|
|
||||||
Allowed fields: `["alerts", "bans"]`.
|
Allowed fields: `["alerts", "bans"]`.
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
@@ -16,4 +19,5 @@ widget:
|
|||||||
url: http://crowdsechostorip:port
|
url: http://crowdsechostorip:port
|
||||||
username: localhost # machine_id in crowdsec
|
username: localhost # machine_id in crowdsec
|
||||||
password: password
|
password: password
|
||||||
|
limit24h: true # optional, limits alerts to last 24h. Default: false
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ To access these system metrics you need to connect to the DiskStation (`DSM`) wi
|
|||||||
3. Under the `User Groups` tab of the user config dialogue check the box for `Administrators`.
|
3. Under the `User Groups` tab of the user config dialogue check the box for `Administrators`.
|
||||||
4. On the `Permissions` tab check the top box for `No Access`, effectively prohibiting the user from accessing anything in the shared folders.
|
4. On the `Permissions` tab check the top box for `No Access`, effectively prohibiting the user from accessing anything in the shared folders.
|
||||||
5. Under `Applications` check the box next to `Deny` in the header to explicitly prohibit login to all applications.
|
5. Under `Applications` check the box next to `Deny` in the header to explicitly prohibit login to all applications.
|
||||||
6. Now _only_ allow login to the `DSM` application, either by
|
6. Now _only_ allow login to the `DSM` and `Download Station` applications, either by
|
||||||
- unchecking `Deny` in the respective row, or (if inheriting permission doesn't work because of other group settings)
|
- unchecking `Deny` in the respective row, or (if inheriting permission doesn't work because of other group settings)
|
||||||
- checking `Allow` for this app, or
|
- checking `Allow` for this app, or
|
||||||
- checking `By IP` for this app to limit the source of login attempts to one or more IP addresses/subnets.
|
- checking `By IP` for this app to limit the source of login attempts to one or more IP addresses/subnets.
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
---
|
||||||
|
title: Dispatcharr
|
||||||
|
description: Dispatcharr Widget Configuration
|
||||||
|
---
|
||||||
|
|
||||||
|
Learn more about [Dispatcharr](https://github.com/Dispatcharr/Dispatcharr).
|
||||||
|
|
||||||
|
Allowed fields: `["channels", "streams"]`.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
widget:
|
||||||
|
type: dispatcharr
|
||||||
|
url: http://dispatcharr.host.or.ip
|
||||||
|
username: username
|
||||||
|
password: password
|
||||||
|
enableActiveStreams: true # optional, defaults to false
|
||||||
|
```
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
---
|
||||||
|
title: Dockhand
|
||||||
|
description: Dockhand Widget Configuration
|
||||||
|
---
|
||||||
|
|
||||||
|
Learn more about [Dockhand](https://dockhand.pro/).
|
||||||
|
|
||||||
|
Note: The widget currently supports Dockhand's **local** authentication only.
|
||||||
|
|
||||||
|
**Allowed fields:** (max 4): `running`, `stopped`, `paused`, `total`, `cpu`, `memory`, `images`, `volumes`, `events_today`, `pending_updates`, `stacks`.
|
||||||
|
**Default fields:** `running`, `total`, `cpu`, `memory`.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
widget:
|
||||||
|
type: dockhand
|
||||||
|
url: http://localhost:3001
|
||||||
|
environment: local # optional: name or id; aggregates all when omitted
|
||||||
|
username: your-user # required for local auth
|
||||||
|
password: your-pass # required for local auth
|
||||||
|
```
|
||||||
@@ -17,6 +17,7 @@ widget:
|
|||||||
enableBlocks: true # optional, defaults to false
|
enableBlocks: true # optional, defaults to false
|
||||||
enableNowPlaying: true # optional, defaults to true
|
enableNowPlaying: true # optional, defaults to true
|
||||||
enableUser: true # optional, defaults to false
|
enableUser: true # optional, defaults to false
|
||||||
|
enableMediaControl: false # optional, defaults to true
|
||||||
showEpisodeNumber: true # optional, defaults to false
|
showEpisodeNumber: true # optional, defaults to false
|
||||||
expandOneStreamToTwoRows: false # optional, defaults to true
|
expandOneStreamToTwoRows: false # optional, defaults to true
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
---
|
||||||
|
title: Filebrowser
|
||||||
|
description: Filebrowser Widget Configuration
|
||||||
|
---
|
||||||
|
|
||||||
|
Learn more about [Filebrowser](https://filebrowser.org).
|
||||||
|
|
||||||
|
If you are using [Proxy header authentication](https://filebrowser.org/configuration/authentication-method#proxy-header) you have to set `authHeader` and `username`.
|
||||||
|
|
||||||
|
Allowed fields: `["available", "used", "total"]`.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
widget:
|
||||||
|
type: filebrowser
|
||||||
|
url: http://filebrowserhostorip:port
|
||||||
|
username: username
|
||||||
|
password: password
|
||||||
|
authHeader: X-My-Header # If using Proxy header authentication
|
||||||
|
```
|
||||||
@@ -14,4 +14,6 @@ widget:
|
|||||||
type: frigate
|
type: frigate
|
||||||
url: http://frigate.host.or.ip:port
|
url: http://frigate.host.or.ip:port
|
||||||
enableRecentEvents: true # Optional, defaults to false
|
enableRecentEvents: true # Optional, defaults to false
|
||||||
|
username: username # optional
|
||||||
|
password: password # optional
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ title: Gatus
|
|||||||
description: Gatus Widget Configuration
|
description: Gatus Widget Configuration
|
||||||
---
|
---
|
||||||
|
|
||||||
|
Learn more about [Gatus](https://github.com/TwiN/gatus).
|
||||||
|
|
||||||
Allowed fields: `["up", "down", "uptime"]`.
|
Allowed fields: `["up", "down", "uptime"]`.
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ See the [official docs](https://github.com/ghostfolio/ghostfolio#authorization-b
|
|||||||
|
|
||||||
_Note that the Bearer token is valid for 6 months, after which a new one must be generated._
|
_Note that the Bearer token is valid for 6 months, after which a new one must be generated._
|
||||||
|
|
||||||
Allowed fields: `["gross_percent_today", "gross_percent_1y", "gross_percent_max"]`
|
Allowed fields: `["gross_percent_today", "gross_percent_1y", "gross_percent_max", "net_worth"]`
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
widget:
|
widget:
|
||||||
|
|||||||
@@ -12,11 +12,17 @@ Learn more about [Gluetun](https://github.com/qdm12/gluetun).
|
|||||||
Allowed fields: `["public_ip", "region", "country", "port_forwarded"]`.
|
Allowed fields: `["public_ip", "region", "country", "port_forwarded"]`.
|
||||||
Default fields: `["public_ip", "region", "country"]`.
|
Default fields: `["public_ip", "region", "country"]`.
|
||||||
|
|
||||||
To setup authentication, follow [the official Gluetun documentation](https://github.com/qdm12/gluetun-wiki/blob/main/setup/advanced/control-server.md#authentication). Note that to use the api key method, you must add the route `GET /v1/publicip/ip` to the `routes` array in your Gluetun config.toml. Similarly, if you want to include the `port_forwarded` field, you must add the route `GET /v1/openvpn/portforwarded` to your Gluetun config.toml.
|
To setup authentication, follow [the official Gluetun documentation](https://github.com/qdm12/gluetun-wiki/blob/main/setup/advanced/control-server.md#authentication). Note that to use the api key method, you must add the route `GET /v1/publicip/ip` to the `routes` array in your Gluetun config.toml. Similarly, if you want to include the `port_forwarded` field, you must add the route `GET /v1/openvpn/portforwarded` (or `/v1/portforward`) to your Gluetun config.toml.
|
||||||
|
|
||||||
|
| Gluetun Version | Homepage Widget Version |
|
||||||
|
| --------------- | ----------------------- |
|
||||||
|
| < 3.40.1 | 1 (default) |
|
||||||
|
| >= 3.40.1 | 2 |
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
widget:
|
widget:
|
||||||
type: gluetun
|
type: gluetun
|
||||||
url: http://gluetun.host.or.ip:port
|
url: http://gluetun.host.or.ip:port
|
||||||
key: gluetunkey # Not required if /v1/publicip/ip endpoint is configured with `auth = none`
|
key: gluetunkey # Not required if /v1/publicip/ip endpoint is configured with `auth = none`
|
||||||
|
version: 2 # optional, default is 1
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -5,11 +5,18 @@ description: Grafana Widget Configuration
|
|||||||
|
|
||||||
Learn more about [Grafana](https://github.com/grafana/grafana).
|
Learn more about [Grafana](https://github.com/grafana/grafana).
|
||||||
|
|
||||||
|
| Grafana Version | Homepage Widget Version |
|
||||||
|
| --------------- | ----------------------- |
|
||||||
|
| <= v10.4 | 1 (default) |
|
||||||
|
| > v10.4 | 2 |
|
||||||
|
|
||||||
Allowed fields: `["dashboards", "datasources", "totalalerts", "alertstriggered"]`.
|
Allowed fields: `["dashboards", "datasources", "totalalerts", "alertstriggered"]`.
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
widget:
|
widget:
|
||||||
type: grafana
|
type: grafana
|
||||||
|
version: 2 # optional, default is 1
|
||||||
|
alerts: alertmanager # optional, default is grafana
|
||||||
url: http://grafana.host.or.ip:port
|
url: http://grafana.host.or.ip:port
|
||||||
username: username
|
username: username
|
||||||
password: password
|
password: password
|
||||||
|
|||||||
@@ -10,12 +10,11 @@ Learn more about [Immich](https://github.com/immich-app/immich).
|
|||||||
| < v1.118 | 1 (default) |
|
| < v1.118 | 1 (default) |
|
||||||
| >= v1.118 | 2 |
|
| >= v1.118 | 2 |
|
||||||
|
|
||||||
Find your API key under `Account Settings > API Keys`.
|
Find your API key under `Account Settings > API Keys`. The key should have the
|
||||||
|
`server.statistics` permission.
|
||||||
|
|
||||||
Allowed fields: `["users" ,"photos", "videos", "storage"]`.
|
Allowed fields: `["users" ,"photos", "videos", "storage"]`.
|
||||||
|
|
||||||
Note that API key must be from admin user.
|
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
widget:
|
widget:
|
||||||
type: immich
|
type: immich
|
||||||
|
|||||||
@@ -9,19 +9,23 @@ You can also find a list of all available service widgets in the sidebar navigat
|
|||||||
|
|
||||||
- [Adguard Home](adguard-home.md)
|
- [Adguard Home](adguard-home.md)
|
||||||
- [APC UPS](apcups.md)
|
- [APC UPS](apcups.md)
|
||||||
|
- [Arcane](arcane.md)
|
||||||
- [ArgoCD](argocd.md)
|
- [ArgoCD](argocd.md)
|
||||||
- [Atsumeru](atsumeru.md)
|
- [Atsumeru](atsumeru.md)
|
||||||
- [Audiobookshelf](audiobookshelf.md)
|
- [Audiobookshelf](audiobookshelf.md)
|
||||||
- [Authentik](authentik.md)
|
- [Authentik](authentik.md)
|
||||||
- [Autobrr](autobrr.md)
|
- [Autobrr](autobrr.md)
|
||||||
- [Azure DevOps](azuredevops.md)
|
- [Azure DevOps](azuredevops.md)
|
||||||
|
- [Backrest](backrest.md)
|
||||||
- [Bazarr](bazarr.md)
|
- [Bazarr](bazarr.md)
|
||||||
|
- [Booklore](booklore.md)
|
||||||
- [Beszel](beszel.md)
|
- [Beszel](beszel.md)
|
||||||
- [Caddy](caddy.md)
|
- [Caddy](caddy.md)
|
||||||
- [Calendar](calendar.md)
|
- [Calendar](calendar.md)
|
||||||
- [Calibre-Web](calibre-web.md)
|
- [Calibre-Web](calibre-web.md)
|
||||||
- [ChangeDetection.io](changedetectionio.md)
|
- [ChangeDetection.io](changedetectionio.md)
|
||||||
- [Channels DVR Server](channelsdvrserver.md)
|
- [Channels DVR Server](channelsdvrserver.md)
|
||||||
|
- [Checkmk](checkmk.md)
|
||||||
- [Cloudflared](cloudflared.md)
|
- [Cloudflared](cloudflared.md)
|
||||||
- [Coin Market Cap](coin-market-cap.md)
|
- [Coin Market Cap](coin-market-cap.md)
|
||||||
- [CrowdSec](crowdsec.md)
|
- [CrowdSec](crowdsec.md)
|
||||||
@@ -29,10 +33,13 @@ You can also find a list of all available service widgets in the sidebar navigat
|
|||||||
- [Deluge](deluge.md)
|
- [Deluge](deluge.md)
|
||||||
- [DeveLanCacheUI](develancacheui.md)
|
- [DeveLanCacheUI](develancacheui.md)
|
||||||
- [DiskStation](diskstation.md)
|
- [DiskStation](diskstation.md)
|
||||||
|
- [Dispatcharr](dispatcharr.md)
|
||||||
|
- [Dockhand](dockhand.md)
|
||||||
- [DownloadStation](downloadstation.md)
|
- [DownloadStation](downloadstation.md)
|
||||||
- [Emby](emby.md)
|
- [Emby](emby.md)
|
||||||
- [ESPHome](esphome.md)
|
- [ESPHome](esphome.md)
|
||||||
- [EVCC](evcc.md)
|
- [EVCC](evcc.md)
|
||||||
|
- [Filebrowser](filebrowser.md)
|
||||||
- [Fileflows](fileflows.md)
|
- [Fileflows](fileflows.md)
|
||||||
- [Firefly III](firefly.md)
|
- [Firefly III](firefly.md)
|
||||||
- [Flood](flood.md)
|
- [Flood](flood.md)
|
||||||
@@ -60,9 +67,11 @@ You can also find a list of all available service widgets in the sidebar navigat
|
|||||||
- [Jackett](jackett.md)
|
- [Jackett](jackett.md)
|
||||||
- [JDownloader](jdownloader.md)
|
- [JDownloader](jdownloader.md)
|
||||||
- [Jellyfin](jellyfin.md)
|
- [Jellyfin](jellyfin.md)
|
||||||
- [Jellyseerr](jellyseerr.md)
|
- [Seerr](seerr.md)
|
||||||
|
- [Jellystat](jellystat.md)
|
||||||
- [Kavita](kavita.md)
|
- [Kavita](kavita.md)
|
||||||
- [Komga](komga.md)
|
- [Komga](komga.md)
|
||||||
|
- [Komodo](komodo.md)
|
||||||
- [Kopia](kopia.md)
|
- [Kopia](kopia.md)
|
||||||
- [Lidarr](lidarr.md)
|
- [Lidarr](lidarr.md)
|
||||||
- [Linkwarden](linkwarden.md)
|
- [Linkwarden](linkwarden.md)
|
||||||
@@ -92,7 +101,6 @@ You can also find a list of all available service widgets in the sidebar navigat
|
|||||||
- [OpenMediaVault](openmediavault.md)
|
- [OpenMediaVault](openmediavault.md)
|
||||||
- [OpenWRT](openwrt.md)
|
- [OpenWRT](openwrt.md)
|
||||||
- [OPNsense](opnsense.md)
|
- [OPNsense](opnsense.md)
|
||||||
- [Overseerr](overseerr.md)
|
|
||||||
- [PaperlessNGX](paperlessngx.md)
|
- [PaperlessNGX](paperlessngx.md)
|
||||||
- [Peanut](peanut.md)
|
- [Peanut](peanut.md)
|
||||||
- [pfSense](pfsense.md)
|
- [pfSense](pfsense.md)
|
||||||
@@ -130,14 +138,17 @@ You can also find a list of all available service widgets in the sidebar navigat
|
|||||||
- [TDarr](tdarr.md)
|
- [TDarr](tdarr.md)
|
||||||
- [Traefik](traefik.md)
|
- [Traefik](traefik.md)
|
||||||
- [Transmission](transmission.md)
|
- [Transmission](transmission.md)
|
||||||
|
- [Trilium](trilium.md)
|
||||||
- [TrueNAS](truenas.md)
|
- [TrueNAS](truenas.md)
|
||||||
- [TubeArchivist](tubearchivist.md)
|
- [TubeArchivist](tubearchivist.md)
|
||||||
- [UniFi Controller](unifi-controller.md)
|
- [UniFi Controller](unifi-controller.md)
|
||||||
- [Unmanic](unmanic.md)
|
- [Unmanic](unmanic.md)
|
||||||
|
- [Unraid](unraid.md)
|
||||||
- [Uptime Kuma](uptime-kuma.md)
|
- [Uptime Kuma](uptime-kuma.md)
|
||||||
- [UptimeRobot](uptimerobot.md)
|
- [UptimeRobot](uptimerobot.md)
|
||||||
- [UrBackup](urbackup.md)
|
- [UrBackup](urbackup.md)
|
||||||
- [Vikunja](vikunja.md)
|
- [Vikunja](vikunja.md)
|
||||||
|
- [Wallos](wallos.md)
|
||||||
- [Watchtower](watchtower.md)
|
- [Watchtower](watchtower.md)
|
||||||
- [WGEasy](wgeasy.md)
|
- [WGEasy](wgeasy.md)
|
||||||
- [WhatsUpDocker](whatsupdocker.md)
|
- [WhatsUpDocker](whatsupdocker.md)
|
||||||
|
|||||||
@@ -5,18 +5,25 @@ description: Jellyfin Widget Configuration
|
|||||||
|
|
||||||
Learn more about [Jellyfin](https://github.com/jellyfin/jellyfin).
|
Learn more about [Jellyfin](https://github.com/jellyfin/jellyfin).
|
||||||
|
|
||||||
You can create an API key from inside Jellyfin at `Settings > Advanced > Api Keys`.
|
You can create an API key from inside the Jellyfin Administration Dashboard under `Advanced > API Keys`.
|
||||||
|
|
||||||
As of v0.6.11 the widget supports fields `["movies", "series", "episodes", "songs"]`. These blocks are disabled by default but can be enabled with the `enableBlocks` option, and the "Now Playing" feature (enabled by default) can be disabled with the `enableNowPlaying` option.
|
As of v0.6.11 the widget supports fields `["movies", "series", "episodes", "songs"]`. These blocks are disabled by default but can be enabled with the `enableBlocks` option, and the "Now Playing" feature (enabled by default) can be disabled with the `enableNowPlaying` option.
|
||||||
|
|
||||||
|
| Jellyfin Version | Homepage Widget Version |
|
||||||
|
| ---------------- | ----------------------- |
|
||||||
|
| < 10.12 | 1 (default) |
|
||||||
|
| >= 10.12 | 2 |
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
widget:
|
widget:
|
||||||
type: jellyfin
|
type: jellyfin
|
||||||
url: http://jellyfin.host.or.ip
|
url: http://jellyfin.host.or.ip:port
|
||||||
key: apikeyapikeyapikeyapikeyapikey
|
key: apikeyapikeyapikeyapikeyapikey
|
||||||
|
version: 2 # optional, default is 1
|
||||||
enableBlocks: true # optional, defaults to false
|
enableBlocks: true # optional, defaults to false
|
||||||
enableNowPlaying: true # optional, defaults to true
|
enableNowPlaying: true # optional, defaults to true
|
||||||
enableUser: true # optional, defaults to false
|
enableUser: true # optional, defaults to false
|
||||||
|
enableMediaControl: false # optional, defaults to true
|
||||||
showEpisodeNumber: true # optional, defaults to false
|
showEpisodeNumber: true # optional, defaults to false
|
||||||
expandOneStreamToTwoRows: false # optional, defaults to true
|
expandOneStreamToTwoRows: false # optional, defaults to true
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -1,17 +0,0 @@
|
|||||||
---
|
|
||||||
title: Jellyseerr
|
|
||||||
description: Jellyseerr Widget Configuration
|
|
||||||
---
|
|
||||||
|
|
||||||
Learn more about [Jellyseerr](https://github.com/Fallenbagel/jellyseerr).
|
|
||||||
|
|
||||||
Find your API key under `Settings > General > API Key`.
|
|
||||||
|
|
||||||
Allowed fields: `["pending", "approved", "available"]`.
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
widget:
|
|
||||||
type: jellyseerr
|
|
||||||
url: http://jellyseerr.host.or.ip
|
|
||||||
key: apikeyapikeyapikeyapikeyapikey
|
|
||||||
```
|
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
---
|
||||||
|
title: Komodo
|
||||||
|
description: Komodo Widget Configuration
|
||||||
|
---
|
||||||
|
|
||||||
|
This widget shows either details about all containers or stacks (if `showStacks` is true) managed by [Komodo](https://komo.do/) or the number of running servers, containers and stacks when `showSummary` is enabled.
|
||||||
|
|
||||||
|
The api key and secret can be found in the Komodo settings.
|
||||||
|
|
||||||
|
Allowed fields (max 4): `["total", "running", "stopped", "unhealthy", "unknown"]`.
|
||||||
|
Allowed fields with `showStacks` (max 4): `["total", "running", "down", "unhealthy", "unknown"]`.
|
||||||
|
Allowed fields with `showSummary`: `["servers", "stacks", "containers"]`.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
widget:
|
||||||
|
type: komodo
|
||||||
|
url: http://komodo.hostname.or.ip:port
|
||||||
|
key: K-xxxxxx...
|
||||||
|
secret: S-xxxxxx...
|
||||||
|
showSummary: true # optional, default: false. Takes precedence over showStacks
|
||||||
|
showStacks: true # optional, default: false
|
||||||
|
```
|
||||||
@@ -3,7 +3,7 @@ title: Mylar3
|
|||||||
description: Mylar3 Widget Configuration
|
description: Mylar3 Widget Configuration
|
||||||
---
|
---
|
||||||
|
|
||||||
Learn more about [Mylar3](https://github.com/mylar3/mylar3).
|
Learn more about [Mylar3](https://github.com/MylarComics/mylar3).
|
||||||
|
|
||||||
API must be enabled in Mylar3 settings.
|
API must be enabled in Mylar3 settings.
|
||||||
|
|
||||||
|
|||||||
@@ -9,11 +9,17 @@ _Note that the project was renamed from PiAlert to NetAlertX._
|
|||||||
|
|
||||||
Allowed fields: `["total", "connected", "new_devices", "down_alerts"]`.
|
Allowed fields: `["total", "connected", "new_devices", "down_alerts"]`.
|
||||||
|
|
||||||
If you have enabled a password on your NetAlertX instance, you will need to provide the `SYNC_api_token` as the `key` in your config.
|
Provide the `API_TOKEN` (f.k.a. `SYNC_api_token`) as the `key` in your config.
|
||||||
|
|
||||||
|
| NetAlertX Version | Homepage Widget Version |
|
||||||
|
| ----------------- | ----------------------- |
|
||||||
|
| < v26.1.17 | 1 (default) |
|
||||||
|
| > v26.1.17 | 2 |
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
widget:
|
widget:
|
||||||
type: netalertx
|
type: netalertx
|
||||||
url: http://ip:port
|
url: http://ip:port # use backend port for widget version 2+
|
||||||
key: netalertxsyncapitoken # optional, only if password is enabled
|
key: yournetalertxapitoken
|
||||||
|
version: 2 # optional, default is 1
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
---
|
||||||
|
title: ntfy
|
||||||
|
description: ntfy Widget Configuration
|
||||||
|
---
|
||||||
|
|
||||||
|
Learn more about [ntfy](https://github.com/binwiederhier/ntfy).
|
||||||
|
|
||||||
|
This widget shows the latest notification for a ntfy topic, including the title or body, priority level, and when it was received. Works with both self-hosted ntfy instances and the public [ntfy.sh](https://ntfy.sh) service.
|
||||||
|
|
||||||
|
Allowed fields: `["title", "message", "priority", "lastReceived", "tags"]`.
|
||||||
|
|
||||||
|
Default fields: `["title", "message", "priority", "lastReceived"]`.
|
||||||
|
|
||||||
|
If more than 4 fields are provided, only the first 4 are displayed.
|
||||||
|
|
||||||
|
## Authentication
|
||||||
|
|
||||||
|
ntfy supports both public and private topics. For private instances or access-controlled topics, you can authenticate using either a **Bearer token** (ntfy access token) or **Basic auth** (username/password).
|
||||||
|
|
||||||
|
| Auth Method | Config Fields | Notes |
|
||||||
|
| ------------ | ------------------------------ | --------------------------------- |
|
||||||
|
| None | _(omit key/username/password)_ | For public topics |
|
||||||
|
| Bearer token | `key` | ntfy access tokens (`tk_` prefix) |
|
||||||
|
| Basic auth | `username` + `password` | Username/password credentials |
|
||||||
|
|
||||||
|
See the [ntfy documentation](https://docs.ntfy.sh/config/#access-control) for details on access control.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
widget:
|
||||||
|
type: ntfy
|
||||||
|
url: http://ntfy.host.or.ip:port # required
|
||||||
|
topic: mytopic # required
|
||||||
|
# key: tk_accesstoken # optional — for token auth
|
||||||
|
# username: user # optional — for basic auth
|
||||||
|
# password: pass # optional — for basic auth
|
||||||
|
```
|
||||||
@@ -3,7 +3,7 @@ title: Omada
|
|||||||
description: Omada Widget Configuration
|
description: Omada Widget Configuration
|
||||||
---
|
---
|
||||||
|
|
||||||
The widget supports controller versions 3, 4 and 5.
|
The widget supports controller versions 3, 4, 5 and 6.
|
||||||
|
|
||||||
Allowed fields: `["connectedAp", "activeUser", "alerts", "connectedGateways", "connectedSwitches"]`.
|
Allowed fields: `["connectedAp", "activeUser", "alerts", "connectedGateways", "connectedSwitches"]`.
|
||||||
|
|
||||||
|
|||||||
@@ -1,17 +0,0 @@
|
|||||||
---
|
|
||||||
title: Overseerr
|
|
||||||
description: Overseerr Widget Configuration
|
|
||||||
---
|
|
||||||
|
|
||||||
Learn more about [Overseerr](https://github.com/sct/overseerr).
|
|
||||||
|
|
||||||
Find your API key under `Settings > General`.
|
|
||||||
|
|
||||||
Allowed fields: `["pending", "approved", "available", "processing"]`.
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
widget:
|
|
||||||
type: overseerr
|
|
||||||
url: http://overseerr.host.or.ip
|
|
||||||
key: apikeyapikeyapikeyapikeyapikey
|
|
||||||
```
|
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
---
|
||||||
|
title: Pangolin
|
||||||
|
description: Pangolin Widget Configuration
|
||||||
|
---
|
||||||
|
|
||||||
|
Learn more about [Pangolin](https://github.com/fosrl/pangolin).
|
||||||
|
|
||||||
|
This widget shows sites (online/total), resources (healthy/total), targets (healthy/total), and traffic statistics for a Pangolin organization. A resource is considered healthy if at least one of its targets is healthy, or if it has no targets.
|
||||||
|
|
||||||
|
Allowed fields: `["sites", "resources", "targets", "traffic", "in", "out"]` (maximum of 4).
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
widget:
|
||||||
|
type: pangolin
|
||||||
|
url: https://api.pangolin.net
|
||||||
|
key: your-api-key
|
||||||
|
org: your-org-id
|
||||||
|
```
|
||||||
|
|
||||||
|
Find your organization ID in the URL when logged in (e.g., `https://app.pangolin.net/{org-id}/...`).
|
||||||
|
|
||||||
|
## API Key Setup
|
||||||
|
|
||||||
|
Create an API key with the following permissions:
|
||||||
|
|
||||||
|
- **List Sites**
|
||||||
|
- **List Resources**
|
||||||
|
|
||||||
|
**Self-Hosted:** Enable the [Integration API](https://docs.pangolin.net/self-host/advanced/integration-api) in your Pangolin configuration before creating the key.
|
||||||
@@ -12,7 +12,7 @@ Allowed fields: no configurable fields for this widget.
|
|||||||
```yaml
|
```yaml
|
||||||
widget:
|
widget:
|
||||||
type: tautulli
|
type: tautulli
|
||||||
url: http://tautulli.host.or.ip
|
url: http://tautulli.host.or.ip:port
|
||||||
key: apikeyapikeyapikeyapikeyapikey
|
key: apikeyapikeyapikeyapikeyapikey
|
||||||
enableUser: true # optional, defaults to false
|
enableUser: true # optional, defaults to false
|
||||||
showEpisodeNumber: true # optional, defaults to false
|
showEpisodeNumber: true # optional, defaults to false
|
||||||
|
|||||||
@@ -7,12 +7,16 @@ Learn more about [Portainer](https://github.com/portainer/portainer).
|
|||||||
|
|
||||||
You'll need to make sure you have the correct environment set for the integration to work properly. From the Environments section inside of Portainer, click the one you'd like to connect to and observe the ID at the end of the URL (should be), something like `#!/endpoints/1`, here `1` is the value to set as the `env` value. In order to generate an API key, please follow the steps outlined here https://docs.portainer.io/api/access.
|
You'll need to make sure you have the correct environment set for the integration to work properly. From the Environments section inside of Portainer, click the one you'd like to connect to and observe the ID at the end of the URL (should be), something like `#!/endpoints/1`, here `1` is the value to set as the `env` value. In order to generate an API key, please follow the steps outlined here https://docs.portainer.io/api/access.
|
||||||
|
|
||||||
Allowed fields: `["running", "stopped", "total"]`.
|
Allowed fields:
|
||||||
|
|
||||||
|
- For Docker mode (default): `["running", "stopped", "total"]`
|
||||||
|
- For Kubernetes mode (`kubernetes: true`): `["applications", "services", "namespaces"]`
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
widget:
|
widget:
|
||||||
type: portainer
|
type: portainer
|
||||||
url: https://portainer.host.or.ip:9443
|
url: https://portainer.host.or.ip:9443
|
||||||
env: 1
|
env: 1
|
||||||
|
kubernetes: true # optional, defaults to false
|
||||||
key: ptr_accesskeyaccesskeyaccesskeyaccesskey
|
key: ptr_accesskeyaccesskeyaccesskeyaccesskey
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -7,34 +7,7 @@ Learn more about [Proxmox](https://www.proxmox.com/en/).
|
|||||||
|
|
||||||
This widget shows the running and total counts of both QEMU VMs and LX Containers in the Proxmox cluster. It also shows the CPU and memory usage of the first node in the cluster.
|
This widget shows the running and total counts of both QEMU VMs and LX Containers in the Proxmox cluster. It also shows the CPU and memory usage of the first node in the cluster.
|
||||||
|
|
||||||
You will need to generate an API Token for new or an existing user. Here is an example of how to do this for a new user.
|
See the [Proxmox configuration documentation](../../configs/proxmox.md#create-token) for details on creating API tokens.
|
||||||
|
|
||||||
1. Navigate to the Proxmox portal, click on Datacenter
|
|
||||||
2. Expand Permissions, click on Groups
|
|
||||||
3. Click the Create button
|
|
||||||
4. Name the group something informative, like api-ro-users
|
|
||||||
5. Click on the Permissions "folder"
|
|
||||||
6. Click Add -> Group Permission
|
|
||||||
- Path: /
|
|
||||||
- Group: group from bullet 4 above
|
|
||||||
- Role: PVEAuditor
|
|
||||||
- Propagate: Checked
|
|
||||||
7. Expand Permissions, click on Users
|
|
||||||
8. Click the Add button
|
|
||||||
- User name: something informative like `api`
|
|
||||||
- Realm: Linux PAM standard authentication
|
|
||||||
- Group: group from bullet 4 above
|
|
||||||
9. Expand Permissions, click on API Tokens
|
|
||||||
10. Click the Add button
|
|
||||||
- User: user from bullet 8 above
|
|
||||||
- Token ID: something informative like the application or purpose like `homepage`
|
|
||||||
- Privilege Separation: Checked
|
|
||||||
11. Go back to the "Permissions" menu
|
|
||||||
12. Click Add -> API Token Permission
|
|
||||||
- Path: /
|
|
||||||
- API Token: select the Token ID created in Step 10
|
|
||||||
- Role: PVE Auditor
|
|
||||||
- Propagate: Checked
|
|
||||||
|
|
||||||
Use `username@pam!Token ID` as the `username` (e.g `api@pam!homepage`) setting and `Secret` as the `password` setting.
|
Use `username@pam!Token ID` as the `username` (e.g `api@pam!homepage`) setting and `Secret` as the `password` setting.
|
||||||
|
|
||||||
|
|||||||
@@ -13,4 +13,5 @@ widget:
|
|||||||
url: http://pyload.host.or.ip:port
|
url: http://pyload.host.or.ip:port
|
||||||
username: username
|
username: username
|
||||||
password: password # only needed if set
|
password: password # only needed if set
|
||||||
|
key: pyloadapikey # only needed if set, takes precedence over username/password
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -16,4 +16,5 @@ widget:
|
|||||||
username: username
|
username: username
|
||||||
password: password
|
password: password
|
||||||
enableLeechProgress: true # optional, defaults to false
|
enableLeechProgress: true # optional, defaults to false
|
||||||
|
enableLeechSize: true # optional, defaults to false
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
---
|
||||||
|
title: Seerr Widget
|
||||||
|
description: Seerr Widget Configuration
|
||||||
|
---
|
||||||
|
|
||||||
|
Learn more about [Seerr](https://github.com/seerr-team/seerr).
|
||||||
|
|
||||||
|
Find your API key under `Settings > General > API Key`.
|
||||||
|
|
||||||
|
_Jellyseerr and Overseerr merged into Seerr. Use `type: seerr` (legacy `type: jellyseerr` and `type: overseerr` are aliased)._
|
||||||
|
|
||||||
|
Allowed fields: `["pending", "approved", "available", "completed", "processing", "issues"]`.
|
||||||
|
Default fields: `["pending", "approved", "completed"]`.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
widget:
|
||||||
|
type: seerr
|
||||||
|
url: http://seerr.host.or.ip
|
||||||
|
key: apikeyapikeyapikeyapikeyapikey
|
||||||
|
```
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
---
|
||||||
|
title: SparkyFitness
|
||||||
|
description: SparkyFitness Widget Configuration
|
||||||
|
---
|
||||||
|
|
||||||
|
Learn more about [SparkyFitness](https://github.com/CodeWithCJ/SparkyFitness).
|
||||||
|
|
||||||
|
Allowed fields: `["eaten", "burned", "remaining", "steps"]`.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
widget:
|
||||||
|
type: sparkyfitness
|
||||||
|
url: http://sparkyfitness.host.or.ip
|
||||||
|
key: apikeyapikeyapikeyapikeyapikey
|
||||||
|
```
|
||||||
@@ -9,7 +9,7 @@ You will need to generate an API access token from the [keys page](https://login
|
|||||||
|
|
||||||
To find your device ID, go to the [machine overview page](https://login.tailscale.com/admin/machines) and select your machine. In the "Machine Details" section, copy your `ID`. It will end with `CNTRL`.
|
To find your device ID, go to the [machine overview page](https://login.tailscale.com/admin/machines) and select your machine. In the "Machine Details" section, copy your `ID`. It will end with `CNTRL`.
|
||||||
|
|
||||||
Allowed fields: `["address", "last_seen", "expires"]`.
|
Allowed fields: `[ "address", "last_seen", "expires", "user", "hostname", "name", "client_version", "os", "created", "authorized", "is_external", "update_available", "tags" ]`.
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
widget:
|
widget:
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ widget:
|
|||||||
type: technitium
|
type: technitium
|
||||||
url: <url to dns server>
|
url: <url to dns server>
|
||||||
key: biglongapitoken
|
key: biglongapitoken
|
||||||
|
node: <node dns name or cluster> # optional, defaults to current node
|
||||||
range: LastDay # optional, defaults to LastHour
|
range: LastDay # optional, defaults to LastHour
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -21,6 +22,10 @@ widget:
|
|||||||
|
|
||||||
This can be generated via the Technitium DNS Dashboard, and should be generated from a special API specific user.
|
This can be generated via the Technitium DNS Dashboard, and should be generated from a special API specific user.
|
||||||
|
|
||||||
|
#### Node
|
||||||
|
|
||||||
|
`node` value determines which Technitium cluster node the statistics are returned for. Specifying a value of `cluster` returns aggregrate stats for all nodes in the cluster. Specify a node domain name to return specific node stats, no value returns stats for the node against which the API is executed.
|
||||||
|
|
||||||
#### Range
|
#### Range
|
||||||
|
|
||||||
`range` value determines how far back of statistics to pull data for. The value comes directly from Technitium API documentation found [here](https://github.com/TechnitiumSoftware/DnsServer/blob/master/APIDOCS.md#dashboard-api-calls), defined as `"type"`. The value can be one of: `LastHour`, `LastDay`, `LastWeek`, `LastMonth`, `LastYear`.
|
`range` value determines how far back of statistics to pull data for. The value comes directly from Technitium API documentation found [here](https://github.com/TechnitiumSoftware/DnsServer/blob/master/APIDOCS.md#dashboard-api-calls), defined as `"type"`. The value can be one of: `LastHour`, `LastDay`, `LastWeek`, `LastMonth`, `LastYear`.
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
---
|
||||||
|
title: Tracearr
|
||||||
|
description: Tracearr Widget Configuration
|
||||||
|
---
|
||||||
|
|
||||||
|
Learn more about [Tracearr](https://www.tracearr.com/).
|
||||||
|
|
||||||
|
Provides detailed information about currently active streams across multiple servers.
|
||||||
|
|
||||||
|
Allowed fields (for summary view): `["streams", "transcodes", "directplay", "bitrate"]`.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
widget:
|
||||||
|
type: tracearr
|
||||||
|
url: http://tracearr.host.or.ip:3000
|
||||||
|
key: apikeyapikeyapikeyapikeyapikey
|
||||||
|
view: both # optional, "summary", "details", or "both", defaults to "details"
|
||||||
|
enableUser: true # optional, defaults to false
|
||||||
|
showEpisodeNumber: true # optional, defaults to false
|
||||||
|
expandOneStreamToTwoRows: false # optional, defaults to true
|
||||||
|
```
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
---
|
||||||
|
title: Trilium
|
||||||
|
description: Trilium Widget Configuration
|
||||||
|
---
|
||||||
|
|
||||||
|
Learn more about [Trilium](https://github.com/TriliumNext/Notes).
|
||||||
|
|
||||||
|
This widget is compatible with [TriliumNext](https://github.com/TriliumNext/Notes) versions >= [v0.94.0](https://github.com/TriliumNext/Notes/releases/tag/v0.94.0).
|
||||||
|
|
||||||
|
Find (or create) your ETAPI key under `Options > ETAPI > Create new ETAPI token`.
|
||||||
|
|
||||||
|
Allowed fields: `["version", "notesCount", "dbSize"]`
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
widget:
|
||||||
|
type: trilium
|
||||||
|
url: https://trilium.host.or.ip
|
||||||
|
key: etapi_token
|
||||||
|
```
|
||||||
@@ -5,6 +5,11 @@ description: TrueNas Scale Widget Configuration
|
|||||||
|
|
||||||
Learn more about [TrueNas](https://www.truenas.com/).
|
Learn more about [TrueNas](https://www.truenas.com/).
|
||||||
|
|
||||||
|
| TrueNAS Version | Homepage widget version |
|
||||||
|
| ----------------------- | ----------------------- |
|
||||||
|
| < 26.04 (REST API) | 1 (default) |
|
||||||
|
| > 25.04 (Websocket API) | 2 |
|
||||||
|
|
||||||
Allowed fields: `["load", "uptime", "alerts"]`.
|
Allowed fields: `["load", "uptime", "alerts"]`.
|
||||||
|
|
||||||
To create an API Key, follow [the official TrueNAS documentation](https://www.truenas.com/docs/scale/scaletutorials/toptoolbar/managingapikeys/).
|
To create an API Key, follow [the official TrueNAS documentation](https://www.truenas.com/docs/scale/scaletutorials/toptoolbar/managingapikeys/).
|
||||||
@@ -17,6 +22,7 @@ To use the `enablePools` option with TrueNAS Core, the `nasType` parameter is re
|
|||||||
widget:
|
widget:
|
||||||
type: truenas
|
type: truenas
|
||||||
url: http://truenas.host.or.ip
|
url: http://truenas.host.or.ip
|
||||||
|
version: 2 # optional, defaults to 1
|
||||||
username: user # not required if using api key
|
username: user # not required if using api key
|
||||||
password: pass # not required if using api key
|
password: pass # not required if using api key
|
||||||
key: yourtruenasapikey # not required if using username / password
|
key: yourtruenasapikey # not required if using username / password
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ An optional 'site' parameter can be supplied, if it is not the widget will use t
|
|||||||
|
|
||||||
Allowed fields: `["uptime", "wan", "lan", "lan_users", "lan_devices", "wlan", "wlan_users", "wlan_devices"]` (maximum of four). Fields unsupported by the unifi device will not be shown.
|
Allowed fields: `["uptime", "wan", "lan", "lan_users", "lan_devices", "wlan", "wlan_users", "wlan_devices"]` (maximum of four). Fields unsupported by the unifi device will not be shown.
|
||||||
|
|
||||||
!!! hint
|
!!! tip
|
||||||
|
|
||||||
If you enter e.g. incorrect credentials and receive an "API Error", you may need to recreate the container or restart the service to clear the cache.
|
If you enter e.g. incorrect credentials and receive an "API Error", you may need to recreate the container or restart the service to clear the cache.
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
---
|
||||||
|
title: UniFi Drive
|
||||||
|
description: UniFi Drive Widget Configuration
|
||||||
|
---
|
||||||
|
|
||||||
|
Learn more about [UniFi Drive](https://ui.com/integrations/network-storage).
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
Displays storage statistics from your UniFi Network Attached Storage (UNAS) device. Requires a local UniFi account with at least read privileges.
|
||||||
|
|
||||||
|
Allowed fields: `["total", "used", "available", "status"]`
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
widget:
|
||||||
|
type: unifi_drive
|
||||||
|
url: https://unifi.host.or.ip
|
||||||
|
username: your_username
|
||||||
|
password: your_password
|
||||||
|
```
|
||||||
|
|
||||||
|
!!! tip
|
||||||
|
|
||||||
|
If you enter incorrect credentials and receive an "API Error", you may need to recreate the container or restart the service to clear the cache.
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
---
|
||||||
|
title: Unraid
|
||||||
|
description: Unraid Widget Configuration
|
||||||
|
---
|
||||||
|
|
||||||
|
Learn more about [Unraid](https://unraid.net/).
|
||||||
|
|
||||||
|
The Unraid widget allows you to monitor the resources of an Unraid server.
|
||||||
|
|
||||||
|
**Minimum Requirements:**
|
||||||
|
|
||||||
|
- Unraid 7.2 -or- Unraid Connect plugin 2025.08.19.1850
|
||||||
|
- API key with the **ADMIN** role: [Managing API Keys](https://docs.unraid.net/go/managing-api-keys)
|
||||||
|
|
||||||
|
The widget can display metrics for selected Unraid pools. If using one of the "pool" fields, you must also add the pool name to the settings.
|
||||||
|
|
||||||
|
**Allowed fields:** `["cpu","memoryPercent","memoryAvailable","memoryUsed","notifications","arrayFree","arrayUsedSpace","arrayUsedPercent","status","pool1UsedSpace","pool1FreeSpace","pool1UsedPercent","pool2UsedSpace","pool2FreeSpace","pool2UsedPercent","pool3UsedSpace","pool3FreeSpace","pool3UsedPercent","pool4UsedSpace","pool4FreeSpace","pool4UsedPercent"]`
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
widget:
|
||||||
|
type: unraid
|
||||||
|
url: https://unraid.host.or.ip
|
||||||
|
key: api-key
|
||||||
|
pool1: pool1name # required only if using pool1 fields
|
||||||
|
pool2: pool2name # required only if using pool2 fields
|
||||||
|
pool3: pool3name # required only if using pool3 fields
|
||||||
|
pool4: pool4name # required only if using pool4 fields
|
||||||
|
```
|
||||||
@@ -9,10 +9,16 @@ Allowed fields: `["projects", "tasks7d", "tasksOverdue", "tasksInProgress"]`.
|
|||||||
|
|
||||||
A list of the next 5 tasks ordered by due date is disabled by default, but can be enabled with the `enableTaskList` option.
|
A list of the next 5 tasks ordered by due date is disabled by default, but can be enabled with the `enableTaskList` option.
|
||||||
|
|
||||||
|
| Vikunja Version | Homepage Widget Version |
|
||||||
|
| --------------- | ----------------------- |
|
||||||
|
| < v1.0.0-rc4 | 1 (default) |
|
||||||
|
| >= v1.0.0-rc4 | 2 |
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
widget:
|
widget:
|
||||||
type: vikunja
|
type: vikunja
|
||||||
url: http[s]://vikunja.host.or.ip[:port]
|
url: http[s]://vikunja.host.or.ip[:port]
|
||||||
key: vikunjaapikey
|
key: vikunjaapikey
|
||||||
enableTaskList: true # optional, defaults to false
|
enableTaskList: true # optional, defaults to false
|
||||||
|
version: 2 # optional, defaults to 1
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
---
|
||||||
|
title: Wallos
|
||||||
|
description: Wallos Widget Configuration
|
||||||
|
---
|
||||||
|
|
||||||
|
Learn more about [Wallos](https://github.com/ellite/wallos).
|
||||||
|
|
||||||
|
If you're using more than one currency to record subscriptions then you should also have your "Fixer API" key set-up (`Settings > Fixer API Key`).
|
||||||
|
|
||||||
|
> **Please Note:** The monthly cost displayed is the total cost of subscriptions in that month, **not** the _"monthly"_ average cost.
|
||||||
|
|
||||||
|
Get your API key under `Profile > API Key`.
|
||||||
|
|
||||||
|
Allowed fields: `["activeSubscriptions", "nextRenewingSubscription", "previousMonthlyCost", "thisMonthlyCost", "nextMonthlyCost"]`.
|
||||||
|
|
||||||
|
Default fields: `["activeSubscriptions", "nextRenewingSubscription", "thisMonthlyCost", "nextMonthlyCost"]`.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
widget:
|
||||||
|
type: wallos
|
||||||
|
url: http://wallos.host.or.ip
|
||||||
|
key: apikeyapikeyapikeyapikeyapikey
|
||||||
|
```
|
||||||
@@ -3,9 +3,9 @@ title: Watchtower
|
|||||||
description: Watchtower Widget Configuration
|
description: Watchtower Widget Configuration
|
||||||
---
|
---
|
||||||
|
|
||||||
Learn more about [Watchtower](https://github.com/containrrr/watchtower).
|
Learn more about [Watchtower](https://github.com/nicholas-fedor/watchtower).
|
||||||
|
|
||||||
To use this widget, Watchtower needs to be configured to [enable metrics](https://containrrr.dev/watchtower/metrics/).
|
To use this widget, Watchtower needs to be configured to [enable metrics](https://watchtower.nickfedor.com/dev/advanced-features/metrics-api/).
|
||||||
|
|
||||||
Allowed fields: `["containers_scanned", "containers_updated", "containers_failed"]`.
|
Allowed fields: `["containers_scanned", "containers_updated", "containers_failed"]`.
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
---
|
||||||
|
title: Your Spotify
|
||||||
|
description: Your Spotify Widget Configuration
|
||||||
|
---
|
||||||
|
|
||||||
|
Learn more about [Your Spotify](https://github.com/Yooooomi/your_spotify).
|
||||||
|
|
||||||
|
Find your API key under `Settings > Account > Public token`, click `Generate` if not yet generated, copy key after
|
||||||
|
`?token=`.
|
||||||
|
|
||||||
|
Allowed fields: `["songs", "time", "artists"]`.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
widget:
|
||||||
|
type: yourspotify
|
||||||
|
url: http://your-spotify-server.host.or.ip # if using lsio image, add /api/
|
||||||
|
key: apikeyapikeyapikeyapikeyapikey
|
||||||
|
interval: month # optional, defaults to week
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Interval
|
||||||
|
|
||||||
|
Allowed values for `interval`: `day`, `week`, `month`, `year`, `all`.
|
||||||
|
|
||||||
|
!!! note
|
||||||
|
|
||||||
|
`interval` is different from predefined intervals you see in `Your Spotify`'s UI.
|
||||||
|
For example, `This week` in UI means _from the start of this week_, here `week` means _past 7 days_.
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
import path from "node:path";
|
||||||
|
import { fileURLToPath } from "node:url";
|
||||||
|
|
||||||
|
import { fixupConfigRules } from "@eslint/compat";
|
||||||
|
import { FlatCompat } from "@eslint/eslintrc";
|
||||||
|
import js from "@eslint/js";
|
||||||
|
import prettier from "eslint-plugin-prettier";
|
||||||
|
import { defineConfig, globalIgnores } from "eslint/config";
|
||||||
|
|
||||||
|
const __filename = fileURLToPath(import.meta.url);
|
||||||
|
const __dirname = path.dirname(__filename);
|
||||||
|
const compat = new FlatCompat({
|
||||||
|
baseDirectory: __dirname,
|
||||||
|
recommendedConfig: js.configs.recommended,
|
||||||
|
allConfig: js.configs.all,
|
||||||
|
});
|
||||||
|
|
||||||
|
export default defineConfig([
|
||||||
|
{
|
||||||
|
extends: fixupConfigRules(compat.extends("next/core-web-vitals", "prettier", "plugin:react-hooks/recommended")),
|
||||||
|
|
||||||
|
plugins: {
|
||||||
|
prettier,
|
||||||
|
},
|
||||||
|
|
||||||
|
languageOptions: {
|
||||||
|
ecmaVersion: 6,
|
||||||
|
sourceType: "module",
|
||||||
|
|
||||||
|
parserOptions: {
|
||||||
|
ecmaFeatures: {
|
||||||
|
modules: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
settings: {
|
||||||
|
"import/resolver": {
|
||||||
|
node: {
|
||||||
|
paths: ["src"],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
rules: {
|
||||||
|
"import/no-cycle": [
|
||||||
|
"error",
|
||||||
|
{
|
||||||
|
maxDepth: 1,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
"import/order": [
|
||||||
|
"error",
|
||||||
|
{
|
||||||
|
"newlines-between": "always",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
"no-else-return": [
|
||||||
|
"error",
|
||||||
|
{
|
||||||
|
allowElseIf: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// Vitest tests often intentionally place imports after `vi.mock(...)` to ensure
|
||||||
|
// modules under test see the mocked dependencies. `import/order` can't safely
|
||||||
|
// auto-fix those cases, so disable it for test files.
|
||||||
|
{
|
||||||
|
files: ["src/**/*.test.{js,jsx}", "src/**/*.spec.{js,jsx}"],
|
||||||
|
rules: {
|
||||||
|
"import/order": "off",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
globalIgnores(["./config/", "./coverage/", "./.venv/", "./.next/", "./site/"]),
|
||||||
|
]);
|
||||||
+3
-3
@@ -20,13 +20,13 @@ helm install my-release jameswynn/homepage
|
|||||||
Set the `mode` in the `kubernetes.yaml` to `cluster`.
|
Set the `mode` in the `kubernetes.yaml` to `cluster`.
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
mode: default
|
mode: cluster
|
||||||
```
|
```
|
||||||
|
|
||||||
To enable Kubernetes gateway-api compatibility, set `route` to `gateway`.
|
To enable Kubernetes gateway-api compatibility, set `gateway` to `true`.
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
route: gateway
|
gateway: true
|
||||||
```
|
```
|
||||||
|
|
||||||
## Widgets
|
## Widgets
|
||||||
|
|||||||
+21
-2
@@ -25,6 +25,7 @@ nav:
|
|||||||
- configs/services.md
|
- configs/services.md
|
||||||
- configs/kubernetes.md
|
- configs/kubernetes.md
|
||||||
- configs/docker.md
|
- configs/docker.md
|
||||||
|
- configs/proxmox.md
|
||||||
- configs/custom-css-js.md
|
- configs/custom-css-js.md
|
||||||
- "Widgets":
|
- "Widgets":
|
||||||
- widgets/index.md
|
- widgets/index.md
|
||||||
@@ -32,19 +33,23 @@ nav:
|
|||||||
- widgets/services/index.md
|
- widgets/services/index.md
|
||||||
- widgets/services/adguard-home.md
|
- widgets/services/adguard-home.md
|
||||||
- widgets/services/apcups.md
|
- widgets/services/apcups.md
|
||||||
|
- widgets/services/arcane.md
|
||||||
- widgets/services/argocd.md
|
- widgets/services/argocd.md
|
||||||
- widgets/services/atsumeru.md
|
- widgets/services/atsumeru.md
|
||||||
- widgets/services/audiobookshelf.md
|
- widgets/services/audiobookshelf.md
|
||||||
- widgets/services/authentik.md
|
- widgets/services/authentik.md
|
||||||
- widgets/services/autobrr.md
|
- widgets/services/autobrr.md
|
||||||
- widgets/services/azuredevops.md
|
- widgets/services/azuredevops.md
|
||||||
|
- widgets/services/backrest.md
|
||||||
- widgets/services/bazarr.md
|
- widgets/services/bazarr.md
|
||||||
|
- widgets/services/booklore.md
|
||||||
- widgets/services/beszel.md
|
- widgets/services/beszel.md
|
||||||
- widgets/services/caddy.md
|
- widgets/services/caddy.md
|
||||||
- widgets/services/calendar.md
|
- widgets/services/calendar.md
|
||||||
- widgets/services/calibre-web.md
|
- widgets/services/calibre-web.md
|
||||||
- widgets/services/changedetectionio.md
|
- widgets/services/changedetectionio.md
|
||||||
- widgets/services/channelsdvrserver.md
|
- widgets/services/channelsdvrserver.md
|
||||||
|
- widgets/services/checkmk.md
|
||||||
- widgets/services/cloudflared.md
|
- widgets/services/cloudflared.md
|
||||||
- widgets/services/coin-market-cap.md
|
- widgets/services/coin-market-cap.md
|
||||||
- widgets/services/crowdsec.md
|
- widgets/services/crowdsec.md
|
||||||
@@ -52,10 +57,13 @@ nav:
|
|||||||
- widgets/services/deluge.md
|
- widgets/services/deluge.md
|
||||||
- widgets/services/develancacheui.md
|
- widgets/services/develancacheui.md
|
||||||
- widgets/services/diskstation.md
|
- widgets/services/diskstation.md
|
||||||
|
- widgets/services/dispatcharr.md
|
||||||
|
- widgets/services/dockhand.md
|
||||||
- widgets/services/downloadstation.md
|
- widgets/services/downloadstation.md
|
||||||
- widgets/services/emby.md
|
- widgets/services/emby.md
|
||||||
- widgets/services/esphome.md
|
- widgets/services/esphome.md
|
||||||
- widgets/services/evcc.md
|
- widgets/services/evcc.md
|
||||||
|
- widgets/services/filebrowser.md
|
||||||
- widgets/services/fileflows.md
|
- widgets/services/fileflows.md
|
||||||
- widgets/services/firefly.md
|
- widgets/services/firefly.md
|
||||||
- widgets/services/flood.md
|
- widgets/services/flood.md
|
||||||
@@ -83,9 +91,10 @@ nav:
|
|||||||
- widgets/services/jackett.md
|
- widgets/services/jackett.md
|
||||||
- widgets/services/jdownloader.md
|
- widgets/services/jdownloader.md
|
||||||
- widgets/services/jellyfin.md
|
- widgets/services/jellyfin.md
|
||||||
- widgets/services/jellyseerr.md
|
- widgets/services/jellystat.md
|
||||||
- widgets/services/kavita.md
|
- widgets/services/kavita.md
|
||||||
- widgets/services/komga.md
|
- widgets/services/komga.md
|
||||||
|
- widgets/services/komodo.md
|
||||||
- widgets/services/kopia.md
|
- widgets/services/kopia.md
|
||||||
- widgets/services/lidarr.md
|
- widgets/services/lidarr.md
|
||||||
- widgets/services/linkwarden.md
|
- widgets/services/linkwarden.md
|
||||||
@@ -107,6 +116,7 @@ nav:
|
|||||||
- widgets/services/nextcloud.md
|
- widgets/services/nextcloud.md
|
||||||
- widgets/services/nextdns.md
|
- widgets/services/nextdns.md
|
||||||
- widgets/services/nginx-proxy-manager.md
|
- widgets/services/nginx-proxy-manager.md
|
||||||
|
- widgets/services/ntfy.md
|
||||||
- widgets/services/nzbget.md
|
- widgets/services/nzbget.md
|
||||||
- widgets/services/octoprint.md
|
- widgets/services/octoprint.md
|
||||||
- widgets/services/omada.md
|
- widgets/services/omada.md
|
||||||
@@ -115,7 +125,7 @@ nav:
|
|||||||
- widgets/services/openmediavault.md
|
- widgets/services/openmediavault.md
|
||||||
- widgets/services/opnsense.md
|
- widgets/services/opnsense.md
|
||||||
- widgets/services/openwrt.md
|
- widgets/services/openwrt.md
|
||||||
- widgets/services/overseerr.md
|
- widgets/services/pangolin.md
|
||||||
- widgets/services/paperlessngx.md
|
- widgets/services/paperlessngx.md
|
||||||
- widgets/services/peanut.md
|
- widgets/services/peanut.md
|
||||||
- widgets/services/pfsense.md
|
- widgets/services/pfsense.md
|
||||||
@@ -140,7 +150,10 @@ nav:
|
|||||||
- widgets/services/rutorrent.md
|
- widgets/services/rutorrent.md
|
||||||
- widgets/services/sabnzbd.md
|
- widgets/services/sabnzbd.md
|
||||||
- widgets/services/scrutiny.md
|
- widgets/services/scrutiny.md
|
||||||
|
- widgets/services/seerr.md
|
||||||
|
- widgets/services/slskd.md
|
||||||
- widgets/services/sonarr.md
|
- widgets/services/sonarr.md
|
||||||
|
- widgets/services/sparkyfitness.md
|
||||||
- widgets/services/speedtest-tracker.md
|
- widgets/services/speedtest-tracker.md
|
||||||
- widgets/services/spoolman.md
|
- widgets/services/spoolman.md
|
||||||
- widgets/services/stash.md
|
- widgets/services/stash.md
|
||||||
@@ -153,19 +166,25 @@ nav:
|
|||||||
- widgets/services/technitium.md
|
- widgets/services/technitium.md
|
||||||
- widgets/services/tdarr.md
|
- widgets/services/tdarr.md
|
||||||
- widgets/services/traefik.md
|
- widgets/services/traefik.md
|
||||||
|
- widgets/services/tracearr.md
|
||||||
- widgets/services/transmission.md
|
- widgets/services/transmission.md
|
||||||
|
- widgets/services/trilium.md
|
||||||
- widgets/services/truenas.md
|
- widgets/services/truenas.md
|
||||||
- widgets/services/tubearchivist.md
|
- widgets/services/tubearchivist.md
|
||||||
- widgets/services/unifi-controller.md
|
- widgets/services/unifi-controller.md
|
||||||
|
- widgets/services/unifi-drive.md
|
||||||
- widgets/services/unmanic.md
|
- widgets/services/unmanic.md
|
||||||
|
- widgets/services/unraid.md
|
||||||
- widgets/services/uptime-kuma.md
|
- widgets/services/uptime-kuma.md
|
||||||
- widgets/services/uptimerobot.md
|
- widgets/services/uptimerobot.md
|
||||||
- widgets/services/urbackup.md
|
- widgets/services/urbackup.md
|
||||||
- widgets/services/vikunja.md
|
- widgets/services/vikunja.md
|
||||||
|
- widgets/services/wallos.md
|
||||||
- widgets/services/watchtower.md
|
- widgets/services/watchtower.md
|
||||||
- widgets/services/wgeasy.md
|
- widgets/services/wgeasy.md
|
||||||
- widgets/services/whatsupdocker.md
|
- widgets/services/whatsupdocker.md
|
||||||
- widgets/services/xteve.md
|
- widgets/services/xteve.md
|
||||||
|
- widgets/services/yourspotify.md
|
||||||
- widgets/services/zabbix.md
|
- widgets/services/zabbix.md
|
||||||
- "Information Widgets":
|
- "Information Widgets":
|
||||||
- widgets/info/index.md
|
- widgets/info/index.md
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
// prettyBytes taken from https://github.com/sindresorhus/pretty-bytes
|
// prettyBytes taken from https://github.com/sindresorhus/pretty-bytes
|
||||||
|
|
||||||
/* eslint-disable no-param-reassign */
|
|
||||||
const BYTE_UNITS = ["B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
|
const BYTE_UNITS = ["B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
|
||||||
|
|
||||||
const BIBYTE_UNITS = ["B", "kiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"];
|
const BIBYTE_UNITS = ["B", "kiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"];
|
||||||
@@ -37,7 +36,6 @@ function prettyBytes(number, options) {
|
|||||||
...options,
|
...options,
|
||||||
};
|
};
|
||||||
|
|
||||||
// eslint-disable-next-line no-nested-ternary
|
|
||||||
const UNITS = options.bits ? (options.binary ? BIBIT_UNITS : BIT_UNITS) : options.binary ? BIBYTE_UNITS : BYTE_UNITS;
|
const UNITS = options.bits ? (options.binary ? BIBIT_UNITS : BIT_UNITS) : options.binary ? BIBYTE_UNITS : BYTE_UNITS;
|
||||||
|
|
||||||
if (options.signed && number === 0) {
|
if (options.signed && number === 0) {
|
||||||
@@ -45,7 +43,7 @@ function prettyBytes(number, options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const isNegative = number < 0;
|
const isNegative = number < 0;
|
||||||
// eslint-disable-next-line no-nested-ternary
|
|
||||||
const prefix = isNegative ? "-" : options.signed ? "+" : "";
|
const prefix = isNegative ? "-" : options.signed ? "+" : "";
|
||||||
|
|
||||||
if (isNegative) {
|
if (isNegative) {
|
||||||
|
|||||||
+6
-1
@@ -5,7 +5,12 @@ const nextConfig = {
|
|||||||
reactStrictMode: true,
|
reactStrictMode: true,
|
||||||
output: "standalone",
|
output: "standalone",
|
||||||
images: {
|
images: {
|
||||||
domains: ["cdn.jsdelivr.net"],
|
remotePatterns: [
|
||||||
|
{
|
||||||
|
protocol: "https",
|
||||||
|
hostname: "cdn.jsdelivr.net",
|
||||||
|
},
|
||||||
|
],
|
||||||
unoptimized: true,
|
unoptimized: true,
|
||||||
},
|
},
|
||||||
i18n,
|
i18n,
|
||||||
|
|||||||
+51
-44
@@ -1,71 +1,78 @@
|
|||||||
{
|
{
|
||||||
"name": "homepage",
|
"name": "homepage",
|
||||||
"version": "1.3.1",
|
"version": "1.13.1",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"preinstall": "npx only-allow pnpm",
|
"preinstall": "npx only-allow pnpm",
|
||||||
"dev": "next dev",
|
"dev": "next dev",
|
||||||
"build": "next build",
|
"build": "next build --webpack",
|
||||||
"start": "next start",
|
"start": "next start",
|
||||||
"lint": "next lint",
|
"lint": "eslint .",
|
||||||
|
"test": "vitest run",
|
||||||
|
"test:coverage": "vitest run --coverage",
|
||||||
|
"test:watch": "vitest",
|
||||||
"telemetry": "next telemetry disable"
|
"telemetry": "next telemetry disable"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@headlessui/react": "^1.7.19",
|
"@headlessui/react": "^2.2.10",
|
||||||
"@kubernetes/client-node": "^1.0.0",
|
"@kubernetes/client-node": "^1.0.0",
|
||||||
"classnames": "^2.5.1",
|
"classnames": "^2.5.1",
|
||||||
"compare-versions": "^6.1.1",
|
"compare-versions": "^6.1.1",
|
||||||
"dockerode": "^4.0.4",
|
"dockerode": "^4.0.10",
|
||||||
"follow-redirects": "^1.15.9",
|
"follow-redirects": "^1.16.0",
|
||||||
"gamedig": "^5.2.0",
|
"gamedig": "^5.3.2",
|
||||||
"i18next": "^24.2.3",
|
"i18next": "^25.10.9",
|
||||||
"ical.js": "^2.1.0",
|
"ical.js": "^2.2.1",
|
||||||
"js-yaml": "^4.1.0",
|
"js-yaml": "^4.1.1",
|
||||||
"json-rpc-2.0": "^1.7.0",
|
"json-rpc-2.0": "^1.7.1",
|
||||||
"luxon": "^3.5.0",
|
"luxon": "^3.6.1",
|
||||||
"memory-cache": "^0.2.0",
|
"memory-cache": "^0.2.0",
|
||||||
"minecraftstatuspinger": "^1.2.2",
|
"minecraftstatuspinger": "^1.2.2",
|
||||||
"next": "^15.3.1",
|
"next": "^16.2.4",
|
||||||
"next-i18next": "^12.1.0",
|
"next-i18next": "^15.4.3",
|
||||||
"ping": "^0.4.4",
|
"ping": "^0.4.4",
|
||||||
"pretty-bytes": "^6.1.1",
|
"pretty-bytes": "^7.1.0",
|
||||||
"raw-body": "^3.0.0",
|
"raw-body": "^3.0.2",
|
||||||
"react": "^18.3.1",
|
"react": "^19.2.5",
|
||||||
"react-dom": "^18.3.1",
|
"react-dom": "^19.2.5",
|
||||||
"react-i18next": "^11.18.6",
|
"react-i18next": "^15.5.3",
|
||||||
"react-icons": "^5.4.0",
|
"react-icons": "^5.6.0",
|
||||||
"recharts": "^2.15.3",
|
"recharts": "^3.1.2",
|
||||||
"swr": "^2.3.3",
|
"swr": "^2.4.1",
|
||||||
"systeminformation": "^5.25.11",
|
"systeminformation": "^5.30.8",
|
||||||
"tough-cookie": "^5.1.2",
|
"tough-cookie": "^6.0.0",
|
||||||
"urbackup-server-api": "^0.8.9",
|
"urbackup-server-api": "^0.92.2",
|
||||||
"winston": "^3.17.0",
|
"winston": "^3.19.0",
|
||||||
|
"ws": "^8.18.3",
|
||||||
"xml-js": "^1.6.11"
|
"xml-js": "^1.6.11"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@tailwindcss/forms": "^0.5.10",
|
"@eslint/compat": "^2.0.3",
|
||||||
"@tailwindcss/postcss": "^4.0.9",
|
"@eslint/eslintrc": "^3.3.3",
|
||||||
|
"@eslint/js": "^9.39.4",
|
||||||
|
"@tailwindcss/forms": "^0.5.11",
|
||||||
|
"@tailwindcss/postcss": "^4.1.18",
|
||||||
|
"@testing-library/jest-dom": "^6.8.0",
|
||||||
|
"@testing-library/react": "^16.3.0",
|
||||||
|
"@vitest/coverage-v8": "^3.2.4",
|
||||||
"eslint": "^9.25.1",
|
"eslint": "^9.25.1",
|
||||||
"eslint-config-next": "^15.2.4",
|
"eslint-config-next": "^15.5.11",
|
||||||
"eslint-config-prettier": "^10.1.1",
|
"eslint-config-prettier": "^10.1.8",
|
||||||
"eslint-plugin-import": "^2.31.0",
|
"eslint-plugin-import": "^2.32.0",
|
||||||
"eslint-plugin-jsx-a11y": "^6.10.2",
|
"eslint-plugin-jsx-a11y": "^6.10.2",
|
||||||
"eslint-plugin-prettier": "^5.2.6",
|
"eslint-plugin-prettier": "^5.5.5",
|
||||||
"eslint-plugin-react": "^7.37.4",
|
"eslint-plugin-react": "^7.37.4",
|
||||||
"eslint-plugin-react-hooks": "^5.1.0",
|
"eslint-plugin-react-hooks": "^5.2.0",
|
||||||
"postcss": "^8.5.3",
|
"jsdom": "^28.1.0",
|
||||||
"prettier": "^3.5.2",
|
"postcss": "^8.5.10",
|
||||||
"prettier-plugin-organize-imports": "^4.1.0",
|
"prettier": "^3.8.1",
|
||||||
"tailwind-scrollbar": "^4.0.1",
|
"prettier-plugin-organize-imports": "^4.3.0",
|
||||||
"tailwindcss": "^4.0.9",
|
"tailwind-scrollbar": "^4.0.2",
|
||||||
"typescript": "^5.7.3"
|
"tailwindcss": "^4.1.18",
|
||||||
|
"typescript": "^5.7.3",
|
||||||
|
"vitest": "^3.2.4"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"osx-temperature-sensor": "^1.0.8"
|
"osx-temperature-sensor": "^1.0.8"
|
||||||
},
|
|
||||||
"pnpm": {
|
|
||||||
"onlyBuiltDependencies": [
|
|
||||||
"sharp"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Generated
+3063
-1104
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,18 @@
|
|||||||
|
packages:
|
||||||
|
- .
|
||||||
|
|
||||||
|
allowBuilds:
|
||||||
|
'@tailwindcss/oxide': true
|
||||||
|
core-js: false
|
||||||
|
cpu-features: false
|
||||||
|
esbuild: false
|
||||||
|
osx-temperature-sensor: true
|
||||||
|
protobufjs: false
|
||||||
|
sharp: true
|
||||||
|
ssh2: false
|
||||||
|
|
||||||
|
onlyBuiltDependencies:
|
||||||
|
- '@tailwindcss/oxide'
|
||||||
|
- osx-temperature-sensor
|
||||||
|
- protobufjs
|
||||||
|
- sharp
|
||||||
+190
-34
@@ -66,6 +66,11 @@
|
|||||||
"wait": "Wag asseblief",
|
"wait": "Wag asseblief",
|
||||||
"empty_data": "Substelsel status onbekend"
|
"empty_data": "Substelsel status onbekend"
|
||||||
},
|
},
|
||||||
|
"unifi_drive": {
|
||||||
|
"healthy": "Gesond",
|
||||||
|
"degraded": "Gedegradeer",
|
||||||
|
"no_data": "Geen bergingsdata beskikbaar nie"
|
||||||
|
},
|
||||||
"docker": {
|
"docker": {
|
||||||
"rx": "RX",
|
"rx": "RX",
|
||||||
"tx": "TX",
|
"tx": "TX",
|
||||||
@@ -107,9 +112,19 @@
|
|||||||
"episodes": "Episodes",
|
"episodes": "Episodes",
|
||||||
"songs": "Liedjies"
|
"songs": "Liedjies"
|
||||||
},
|
},
|
||||||
|
"jellyfin": {
|
||||||
|
"playing": "Speel",
|
||||||
|
"transcoding": "Transkodering",
|
||||||
|
"bitrate": "Bistempo",
|
||||||
|
"no_active": "Geen Aktiewe Strome",
|
||||||
|
"movies": "Movies",
|
||||||
|
"series": "Reekse",
|
||||||
|
"episodes": "Episode",
|
||||||
|
"songs": "Liedjies"
|
||||||
|
},
|
||||||
"esphome": {
|
"esphome": {
|
||||||
"offline": "Vanlyn",
|
"offline": "Vanlyn af",
|
||||||
"offline_alt": "Vanlyn",
|
"offline_alt": "Vanlyn af",
|
||||||
"online": "Aanlyn",
|
"online": "Aanlyn",
|
||||||
"total": "Totaal",
|
"total": "Totaal",
|
||||||
"unknown": "Onbekend"
|
"unknown": "Onbekend"
|
||||||
@@ -174,6 +189,13 @@
|
|||||||
"no_active": "Geen aktiewe strome nie",
|
"no_active": "Geen aktiewe strome nie",
|
||||||
"plex_connection_error": "Gaan Plex-verbinding Na"
|
"plex_connection_error": "Gaan Plex-verbinding Na"
|
||||||
},
|
},
|
||||||
|
"tracearr": {
|
||||||
|
"no_active": "Geen Aktiewe Strome",
|
||||||
|
"streams": "Uitsendings",
|
||||||
|
"transcodes": "Transkodering",
|
||||||
|
"directplay": "Direkte Speel",
|
||||||
|
"bitrate": "Bistempo"
|
||||||
|
},
|
||||||
"omada": {
|
"omada": {
|
||||||
"connectedAp": "Gekoppelde APs",
|
"connectedAp": "Gekoppelde APs",
|
||||||
"activeUser": "Aktiewe toestelle",
|
"activeUser": "Aktiewe toestelle",
|
||||||
@@ -189,7 +211,7 @@
|
|||||||
"plex": {
|
"plex": {
|
||||||
"streams": "Aktiewe Strome",
|
"streams": "Aktiewe Strome",
|
||||||
"albums": "Albums",
|
"albums": "Albums",
|
||||||
"movies": "Flieks",
|
"movies": "Movies",
|
||||||
"tv": "TV Programme"
|
"tv": "TV Programme"
|
||||||
},
|
},
|
||||||
"sabnzbd": {
|
"sabnzbd": {
|
||||||
@@ -242,15 +264,15 @@
|
|||||||
"wanted": "Gesoek",
|
"wanted": "Gesoek",
|
||||||
"queued": "In ry",
|
"queued": "In ry",
|
||||||
"series": "Reekse",
|
"series": "Reekse",
|
||||||
"queue": "Tou",
|
"queue": "Toustaan",
|
||||||
"unknown": "Onbekend"
|
"unknown": "Onbekend"
|
||||||
},
|
},
|
||||||
"radarr": {
|
"radarr": {
|
||||||
"wanted": "Gesoek",
|
"wanted": "Gesoek",
|
||||||
"missing": "Vermis",
|
"missing": "Vermis",
|
||||||
"queued": "In ry",
|
"queued": "In ry",
|
||||||
"movies": "Flieks",
|
"movies": "Movies",
|
||||||
"queue": "Tou",
|
"queue": "Toustaan",
|
||||||
"unknown": "Onbekend"
|
"unknown": "Onbekend"
|
||||||
},
|
},
|
||||||
"lidarr": {
|
"lidarr": {
|
||||||
@@ -272,16 +294,13 @@
|
|||||||
"approved": "Goedgekeur",
|
"approved": "Goedgekeur",
|
||||||
"available": "Beskikbaar"
|
"available": "Beskikbaar"
|
||||||
},
|
},
|
||||||
"jellyseerr": {
|
"seerr": {
|
||||||
"pending": "Afwagtend",
|
"pending": "Afwagtend",
|
||||||
"approved": "Goedgekeur",
|
"approved": "Goedgekeur",
|
||||||
"available": "Beskikbaar"
|
"available": "Beskikbaar",
|
||||||
},
|
"completed": "Afgehandel",
|
||||||
"overseerr": {
|
|
||||||
"pending": "Afwagtend",
|
|
||||||
"processing": "Verwerking",
|
"processing": "Verwerking",
|
||||||
"approved": "Goedgekeur",
|
"issues": "Oop Kwessies"
|
||||||
"available": "Beskikbaar"
|
|
||||||
},
|
},
|
||||||
"netalertx": {
|
"netalertx": {
|
||||||
"total": "Totaal",
|
"total": "Totaal",
|
||||||
@@ -302,7 +321,7 @@
|
|||||||
"latency": "Latensie"
|
"latency": "Latensie"
|
||||||
},
|
},
|
||||||
"speedtest": {
|
"speedtest": {
|
||||||
"upload": "Laai Op",
|
"upload": "Oplaai",
|
||||||
"download": "Aflaai",
|
"download": "Aflaai",
|
||||||
"ping": "Pieng"
|
"ping": "Pieng"
|
||||||
},
|
},
|
||||||
@@ -325,6 +344,16 @@
|
|||||||
"address": "Adres",
|
"address": "Adres",
|
||||||
"expires": "Verval",
|
"expires": "Verval",
|
||||||
"never": "Nooit",
|
"never": "Nooit",
|
||||||
|
"user": "Gebruiker",
|
||||||
|
"hostname": "Gasheernaam",
|
||||||
|
"name": "Naam",
|
||||||
|
"client_version": "Kliënt Weergawe",
|
||||||
|
"os": "OS",
|
||||||
|
"created": "Geskep",
|
||||||
|
"authorized": "Gemagtig",
|
||||||
|
"is_external": "Is Extern",
|
||||||
|
"update_available": "Opdatering Beskikbaar",
|
||||||
|
"tags": "Merkers",
|
||||||
"last_seen": "Laaste Gesien",
|
"last_seen": "Laaste Gesien",
|
||||||
"now": "Nou",
|
"now": "Nou",
|
||||||
"years": "{{number}}y",
|
"years": "{{number}}y",
|
||||||
@@ -333,7 +362,9 @@
|
|||||||
"hours": "{{number}}h",
|
"hours": "{{number}}h",
|
||||||
"minutes": "{{number}}m",
|
"minutes": "{{number}}m",
|
||||||
"seconds": "{{number}}s",
|
"seconds": "{{number}}s",
|
||||||
"ago": "{{value}} Terug"
|
"ago": "{{value}} Terug",
|
||||||
|
"true": "Ja",
|
||||||
|
"false": "Nee"
|
||||||
},
|
},
|
||||||
"technitium": {
|
"technitium": {
|
||||||
"totalQueries": "Navraë",
|
"totalQueries": "Navraë",
|
||||||
@@ -359,8 +390,14 @@
|
|||||||
"services": "Dienste",
|
"services": "Dienste",
|
||||||
"middleware": "Filtreerprogramme"
|
"middleware": "Filtreerprogramme"
|
||||||
},
|
},
|
||||||
|
"trilium": {
|
||||||
|
"version": "Weergawe",
|
||||||
|
"notesCount": "Notas",
|
||||||
|
"dbSize": "Databasis Grootte",
|
||||||
|
"unknown": "Onbekend"
|
||||||
|
},
|
||||||
"navidrome": {
|
"navidrome": {
|
||||||
"nothing_streaming": "Geen aktiewe strome nie",
|
"nothing_streaming": "Geen Aktiewe Strome",
|
||||||
"please_wait": "Wag Asseblief"
|
"please_wait": "Wag Asseblief"
|
||||||
},
|
},
|
||||||
"npm": {
|
"npm": {
|
||||||
@@ -389,7 +426,7 @@
|
|||||||
},
|
},
|
||||||
"jackett": {
|
"jackett": {
|
||||||
"configured": "Opgestel",
|
"configured": "Opgestel",
|
||||||
"errored": "Fout"
|
"errored": "Gefout"
|
||||||
},
|
},
|
||||||
"strelaysrv": {
|
"strelaysrv": {
|
||||||
"numActiveSessions": "Sessies",
|
"numActiveSessions": "Sessies",
|
||||||
@@ -412,7 +449,7 @@
|
|||||||
"version": "Weergawe",
|
"version": "Weergawe",
|
||||||
"status": "Status",
|
"status": "Status",
|
||||||
"up": "Aanlyn",
|
"up": "Aanlyn",
|
||||||
"down": "Vanlyn"
|
"down": "Vanlyn af"
|
||||||
},
|
},
|
||||||
"miniflux": {
|
"miniflux": {
|
||||||
"read": "Gelees",
|
"read": "Gelees",
|
||||||
@@ -525,7 +562,8 @@
|
|||||||
"child_bridges_status": "{{ok}}/{{total}}",
|
"child_bridges_status": "{{ok}}/{{total}}",
|
||||||
"up": "Op",
|
"up": "Op",
|
||||||
"pending": "Afwagtend",
|
"pending": "Afwagtend",
|
||||||
"down": "Af"
|
"down": "Af",
|
||||||
|
"ok": "Ok"
|
||||||
},
|
},
|
||||||
"healthchecks": {
|
"healthchecks": {
|
||||||
"new": "Nuut",
|
"new": "Nuut",
|
||||||
@@ -549,7 +587,7 @@
|
|||||||
"indexers": "Indekseerders"
|
"indexers": "Indekseerders"
|
||||||
},
|
},
|
||||||
"tubearchivist": {
|
"tubearchivist": {
|
||||||
"downloads": "Tou",
|
"downloads": "Toustaan",
|
||||||
"videos": "Videos",
|
"videos": "Videos",
|
||||||
"channels": "Kanale",
|
"channels": "Kanale",
|
||||||
"playlists": "Snitlyste"
|
"playlists": "Snitlyste"
|
||||||
@@ -557,7 +595,7 @@
|
|||||||
"truenas": {
|
"truenas": {
|
||||||
"load": "Stelsellading",
|
"load": "Stelsellading",
|
||||||
"uptime": "Optyd",
|
"uptime": "Optyd",
|
||||||
"alerts": "Waarskuwings"
|
"alerts": "Opletberigte"
|
||||||
},
|
},
|
||||||
"pyload": {
|
"pyload": {
|
||||||
"speed": "Spoed",
|
"speed": "Spoed",
|
||||||
@@ -592,6 +630,15 @@
|
|||||||
"inbox": "Inmandjie",
|
"inbox": "Inmandjie",
|
||||||
"total": "Totaal"
|
"total": "Totaal"
|
||||||
},
|
},
|
||||||
|
"pangolin": {
|
||||||
|
"orgs": "Orgs",
|
||||||
|
"sites": "Sites",
|
||||||
|
"resources": "Bronne",
|
||||||
|
"targets": "Teikens",
|
||||||
|
"traffic": "Verkeer",
|
||||||
|
"in": "In",
|
||||||
|
"out": "Uit"
|
||||||
|
},
|
||||||
"peanut": {
|
"peanut": {
|
||||||
"battery_charge": "Batterylading",
|
"battery_charge": "Batterylading",
|
||||||
"ups_load": "SVE-lading",
|
"ups_load": "SVE-lading",
|
||||||
@@ -688,6 +735,10 @@
|
|||||||
"uptime": "Optyd",
|
"uptime": "Optyd",
|
||||||
"volumeAvailable": "Beskikbaar"
|
"volumeAvailable": "Beskikbaar"
|
||||||
},
|
},
|
||||||
|
"dispatcharr": {
|
||||||
|
"channels": "Kanale",
|
||||||
|
"streams": "Uitsendings"
|
||||||
|
},
|
||||||
"mylar": {
|
"mylar": {
|
||||||
"series": "Reekse",
|
"series": "Reekse",
|
||||||
"issues": "Kwessies",
|
"issues": "Kwessies",
|
||||||
@@ -752,7 +803,8 @@
|
|||||||
"ghostfolio": {
|
"ghostfolio": {
|
||||||
"gross_percent_today": "Vandag",
|
"gross_percent_today": "Vandag",
|
||||||
"gross_percent_1y": "Een jaar",
|
"gross_percent_1y": "Een jaar",
|
||||||
"gross_percent_max": "Alle tyd"
|
"gross_percent_max": "Alle tyd",
|
||||||
|
"net_worth": "Netto Waarde"
|
||||||
},
|
},
|
||||||
"audiobookshelf": {
|
"audiobookshelf": {
|
||||||
"podcasts": "Podsendinge",
|
"podcasts": "Podsendinge",
|
||||||
@@ -767,7 +819,7 @@
|
|||||||
},
|
},
|
||||||
"whatsupdocker": {
|
"whatsupdocker": {
|
||||||
"monitoring": "Monitering",
|
"monitoring": "Monitering",
|
||||||
"updates": "Opdatering"
|
"updates": "Opdaterings"
|
||||||
},
|
},
|
||||||
"calibreweb": {
|
"calibreweb": {
|
||||||
"books": "Boeke",
|
"books": "Boeke",
|
||||||
@@ -775,6 +827,12 @@
|
|||||||
"categories": "Kategorieë",
|
"categories": "Kategorieë",
|
||||||
"series": "Reekse"
|
"series": "Reekse"
|
||||||
},
|
},
|
||||||
|
"booklore": {
|
||||||
|
"libraries": "Biblioteke",
|
||||||
|
"books": "Boeke",
|
||||||
|
"reading": "Lees",
|
||||||
|
"finished": "Klaar"
|
||||||
|
},
|
||||||
"jdownloader": {
|
"jdownloader": {
|
||||||
"downloadCount": "Tou",
|
"downloadCount": "Tou",
|
||||||
"downloadBytesRemaining": "Oorblywende",
|
"downloadBytesRemaining": "Oorblywende",
|
||||||
@@ -801,7 +859,7 @@
|
|||||||
"gamedig": {
|
"gamedig": {
|
||||||
"status": "Status",
|
"status": "Status",
|
||||||
"online": "Aanlyn",
|
"online": "Aanlyn",
|
||||||
"offline": "Vanlyn",
|
"offline": "Vanlyn af",
|
||||||
"name": "Naam",
|
"name": "Naam",
|
||||||
"map": "Kaart",
|
"map": "Kaart",
|
||||||
"currentPlayers": "Huidige Spelers",
|
"currentPlayers": "Huidige Spelers",
|
||||||
@@ -872,12 +930,25 @@
|
|||||||
"domains": "Domeine",
|
"domains": "Domeine",
|
||||||
"mailboxes": "Posbusse",
|
"mailboxes": "Posbusse",
|
||||||
"mails": "E-posse",
|
"mails": "E-posse",
|
||||||
"storage": "Bergplek"
|
"storage": "Stoor plek"
|
||||||
},
|
},
|
||||||
"netdata": {
|
"netdata": {
|
||||||
"warnings": "Waarskuwings",
|
"warnings": "Waarskuwings",
|
||||||
"criticals": "Kritici"
|
"criticals": "Kritici"
|
||||||
},
|
},
|
||||||
|
"ntfy": {
|
||||||
|
"title": "Title",
|
||||||
|
"priority": "Priority",
|
||||||
|
"lastReceived": "Last Received",
|
||||||
|
"message": "Message",
|
||||||
|
"tags": "Tags",
|
||||||
|
"none": "None",
|
||||||
|
"min": "Min",
|
||||||
|
"low": "Low",
|
||||||
|
"default": "Default",
|
||||||
|
"high": "High",
|
||||||
|
"urgent": "Urgent"
|
||||||
|
},
|
||||||
"plantit": {
|
"plantit": {
|
||||||
"events": "Gebeure",
|
"events": "Gebeure",
|
||||||
"plants": "Plante",
|
"plants": "Plante",
|
||||||
@@ -902,7 +973,7 @@
|
|||||||
"galleries": "Galerye",
|
"galleries": "Galerye",
|
||||||
"performers": "Kunstenaars",
|
"performers": "Kunstenaars",
|
||||||
"studios": "Ateljees",
|
"studios": "Ateljees",
|
||||||
"movies": "Flieks",
|
"movies": "Movies",
|
||||||
"tags": "Merkers",
|
"tags": "Merkers",
|
||||||
"oCount": "O Tel"
|
"oCount": "O Tel"
|
||||||
},
|
},
|
||||||
@@ -920,13 +991,13 @@
|
|||||||
"totalValue": "Totale Waarde"
|
"totalValue": "Totale Waarde"
|
||||||
},
|
},
|
||||||
"crowdsec": {
|
"crowdsec": {
|
||||||
"alerts": "Waarskuwings",
|
"alerts": "Opletberigte",
|
||||||
"bans": "Verbanne"
|
"bans": "Verbanne"
|
||||||
},
|
},
|
||||||
"wgeasy": {
|
"wgeasy": {
|
||||||
"connected": "Gekoppel",
|
"connected": "Gekoppel",
|
||||||
"enabled": "Geaktiveer",
|
"enabled": "Geaktiveer",
|
||||||
"disabled": "Onaktief",
|
"disabled": "Gediaktiveer",
|
||||||
"total": "Totaal"
|
"total": "Totaal"
|
||||||
},
|
},
|
||||||
"swagdashboard": {
|
"swagdashboard": {
|
||||||
@@ -938,7 +1009,7 @@
|
|||||||
"myspeed": {
|
"myspeed": {
|
||||||
"ping": "Pieng",
|
"ping": "Pieng",
|
||||||
"download": "Aflaai",
|
"download": "Aflaai",
|
||||||
"upload": "Laai Op"
|
"upload": "Oplaai"
|
||||||
},
|
},
|
||||||
"stocks": {
|
"stocks": {
|
||||||
"stocks": "Aandele",
|
"stocks": "Aandele",
|
||||||
@@ -959,7 +1030,7 @@
|
|||||||
},
|
},
|
||||||
"zabbix": {
|
"zabbix": {
|
||||||
"unclassified": "Nie geklassifiseer nie",
|
"unclassified": "Nie geklassifiseer nie",
|
||||||
"information": "Informasie",
|
"information": "Inligting",
|
||||||
"warning": "Waarskuwing",
|
"warning": "Waarskuwing",
|
||||||
"average": "Gemiddeld",
|
"average": "Gemiddeld",
|
||||||
"high": "Hoog",
|
"high": "Hoog",
|
||||||
@@ -982,7 +1053,7 @@
|
|||||||
"headscale": {
|
"headscale": {
|
||||||
"name": "Naam",
|
"name": "Naam",
|
||||||
"address": "Adres",
|
"address": "Adres",
|
||||||
"last_seen": "Laaste Gesien",
|
"last_seen": "Laas gesien",
|
||||||
"status": "Status",
|
"status": "Status",
|
||||||
"online": "Aanlyn",
|
"online": "Aanlyn",
|
||||||
"offline": "Vanlyn"
|
"offline": "Vanlyn"
|
||||||
@@ -1008,7 +1079,7 @@
|
|||||||
"healthy": "Gesond",
|
"healthy": "Gesond",
|
||||||
"degraded": "Gedegradeer",
|
"degraded": "Gedegradeer",
|
||||||
"progressing": "Vorderend",
|
"progressing": "Vorderend",
|
||||||
"missing": "Vermis",
|
"missing": "Afwesig",
|
||||||
"suspended": "Geskors"
|
"suspended": "Geskors"
|
||||||
},
|
},
|
||||||
"spoolman": {
|
"spoolman": {
|
||||||
@@ -1047,12 +1118,97 @@
|
|||||||
},
|
},
|
||||||
"jellystat": {
|
"jellystat": {
|
||||||
"songs": "Liedjies",
|
"songs": "Liedjies",
|
||||||
"movies": "Flieks",
|
"movies": "Movies",
|
||||||
"episodes": "Episodes",
|
"episodes": "Episode",
|
||||||
"other": "Ander"
|
"other": "Ander"
|
||||||
},
|
},
|
||||||
"checkmk": {
|
"checkmk": {
|
||||||
"serviceErrors": "Diensprobleme",
|
"serviceErrors": "Diensprobleme",
|
||||||
"hostErrors": "Gasheerprobleme"
|
"hostErrors": "Gasheerprobleme"
|
||||||
|
},
|
||||||
|
"komodo": {
|
||||||
|
"total": "Totaal",
|
||||||
|
"running": "Lopend",
|
||||||
|
"stopped": "Gestop",
|
||||||
|
"down": "Af",
|
||||||
|
"unhealthy": "Ongesond",
|
||||||
|
"unknown": "Onbekend",
|
||||||
|
"servers": "Bedieners",
|
||||||
|
"stacks": "Stapels",
|
||||||
|
"containers": "Houers"
|
||||||
|
},
|
||||||
|
"filebrowser": {
|
||||||
|
"available": "Beskikbaar",
|
||||||
|
"used": "Gebruik",
|
||||||
|
"total": "Totaal"
|
||||||
|
},
|
||||||
|
"wallos": {
|
||||||
|
"activeSubscriptions": "Intekeninge",
|
||||||
|
"thisMonthlyCost": "Hierdie Maand",
|
||||||
|
"nextMonthlyCost": "Volgende Maand",
|
||||||
|
"previousMonthlyCost": "Vorige Maand",
|
||||||
|
"nextRenewingSubscription": "Volgende paaiement"
|
||||||
|
},
|
||||||
|
"unraid": {
|
||||||
|
"STARTED": "Begin",
|
||||||
|
"STOPPED": "Gestop",
|
||||||
|
"NEW_ARRAY": "Nuwe Skikking",
|
||||||
|
"RECON_DISK": "Rekonstruksie van Skyf",
|
||||||
|
"DISABLE_DISK": "Skyf Gedeaktiveer",
|
||||||
|
"SWAP_DSBL": "Ruil Gedeaktiveer",
|
||||||
|
"INVALID_EXPANSION": "Ongeldige Uitbreiding",
|
||||||
|
"PARITY_NOT_BIGGEST": "Pariteit nie die Grootste nie",
|
||||||
|
"TOO_MANY_MISSING_DISKS": "Te Veel Ontbrekende Skywe",
|
||||||
|
"NEW_DISK_TOO_SMALL": "Nuwe Skyf te Klein",
|
||||||
|
"NO_DATA_DISKS": "Geen Data Skywe",
|
||||||
|
"notifications": "Kennisgewings",
|
||||||
|
"status": "Status",
|
||||||
|
"cpu": "SVE",
|
||||||
|
"memoryUsed": "Geheue Gebruik",
|
||||||
|
"memoryAvailable": "Geheue Beskikbaar",
|
||||||
|
"arrayUsed": "Skikking Gebruik",
|
||||||
|
"arrayFree": "Skikking Vry",
|
||||||
|
"poolUsed": "{{pool}} Gebruik",
|
||||||
|
"poolFree": "{{pool}} Vry"
|
||||||
|
},
|
||||||
|
"backrest": {
|
||||||
|
"num_plans": "Planne",
|
||||||
|
"num_success_30": "Suksesse",
|
||||||
|
"num_failure_30": "Mislukkings",
|
||||||
|
"num_success_latest": "Slaag",
|
||||||
|
"num_failure_latest": "Mislukking",
|
||||||
|
"bytes_added_30": "Grepe bygevoeg"
|
||||||
|
},
|
||||||
|
"yourspotify": {
|
||||||
|
"songs": "Liedjies",
|
||||||
|
"time": "Tyd",
|
||||||
|
"artists": "Kunstenaars"
|
||||||
|
},
|
||||||
|
"arcane": {
|
||||||
|
"containers": "Houers",
|
||||||
|
"images": "Beelde",
|
||||||
|
"image_updates": "Beeldopdaterings",
|
||||||
|
"images_unused": "Ongebruik",
|
||||||
|
"environment_required": "Omgewings-ID Vereis"
|
||||||
|
},
|
||||||
|
"dockhand": {
|
||||||
|
"running": "Lopend",
|
||||||
|
"stopped": "Gestop",
|
||||||
|
"cpu": "SVE",
|
||||||
|
"memory": "Geheue",
|
||||||
|
"images": "Beelde",
|
||||||
|
"volumes": "Volumes",
|
||||||
|
"events_today": "Vandag se byeenkomste",
|
||||||
|
"pending_updates": "Hangende opdaterings",
|
||||||
|
"stacks": "Stapels",
|
||||||
|
"paused": "Onderbreek",
|
||||||
|
"total": "Totaal",
|
||||||
|
"environment_not_found": "Omgewing Nie Gevind Nie"
|
||||||
|
},
|
||||||
|
"sparkyfitness": {
|
||||||
|
"eaten": "Geëet",
|
||||||
|
"burned": "Verbrand",
|
||||||
|
"remaining": "Oorblywende",
|
||||||
|
"steps": "Stappe"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user