Compare commits

...
183 Commits
Author SHA1 Message Date
Releases Homarr 80fbbda111 chore(release): 1.53.1 [skip ci] 2026-02-13 19:42:07 +00:00
homarr-releases[bot] 72fcae1b85 chore(release): automatic release v1.53.1 2026-02-13 19:41:04 +00:00
Meier Lukas be1a26a98d fix(seerr): use reasonable limits for amount of returned entries (#5001) 2026-02-13 19:23:35 +01:00
homarr-renovate[bot] 30f561f85a fix(deps): update dependency fast-xml-parser to ^5.3.5 (#5050)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-02-13 15:49:24 +00:00
Meier Lukas 661d738302 ci: on-release pipeline no longer triggering and bug-report template not updated (#5048) 2026-02-13 15:43:48 +01:00
homarr-renovate[bot] 8002882979 chore(deps): update dependency hono@&lt;4.6.5 to >=4.11.9 (#5052)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-02-13 13:09:10 +00:00
homarr-renovate[bot] 5bd6cceaf1 chore(deps): update dependency @types/node to ^24.10.12 (#5045)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-02-13 07:18:22 +00:00
Meier Lukas 60fcb71bd2 fix(sections): dynamic sections vanish when adding category (#5046) 2026-02-13 08:05:15 +01:00
homarr-renovate[bot] 175d7d6324 chore(deps): update pnpm to v10.29.1 (#5043)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-02-12 19:58:05 +00:00
homarr-renovate[bot] 9e8701171b chore(deps): update dependency esbuild@&lt;&#x3d;0.24.2 to >=0.27.3 (#5031)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-02-12 19:46:18 +01:00
homarr-renovate[bot] 6568c22d86 chore(deps): update dependency esbuild to ^0.27.3 (#5030)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-02-12 19:46:02 +01:00
homarr-renovate[bot] e1a79afaaa chore(deps): update dependency vite-tsconfig-paths to ^6.1.0 (#5042)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-02-12 18:29:20 +00:00
homarr-renovate[bot] e561fc550f fix(deps): update dependency isomorphic-dompurify to ^2.36.0 (#5041)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-02-12 09:58:55 +00:00
homarr-renovate[bot] f2f16f0502 chore(deps): update dependency @semantic-release/github to ^12.0.5 (#5039)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-02-12 05:04:44 +00:00
homarr-renovate[bot] c92fd3a9ca chore(deps): update dependency @semantic-release/github to ^12.0.4 (#5037)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-02-11 22:38:11 +00:00
homarr-renovate[bot] 4dc04bb58b chore(deps): update dependency @semantic-release/npm to ^13.1.4 (#5035)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-02-11 20:47:43 +00:00
homarr-renovate[bot] d694b1a541 fix(deps): update dependency tsdav to ^2.1.7 (#5033)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-02-11 19:16:22 +00:00
homarr-renovate[bot] 0fff39ee1c chore(deps): update dependency hono@&lt;4.6.5 to >=4.11.8 (#5032)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-02-11 19:15:27 +00:00
homarr-renovate[bot] 6efabd4368 fix(deps): update dependency video.js to ^8.23.7 (#5034)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-02-11 18:03:26 +00:00
homarr-renovate[bot] 18e16d687f fix(deps): update dependency fastify to ^5.7.4 (#5027)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-02-10 21:54:36 +00:00
homarr-renovate[bot] e8c7f45476 fix(deps): update dependency dotenv to ^17.2.4 (#5029)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-02-10 21:04:17 +00:00
homarr-renovate[bot] 7bf5bbd035 chore(deps): update dependency jsdom to v28 (#5003)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-02-10 20:28:22 +01:00
homarr-renovate[bot]andMeier Lukas 29d9a9d288 chore(deps): update dependency fastify to v5.7.3 [security] (#4994)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
Co-authored-by: Meier Lukas <meierschlumpf@gmail.com>
2026-02-10 20:05:12 +01:00
homarr-renovate[bot] 69d90c1ece chore(deps): update dependency @types/node to ^24.10.11 (#5025)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-02-10 15:07:49 +00:00
homarr-renovate[bot] 5946e6c719 fix(deps): update dependency @ianvs/prettier-plugin-sort-imports to ^4.7.1 (#5021)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-02-10 13:25:48 +00:00
homarr-renovate[bot] 74753c8918 chore(deps): update dependency @types/react to v19.2.13 (#5024)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-02-10 13:25:09 +00:00
homarr-renovate[bot] ef4ed16dc4 chore(deps): update dependency axios@&gt;&#x3d;1.0.0 &lt;1.8.2 to >=1.13.5 [security] (#5023)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-02-10 13:18:20 +00:00
homarr-renovate[bot] 49570417d4 chore(deps): update dependency @types/react to v19.2.12 (#5022)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-02-10 10:12:12 +00:00
homarr-renovate[bot] 98283ff526 chore(deps): update dependency @types/react to v19.2.11 (#5020)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-02-09 11:52:32 +00:00
homarr-renovate[bot] da965668d0 fix(deps): update dependency jotai to ^2.17.1 (#5019)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-02-09 05:08:24 +00:00
homarr-renovate[bot] c92d487cea fix(deps): update dependency ldapts to v8.1.6 (#5018)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-02-09 02:31:43 +00:00
homarr-crowdin[bot] 81cecbfb57 chore(lang): updated translations from crowdin
Co-authored-by: Crowdin Homarr <190541745+homarr-crowdin[bot]@users.noreply.github.com>
2026-02-09 01:11:26 +00:00
homarr-renovate[bot] f1d2f07f38 fix(deps): update turbo monorepo to ^2.8.3 (#5016)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-02-08 23:40:57 +00:00
homarr-renovate[bot] 04b35980f5 fix(deps): update dependency mysql2 to v3.16.3 (#5014)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-02-08 18:47:39 +00:00
homarr-renovate[bot] 3b21c3ef76 fix(deps): update dependency glob to ^13.0.1 (#5013)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-02-08 18:45:16 +00:00
homarr-renovate[bot] ad41a918ef fix(deps): update tiptap monorepo to v3.19.0 (#5012)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-02-08 17:35:55 +00:00
homarr-crowdin[bot] 0b654aeafa chore(lang): update translations from crowdin (#5002)
Co-authored-by: Crowdin Homarr <190541745+homarr-crowdin[bot]@users.noreply.github.com>
2026-02-08 14:03:04 +01:00
homarr-renovate[bot] 9e9b904f69 chore(deps): update dependency @types/node to ^24.10.10 (#5011)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-02-08 09:39:25 +00:00
homarr-renovate[bot] b479fea6eb fix(deps): update turbo monorepo to ^2.8.2 (#5010)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-02-08 06:59:58 +00:00
homarr-renovate[bot] 4a86361134 fix(deps): update dependency @octokit/auth-app to ^8.2.0 (#5009)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-02-08 02:45:18 +00:00
homarr-renovate[bot] b67fecd396 fix(deps): update dependency next-intl to v4.8.2 (#5005)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-02-07 11:30:58 +00:00
homarr-renovate[bot] 075ddb7a83 chore(deps): update dependency @vitejs/plugin-react to ^5.1.3 (#5006)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-02-07 10:38:18 +00:00
homarr-renovate[bot] c3932b18f0 fix(deps): update dependency ldapts to v8.1.5 (#5004)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-02-07 09:41:54 +00:00
Releases Homarr 6dd13f6dea chore(release): 1.53.0 [skip ci] 2026-02-06 19:37:59 +00:00
homarr-releases[bot] 129d96f607 chore(release): automatic release v1.53.0 2026-02-06 19:37:00 +00:00
homarr-renovate[bot] 0fafa505ac fix(deps): update mantine monorepo to ^8.3.14 (#4998)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-02-06 13:10:10 +00:00
homarr-crowdin[bot] 5e085b0da0 chore(lang): updated translations from crowdin
Co-authored-by: Crowdin Homarr <190541745+homarr-crowdin[bot]@users.noreply.github.com>
2026-02-06 01:04:58 +00:00
homarr-renovate[bot] c2d9f18e4e fix(deps): update dependency ldapts to v8.1.4 (#4993)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-02-05 14:50:32 +00:00
homarr-renovate[bot] 4209f7c70e fix(deps): update dependency video.js to ^8.23.6 (#4992)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-02-05 11:43:25 +00:00
ajnart 10848db595 feat(analytics): consolidate server analytics into single comprehensive Umami event (#4938)
* feat(analytics): consolidate server analytics into single Umami event

- Replace multiple separate events with single 'server-analytics' event
- Add comprehensive metrics: Homarr version, database type, Docker/K8s status
- Add auth providers status (credentials, OIDC, LDAP)
- Add counts for users, boards, groups, apps, widgets, sections, integrations
- Add counts for search engines, icon repos, icons, API keys, invites, media
- Add counts for layouts, item layouts, section layouts, cron job configs
- Include per-integration-kind breakdown (integration_sonarr, etc.)
- Add required dependencies: @homarr/auth, @homarr/common, @homarr/docker

* refactor(ui): simplify analytics settings to single toggle

- Remove individual toggles for widget/integration/user data
- Keep only the main 'Enable analytics' toggle
- All data is now collected when analytics are enabled
- Update both init settings and manage settings pages

* docs(i18n): update analytics description with collected data details

- Explain all data points collected when analytics are enabled
- List: version, DB type, Docker/K8s, auth methods, counts
- Clarify that no personal info, URLs, or names are collected

* chore(deps): update pnpm-lock.yaml for analytics package dependencies
2026-02-05 09:54:41 +01:00
homarr-renovate[bot] 43b6246876 fix(deps): update turbo monorepo to ^2.8.1 (#4991)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-02-04 22:37:10 +00:00
homarr-renovate[bot] bd07570c8d chore(deps): update semantic-release monorepo (#4990)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-02-04 21:41:31 +00:00
homarr-renovate[bot] 62b6939b92 fix(deps): update dependency next-intl to v4.8.1 (#4986)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-02-04 19:46:39 +00:00
homarr-renovate[bot] c3071a3c95 fix(deps): update dependency pg to ^8.18.0 (#4989)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-02-04 19:00:45 +00:00
homarr-renovate[bot] 1115ad1364 fix(deps): update dependency @tanstack/react-query-devtools to ^5.91.3 (#4985)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-02-04 09:51:43 +00:00
homarr-renovate[bot] 4cfd2aca94 chore(deps): update dependency rollup@&gt;&#x3d;4.0.0 &lt;4.22.4 to >=4.57.1 (#4984)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-02-04 08:49:28 +00:00
homarr-renovate[bot] 460d53cafa fix(deps): update dependency fast-xml-parser to ^5.3.4 (#4982)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-02-04 04:47:35 +00:00
homarr-crowdin[bot] 0b88d5703e chore(lang): updated translations from crowdin
Co-authored-by: Crowdin Homarr <190541745+homarr-crowdin[bot]@users.noreply.github.com>
2026-02-03 01:09:22 +00:00
homarr-renovate[bot] 054ca57188 fix(deps): update turbo monorepo to ^2.8.0 (#4978)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-02-02 18:54:38 +00:00
homarr-renovate[bot] c3a7ab52ee fix(deps): update dependency next-intl to v4.8.0 (#4977)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-02-02 17:46:05 +00:00
homarr-crowdin[bot] 8ee1e32e83 chore(lang): update translations from crowdin (#4954)
Co-authored-by: Crowdin Homarr <190541745+homarr-crowdin[bot]@users.noreply.github.com>
2026-02-02 17:24:22 +01:00
homarr-renovate[bot] 24e24dc634 fix(deps): update tiptap monorepo to v3.18.0 (#4975)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-02-02 13:09:45 +00:00
homarr-renovate[bot] 6303aec209 chore(deps): update dependency fast-xml-parser to v5.3.4 [security] (#4974)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-02-02 07:53:26 +00:00
homarr-renovate[bot] 7c3fe3d6d4 fix(deps): update nextjs monorepo to v16.1.6 (#4969)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-02-02 05:05:02 +00:00
homarr-renovate[bot] e67483fea5 fix(deps): update dependency jotai to ^2.17.0 (#4972)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-02-02 02:29:58 +00:00
homarr-renovate[bot] d1f7e04a2a chore(deps): update dependency proxmox-api&gt;undici to v7.19.2 (#4967)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-02-02 02:28:37 +00:00
homarr-renovate[bot] 0a2f71bd31 chore(deps): update dependency rollup@&gt;&#x3d;4.0.0 &lt;4.22.4 to >=4.57.0 (#4963)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-02-01 23:34:08 +00:00
homarr-renovate[bot] aeb6e0f406 fix(deps): update trpc monorepo to ^11.9.0 (#4970)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-02-01 22:34:19 +00:00
homarr-renovate[bot] df264f58d0 chore(deps): update dependency @types/react to v19.2.10 (#4964)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-02-01 19:31:41 +00:00
homarr-renovate[bot] 71aa5b660b chore(deps): update dependency axios@&gt;&#x3d;1.0.0 &lt;1.8.2 to >=1.13.4 (#4966)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-02-01 18:42:55 +00:00
homarr-renovate[bot] 5c6eafb272 fix(deps): update dependency mysql2 to v3.16.2 (#4961)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-31 21:30:15 +00:00
homarr-renovate[bot] e88d126355 fix(deps): update dependency typescript-eslint to ^8.54.0 (#4958)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-31 19:28:39 +00:00
homarr-renovate[bot] d3e0b47875 fix(deps): update react monorepo to v19.2.4 (#4960)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-31 18:42:46 +00:00
homarr-renovate[bot] ec40309cde fix(deps): update dependency @next/eslint-plugin-next to v16.1.5 (#4959)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-31 18:42:21 +00:00
homarr-renovate[bot] a3ba70177b chore(deps): update pnpm to v10.28.2 (#4956)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-31 15:32:24 +00:00
homarr-renovate[bot] 0eab26cdac fix(deps): update dependency fastify to ^5.7.2 (#4955)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-31 11:27:34 +00:00
homarr-renovate[bot] a9db68bd3e fix(deps): update dependency @paralleldrive/cuid2 to ^3.3.0 (#4952)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-30 21:36:03 +00:00
Releases Homarr d2c075517f chore(release): 1.52.0 [skip ci] 2026-01-30 19:32:17 +00:00
homarr-releases[bot] fab80d5ab2 chore(release): automatic release v1.52.0 2026-01-30 19:31:27 +00:00
Meier Lukasandajnart 8811af5e6e Merge commit from fork
* fix(security): resolve ssrf issue with simple ping

* refactor: improve testability of app-access-control and fix tests

* fix: unnecessary space

Co-authored-by: ajnart <thomas@ajnart.fr>

---------

Co-authored-by: ajnart <thomas@ajnart.fr>
2026-01-30 18:31:13 +01:00
Meier Lukas 9ba82133da feat(installations): support docker secrets file for encryption key (#4946) 2026-01-30 17:28:08 +01:00
homarr-renovate[bot] 67e1b9bdc3 chore(deps): update dependency axios@&gt;&#x3d;1.0.0 &lt;1.8.2 to >=1.13.3 (#4950)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-30 14:52:11 +00:00
homarr-renovate[bot] 08711a551f chore(deps): update dependency hono@&lt;4.6.5 to >=4.11.7 [security] (#4930)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-30 14:01:18 +00:00
homarr-update-contributors[bot] ef1197b382 chore: update contributors (#4949)
Co-authored-by: Homarr Update Contributors <210161987+homarr-update-contributors[bot]@users.noreply.github.com>
2026-01-30 12:45:40 +00:00
homarr-crowdin[bot] 26144e22f4 chore(lang): updated translations from crowdin
Co-authored-by: Crowdin Homarr <190541745+homarr-crowdin[bot]@users.noreply.github.com>
2026-01-30 01:05:18 +00:00
homarr-renovate[bot] e078237e31 fix(deps): update turbo monorepo to ^2.7.6 (#4947)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-29 22:36:34 +00:00
Meier Lukas 1a33d8ccee chore: ignore .turbo directory for docker build 2026-01-29 20:37:01 +01:00
homarr-renovate[bot] b354085c7a fix(deps): update tiptap monorepo to v3.17.1 (#4945)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-29 18:56:43 +00:00
homarr-crowdin[bot] a43429b351 chore(lang): updated translations from crowdin
Co-authored-by: Crowdin Homarr <190541745+homarr-crowdin[bot]@users.noreply.github.com>
2026-01-29 18:49:45 +00:00
homarr-renovate[bot] 203ebbbd4e chore(deps): update dependency proxmox-api&gt;undici to v7.19.1 (#4944)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-29 15:44:22 +00:00
homarr-renovate[bot] 0bdc76cc23 chore(deps): update dependency vite-tsconfig-paths to ^6.0.5 (#4941)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-28 22:35:54 +00:00
homarr-renovate[bot] 840940bab6 fix(deps): update dependency @tanstack/react-query to ^5.90.20 (#4939)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-28 14:38:30 +00:00
homarr-renovate[bot] d03026187c fix(deps): update tiptap monorepo to v3.17.0 (#4940)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-28 13:58:20 +00:00
homarr-renovate[bot] aeb1df1229 fix(deps): update dependency next to v16.1.5 [security] (#4937)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-27 21:21:21 +00:00
homarr-renovate[bot] dea3f02e6f chore(deps): update vitest monorepo to ^4.0.18 (#4929)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-27 20:40:04 +01:00
homarr-renovate[bot] 6fd0fb5508 chore(deps): update dependency prettier-plugin-packagejson to v3 (#4910)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-27 17:16:26 +01:00
homarr-renovate[bot] ce72b21a04 chore(deps): update dependency rollup@&gt;&#x3d;4.0.0 &lt;4.22.4 to >=4.56.0 (#4928)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-27 06:43:47 +00:00
homarr-renovate[bot] b1658a5d01 fix(deps): update dependency sass to ^1.97.3 (#4927)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-27 03:55:45 +00:00
homarr-renovate[bot] 4df63eacc5 chore(deps): update dependency hono@&lt;4.6.5 to >=4.11.5 (#4926)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-27 02:02:21 +00:00
homarr-renovate[bot] 3cca339881 chore(deps): update dependency rollup@&gt;&#x3d;4.0.0 &lt;4.22.4 to >=4.55.3 (#4919)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-26 20:35:32 +00:00
homarr-renovate[bot] fd18cf79cc chore(deps): update dependency proxmox-api&gt;undici to v7.19.0 (#4922)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-26 19:31:50 +00:00
homarr-renovate[bot] a727b8e323 fix(deps): update dependency prettier to ^3.8.1 (#4925)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-26 18:45:54 +00:00
homarr-renovate[bot] 21c3882189 chore(deps): update dependency @types/dockerode to ^4.0.1 (#4918)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-26 04:08:39 +00:00
homarr-renovate[bot] d0c27b22ef chore(deps): update dependency @types/react to v19.2.9 (#4914)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-25 19:25:21 +00:00
homarr-renovate[bot] a50a29a778 fix(deps): update dependency pg to ^8.17.2 (#4916)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-25 18:39:14 +00:00
homarr-renovate[bot] 23545101b6 fix(deps): update tiptap monorepo to v3.16.0 (#4912)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-25 12:52:13 +00:00
homarr-renovate[bot] f2eec74849 fix(deps): update mantine monorepo to ^8.3.13 (#4911)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-25 07:29:50 +00:00
homarr-renovate[bot] 99a2574d80 fix(deps): update nextjs monorepo to v16.1.4 (#4909)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-25 02:08:32 +00:00
homarr-crowdin[bot] 66bde23667 chore(lang): updated translations from crowdin
Co-authored-by: Crowdin Homarr <190541745+homarr-crowdin[bot]@users.noreply.github.com>
2026-01-25 01:02:57 +00:00
homarr-renovate[bot] c58da00957 fix(deps): update dependency typescript-eslint to ^8.53.1 (#4904)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-24 17:26:34 +00:00
homarr-renovate[bot] 6700124ccd chore(deps): update dependency rollup@&gt;&#x3d;4.0.0 &lt;4.22.4 to >=4.55.2 (#4902)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-24 13:37:13 +00:00
homarr-renovate[bot] f428abc0ce chore(deps): update pnpm to v10.28.1 (#4903)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-24 12:50:35 +00:00
homarr-crowdin[bot] 16e3e5b90b chore(lang): updated translations from crowdin
Co-authored-by: Crowdin Homarr <190541745+homarr-crowdin[bot]@users.noreply.github.com>
2026-01-24 00:55:54 +00:00
Releases Homarr 86b6c1a788 chore(release): 1.51.0 [skip ci] 2026-01-23 19:24:52 +00:00
homarr-releases[bot] 4648741bcc chore(release): automatic release v1.51.0 2026-01-23 19:23:48 +00:00
homarr-update-contributors[bot] 5da5a83a41 chore: update integrations list readme (#4899)
Co-authored-by: Homarr Update Contributors <210161987+homarr-update-contributors[bot]@users.noreply.github.com>
2026-01-23 20:21:20 +01:00
homarr-renovate[bot] ff338e20a5 chore(deps): update dependency @types/node to ^24.10.9 (#4897)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-23 18:43:00 +00:00
Rhiz3KandMeier Lukas 81dac58005 feat(integrations): add Coolify integration and widget (#4789)
Co-authored-by: Meier Lukas <meierschlumpf@gmail.com>
2026-01-23 19:09:53 +01:00
Meier Lukas 0ef3046d65 ci: typo in runner for validating prebuilt-debian with arm64 (#4896) 2026-01-23 18:54:02 +01:00
62caa71a48 feat(widgets): add disks widget (#4445)
Co-authored-by: ajnart <49837342+ajnart@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Meier Lukas <meierschlumpf@gmail.com>
2026-01-23 16:23:42 +01:00
homarr-renovate[bot]andMeier Lukas 15119b66e9 chore(deps): update node.js to v24.13.0 (#4858)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
Co-authored-by: Meier Lukas <meierschlumpf@gmail.com>
2026-01-23 16:21:21 +01:00
homarr-renovate[bot]andMeier Lukas 41b02b63d9 fix(deps): update dependency react-error-boundary to ^6.1.0 (#4884)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
Co-authored-by: Meier Lukas <meierschlumpf@gmail.com>
2026-01-23 16:14:44 +01:00
homarr-renovate[bot]andMeier Lukas 63a0793c6e fix(deps): update dependency better-sqlite3 to ^12.6.2 (#4891)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
Co-authored-by: Meier Lukas <meierschlumpf@gmail.com>
2026-01-23 16:13:55 +01:00
homarr-crowdin[bot] 101c1fd819 chore(lang): update translations from crowdin (#4890)
Co-authored-by: Crowdin Homarr <190541745+homarr-crowdin[bot]@users.noreply.github.com>
2026-01-23 15:42:55 +01:00
homarr-renovate[bot] 09006c3169 chore(deps): update dependency prettier-plugin-packagejson to ^2.5.22 (#4894)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-23 14:34:56 +00:00
homarr-renovate[bot] 5a8e864630 fix(deps): update nextjs monorepo to v16.1.3 (#4889)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-23 13:50:18 +00:00
homarr-renovate[bot] fa84bd569f fix(deps): update dependency @tanstack/react-query to ^5.90.19 (#4888)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-23 12:56:49 +00:00
homarr-update-contributors[bot] e50ed15eb3 chore: update contributors (#4895)
Co-authored-by: Homarr Update Contributors <210161987+homarr-update-contributors[bot]@users.noreply.github.com>
2026-01-23 12:40:06 +00:00
homarr-renovate[bot] c847f6004d fix(deps): update turbo monorepo to ^2.7.5 (#4892)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-22 03:58:10 +00:00
homarr-renovate[bot] 40ee667832 fix(deps): update dependency mysql2 to v3.16.1 (#4886)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-21 09:40:26 +00:00
homarr-renovate[bot] 02e722aa45 fix(deps): update dependency fastify to ^5.7.1 (#4887)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-21 08:40:00 +00:00
homarr-crowdin[bot] 416e31fab6 chore(lang): updated translations from crowdin
Co-authored-by: Crowdin Homarr <190541745+homarr-crowdin[bot]@users.noreply.github.com>
2026-01-21 00:58:31 +00:00
homarr-renovate[bot] e3ba1ee931 fix(deps): update dependency ioredis to v5.9.2 (#4881)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-20 15:39:59 +00:00
homarr-renovate[bot] fcd417198f fix(deps): update dependency pg to ^8.17.1 (#4877)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-20 14:39:00 +00:00
homarr-renovate[bot] b9bc9dd38d fix(deps): update dependency fastify to ^5.7.0 (#4882)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-20 13:55:34 +00:00
homarr-renovate[bot] 3ade915d35 fix(deps): update dependency prettier to ^3.8.0 (#4876)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-20 01:57:28 +00:00
homarr-renovate[bot] c6be8c5475 fix(deps): update nextjs monorepo to v16.1.2 (#4875)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-19 23:29:51 +00:00
Meier Lukas 1623fbaaeb perf(memory): lazy routers (#4868) 2026-01-19 22:37:05 +01:00
homarr-renovate[bot] b923891fac fix(deps): update dependency pg to ^8.17.0 (#4874)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-19 18:41:55 +00:00
homarr-renovate[bot] 624bd55b11 fix(deps): update dependency @tanstack/react-query to ^5.90.17 (#4873)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-19 06:48:02 +00:00
homarr-renovate[bot]andMeier Lukas 9d4fb9eb46 fix(deps): update dependency better-sqlite3 to ^12.6.0 (#4853)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
Co-authored-by: Meier Lukas <meierschlumpf@gmail.com>
2026-01-18 21:07:31 +01:00
homarr-renovate[bot] fa64b2c525 chore(deps): update dependency @types/dockerode to v4 (#4867)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-18 17:14:02 +01:00
homarr-renovate[bot] 2e58acc3bd fix(deps): update dependency jotai to ^2.16.2 (#4869)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-18 15:09:24 +00:00
homarr-renovate[bot] 939996f41e chore(deps): update dependency prettier-plugin-packagejson to ^2.5.21 (#4866)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-18 07:28:16 +00:00
homarr-crowdin[bot] fbad058712 chore(lang): updated translations from crowdin
Co-authored-by: Crowdin Homarr <190541745+homarr-crowdin[bot]@users.noreply.github.com>
2026-01-18 01:02:11 +00:00
homarr-renovate[bot] 0c38e2f290 fix(deps): update turbo monorepo to ^2.7.4 (#4861)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-17 18:41:01 +00:00
homarr-renovate[bot] 31c68f43d5 chore(deps): update vitest monorepo to ^4.0.17 (#4862)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-17 18:40:14 +00:00
homarr-renovate[bot] f096476fc2 chore(deps): update babel monorepo to >=7.28.6 (#4864)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-17 18:39:50 +00:00
homarr-renovate[bot] e9020e68ec fix(deps): update dependency typescript-eslint to ^8.53.0 (#4863)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-17 17:26:06 +00:00
Releases Homarr be75c320f9 chore(release): 1.50.1 [skip ci] 2026-01-16 19:20:12 +00:00
homarr-releases[bot] 05ce9cf7a6 chore(release): automatic release v1.50.1 2026-01-16 19:19:19 +00:00
homarr-renovate[bot] a4a5d0ac51 chore(deps): update dependency hono@&lt;4.6.5 to >=4.11.4 [security] (#4846)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-16 14:26:55 +00:00
homarr-update-contributors[bot] 11c92929b1 chore: update contributors (#4857)
Co-authored-by: Homarr Update Contributors <210161987+homarr-update-contributors[bot]@users.noreply.github.com>
2026-01-16 13:03:27 +00:00
homarr-renovate[bot] 70f3ab21c1 chore(deps): update dependency @types/react to v19.2.8 (#4855)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-15 19:35:21 +00:00
homarr-renovate[bot] c3dc3f2eef chore(deps): update pnpm to v10.28.0 (#4851)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-15 19:33:38 +00:00
homarr-renovate[bot] 4f8b530294 chore(deps): update dependency @types/node to ^24.10.7 (#4852)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-15 18:57:32 +00:00
homarr-renovate[bot] c54d3498f3 chore(deps): update dependency vite-tsconfig-paths to ^6.0.4 (#4849)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-14 22:31:42 +00:00
homarr-renovate[bot] 275a346afa fix(deps): update mantine monorepo to ^8.3.12 (#4848)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-14 14:34:40 +00:00
homarr-renovate[bot] c24006dca6 fix(deps): update dependency react-error-boundary to ^6.0.3 (#4847)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-13 22:31:49 +00:00
homarr-renovate[bot] 5d00642268 fix(deps): update dependency ioredis to v5.9.1 (#4844)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-13 19:28:34 +00:00
homarr-crowdin[bot] b2798d7aca chore(lang): update translations from crowdin (#4834)
Co-authored-by: Crowdin Homarr <190541745+homarr-crowdin[bot]@users.noreply.github.com>
2026-01-13 20:21:03 +01:00
homarr-renovate[bot] b26cf0e65f fix(deps): update tiptap monorepo to v3.15.3 (#4843)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-12 15:36:08 +00:00
homarr-renovate[bot] 55c2666f9d fix(deps): update tiptap monorepo to v3.15.2 (#4842)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-12 12:59:38 +00:00
homarr-renovate[bot] 7fa990712b fix(deps): update dependency ldapts to v8.1.3 (#4841)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-12 09:41:50 +00:00
homarr-renovate[bot] 21db9618c6 chore(deps): update dependency vite@&gt;&#x3d;5.0.0 &lt;&#x3d;5.4.18 to >=7.3.1 (#4840)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-12 06:46:30 +00:00
homarr-renovate[bot] 07ba53165c fix(deps): update dependency sass to ^1.97.2 (#4835)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-11 18:38:22 +00:00
homarr-renovate[bot] 16733c2a0e fix(deps): update dependency undici to v7.18.2 (#4837)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-11 17:26:28 +00:00
homarr-renovate[bot] 33a3c857a6 chore(deps): update dependency proxmox-api&gt;undici to v7.18.2 (#4839)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-11 16:33:38 +00:00
homarr-renovate[bot] d479b63a80 fix(deps): update tiptap monorepo to v3.15.1 (#4838)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-11 12:52:08 +00:00
homarr-renovate[bot] 9043d8e4b8 chore(deps): update dependency proxmox-api&gt;undici to v7.18.1 (#4836)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-11 12:50:29 +00:00
homarr-renovate[bot] 629359e3e4 fix(deps): update dependency ws to ^8.19.0 (#4833)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-10 21:45:37 +00:00
homarr-renovate[bot] 50410fedb3 fix(deps): update turbo monorepo to ^2.7.3 (#4831)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-10 21:45:10 +00:00
homarr-renovate[bot] ab3ee4f78a fix(deps): update tiptap monorepo to v3.15.0 (#4832)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-10 20:32:53 +00:00
homarr-crowdin[bot] fe615755c7 chore(lang): update translations from crowdin (#4820)
Co-authored-by: Crowdin Homarr <190541745+homarr-crowdin[bot]@users.noreply.github.com>
2026-01-10 20:59:19 +01:00
homarr-renovate[bot] b76ab2961d fix(deps): update dependency undici to v7.18.0 (#4829)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-10 18:40:02 +00:00
homarr-renovate[bot] ab2703b32a chore(deps): update dependency proxmox-api&gt;undici to v7.18.0 (#4828)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-10 18:38:30 +00:00
homarr-renovate[bot] f67a915174 chore(deps): update dependency rollup@&gt;&#x3d;4.0.0 &lt;4.22.4 to >=4.55.1 (#4824)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-10 18:38:05 +00:00
homarr-renovate[bot] fa8af6a453 fix(deps): update dependency typescript-eslint to ^8.52.0 (#4830)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-10 17:26:48 +00:00
homarr-renovate[bot] 155d4f2270 fix(deps): update dependency ioredis to v5.9.0 (#4827)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-10 14:27:50 +00:00
homarr-renovate[bot] 21a91b1489 fix(deps): update dependency undici to v7.17.0 (#4826)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-10 12:50:10 +00:00
homarr-renovate[bot] 0d8695feae chore(deps): update dependency proxmox-api&gt;undici to v7.17.0 (#4825)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-10 12:49:27 +00:00
homarr-renovate[bot] 0364e102cd fix(deps): update mantine monorepo to ^8.3.11 (#4822)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-10 06:39:58 +00:00
homarr-renovate[bot] e9ba102cf6 fix(deps): update dependency react-error-boundary to ^6.0.2 (#4821)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-01-10 04:42:22 +00:00
131 changed files with 9123 additions and 4757 deletions

No files matched your search

+1
View File
@@ -5,6 +5,7 @@ node_modules
npm-debug.log
README.md
.next
.turbo
.git
dev
.build
+6
View File
@@ -33,6 +33,12 @@ body:
options:
# The below comment is used to insert a new version with on-release.yml
#NEXT_VERSION#
- 1.53.0
- 1.52.0
- 1.51.0
- 1.50.1
- 1.50.0
- 1.49.1
- 1.49.0
- 1.48.0
- 1.47.0
@@ -65,7 +65,7 @@ jobs:
- uses: actions/setup-node@v6
if: env.SKIP_RELEASE == 'false'
with:
node-version: 24.12.0
node-version: 24.13.0
cache: "pnpm"
- run: npm i -g pnpm
if: env.SKIP_RELEASE == 'false'
@@ -27,7 +27,7 @@ jobs:
exit 1
fi
prebuilt-debian-validate-arm64:
runs-on: ubuntu-24.04-
runs-on: ubuntu-24.04-arm
timeout-minutes: 5
steps:
- uses: actions/checkout@v6
+7 -9
View File
@@ -2,7 +2,7 @@ permissions: {}
on:
release:
types: [published]
types: [released]
jobs:
trigger-docs-release:
@@ -37,6 +37,7 @@ jobs:
}
}
EOF
update-bug-report-template:
name: Update Bug Report Template
runs-on: ubuntu-latest
@@ -54,23 +55,20 @@ jobs:
uses: actions/checkout@v6
with:
token: ${{ steps.obtainToken.outputs.token }}
ref: dev
- name: Setup
uses: ./tooling/github/setup
- run: pnpm run scripts:update-bug-report-template
env:
NEXT_VERSION: ${{ github.event.release.tag_name }}
- name: Commit changes
run: |
git config --global user.email "175486441+homarr-releases[bot]@users.noreply.github.com"
git config --global user.name "Releases Homarr"
git checkout -b update-bug-report-template
git add .
git commit -m "chore: update bug report template"
- name: Create Pull Request
id: create-pull-request
uses: peter-evans/create-pull-request@v8
uses: peter-evans/create-pull-request@v7
with:
add-paths: .github/ISSUE_TEMPLATE/bug_report.yml
commit-message: "chore: update bug report template"
author: Releases Homarr <175486441+homarr-releases[bot]@users.noreply.github.com>
token: ${{ steps.obtainToken.outputs.token }}
branch: update-bug-report-template
base: dev
+1 -1
View File
@@ -1 +1 @@
24.12.0
24.13.0
+129
View File
@@ -1,3 +1,132 @@
## [1.53.1](https://github.com/homarr-labs/homarr/compare/v1.53.0...v1.53.1) (2026-02-13)
### Bug Fixes
* **deps:** update dependency @ianvs/prettier-plugin-sort-imports to ^4.7.1 ([#5021](https://github.com/homarr-labs/homarr/issues/5021)) ([5946e6c](https://github.com/homarr-labs/homarr/commit/5946e6c7193eded77b98c76aedff71a7bb912574))
* **deps:** update dependency @octokit/auth-app to ^8.2.0 ([#5009](https://github.com/homarr-labs/homarr/issues/5009)) ([4a86361](https://github.com/homarr-labs/homarr/commit/4a86361134da404462b1a9f8ff98fe3504fade0d))
* **deps:** update dependency dotenv to ^17.2.4 ([#5029](https://github.com/homarr-labs/homarr/issues/5029)) ([e8c7f45](https://github.com/homarr-labs/homarr/commit/e8c7f454768044540ee37d75fc73654b74315390))
* **deps:** update dependency fast-xml-parser to ^5.3.5 ([#5050](https://github.com/homarr-labs/homarr/issues/5050)) ([30f561f](https://github.com/homarr-labs/homarr/commit/30f561f85ad2abb90ccb9fa3292155d51f1f379b))
* **deps:** update dependency fastify to ^5.7.4 ([#5027](https://github.com/homarr-labs/homarr/issues/5027)) ([18e16d6](https://github.com/homarr-labs/homarr/commit/18e16d687f8137e5b5c55cf2385436b714a2d27b))
* **deps:** update dependency glob to ^13.0.1 ([#5013](https://github.com/homarr-labs/homarr/issues/5013)) ([3b21c3e](https://github.com/homarr-labs/homarr/commit/3b21c3ef765add0f7cdc8f66ae8f1b7aac3cf51e))
* **deps:** update dependency isomorphic-dompurify to ^2.36.0 ([#5041](https://github.com/homarr-labs/homarr/issues/5041)) ([e561fc5](https://github.com/homarr-labs/homarr/commit/e561fc550fab2207212ae108a5177a248795cf66))
* **deps:** update dependency jotai to ^2.17.1 ([#5019](https://github.com/homarr-labs/homarr/issues/5019)) ([da96566](https://github.com/homarr-labs/homarr/commit/da965668d021ebebd8c8a7e2a4560577a6b0828b))
* **deps:** update dependency ldapts to v8.1.5 ([#5004](https://github.com/homarr-labs/homarr/issues/5004)) ([c3932b1](https://github.com/homarr-labs/homarr/commit/c3932b18f03b86e8ee049c14ace63119fd2ab0d6))
* **deps:** update dependency ldapts to v8.1.6 ([#5018](https://github.com/homarr-labs/homarr/issues/5018)) ([c92d487](https://github.com/homarr-labs/homarr/commit/c92d487ceaa9159579ef4352d763429887953bb5))
* **deps:** update dependency mysql2 to v3.16.3 ([#5014](https://github.com/homarr-labs/homarr/issues/5014)) ([04b3598](https://github.com/homarr-labs/homarr/commit/04b35980f5997e744a455a847f28b1a676f9861e))
* **deps:** update dependency next-intl to v4.8.2 ([#5005](https://github.com/homarr-labs/homarr/issues/5005)) ([b67fecd](https://github.com/homarr-labs/homarr/commit/b67fecd3963bc3112ab8ecd91385bbe13c982290))
* **deps:** update dependency tsdav to ^2.1.7 ([#5033](https://github.com/homarr-labs/homarr/issues/5033)) ([d694b1a](https://github.com/homarr-labs/homarr/commit/d694b1a5410833a791d57fb3dd4650003510140e))
* **deps:** update dependency video.js to ^8.23.7 ([#5034](https://github.com/homarr-labs/homarr/issues/5034)) ([6efabd4](https://github.com/homarr-labs/homarr/commit/6efabd436849b9fdea0d060fe7beaa9c67424c29))
* **deps:** update tiptap monorepo to v3.19.0 ([#5012](https://github.com/homarr-labs/homarr/issues/5012)) ([ad41a91](https://github.com/homarr-labs/homarr/commit/ad41a918ef72f322015a02e9601c43728e680b34))
* **deps:** update turbo monorepo to ^2.8.2 ([#5010](https://github.com/homarr-labs/homarr/issues/5010)) ([b479fea](https://github.com/homarr-labs/homarr/commit/b479fea6eb0b025b55668201160a5e57267de2e7))
* **deps:** update turbo monorepo to ^2.8.3 ([#5016](https://github.com/homarr-labs/homarr/issues/5016)) ([f1d2f07](https://github.com/homarr-labs/homarr/commit/f1d2f07f3888e7567b56ae61a9d137255a2b8529))
* **sections:** dynamic sections vanish when adding category ([#5046](https://github.com/homarr-labs/homarr/issues/5046)) ([60fcb71](https://github.com/homarr-labs/homarr/commit/60fcb71bd2616af3e99b20cbbcd1b0417a0fff76))
* **seerr:** use reasonable limits for amount of returned entries ([#5001](https://github.com/homarr-labs/homarr/issues/5001)) ([be1a26a](https://github.com/homarr-labs/homarr/commit/be1a26a98d2ed9d25969ded5ae64705c001f71dd))
## [1.53.0](https://github.com/homarr-labs/homarr/compare/v1.52.0...v1.53.0) (2026-02-06)
### Features
* **analytics:** consolidate server analytics into single comprehensive Umami event ([#4938](https://github.com/homarr-labs/homarr/issues/4938)) ([10848db](https://github.com/homarr-labs/homarr/commit/10848db595b2254b1485ea168d1c327b907d9ff8))
### Bug Fixes
* **deps:** update dependency @next/eslint-plugin-next to v16.1.5 ([#4959](https://github.com/homarr-labs/homarr/issues/4959)) ([ec40309](https://github.com/homarr-labs/homarr/commit/ec40309cde2280cf689856d4f78fb1500b583130))
* **deps:** update dependency @paralleldrive/cuid2 to ^3.3.0 ([#4952](https://github.com/homarr-labs/homarr/issues/4952)) ([a9db68b](https://github.com/homarr-labs/homarr/commit/a9db68bd3eaea6a4564cd6842054ea60cc45e3a3))
* **deps:** update dependency @tanstack/react-query-devtools to ^5.91.3 ([#4985](https://github.com/homarr-labs/homarr/issues/4985)) ([1115ad1](https://github.com/homarr-labs/homarr/commit/1115ad1364bca84dee33aa42499c986bdad2c528))
* **deps:** update dependency fast-xml-parser to ^5.3.4 ([#4982](https://github.com/homarr-labs/homarr/issues/4982)) ([460d53c](https://github.com/homarr-labs/homarr/commit/460d53cafa1abeebf4dea7b1bb1e920267c2f9fe))
* **deps:** update dependency fastify to ^5.7.2 ([#4955](https://github.com/homarr-labs/homarr/issues/4955)) ([0eab26c](https://github.com/homarr-labs/homarr/commit/0eab26cdace47c0b19519372a3daa6998e0c8207))
* **deps:** update dependency jotai to ^2.17.0 ([#4972](https://github.com/homarr-labs/homarr/issues/4972)) ([e67483f](https://github.com/homarr-labs/homarr/commit/e67483fea56f0b06fa54e68b8dd62fd0b5dedadd))
* **deps:** update dependency ldapts to v8.1.4 ([#4993](https://github.com/homarr-labs/homarr/issues/4993)) ([c2d9f18](https://github.com/homarr-labs/homarr/commit/c2d9f18e4ef28f063e4abf1175cd90ba746410b7))
* **deps:** update dependency mysql2 to v3.16.2 ([#4961](https://github.com/homarr-labs/homarr/issues/4961)) ([5c6eafb](https://github.com/homarr-labs/homarr/commit/5c6eafb272436b78d4668d562d50001bca48e6d3))
* **deps:** update dependency next-intl to v4.8.0 ([#4977](https://github.com/homarr-labs/homarr/issues/4977)) ([c3a7ab5](https://github.com/homarr-labs/homarr/commit/c3a7ab52ee3acbcf47255d5813317c3cf67ea49f))
* **deps:** update dependency next-intl to v4.8.1 ([#4986](https://github.com/homarr-labs/homarr/issues/4986)) ([62b6939](https://github.com/homarr-labs/homarr/commit/62b6939b92f29618cc6d13a189b65df1922779ba))
* **deps:** update dependency pg to ^8.18.0 ([#4989](https://github.com/homarr-labs/homarr/issues/4989)) ([c3071a3](https://github.com/homarr-labs/homarr/commit/c3071a3c95f3a30438050aa37c65950cccabf681))
* **deps:** update dependency typescript-eslint to ^8.54.0 ([#4958](https://github.com/homarr-labs/homarr/issues/4958)) ([e88d126](https://github.com/homarr-labs/homarr/commit/e88d126355b96ac5060b552047c191f8b284461c))
* **deps:** update dependency video.js to ^8.23.6 ([#4992](https://github.com/homarr-labs/homarr/issues/4992)) ([4209f7c](https://github.com/homarr-labs/homarr/commit/4209f7c70e75870f56b93a97f3b6053962ee3ff7))
* **deps:** update mantine monorepo to ^8.3.14 ([#4998](https://github.com/homarr-labs/homarr/issues/4998)) ([0fafa50](https://github.com/homarr-labs/homarr/commit/0fafa505ac1c7f4ddb33ee5e8dedca9a883164ba))
* **deps:** update nextjs monorepo to v16.1.6 ([#4969](https://github.com/homarr-labs/homarr/issues/4969)) ([7c3fe3d](https://github.com/homarr-labs/homarr/commit/7c3fe3d6d47879c67950b3dc4d7e39adbc06c146))
* **deps:** update react monorepo to v19.2.4 ([#4960](https://github.com/homarr-labs/homarr/issues/4960)) ([d3e0b47](https://github.com/homarr-labs/homarr/commit/d3e0b47875998fc766e1c5f0481244fc659b0c49))
* **deps:** update tiptap monorepo to v3.18.0 ([#4975](https://github.com/homarr-labs/homarr/issues/4975)) ([24e24dc](https://github.com/homarr-labs/homarr/commit/24e24dc634a9e5a25ab934541225996e62ac31be))
* **deps:** update trpc monorepo to ^11.9.0 ([#4970](https://github.com/homarr-labs/homarr/issues/4970)) ([aeb6e0f](https://github.com/homarr-labs/homarr/commit/aeb6e0f40659bf1c514380a6c96858afdaf7e6db))
* **deps:** update turbo monorepo to ^2.8.0 ([#4978](https://github.com/homarr-labs/homarr/issues/4978)) ([054ca57](https://github.com/homarr-labs/homarr/commit/054ca57188656ddac7aaa16f792269eaa2ef319b))
* **deps:** update turbo monorepo to ^2.8.1 ([#4991](https://github.com/homarr-labs/homarr/issues/4991)) ([43b6246](https://github.com/homarr-labs/homarr/commit/43b6246876debccbe7239c8ee67753e17527e469))
## [1.52.0](https://github.com/homarr-labs/homarr/compare/v1.51.0...v1.52.0) (2026-01-30)
### Features
* **installations:** support docker secrets file for encryption key ([#4946](https://github.com/homarr-labs/homarr/issues/4946)) ([9ba8213](https://github.com/homarr-labs/homarr/commit/9ba82133da2ae472952358f84d8ee1758c0f108a))
### Bug Fixes
* **deps:** update dependency @tanstack/react-query to ^5.90.20 ([#4939](https://github.com/homarr-labs/homarr/issues/4939)) ([840940b](https://github.com/homarr-labs/homarr/commit/840940bab663e728b8516ac48f913fef2b5c61b7))
* **deps:** update dependency next to v16.1.5 [security] ([#4937](https://github.com/homarr-labs/homarr/issues/4937)) ([aeb1df1](https://github.com/homarr-labs/homarr/commit/aeb1df122926c7bed71bea9b21f1c42c45cc9b3e))
* **deps:** update dependency pg to ^8.17.2 ([#4916](https://github.com/homarr-labs/homarr/issues/4916)) ([a50a29a](https://github.com/homarr-labs/homarr/commit/a50a29a778689efcca0afc2b640fdb497e6e7d98))
* **deps:** update dependency prettier to ^3.8.1 ([#4925](https://github.com/homarr-labs/homarr/issues/4925)) ([a727b8e](https://github.com/homarr-labs/homarr/commit/a727b8e323b9fb7cba536909a51fabde0a992a69))
* **deps:** update dependency sass to ^1.97.3 ([#4927](https://github.com/homarr-labs/homarr/issues/4927)) ([b1658a5](https://github.com/homarr-labs/homarr/commit/b1658a5d01b5c12f391af9d326ec98b3da000f9e))
* **deps:** update dependency typescript-eslint to ^8.53.1 ([#4904](https://github.com/homarr-labs/homarr/issues/4904)) ([c58da00](https://github.com/homarr-labs/homarr/commit/c58da0095738352515d6d8c5e81b3c34c8726ffe))
* **deps:** update mantine monorepo to ^8.3.13 ([#4911](https://github.com/homarr-labs/homarr/issues/4911)) ([f2eec74](https://github.com/homarr-labs/homarr/commit/f2eec748494480e773b45a309aa89ae3862e2b05))
* **deps:** update nextjs monorepo to v16.1.4 ([#4909](https://github.com/homarr-labs/homarr/issues/4909)) ([99a2574](https://github.com/homarr-labs/homarr/commit/99a2574d80ad5a7dfe3b9c92d43bd4b9423bf22d))
* **deps:** update tiptap monorepo to v3.16.0 ([#4912](https://github.com/homarr-labs/homarr/issues/4912)) ([2354510](https://github.com/homarr-labs/homarr/commit/23545101b61e456fd886eedb4b3d86b8cc606639))
* **deps:** update tiptap monorepo to v3.17.0 ([#4940](https://github.com/homarr-labs/homarr/issues/4940)) ([d030261](https://github.com/homarr-labs/homarr/commit/d03026187cb6451d727167b02ac138f9c7ccc754))
* **deps:** update tiptap monorepo to v3.17.1 ([#4945](https://github.com/homarr-labs/homarr/issues/4945)) ([b354085](https://github.com/homarr-labs/homarr/commit/b354085c7adfb6e5f3cad51b5b825426e072e874))
* **deps:** update turbo monorepo to ^2.7.6 ([#4947](https://github.com/homarr-labs/homarr/issues/4947)) ([e078237](https://github.com/homarr-labs/homarr/commit/e078237e31d11029987c6c4370fd8f65023b87bc))
## [1.51.0](https://github.com/homarr-labs/homarr/compare/v1.50.1...v1.51.0) (2026-01-23)
### Features
* **integrations:** add Coolify integration and widget ([#4789](https://github.com/homarr-labs/homarr/issues/4789)) ([81dac58](https://github.com/homarr-labs/homarr/commit/81dac580050a86e34135beef09b876089777f1c7))
* **widgets:** add disks widget ([#4445](https://github.com/homarr-labs/homarr/issues/4445)) ([62caa71](https://github.com/homarr-labs/homarr/commit/62caa71a48c38f59f109666e83f26019586a5ca0))
### Bug Fixes
* **deps:** update dependency @tanstack/react-query to ^5.90.17 ([#4873](https://github.com/homarr-labs/homarr/issues/4873)) ([624bd55](https://github.com/homarr-labs/homarr/commit/624bd55b117b2b9f9109aecdeabf1515c567656e))
* **deps:** update dependency @tanstack/react-query to ^5.90.19 ([#4888](https://github.com/homarr-labs/homarr/issues/4888)) ([fa84bd5](https://github.com/homarr-labs/homarr/commit/fa84bd569fdf6c9aecfcb9b4d8fb20d14215160b))
* **deps:** update dependency better-sqlite3 to ^12.6.0 ([#4853](https://github.com/homarr-labs/homarr/issues/4853)) ([9d4fb9e](https://github.com/homarr-labs/homarr/commit/9d4fb9eb462a0297618c70f619618f94d8857e1f))
* **deps:** update dependency better-sqlite3 to ^12.6.2 ([#4891](https://github.com/homarr-labs/homarr/issues/4891)) ([63a0793](https://github.com/homarr-labs/homarr/commit/63a0793c6ea02456a49a07635b927adf3a314ee0))
* **deps:** update dependency fastify to ^5.7.0 ([#4882](https://github.com/homarr-labs/homarr/issues/4882)) ([b9bc9dd](https://github.com/homarr-labs/homarr/commit/b9bc9dd38d22f03a0faa59a68056192c3f1519d4))
* **deps:** update dependency fastify to ^5.7.1 ([#4887](https://github.com/homarr-labs/homarr/issues/4887)) ([02e722a](https://github.com/homarr-labs/homarr/commit/02e722aa4531e816bb563628ebbb7e8b0cf93ce3))
* **deps:** update dependency ioredis to v5.9.2 ([#4881](https://github.com/homarr-labs/homarr/issues/4881)) ([e3ba1ee](https://github.com/homarr-labs/homarr/commit/e3ba1ee931b0e53fb94bf0e50fae81eecfade237))
* **deps:** update dependency jotai to ^2.16.2 ([#4869](https://github.com/homarr-labs/homarr/issues/4869)) ([2e58acc](https://github.com/homarr-labs/homarr/commit/2e58acc3bd5da474bfe0636a58b43759947ef2d2))
* **deps:** update dependency mysql2 to v3.16.1 ([#4886](https://github.com/homarr-labs/homarr/issues/4886)) ([40ee667](https://github.com/homarr-labs/homarr/commit/40ee667832124075b0730a54a4b8019365ab8794))
* **deps:** update dependency pg to ^8.17.0 ([#4874](https://github.com/homarr-labs/homarr/issues/4874)) ([b923891](https://github.com/homarr-labs/homarr/commit/b923891fac4cd61c5a1a8505d5bcfb737255196f))
* **deps:** update dependency pg to ^8.17.1 ([#4877](https://github.com/homarr-labs/homarr/issues/4877)) ([fcd4171](https://github.com/homarr-labs/homarr/commit/fcd417198f4a1afc250455bf25594a32f61b1070))
* **deps:** update dependency prettier to ^3.8.0 ([#4876](https://github.com/homarr-labs/homarr/issues/4876)) ([3ade915](https://github.com/homarr-labs/homarr/commit/3ade915d35540578a7f193baf99cbdbf89103b97))
* **deps:** update dependency react-error-boundary to ^6.1.0 ([#4884](https://github.com/homarr-labs/homarr/issues/4884)) ([41b02b6](https://github.com/homarr-labs/homarr/commit/41b02b63d9a1f9b73cc54371bbc1b6161a4d76d0))
* **deps:** update dependency typescript-eslint to ^8.53.0 ([#4863](https://github.com/homarr-labs/homarr/issues/4863)) ([e9020e6](https://github.com/homarr-labs/homarr/commit/e9020e68ecf9e33df983108e7ab239776874413c))
* **deps:** update nextjs monorepo to v16.1.2 ([#4875](https://github.com/homarr-labs/homarr/issues/4875)) ([c6be8c5](https://github.com/homarr-labs/homarr/commit/c6be8c5475722e5a6dbc886e5e7f24ef8a04c470))
* **deps:** update nextjs monorepo to v16.1.3 ([#4889](https://github.com/homarr-labs/homarr/issues/4889)) ([5a8e864](https://github.com/homarr-labs/homarr/commit/5a8e864630b61595b53a9e849973460ffdce5fd2))
* **deps:** update turbo monorepo to ^2.7.4 ([#4861](https://github.com/homarr-labs/homarr/issues/4861)) ([0c38e2f](https://github.com/homarr-labs/homarr/commit/0c38e2f290fc6dcb9608b338ee38409afb3beabe))
* **deps:** update turbo monorepo to ^2.7.5 ([#4892](https://github.com/homarr-labs/homarr/issues/4892)) ([c847f60](https://github.com/homarr-labs/homarr/commit/c847f6004dc4c166969ee1248ec64b7d27ba8362))
### Performance Improvements
* **memory:** lazy routers ([#4868](https://github.com/homarr-labs/homarr/issues/4868)) ([1623fba](https://github.com/homarr-labs/homarr/commit/1623fbaaeb41b16e13dcd401a00f70711a283bf9))
## [1.50.1](https://github.com/homarr-labs/homarr/compare/v1.50.0...v1.50.1) (2026-01-16)
### Bug Fixes
* **deps:** update dependency ioredis to v5.9.0 ([#4827](https://github.com/homarr-labs/homarr/issues/4827)) ([155d4f2](https://github.com/homarr-labs/homarr/commit/155d4f2270b3b35c4ad696499b0aaa0b10100989))
* **deps:** update dependency ioredis to v5.9.1 ([#4844](https://github.com/homarr-labs/homarr/issues/4844)) ([5d00642](https://github.com/homarr-labs/homarr/commit/5d006422688cf3fe7440ae3ab66ad3b2cc9286a8))
* **deps:** update dependency ldapts to v8.1.3 ([#4841](https://github.com/homarr-labs/homarr/issues/4841)) ([7fa9907](https://github.com/homarr-labs/homarr/commit/7fa990712bddc88bbb3bbe01e758bfef7cb4dea3))
* **deps:** update dependency react-error-boundary to ^6.0.2 ([#4821](https://github.com/homarr-labs/homarr/issues/4821)) ([e9ba102](https://github.com/homarr-labs/homarr/commit/e9ba102cf668c0ef54628d3dbc6e6cbda2d059b5))
* **deps:** update dependency react-error-boundary to ^6.0.3 ([#4847](https://github.com/homarr-labs/homarr/issues/4847)) ([c24006d](https://github.com/homarr-labs/homarr/commit/c24006dca691f26a7187c0ba112d9ed2ec424bb0))
* **deps:** update dependency sass to ^1.97.2 ([#4835](https://github.com/homarr-labs/homarr/issues/4835)) ([07ba531](https://github.com/homarr-labs/homarr/commit/07ba53165c90d675aa54c5ad3fca930fef5cd35e))
* **deps:** update dependency typescript-eslint to ^8.52.0 ([#4830](https://github.com/homarr-labs/homarr/issues/4830)) ([fa8af6a](https://github.com/homarr-labs/homarr/commit/fa8af6a453b846af2305db3c318c8c1c303a3a88))
* **deps:** update dependency undici to v7.17.0 ([#4826](https://github.com/homarr-labs/homarr/issues/4826)) ([21a91b1](https://github.com/homarr-labs/homarr/commit/21a91b1489ff1a1f0a1428a3f50f00db8932da72))
* **deps:** update dependency undici to v7.18.0 ([#4829](https://github.com/homarr-labs/homarr/issues/4829)) ([b76ab29](https://github.com/homarr-labs/homarr/commit/b76ab2961d84081c9ef04d76193f21a1068e72d9))
* **deps:** update dependency undici to v7.18.2 ([#4837](https://github.com/homarr-labs/homarr/issues/4837)) ([16733c2](https://github.com/homarr-labs/homarr/commit/16733c2a0efabcbc5b693a8b6f82833f6fc344b7))
* **deps:** update dependency ws to ^8.19.0 ([#4833](https://github.com/homarr-labs/homarr/issues/4833)) ([629359e](https://github.com/homarr-labs/homarr/commit/629359e3e44ddad880842cfd576edb514f80d61a))
* **deps:** update mantine monorepo to ^8.3.11 ([#4822](https://github.com/homarr-labs/homarr/issues/4822)) ([0364e10](https://github.com/homarr-labs/homarr/commit/0364e102cd6c0f560bc49e0b9ccd71df0b75eed6))
* **deps:** update mantine monorepo to ^8.3.12 ([#4848](https://github.com/homarr-labs/homarr/issues/4848)) ([275a346](https://github.com/homarr-labs/homarr/commit/275a346afaaebfa894ef2193f70966986a138dbb))
* **deps:** update tiptap monorepo to v3.15.0 ([#4832](https://github.com/homarr-labs/homarr/issues/4832)) ([ab3ee4f](https://github.com/homarr-labs/homarr/commit/ab3ee4f78a739bdb3b49a81652420df6ec143b62))
* **deps:** update tiptap monorepo to v3.15.1 ([#4838](https://github.com/homarr-labs/homarr/issues/4838)) ([d479b63](https://github.com/homarr-labs/homarr/commit/d479b63a803f2295ccdf20fcd31c418a4aab148c))
* **deps:** update tiptap monorepo to v3.15.2 ([#4842](https://github.com/homarr-labs/homarr/issues/4842)) ([55c2666](https://github.com/homarr-labs/homarr/commit/55c2666f9d27ca34b6d028070f0d7b84e4c40e97))
* **deps:** update tiptap monorepo to v3.15.3 ([#4843](https://github.com/homarr-labs/homarr/issues/4843)) ([b26cf0e](https://github.com/homarr-labs/homarr/commit/b26cf0e65fd8150e241465628df2cb8b5a72088e))
* **deps:** update turbo monorepo to ^2.7.3 ([#4831](https://github.com/homarr-labs/homarr/issues/4831)) ([50410fe](https://github.com/homarr-labs/homarr/commit/50410fedb3f33ed131f923257e61ae2dca4e0288))
## [1.50.0](https://github.com/homarr-labs/homarr/compare/v1.49.1...v1.50.0) (2026-01-09)
### Features
+1 -1
View File
@@ -1,4 +1,4 @@
FROM node:24.12.0-alpine AS base
FROM node:24.13.0-alpine AS base
FROM base AS builder
RUN apk add --no-cache libc6-compat
+24 -24
View File
@@ -48,21 +48,21 @@
"@homarr/ui": "workspace:^0.1.0",
"@homarr/validation": "workspace:^0.1.0",
"@homarr/widgets": "workspace:^0.1.0",
"@mantine/colors-generator": "^8.3.10",
"@mantine/core": "^8.3.10",
"@mantine/dropzone": "^8.3.10",
"@mantine/hooks": "^8.3.10",
"@mantine/modals": "^8.3.10",
"@mantine/tiptap": "^8.3.10",
"@mantine/colors-generator": "^8.3.14",
"@mantine/core": "^8.3.14",
"@mantine/dropzone": "^8.3.14",
"@mantine/hooks": "^8.3.14",
"@mantine/modals": "^8.3.14",
"@mantine/tiptap": "^8.3.14",
"@million/lint": "1.0.14",
"@tabler/icons-react": "^3.36.1",
"@tanstack/react-query": "^5.90.16",
"@tanstack/react-query-devtools": "^5.91.2",
"@tanstack/react-query": "^5.90.20",
"@tanstack/react-query-devtools": "^5.91.3",
"@tanstack/react-query-next-experimental": "^5.91.0",
"@trpc/client": "^11.8.1",
"@trpc/next": "^11.8.1",
"@trpc/react-query": "^11.8.1",
"@trpc/server": "^11.8.1",
"@trpc/client": "^11.9.0",
"@trpc/next": "^11.9.0",
"@trpc/react-query": "^11.9.0",
"@trpc/server": "^11.9.0",
"@xterm/addon-canvas": "^0.7.0",
"@xterm/addon-fit": "0.11.0",
"@xterm/xterm": "^6.0.0",
@@ -70,20 +70,20 @@
"chroma-js": "^3.2.0",
"clsx": "^2.1.1",
"dayjs": "^1.11.19",
"dotenv": "^17.2.3",
"dotenv": "^17.2.4",
"flag-icons": "^7.5.0",
"glob": "^13.0.0",
"isomorphic-dompurify": "^2.35.0",
"jotai": "^2.16.1",
"glob": "^13.0.1",
"isomorphic-dompurify": "^2.36.0",
"jotai": "^2.17.1",
"mantine-react-table": "2.0.0-beta.9",
"next": "16.1.1",
"next": "16.1.6",
"postcss-preset-mantine": "^1.18.0",
"prismjs": "^1.30.0",
"react": "19.2.3",
"react-dom": "19.2.3",
"react-error-boundary": "^6.0.1",
"react": "19.2.4",
"react-dom": "19.2.4",
"react-error-boundary": "^6.1.0",
"react-simple-code-editor": "^0.14.1",
"sass": "^1.97.1",
"sass": "^1.97.3",
"superjson": "2.2.6",
"swagger-ui-react": "^5.31.0",
"use-deep-compare-effect": "^1.8.1",
@@ -94,15 +94,15 @@
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
"@types/chroma-js": "3.1.2",
"@types/node": "^24.10.4",
"@types/node": "^24.10.12",
"@types/prismjs": "^1.26.5",
"@types/react": "19.2.7",
"@types/react": "19.2.13",
"@types/react-dom": "19.2.3",
"@types/swagger-ui-react": "^5.18.0",
"concurrently": "^9.2.1",
"eslint": "^9.39.2",
"node-loader": "^2.1.0",
"prettier": "^3.7.4",
"prettier": "^3.8.1",
"typescript": "^5.9.3"
}
}
@@ -1,6 +1,5 @@
"use client";
import { startTransition } from "react";
import { Button, Card, Group, Stack, Switch, Text } from "@mantine/core";
import { IconArrowRight } from "@tabler/icons-react";
import type { z } from "zod/v4";
@@ -24,16 +23,6 @@ export const InitSettings = () => {
});
const form = useZodForm(settingsInitSchema, { initialValues: defaultServerSettings });
form.watch("analytics.enableGeneral", ({ value }) => {
if (!value) {
startTransition(() => {
form.setFieldValue("analytics.enableWidgetData", false);
form.setFieldValue("analytics.enableIntegrationData", false);
form.setFieldValue("analytics.enableUserData", false);
});
}
});
const handleSubmitAsync = async (values: z.infer<typeof settingsInitSchema>) => {
await mutateAsync(values);
};
@@ -47,24 +36,6 @@ export const InitSettings = () => {
<Stack gap="xs">
<AnalyticsRow kind="general" {...form.getInputProps("analytics.enableGeneral", { type: "checkbox" })} />
<Stack gap="xs" ps="md" w="100%">
<AnalyticsRow
kind="integrationData"
disabled={!form.values.analytics.enableGeneral}
{...form.getInputProps("analytics.enableWidgetData", { type: "checkbox" })}
/>
<AnalyticsRow
kind="widgetData"
disabled={!form.values.analytics.enableGeneral}
{...form.getInputProps("analytics.enableIntegrationData", { type: "checkbox" })}
/>
<AnalyticsRow
kind="usersData"
disabled={!form.values.analytics.enableGeneral}
{...form.getInputProps("analytics.enableUserData", { type: "checkbox" })}
/>
</Stack>
</Stack>
</Stack>
</Card>
@@ -24,15 +24,6 @@ export const AnalyticsSettings = ({ initialData }: AnalyticsSettingsProps) => {
return;
}
if (
!updatedValues.enableGeneral &&
(updatedValues.enableWidgetData || updatedValues.enableIntegrationData || updatedValues.enableUserData)
) {
updatedValues.enableIntegrationData = false;
updatedValues.enableUserData = false;
updatedValues.enableWidgetData = false;
}
void mutateAsync({
settingsKey: "analytics",
value: updatedValues,
@@ -54,30 +45,6 @@ export const AnalyticsSettings = ({ initialData }: AnalyticsSettingsProps) => {
<LoadingOverlay visible={isPending} zIndex={1000} overlayProps={{ radius: "sm", blur: 2 }} />
<Stack>
<SwitchSetting form={form} formKey="enableGeneral" title={t("general.title")} text={t("general.text")} />
<SwitchSetting
form={form}
formKey="enableIntegrationData"
ms="xl"
title={t("integrationData.title")}
text={t("integrationData.text")}
disabled={!form.values.enableGeneral}
/>
<SwitchSetting
form={form}
formKey="enableWidgetData"
ms="xl"
title={t("widgetData.title")}
text={t("widgetData.text")}
disabled={!form.values.enableGeneral}
/>
<SwitchSetting
form={form}
formKey="enableUserData"
ms="xl"
title={t("usersData.title")}
text={t("usersData.text")}
disabled={!form.values.enableGeneral}
/>
</Stack>
</Card>
</>
@@ -105,7 +105,7 @@ export const WidgetPreviewPageContent = ({ kind, integrationData }: WidgetPrevie
<ErrorBoundary
onReset={reset}
fallbackRender={({ resetErrorBoundary, error }) => (
<WidgetError kind={kind} error={error as unknown} resetErrorBoundary={resetErrorBoundary} />
<WidgetError kind={kind} error={error} resetErrorBoundary={resetErrorBoundary} />
)}
>
<Comp
@@ -108,7 +108,7 @@ const InnerContent = ({ item, ...dimensions }: InnerContentProps) => {
fallbackRender={({ resetErrorBoundary, error }) => (
<>
<BoardItemMenu offset={4} item={newItem} resetErrorBoundary={resetErrorBoundary} />
<WidgetError kind={item.kind} error={error as unknown} resetErrorBoundary={resetErrorBoundary} />
<WidgetError kind={item.kind} error={error} resetErrorBoundary={resetErrorBoundary} />
</>
)}
>
@@ -58,6 +58,7 @@ export const useCategoryActions = () => {
...section,
yOffset: section.yOffset + 2,
})),
...previous.sections.filter((section) => section.kind !== "category" && section.kind !== "empty"),
] satisfies Section[],
}));
},
+6 -6
View File
@@ -38,20 +38,20 @@
"@homarr/validation": "workspace:^0.1.0",
"@homarr/widgets": "workspace:^0.1.0",
"dayjs": "^1.11.19",
"dotenv": "^17.2.3",
"fastify": "^5.6.2",
"dotenv": "^17.2.4",
"fastify": "^5.7.4",
"superjson": "2.2.6",
"undici": "7.16.0"
"undici": "7.18.2"
},
"devDependencies": {
"@homarr/eslint-config": "workspace:^0.2.0",
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
"@types/node": "^24.10.4",
"@types/node": "^24.10.12",
"dotenv-cli": "^11.0.0",
"esbuild": "^0.27.2",
"esbuild": "^0.27.3",
"eslint": "^9.39.2",
"prettier": "^3.7.4",
"prettier": "^3.8.1",
"tsx": "4.20.4",
"typescript": "^5.9.3"
}
+4 -4
View File
@@ -25,18 +25,18 @@
"@homarr/definitions": "workspace:^0.1.0",
"@homarr/redis": "workspace:^0.1.0",
"@homarr/validation": "workspace:^0.1.0",
"dotenv": "^17.2.3",
"dotenv": "^17.2.4",
"tsx": "4.20.4",
"ws": "^8.18.3"
"ws": "^8.19.0"
},
"devDependencies": {
"@homarr/eslint-config": "workspace:^0.2.0",
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
"@types/ws": "^8.18.1",
"esbuild": "^0.27.2",
"esbuild": "^0.27.3",
"eslint": "^9.39.2",
"prettier": "^3.7.4",
"prettier": "^3.8.1",
"typescript": "^5.9.3"
}
}
+1 -1
View File
@@ -1,4 +1,4 @@
FROM node:24.12.0-trixie AS base
FROM node:24.13.0-trixie AS base
WORKDIR /app
COPY package.json .
COPY pnpm-lock.yaml .
+4 -4
View File
@@ -2,12 +2,12 @@
"name": "homarr-prebuilt-debian",
"private": true,
"dependencies": {
"better-sqlite3": "^12.5.0"
"better-sqlite3": "^12.6.2"
},
"packageManager": "pnpm@10.27.0",
"packageManager": "pnpm@10.29.1",
"engines": {
"node": ">=24.12.0",
"pnpm": ">=10.27.0"
"node": ">=24.13.0",
"pnpm": ">=10.29.1"
},
"pnpm": {
"onlyBuiltDependencies": [
+5 -5
View File
@@ -9,16 +9,16 @@ importers:
.:
dependencies:
better-sqlite3:
specifier: ^12.5.0
version: 12.5.0
specifier: ^12.6.2
version: 12.6.2
packages:
base64-js@1.5.1:
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
better-sqlite3@12.5.0:
resolution: {integrity: sha512-WwCZ/5Diz7rsF29o27o0Gcc1Du+l7Zsv7SYtVPG0X3G/uUI1LqdxrQI7c9Hs2FWpqXXERjW9hp6g3/tH7DlVKg==}
better-sqlite3@12.6.2:
resolution: {integrity: sha512-8VYKM3MjCa9WcaSAI3hzwhmyHVlH8tiGFwf0RlTsZPWJ1I5MkzjiudCo4KC4DxOaL/53A5B1sI/IbldNFDbsKA==}
engines: {node: 20.x || 22.x || 23.x || 24.x || 25.x}
bindings@1.5.0:
@@ -147,7 +147,7 @@ snapshots:
base64-js@1.5.1: {}
better-sqlite3@12.5.0:
better-sqlite3@12.6.2:
dependencies:
bindings: 1.5.0
prebuild-install: 7.1.3
+27 -20
View File
@@ -78,6 +78,13 @@
</a>
</td>
<td align="center">
<a href="https://homarr.dev/docs/integrations/coolify" target="_blank" rel="noreferrer noopener">
<img src="https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons@master/svg/coolify.svg" alt="Coolify" width="90" height="90" />
<br/>
<p align="center">Coolify</p>
</a>
</td>
<td align="center">
<a href="https://homarr.dev/docs/integrations/dash-dot" target="_blank" rel="noreferrer noopener">
<img src="https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons@master/png/dashdot.png" alt="Dash." width="90" height="90" />
<br/>
@@ -97,15 +104,15 @@
<br/>
<p align="center">Docker<br/>Hub</p>
</a>
</td>
<td align="center">
</td></tr>
<tr><td align="center">
<a href="https://homarr.dev/docs/integrations/emby" target="_blank" rel="noreferrer noopener">
<img src="https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons@master/svg/emby.svg" alt="Emby" width="90" height="90" />
<br/>
<p align="center">Emby</p>
</a>
</td></tr>
<tr><td align="center">
</td>
<td align="center">
<a href="https://homarr.dev/docs/integrations/github" target="_blank" rel="noreferrer noopener">
<img src="https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons@master/svg/github.svg" alt="Github" width="90" height="90" />
<br/>
@@ -146,15 +153,15 @@
<br/>
<p align="center">Jellyfin</p>
</a>
</td>
<td align="center">
</td></tr>
<tr><td align="center">
<a href="https://homarr.dev/docs/integrations/jellyseerr" target="_blank" rel="noreferrer noopener">
<img src="https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons@master/svg/jellyseerr.svg" alt="Jellyseerr" width="90" height="90" />
<br/>
<p align="center">Jellyseerr</p>
</a>
</td></tr>
<tr><td align="center">
</td>
<td align="center">
<a href="https://homarr.dev/docs/integrations/lidarr" target="_blank" rel="noreferrer noopener">
<img src="https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons@master/svg/lidarr.svg" alt="Lidarr" width="90" height="90" />
<br/>
@@ -195,15 +202,15 @@
<br/>
<p align="center">NZBGet</p>
</a>
</td>
<td align="center">
</td></tr>
<tr><td align="center">
<a href="https://homarr.dev/docs/integrations/open-media-vault" target="_blank" rel="noreferrer noopener">
<img src="https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons@master/svg/openmediavault.svg" alt="OpenMediaVault" width="90" height="90" />
<br/>
<p align="center">OpenMediaVault</p>
</a>
</td></tr>
<tr><td align="center">
</td>
<td align="center">
<a href="https://homarr.dev/docs/integrations/opnsense" target="_blank" rel="noreferrer noopener">
<img src="https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons@master/svg/opnsense.svg" alt="OPNsense" width="90" height="90" />
<br/>
@@ -244,15 +251,15 @@
<br/>
<p align="center">Proxmox</p>
</a>
</td>
<td align="center">
</td></tr>
<tr><td align="center">
<a href="https://homarr.dev/docs/integrations/q-bittorent" target="_blank" rel="noreferrer noopener">
<img src="https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons@master/svg/qbittorrent.svg" alt="qBittorrent" width="90" height="90" />
<br/>
<p align="center">qBittorrent</p>
</a>
</td></tr>
<tr><td align="center">
</td>
<td align="center">
<a href="https://homarr.dev/docs/integrations/quay" target="_blank" rel="noreferrer noopener">
<img src="https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons@master/png/quay.png" alt="Quay" width="90" height="90" />
<br/>
@@ -293,15 +300,15 @@
<br/>
<p align="center">Tdarr</p>
</a>
</td>
<td align="center">
</td></tr>
<tr><td align="center">
<a href="https://homarr.dev/docs/integrations/transmission" target="_blank" rel="noreferrer noopener">
<img src="https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons@master/svg/transmission.svg" alt="Transmission" width="90" height="90" />
<br/>
<p align="center">Transmission</p>
</a>
</td></tr>
<tr><td align="center">
</td>
<td align="center">
<a href="https://homarr.dev/docs/integrations/truenas" target="_blank" rel="noreferrer noopener">
<img src="https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons@master/svg/truenas.svg" alt="TrueNAS" width="90" height="90" />
<br/>
+25 -25
View File
@@ -1,6 +1,6 @@
{
"name": "homarr",
"version": "1.50.0",
"version": "1.53.1",
"private": true,
"scripts": {
"build": "cross-env CI=true turbo build",
@@ -39,30 +39,30 @@
"@semantic-release/changelog": "^6.0.3",
"@semantic-release/commit-analyzer": "^13.0.1",
"@semantic-release/git": "^10.0.1",
"@semantic-release/github": "^12.0.2",
"@semantic-release/npm": "^13.1.3",
"@semantic-release/github": "^12.0.5",
"@semantic-release/npm": "^13.1.4",
"@semantic-release/release-notes-generator": "^14.1.0",
"@testcontainers/redis": "^11.11.0",
"@turbo/gen": "^2.7.2",
"@vitejs/plugin-react": "^5.1.2",
"@vitest/coverage-v8": "^4.0.16",
"@vitest/ui": "^4.0.16",
"@turbo/gen": "^2.8.3",
"@vitejs/plugin-react": "^5.1.3",
"@vitest/coverage-v8": "^4.0.18",
"@vitest/ui": "^4.0.18",
"conventional-changelog-conventionalcommits": "^9.1.0",
"cross-env": "^10.1.0",
"jsdom": "^27.4.0",
"jsdom": "^28.0.0",
"json5": "^2.2.3",
"prettier": "^3.7.4",
"semantic-release": "^25.0.2",
"prettier": "^3.8.1",
"semantic-release": "^25.0.3",
"testcontainers": "^11.11.0",
"turbo": "^2.7.2",
"turbo": "^2.8.3",
"typescript": "^5.9.3",
"vite-tsconfig-paths": "^6.0.3",
"vitest": "^4.0.16"
"vite-tsconfig-paths": "^6.1.0",
"vitest": "^4.0.18"
},
"packageManager": "pnpm@10.27.0",
"packageManager": "pnpm@10.29.1",
"engines": {
"node": ">=24.12.0",
"pnpm": ">=10.27.0"
"node": ">=24.13.0",
"pnpm": ">=10.29.1"
},
"pnpm": {
"onlyBuiltDependencies": [
@@ -77,25 +77,25 @@
"tree-sitter-json"
],
"overrides": {
"@babel/helpers@<7.26.10": ">=7.28.4",
"@babel/runtime@<7.26.10": ">=7.28.4",
"axios@>=1.0.0 <1.8.2": ">=1.13.2",
"@babel/helpers@<7.26.10": ">=7.28.6",
"@babel/runtime@<7.26.10": ">=7.28.6",
"axios@>=1.0.0 <1.8.2": ">=1.13.5",
"brace-expansion@>=2.0.0 <=2.0.1": ">=4.0.1",
"brace-expansion@>=1.0.0 <=1.1.11": ">=4.0.1",
"esbuild@<=0.24.2": ">=0.27.2",
"esbuild@<=0.24.2": ">=0.27.3",
"form-data@>=4.0.0 <4.0.4": ">=4.0.5",
"hono@<4.6.5": ">=4.11.3",
"hono@<4.6.5": ">=4.11.9",
"linkifyjs@<4.3.2": ">=4.3.2",
"nanoid@>=4.0.0 <5.0.9": ">=5.1.6",
"prismjs@<1.30.0": ">=1.30.0",
"proxmox-api>undici": "7.16.0",
"react-is": "^19.2.3",
"rollup@>=4.0.0 <4.22.4": ">=4.54.0",
"proxmox-api>undici": "7.19.2",
"react-is": "^19.2.4",
"rollup@>=4.0.0 <4.22.4": ">=4.57.1",
"sha.js@<=2.4.11": ">=2.4.12",
"tar-fs@>=3.0.0 <3.0.9": ">=3.1.1",
"tar-fs@>=2.0.0 <2.1.3": ">=3.1.1",
"tmp@<=0.2.3": ">=0.2.5",
"vite@>=5.0.0 <=5.4.18": ">=7.3.0"
"vite@>=5.0.0 <=5.4.18": ">=7.3.1"
},
"patchedDependencies": {
"@types/node-unifi": "patches/@types__node-unifi.patch",
+3
View File
@@ -22,8 +22,11 @@
},
"prettier": "@homarr/prettier-config",
"dependencies": {
"@homarr/auth": "workspace:^0.1.0",
"@homarr/common": "workspace:^0.1.0",
"@homarr/core": "workspace:^0.1.0",
"@homarr/db": "workspace:^0.1.0",
"@homarr/docker": "workspace:^0.1.0",
"@homarr/server-settings": "workspace:^0.1.0",
"@umami/node": "^0.4.0",
"superjson": "2.2.6"
+70 -54
View File
@@ -1,17 +1,52 @@
import type { UmamiEventData } from "@umami/node";
import { Umami } from "@umami/node";
import { isProviderEnabled } from "@homarr/auth/server";
import { Stopwatch } from "@homarr/common";
import { createLogger } from "@homarr/core/infrastructure/logs";
import { count, db } from "@homarr/db";
import { isMysql, isPostgresql } from "@homarr/db/collection";
import { getServerSettingByKeyAsync } from "@homarr/db/queries";
import { integrations, items, users } from "@homarr/db/schema";
import type { defaultServerSettings } from "@homarr/server-settings";
import {
apiKeys,
apps,
boards,
cronJobConfigurations,
groups,
iconRepositories,
icons,
integrations,
invites,
itemLayouts,
items,
layouts,
medias,
searchEngines,
sectionLayouts,
sections,
users,
} from "@homarr/db/schema";
import { env as dockerEnv } from "@homarr/docker/env";
import { Stopwatch } from "../../common/src";
import packageJson from "../../../package.json";
import { UMAMI_HOST_URL, UMAMI_WEBSITE_ID } from "./constants";
const logger = createLogger({ module: "analytics" });
const getDatabaseType = (): "mysql" | "postgresql" | "sqlite" => {
if (isMysql()) return "mysql";
if (isPostgresql()) return "postgresql";
return "sqlite";
};
const getEnabledAuthProviders = (): string[] => {
const providers: string[] = [];
if (isProviderEnabled("credentials")) providers.push("credentials");
if (isProviderEnabled("oidc")) providers.push("oidc");
if (isProviderEnabled("ldap")) providers.push("ldap");
return providers;
};
export const sendServerAnalyticsAsync = async () => {
const stopWatch = new Stopwatch();
const analyticsSettings = await getServerSettingByKeyAsync(db, "analytics");
@@ -27,67 +62,48 @@ export const sendServerAnalyticsAsync = async () => {
websiteId: UMAMI_WEBSITE_ID,
});
await sendIntegrationDataAsync(umamiInstance, analyticsSettings);
await sendWidgetDataAsync(umamiInstance, analyticsSettings);
await sendUserDataAsync(umamiInstance, analyticsSettings);
const enabledAuthProviders = getEnabledAuthProviders();
logger.info(`Sent all analytics in ${stopWatch.getElapsedInHumanWords()}`);
};
const analyticsData: UmamiEventData = {
homarrVersion: packageJson.version,
databaseType: getDatabaseType(),
dockerEnabled: dockerEnv.ENABLE_DOCKER ? 1 : 0,
kubernetesEnabled: dockerEnv.ENABLE_KUBERNETES ? 1 : 0,
authCredentials: enabledAuthProviders.includes("credentials") ? 1 : 0,
authOidc: enabledAuthProviders.includes("oidc") ? 1 : 0,
authLdap: enabledAuthProviders.includes("ldap") ? 1 : 0,
countUsers: await db.$count(users),
countBoards: await db.$count(boards),
countGroups: await db.$count(groups),
countApps: await db.$count(apps),
countWidgets: await db.$count(items),
countSections: await db.$count(sections),
countIntegrations: await db.$count(integrations),
countSearchEngines: await db.$count(searchEngines),
countIconRepositories: await db.$count(iconRepositories),
countIcons: await db.$count(icons),
countApiKeys: await db.$count(apiKeys),
countInvites: await db.$count(invites),
countMedias: await db.$count(medias),
countLayouts: await db.$count(layouts),
countItemLayouts: await db.$count(itemLayouts),
countSectionLayouts: await db.$count(sectionLayouts),
countCronJobConfigs: await db.$count(cronJobConfigurations),
};
const sendWidgetDataAsync = async (umamiInstance: Umami, analyticsSettings: typeof defaultServerSettings.analytics) => {
if (!analyticsSettings.enableWidgetData) {
return;
}
const widgetCount = await db.$count(items);
const response = await umamiInstance.track("server-widget-data", {
countWidgets: widgetCount,
});
if (response.ok) {
return;
}
logger.warn("Unable to send track event data to Umami instance");
};
const sendUserDataAsync = async (umamiInstance: Umami, analyticsSettings: typeof defaultServerSettings.analytics) => {
if (!analyticsSettings.enableUserData) {
return;
}
const userCount = await db.$count(users);
const response = await umamiInstance.track("server-user-data", {
countUsers: userCount,
});
if (response.ok) {
return;
}
logger.warn("Unable to send track event data to Umami instance");
};
const sendIntegrationDataAsync = async (
umamiInstance: Umami,
analyticsSettings: typeof defaultServerSettings.analytics,
) => {
if (!analyticsSettings.enableIntegrationData) {
return;
}
const integrationKinds = await db
.select({ kind: integrations.kind, count: count(integrations.id) })
.from(integrations)
.groupBy(integrations.kind);
const map: UmamiEventData = {};
integrationKinds.forEach((integrationKind) => {
map[integrationKind.kind] = integrationKind.count;
analyticsData[`integration_${integrationKind.kind}`] = integrationKind.count;
});
const response = await umamiInstance.track("server-integration-data-kind", map);
if (response.ok) {
return;
const response = await umamiInstance.track("server-analytics-v2", analyticsData);
if (!response.ok) {
logger.warn("Unable to send analytics to Umami instance");
}
logger.warn("Unable to send track event data to Umami instance");
logger.info(`Sent analytics in ${stopWatch.getElapsedInHumanWords()}`);
};
+9 -9
View File
@@ -41,15 +41,15 @@
"@homarr/translation": "workspace:^0.1.0",
"@homarr/validation": "workspace:^0.1.0",
"@kubernetes/client-node": "^1.4.0",
"@tanstack/react-query": "^5.90.16",
"@trpc/client": "^11.8.1",
"@trpc/react-query": "^11.8.1",
"@trpc/server": "^11.8.1",
"@trpc/tanstack-react-query": "^11.8.1",
"@tanstack/react-query": "^5.90.20",
"@trpc/client": "^11.9.0",
"@trpc/react-query": "^11.9.0",
"@trpc/server": "^11.9.0",
"@trpc/tanstack-react-query": "^11.9.0",
"lodash.clonedeep": "^4.5.0",
"next": "16.1.1",
"react": "19.2.3",
"react-dom": "19.2.3",
"next": "16.1.6",
"react": "19.2.4",
"react-dom": "19.2.4",
"superjson": "2.2.6",
"trpc-to-openapi": "^3.1.0",
"zod": "^4.2.1"
@@ -59,7 +59,7 @@
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
"eslint": "^9.39.2",
"prettier": "^3.7.4",
"prettier": "^3.8.1",
"typescript": "^5.9.3"
}
}
+26 -48
View File
@@ -1,54 +1,32 @@
import { apiKeysRouter } from "./router/apiKeys";
import { appRouter as innerAppRouter } from "./router/app";
import { boardRouter } from "./router/board";
import { certificateRouter } from "./router/certificates/certificate-router";
import { cronJobsRouter } from "./router/cron-jobs";
import { dockerRouter } from "./router/docker/docker-router";
import { groupRouter } from "./router/group";
import { homeRouter } from "./router/home";
import { iconsRouter } from "./router/icons";
import { importRouter } from "./router/import/import-router";
import { infoRouter } from "./router/info";
import { integrationRouter } from "./router/integration/integration-router";
import { inviteRouter } from "./router/invite";
import { kubernetesRouter } from "./router/kubernetes/router/kubernetes-router";
import { locationRouter } from "./router/location";
import { logRouter } from "./router/log";
import { mediaRouter } from "./router/medias/media-router";
import { onboardRouter } from "./router/onboard/onboard-router";
import { searchEngineRouter } from "./router/search-engine/search-engine-router";
import { sectionRouter } from "./router/section/section-router";
import { serverSettingsRouter } from "./router/serverSettings";
import { updateCheckerRouter } from "./router/update-checker";
import { userRouter } from "./router/user";
import { widgetRouter } from "./router/widgets";
import { lazy } from "@trpc/server";
import { createTRPCRouter } from "./trpc";
export const appRouter = createTRPCRouter({
user: userRouter,
group: groupRouter,
invite: inviteRouter,
integration: integrationRouter,
board: boardRouter,
section: sectionRouter,
app: innerAppRouter,
searchEngine: searchEngineRouter,
widget: widgetRouter,
location: locationRouter,
log: logRouter,
icon: iconsRouter,
import: importRouter,
onboard: onboardRouter,
home: homeRouter,
docker: dockerRouter,
kubernetes: kubernetesRouter,
serverSettings: serverSettingsRouter,
cronJobs: cronJobsRouter,
apiKeys: apiKeysRouter,
media: mediaRouter,
updateChecker: updateCheckerRouter,
certificates: certificateRouter,
info: infoRouter,
user: lazy(() => import("./router/user").then((mod) => mod.userRouter)),
group: lazy(() => import("./router/group").then((mod) => mod.groupRouter)),
invite: lazy(() => import("./router/invite").then((mod) => mod.inviteRouter)),
integration: lazy(() => import("./router/integration/integration-router").then((mod) => mod.integrationRouter)),
board: lazy(() => import("./router/board").then((mod) => mod.boardRouter)),
section: lazy(() => import("./router/section/section-router").then((mod) => mod.sectionRouter)),
app: lazy(() => import("./router/app").then((mod) => mod.appRouter)),
searchEngine: lazy(() => import("./router/search-engine/search-engine-router").then((mod) => mod.searchEngineRouter)),
widget: lazy(() => import("./router/widgets").then((mod) => mod.widgetRouter)),
location: lazy(() => import("./router/location").then((mod) => mod.locationRouter)),
log: lazy(() => import("./router/log").then((mod) => mod.logRouter)),
icon: lazy(() => import("./router/icons").then((mod) => mod.iconsRouter)),
import: lazy(() => import("./router/import/import-router").then((mod) => mod.importRouter)),
onboard: lazy(() => import("./router/onboard/onboard-router").then((mod) => mod.onboardRouter)),
home: lazy(() => import("./router/home").then((mod) => mod.homeRouter)),
docker: lazy(() => import("./router/docker/docker-router").then((mod) => mod.dockerRouter)),
kubernetes: lazy(() => import("./router/kubernetes/router/kubernetes-router").then((mod) => mod.kubernetesRouter)),
serverSettings: lazy(() => import("./router/serverSettings").then((mod) => mod.serverSettingsRouter)),
cronJobs: lazy(() => import("./router/cron-jobs").then((mod) => mod.cronJobsRouter)),
apiKeys: lazy(() => import("./router/apiKeys").then((mod) => mod.apiKeysRouter)),
media: lazy(() => import("./router/medias/media-router").then((mod) => mod.mediaRouter)),
updateChecker: lazy(() => import("./router/update-checker").then((mod) => mod.updateCheckerRouter)),
certificates: lazy(() => import("./router/certificates/certificate-router").then((mod) => mod.certificateRouter)),
info: lazy(() => import("./router/info").then((mod) => mod.infoRouter)),
});
// export type definition of API
+34 -15
View File
@@ -1,7 +1,9 @@
import { TRPCError } from "@trpc/server";
import { z } from "zod/v4";
import type { Session } from "@homarr/auth";
import { createId } from "@homarr/common";
import type { Database, InferSelectModel } from "@homarr/db";
import { asc, eq, inArray, like } from "@homarr/db";
import { apps } from "@homarr/db/schema";
import { selectAppSchema } from "@homarr/db/validationSchemas";
@@ -11,7 +13,7 @@ import { byIdSchema, paginatedSchema } from "@homarr/validation/common";
import { convertIntersectionToZodObject } from "../schema-merger";
import { createTRPCRouter, permissionRequiredProcedure, protectedProcedure, publicProcedure } from "../trpc";
import { canUserSeeAppAsync } from "./app/app-access-control";
import { AppAccessControl } from "./app/app-access-control";
const defaultIcon = "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons@master/svg/homarr.svg";
@@ -89,9 +91,8 @@ export const appRouter = createTRPCRouter({
.output(selectAppSchema)
.meta({ openapi: { method: "GET", path: "/api/apps/{id}", tags: ["apps"], protect: true } })
.query(async ({ ctx, input }) => {
const app = await ctx.db.query.apps.findFirst({
where: eq(apps.id, input.id),
});
const repository = new AppRepository(ctx.db, ctx.session?.user ?? null);
const app = await repository.getByIdAsync(input.id);
if (!app) {
throw new TRPCError({
@@ -100,20 +101,11 @@ export const appRouter = createTRPCRouter({
});
}
const canUserSeeApp = await canUserSeeAppAsync(ctx.session?.user ?? null, app.id);
if (!canUserSeeApp) {
throw new TRPCError({
code: "NOT_FOUND",
message: "App not found",
});
}
return app;
}),
byIds: publicProcedure.input(z.array(z.string())).query(async ({ ctx, input }) => {
return await ctx.db.query.apps.findMany({
where: inArray(apps.id, input),
});
const repository = new AppRepository(ctx.db, ctx.session?.user ?? null);
return await repository.getByIdsAsync(input);
}),
create: permissionRequiredProcedure
.requiresPermission("app-create")
@@ -187,3 +179,30 @@ export const appRouter = createTRPCRouter({
await ctx.db.delete(apps).where(eq(apps.id, input.id));
}),
});
type App = InferSelectModel<typeof apps>;
export class AppRepository {
private readonly accessControl: AppAccessControl;
constructor(
private db: Database,
user: Session["user"] | null,
) {
this.accessControl = new AppAccessControl(db, user);
}
public async getByIdAsync(id: string): Promise<App | null> {
const apps = await this.getByIdsAsync([id]);
return apps[0] ?? null;
}
public async getByIdsAsync(ids: string[]): Promise<App[]> {
const canUserSeeApps = await this.accessControl.canUserSeeAppsAsync(ids);
const dbApps = await this.db.query.apps.findMany({
where: inArray(apps.id, ids),
});
return canUserSeeApps ? dbApps : [];
}
}
@@ -1,45 +1,52 @@
import SuperJSON from "superjson";
import type { Session } from "@homarr/auth";
import { db, eq, or } from "@homarr/db";
import type { Database } from "@homarr/db";
import { eq, or } from "@homarr/db";
import { items } from "@homarr/db/schema";
import type { WidgetComponentProps } from "../../../../widgets/src";
export const canUserSeeAppAsync = async (user: Session["user"] | null, appId: string) => {
return await canUserSeeAppsAsync(user, [appId]);
};
export class AppAccessControl {
constructor(
private db: Database,
private user: Session["user"] | null,
) {}
export const canUserSeeAppsAsync = async (user: Session["user"] | null, appIds: string[]) => {
if (user) return true;
async canUserSeeAppAsync(appId: string) {
return await this.canUserSeeAppsAsync([appId]);
}
const appIdsOnPublicBoards = await getAllAppIdsOnPublicBoardsAsync();
return appIds.every((appId) => appIdsOnPublicBoards.includes(appId));
};
async canUserSeeAppsAsync(appIds: string[]) {
// Currently any user can see all apps if they are logged in
if (this.user) return true;
const getAllAppIdsOnPublicBoardsAsync = async () => {
const itemsWithApps = await db.query.items.findMany({
where: or(eq(items.kind, "app"), eq(items.kind, "bookmarks")),
with: {
board: {
columns: {
isPublic: true,
const appIdsOnPublicBoards = await this.getAllAppIdsOnPublicBoardsAsync();
return appIds.every((appId) => appIdsOnPublicBoards.includes(appId));
}
private async getAllAppIdsOnPublicBoardsAsync() {
const itemsWithApps = await this.db.query.items.findMany({
where: or(eq(items.kind, "app"), eq(items.kind, "bookmarks")),
with: {
board: {
columns: {
isPublic: true,
},
},
},
},
});
});
return itemsWithApps
.filter((item) => item.board.isPublic)
.flatMap((item) => {
if (item.kind === "app") {
const parsedOptions = SuperJSON.parse<WidgetComponentProps<"app">["options"]>(item.options);
return [parsedOptions.appId];
}
return itemsWithApps
.filter((item) => item.board.isPublic)
.flatMap((item) => {
if (item.kind === "app") {
const parsedOptions = SuperJSON.parse<WidgetComponentProps<"app">["options"]>(item.options);
return [parsedOptions.appId];
} else if (item.kind === "bookmarks") {
const parsedOptions = SuperJSON.parse<WidgetComponentProps<"bookmarks">["options"]>(item.options);
return parsedOptions.items;
}
throw new Error("Failed to get app ids from board. Invalid item kind: 'test'");
});
};
});
}
}
@@ -1,22 +1,15 @@
import { lazy } from "@trpc/server";
import { createTRPCRouter } from "../../../trpc";
import { clusterRouter } from "./cluster";
import { configMapsRouter } from "./configMaps";
import { ingressesRouter } from "./ingresses";
import { namespacesRouter } from "./namespaces";
import { nodesRouter } from "./nodes";
import { podsRouter } from "./pods";
import { secretsRouter } from "./secrets";
import { servicesRouter } from "./services";
import { volumesRouter } from "./volumes";
export const kubernetesRouter = createTRPCRouter({
nodes: nodesRouter,
cluster: clusterRouter,
namespaces: namespacesRouter,
ingresses: ingressesRouter,
services: servicesRouter,
pods: podsRouter,
secrets: secretsRouter,
configMaps: configMapsRouter,
volumes: volumesRouter,
nodes: lazy(() => import("./nodes").then((mod) => mod.nodesRouter)),
cluster: lazy(() => import("./cluster").then((mod) => mod.clusterRouter)),
namespaces: lazy(() => import("./namespaces").then((mod) => mod.namespacesRouter)),
ingresses: lazy(() => import("./ingresses").then((mod) => mod.ingressesRouter)),
services: lazy(() => import("./services").then((mod) => mod.servicesRouter)),
pods: lazy(() => import("./pods").then((mod) => mod.podsRouter)),
secrets: lazy(() => import("./secrets").then((mod) => mod.secretsRouter)),
configMaps: lazy(() => import("./configMaps").then((mod) => mod.configMapsRouter)),
volumes: lazy(() => import("./volumes").then((mod) => mod.volumesRouter)),
});
+10 -2
View File
@@ -13,6 +13,14 @@ import * as appAccessControl from "../app/app-access-control";
// Mock the auth module to return an empty session
vi.mock("@homarr/auth", () => ({ auth: () => ({}) as Session }));
const createFakeAccessControl = (canAccess: boolean) =>
vi.fn(
class {
canUserSeeAppAsync = async (_: string) => await Promise.resolve(canAccess);
canUserSeeAppsAsync = async (_: string[]) => await Promise.resolve(canAccess);
} as unknown as typeof appAccessControl.AppAccessControl,
);
const createDefaultSession = (permissions: GroupPermissionKey[] = []): Session => ({
user: { id: createId(), permissions, colorScheme: "light" },
expires: new Date().toISOString(),
@@ -77,7 +85,7 @@ describe("byId should return an app by id", () => {
deviceType: undefined,
session: null,
});
vi.spyOn(appAccessControl, "canUserSeeAppAsync").mockReturnValue(Promise.resolve(true));
vi.spyOn(appAccessControl, "AppAccessControl").mockImplementation(createFakeAccessControl(true));
await db.insert(apps).values([
{
@@ -118,7 +126,7 @@ describe("byId should return an app by id", () => {
href: "https://mantine.dev",
},
]);
vi.spyOn(appAccessControl, "canUserSeeAppAsync").mockReturnValue(Promise.resolve(false));
vi.spyOn(appAccessControl, "AppAccessControl").mockImplementation(createFakeAccessControl(false));
// Act
const actAsync = async () => await caller.byId({ id: "2" });
@@ -1,6 +1,9 @@
import { describe, expect, test, vi } from "vitest";
import type { Session } from "@homarr/auth";
import { createId } from "@homarr/common";
import type { InferInsertModel } from "@homarr/db";
import { apps } from "@homarr/db/schema";
import { createDb } from "@homarr/db/test";
import * as ping from "@homarr/ping";
@@ -9,22 +12,31 @@ import { appRouter } from "../../widgets/app";
// Mock the auth module to return an empty session
vi.mock("@homarr/auth", () => ({ auth: () => ({}) as Session }));
vi.mock("@homarr/ping", () => ({ sendPingRequestAsync: async () => await Promise.resolve(null) }));
vi.mock("../../app/app-access-control", () => ({
AppAccessControl: vi.fn(
class {
canUserSeeAppAsync = async (_: string) => await Promise.resolve(true);
canUserSeeAppsAsync = async (_: string[]) => await Promise.resolve(true);
},
),
}));
describe("ping should call sendPingRequestAsync with url and return result", () => {
test("ping with error response should return error and url", async () => {
// Arrange
const spy = vi.spyOn(ping, "sendPingRequestAsync");
vi.spyOn(ping, "sendPingRequestAsync").mockImplementation(() => Promise.resolve({ error: "error" }));
const url = "http://localhost";
const db = createDb();
const app = createApp({ url });
await db.insert(apps).values(app);
const caller = appRouter.createCaller({
db,
deviceType: undefined,
session: null,
});
spy.mockImplementation(() => Promise.resolve({ error: "error" }));
// Act
const result = await caller.ping({ url });
const result = await caller.ping({ id: app.id });
// Assert
expect(result.url).toBe(url);
@@ -33,21 +45,32 @@ describe("ping should call sendPingRequestAsync with url and return result", ()
test("ping with success response should return statusCode and url", async () => {
// Arrange
const spy = vi.spyOn(ping, "sendPingRequestAsync");
vi.spyOn(ping, "sendPingRequestAsync").mockImplementation(() =>
Promise.resolve({ statusCode: 200, durationMs: 123 }),
);
const url = "http://localhost";
const db = createDb();
const app = createApp({ url });
await db.insert(apps).values(app);
const caller = appRouter.createCaller({
db,
deviceType: undefined,
session: null,
});
spy.mockImplementation(() => Promise.resolve({ statusCode: 200, durationMs: 123 }));
// Act
const result = await caller.ping({ url });
const result = await caller.ping({ id: app.id });
// Assert
expect(result.url).toBe(url);
expect("statusCode" in result).toBe(true);
});
});
const createApp = ({ url }: { url: string }) =>
({
id: createId(),
iconUrl: "",
name: "Test App",
href: url,
}) satisfies InferInsertModel<typeof apps>;
+64 -10
View File
@@ -1,43 +1,97 @@
import { TRPCError } from "@trpc/server";
import { observable } from "@trpc/server/observable";
import { z } from "zod/v4";
import { getServerSettingByKeyAsync } from "@homarr/db/queries";
import { sendPingRequestAsync } from "@homarr/ping";
import { pingChannel, pingUrlChannel } from "@homarr/redis";
import { createTRPCRouter, publicProcedure } from "../../trpc";
import { AppRepository } from "../app";
export const appRouter = createTRPCRouter({
ping: publicProcedure.input(z.object({ url: z.string() })).query(async ({ input }) => {
const pingResult = await sendPingRequestAsync(input.url);
ping: publicProcedure.input(z.object({ id: z.string() })).query(async ({ ctx, input }) => {
const boardSettings = await getServerSettingByKeyAsync(ctx.db, "board");
if (boardSettings.forceDisableStatus) {
throw new TRPCError({
code: "FORBIDDEN",
message: "Ping functionality is disabled by server settings",
});
}
const repository = new AppRepository(ctx.db, ctx.session?.user ?? null);
const app = await repository.getByIdAsync(input.id);
if (!app) {
throw new TRPCError({
code: "NOT_FOUND",
message: "App not found",
});
}
const pingUrl = app.pingUrl ?? app.href;
if (!pingUrl) {
throw new TRPCError({
code: "CONFLICT",
message: "No URL to ping configured for this app",
});
}
const pingResult = await sendPingRequestAsync(pingUrl);
return {
url: input.url,
url: pingUrl,
...pingResult,
};
}),
updatedPing: publicProcedure
.input(
z.object({
url: z.string(),
id: z.string(),
}),
)
.subscription(async ({ input }) => {
await pingUrlChannel.addAsync(input.url);
.subscription(async ({ ctx, input }) => {
const boardSettings = await getServerSettingByKeyAsync(ctx.db, "board");
if (boardSettings.forceDisableStatus) {
throw new TRPCError({
code: "FORBIDDEN",
message: "Ping functionality is disabled by server settings",
});
}
const pingResult = await sendPingRequestAsync(input.url);
const repository = new AppRepository(ctx.db, ctx.session?.user ?? null);
const app = await repository.getByIdAsync(input.id);
if (!app) {
throw new TRPCError({
code: "NOT_FOUND",
message: "App not found",
});
}
const pingUrl = app.pingUrl ?? app.href;
if (!pingUrl) {
throw new TRPCError({
code: "CONFLICT",
message: "No URL to ping configured for this app",
});
}
await pingUrlChannel.addAsync(pingUrl);
return observable<{ url: string; statusCode: number; durationMs: number } | { url: string; error: string }>(
(emit) => {
emit.next({ url: input.url, ...pingResult });
const unsubscribe = pingChannel.subscribe((message) => {
// Only emit if same url
if (message.url !== input.url) return;
if (message.url !== pingUrl) return;
emit.next(message);
});
return () => {
unsubscribe();
void pingUrlChannel.removeAsync(input.url);
void pingUrlChannel.removeAsync(pingUrl);
};
},
);
@@ -0,0 +1,50 @@
import { observable } from "@trpc/server/observable";
import type { CoolifyInstanceInfo } from "@homarr/integrations/types";
import { coolifyRequestHandler } from "@homarr/request-handler/coolify";
import { createManyIntegrationMiddleware } from "../../middlewares/integration";
import { createTRPCRouter, publicProcedure } from "../../trpc";
export const coolifyRouter = createTRPCRouter({
getInstancesInfo: publicProcedure
.concat(createManyIntegrationMiddleware("query", "coolify"))
.query(async ({ ctx }) => {
const results = await Promise.all(
ctx.integrations.map(async (integration) => {
const innerHandler = coolifyRequestHandler.handler(integration, {});
const { data, timestamp } = await innerHandler.getCachedOrUpdatedDataAsync({ forceUpdate: false });
return {
integrationId: integration.id,
integrationName: integration.name,
integrationUrl: integration.url,
instanceInfo: data,
updatedAt: timestamp,
};
}),
);
return results;
}),
subscribeInstancesInfo: publicProcedure
.concat(createManyIntegrationMiddleware("query", "coolify"))
.subscription(({ ctx }) => {
return observable<{ integrationId: string; instanceInfo: CoolifyInstanceInfo; timestamp: Date }>((emit) => {
const unsubscribes = ctx.integrations.map((integration) => {
const innerHandler = coolifyRequestHandler.handler(integration, {});
return innerHandler.subscribe((instanceInfo) => {
emit.next({
integrationId: integration.id,
instanceInfo,
timestamp: new Date(),
});
});
});
return () => {
unsubscribes.forEach((unsubscribe) => unsubscribe());
};
});
}),
});
+24 -42
View File
@@ -1,46 +1,28 @@
import { lazy } from "@trpc/server";
import { createTRPCRouter } from "../../trpc";
import { appRouter } from "./app";
import { calendarRouter } from "./calendar";
import { dnsHoleRouter } from "./dns-hole";
import { downloadsRouter } from "./downloads";
import { firewallRouter } from "./firewall";
import { healthMonitoringRouter } from "./health-monitoring";
import { indexerManagerRouter } from "./indexer-manager";
import { mediaReleaseRouter } from "./media-release";
import { mediaRequestsRouter } from "./media-requests";
import { mediaServerRouter } from "./media-server";
import { mediaTranscodingRouter } from "./media-transcoding";
import { minecraftRouter } from "./minecraft";
import { networkControllerRouter } from "./network-controller";
import { notebookRouter } from "./notebook";
import { notificationsRouter } from "./notifications";
import { optionsRouter } from "./options";
import { releasesRouter } from "./releases";
import { rssFeedRouter } from "./rssFeed";
import { smartHomeRouter } from "./smart-home";
import { stockPriceRouter } from "./stocks";
import { weatherRouter } from "./weather";
export const widgetRouter = createTRPCRouter({
notebook: notebookRouter,
weather: weatherRouter,
app: appRouter,
dnsHole: dnsHoleRouter,
smartHome: smartHomeRouter,
stockPrice: stockPriceRouter,
mediaServer: mediaServerRouter,
mediaRelease: mediaReleaseRouter,
calendar: calendarRouter,
downloads: downloadsRouter,
mediaRequests: mediaRequestsRouter,
rssFeed: rssFeedRouter,
indexerManager: indexerManagerRouter,
healthMonitoring: healthMonitoringRouter,
mediaTranscoding: mediaTranscodingRouter,
minecraft: minecraftRouter,
options: optionsRouter,
releases: releasesRouter,
networkController: networkControllerRouter,
firewall: firewallRouter,
notifications: notificationsRouter,
coolify: lazy(() => import("./coolify").then((mod) => mod.coolifyRouter)),
notebook: lazy(() => import("./notebook").then((mod) => mod.notebookRouter)),
weather: lazy(() => import("./weather").then((mod) => mod.weatherRouter)),
app: lazy(() => import("./app").then((mod) => mod.appRouter)),
dnsHole: lazy(() => import("./dns-hole").then((mod) => mod.dnsHoleRouter)),
smartHome: lazy(() => import("./smart-home").then((mod) => mod.smartHomeRouter)),
stockPrice: lazy(() => import("./stocks").then((mod) => mod.stockPriceRouter)),
mediaServer: lazy(() => import("./media-server").then((mod) => mod.mediaServerRouter)),
mediaRelease: lazy(() => import("./media-release").then((mod) => mod.mediaReleaseRouter)),
calendar: lazy(() => import("./calendar").then((mod) => mod.calendarRouter)),
downloads: lazy(() => import("./downloads").then((mod) => mod.downloadsRouter)),
mediaRequests: lazy(() => import("./media-requests").then((mod) => mod.mediaRequestsRouter)),
rssFeed: lazy(() => import("./rssFeed").then((mod) => mod.rssFeedRouter)),
indexerManager: lazy(() => import("./indexer-manager").then((mod) => mod.indexerManagerRouter)),
healthMonitoring: lazy(() => import("./health-monitoring").then((mod) => mod.healthMonitoringRouter)),
mediaTranscoding: lazy(() => import("./media-transcoding").then((mod) => mod.mediaTranscodingRouter)),
minecraft: lazy(() => import("./minecraft").then((mod) => mod.minecraftRouter)),
options: lazy(() => import("./options").then((mod) => mod.optionsRouter)),
releases: lazy(() => import("./releases").then((mod) => mod.releasesRouter)),
networkController: lazy(() => import("./network-controller").then((mod) => mod.networkControllerRouter)),
firewall: lazy(() => import("./firewall").then((mod) => mod.firewallRouter)),
notifications: lazy(() => import("./notifications").then((mod) => mod.notificationsRouter)),
});
+5 -5
View File
@@ -33,11 +33,11 @@
"@homarr/validation": "workspace:^0.1.0",
"bcrypt": "^6.0.0",
"cookies": "^0.9.1",
"ldapts": "8.1.2",
"next": "16.1.1",
"ldapts": "8.1.6",
"next": "16.1.6",
"next-auth": "5.0.0-beta.30",
"react": "19.2.3",
"react-dom": "19.2.3",
"react": "19.2.4",
"react-dom": "19.2.4",
"zod": "^4.2.1"
},
"devDependencies": {
@@ -47,7 +47,7 @@
"@types/bcrypt": "6.0.0",
"@types/cookies": "0.9.2",
"eslint": "^9.39.2",
"prettier": "^3.7.4",
"prettier": "^3.8.1",
"typescript": "^5.9.3"
}
}
+2 -2
View File
@@ -25,8 +25,8 @@
"prettier": "@homarr/prettier-config",
"dependencies": {
"@homarr/api": "workspace:^0.1.0",
"react": "19.2.3",
"react-dom": "19.2.3"
"react": "19.2.4",
"react-dom": "19.2.4"
},
"devDependencies": {
"@homarr/eslint-config": "workspace:^0.2.0",
+2 -2
View File
@@ -28,13 +28,13 @@
"@homarr/common": "workspace:^0.1.0",
"@homarr/db": "workspace:^0.1.0",
"@homarr/validation": "workspace:^0.1.0",
"dotenv": "^17.2.3"
"dotenv": "^17.2.4"
},
"devDependencies": {
"@homarr/eslint-config": "workspace:^0.2.0",
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
"esbuild": "^0.27.2",
"esbuild": "^0.27.3",
"eslint": "^9.39.2",
"typescript": "^5.9.3"
}
+6 -5
View File
@@ -27,13 +27,14 @@
"prettier": "@homarr/prettier-config",
"dependencies": {
"@homarr/core": "workspace:^0.1.0",
"@paralleldrive/cuid2": "^3.1.0",
"@paralleldrive/cuid2": "^3.3.0",
"cookie": "1.1.1",
"dayjs": "^1.11.19",
"next": "16.1.1",
"next": "16.1.6",
"octokit": "^5.0.5",
"react": "19.2.3",
"react-dom": "19.2.3",
"undici": "7.16.0",
"react": "19.2.4",
"react-dom": "19.2.4",
"undici": "7.18.2",
"zod": "^4.2.1",
"zod-validation-error": "^5.0.0"
},
+3 -3
View File
@@ -1,10 +1,10 @@
import type { SerializeOptions } from "cookie";
import { parse, serialize } from "cookie";
import { parseCookie, stringifySetCookie } from "cookie";
export function parseCookies(cookieString: string) {
return parse(cookieString);
return parseCookie(cookieString);
}
export function setClientCookie(name: string, value: string, options: SerializeOptions = {}) {
document.cookie = serialize(name, value, options);
document.cookie = stringifySetCookie(name, value, options);
}
+4 -4
View File
@@ -38,12 +38,12 @@
"prettier": "@homarr/prettier-config",
"dependencies": {
"@t3-oss/env-nextjs": "^0.13.10",
"better-sqlite3": "^12.5.0",
"better-sqlite3": "^12.6.2",
"dns-caching": "^0.2.9",
"drizzle-orm": "^0.45.1",
"ioredis": "5.8.2",
"mysql2": "3.16.0",
"pg": "^8.16.3",
"ioredis": "5.9.2",
"mysql2": "3.16.3",
"pg": "^8.18.0",
"superjson": "2.2.6",
"winston": "3.19.0",
"zod": "^4.2.1"
+6 -6
View File
@@ -28,12 +28,12 @@
"@homarr/common": "workspace:^0.1.0",
"@homarr/core": "workspace:^0.1.0",
"@homarr/cron-jobs": "workspace:^0.1.0",
"@tanstack/react-query": "^5.90.16",
"@trpc/client": "^11.8.1",
"@trpc/server": "^11.8.1",
"@trpc/tanstack-react-query": "^11.8.1",
"@tanstack/react-query": "^5.90.20",
"@trpc/client": "^11.9.0",
"@trpc/server": "^11.9.0",
"@trpc/tanstack-react-query": "^11.9.0",
"node-cron": "^4.2.1",
"react": "19.2.3",
"react": "19.2.4",
"zod": "^4.2.1"
},
"devDependencies": {
@@ -41,7 +41,7 @@
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
"@types/node-cron": "^3.0.11",
"@types/react": "19.2.7",
"@types/react": "19.2.13",
"eslint": "^9.39.2",
"typescript": "^5.9.3"
}
@@ -1,4 +1,5 @@
import { EVERY_5_SECONDS } from "@homarr/cron-jobs-core/expressions";
import { coolifyRequestHandler } from "@homarr/request-handler/coolify";
import { clusterInfoRequestHandler, systemInfoRequestHandler } from "@homarr/request-handler/health-monitoring";
import { createRequestIntegrationJobHandler } from "@homarr/request-handler/lib/cached-request-integration-job-handler";
@@ -9,16 +10,20 @@ export const healthMonitoringJob = createCronJob("healthMonitoring", EVERY_5_SEC
(integration, itemOptions: Record<string, never>) => {
const { kind } = integration;
if (kind !== "proxmox" && kind !== "mock") {
if (kind !== "proxmox" && kind !== "mock" && kind !== "coolify") {
return systemInfoRequestHandler.handler({ ...integration, kind }, itemOptions);
}
if (kind === "coolify") {
return coolifyRequestHandler.handler({ ...integration, kind }, itemOptions);
}
return clusterInfoRequestHandler.handler({ ...integration, kind }, itemOptions);
},
{
widgetKinds: ["healthMonitoring", "systemResources"],
widgetKinds: ["healthMonitoring", "systemResources", "coolify"],
getInput: {
healthMonitoring: () => ({}),
systemResources: () => ({}),
coolify: () => ({}),
},
},
),
+8 -8
View File
@@ -47,17 +47,17 @@
"@homarr/core": "workspace:^0.1.0",
"@homarr/definitions": "workspace:^0.1.0",
"@homarr/server-settings": "workspace:^0.1.0",
"@mantine/core": "^8.3.10",
"@paralleldrive/cuid2": "^3.1.0",
"@mantine/core": "^8.3.14",
"@paralleldrive/cuid2": "^3.3.0",
"@testcontainers/mysql": "^11.11.0",
"@testcontainers/postgresql": "^11.11.0",
"better-sqlite3": "^12.5.0",
"dotenv": "^17.2.3",
"better-sqlite3": "^12.6.2",
"dotenv": "^17.2.4",
"drizzle-kit": "^0.31.8",
"drizzle-orm": "^0.45.1",
"drizzle-zod": "^0.8.3",
"mysql2": "3.16.0",
"pg": "^8.16.3",
"mysql2": "3.16.3",
"pg": "^8.18.0",
"superjson": "2.2.6"
},
"devDependencies": {
@@ -67,9 +67,9 @@
"@types/better-sqlite3": "7.6.13",
"@types/pg": "^8.16.0",
"dotenv-cli": "^11.0.0",
"esbuild": "^0.27.2",
"esbuild": "^0.27.3",
"eslint": "^9.39.2",
"prettier": "^3.7.4",
"prettier": "^3.8.1",
"tsx": "4.20.4",
"typescript": "^5.9.3"
}
+1 -1
View File
@@ -24,7 +24,7 @@
"prettier": "@homarr/prettier-config",
"dependencies": {
"@homarr/common": "workspace:^0.1.0",
"fast-xml-parser": "^5.3.3",
"fast-xml-parser": "^5.3.5",
"zod": "^4.2.1"
},
"devDependencies": {
+8
View File
@@ -305,6 +305,14 @@ export const integrationDefs = {
category: ["healthMonitoring"],
documentationUrl: createDocumentationLink("/docs/integrations/unraid"),
},
coolify: {
name: "Coolify",
secretKinds: [["apiKey"]],
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons@master/svg/coolify.svg",
category: ["healthMonitoring"],
// @ts-expect-error - docs page will be created when integration is merged
documentationUrl: createDocumentationLink("/docs/integrations/coolify"),
},
// This integration only returns mock data, it is used during development (but can also be used in production by directly going to the create page)
mock: {
name: "Mock",
+2
View File
@@ -29,5 +29,7 @@ export const widgetKinds = [
"firewall",
"notifications",
"systemResources",
"coolify",
"systemDisks",
] as const;
export type WidgetKind = (typeof widgetKinds)[number];
+1 -1
View File
@@ -32,7 +32,7 @@
"@homarr/eslint-config": "workspace:^0.2.0",
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
"@types/dockerode": "^3.3.47",
"@types/dockerode": "^4.0.1",
"eslint": "^9.39.2",
"typescript": "^5.9.3"
}
+1 -1
View File
@@ -26,7 +26,7 @@
"@homarr/common": "workspace:^0.1.0",
"@homarr/translation": "workspace:^0.1.0",
"@homarr/validation": "workspace:^0.1.0",
"@mantine/form": "^8.3.10",
"@mantine/form": "^8.3.14",
"mantine-form-zod-resolver": "^1.3.0",
"zod": "^4.2.1"
},
+2 -2
View File
@@ -30,8 +30,8 @@
"@homarr/translation": "workspace:^0.1.0",
"@homarr/ui": "workspace:^0.1.0",
"@homarr/validation": "workspace:^0.1.0",
"@mantine/core": "^8.3.10",
"react": "19.2.3",
"@mantine/core": "^8.3.14",
"react": "19.2.4",
"zod": "^4.2.1"
},
"devDependencies": {
+3 -3
View File
@@ -39,14 +39,14 @@
"@homarr/translation": "workspace:^0.1.0",
"@homarr/validation": "workspace:^0.1.0",
"@jellyfin/sdk": "^0.13.0",
"@octokit/auth-app": "^8.1.2",
"@octokit/auth-app": "^8.2.0",
"ical.js": "^2.2.1",
"maria2": "^0.4.1",
"node-ical": "^0.22.1",
"octokit": "^5.0.5",
"proxmox-api": "1.1.1",
"tsdav": "^2.1.6",
"undici": "7.16.0",
"tsdav": "^2.1.7",
"undici": "7.18.2",
"xml2js": "^0.6.2",
"zod": "^4.2.1"
},
@@ -2,6 +2,7 @@ import type { IntegrationKind } from "@homarr/definitions";
import { AdGuardHomeIntegration } from "../adguard-home/adguard-home-integration";
import { CodebergIntegration } from "../codeberg/codeberg-integration";
import { CoolifyIntegration } from "../coolify/coolify-integration";
import { DashDotIntegration } from "../dashdot/dashdot-integration";
import { DockerHubIntegration } from "../docker-hub/docker-hub-integration";
import { Aria2Integration } from "../download-client/aria2/aria2-integration";
@@ -103,6 +104,7 @@ export const integrationCreators = {
mock: MockIntegration,
truenas: TrueNasIntegration,
unraid: UnraidIntegration,
coolify: CoolifyIntegration,
} satisfies Record<IntegrationKind, IntegrationInstance | [(input: IntegrationInput) => Promise<Integration>]>;
type IntegrationInstanceOfKind<TKind extends keyof typeof integrationCreators> = {
@@ -0,0 +1,351 @@
import { ResponseError } from "@homarr/common/server";
import { fetchWithTrustedCertificatesAsync } from "@homarr/core/infrastructure/http";
import type { IntegrationTestingInput } from "../base/integration";
import { Integration } from "../base/integration";
import type { TestingResult } from "../base/test-connection/test-connection-service";
import type {
CoolifyApplication,
CoolifyApplicationWithContext,
CoolifyEnvironment,
CoolifyEnvironmentVariable,
CoolifyHealthcheck,
CoolifyInstanceInfo,
CoolifyProject,
CoolifyProjectWithEnvironments,
CoolifyResource,
CoolifyServer,
CoolifyService,
CoolifyServiceWithContext,
} from "./coolify-types";
import {
coolifyApplicationLogSchema,
coolifyApplicationSchema,
coolifyEnvironmentSchema,
coolifyEnvironmentVariableSchema,
coolifyHealthcheckSchema,
coolifyProjectSchema,
coolifyProjectWithEnvironmentsSchema,
coolifyResourceSchema,
coolifyServerSchema,
coolifyServiceSchema,
} from "./coolify-types";
export class CoolifyIntegration extends Integration {
protected async testingAsync(input: IntegrationTestingInput): Promise<TestingResult> {
const healthUrl = this.url("/api/health");
const healthResponse = await input.fetchAsync(healthUrl, {});
if (!healthResponse.ok) {
throw new ResponseError(healthResponse);
}
// Test API key authentication
const versionUrl = this.url("/api/v1/version");
const versionResponse = await input.fetchAsync(versionUrl, {
headers: this.getAuthHeaders(),
});
if (!versionResponse.ok) {
throw new ResponseError(versionResponse);
}
return { success: true };
}
/**
* Get Coolify version information
* https://coolify.io/docs/api-reference/api/operations/version
*/
public async getVersionAsync(): Promise<string> {
const url = this.url("/api/v1/version");
const response = await fetchWithTrustedCertificatesAsync(url, {
headers: this.getAuthHeaders(),
});
if (!response.ok) {
throw new ResponseError(response);
}
const version = await response.text();
return version.trim();
}
/**
* Get Coolify healthcheck status
* https://coolify.io/docs/api-reference/api/operations/healthcheck
*/
public async getHealthcheckAsync(): Promise<CoolifyHealthcheck> {
const url = this.url("/api/v1/healthcheck");
const response = await fetchWithTrustedCertificatesAsync(url, {
headers: this.getAuthHeaders(),
});
if (!response.ok) {
throw new ResponseError(response);
}
return coolifyHealthcheckSchema.parse(await response.json());
}
/**
* List all applications
* https://coolify.io/docs/api-reference/api/operations/list-applications
*/
public async listApplicationsAsync(): Promise<CoolifyApplication[]> {
const url = this.url("/api/v1/applications");
const response = await fetchWithTrustedCertificatesAsync(url, {
headers: this.getAuthHeaders(),
});
if (!response.ok) {
throw new ResponseError(response);
}
return coolifyApplicationSchema.array().parse(await response.json());
}
/**
* Get application by UUID
* https://coolify.io/docs/api-reference/api/operations/get-application-by-uuid
*/
public async getApplicationByUuidAsync(uuid: string): Promise<CoolifyApplication> {
const url = this.url(`/api/v1/applications/${uuid}`);
const response = await fetchWithTrustedCertificatesAsync(url, {
headers: this.getAuthHeaders(),
});
if (!response.ok) {
throw new ResponseError(response);
}
return coolifyApplicationSchema.parse(await response.json());
}
/**
* Get application logs by UUID
* https://coolify.io/docs/api-reference/api/operations/get-application-logs-by-uuid
*/
public async getApplicationLogsAsync(uuid: string): Promise<string> {
const url = this.url(`/api/v1/applications/${uuid}/logs`);
const response = await fetchWithTrustedCertificatesAsync(url, {
headers: this.getAuthHeaders(),
});
if (!response.ok) {
throw new ResponseError(response);
}
const result = coolifyApplicationLogSchema.parse(await response.json());
return result.logs;
}
/**
* List environment variables by application UUID
* https://coolify.io/docs/api-reference/api/operations/list-envs-by-application-uuid
*/
public async listEnvsByApplicationUuidAsync(uuid: string): Promise<CoolifyEnvironmentVariable[]> {
const url = this.url(`/api/v1/applications/${uuid}/envs`);
const response = await fetchWithTrustedCertificatesAsync(url, {
headers: this.getAuthHeaders(),
});
if (!response.ok) {
throw new ResponseError(response);
}
return coolifyEnvironmentVariableSchema.array().parse(await response.json());
}
/**
* List projects
* https://coolify.io/docs/api-reference/api/operations/list-projects
*/
public async listProjectsAsync(): Promise<CoolifyProject[]> {
const url = this.url("/api/v1/projects");
const response = await fetchWithTrustedCertificatesAsync(url, {
headers: this.getAuthHeaders(),
});
if (!response.ok) {
throw new ResponseError(response);
}
return coolifyProjectSchema.array().parse(await response.json());
}
/**
* Get project by UUID (includes environments)
* https://coolify.io/docs/api-reference/api/operations/get-project-by-uuid
*/
public async getProjectByUuidAsync(uuid: string): Promise<CoolifyProjectWithEnvironments> {
const url = this.url(`/api/v1/projects/${uuid}`);
const response = await fetchWithTrustedCertificatesAsync(url, {
headers: this.getAuthHeaders(),
});
if (!response.ok) {
throw new ResponseError(response);
}
return coolifyProjectWithEnvironmentsSchema.parse(await response.json());
}
/**
* Get environments
* https://coolify.io/docs/api-reference/api/operations/get-environments
*/
public async getEnvironmentsAsync(): Promise<CoolifyEnvironment[]> {
const url = this.url("/api/v1/environments");
const response = await fetchWithTrustedCertificatesAsync(url, {
headers: this.getAuthHeaders(),
});
if (!response.ok) {
throw new ResponseError(response);
}
return coolifyEnvironmentSchema.array().parse(await response.json());
}
/**
* Get environment by name or UUID
* https://coolify.io/docs/api-reference/api/operations/get-environment-by-name-or-uuid
*/
public async getEnvironmentByNameOrUuidAsync(nameOrUuid: string): Promise<CoolifyEnvironment> {
const url = this.url(`/api/v1/environments/${nameOrUuid}`);
const response = await fetchWithTrustedCertificatesAsync(url, {
headers: this.getAuthHeaders(),
});
if (!response.ok) {
throw new ResponseError(response);
}
return coolifyEnvironmentSchema.parse(await response.json());
}
/**
* List resources
* https://coolify.io/docs/api-reference/api/operations/list-resources
*/
public async listResourcesAsync(): Promise<CoolifyResource[]> {
const url = this.url("/api/v1/resources");
const response = await fetchWithTrustedCertificatesAsync(url, {
headers: this.getAuthHeaders(),
});
if (!response.ok) {
throw new ResponseError(response);
}
return coolifyResourceSchema.array().parse(await response.json());
}
/**
* List servers
* https://coolify.io/docs/api-reference/api/operations/list-servers
*/
public async listServersAsync(): Promise<CoolifyServer[]> {
const url = this.url("/api/v1/servers");
const response = await fetchWithTrustedCertificatesAsync(url, {
headers: this.getAuthHeaders(),
});
if (!response.ok) {
throw new ResponseError(response);
}
return coolifyServerSchema.array().parse(await response.json());
}
/**
* List services
* https://coolify.io/docs/api-reference/api/operations/list-services
*/
public async listServicesAsync(): Promise<CoolifyService[]> {
const url = this.url("/api/v1/services");
const response = await fetchWithTrustedCertificatesAsync(url, {
headers: this.getAuthHeaders(),
});
if (!response.ok) {
throw new ResponseError(response);
}
return coolifyServiceSchema.array().parse(await response.json());
}
public async getInstanceInfoAsync(): Promise<CoolifyInstanceInfo> {
const [version, applications, services, projectsWithEnvs, servers] = await Promise.all([
this.getVersionAsync(),
this.listApplicationsAsync(),
this.listServicesAsync(),
this.listProjectsWithEnvironmentsAsync(),
this.listServersAsync(),
]);
const envToProjectMap = new Map<
number,
{ projectName: string; projectUuid: string; environmentName: string; environmentUuid?: string }
>();
for (const project of projectsWithEnvs) {
for (const env of project.environments ?? []) {
if (env.id != null) {
envToProjectMap.set(env.id, {
projectName: project.name,
projectUuid: project.uuid,
environmentName: env.name,
environmentUuid: env.uuid ?? undefined,
});
}
}
}
const applicationsWithContext: CoolifyApplicationWithContext[] = applications.map((app) => {
const context = app.environment_id ? envToProjectMap.get(app.environment_id) : undefined;
return {
...app,
projectName: context?.projectName,
projectUuid: context?.projectUuid,
environmentName: context?.environmentName,
environmentUuid: context?.environmentUuid,
};
});
const servicesWithContext: CoolifyServiceWithContext[] = services.map((service) => {
const context = service.environment_id ? envToProjectMap.get(service.environment_id) : undefined;
const fqdn = service.fqdn ?? service.applications?.find((app) => app.fqdn)?.fqdn ?? undefined;
return {
...service,
fqdn,
projectName: context?.projectName,
projectUuid: context?.projectUuid,
environmentName: context?.environmentName,
environmentUuid: context?.environmentUuid,
};
});
return {
version,
applications: applicationsWithContext,
services: servicesWithContext,
servers,
};
}
/**
* List all projects with their environments
*/
private async listProjectsWithEnvironmentsAsync(): Promise<CoolifyProjectWithEnvironments[]> {
const projects = await this.listProjectsAsync();
const projectsWithEnvs = await Promise.all(projects.map((project) => this.getProjectByUuidAsync(project.uuid)));
return projectsWithEnvs;
}
private getAuthHeaders(): Record<string, string> {
return {
Authorization: `Bearer ${this.getSecretValue("apiKey")}`,
};
}
}
@@ -0,0 +1,154 @@
// Coolify API Types and Schemas based on https://coolify.io/docs/api-reference/api
import { z } from "zod/v4";
// Health check schema
export const coolifyHealthcheckSchema = z.object({
status: z.string(),
});
export type CoolifyHealthcheck = z.infer<typeof coolifyHealthcheckSchema>;
// Application log schema
export const coolifyApplicationLogSchema = z.object({
logs: z.string(),
});
export type CoolifyApplicationLog = z.infer<typeof coolifyApplicationLogSchema>;
// Environment variable schema
export const coolifyEnvironmentVariableSchema = z.object({
id: z.number().nullish(),
key: z.string(),
value: z.string(),
is_build_time: z.boolean().nullish(),
is_preview: z.boolean().nullish(),
application_id: z.number().nullish(),
});
export type CoolifyEnvironmentVariable = z.infer<typeof coolifyEnvironmentVariableSchema>;
// Application schema (only fields used in the widget)
export const coolifyApplicationSchema = z.object({
id: z.number().nullish(),
uuid: z.string(),
name: z.string(),
status: z.string().nullish(),
fqdn: z.string().nullish(),
environment_id: z.number().nullish(),
server_id: z.number().nullish(),
destination_id: z.number().nullish(),
updated_at: z.string().nullish(),
last_online_at: z.string().nullish(),
});
export type CoolifyApplication = z.infer<typeof coolifyApplicationSchema>;
// Project schema
export const coolifyProjectSchema = z.object({
id: z.number().nullish(),
uuid: z.string(),
name: z.string(),
});
export type CoolifyProject = z.infer<typeof coolifyProjectSchema>;
// Environment schema
export const coolifyEnvironmentSchema = z.object({
id: z.number().nullish(),
uuid: z.string().nullish(),
name: z.string(),
project_id: z.number().nullish(),
});
export type CoolifyEnvironment = z.infer<typeof coolifyEnvironmentSchema>;
// Project with environments schema
export const coolifyProjectWithEnvironmentsSchema = coolifyProjectSchema.extend({
environments: z.array(coolifyEnvironmentSchema).nullish(),
});
export type CoolifyProjectWithEnvironments = z.infer<typeof coolifyProjectWithEnvironmentsSchema>;
// Resource schema
export const coolifyResourceSchema = z.object({
id: z.number().nullish(),
uuid: z.string(),
name: z.string(),
type: z.string(),
status: z.string().nullish(),
});
export type CoolifyResource = z.infer<typeof coolifyResourceSchema>;
// Server settings schema
export const coolifyServerSettingsSchema = z.object({
server_id: z.number().nullish(),
is_build_server: z.boolean().nullish(),
is_reachable: z.boolean().nullish(),
is_usable: z.boolean().nullish(),
});
export type CoolifyServerSettings = z.infer<typeof coolifyServerSettingsSchema>;
// Server schema
export const coolifyServerSchema = z.object({
id: z.number().nullish(),
uuid: z.string(),
name: z.string(),
ip: z.string().nullish(),
is_reachable: z.boolean().nullish(),
is_usable: z.boolean().nullish(),
settings: coolifyServerSettingsSchema.nullish(),
});
export type CoolifyServer = z.infer<typeof coolifyServerSchema>;
// Service application schema (nested in services)
export const coolifyServiceApplicationSchema = z.object({
id: z.number().nullish(),
uuid: z.string(),
name: z.string(),
fqdn: z.string().nullish(),
status: z.string().nullish(),
});
export type CoolifyServiceApplication = z.infer<typeof coolifyServiceApplicationSchema>;
// Service schema
export const coolifyServiceSchema = z.object({
id: z.number().nullish(),
uuid: z.string(),
name: z.string(),
status: z.string().nullish(),
fqdn: z.string().nullish(),
environment_id: z.number().nullish(),
server_id: z.number().nullish(),
destination_id: z.number().nullish(),
updated_at: z.string().nullish(),
applications: z.array(coolifyServiceApplicationSchema).nullish(),
});
export type CoolifyService = z.infer<typeof coolifyServiceSchema>;
// Extended types with context (not from API, added by integration)
export interface CoolifyApplicationWithContext extends CoolifyApplication {
projectName?: string;
projectUuid?: string;
environmentName?: string;
environmentUuid?: string;
}
export interface CoolifyServiceWithContext extends CoolifyService {
projectName?: string;
projectUuid?: string;
environmentName?: string;
environmentUuid?: string;
}
// Aggregated information for the Coolify instance
export interface CoolifyInstanceInfo {
version: string;
applications: CoolifyApplicationWithContext[];
services: CoolifyServiceWithContext[];
servers: CoolifyServer[];
}
@@ -0,0 +1,313 @@
import { Request, Response } from "undici";
import { beforeEach, describe, expect, test, vi } from "vitest";
import { fetchWithTrustedCertificatesAsync } from "@homarr/core/infrastructure/http";
import { CoolifyIntegration } from "../coolify-integration";
import type {
CoolifyApplication,
CoolifyProject,
CoolifyProjectWithEnvironments,
CoolifyServer,
CoolifyService,
} from "../coolify-types";
vi.mock("@homarr/core/infrastructure/http", () => ({
fetchWithTrustedCertificatesAsync: vi.fn(),
}));
const TEST_API_KEY = "test-api-key-12345";
const TEST_URL = "https://coolify.example.com";
type MockResponseData = string | Record<string, unknown> | unknown[];
const mockFetchWithTrustedCertificates = vi.mocked(fetchWithTrustedCertificatesAsync);
const setupMockFetch = (responses: Record<string, MockResponseData>) => {
mockFetchWithTrustedCertificates.mockImplementation((url) => {
const urlString = typeof url === "string" ? url : url instanceof Request ? url.url : url.toString();
const urlObj = new URL(urlString);
const path = urlObj.pathname;
if (path in responses) {
const data = responses[path];
const body = typeof data === "string" ? data : JSON.stringify(data);
return Promise.resolve(
new Response(body, {
status: 200,
headers: { "content-type": "application/json" },
}) as unknown as Awaited<ReturnType<typeof fetchWithTrustedCertificatesAsync>>,
);
}
return Promise.resolve(
new Response(JSON.stringify({ error: "Not Found" }), {
status: 404,
headers: { "content-type": "application/json" },
}) as unknown as Awaited<ReturnType<typeof fetchWithTrustedCertificatesAsync>>,
);
});
};
const createCoolifyIntegration = () => {
return new CoolifyIntegration({
id: "test-coolify",
name: "Test Coolify",
url: TEST_URL,
externalUrl: null,
decryptedSecrets: [{ kind: "apiKey", value: TEST_API_KEY }],
});
};
describe("CoolifyIntegration", () => {
beforeEach(() => {
vi.clearAllMocks();
});
describe("getVersionAsync", () => {
test("should return version string from Coolify API", async () => {
setupMockFetch({
"/api/v1/version": "4.0.0-beta.460",
});
const integration = createCoolifyIntegration();
const result = await integration.getVersionAsync();
expect(result).toBe("4.0.0-beta.460");
expect(mockFetchWithTrustedCertificates).toHaveBeenCalled();
});
test("should throw error when API returns error", async () => {
mockFetchWithTrustedCertificates.mockResolvedValue(
new Response("Unauthorized", {
status: 401,
headers: { "content-type": "text/plain" },
}) as unknown as Awaited<ReturnType<typeof fetchWithTrustedCertificatesAsync>>,
);
const integration = createCoolifyIntegration();
await expect(integration.getVersionAsync()).rejects.toThrow();
});
});
describe("listServersAsync", () => {
test("should return list of servers", async () => {
const servers: CoolifyServer[] = [
{
id: 1,
uuid: "server-uuid-1",
name: "Production Server",
ip: "192.168.1.100",
is_reachable: true,
is_usable: true,
settings: { is_build_server: false },
},
{
id: 2,
uuid: "server-uuid-2",
name: "Build Server",
ip: "192.168.1.101",
is_reachable: true,
is_usable: true,
settings: { is_build_server: true },
},
];
setupMockFetch({
"/api/v1/servers": servers,
});
const integration = createCoolifyIntegration();
const result = await integration.listServersAsync();
expect(result).toHaveLength(2);
expect(result[0]?.name).toBe("Production Server");
expect(result[1]?.settings?.is_build_server).toBe(true);
});
});
describe("listApplicationsAsync", () => {
test("should return list of applications", async () => {
const applications: CoolifyApplication[] = [
{
id: 1,
uuid: "app-uuid-1",
name: "my-app",
fqdn: "https://myapp.example.com",
status: "running",
updated_at: "2024-01-01T00:00:00Z",
},
{
id: 2,
uuid: "app-uuid-2",
name: "another-app",
fqdn: "https://another.example.com",
status: "stopped",
updated_at: "2024-01-01T00:00:00Z",
},
];
setupMockFetch({
"/api/v1/applications": applications,
});
const integration = createCoolifyIntegration();
const result = await integration.listApplicationsAsync();
expect(result).toHaveLength(2);
expect(result[0]?.status).toBe("running");
expect(result[1]?.status).toBe("stopped");
});
});
describe("listServicesAsync", () => {
test("should return list of services", async () => {
const services: CoolifyService[] = [
{
id: 1,
uuid: "service-uuid-1",
name: "postgresql",
updated_at: "2024-01-01T00:00:00Z",
},
];
setupMockFetch({
"/api/v1/services": services,
});
const integration = createCoolifyIntegration();
const result = await integration.listServicesAsync();
expect(result).toHaveLength(1);
expect(result[0]?.name).toBe("postgresql");
});
});
describe("listProjectsAsync", () => {
test("should return list of projects", async () => {
const projects: CoolifyProject[] = [
{
id: 1,
uuid: "proj-uuid-1",
name: "Production",
},
];
setupMockFetch({
"/api/v1/projects": projects,
});
const integration = createCoolifyIntegration();
const result = await integration.listProjectsAsync();
expect(result).toHaveLength(1);
expect(result[0]?.name).toBe("Production");
});
});
describe("getInstanceInfoAsync", () => {
test("should aggregate all instance data with project context", async () => {
const projectWithEnvs: CoolifyProjectWithEnvironments = {
id: 1,
uuid: "proj-uuid-1",
name: "Production",
environments: [
{
id: 1,
uuid: "env-uuid-1",
name: "production",
project_id: 1,
},
],
};
setupMockFetch({
"/api/v1/version": "4.0.0-beta.460",
"/api/v1/applications": [
{
id: 1,
uuid: "app-uuid-1",
name: "my-app",
status: "running",
environment_id: 1,
updated_at: "2024-01-01T00:00:00Z",
},
],
"/api/v1/services": [
{
id: 1,
uuid: "service-uuid-1",
name: "postgres",
environment_id: 1,
updated_at: "2024-01-01T00:00:00Z",
},
],
"/api/v1/projects": [
{
id: 1,
uuid: "proj-uuid-1",
name: "Production",
},
],
"/api/v1/servers": [
{
id: 1,
uuid: "server-uuid-1",
name: "Server 1",
ip: "192.168.1.1",
is_reachable: true,
is_usable: true,
settings: { is_build_server: false },
},
],
"/api/v1/projects/proj-uuid-1": projectWithEnvs,
});
const integration = createCoolifyIntegration();
const result = await integration.getInstanceInfoAsync();
expect(result.version).toBe("4.0.0-beta.460");
expect(result.applications).toHaveLength(1);
expect(result.services).toHaveLength(1);
expect(result.servers).toHaveLength(1);
expect(result.applications[0]?.projectName).toBe("Production");
expect(result.applications[0]?.environmentName).toBe("production");
});
});
describe("getHealthcheckAsync", () => {
test("should return healthcheck status", async () => {
setupMockFetch({
"/api/v1/healthcheck": { status: "healthy" },
});
const integration = createCoolifyIntegration();
const result = await integration.getHealthcheckAsync();
expect(result.status).toBe("healthy");
});
});
describe("getApplicationByUuidAsync", () => {
test("should return application details by UUID", async () => {
const application: CoolifyApplication = {
id: 1,
uuid: "app-uuid-1",
name: "my-app",
fqdn: "https://app.example.com",
status: "running",
updated_at: "2024-01-01T00:00:00Z",
};
setupMockFetch({
"/api/v1/applications/app-uuid-1": application,
});
const integration = createCoolifyIntegration();
const result = await integration.getApplicationByUuidAsync("app-uuid-1");
expect(result.uuid).toBe("app-uuid-1");
expect(result.name).toBe("my-app");
});
});
});
@@ -55,7 +55,7 @@ export class DashDotIntegration extends Integration implements ISystemHealthMoni
cpuTemp: cpuLoad.averageTemperature,
availablePkgUpdates: 0,
rebootRequired: false,
smart: [],
smart: [], // API endpoint does not provide S.M.A.R.T data.
uptime: info.uptime,
version: `${info.operatingSystemVersion}`,
loadAverage: {
+1
View File
@@ -25,6 +25,7 @@ export { TrueNasIntegration } from "./truenas/truenas-integration";
export { UnraidIntegration } from "./unraid/unraid-integration";
export { OPNsenseIntegration } from "./opnsense/opnsense-integration";
export { ICalIntegration } from "./ical/ical-integration";
export { CoolifyIntegration } from "./coolify/coolify-integration";
// Types
export type { IntegrationInput } from "./base/integration";
@@ -29,6 +29,7 @@ export interface SystemHealthMonitoring {
deviceName: string;
temperature: number | null;
overallStatus: string;
healthy: boolean;
}[];
}
@@ -33,6 +33,7 @@ export class SystemHealthMonitoringMockService implements ISystemHealthMonitorin
deviceName: "Mock Device",
temperature: Math.floor(Math.random() * 100), // Random temperature between 0 and 99
overallStatus: "OK",
healthy: true,
},
],
});
@@ -62,6 +62,8 @@ export class OpenMediaVaultIntegration extends Integration implements ISystemHea
const smart = smartResult.data.response.map((smart) => ({
deviceName: smart.devicename,
temperature: smart.temperature,
// https://github.com/openmediavault/openmediavault/blob/2eb871d05cec6ff49603134d3acead561da01e4d/deb/openmediavault/usr/share/php/openmediavault/system/storage/smartinformation.inc#L592-L605
healthy: smart.overallstatus === "GOOD",
overallStatus: smart.overallstatus,
}));
@@ -115,9 +115,8 @@ export class OverseerrIntegration
}
public async getRequestsAsync(): Promise<MediaRequest[]> {
//Ensure to get all pending request first
const pendingRequests = await fetchWithTrustedCertificatesAsync(
this.url("/api/v1/request", { take: -1, filter: "pending" }),
this.url("/api/v1/request", { take: 20, filter: "pending" }),
{
headers: {
"X-Api-Key": this.getSecretValue("apiKey"),
@@ -125,7 +124,6 @@ export class OverseerrIntegration
},
);
//Change 20 to integration setting (set to -1 for all)
const allRequests = await fetchWithTrustedCertificatesAsync(this.url("/api/v1/request", { take: 20 }), {
headers: {
"X-Api-Key": this.getSecretValue("apiKey"),
@@ -223,7 +221,7 @@ export class OverseerrIntegration
}
public async getUsersAsync(): Promise<RequestUser[]> {
const response = await fetchWithTrustedCertificatesAsync(this.url("/api/v1/user", { take: -1 }), {
const response = await fetchWithTrustedCertificatesAsync(this.url("/api/v1/user", { take: 10, sort: "requests" }), {
headers: {
"X-Api-Key": this.getSecretValue("apiKey"),
},
@@ -112,6 +112,27 @@ export class TrueNasIntegration extends Integration implements ISystemHealthMoni
});
}
private async getPoolsAsync() {
logger.debug("Retrieving pools", {
url: this.wsUrl(),
});
const response = await this.requestAsync("pool.query", [
[],
{
extra: {
is_upgraded: true,
},
},
]);
const result = await poolSchema.parseAsync(response);
logger.debug("Retrieved pools", {
url: this.wsUrl(),
count: result.length,
});
return result;
}
/**
* Retrieves data using the reporting method
* @see https://www.truenas.com/docs/api/scale_websocket_api.html#reporting
@@ -225,6 +246,7 @@ export class TrueNasIntegration extends Integration implements ISystemHealthMoni
const cpuData = this.extractLatestReportingData(reporting, "cpu");
const cpuTempData = this.extractLatestReportingData(reporting, "cputemp");
const memoryData = this.extractLatestReportingData(reporting, "memory");
const datasets = await this.getPoolsAsync();
const netdata = await this.getReportingNetdataAsync();
@@ -236,14 +258,24 @@ export class TrueNasIntegration extends Integration implements ISystemHealthMoni
cpuTemp: Math.max(...cpuTempData.filter((_item, i) => i > 0)),
memAvailableInBytes: systemInformation.physmem,
memUsedInBytes: memoryData[1] ?? 0, // Index 0 is UNIX timestamp, Index 1 is free space in bytes
fileSystem: [],
fileSystem: datasets.map((dataset) => ({
deviceName: dataset.name,
available: `${dataset.size}`, // TODO: can we use number instead of string here?
used: `${dataset.allocated}`,
percentage: (dataset.allocated / dataset.size) * 100,
})),
availablePkgUpdates: 0,
network: {
up: upload * NETWORK_MULTIPLIER,
down: download * NETWORK_MULTIPLIER,
},
loadAverage: null,
smart: [],
smart: datasets.map((dataset) => ({
deviceName: dataset.name,
healthy: dataset.healthy,
overallStatus: dataset.status,
temperature: null,
})),
uptime: systemInformation.uptime_seconds,
version: systemInformation.version,
cpuModelName: systemInformation.model,
@@ -351,6 +383,17 @@ const reportingItemSchema = z.object({
type ReportingItem = z.infer<typeof reportingItemSchema>;
const poolSchema = z.array(
z.object({
name: z.string(),
status: z.string(),
healthy: z.boolean(),
free: z.number().min(0),
size: z.number(),
allocated: z.number(),
}),
);
const reportingNetDataSchema = z.array(
z.object({
name: z.string(),
+1
View File
@@ -11,3 +11,4 @@ export * from "./proxmox/proxmox-types";
export * from "./unifi-controller/unifi-controller-types";
export * from "./opnsense/opnsense-types";
export * from "./interfaces/media-releases";
export * from "./coolify/coolify-types";
@@ -67,6 +67,8 @@ export class UnraidIntegration extends Integration implements ISystemHealthMonit
deviceName: disk.name,
temperature: disk.temp ?? null,
overallStatus: disk.status,
// See ArrayDiskStatus from https://studio.apollographql.com/public/Unraid-API/variant/current/explorer
healthy: disk.status === "DISK_OK",
})),
};
}
+4 -4
View File
@@ -33,12 +33,12 @@
"@homarr/translation": "workspace:^0.1.0",
"@homarr/ui": "workspace:^0.1.0",
"@homarr/validation": "workspace:^0.1.0",
"@mantine/core": "^8.3.10",
"@mantine/core": "^8.3.14",
"@tabler/icons-react": "^3.36.1",
"dayjs": "^1.11.19",
"next": "16.1.1",
"react": "19.2.3",
"react-dom": "19.2.3",
"next": "16.1.6",
"react": "19.2.4",
"react-dom": "19.2.4",
"zod": "^4.2.1"
},
"devDependencies": {
+3 -3
View File
@@ -24,9 +24,9 @@
"dependencies": {
"@homarr/translation": "workspace:^0.1.0",
"@homarr/ui": "workspace:^0.1.0",
"@mantine/core": "^8.3.10",
"@mantine/hooks": "^8.3.10",
"react": "19.2.3"
"@mantine/core": "^8.3.14",
"@mantine/hooks": "^8.3.14",
"react": "19.2.4"
},
"devDependencies": {
"@homarr/eslint-config": "workspace:^0.2.0",
+1 -1
View File
@@ -24,7 +24,7 @@
"prettier": "@homarr/prettier-config",
"dependencies": {
"@homarr/ui": "workspace:^0.1.0",
"@mantine/notifications": "^8.3.10",
"@mantine/notifications": "^8.3.14",
"@tabler/icons-react": "^3.36.1"
},
"devDependencies": {
+5 -5
View File
@@ -37,12 +37,12 @@
"@homarr/translation": "workspace:^0.1.0",
"@homarr/ui": "workspace:^0.1.0",
"@homarr/validation": "workspace:^0.1.0",
"@mantine/core": "^8.3.10",
"@mantine/hooks": "^8.3.10",
"@mantine/core": "^8.3.14",
"@mantine/hooks": "^8.3.14",
"adm-zip": "0.5.16",
"next": "16.1.1",
"react": "19.2.3",
"react-dom": "19.2.3",
"next": "16.1.6",
"react": "19.2.4",
"react-dom": "19.2.4",
"superjson": "2.2.6",
"zod": "^4.2.1",
"zod-form-data": "^3.0.1"
+1 -1
View File
@@ -26,7 +26,7 @@
"@homarr/core": "workspace:^",
"@homarr/db": "workspace:^",
"@homarr/definitions": "workspace:^",
"ioredis": "5.8.2",
"ioredis": "5.9.2",
"superjson": "2.2.6"
},
"devDependencies": {
+1 -1
View File
@@ -33,7 +33,7 @@
"dayjs": "^1.11.19",
"octokit": "^5.0.5",
"superjson": "2.2.6",
"undici": "7.16.0",
"undici": "7.18.2",
"zod": "^4.2.1"
},
"devDependencies": {
+19
View File
@@ -0,0 +1,19 @@
import dayjs from "dayjs";
import { createIntegrationAsync } from "@homarr/integrations";
import type { CoolifyInstanceInfo } from "@homarr/integrations/types";
import { createCachedIntegrationRequestHandler } from "./lib/cached-integration-request-handler";
export const coolifyRequestHandler = createCachedIntegrationRequestHandler<
CoolifyInstanceInfo,
"coolify",
Record<string, never>
>({
async requestAsync(integration, _input) {
const integrationInstance = await createIntegrationAsync(integration);
return await integrationInstance.getInstanceInfoAsync();
},
cacheDuration: dayjs.duration(30, "seconds"),
queryKey: "coolifyInfo",
});
@@ -8,7 +8,7 @@ import { createCachedIntegrationRequestHandler } from "./lib/cached-integration-
export const systemInfoRequestHandler = createCachedIntegrationRequestHandler<
SystemHealthMonitoring,
Exclude<IntegrationKindByCategory<"healthMonitoring">, "proxmox">,
Exclude<IntegrationKindByCategory<"healthMonitoring">, "proxmox" | "coolify">,
Record<string, never>
>({
async requestAsync(integration, _input) {
+4 -4
View File
@@ -25,10 +25,10 @@
"dependencies": {
"@homarr/db": "workspace:^0.1.0",
"@homarr/server-settings": "workspace:^0.1.0",
"@mantine/dates": "^8.3.10",
"next": "16.1.1",
"react": "19.2.3",
"react-dom": "19.2.3"
"@mantine/dates": "^8.3.14",
"next": "16.1.6",
"react": "19.2.4",
"react-dom": "19.2.4"
},
"devDependencies": {
"@homarr/eslint-config": "workspace:^0.2.0",
+7 -7
View File
@@ -33,14 +33,14 @@
"@homarr/settings": "workspace:^0.1.0",
"@homarr/translation": "workspace:^0.1.0",
"@homarr/ui": "workspace:^0.1.0",
"@mantine/core": "^8.3.10",
"@mantine/hooks": "^8.3.10",
"@mantine/spotlight": "^8.3.10",
"@mantine/core": "^8.3.14",
"@mantine/hooks": "^8.3.14",
"@mantine/spotlight": "^8.3.14",
"@tabler/icons-react": "^3.36.1",
"jotai": "^2.16.1",
"next": "16.1.1",
"react": "19.2.3",
"react-dom": "19.2.3",
"jotai": "^2.17.1",
"next": "16.1.6",
"react": "19.2.4",
"react-dom": "19.2.4",
"use-deep-compare-effect": "^1.8.1"
},
"devDependencies": {
+4 -4
View File
@@ -32,10 +32,10 @@
"dayjs": "^1.11.19",
"deepmerge": "4.3.1",
"mantine-react-table": "2.0.0-beta.9",
"next": "16.1.1",
"next-intl": "4.7.0",
"react": "19.2.3",
"react-dom": "19.2.3"
"next": "16.1.6",
"next-intl": "4.8.2",
"react": "19.2.4",
"react-dom": "19.2.4"
},
"devDependencies": {
"@homarr/eslint-config": "workspace:^0.2.0",
+72
View File
@@ -1138,6 +1138,9 @@
"dangerZone": "",
"noResults": "",
"unsavedChanges": "",
"servers": "",
"applications": "",
"services": "",
"preview": {
"show": "",
"hide": ""
@@ -1960,6 +1963,39 @@
"internalServerError": ""
}
},
"coolify": {
"name": "",
"description": "",
"option": {
"showServers": {
"label": ""
},
"showApplications": {
"label": ""
},
"showServices": {
"label": ""
}
},
"empty": {
"servers": "",
"applications": "",
"services": ""
},
"footer": {
"updated": ""
},
"error": {
"noIntegration": "",
"internalServerError": ""
},
"server": {
"buildServer": ""
},
"instances": {
"title": ""
}
},
"common": {
"location": {
"query": "",
@@ -2608,6 +2644,35 @@
"up": "",
"down": ""
}
},
"systemDisks": {
"name": "",
"description": "",
"option": {
"showTemperatureIfAvailable": {
"label": ""
},
"displayMode": {
"label": "",
"option": {
"percentage": {
"label": ""
},
"absolute": {
"label": ""
},
"free": {
"label": ""
}
}
},
"showBackgroundBar": {
"label": ""
}
},
"status": {
"unhealthy": ""
}
}
},
"widgetPreview": {
@@ -3294,6 +3359,13 @@
}
}
},
"user": {
"title": "",
"enableGravatar": {
"label": "",
"description": ""
}
},
"search": {
"title": "",
"defaultSearchEngine": {
+72
View File
@@ -1138,6 +1138,9 @@
"dangerZone": "危险",
"noResults": "未找到结果",
"unsavedChanges": "你有未保存的更改 !",
"servers": "",
"applications": "",
"services": "",
"preview": {
"show": "显示预览",
"hide": "隐藏预览"
@@ -1960,6 +1963,39 @@
"internalServerError": "获取容器统计信息失败"
}
},
"coolify": {
"name": "",
"description": "",
"option": {
"showServers": {
"label": ""
},
"showApplications": {
"label": ""
},
"showServices": {
"label": ""
}
},
"empty": {
"servers": "",
"applications": "",
"services": ""
},
"footer": {
"updated": ""
},
"error": {
"noIntegration": "",
"internalServerError": ""
},
"server": {
"buildServer": ""
},
"instances": {
"title": ""
}
},
"common": {
"location": {
"query": "城市/邮编",
@@ -2608,6 +2644,35 @@
"up": "上传",
"down": "下载"
}
},
"systemDisks": {
"name": "",
"description": "",
"option": {
"showTemperatureIfAvailable": {
"label": ""
},
"displayMode": {
"label": "",
"option": {
"percentage": {
"label": ""
},
"absolute": {
"label": ""
},
"free": {
"label": ""
}
}
},
"showBackgroundBar": {
"label": ""
}
},
"status": {
"unhealthy": ""
}
}
},
"widgetPreview": {
@@ -3294,6 +3359,13 @@
}
}
},
"user": {
"title": "用户",
"enableGravatar": {
"label": "启用Gravatar",
"description": "未设置自定义头像时,若用户有邮箱,则自动采用其 Libravatar/Gravatar 头像"
}
},
"search": {
"title": "搜索",
"defaultSearchEngine": {
+73 -1
View File
@@ -1138,6 +1138,9 @@
"dangerZone": "crwdns610:0crwdne610:0",
"noResults": "crwdns612:0crwdne612:0",
"unsavedChanges": "crwdns2784:0crwdne2784:0",
"servers": "crwdns3846:0crwdne3846:0",
"applications": "crwdns3848:0crwdne3848:0",
"services": "crwdns3850:0crwdne3850:0",
"preview": {
"show": "crwdns614:0crwdne614:0",
"hide": "crwdns616:0crwdne616:0"
@@ -1960,6 +1963,39 @@
"internalServerError": "crwdns3428:0crwdne3428:0"
}
},
"coolify": {
"name": "crwdns3852:0crwdne3852:0",
"description": "crwdns3854:0crwdne3854:0",
"option": {
"showServers": {
"label": "crwdns3856:0crwdne3856:0"
},
"showApplications": {
"label": "crwdns3858:0crwdne3858:0"
},
"showServices": {
"label": "crwdns3860:0crwdne3860:0"
}
},
"empty": {
"servers": "crwdns3862:0crwdne3862:0",
"applications": "crwdns3864:0crwdne3864:0",
"services": "crwdns3866:0crwdne3866:0"
},
"footer": {
"updated": "crwdns3868:0{when}crwdne3868:0"
},
"error": {
"noIntegration": "crwdns3870:0crwdne3870:0",
"internalServerError": "crwdns3872:0crwdne3872:0"
},
"server": {
"buildServer": "crwdns3874:0crwdne3874:0"
},
"instances": {
"title": "crwdns3876:0crwdne3876:0"
}
},
"common": {
"location": {
"query": "crwdns1110:0crwdne1110:0",
@@ -2608,6 +2644,35 @@
"up": "crwdns3610:0crwdne3610:0",
"down": "crwdns3612:0crwdne3612:0"
}
},
"systemDisks": {
"name": "crwdns3828:0crwdne3828:0",
"description": "crwdns3830:0crwdne3830:0",
"option": {
"showTemperatureIfAvailable": {
"label": "crwdns3832:0crwdne3832:0"
},
"displayMode": {
"label": "crwdns3834:0crwdne3834:0",
"option": {
"percentage": {
"label": "crwdns3836:0crwdne3836:0"
},
"absolute": {
"label": "crwdns3838:0crwdne3838:0"
},
"free": {
"label": "crwdns3840:0crwdne3840:0"
}
}
},
"showBackgroundBar": {
"label": "crwdns3842:0crwdne3842:0"
}
},
"status": {
"unhealthy": "crwdns3844:0crwdne3844:0"
}
}
},
"widgetPreview": {
@@ -3240,7 +3305,7 @@
"title": "crwdns1764:0crwdne1764:0",
"general": {
"title": "crwdns1766:0crwdne1766:0",
"text": "crwdns1768:0crwdne1768:0"
"text": "crwdns3878:0crwdne3878:0"
},
"widgetData": {
"title": "crwdns1770:0crwdne1770:0",
@@ -3294,6 +3359,13 @@
}
}
},
"user": {
"title": "crwdns3822:0crwdne3822:0",
"enableGravatar": {
"label": "crwdns3824:0crwdne3824:0",
"description": "crwdns3826:0crwdne3826:0"
}
},
"search": {
"title": "crwdns2550:0crwdne2550:0",
"defaultSearchEngine": {
+72
View File
@@ -1138,6 +1138,9 @@
"dangerZone": "Nebezpečná zóna",
"noResults": "Nebyly nalezeny žádné výsledky",
"unsavedChanges": "",
"servers": "",
"applications": "",
"services": "",
"preview": {
"show": "Zobrazit náhled",
"hide": "Skrýt náhled"
@@ -1960,6 +1963,39 @@
"internalServerError": ""
}
},
"coolify": {
"name": "",
"description": "",
"option": {
"showServers": {
"label": ""
},
"showApplications": {
"label": ""
},
"showServices": {
"label": ""
}
},
"empty": {
"servers": "",
"applications": "",
"services": ""
},
"footer": {
"updated": ""
},
"error": {
"noIntegration": "",
"internalServerError": ""
},
"server": {
"buildServer": ""
},
"instances": {
"title": ""
}
},
"common": {
"location": {
"query": "",
@@ -2608,6 +2644,35 @@
"up": "",
"down": ""
}
},
"systemDisks": {
"name": "",
"description": "",
"option": {
"showTemperatureIfAvailable": {
"label": ""
},
"displayMode": {
"label": "",
"option": {
"percentage": {
"label": ""
},
"absolute": {
"label": ""
},
"free": {
"label": ""
}
}
},
"showBackgroundBar": {
"label": ""
}
},
"status": {
"unhealthy": ""
}
}
},
"widgetPreview": {
@@ -3294,6 +3359,13 @@
}
}
},
"user": {
"title": "",
"enableGravatar": {
"label": "",
"description": ""
}
},
"search": {
"title": "",
"defaultSearchEngine": {
+72
View File
@@ -1138,6 +1138,9 @@
"dangerZone": "Farezone",
"noResults": "Ingen resultater fundet",
"unsavedChanges": "Du har ikke gemte ændringer!",
"servers": "",
"applications": "",
"services": "",
"preview": {
"show": "Vis forhåndsvisning",
"hide": "Skjul forhåndsvisning"
@@ -1960,6 +1963,39 @@
"internalServerError": "Kunne ikke hente containerstatistik"
}
},
"coolify": {
"name": "",
"description": "",
"option": {
"showServers": {
"label": ""
},
"showApplications": {
"label": ""
},
"showServices": {
"label": ""
}
},
"empty": {
"servers": "",
"applications": "",
"services": ""
},
"footer": {
"updated": ""
},
"error": {
"noIntegration": "",
"internalServerError": ""
},
"server": {
"buildServer": ""
},
"instances": {
"title": ""
}
},
"common": {
"location": {
"query": "By / Postnummer",
@@ -2608,6 +2644,35 @@
"up": "OP",
"down": "NED"
}
},
"systemDisks": {
"name": "",
"description": "",
"option": {
"showTemperatureIfAvailable": {
"label": ""
},
"displayMode": {
"label": "",
"option": {
"percentage": {
"label": ""
},
"absolute": {
"label": ""
},
"free": {
"label": ""
}
}
},
"showBackgroundBar": {
"label": ""
}
},
"status": {
"unhealthy": ""
}
}
},
"widgetPreview": {
@@ -3294,6 +3359,13 @@
}
}
},
"user": {
"title": "",
"enableGravatar": {
"label": "",
"description": ""
}
},
"search": {
"title": "Søg",
"defaultSearchEngine": {
+72
View File
@@ -1138,6 +1138,9 @@
"dangerZone": "Gefahrenbereich",
"noResults": "Die Suche ergab keine Treffer",
"unsavedChanges": "Sie haben ungespeicherte Änderungen!",
"servers": "",
"applications": "",
"services": "",
"preview": {
"show": "Vorschau ansehen",
"hide": "Vorschau ausblenden"
@@ -1960,6 +1963,39 @@
"internalServerError": ""
}
},
"coolify": {
"name": "",
"description": "",
"option": {
"showServers": {
"label": ""
},
"showApplications": {
"label": ""
},
"showServices": {
"label": ""
}
},
"empty": {
"servers": "",
"applications": "",
"services": ""
},
"footer": {
"updated": ""
},
"error": {
"noIntegration": "",
"internalServerError": ""
},
"server": {
"buildServer": ""
},
"instances": {
"title": ""
}
},
"common": {
"location": {
"query": "Stadt / Postleitzahl",
@@ -2608,6 +2644,35 @@
"up": "",
"down": ""
}
},
"systemDisks": {
"name": "",
"description": "",
"option": {
"showTemperatureIfAvailable": {
"label": ""
},
"displayMode": {
"label": "",
"option": {
"percentage": {
"label": ""
},
"absolute": {
"label": ""
},
"free": {
"label": ""
}
}
},
"showBackgroundBar": {
"label": ""
}
},
"status": {
"unhealthy": ""
}
}
},
"widgetPreview": {
@@ -3294,6 +3359,13 @@
}
}
},
"user": {
"title": "",
"enableGravatar": {
"label": "",
"description": ""
}
},
"search": {
"title": "Suche",
"defaultSearchEngine": {
+72
View File
@@ -1138,6 +1138,9 @@
"dangerZone": "Gefahrenbereich",
"noResults": "Die Suche ergab keine Treffer",
"unsavedChanges": "Sie haben ungespeicherte Änderungen!",
"servers": "",
"applications": "",
"services": "",
"preview": {
"show": "Vorschau ansehen",
"hide": "Vorschau ausblenden"
@@ -1960,6 +1963,39 @@
"internalServerError": "Fehler beim Abrufen der Container Statistiken"
}
},
"coolify": {
"name": "",
"description": "",
"option": {
"showServers": {
"label": ""
},
"showApplications": {
"label": ""
},
"showServices": {
"label": ""
}
},
"empty": {
"servers": "",
"applications": "",
"services": ""
},
"footer": {
"updated": ""
},
"error": {
"noIntegration": "",
"internalServerError": ""
},
"server": {
"buildServer": ""
},
"instances": {
"title": ""
}
},
"common": {
"location": {
"query": "Stadt / Postleitzahl",
@@ -2608,6 +2644,35 @@
"up": "OBEN",
"down": "UNTEN"
}
},
"systemDisks": {
"name": "",
"description": "",
"option": {
"showTemperatureIfAvailable": {
"label": ""
},
"displayMode": {
"label": "",
"option": {
"percentage": {
"label": ""
},
"absolute": {
"label": ""
},
"free": {
"label": ""
}
}
},
"showBackgroundBar": {
"label": ""
}
},
"status": {
"unhealthy": ""
}
}
},
"widgetPreview": {
@@ -3294,6 +3359,13 @@
}
}
},
"user": {
"title": "",
"enableGravatar": {
"label": "",
"description": ""
}
},
"search": {
"title": "Suche",
"defaultSearchEngine": {
+72
View File
@@ -1138,6 +1138,9 @@
"dangerZone": "Επικίνδυνη Περιοχή",
"noResults": "Δεν βρέθηκαν αποτελέσματα",
"unsavedChanges": "",
"servers": "",
"applications": "",
"services": "",
"preview": {
"show": "",
"hide": ""
@@ -1960,6 +1963,39 @@
"internalServerError": ""
}
},
"coolify": {
"name": "",
"description": "",
"option": {
"showServers": {
"label": ""
},
"showApplications": {
"label": ""
},
"showServices": {
"label": ""
}
},
"empty": {
"servers": "",
"applications": "",
"services": ""
},
"footer": {
"updated": ""
},
"error": {
"noIntegration": "",
"internalServerError": ""
},
"server": {
"buildServer": ""
},
"instances": {
"title": ""
}
},
"common": {
"location": {
"query": "",
@@ -2608,6 +2644,35 @@
"up": "",
"down": ""
}
},
"systemDisks": {
"name": "",
"description": "",
"option": {
"showTemperatureIfAvailable": {
"label": ""
},
"displayMode": {
"label": "",
"option": {
"percentage": {
"label": ""
},
"absolute": {
"label": ""
},
"free": {
"label": ""
}
}
},
"showBackgroundBar": {
"label": ""
}
},
"status": {
"unhealthy": ""
}
}
},
"widgetPreview": {
@@ -3294,6 +3359,13 @@
}
}
},
"user": {
"title": "",
"enableGravatar": {
"label": "",
"description": ""
}
},
"search": {
"title": "",
"defaultSearchEngine": {
+175 -103
View File
@@ -836,19 +836,19 @@
"title": "Request error",
"description": {
"connection": {
"hostUnreachable": "",
"networkUnreachable": "",
"refused": "",
"reset": ""
"hostUnreachable": "The server could not be reached. This usually means the host is offline or unreachable from your network.",
"networkUnreachable": "The network is unreachable. Please check your Internet connection or network configuration.",
"refused": "The server refused the connection. It may not be running or is rejecting requests on the specified port.",
"reset": "The connection was unexpectedly closed by the server. This can happen if the server is unstable or restarted."
},
"dns": {
"notFound": "",
"timeout": "",
"noAnswer": ""
"notFound": "The server address could not be found. Please check the URL for typos or invalid domain names.",
"timeout": "DNS lookup timed out. This may be a temporary issue—please try again in a few moments.",
"noAnswer": "The DNS server didn't return a valid response. The domain may exist but has no valid records."
},
"timeout": {
"aborted": "",
"timeout": ""
"aborted": "The request was aborted before it could complete. This might be due to a user action or system timeout.",
"timeout": "The request took too long to complete and was timed out. Check your network or try again later."
}
}
}
@@ -920,8 +920,8 @@
"message": "The path is incorrect. Please double-check the URL"
},
"tooManyRequests": {
"title": "",
"message": ""
"title": "Too many requests in a given time",
"message": "There were too many requests. You are likely being rate-limited or rejected by the target system"
}
}
},
@@ -963,36 +963,36 @@
"newLabel": "New realm"
},
"personalAccessToken": {
"label": "",
"newLabel": ""
"label": "Personal Access Token",
"newLabel": "New Personal Access Token"
},
"topic": {
"label": "",
"newLabel": ""
"label": "Topic",
"newLabel": "New topic"
},
"url": {
"label": "",
"newLabel": ""
"label": "URL",
"newLabel": "New URL"
},
"opnsenseApiKey": {
"label": "",
"newLabel": ""
"label": "API Key (Key)",
"newLabel": "New API Key (Key)"
},
"opnsenseApiSecret": {
"label": "",
"newLabel": ""
"label": "API Key (Secret)",
"newLabel": "New API Key (Secret)"
},
"githubAppId": {
"label": "",
"newLabel": ""
"label": "App Id",
"newLabel": "New App Id"
},
"githubInstallationId": {
"label": "",
"newLabel": ""
"label": "Installation Id",
"newLabel": "New Installation Id"
},
"privateKey": {
"label": "",
"newLabel": ""
"label": "Private key",
"newLabel": "New private key"
}
}
},
@@ -1044,14 +1044,14 @@
}
},
"common": {
"success": "",
"success": "Success",
"beta": "Beta",
"error": "Alpha",
"action": {
"add": "Add",
"apply": "Apply",
"backToOverview": "Back to overview",
"change": "",
"change": "Change",
"create": "Create",
"createAnother": "Create and start over",
"edit": "Edit",
@@ -1063,7 +1063,7 @@
"cancel": "Cancel",
"delete": "Delete",
"discard": "Discard",
"close": "",
"close": "Close",
"confirm": "Confirm",
"continue": "Continue",
"previous": "Previous",
@@ -1138,6 +1138,9 @@
"dangerZone": "Danger zone",
"noResults": "No results have been found",
"unsavedChanges": "You have unsaved changes!",
"servers": "Servers",
"applications": "Apps",
"services": "Services",
"preview": {
"show": "Show a preview",
"hide": "Hide the preview"
@@ -1174,8 +1177,8 @@
},
"unit": {
"speed": {
"kilometersPerHour": "",
"milesPerHour": ""
"kilometersPerHour": "km/h",
"milesPerHour": "mph"
}
}
},
@@ -1190,7 +1193,7 @@
"label": "Title"
},
"customCssClasses": {
"label": ""
"label": "Custom CSS classes"
},
"borderColor": {
"label": "Border colour"
@@ -1223,69 +1226,69 @@
},
"remove": {
"title": "Remove category",
"message": ""
"message": "Are you sure you want to remove the category {name}?"
},
"edit": {
"title": "",
"submit": ""
"title": "Rename category",
"submit": "Rename category"
},
"menu": {
"label": {
"create": "",
"changePosition": ""
"create": "New category",
"changePosition": "Change position"
}
},
"openAllInNewTabs": {
"title": "",
"text": ""
"title": "Open all in tabs",
"text": "Some browsers may block the bulk-opening of tabs for security reasons. Homarr was unable to open all windows, because your browser blocked this action. Please allow \"Open pop-up windows\" and re-try."
}
}
},
"item": {
"action": {
"create": "",
"import": "",
"edit": "",
"moveResize": "",
"duplicate": "",
"remove": ""
"create": "New item",
"import": "Import item",
"edit": "Edit item",
"moveResize": "Move / resize item",
"duplicate": "Duplicate item",
"remove": "Remove item"
},
"menu": {
"label": {
"settings": ""
"settings": "Settings"
}
},
"create": {
"title": "",
"search": "",
"addToBoard": ""
"title": "Choose item to add",
"search": "Filter items",
"addToBoard": "Add to board"
},
"moveResize": {
"title": "",
"title": "Move / resize item",
"field": {
"width": {
"label": ""
"label": "Width"
},
"height": {
"label": ""
"label": "Height"
},
"xOffset": {
"label": ""
"label": "X offset"
},
"yOffset": {
"label": ""
"label": "Y offset"
}
}
},
"edit": {
"title": "",
"title": "Edit item",
"advancedOptions": {
"label": "",
"title": ""
"label": "Advanced options",
"title": "Advanced item options"
},
"field": {
"integrations": {
"label": ""
"label": "Integrations"
},
"title": {
"label": ""
@@ -1424,46 +1427,46 @@
},
"dnsHoleControls": {
"name": "",
"description": "",
"description": "Control PiHole or AdGuard from your dashboard",
"option": {
"layout": {
"label": "",
"label": "Layout",
"option": {
"row": {
"label": ""
"label": "Horizontal"
},
"column": {
"label": ""
"label": "Vertical"
},
"grid": {
"label": ""
"label": "Grid"
}
}
},
"showToggleAllButtons": {
"label": ""
"label": "Show Toggle All Buttons"
}
},
"error": {
"internalServerError": ""
"internalServerError": "Failed to control DNS Hole"
},
"controls": {
"enableAll": "",
"disableAll": "",
"setTimer": "",
"set": "",
"enabled": "",
"disabled": "",
"processing": "",
"disconnected": "",
"hours": "",
"minutes": "",
"unlimited": ""
"enableAll": "Enable All",
"disableAll": "Disable All",
"setTimer": "Set Timer",
"set": "Set",
"enabled": "Enabled",
"disabled": "Disabled",
"processing": "Processing",
"disconnected": "Disconnected",
"hours": "Hours",
"minutes": "Minutes",
"unlimited": "Leave blank to unlimited"
}
},
"clock": {
"name": "",
"description": "",
"name": "Date and time",
"description": "Displays the current date and time.",
"option": {
"customTitleToggle": {
"label": "",
@@ -1960,6 +1963,39 @@
"internalServerError": ""
}
},
"coolify": {
"name": "",
"description": "",
"option": {
"showServers": {
"label": ""
},
"showApplications": {
"label": ""
},
"showServices": {
"label": ""
}
},
"empty": {
"servers": "",
"applications": "",
"services": ""
},
"footer": {
"updated": ""
},
"error": {
"noIntegration": "",
"internalServerError": ""
},
"server": {
"buildServer": ""
},
"instances": {
"title": ""
}
},
"common": {
"location": {
"query": "",
@@ -2608,6 +2644,35 @@
"up": "",
"down": ""
}
},
"systemDisks": {
"name": "",
"description": "",
"option": {
"showTemperatureIfAvailable": {
"label": ""
},
"displayMode": {
"label": "",
"option": {
"percentage": {
"label": ""
},
"absolute": {
"label": ""
},
"free": {
"label": ""
}
}
},
"showBackgroundBar": {
"label": ""
}
},
"status": {
"unhealthy": ""
}
}
},
"widgetPreview": {
@@ -3294,6 +3359,13 @@
}
}
},
"user": {
"title": "",
"enableGravatar": {
"label": "",
"description": ""
}
},
"search": {
"title": "",
"defaultSearchEngine": {
@@ -4403,12 +4475,12 @@
"message": "",
"notification": {
"success": {
"title": "",
"message": ""
"title": "Search engine deleted",
"message": "The search engine was deleted successfully"
},
"error": {
"title": "",
"message": ""
"title": "Search engine not deleted",
"message": "The search engine could not be deleted"
}
}
}
@@ -4416,15 +4488,15 @@
"media": {
"request": {
"modal": {
"title": "",
"title": "Request \"{name}\"",
"table": {
"header": {
"season": "",
"episodes": ""
"season": "Season",
"episodes": "Episodes"
}
},
"button": {
"send": ""
"send": "Send request"
}
}
}
@@ -4434,44 +4506,44 @@
"certificate": {
"field": {
"hostname": {
"label": ""
"label": "Hostname"
},
"subject": {
"label": ""
"label": "Subject"
},
"issuer": {
"label": ""
"label": "Issuer"
},
"validFrom": {
"label": ""
"label": "Valid from"
},
"validTo": {
"label": ""
"label": "Valid to"
},
"serialNumber": {
"label": ""
"label": "Serial number"
},
"fingerprint": {
"label": ""
"label": "Fingerprint"
}
},
"page": {
"list": {
"title": "",
"description": "",
"title": "Trusted certificates",
"description": "Used by Homarr to request data from integrations.",
"noResults": {
"title": ""
"title": "There are no certificates yet"
},
"invalid": {
"title": "",
"description": ""
"title": "Invalid certificate",
"description": "Failed to parse certificate"
},
"expires": "",
"toHostnames": ""
"expires": "Expires {when}",
"toHostnames": "Trusted hostnames"
},
"hostnames": {
"title": "",
"description": "",
"title": "Trusted certificate hostnames",
"description": "Some certificates do not allow the specific domain Homarr uses to request them, because of this all trusted hostnames with their certificate thumbprints are used to bypass these restrictions.",
"noResults": {
"title": "There are no hostnames yet"
},
+66 -1
View File
@@ -1138,6 +1138,9 @@
"dangerZone": "Danger zone",
"noResults": "No results found",
"unsavedChanges": "You have unsaved changes!",
"servers": "Servers",
"applications": "Apps",
"services": "Services",
"preview": {
"show": "Show preview",
"hide": "Hide preview"
@@ -1960,6 +1963,39 @@
"internalServerError": "Failed to fetch containers stats"
}
},
"coolify": {
"name": "Coolify",
"description": "Overview of your Coolify instance with servers and applications",
"option": {
"showServers": {
"label": "Show servers"
},
"showApplications": {
"label": "Show applications"
},
"showServices": {
"label": "Show services"
}
},
"empty": {
"servers": "No servers found",
"applications": "No applications found",
"services": "No services found"
},
"footer": {
"updated": "Updated {when}"
},
"error": {
"noIntegration": "No Coolify integration configured",
"internalServerError": "Failed to fetch Coolify data"
},
"server": {
"buildServer": "Build"
},
"instances": {
"title": "Instances"
}
},
"common": {
"location": {
"query": "City / Postal code",
@@ -2608,6 +2644,35 @@
"up": "UP",
"down": "DOWN"
}
},
"systemDisks": {
"name": "System disks",
"description": "Disk usage of your system",
"option": {
"showTemperatureIfAvailable": {
"label": "Show temperature if available"
},
"displayMode": {
"label": "Display mode",
"option": {
"percentage": {
"label": "Percentage (e.g., 76%)"
},
"absolute": {
"label": "Absolute values (e.g., 800GB / 1TB)"
},
"free": {
"label": "Free space percentage (e.g., 24% free)"
}
}
},
"showBackgroundBar": {
"label": "Show background usage bar"
}
},
"status": {
"unhealthy": "Unhealthy"
}
}
},
"widgetPreview": {
@@ -3240,7 +3305,7 @@
"title": "Analytics",
"general": {
"title": "Send anonymous analytics",
"text": "Homarr will send anonymized analytics using the open source software Umami. It never collects any personal information and is therefore fully GDPR & CCPA compliant. We encourage you to enable analytics because it helps our open source team to identify issues and prioritize our backlog."
"text": "Homarr will send anonymized analytics using the open source software Umami. When enabled, we collect: Homarr version, database type (MySQL/PostgreSQL/SQLite), Docker/Kubernetes status, authentication methods enabled, and the number of each feature. All data is anonymous and aggregated - no personal information, URLs, names, or identifiable data is ever collected. This helps our open source team understand usage patterns and prioritize development."
},
"widgetData": {
"title": "Widget data",
+72
View File
@@ -1138,6 +1138,9 @@
"dangerZone": "Zona de riesgo",
"noResults": "No se han encontrado resultados",
"unsavedChanges": "¡Tienes cambios sin guardar!",
"servers": "Servidores",
"applications": "Aplicaciones",
"services": "Servicios",
"preview": {
"show": "Mostrar vista previa",
"hide": "Ocultar vista previa"
@@ -1960,6 +1963,39 @@
"internalServerError": "No se pudo obtener las estadísticas de los contenedores"
}
},
"coolify": {
"name": "Coolify",
"description": "Resumen de su instancia de Coolify con servidores y aplicaciones",
"option": {
"showServers": {
"label": "Mostrar servidores"
},
"showApplications": {
"label": "Mostrar aplicaciones"
},
"showServices": {
"label": "Mostrar servicios"
}
},
"empty": {
"servers": "No se encontraron servidores",
"applications": "No se encontraron aplicaciones",
"services": "No se encontraron servicios"
},
"footer": {
"updated": "Actualizado {when}"
},
"error": {
"noIntegration": "No hay integración de Coolify configurada",
"internalServerError": "No se pudieron obtener los datos de Coolify"
},
"server": {
"buildServer": "Construir"
},
"instances": {
"title": "Instancias"
}
},
"common": {
"location": {
"query": "Ciudad / Código postal",
@@ -2608,6 +2644,35 @@
"up": "ENCENDIDO",
"down": "APAGADO"
}
},
"systemDisks": {
"name": "Discos del sistema",
"description": "Uso del disco de su sistema",
"option": {
"showTemperatureIfAvailable": {
"label": "Mostrar la temperatura si está disponible"
},
"displayMode": {
"label": "Modo de visualización",
"option": {
"percentage": {
"label": "Porcentaje (e.g., 76 %)"
},
"absolute": {
"label": "Valores absolutos (e.g., 800 GB / 1 TB)"
},
"free": {
"label": "Porcentaje de espacio libre (e.g., 24 % libre)"
}
}
},
"showBackgroundBar": {
"label": "Mostrar la barra de uso en segundo plano"
}
},
"status": {
"unhealthy": "Poco sano"
}
}
},
"widgetPreview": {
@@ -3294,6 +3359,13 @@
}
}
},
"user": {
"title": "Usuarios",
"enableGravatar": {
"label": "Habilitar Gravatar",
"description": "Recupera los avatares de usuario de Libravatar/Gravatar cuando no hay ningún avatar personalizado y se configura un correo electrónico"
}
},
"search": {
"title": "Buscar",
"defaultSearchEngine": {
+72
View File
@@ -1138,6 +1138,9 @@
"dangerZone": "",
"noResults": "",
"unsavedChanges": "",
"servers": "",
"applications": "",
"services": "",
"preview": {
"show": "",
"hide": ""
@@ -1960,6 +1963,39 @@
"internalServerError": ""
}
},
"coolify": {
"name": "",
"description": "",
"option": {
"showServers": {
"label": ""
},
"showApplications": {
"label": ""
},
"showServices": {
"label": ""
}
},
"empty": {
"servers": "",
"applications": "",
"services": ""
},
"footer": {
"updated": ""
},
"error": {
"noIntegration": "",
"internalServerError": ""
},
"server": {
"buildServer": ""
},
"instances": {
"title": ""
}
},
"common": {
"location": {
"query": "",
@@ -2608,6 +2644,35 @@
"up": "",
"down": ""
}
},
"systemDisks": {
"name": "",
"description": "",
"option": {
"showTemperatureIfAvailable": {
"label": ""
},
"displayMode": {
"label": "",
"option": {
"percentage": {
"label": ""
},
"absolute": {
"label": ""
},
"free": {
"label": ""
}
}
},
"showBackgroundBar": {
"label": ""
}
},
"status": {
"unhealthy": ""
}
}
},
"widgetPreview": {
@@ -3294,6 +3359,13 @@
}
}
},
"user": {
"title": "",
"enableGravatar": {
"label": "",
"description": ""
}
},
"search": {
"title": "",
"defaultSearchEngine": {
+73 -1
View File
@@ -2,7 +2,7 @@
"init": {
"step": {
"start": {
"title": "Bienvenue dans Homarr",
"title": "Bienvenue sur Homarr",
"subtitle": "Commençons par configurer votre instance Homarr.",
"description": "Pour commencer, veuillez selectionner comment vous souhaitez configurer votre instance Homarr.",
"action": {
@@ -1138,6 +1138,9 @@
"dangerZone": "Zone de danger",
"noResults": "Aucun résultat trouvé",
"unsavedChanges": "Vous avez des modifications non enregistrées !",
"servers": "Serveurs",
"applications": "Applications",
"services": "Services",
"preview": {
"show": "Afficher l’aperçu",
"hide": "Masquer l'aperçu"
@@ -1960,6 +1963,39 @@
"internalServerError": "Impossible de récupérer les statistiques des conteneurs"
}
},
"coolify": {
"name": "Coolify",
"description": "Aperçu de votre instance Coolify avec les serveurs et les applications",
"option": {
"showServers": {
"label": "Afficher les serveurs"
},
"showApplications": {
"label": "Afficher les applications"
},
"showServices": {
"label": "Afficher les services"
}
},
"empty": {
"servers": "Aucun serveur trouvé",
"applications": "Aucune application trouvée",
"services": "Aucun service trouvé"
},
"footer": {
"updated": "Mis à jour {when}"
},
"error": {
"noIntegration": "Aucune intégration de Coolify configurée",
"internalServerError": "Impossible de récupérer les données de Coolify"
},
"server": {
"buildServer": "Version"
},
"instances": {
"title": "Instances"
}
},
"common": {
"location": {
"query": "Ville / Code Postal",
@@ -2608,6 +2644,35 @@
"up": "UP",
"down": "HORS SERVICE"
}
},
"systemDisks": {
"name": "Disques système",
"description": "Utilisation du disque de votre système",
"option": {
"showTemperatureIfAvailable": {
"label": "Afficher la température si disponible"
},
"displayMode": {
"label": "Mode d'affichage",
"option": {
"percentage": {
"label": "Pourcentage (ex : 70%)"
},
"absolute": {
"label": "Valeurs absolues (ex. : 800 Go / 1 To)"
},
"free": {
"label": "Pourcentage d'espace libre (ex. : 24 % libre)"
}
}
},
"showBackgroundBar": {
"label": "Afficher la barre d'utilisation en arrière-plan"
}
},
"status": {
"unhealthy": "Dysfonctionnement"
}
}
},
"widgetPreview": {
@@ -3294,6 +3359,13 @@
}
}
},
"user": {
"title": "Utilisateurs",
"enableGravatar": {
"label": "Activer Gravatar",
"description": "Revient aux avatars des utilisateurs de Libravatar/Gravatar quand aucun avatar personnalisé n'est défini et qu'un e-mail est configuré"
}
},
"search": {
"title": "Rechercher",
"defaultSearchEngine": {
+72
View File
@@ -1138,6 +1138,9 @@
"dangerZone": "אזור מסוכן",
"noResults": "לא נמצאו תוצאות",
"unsavedChanges": "ישנם שינויים שלא נשמרו!",
"servers": "שרתים",
"applications": "",
"services": "",
"preview": {
"show": "הצג תצוגה מקדימה",
"hide": "הסתר תצוגה המקדימה"
@@ -1960,6 +1963,39 @@
"internalServerError": "נכשל באחזור סטטיסטיקות המכולות"
}
},
"coolify": {
"name": "",
"description": "",
"option": {
"showServers": {
"label": ""
},
"showApplications": {
"label": ""
},
"showServices": {
"label": ""
}
},
"empty": {
"servers": "",
"applications": "",
"services": ""
},
"footer": {
"updated": ""
},
"error": {
"noIntegration": "",
"internalServerError": ""
},
"server": {
"buildServer": ""
},
"instances": {
"title": ""
}
},
"common": {
"location": {
"query": "עיר / מיקוד",
@@ -2608,6 +2644,35 @@
"up": "העלאה",
"down": "הורדה"
}
},
"systemDisks": {
"name": "",
"description": "",
"option": {
"showTemperatureIfAvailable": {
"label": ""
},
"displayMode": {
"label": "",
"option": {
"percentage": {
"label": ""
},
"absolute": {
"label": ""
},
"free": {
"label": ""
}
}
},
"showBackgroundBar": {
"label": ""
}
},
"status": {
"unhealthy": ""
}
}
},
"widgetPreview": {
@@ -3294,6 +3359,13 @@
}
}
},
"user": {
"title": "משתמשים",
"enableGravatar": {
"label": "",
"description": ""
}
},
"search": {
"title": "חיפוש",
"defaultSearchEngine": {
+72
View File
@@ -1138,6 +1138,9 @@
"dangerZone": "Opasna zona",
"noResults": "Nije pronađen nijedan rezultat",
"unsavedChanges": "",
"servers": "",
"applications": "",
"services": "",
"preview": {
"show": "",
"hide": ""
@@ -1960,6 +1963,39 @@
"internalServerError": ""
}
},
"coolify": {
"name": "",
"description": "",
"option": {
"showServers": {
"label": ""
},
"showApplications": {
"label": ""
},
"showServices": {
"label": ""
}
},
"empty": {
"servers": "",
"applications": "",
"services": ""
},
"footer": {
"updated": ""
},
"error": {
"noIntegration": "",
"internalServerError": ""
},
"server": {
"buildServer": ""
},
"instances": {
"title": ""
}
},
"common": {
"location": {
"query": "",
@@ -2608,6 +2644,35 @@
"up": "",
"down": ""
}
},
"systemDisks": {
"name": "",
"description": "",
"option": {
"showTemperatureIfAvailable": {
"label": ""
},
"displayMode": {
"label": "",
"option": {
"percentage": {
"label": ""
},
"absolute": {
"label": ""
},
"free": {
"label": ""
}
}
},
"showBackgroundBar": {
"label": ""
}
},
"status": {
"unhealthy": ""
}
}
},
"widgetPreview": {
@@ -3294,6 +3359,13 @@
}
}
},
"user": {
"title": "",
"enableGravatar": {
"label": "",
"description": ""
}
},
"search": {
"title": "",
"defaultSearchEngine": {
+72
View File
@@ -1138,6 +1138,9 @@
"dangerZone": "Veszélyzóna",
"noResults": "Nincs eredmény",
"unsavedChanges": "",
"servers": "",
"applications": "",
"services": "",
"preview": {
"show": "",
"hide": ""
@@ -1960,6 +1963,39 @@
"internalServerError": ""
}
},
"coolify": {
"name": "",
"description": "",
"option": {
"showServers": {
"label": ""
},
"showApplications": {
"label": ""
},
"showServices": {
"label": ""
}
},
"empty": {
"servers": "",
"applications": "",
"services": ""
},
"footer": {
"updated": ""
},
"error": {
"noIntegration": "",
"internalServerError": ""
},
"server": {
"buildServer": ""
},
"instances": {
"title": ""
}
},
"common": {
"location": {
"query": "",
@@ -2608,6 +2644,35 @@
"up": "",
"down": ""
}
},
"systemDisks": {
"name": "",
"description": "",
"option": {
"showTemperatureIfAvailable": {
"label": ""
},
"displayMode": {
"label": "",
"option": {
"percentage": {
"label": ""
},
"absolute": {
"label": ""
},
"free": {
"label": ""
}
}
},
"showBackgroundBar": {
"label": ""
}
},
"status": {
"unhealthy": ""
}
}
},
"widgetPreview": {
@@ -3294,6 +3359,13 @@
}
}
},
"user": {
"title": "",
"enableGravatar": {
"label": "",
"description": ""
}
},
"search": {
"title": "",
"defaultSearchEngine": {
+72
View File
@@ -1138,6 +1138,9 @@
"dangerZone": "Zona pericolosa",
"noResults": "Nessun risultato trovato",
"unsavedChanges": "Ci sono modifiche non salvate!",
"servers": "Server",
"applications": "App",
"services": "Servizi",
"preview": {
"show": "Mostra anteprima",
"hide": "Nascondi anteprima"
@@ -1960,6 +1963,39 @@
"internalServerError": "Recupero statistiche container non riuscito"
}
},
"coolify": {
"name": "Coolify",
"description": "Panoramica della tua istanza Coolify con server e applicazioni",
"option": {
"showServers": {
"label": "Mostra server"
},
"showApplications": {
"label": "Mostra applicazioni"
},
"showServices": {
"label": "Mostra servizi"
}
},
"empty": {
"servers": "Nessun server trovato",
"applications": "Nessuna applicazione trovata",
"services": "Nessun servizio trovato"
},
"footer": {
"updated": "Aggiornato {when}"
},
"error": {
"noIntegration": "Nessuna integrazione di Coolify configurata",
"internalServerError": "Impossibile recuperare i dati Coolify"
},
"server": {
"buildServer": "Build"
},
"instances": {
"title": "Istanze"
}
},
"common": {
"location": {
"query": "Città / Codice postale",
@@ -2608,6 +2644,35 @@
"up": "SU",
"down": "DOWN"
}
},
"systemDisks": {
"name": "Dischi di sistema",
"description": "Uso del disco del sistema",
"option": {
"showTemperatureIfAvailable": {
"label": "Mostra temperatura se disponibile"
},
"displayMode": {
"label": "Modalità di visualizzazione",
"option": {
"percentage": {
"label": "Percentuale (es. 76%)"
},
"absolute": {
"label": "Valori assoluti (ad es. 800GB / 1TB)"
},
"free": {
"label": "Percentuale di spazio libero (ad es. 24% libero)"
}
}
},
"showBackgroundBar": {
"label": "Mostra barra di utilizzo in background"
}
},
"status": {
"unhealthy": "Compromesso"
}
}
},
"widgetPreview": {
@@ -3294,6 +3359,13 @@
}
}
},
"user": {
"title": "Utenti",
"enableGravatar": {
"label": "Abilita Gravatar",
"description": "Torna agli avatar degli utenti da Libravatar/Gravatar quando non è impostato alcun avatar personalizzato e viene configurata un'email"
}
},
"search": {
"title": "Cerca",
"defaultSearchEngine": {
+80 -8
View File
@@ -1138,6 +1138,9 @@
"dangerZone": "危険な操作",
"noResults": "結果が見つかりません",
"unsavedChanges": "保存していない変更があります!",
"servers": "",
"applications": "",
"services": "",
"preview": {
"show": "プレビューを表示",
"hide": "プレビューを閉じる"
@@ -1941,25 +1944,58 @@
"description": "あなたのコンテナの統計(このウィジェットは管理者権限でのみ追加できます)",
"option": {
"enableRowSorting": {
"label": ""
"label": "アイテムの並び替えを有効にする"
},
"defaultSort": {
"label": "",
"label": "デフォルトで並び替えに使用される列",
"option": {
"name": "",
"state": "",
"cpuUsage": "",
"memoryUsage": ""
"name": "名称",
"state": "状態",
"cpuUsage": "CPU 使用率",
"memoryUsage": "メモリ使用量"
}
},
"descendingDefaultSort": {
"label": ""
"label": "並び替えを反転"
}
},
"error": {
"internalServerError": "コンテナステータスの取得に失敗しました"
}
},
"coolify": {
"name": "",
"description": "",
"option": {
"showServers": {
"label": ""
},
"showApplications": {
"label": ""
},
"showServices": {
"label": ""
}
},
"empty": {
"servers": "",
"applications": "",
"services": ""
},
"footer": {
"updated": ""
},
"error": {
"noIntegration": "",
"internalServerError": ""
},
"server": {
"buildServer": ""
},
"instances": {
"title": ""
}
},
"common": {
"location": {
"query": "都市/郵便番号",
@@ -2248,7 +2284,7 @@
"unknown": "不明",
"pending": "保留中",
"processing": "処理中",
"requested": "",
"requested": "要求済み",
"partiallyAvailable": "一部",
"available": "利用可能",
"blacklisted": "ブラックリスト",
@@ -2608,6 +2644,35 @@
"up": "UP",
"down": "DOWN"
}
},
"systemDisks": {
"name": "",
"description": "",
"option": {
"showTemperatureIfAvailable": {
"label": ""
},
"displayMode": {
"label": "",
"option": {
"percentage": {
"label": ""
},
"absolute": {
"label": ""
},
"free": {
"label": ""
}
}
},
"showBackgroundBar": {
"label": ""
}
},
"status": {
"unhealthy": ""
}
}
},
"widgetPreview": {
@@ -3294,6 +3359,13 @@
}
}
},
"user": {
"title": "ユーザー",
"enableGravatar": {
"label": "Gravatar を有効化",
"description": "カスタムアバターが設定されておらず、メールが設定されている場合は、Libavatar/Gravatarからユーザーのアバターにフォールバックします"
}
},
"search": {
"title": "検索",
"defaultSearchEngine": {
+72
View File
@@ -1138,6 +1138,9 @@
"dangerZone": "위험한 설정",
"noResults": "결과를 찾을 수 없습니다.",
"unsavedChanges": "",
"servers": "",
"applications": "",
"services": "",
"preview": {
"show": "",
"hide": ""
@@ -1960,6 +1963,39 @@
"internalServerError": ""
}
},
"coolify": {
"name": "",
"description": "",
"option": {
"showServers": {
"label": ""
},
"showApplications": {
"label": ""
},
"showServices": {
"label": ""
}
},
"empty": {
"servers": "",
"applications": "",
"services": ""
},
"footer": {
"updated": ""
},
"error": {
"noIntegration": "",
"internalServerError": ""
},
"server": {
"buildServer": ""
},
"instances": {
"title": ""
}
},
"common": {
"location": {
"query": "",
@@ -2608,6 +2644,35 @@
"up": "",
"down": ""
}
},
"systemDisks": {
"name": "",
"description": "",
"option": {
"showTemperatureIfAvailable": {
"label": ""
},
"displayMode": {
"label": "",
"option": {
"percentage": {
"label": ""
},
"absolute": {
"label": ""
},
"free": {
"label": ""
}
}
},
"showBackgroundBar": {
"label": ""
}
},
"status": {
"unhealthy": ""
}
}
},
"widgetPreview": {
@@ -3294,6 +3359,13 @@
}
}
},
"user": {
"title": "",
"enableGravatar": {
"label": "",
"description": ""
}
},
"search": {
"title": "",
"defaultSearchEngine": {
+72
View File
@@ -1138,6 +1138,9 @@
"dangerZone": "",
"noResults": "Rezultatų nerasta",
"unsavedChanges": "",
"servers": "",
"applications": "",
"services": "",
"preview": {
"show": "",
"hide": ""
@@ -1960,6 +1963,39 @@
"internalServerError": ""
}
},
"coolify": {
"name": "",
"description": "",
"option": {
"showServers": {
"label": ""
},
"showApplications": {
"label": ""
},
"showServices": {
"label": ""
}
},
"empty": {
"servers": "",
"applications": "",
"services": ""
},
"footer": {
"updated": ""
},
"error": {
"noIntegration": "",
"internalServerError": ""
},
"server": {
"buildServer": ""
},
"instances": {
"title": ""
}
},
"common": {
"location": {
"query": "",
@@ -2608,6 +2644,35 @@
"up": "",
"down": ""
}
},
"systemDisks": {
"name": "",
"description": "",
"option": {
"showTemperatureIfAvailable": {
"label": ""
},
"displayMode": {
"label": "",
"option": {
"percentage": {
"label": ""
},
"absolute": {
"label": ""
},
"free": {
"label": ""
}
}
},
"showBackgroundBar": {
"label": ""
}
},
"status": {
"unhealthy": ""
}
}
},
"widgetPreview": {
@@ -3294,6 +3359,13 @@
}
}
},
"user": {
"title": "",
"enableGravatar": {
"label": "",
"description": ""
}
},
"search": {
"title": "",
"defaultSearchEngine": {
+72
View File
@@ -1138,6 +1138,9 @@
"dangerZone": "Bīstamā zona",
"noResults": "Nav atrasts neviens rezultāts",
"unsavedChanges": "",
"servers": "",
"applications": "",
"services": "",
"preview": {
"show": "",
"hide": ""
@@ -1960,6 +1963,39 @@
"internalServerError": ""
}
},
"coolify": {
"name": "",
"description": "",
"option": {
"showServers": {
"label": ""
},
"showApplications": {
"label": ""
},
"showServices": {
"label": ""
}
},
"empty": {
"servers": "",
"applications": "",
"services": ""
},
"footer": {
"updated": ""
},
"error": {
"noIntegration": "",
"internalServerError": ""
},
"server": {
"buildServer": ""
},
"instances": {
"title": ""
}
},
"common": {
"location": {
"query": "",
@@ -2608,6 +2644,35 @@
"up": "",
"down": ""
}
},
"systemDisks": {
"name": "",
"description": "",
"option": {
"showTemperatureIfAvailable": {
"label": ""
},
"displayMode": {
"label": "",
"option": {
"percentage": {
"label": ""
},
"absolute": {
"label": ""
},
"free": {
"label": ""
}
}
},
"showBackgroundBar": {
"label": ""
}
},
"status": {
"unhealthy": ""
}
}
},
"widgetPreview": {
@@ -3294,6 +3359,13 @@
}
}
},
"user": {
"title": "",
"enableGravatar": {
"label": "",
"description": ""
}
},
"search": {
"title": "",
"defaultSearchEngine": {
+72
View File
@@ -1138,6 +1138,9 @@
"dangerZone": "Gevarenzone",
"noResults": "Geen resultaten gevonden",
"unsavedChanges": "Er zijn niet-opgeslagen wijzigingen!",
"servers": "",
"applications": "",
"services": "",
"preview": {
"show": "Voorbeeld weergeven",
"hide": "Voorbeeld verbergen"
@@ -1960,6 +1963,39 @@
"internalServerError": ""
}
},
"coolify": {
"name": "",
"description": "",
"option": {
"showServers": {
"label": ""
},
"showApplications": {
"label": ""
},
"showServices": {
"label": ""
}
},
"empty": {
"servers": "",
"applications": "",
"services": ""
},
"footer": {
"updated": ""
},
"error": {
"noIntegration": "",
"internalServerError": ""
},
"server": {
"buildServer": ""
},
"instances": {
"title": ""
}
},
"common": {
"location": {
"query": "Stad / postcode",
@@ -2608,6 +2644,35 @@
"up": "OMHOOG",
"down": "OMLAAG"
}
},
"systemDisks": {
"name": "",
"description": "",
"option": {
"showTemperatureIfAvailable": {
"label": ""
},
"displayMode": {
"label": "",
"option": {
"percentage": {
"label": ""
},
"absolute": {
"label": ""
},
"free": {
"label": ""
}
}
},
"showBackgroundBar": {
"label": ""
}
},
"status": {
"unhealthy": ""
}
}
},
"widgetPreview": {
@@ -3294,6 +3359,13 @@
}
}
},
"user": {
"title": "",
"enableGravatar": {
"label": "",
"description": ""
}
},
"search": {
"title": "Zoeken",
"defaultSearchEngine": {
+73 -1
View File
@@ -1138,6 +1138,9 @@
"dangerZone": "Faresonen",
"noResults": "Ingen resultater funnet",
"unsavedChanges": "Du har ulagrede endringer!",
"servers": "Servere",
"applications": "Apper",
"services": "Tjenester",
"preview": {
"show": "Vis forhåndsvisning",
"hide": "Skjul forhåndsvisning"
@@ -1960,6 +1963,39 @@
"internalServerError": "Kunne ikke hente containerstatistikk"
}
},
"coolify": {
"name": "Coolify",
"description": "Oversikt over din Coolify-instans med servere og apper",
"option": {
"showServers": {
"label": "Vis servere"
},
"showApplications": {
"label": "Vis applikasjoner"
},
"showServices": {
"label": "Vis tjenester"
}
},
"empty": {
"servers": "Ingen server funnet",
"applications": "Ingen applikasjoner funnet",
"services": "Ingen tjenester funnet"
},
"footer": {
"updated": "Oppdatert {when}"
},
"error": {
"noIntegration": "Ingen Coolify integrasjon konfigurert",
"internalServerError": "Kunne ikke hente Coolify data"
},
"server": {
"buildServer": "Bygg"
},
"instances": {
"title": "Instanser"
}
},
"common": {
"location": {
"query": "By / Postnummer",
@@ -2608,6 +2644,35 @@
"up": "OPP",
"down": "NED"
}
},
"systemDisks": {
"name": "Systemdisker",
"description": "Disk bruk av systemet",
"option": {
"showTemperatureIfAvailable": {
"label": "Vis temperatur hvis tilgjengelig"
},
"displayMode": {
"label": "Visningsmodus",
"option": {
"percentage": {
"label": "Prosentandel (f.eks. 76%)"
},
"absolute": {
"label": "Absolutte verdier (f.eks. 800GB / 1TB)"
},
"free": {
"label": "Prosentandel ledig plass (f.eks. 24% ledig)"
}
}
},
"showBackgroundBar": {
"label": "Vis bakgrunnsbrukslinje"
}
},
"status": {
"unhealthy": "Usunn"
}
}
},
"widgetPreview": {
@@ -3240,7 +3305,7 @@
"title": "Statistikk",
"general": {
"title": "Send anonym brukerdata",
"text": "Homarr vil sende anonymt brukerdata med åpen kildekode programvaren Umami. Det vil aldri samle inn personlig informasjon og følger derfor GDPR & CCPA fullstendig. Vi oppfordrer deg til å aktivere sending av brukerdata da det hjelper teamet vårt å identifisere problemer og sette prioritering."
"text": "Homarr vil sende anonymiserte analyser ved bruk av den åpne programvaren Umami. Når dette er aktivert, samler vi inn: Homarr-versjon, databastype (MySQL/PostgreSQL/SQLite), Docker/Kubernetes-status, aktiverte autentiseringsmetoder, og antallet av hver funksjon. Alle data er anonyme og aggregerte – ingen personlig informasjon, URL-er, navn eller identifiserbare data samles inn. Dette hjelper vårt open source-team med å forstå bruks‑mønstre og prioritere utvikling."
},
"widgetData": {
"title": "Widget data",
@@ -3294,6 +3359,13 @@
}
}
},
"user": {
"title": "Brukere",
"enableGravatar": {
"label": "Aktiver Gravatar",
"description": "Bruker avatarer fra Libravatar/Gravatar som reserve når ingen egendefinert avatar er angitt og en e-post er konfigurert"
}
},
"search": {
"title": "Søk",
"defaultSearchEngine": {
+72
View File
@@ -1138,6 +1138,9 @@
"dangerZone": "Strefa zagrożenia",
"noResults": "Nie znaleziono żadnych wyników",
"unsavedChanges": "Masz niezapisane zmiany!",
"servers": "",
"applications": "",
"services": "",
"preview": {
"show": "Pokaż podgląd",
"hide": "Ukryj podgląd"
@@ -1960,6 +1963,39 @@
"internalServerError": "Nie udało się pobrać statystyk kontenerów"
}
},
"coolify": {
"name": "",
"description": "",
"option": {
"showServers": {
"label": ""
},
"showApplications": {
"label": ""
},
"showServices": {
"label": ""
}
},
"empty": {
"servers": "",
"applications": "",
"services": ""
},
"footer": {
"updated": ""
},
"error": {
"noIntegration": "",
"internalServerError": ""
},
"server": {
"buildServer": ""
},
"instances": {
"title": ""
}
},
"common": {
"location": {
"query": "Miasto / kod pocztowy",
@@ -2608,6 +2644,35 @@
"up": "Aktywny",
"down": "Nieaktywny"
}
},
"systemDisks": {
"name": "",
"description": "",
"option": {
"showTemperatureIfAvailable": {
"label": ""
},
"displayMode": {
"label": "",
"option": {
"percentage": {
"label": ""
},
"absolute": {
"label": ""
},
"free": {
"label": ""
}
}
},
"showBackgroundBar": {
"label": ""
}
},
"status": {
"unhealthy": ""
}
}
},
"widgetPreview": {
@@ -3294,6 +3359,13 @@
}
}
},
"user": {
"title": "",
"enableGravatar": {
"label": "",
"description": ""
}
},
"search": {
"title": "Szukaj",
"defaultSearchEngine": {
File diff suppressed because it is too large. Load diff
+72
View File
@@ -1138,6 +1138,9 @@
"dangerZone": "Zonă periculoasă",
"noResults": "Nici un rezultat găsit",
"unsavedChanges": "",
"servers": "",
"applications": "",
"services": "",
"preview": {
"show": "",
"hide": ""
@@ -1960,6 +1963,39 @@
"internalServerError": ""
}
},
"coolify": {
"name": "",
"description": "",
"option": {
"showServers": {
"label": ""
},
"showApplications": {
"label": ""
},
"showServices": {
"label": ""
}
},
"empty": {
"servers": "",
"applications": "",
"services": ""
},
"footer": {
"updated": ""
},
"error": {
"noIntegration": "",
"internalServerError": ""
},
"server": {
"buildServer": ""
},
"instances": {
"title": ""
}
},
"common": {
"location": {
"query": "",
@@ -2608,6 +2644,35 @@
"up": "",
"down": ""
}
},
"systemDisks": {
"name": "",
"description": "",
"option": {
"showTemperatureIfAvailable": {
"label": ""
},
"displayMode": {
"label": "",
"option": {
"percentage": {
"label": ""
},
"absolute": {
"label": ""
},
"free": {
"label": ""
}
}
},
"showBackgroundBar": {
"label": ""
}
},
"status": {
"unhealthy": ""
}
}
},
"widgetPreview": {
@@ -3294,6 +3359,13 @@
}
}
},
"user": {
"title": "",
"enableGravatar": {
"label": "",
"description": ""
}
},
"search": {
"title": "",
"defaultSearchEngine": {
File diff suppressed because it is too large. Load diff
Loaded 100 of 131 files, more files were not shown because too many files have changed in this diff. Show more