Compare commits

..
Author SHA1 Message Date
Thomas Camlong e0dc782c9e ci: bump typecheck timeout to 15 minutes
Setup phase (ssh2 native build) eats ~5min, leaving insufficient time
for typecheck across 37 packages within the 10min limit.
2026-07-03 16:34:05 +02:00
Thomas Camlong 8b38c83cc0 merge: origin/dev (immich v3, release-providers cleanup)
Take dev's cleaner fetchProvider typing and repositoryId extraction.
No architectural changes — our simplified caching patterns preserved.
2026-07-03 16:01:22 +02:00
Thomas a5ec880eec fix(immich): v3 API compatibility — use searchAssets for album assets, drop deviceAssetId (#5977) 2026-07-03 15:59:08 +02:00
homarr-update-contributors[bot] b588672709 chore: update contributors (#6167)
Co-authored-by: Homarr Update Contributors <210161987+homarr-update-contributors[bot]@users.noreply.github.com>
2026-07-03 13:58:25 +00:00
Thomas Camlong 9c829679f5 ci: remove memory-regression job from code-quality workflow 2026-07-03 10:32:51 +02:00
Thomas Camlong 16f82fcc6f fix: address PR review findings
- Strip integration secrets from server cache keys (security)
- Add max size + TTL eviction to in-process cache Map (memory)
- Scope widget refresh + cache age to current widget kind (UX)
- Remove double caching in update-checker (simplicity)
- Simplify timetable router (verbosity)
- Fix update-checker import path
2026-07-03 09:59:08 +02:00
ajnart 0fd495c277 style: auto-fix lint and format 2026-07-02 16:29:52 +00:00
Thomas Camlong e93b5f6469 Merge branch 'feat/simplify-caching-tanstack-persister' of github.com:homarr-labs/homarr into feat/simplify-caching-tanstack-persister 2026-07-02 18:28:36 +02:00
Thomas Camlong 5ea902d260 fix: resolve type errors from dev merge
- Fix URL/RequestInfo/RequestInit type conflicts with Node 24.18
- Fix optional repository.id type mismatch in releases router
2026-07-02 18:28:28 +02:00
Thomas Camlong 356fadb9d6 merge: origin/dev (widget-only integration refactor)
Resolve conflicts keeping our simplified request handlers (with TTL
cache) and adopting dev's new release-provider + timetable direct
implementations. Remove per-query staleTime from timetable widget.
2026-07-02 18:19:46 +02:00
Thomas Camlong 33080e3d4f feat: add server-side TTL cache + in-flight dedup to request handler
10s default TTL deduplicates concurrent requests from multiple clients
polling the same integration. 83 users hitting the same widget every
30s now produce ~6 upstream calls/min instead of ~166.
2026-07-02 18:17:04 +02:00
homarr-update-contributors[bot] ceed5c6751 chore: update integrations list readme (#6085)
Co-authored-by: Homarr Update Contributors <210161987+homarr-update-contributors[bot]@users.noreply.github.com>
2026-07-02 15:47:49 +00:00
Thomas f7ede23dc3 Merge pull request #6089 from homarr-labs/feat/widget-only-integration-refactor 2026-07-02 17:37:07 +02:00
homarr-renovate[bot] 1b50249ea9 chore(deps): update dependency tar-fs@>=3.0.0 <3.0.9 to >=3.1.3 (#6162)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-07-02 14:11:50 +00:00
homarr-renovate[bot] 1d57519005 chore(deps): update dependency tar-fs@>=2.0.0 <2.1.3 to >=3.1.3 (#6161)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-07-02 11:44:07 +00:00
ajnart 230ee3e1fc style: auto-fix lint and format 2026-07-01 18:19:41 +00:00
Thomas Camlong 8571b4dcb7 feat: add server-side TTL cache + in-flight dedup to request handler
10s default TTL deduplicates concurrent requests from multiple clients
polling the same integration. 83 users hitting the same widget every
30s now produce ~6 upstream calls/min instead of ~166.
2026-07-01 20:18:37 +02:00
homarr-renovate[bot] dd2eb3aa66 chore(deps): update dependency posthog-js to ^1.395.0 (#6150)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-07-01 15:51:52 +00:00
Thomas Camlong 2c1a5c92e8 chore(i18n): revert non-English translations to dev
Keep translation changes in en.json only; Crowdin handles other locales.
2026-07-01 17:25:43 +02:00
Thomas Camlong 781378dc76 fix: address PR review findings
- WidgetCacheAge reads from query cache on every tick (reactive)
- Guard empty timestamps array (no -Infinity edge case)
- Docker widget: add explicit refetchInterval (not under [["widget"]])
- system-resources: split integrationIds reset into separate effect
- Remove unused React import in vpn widget
2026-07-01 15:36:00 +02:00
Thomas Camlong 445a100cd7 Merge branch 'feat/simplify-caching-tanstack-persister' of github.com:homarr-labs/homarr into feat/simplify-caching-tanstack-persister 2026-07-01 15:18:55 +02:00
Thomas Camlong 5784612d59 merge: incorporate dev and add context menu refetch
- Resolve dns-hole conflicts (keep simplified polling, no per-query opts)
- Calendar hover/pin UI and docker column visibility preserved
- Subscriptions from dev (docker, calendar) correctly excluded by auto-merge
- Error boundary invalidateQueries fix preserved alongside context menu
- Add "Refresh" button to widget context menu with live "Xs ago" indicator
2026-07-01 15:18:25 +02:00
ajnart 0425bec2ca style: auto-fix lint and format 2026-07-01 13:00:06 +00:00
Thomas Camlong 06da6191cc Merge origin/dev into feat/widget-only-integration-refactor
Resolve integration.ts conflict (keep widget-only documentationUrl: null, take defaultUrl from dev) and regenerate pnpm-lock.yaml.
2026-07-01 14:57:00 +02:00
homarr-renovate[bot] aec6bb18c5 chore(deps): update dependency @scalar/api-reference-react to ^0.9.49 (#6146)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-07-01 12:21:19 +00:00
ajnart d670b69396 fix(timetable): restore station search by removing disabled query guard
The refactor from integration-based to option-based config changed the
useQuery enabled condition from 'integrationIds.length > 0' (always true
when an integration was linked) to 'query.length > 0'. The combination
of the debounced search value and the enabled toggle inside the nested
useOptions callback caused the query to never fire, making stations
unsearchable in the edit form.

Removing the enabled guard lets the query always run. The 300ms debounce
already prevents excessive requests.
2026-06-30 18:40:27 +02:00
Thomas Camlong 8747d5f93e fix: add id to repository schema and handle missing ids gracefully 2026-06-28 13:55:17 +02:00
Thomas Camlong af35a50fa0 fix: handle missing widgetSecrets table and add default releases repo
- getConfiguredKinds now returns [] if table doesn't exist yet
- Add homarr-labs/homarr as default releases repository (v#.#.#)
2026-06-28 08:47:09 +02:00
ajnart 39ffdd2830 style: auto-fix lint and format 2026-06-27 11:07:07 +00:00
Thomas Camlong 8e2cac6bf0 fix(lint): remove non-null assertion in VPN widget 2026-06-27 13:06:02 +02:00
ajnart a56bf0f32d style: auto-fix lint and format 2026-06-27 11:04:33 +00:00
Thomas Camlong e687bc8c92 fix: address review - paginate GH releases, GitLab tag_name, docs, test
- Paginate GitHub releases via api.paginate to avoid missing tags beyond page 1
- Use tag_name instead of name for GitLab releases (name is a display label)
- Remove ArchiveTeam Warrior from widget-configured note in docs
- Fix test assertion to use objectContaining for error shape with message
2026-06-27 13:02:58 +02:00
Thomas Camlong 64c7512283 fix: compile versionRegex once and add fetch timeouts
- Compile regex once via compileVersionRegex, reject invalid patterns early
- Add 10s timeout to all provider fetch calls via fetchProvider wrapper
2026-06-27 12:56:48 +02:00
Thomas Camlong 1cd04aaf45 fix: cache update checker responses for 30 minutes
GitHub API has strict rate limits; avoid hitting it on every poll.
2026-06-27 12:24:54 +02:00
ajnart 482e74f8c7 style: auto-fix lint and format 2026-06-27 10:15:09 +00:00
Thomas Camlong 12bf6ee4be fix: address CodeRabbit review findings
- docker-table: inspect refetch result instead of .catch() (TQ v5 compat)
- rssFeed: sort all entries by date before slicing to max posts
- toValidDate: reject null/boolean inputs before Date construction
- system-resources: reset chart history when integrationIds changes
- settleIntegrationQueries: wrap fn in async boundary for safe allSettled
2026-06-27 12:13:52 +02:00
Thomas Camlong 45c58c967e revert: re-apply all deletions and request handler simplifications
Restores the full PR changes after CodeRabbit review window.
2026-06-27 12:09:48 +02:00
Thomas Camlong e9611e8098 chore: temporarily restore deleted files for CodeRabbit review
Restoring 27 deleted files and 26 trivially-changed request handlers
to bring the PR under CodeRabbit's 150-file review limit.
These will be re-deleted in the next commit.
2026-06-27 11:49:15 +02:00
ajnart 398c88f2c6 style: auto-fix lint and format 2026-06-27 09:06:44 +00:00
Thomas Camlong 34d976eeea fix: apply version filter to LinuxServer.io provider
LSIO was bypassing versionRegex unlike all other providers.
2026-06-27 11:01:12 +02:00
Thomas Camlong 757d59854e fix: address PR review - atomic upsert, MCP metadata, stale tokens, save UX
- Wrap setSecret delete+insert in a cross-DB transaction
- Add MCP metadata to all widget secret procedures and register in mcp.ts
- Show configured tokens even when no repos use that provider
- Only clear token input after mutation succeeds, with loading state
2026-06-27 10:58:35 +02:00
Thomas Camlong 2155f13f24 fix: verbose error messages in all release providers
Every error now includes a diagnostic message:
- noMatchingVersion: shows the regex used, how many tags were
  checked, and sample tag names so users can see why matching failed
- noReleasesFound: distinguishes "no releases at all" from "no match"
- invalidIdentifier: shows the problematic identifier string
- unexpected: includes HTTP status codes from provider APIs

getLatestRelease returns { release } | { noMatch: reason } instead
of Release | null, carrying the diagnostic through.
2026-06-27 10:57:14 +02:00
Thomas Camlong d893515b93 fix: catch individual repo fetch failures to prevent batch crashes
Wrap each repository fetch in try/catch so one failure (Redis,
network, etc.) doesn't crash the entire query batch. Failed repos
now return a proper error response instead of causing all repos
to show "No response from provider".
2026-06-27 10:57:14 +02:00
Thomas Camlong 30107e4e76 fix: gracefully degrade when widget_secret table is missing or access denied
The releases widget was crashing because throwIfActionForbiddenAsync
or the widgetSecrets query would throw before DB migrations are run.
Wrap in try/catch so the widget works without tokens in that case.
2026-06-27 10:57:14 +02:00
ajnart 8c51a3769e style: auto-fix lint and format 2026-06-27 10:57:14 +02:00
Thomas Camlong 77884a3179 feat: add per-widget secret storage for release provider authentication
Adds encrypted token storage per release widget so users can authenticate
with GitHub, GitLab, Docker Hub, etc. without needing full integration setup.

- New `widget_secret` table (all 3 DB drivers) keyed by (itemId, kind)
- tRPC router with setSecret/deleteSecret/getConfiguredKinds (board modify access required)
- Releases router injects decrypted tokens into provider requests (board view access required)
- Tokens only used for repos matching widget's stored configuration (prevents proxy abuse)
- Provider auth: GitHub (Octokit auth), GitLab (PRIVATE-TOKEN), Docker Hub (Bearer),
  GHCR (registry token), npm (Bearer), Codeberg (token header)
- UI: "Provider Tokens" section in widget editor with PasswordInput per provider
2026-06-27 10:57:13 +02:00
ajnart d8a7477039 style: auto-fix lint and format 2026-06-27 10:57:13 +02:00
Thomas Camlong 8e1dcecf64 chore: update lockfile 2026-06-27 10:57:13 +02:00
Thomas Camlong c892731479 fix: address PR review findings for widget-only integration refactor
- Fix npm scoped package support (filter time metadata keys, make
  description optional, exclude falsy releases from version selection)
- Fix timetable date formatting (use Intl.DateTimeFormat for stable
  MM/DD/YYYY output) and named zod import
- Guard migration 0000 against unknown provider keys
- Fix migration 0003 to delete integration links by integrationId
- Reset immich album carousel index when photo list changes
- Add bounded limit to timetable router input
- Remove stale misspelled noProviderSeleceted translation key
- Fix provider name visibility in release widget settings
- Update docs: add ArchiveTeam Warrior note, fix typos, correct
  showPhotoInfo default
2026-06-27 10:57:13 +02:00
Thomas Camlong 62baaf7813 fix: update CHANGES.md for ArchiveTeam Warrior restoration, remove typo translation key 2026-06-27 10:57:13 +02:00
Thomas Camlong 8a5ad5861b fix: restore ArchiveTeam Warrior as a proper integration
The widget-only integrations refactor incorrectly removed the
ArchiveTeam Warrior integration entirely. It only needed to be
excluded from auto-seeding (by removing defaultUrl), not deleted.

This restores the integration class, reverts the widget/router/handler
to use integration middleware, and removes archiveTeamWarrior from the
widget-only-integrations migration.
2026-06-27 10:57:13 +02:00
ajnart d18d07d2f1 style: auto-fix lint and format 2026-06-27 10:57:12 +02:00
Thomas Camlong fb348044fb refactor widget-only integrations 2026-06-27 10:57:12 +02:00
Thomas Camlong 96fe0d55c7 merge: incorporate dev changes and migrate VPN widget
Resolve merge conflicts favoring our simplified caching architecture:
- cron-jobs/index.ts: keep reduced job set (no integration cron jobs)
- en.json: keep reduced cron job labels
- docker-table.tsx: keep refetch() approach, adopt dev's initialData format

Migrate new VPN widget to polling architecture:
- Remove VPN cron job and subscription-based pattern
- Simplify request handler to createIntegrationRequestHandler
- Simplify tRPC router to use getDataAsync + settleIntegrationQueries
- Convert widget from useSuspenseQuery + subscription to useQuery with polling
2026-06-26 20:38:13 +02:00
Thomas Camlong 3e782a6907 style: remove remaining ponytail comments 2026-06-26 18:38:23 +02:00
ajnart 2018e9e81b style: auto-fix lint and format 2026-06-25 15:39:31 +00:00
Thomas Camlong c848dbfc1f fix: scope polling to widgets, fix retry, guard dates, throttle umami
- Remove global refetchInterval; scope to widget queries via setQueryDefaults
- Fix error boundary retry: correct queryKey to [["widget"]], move invalidation to onReset
- Add toValidDate() helper in @homarr/common for cache hydration safety
- Guard date formatting in media-releases and media-requests against non-Date values
- Set umami refetchInterval to 60s via shared umamiQueryOptions constant
- Simplify dns-hole mutations to invalidate() instead of manual optimistic setData
2026-06-25 17:38:13 +02:00
ajnart 210a62b35a style: auto-fix lint and format 2026-06-25 12:49:13 +00:00
Thomas Camlong 8f4f543d29 fix: resilient RSS/releases fetching and effect deps
- RSS feed: Promise.allSettled so one bad URL doesn't fail all feeds
- Releases: Promise.allSettled so one bad repo doesn't blank widget
- system-resources: add data to useEffect deps
- media-requests: invalidate all mediaRequests queries on answer
2026-06-25 14:47:58 +02:00
Thomas Camlong 92920db07d style: fix dep ordering and restore redis null guard 2026-06-25 13:02:39 +02:00
Thomas Camlong e7037ddfe9 chore: remove dead code leftovers from caching rework
- Remove dead Redis exports (exampleChannel, homeAssistantEntityState, queueChannel)
- Remove dead Beszel subscribeRealtimeMetrics/subscribeTopic (~100 lines)
- Add missing onSettled invalidation to downloads queue + indexer-manager mutations
- Rename invalidate-update-checker-cache → warm-update-checker
- Delete empty cron-jobs/integrations directory
- Fix stale comment and unused type imports
2026-06-25 12:37:33 +02:00
ajnart cc50e47668 style: auto-fix lint and format 2026-06-25 10:02:36 +00:00
Thomas Camlong cb5ad15305 fix: remove unused isEditMode params and dead clientApi import
Post-merge lint errors from dev — unused variables left behind
after subscription removal.
2026-06-25 12:01:01 +02:00
ajnart 2cb0964aa2 style: auto-fix lint and format 2026-06-25 09:57:29 +00:00
Thomas Camlong 26a8d219af refactor: resilient integration queries + simplification
- Extract settleIntegrationQueries helper (Promise.allSettled + logging)
  so one failing integration no longer kills the entire widget
- Convert 16 widget routers from Promise.all to settleIntegrationQueries
- Add onSettled query invalidation to downloads and media-requests mutations
- Inline 4 single-use firewall useUpdating* hooks
- Deduplicate firewall router (4 identical procedures → shared factory)
- Fix system-resources chart duplicate initial point (ref-based dedup)
- Simplify docker table refresh (refetch + isFetching, drop manual state)
- Trim invalidateIntegrationCacheAsync to session-store only (dead scan)
- Fix Beszel getAlerts: inner Promise.allSettled so systems failure
  doesn't discard alerts
2026-06-25 11:56:05 +02:00
Thomas cf5934aef6 Merge branch 'dev' into feat/simplify-caching-tanstack-persister 2026-06-25 11:49:39 +02:00
ajnart 9c6f900b82 style: auto-fix lint and format 2026-06-25 09:26:18 +00:00
Thomas Camlong c4a664b7ac fix: address PR review — bugs, dead code, error handling
Critical fixes:
- Smart Home: invalidate entity state query after toggle mutation
- Beszel live mode: use 5s refetchInterval instead of global 30s
- Fix unit test assertions for 5-arg setQueryCacheAsync signature
- Fix serialize/deserialize mismatch: JSON.parse on read (matches persister's JSON.stringify)
- Remove render-time setActiveQueryCacheBoardId race (keep only useEffect)

Error handling:
- Log persistence errors instead of swallowing with catch(() => {})
- Log QueryCacheHydration failures with ErrorWithMetadata
- Beszel: log partial failures (system details, container stats)

Dead code removal:
- Remove dead queryKey from all 39 request handlers + lib files
- Delete unused Redis APIs: createCacheChannel, createChannelWithLatestAndEvents,
  createChannelEventHistory, history-channel.ts
- Remove stale createCacheChannel mock from docker test

Cleanup:
- Seed system-resources chart from initial query data (no empty start)
- Remove redundant refetchOnWindowFocus/refetchOnReconnect from BoardProvider
2026-06-25 11:25:09 +02:00
ajnart 457b1b0ce0 style: auto-fix lint and format 2026-06-25 09:07:24 +00:00
Thomas Camlong 5581b6db94 refactor: simplify request handlers and deduplicate config
- Re-enable TanStack Query retry (retry: 3 with exponential backoff),
  delete all server-side retry logic from request handlers
- Strip handler factories to bare minimum: remove isValid, retry, widgetKind
- Remove redundant refetchOnWindowFocus/refetchOnReconnect from docker-table
- Deduplicate queryCacheMaxValueBytes (pass as param, single source of truth)
- Simplify system-resources chart: use dataUpdatedAt instead of ref-based tracking
- Fix leading blank lines in 27 request handler files
2026-06-25 11:06:03 +02:00
ajnart a164c951ce style: auto-fix lint and format 2026-06-24 13:11:34 +00:00
Thomas Camlong 18d6013f3f merge: resolve conflicts with origin/dev
Take dev's newer dependency versions (tiptap 3.27.1, testcontainers 12.0.3).
Resolve beszel widget conflicts by keeping our approach (no per-widget
staleTime/refetchInterval/subscriptions, globals handle it).
2026-06-24 15:10:10 +02:00
Thomas Camlong 6416080b79 feat: replace server-side Redis caching with TanStack Query AsyncStoragePersister
Consolidate two overlapping cache systems (broken TanStack persister + per-query Redis hash + pub/sub) into one: TanStack Query as single source of truth with Redis as its persistence layer via createAsyncStoragePersister.

- Replace QueryClientProvider with PersistQueryClientProvider backed by Redis
- Set global query defaults (staleTime: 0, refetchInterval: 30s, gcTime: 24h)
- Remove all per-widget staleTime/refetchInterval/retry/refetchOnWindowFocus overrides
- Replace cached request handlers with simplified fetch-only versions
- Remove all tRPC subscription procedures and useSubscription calls in favor of polling
- Delete 20 cron jobs that only pre-warmed server-side cache
- Simplify Redis from per-query hash to single blob per user+board
2026-06-24 14:55:17 +02:00
464 changed files with 3587 additions and 8178 deletions

No files matched your search

+1 -63
View File
@@ -90,7 +90,7 @@ jobs:
typecheck:
runs-on: ubuntu-latest
timeout-minutes: 10
timeout-minutes: 15
steps:
- uses: actions/checkout@v6
with:
@@ -163,65 +163,3 @@ jobs:
run: cp .env.example .env
- name: Build
run: pnpm turbo build --affected
memory-regression:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@v6
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
- name: Build Docker image
uses: docker/build-push-action@v7
with:
platforms: linux/amd64
context: .
push: false
load: true
tags: homarr-memory-test
network: host
cache-from: type=gha
cache-to: type=gha,mode=max
env:
SKIP_ENV_VALIDATION: true
- name: Start container and measure memory
run: |
docker run -d --name homarr-mem-test -p 17575:7575 homarr-memory-test
# Wait for container to be healthy (up to 60s)
healthy=false
for i in $(seq 1 30); do
if curl -sf http://localhost:17575/api/health 2>/dev/null; then
echo "Container healthy after $((i * 2))s"
healthy=true
break
fi
sleep 2
done
if [ "$healthy" != "true" ]; then
echo "ERROR: Container never became healthy"
docker logs homarr-mem-test --tail 50
exit 1
fi
# Warm up: hit the dashboard page a few times
for i in $(seq 1 5); do
curl -sf http://localhost:17575/ > /dev/null 2>&1 || true
sleep 2
done
# Measure RSS after warmup
MEM_KB=$(docker stats --no-stream --format '{{.MemUsage}}' homarr-mem-test | sed 's| /.*||')
echo "Raw memory: $MEM_KB"
# Convert to numeric MB (handles GiB and MiB suffixes)
MEM_NUM=$(echo "$MEM_KB" | awk '{
if ($0 ~ /GiB/) { gsub(/GiB/,""); print $1 * 1024 }
else if ($0 ~ /MiB/) { gsub(/MiB/,""); print $1 }
else if ($0 ~ /KiB/) { gsub(/KiB/,""); print $1 / 1024 }
else { print $1 / 1048576 }
}')
echo "Memory usage: ${MEM_NUM} MB"
MAX_MB=700
if awk "BEGIN {exit !($MEM_NUM > $MAX_MB)}"; then
echo "ERROR: Memory usage ${MEM_NUM} MB exceeds ${MAX_MB} MB threshold"
docker logs homarr-mem-test --tail 50
exit 1
fi
echo "Memory check passed: ${MEM_NUM} MB <= ${MAX_MB} MB"
+4
View File
@@ -2,6 +2,7 @@
# dependencies
node_modules
.pnpm-store/
.pnp
.pnp.js
.idea/
@@ -70,7 +71,10 @@ apps/nextjs/public/images/background.png
# personal agent config
.opencode
.agents/
skills-lock.json
# docusaurus
apps/docs/.docusaurus
apps/docs/build
.pnpm-store
+96
View File
@@ -0,0 +1,96 @@
# Changes
## Goal
Remove widget-only services from Homarr's global Integration system.
The affected services are release providers and Search.ch. They are only used by specific widgets, so keeping them as global integrations added unnecessary setup, UI, database rows, docs pages, and integration package code.
ArchiveTeam Warrior remains a proper integration but is no longer auto-seeded on first install.
## Why
These services do not need shared integration state.
- Release providers are selected per Releases widget repository.
- Search.ch is only used by the Timetable widget.
Moving them into widget options makes configuration simpler and removes dead-weight integration code from `packages/integrations`.
## What Changed
### Release Providers
- Added release provider definitions in `packages/definitions/src/release-provider.ts`.
- Removed release providers from `IntegrationKind`.
- Moved release-fetching code out of `packages/integrations` and into `packages/request-handler/src/release-providers.ts`.
- Updated the Releases widget to store provider configuration directly in widget options:
- `provider`
- `identifier`
- `versionFilter`
- `providerUrl`
- Updated the Releases widget editor to use a provider select instead of an integration select.
- Updated Docker import mapping so `ghcr.io` maps to `gitHubContainerRegistry`.
- GitHub Container Registry now uses the public OCI registry API and accepts full image references such as `ghcr.io/homarr-labs/homarr:latest`.
### Timetable / Search.ch
- Removed Search.ch as an integration.
- Added a Timetable widget `baseUrl` option, defaulting to `https://search.ch`.
- Moved Search.ch request/parsing logic into `packages/request-handler/src/timetable.ts`.
- Updated the Timetable API to receive `baseUrl` directly from widget options.
### ArchiveTeam Warrior
- Kept as a proper integration (not removed).
- Removed `defaultUrl` from the integration definition to prevent auto-seeding on first install.
### Integration Cleanup
- Removed creators, exports, docs references, and implementation files for the deleted integrations.
- Removed unused dependencies from `packages/integrations/package.json`.
### Database Migration
- Added `packages/db/migrations/custom/0003_remove_widget_only_integrations.ts`.
- The migration moves old integration-linked widget config into widget options, then deletes the old widget-only integration rows.
- Updated the earlier release widget migration to use the new `provider` field instead of `providerIntegrationId`.
### Docs
- Updated Releases widget docs to describe providers instead of integrations.
- Updated Timetable docs to remove Search.ch integration setup.
- Removed obsolete integration docs pages for the deleted integration kinds.
- Updated docs sitemap and integration docs mappings.
### Translations
- Added English labels for the new widget options:
- `widget.timetable.option.baseUrl.label`
- `widget.releases.option.repositories.providerUrl.label`
## How It Works Now
Release provider configuration lives on each Releases widget repository entry. The request handler resolves provider metadata and fetches releases directly from the provider-specific endpoint. GHCR uses anonymous OCI registry access for public packages.
Timetable passes its widget URL option directly to its API router and request handler. No global integration lookup is needed.
ArchiveTeam Warrior continues to use the standard integration system, but users must manually add the integration (it is not auto-created on install).
## Deliberate Non-Goals
- No provider secret/token support was added.
- No new secret storage model was introduced.
- No compatibility layer was kept in `packages/integrations`.
Widget options are client-visible, so storing provider credentials there would be wrong. If authenticated provider requests are needed later, they need a separate secret-storage design.
## Verification So Far
- Focused typechecks passed for affected packages.
- Full `pnpm turbo typecheck` passed.
- Full `pnpm lint` passed with existing warnings.
- Focused release provider normalization tests passed.
- Widget translation test passed.
- Live GHCR smoke checks passed for `ghcr.io/muchobien/pocketbase:latest` and `ghcr.io/homarr-labs/homarr:latest`.
- `pnpm test packages/integrations/test/pi-hole.spec.ts` passed earlier, but failed on rebased reruns because Pi-hole reported `domainsBeingBlocked` as `-2`/`0` instead of `> 1`.
@@ -28,6 +28,7 @@ Read our [glossary](/docs/getting-started/glossary) if you are new to Homarr.
Congratulations on installing Homarr. Now it's time to get yourself familiar with the concepts of Homarr and how to use it.
## Onboarding
The onboard will show the first time you start Homarr.
This process will help you with your first steps and adding some initial data, such as the administrator account.
@@ -45,50 +46,68 @@ You can either import a previous dashboard using the ZIP archive or start from s
You may refresh anytime and continue from a different device - the onboarding is saved immediately on the server for your convenience.
### Starting from scratch
Depending on your auth provider configuration you will either first see the admin user creation form or the external group creation form.
If credentials provider was selected, you'll be prompted to create an admin user for Homarr.
This user cannot be deleted and has full control over Homarr and all of it's boards.
You must choose an username and password (both can later be changed).
We enforce strict password requirements, when you enter your password, to protect your instance if you accidentially
expose it to the Internet.
<img src={imageStartFromScratchStepAdminUser} alt={"Screenshot form to create admin user"} width={300} />
Depending on your auth provider configuration you will either first see the admin user creation form or the external group creation form.
If the credentials provider was selected, you'll be prompted to create an admin user for Homarr.
This user cannot be deleted and has full control over Homarr and all of its boards.
You must choose a username and password (both can later be changed).
We enforce strict password requirements when you enter your password to protect your instance if you accidentally
expose it to the internet.
<img
src={imageStartFromScratchStepAdminUser}
alt={"Screenshot form to create admin user"}
width={300}
/>
If you selected external providers (such as LDAP or OIDC), you'll be prompted to create an admin group.
This group will be used to synchronize users from your provider to Homarr.
When a user is logged in through the provider the groups of him that match groups with any in Homarr will be added to the user.
The name of the group has to match exactly the name of the group in the provider.
This group will be used to synchronize users from your provider to Homarr.
When a user logs in through the provider, any of their groups that match groups in Homarr will be assigned to the user.
The name of the group must match exactly the name of the group in the provider.
<img src={imageStartFromScratchStepExternalAdminGroup} alt={"Screenshot form to create external admin group"} width={300} />
<img
src={imageStartFromScratchStepExternalAdminGroup}
alt={"Screenshot form to create external admin group"}
width={300}
/>
Next, you can configure some basic settings for Homarr. We recommend to leave all settings at default for most users.
Here you can also disable analytics. Please note that our analytics are completly anonymous and is fully compliant with GDPR and PECR.
<img src={imageStartFromScratchStepServerSettings} alt={"Screenshot of analytics and indexing settings in the onboarding"} width={300} />
<img
src={imageStartFromScratchStepServerSettings}
alt={"Screenshot of analytics and indexing settings in the onboarding"}
width={300}
/>
### Setting up integrations
After configuring server settings, the onboarding guides you through setting up your integrations.
#### Docker service discovery
If Docker is available (socket mounted), Homarr automatically detects running containers and matches them to known integration types.
Matching integrations are pre-selected in the integration list, saving you from manually picking each one.
#### URL templating
You can define a base URL template to auto-fill integration URLs in bulk.
Two modes are supported:
- **Subdomain mode** - e.g. `{app}.example.com` where `{app}` is replaced with the integration name
- **Port mode** - e.g. `192.168.1.1:{port}` where `{port}` is replaced with the integration's default port
#### API key helper links
For integrations that require API keys (such as Sonarr, Radarr, SABnzbd, or Seerr), a helper link opens the relevant settings page in the target application so you can quickly copy your key.
#### Creating apps from Docker containers
You can optionally auto-create bookmark apps for all discovered Docker containers, making them immediately available on your board.
:::note
Some niche and registry integrations (GitHub, npm, Docker Hub, GitLab, Codeberg, LinuxServer.io, GHCR, Quay, Search.ch) are hidden from the onboarding selection grid but remain available on the manage integrations page.
Release providers and Search.ch are configured directly in their widgets instead of the integrations page.
:::
@@ -97,30 +116,41 @@ The onboarding can no longer be started again.
From here you can click on one of the provided links to continue your journey.
We recommend you to continue with the section [creating your first board on this page](#creating-your-first-board).
<img src={imageStartFromScratchStepFinish} alt={"Screenshot of the finish onboarding process with links"} width={300} />
<img
src={imageStartFromScratchStepFinish}
alt={"Screenshot of the finish onboarding process with links"}
width={300}
/>
### Importing a ZIP from version before 1.0.0
This is recommended when you used Homarr before and want to re-import your data.
It is important that you first migrate correctly using [the list of breaking changes for 1.0](/blog/2024/09/23/version-1.0).
<img src={manageExportOldHomarr} alt="Export from old Homarr" style={{ maxWidth: 500 }} />
<img
src={manageExportOldHomarr}
alt="Export from old Homarr"
style={{ maxWidth: 500 }}
/>
**How to export and import data**
1. Navigate to your old Homarr, open your management pages, open the tools submenu and open ``Migrate to 1.0``.
1. Navigate to your old Homarr, open your management pages, open the tools submenu and open `Migrate to 1.0`.
2. Check the contents that you want to export. We recommend you to export all data.
3. Click on the export data button
4. Save the ZIP file, that is being downloaded, on your device. If you selected "integrations" or "users", you also get an encryption / decryption key.
Copy it and do not loose it!
5. Go to your new >1.0.0 Homarr instance and start the onboarding. Choose ``Import from Homarr before 1.0``
Copy it and do not loose it!
5. Go to your new >1.0.0 Homarr instance and start the onboarding. Choose `Import from Homarr before 1.0`
6. Drag and drop your previously downloaded ZIP archive into the file upload: <br/><img src={manageImportOldHomarrDropzone} style={{ maxWidth: 500 }} />
7. Next, choose the data that you want to import and how to import it. Since screen sizes were removed in 1.0, we create a new board for every screen size by default. We recommend you to only keep the best layout and adjust it later in 1.0.0 - but you can also import all of them and pick later.<br/><img src={manageImportOldHomarrChooseData} style={{ maxWidth: 500 }} />
8. If you previously exported integrations or users, you will be asked to decrypt the data safely using your obtained encryption token. Paste into the modal and confirm your action.<br/><img src={manageImportDecryptionToken} style={{ maxWidth: 500 }} />
9. Next, you can [follow the same setup as when starting from scratch](#starting-from-scratch). After you completed the onboarding, all of your data will be migrated and available.
## Creating your first board
In Homarr, you organize your apps and widgets on boards.
Boards can be organized using the interactive drag and drop.
Let's create your first board by navigating here: ``Manage`` > ``Boards`` > ``New board``:
Let's create your first board by navigating here: `Manage` > `Boards` > `New board`:
![](./img/manage-create-board-button.png)
A board must always have a name and can either be public or private.
@@ -133,12 +163,13 @@ Congratulations - you've just created your first board. You can see boards, that
![](./img/manage-view-board.png)
## Add your first app to Homarr
To add links to your dashboard, you must first add them as an "app".
Navigate to this page to add an app:
![](./img/manage-navigate-apps.png)
Next, click on the ``New app`` button. You'll need to provide a name and an icon to create an app.
Next, click on the `New app` button. You'll need to provide a name and an icon to create an app.
The name must be at least one character long but you can provide any image URL for the icon.
Homarr ships with over 11K icons - so you can just search by entering a search text instead.
@@ -149,8 +180,9 @@ After you created the app, you'll see in on the apps page:
![](./img/manage-created-app.png)
## Arrange and organize your board
Let's add your freshly created app, from the previous step, to the board.
To do this, edit your previously created board by clicking on the big ``Open board`` button:
To do this, edit your previously created board by clicking on the big `Open board` button:
![](./img/manage-view-board.png)
@@ -165,23 +197,38 @@ Here you have the following options in the header:
When entering the edit mode, you'll get some additional buttons to work with:
<img src={manageBoardHeaderEditMode} alt={"Screenshot of buttons in the edit mode"} width={200} />
<img
src={manageBoardHeaderEditMode}
alt={"Screenshot of buttons in the edit mode"}
width={200}
/>
- **Add item**: Click this button to add new elements to your page.
- **Exit edit mode**: Click this btuton to save your changes and exit edit mode.
To continue, click the option "New Item":
<img src={manageBoardHeaderAddItem} alt={"Screenshot of the add item menu"} width={200} />
<img
src={manageBoardHeaderAddItem}
alt={"Screenshot of the add item menu"}
width={200}
/>
Next, you can choose what item you'd like to add.
We will discuss the other options in the following sections - for now choose "App" to continue.
<img src={manageBoardHeaderChooseItem} alt={"Screenshot of choosing the app item in the modal"} width={300} />
<img
src={manageBoardHeaderChooseItem}
alt={"Screenshot of choosing the app item in the modal"}
width={300}
/>
As soon as you chose the app, the modal will close and you'll get the following item on your board:
<img src={manageBoardNoApp} alt="Screenshot of the No app element on the board" />
<img
src={manageBoardNoApp}
alt="Screenshot of the No app element on the board"
/>
This is expected, because you haven't told Homarr what app it should show in this item.
To configure this, click on the small 3 dots at the top of the item in the edit mode and choose "Edit item" in the menu.
@@ -228,17 +275,18 @@ Be sure to save your changes by exiting edit mode!
![](./img/exit-edit-mode.png)
## Adding your first integration
Now it's time to integrate some basic data into your board.
To do this, we first need to create an integration.
An integration is a connection between Homarr and a third party application - usually something that you run and deploy yourself.
Navigate to ``Manage`` > ``Integrations`` (for example via your user menu).
Navigate to `Manage` > `Integrations` (for example via your user menu).
As an example, we are going to use the public demo instance of **Dash.** - a popular application to monitor CPU / hardware usage.
Choose the **Dash.** integration from the list of available integrations:
![](./img/choose-integration.gif)
Next, choose a name (or leave it at default), enter ``https://dash.mauz.dev/`` as the URL in the form and click on ``Test connection and create``.
Next, choose a name (or leave it at default), enter `https://dash.mauz.dev/` as the URL in the form and click on `Test connection and create`.
Pressing the save button will perform a test request to the integration, to confirm that the networking setup is working as expected.
Sometimes invalid configurations, firewalls and other mistakes can lead to connectivity problems - [follow this guide here](/docs/management/integrations/#troubleshooting-connection) if you experience issues.
@@ -254,13 +302,14 @@ the target application or your router.
:::
## Embed integration data using widgets
Let's add your integration, that you have configured in the section above, as a widget to your board.
First, navigate back to your board that you want to add it to.
Next, enter edit mode again and add another item to your board:
![](./img/manage-board-header-add-item-menu.png)
Instead of choosing an app, let's choose ``System Health Monitoring`` this time.
Instead of choosing an app, let's choose `System Health Monitoring` this time.
Click on "Add to board":
![](./img/manage-board-header-choose-system-health.png)
@@ -290,10 +339,12 @@ As with every change, don't forget to save your changes using the exit edit mode
![](./img/exit-edit-mode.png)
## Grouping your items
As the last step, let's organize your freshly created items using two different options.
You can choose either or both of them on your boards.
### Using dynamic sections
Dynamic sections are a simple, resizable visual group to group items.
![](./img/create-dynamic-section.png)
@@ -303,6 +354,7 @@ After adding a dynamic section, you can simply drag and drop items into the sect
![](./img/dynamic-section.gif)
### Using categories
Categories are more advanced and complicated than dynamic sections.
To create a category, open the add item modal and choose "new category":
@@ -329,22 +381,27 @@ You cannot reduce their horizontal width.
After completing the onboarding, Homarr provides interactive guided tours to help you discover key features.
### Management tour
When you first visit the management area (`/manage`), Homarr walks you through the main pages: boards, apps, integrations, and users (admin only).
Each page highlights the list view and the create action so you know where to find and add things.
### Board tour
When you first open a board, a tour highlights the board header elements: search, edit mode, settings, board switcher, and user menu.
### Tour controls
- Press **Enter** (or click **Next**) to advance through tour steps
- Tours auto-start on first visit and do not repeat once completed
- Tours are skipped on mobile screens (below `sm` breakpoint)
- You can **reset tours** from the user settings page under **Manage > Users > [Your user] > General**
## Next steps
You're done with the basic setup 🔥. Now it's time to organize and customize even more.
We highly recommend you to experiment with different options, styles and configurations.
See these curated pages for your next steps:
- Create new apps using the [apps management](/docs/management/apps/)
- Customize your board or add more boards using the [boards management](/docs/management/boards/)
- Integrate software that you use using the [integrations management](/docs/management/integrations/)
@@ -4,7 +4,6 @@ description: "AdGuard Home is a network-wide software for blocking ads and track
hide_title: true
---
import { IntegrationData } from '@site/src/components/integrations/data';
import { IntegrationHeader } from '@site/src/components/integrations/header';
import { IntegrationCapabilites } from '@site/src/components/integrations/widgets';
import { AddingIntegration } from '@site/src/components/integrations/adding';
@@ -19,10 +18,6 @@ import { dnsHoleControlsWidget } from '@site/docs/widgets/dns-hole-controls';
categories={['DNS Hole']}
/>
### Data
<IntegrationData integration={adguardHomeIntegration} />
### Widgets & Capabilities
<IntegrationCapabilites
items={[{
@@ -6,5 +6,4 @@ export const adguardHomeIntegration: IntegrationDefinition = {
"AdGuard Home is a network-wide software for blocking ads and trackers, providing a safer and faster internet experience.",
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/adguard-home.svg",
path: "../../integrations/adguard-home",
data: "Fetches DNS query statistics, blocking status, and filtering rules from AdGuard Home.",
};
@@ -4,7 +4,6 @@ description: "Anchor is a self-hosted note-taking application."
hide_title: true
---
import { IntegrationData } from '@site/src/components/integrations/data';
import { IntegrationHeader } from '@site/src/components/integrations/header';
import { IntegrationCapabilites } from '@site/src/components/integrations/widgets';
import { AddingIntegration } from '@site/src/components/integrations/adding';
@@ -20,10 +19,6 @@ import { anchorNoteWidget } from '@site/docs/widgets/anchor-note';
The Anchor integration lets Homarr connect to your Anchor instance so you can display and edit selected notes directly from your dashboard.
### Data
<IntegrationData integration={anchorIntegration} />
### Widgets & Capabilities
<IntegrationCapabilites
items={[{
@@ -6,5 +6,4 @@ export const anchorIntegration: IntegrationDefinition = {
"Anchor is a self-hosted note-taking application. The Anchor integration lets Homarr display and edit selected notes directly from the dashboard.",
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/anchor.svg",
path: "../../integrations/anchor",
data: "Fetches and updates notes from an Anchor note-taking server.",
};
@@ -4,7 +4,6 @@ description: "ArchiveTeam Warrior is an easy-to-run virtual machine that helps p
hide_title: true
---
import { IntegrationData } from "@site/src/components/integrations/data";
import { IntegrationHeader } from "@site/src/components/integrations/header";
import { AddingIntegration } from "@site/src/components/integrations/adding";
import { IntegrationSecrets } from "@site/src/components/integrations/secrets";
@@ -14,10 +13,6 @@ import { archiveTeamWarriorIntegration } from ".";
The ArchiveTeam Warrior integration lets Homarr connect to your ArchiveTeam Warrior instance so you can manage and monitor your archiving tasks directly from your dashboard.
### Data
<IntegrationData integration={archiveTeamWarriorIntegration} />
### Adding the integration
<AddingIntegration />
@@ -6,5 +6,4 @@ export const archiveTeamWarriorIntegration: IntegrationDefinition = {
"ArchiveTeam Warrior is an easy-to-run virtual machine that helps preserve websites by using some of your bandwidth and disk space to download and upload content to ArchiveTeam’s archive.",
iconUrl: "https://cdn.jsdelivr.net/gh/selfhst/icons/png/archiveteam-warrior.png",
path: "../../integrations/archiveteam-warrior",
data: "Fetches Archive Team Warrior status including project, bandwidth stats, and item progress via WebSocket.",
};
@@ -4,7 +4,6 @@ description: "Lightweight multiprotocol & multi-source command-line download uti
hide_title: true
---
import { IntegrationData } from '@site/src/components/integrations/data';
import { IntegrationHeader } from '@site/src/components/integrations/header';
import { IntegrationCapabilites } from '@site/src/components/integrations/widgets';
import { AddingIntegration } from '@site/src/components/integrations/adding';
@@ -17,10 +16,6 @@ import { downloadsWidget } from '@site/docs/widgets/downloads';
categories={['Download', 'Multiprotocol', 'Multi-source']}
/>
### Data
<IntegrationData integration={aria2Integration} />
### Widgets & Capabilities
<IntegrationCapabilites
items={[{
@@ -6,5 +6,4 @@ export const aria2Integration: IntegrationDefinition = {
"Lightweight multi-protocol & multi-source command-line download utility. It supports HTTP/HTTPS, FTP, SFTP, BitTorrent and Metalink",
iconUrl: "https://cdn.jsdelivr.net/gh/PapirusDevelopmentTeam/papirus_icons@latest/src/system_downloads_3.svg",
path: "../../integrations/aria2",
data: "Manages and monitors Aria2 downloads including active, waiting, and stopped transfers.",
};
@@ -4,7 +4,6 @@ description: "Audiobookshelf is a self-hosted audiobook and podcast server that
hide_title: true
---
import { IntegrationData } from '@site/src/components/integrations/data';
import { IntegrationHeader } from '@site/src/components/integrations/header';
import { IntegrationCapabilites } from '@site/src/components/integrations/widgets';
import { AddingIntegration } from '@site/src/components/integrations/adding';
@@ -20,10 +19,6 @@ import { audioStatsWidget } from '@site/docs/widgets/audio-stats';
Audiobookshelf provides library statistics including audiobook and podcast counts, listening time, and active sessions.
### Data
<IntegrationData integration={audiobookshelfIntegration} />
### Widgets & Capabilities
<IntegrationCapabilites
items={[
@@ -6,5 +6,4 @@ export const audiobookshelfIntegration: IntegrationDefinition = {
"Audiobookshelf is a self-hosted audiobook and podcast server that lets you manage and stream your audio library.",
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/audiobookshelf.svg",
path: "../../integrations/audiobookshelf",
data: "Fetches library statistics, listening time, and active sessions from Audiobookshelf.",
};
@@ -4,7 +4,6 @@ description: "Beszel is a lightweight server monitoring platform with Docker sta
hide_title: true
---
import { IntegrationData } from '@site/src/components/integrations/data';
import { IntegrationHeader } from '@site/src/components/integrations/header';
import { IntegrationCapabilites } from '@site/src/components/integrations/widgets';
import { AddingIntegration } from '@site/src/components/integrations/adding';
@@ -28,10 +27,6 @@ Beszel monitors your servers in real time via lightweight agents, collecting CPU
<img src={beszelDashboard} alt="Beszel dashboard overview showing all four widgets" />
### Data
<IntegrationData integration={beszelIntegration} />
### Widgets & Capabilities
<IntegrationCapabilites
items={[
@@ -6,5 +6,4 @@ export const beszelIntegration: IntegrationDefinition = {
"Beszel is a lightweight server monitoring platform with Docker stats, historical data, and alert functions.",
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons@master/svg/beszel.svg",
path: "../../integrations/beszel",
data: "Fetches server monitoring data including system stats, containers, SMART devices, alerts, and real-time metrics.",
};
@@ -1,42 +0,0 @@
---
title: 'Codeberg'
description: "Codeberg is a non-profit, community-driven platform for hosting and collaborating on software projects."
hide_title: true
---
import { IntegrationData } from '@site/src/components/integrations/data';
import { IntegrationHeader } from '@site/src/components/integrations/header';
import { IntegrationCapabilites } from '@site/src/components/integrations/widgets';
import { AddingIntegration } from '@site/src/components/integrations/adding';
import { IntegrationSecrets } from '@site/src/components/integrations/secrets';
import { codebergIntegration } from '.';
import { releasesWidget } from '@site/docs/widgets/releases';
<IntegrationHeader
integration={codebergIntegration}
categories={['Version Control', 'Software']}
/>
### Data
<IntegrationData integration={codebergIntegration} />
### Widgets & Capabilities
<IntegrationCapabilites
items={[{
widget: releasesWidget
}]}
/>
### Adding the integration
<AddingIntegration />
### Secrets
<IntegrationSecrets secrets={[{
credentials: [],
steps: []
}, {
credentials: ['personalAccessToken'],
steps: []
}]} />
@@ -1,10 +0,0 @@
import { IntegrationDefinition } from "@site/src/types";
export const codebergIntegration: IntegrationDefinition = {
name: "Codeberg",
description:
"Codeberg is a non-profit, community-driven platform for hosting and collaborating on software projects.",
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/codeberg.svg",
path: "../../integrations/codeberg",
data: "Fetches latest releases and repository metadata from a Codeberg instance.",
};
@@ -4,7 +4,6 @@ description: 'Self-hosted PaaS and deployment platform'
hide_title: true
---
import { IntegrationData } from '@site/src/components/integrations/data';
import { IntegrationHeader } from '@site/src/components/integrations/header';
import { IntegrationCapabilites } from '@site/src/components/integrations/widgets';
import { AddingIntegration } from '@site/src/components/integrations/adding';
@@ -17,10 +16,6 @@ import { coolifyWidget } from '../../widgets/coolify';
categories={['System monitoring', 'Deployment']}
/>
### Data
<IntegrationData integration={coolifyIntegration} />
### Widgets & Capabilities
<IntegrationCapabilites
items={[
@@ -5,5 +5,4 @@ export const coolifyIntegration: IntegrationDefinition = {
description: "Self-hosted PaaS and deployment platform",
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons@master/svg/coolify.svg",
path: "../../integrations/coolify",
data: "Fetches Coolify instance information including applications, services, servers, projects, and health status.",
};
@@ -4,7 +4,6 @@ description: "Dash. is a system performance and resource monitoring tool"
hide_title: true
---
import { IntegrationData } from '@site/src/components/integrations/data';
import { IntegrationHeader } from '@site/src/components/integrations/header';
import { IntegrationCapabilites } from '@site/src/components/integrations/widgets';
import { AddingIntegration } from '@site/src/components/integrations/adding';
@@ -20,10 +19,6 @@ import { systemResourcesWidget } from '@site/docs/widgets/system-resources';
categories={['System monitoring']}
/>
### Data
<IntegrationData integration={dashDotIntegration} />
### Widgets & Capabilities
<IntegrationCapabilites
items={[{
@@ -5,5 +5,4 @@ export const dashDotIntegration: IntegrationDefinition = {
description: "Dash. is a system performance and resource monitoring tool",
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/png/dashdot.png",
path: "../../integrations/dash-dot",
data: "Fetches system health monitoring data including CPU, RAM, storage, network, and GPU information.",
};
@@ -4,7 +4,6 @@ description: "Deluge is a lightweight, Free Software, cross-platform BitTorrent
hide_title: true
---
import { IntegrationData } from '@site/src/components/integrations/data';
import { IntegrationHeader } from '@site/src/components/integrations/header';
import { IntegrationCapabilites } from '@site/src/components/integrations/widgets';
import { AddingIntegration } from '@site/src/components/integrations/adding';
@@ -20,10 +19,6 @@ import { downloadsWidget } from '@site/docs/widgets/downloads';
categories={['Torrent client']}
/>
### Data
<IntegrationData integration={delugeIntegration} />
### Widgets & Capabilities
<IntegrationCapabilites
items={[{
@@ -5,5 +5,4 @@ export const delugeIntegration: IntegrationDefinition = {
description: "Deluge is a lightweight, Free Software, cross-platform BitTorrent client.",
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/deluge.svg",
path: "../../integrations/deluge",
data: "Manages and monitors Deluge torrents including progress, speeds, and pause/resume/delete actions.",
};
@@ -1,42 +0,0 @@
---
title: 'Docker Hub'
description: "Docker Hub is a cloud-based registry service for sharing and managing Docker images."
hide_title: true
---
import { IntegrationData } from '@site/src/components/integrations/data';
import { IntegrationHeader } from '@site/src/components/integrations/header';
import { IntegrationCapabilites } from '@site/src/components/integrations/widgets';
import { AddingIntegration } from '@site/src/components/integrations/adding';
import { IntegrationSecrets } from '@site/src/components/integrations/secrets';
import { dockerHubIntegration } from '.';
import { releasesWidget } from '@site/docs/widgets/releases';
<IntegrationHeader
integration={dockerHubIntegration}
categories={['Container Management', 'Software']}
/>
### Data
<IntegrationData integration={dockerHubIntegration} />
### Widgets & Capabilities
<IntegrationCapabilites
items={[{
widget: releasesWidget
}]}
/>
### Adding the integration
<AddingIntegration />
### Secrets
<IntegrationSecrets secrets={[{
credentials: [],
steps: []
}, {
credentials: ['username', 'personalAccessToken'],
steps: []
}]} />
@@ -1,9 +0,0 @@
import { IntegrationDefinition } from "@site/src/types";
export const dockerHubIntegration: IntegrationDefinition = {
name: "Docker Hub",
description: "Docker Hub is a cloud-based registry service for sharing and managing Docker images.",
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/docker.svg",
path: "../../integrations/docker-hub",
data: "Fetches container image tags and repository metadata from Docker Hub.",
};
@@ -4,7 +4,6 @@ description: "Docker is a platform where you can run your applications in contai
hide_title: true
---
import { IntegrationData } from '@site/src/components/integrations/data';
import { IntegrationHeader } from '@site/src/components/integrations/header';
import { IntegrationCapabilites } from '@site/src/components/integrations/widgets';
import {IntegrationSecrets} from '@site/src/components/integrations/secrets';
@@ -18,10 +17,6 @@ import { dockerContainersWidget } from '@site/docs/widgets/docker-containers';
categories={['Containers']}
/>
### Data
<IntegrationData integration={dockerIntegration} />
### Widgets & Capabilities
<IntegrationCapabilites
items={[{
@@ -6,5 +6,4 @@ export const dockerIntegration: IntegrationDefinition = {
"Docker is a platform where you can run your applications in containers, allowing for easy deployment and management of applications.",
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/docker.svg",
path: "../../integrations/docker",
data: "Fetches Docker container information including status, CPU, and memory usage via the Docker socket.",
};
@@ -4,7 +4,6 @@ description: "Emby is a media server platform that allows you to organize, manag
hide_title: true
---
import { IntegrationData } from '@site/src/components/integrations/data';
import { IntegrationHeader } from '@site/src/components/integrations/header';
import { IntegrationCapabilites } from '@site/src/components/integrations/widgets';
import { AddingIntegration } from '@site/src/components/integrations/adding';
@@ -20,10 +19,6 @@ import { mediaReleasesWidget } from '@site/docs/widgets/media-releases';
categories={['Media server']}
/>
### Data
<IntegrationData integration={embyIntegration} />
### Widgets & Capabilities
<IntegrationCapabilites
items={[
@@ -6,5 +6,4 @@ export const embyIntegration: IntegrationDefinition = {
"Emby is a media server platform that allows you to organize, manage, and stream your personal media collection.",
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/emby.svg",
path: "../../integrations/emby",
data: "Fetches active streams and recently added media from an Emby media server.",
};
@@ -1,47 +0,0 @@
---
title: 'GitHub Container Registry'
description: "GitHub Container Registry is a platform for hosting and managing packages."
hide_title: true
---
import { IntegrationData } from '@site/src/components/integrations/data';
import { IntegrationHeader } from '@site/src/components/integrations/header';
import { IntegrationCapabilites } from '@site/src/components/integrations/widgets';
import { AddingIntegration } from '@site/src/components/integrations/adding';
import { IntegrationSecrets } from '@site/src/components/integrations/secrets';
import { gitHubContainerRegistryIntegration } from '.';
import { releasesWidget } from '@site/docs/widgets/releases';
<IntegrationHeader
integration={gitHubContainerRegistryIntegration}
categories={['Package Management', 'Software']}
/>
### Data
<IntegrationData integration={gitHubContainerRegistryIntegration} />
### Widgets & Capabilities
<IntegrationCapabilites
items={[{
widget: releasesWidget
}]}
/>
### Adding the integration
<AddingIntegration />
### Secrets
<IntegrationSecrets secrets={[{
credentials: [],
steps: []
}, {
credentials: ["personalAccessToken"],
steps: []
}, {
tabLabel: "GitHub App",
credentials: ['githubAppId', 'githubInstallationId', 'privateKey'],
steps: ['Create GitHub App', 'Create a private key for it', 'Install it to your organization / user']
}]} />
@@ -1,12 +0,0 @@
import { IntegrationDefinition } from "@site/src/types";
export const gitHubContainerRegistryIntegration: IntegrationDefinition = {
name: "GitHub Container Registry",
description: "GitHub Container Registry is a platform for hosting and managing packages.",
iconUrl: {
light: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/github.svg",
dark: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/github-light.svg",
},
path: "../../integrations/github-packages",
data: "Fetches container image tags and package metadata from GitHub Container Registry.",
};
@@ -1,46 +0,0 @@
---
title: 'GitHub'
description: "GitHub is a web-based platform for version control and collaboration."
hide_title: true
---
import { IntegrationData } from '@site/src/components/integrations/data';
import { IntegrationHeader } from '@site/src/components/integrations/header';
import { IntegrationCapabilites } from '@site/src/components/integrations/widgets';
import { AddingIntegration } from '@site/src/components/integrations/adding';
import { IntegrationSecrets } from '@site/src/components/integrations/secrets';
import { githubIntegration } from '.';
import { releasesWidget } from '@site/docs/widgets/releases';
<IntegrationHeader
integration={githubIntegration}
categories={['Version Control', 'Software']}
/>
### Data
<IntegrationData integration={githubIntegration} />
### Widgets & Capabilities
<IntegrationCapabilites
items={[{
widget: releasesWidget
}]}
/>
### Adding the integration
<AddingIntegration />
### Secrets
<IntegrationSecrets secrets={[{
credentials: [],
steps: []
}, {
credentials: ['personalAccessToken'],
steps: []
}, {
tabLabel: "GitHub App",
credentials: ['githubAppId', 'githubInstallationId', 'privateKey'],
steps: ['Create GitHub App', 'Create a private key for it', 'Install it to your organization / user']
}]} />
@@ -1,12 +0,0 @@
import { IntegrationDefinition } from "@site/src/types";
export const githubIntegration: IntegrationDefinition = {
name: "GitHub",
description: "GitHub is a web-based platform for version control and collaboration.",
iconUrl: {
light: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/github.svg",
dark: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/github-light.svg",
},
path: "../../integrations/github",
data: "Fetches releases and repository metadata from GitHub using the Octokit API.",
};
@@ -1,42 +0,0 @@
---
title: 'GitLab'
description: "GitLab is a web-based DevOps lifecycle tool that provides a Git repository manager."
hide_title: true
---
import { IntegrationData } from '@site/src/components/integrations/data';
import { IntegrationHeader } from '@site/src/components/integrations/header';
import { IntegrationCapabilites } from '@site/src/components/integrations/widgets';
import { AddingIntegration } from '@site/src/components/integrations/adding';
import { IntegrationSecrets } from '@site/src/components/integrations/secrets';
import { gitlabIntegration } from '.';
import { releasesWidget } from '@site/docs/widgets/releases';
<IntegrationHeader
integration={gitlabIntegration}
categories={['Version Control', 'Software']}
/>
### Data
<IntegrationData integration={gitlabIntegration} />
### Widgets & Capabilities
<IntegrationCapabilites
items={[{
widget: releasesWidget
}]}
/>
### Adding the integration
<AddingIntegration />
### Secrets
<IntegrationSecrets secrets={[{
credentials: [],
steps: []
}, {
credentials: ['personalAccessToken'],
steps: []
}]} />
@@ -1,9 +0,0 @@
import { IntegrationDefinition } from "@site/src/types";
export const gitlabIntegration: IntegrationDefinition = {
name: "GitLab",
description: "GitLab is a web-based DevOps lifecycle tool that provides a Git repository manager.",
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/gitlab.svg",
path: "../../integrations/gitlab",
data: "Fetches releases and project metadata from a GitLab instance.",
};
@@ -4,7 +4,6 @@ description: "Glances is a cross-platform system monitoring tool."
hide_title: true
---
import { IntegrationData } from '@site/src/components/integrations/data';
import { IntegrationHeader } from '@site/src/components/integrations/header';
import { IntegrationCapabilites } from '@site/src/components/integrations/widgets';
import { AddingIntegration } from '@site/src/components/integrations/adding';
@@ -19,10 +18,6 @@ import { healthMonitoringWidget } from '@site/docs/widgets/health-monitoring';
categories={['System Monitoring']}
/>
### Data
<IntegrationData integration={glancesIntegration} />
### Widgets & Capabilities
<IntegrationCapabilites
items={[{
@@ -8,5 +8,4 @@ export const glancesIntegration: IntegrationDefinition = {
dark: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/glances-light.svg",
},
path: "../../integrations/glances",
data: "Fetches system health data including CPU, RAM, disk, network, GPU, and sensors from Glances.",
};
@@ -4,7 +4,6 @@ description: 'Connect Gluetun to Homarr as a VPN integration.'
hide_title: true
---
import { IntegrationData } from '@site/src/components/integrations/data';
import { IntegrationHeader } from '@site/src/components/integrations/header';
import { IntegrationCapabilites } from '@site/src/components/integrations/widgets';
import { AddingIntegration } from '@site/src/components/integrations/adding';
@@ -20,10 +19,6 @@ import { vpnWidget } from '@site/docs/widgets/vpn';
[Gluetun](https://github.com/qdm12/gluetun) exposes a control server that Homarr can query to report the VPN tunnel
status, DNS status, public IP address, and active provider details in the VPN widget.
### Data
<IntegrationData integration={gluetunIntegration} />
### Widgets & Capabilities
<IntegrationCapabilites
@@ -5,5 +5,4 @@ export const gluetunIntegration: IntegrationDefinition = {
description: "VPN control server integration for Homarr's VPN widget.",
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/gluetun.svg",
path: "../../integrations/gluetun",
data: "Fetches VPN status, public IP, and DNS information from a Gluetun VPN container.",
};
@@ -6,7 +6,6 @@ hide_title: true
import { notificationsWidget } from '@site/docs/widgets/notifications';
import { AddingIntegration } from '@site/src/components/integrations/adding';
import { IntegrationData } from '@site/src/components/integrations/data';
import { IntegrationHeader } from '@site/src/components/integrations/header';
import { IntegrationSecrets } from '@site/src/components/integrations/secrets';
import { IntegrationCapabilites } from '@site/src/components/integrations/widgets';
@@ -17,10 +16,6 @@ import { gotifyIntegration } from '.';
categories={['Notifications', 'Messaging']}
/>
### Data
<IntegrationData integration={gotifyIntegration} />
### Widgets & Capabilities
<IntegrationCapabilites
items={[{
@@ -5,5 +5,4 @@ export const gotifyIntegration: IntegrationDefinition = {
description: "Gotify is a simple, self-hosted server for sending and receiving messages in real time.",
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/gotify.svg",
path: "../../integrations/gotify",
data: "Fetches recent push notification messages from a Gotify server.",
};
@@ -4,7 +4,6 @@ description: "Home Assistant is an open-source home automation platform that foc
hide_title: true
---
import { IntegrationData } from '@site/src/components/integrations/data';
import { IntegrationHeader } from '@site/src/components/integrations/header';
import { IntegrationCapabilites } from '@site/src/components/integrations/widgets';
import { AddingIntegration } from '@site/src/components/integrations/adding';
@@ -20,10 +19,6 @@ import { smartHomeExecuteAutomationWidget } from '@site/docs/widgets/smart-home-
categories={['Smart Home', 'Automation']}
/>
### Data
<IntegrationData integration={homeAssistantIntegration} />
### Widgets & Capabilities
<IntegrationCapabilites
items={[{
@@ -6,5 +6,4 @@ export const homeAssistantIntegration: IntegrationDefinition = {
"Home Assistant is an open-source home automation platform that focuses on privacy and local control, allowing you to automate and control your smart home devices.",
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/home-assistant.svg",
path: "../../integrations/home-assistant",
data: "Fetches entity states, triggers automations, toggles entities, and retrieves calendar events from Home Assistant.",
};
@@ -4,7 +4,6 @@ description: "iCal is a standard for calendar data exchange, allowing users to s
hide_title: true
---
import { IntegrationData } from '@site/src/components/integrations/data';
import { IntegrationHeader } from '@site/src/components/integrations/header';
import { IntegrationCapabilites } from '@site/src/components/integrations/widgets';
import { AddingIntegration } from '@site/src/components/integrations/adding';
@@ -18,10 +17,6 @@ import { calendarWidget } from '@site/docs/widgets/calendar';
categories={['Calendar']}
/>
### Data
<IntegrationData integration={icalIntegration} />
### Widgets & Capabilities
<IntegrationCapabilites
items={[{
@@ -6,5 +6,4 @@ export const icalIntegration: IntegrationDefinition = {
"iCal is a standard for calendar data exchange, allowing users to share and manage calendar events across different platforms.",
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/ical.svg",
path: "../../integrations/ical",
data: "Fetches and parses an iCal/ICS calendar feed to retrieve calendar events.",
};
@@ -9,7 +9,6 @@ import { immichAlbumCarouselWidget } from '../../widgets/immich-album-carousel';
} from '@site/src/components/integrations/header';
import { IntegrationCapabilites } from '@site/src/components/integrations/widgets';
import { AddingIntegration } from '@site/src/components/integrations/adding';
import { IntegrationData } from '@site/src/components/integrations/data';
import { IntegrationSecrets } from '@site/src/components/integrations/secrets';
import { immichIntegration } from '.';
import { immichServerStatsWidget } from '../../widgets/immich-server-stats';
@@ -20,10 +19,6 @@ import { immichServerStatsWidget } from '../../widgets/immich-server-stats';
categories={['Photo server']}
/>
### Data
<IntegrationData integration={immichIntegration} />
### Widgets & Capabilities
<IntegrationCapabilites
items={[
@@ -5,5 +5,4 @@ export const immichIntegration: IntegrationDefinition = {
description: "Self-hosted photo and video management solution",
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/immich.svg",
path: "../../integrations/immich",
data: "Fetches server statistics, albums, and users from an Immich photo management server.",
};
@@ -4,7 +4,6 @@ description: "Jellyfin is a free and open-source media server software that allo
hide_title: true
---
import { IntegrationData } from '@site/src/components/integrations/data';
import { IntegrationHeader } from '@site/src/components/integrations/header';
import { IntegrationCapabilites } from '@site/src/components/integrations/widgets';
import { AddingIntegration } from '@site/src/components/integrations/adding';
@@ -20,10 +19,6 @@ import { mediaReleasesWidget } from '@site/docs/widgets/media-releases';
categories={['Media server']}
/>
### Data
<IntegrationData integration={jellyfinIntegration} />
### Widgets & Capabilities
<IntegrationCapabilites
items={[
@@ -6,5 +6,4 @@ export const jellyfinIntegration: IntegrationDefinition = {
"Jellyfin is a free and open-source media server software that allows you to organize, manage, and share your media files.",
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/jellyfin.svg",
path: "../../integrations/jellyfin",
data: "Fetches active streams and recently added media from a Jellyfin media server.",
};
@@ -4,7 +4,6 @@ description: "Jellyseerr is a self-hosted media request management system that i
hide_title: true
---
import { IntegrationData } from '@site/src/components/integrations/data';
import { IntegrationHeader } from '@site/src/components/integrations/header';
import { IntegrationCapabilites } from '@site/src/components/integrations/widgets';
import { AddingIntegration } from '@site/src/components/integrations/adding';
@@ -20,10 +19,6 @@ import { mediaRequestStatsWidget } from '@site/docs/widgets/media-request-stats'
categories={['Media requests']}
/>
### Data
<IntegrationData integration={jellyseerrIntegration} />
### Widgets & Capabilities
<IntegrationCapabilites
items={[{
@@ -6,5 +6,4 @@ export const jellyseerrIntegration: IntegrationDefinition = {
"Jellyseerr is a self-hosted media request management system that integrates with Jellyfin and other media servers.",
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/jellyseerr.svg",
path: "../../integrations/jellyseerr",
data: "Fetches media requests, search results, and user information from Jellyseerr.",
};
@@ -4,7 +4,6 @@ description: "Kubernetes is a powerful container orchestration platform that aut
hide_title: true
---
import { IntegrationData } from '@site/src/components/integrations/data';
import { IntegrationHeader } from '@site/src/components/integrations/header';
import { IntegrationCapabilites } from '@site/src/components/integrations/widgets';
import {IntegrationSecrets} from '@site/src/components/integrations/secrets';
@@ -25,10 +24,6 @@ This integration is read-only, meaning Homarr does not modify or manage cluster
![Dashboard](img/dashboard.jpeg)
### Data
<IntegrationData integration={kubernetesIntegration} />
### Prerequisites
Before deploying Homarr in Kubernetes, ensure the following prerequisites are met:
@@ -6,5 +6,4 @@ export const kubernetesIntegration: IntegrationDefinition = {
"Kubernetes is a powerful container orchestration platform that automates the deployment, scaling, and management of containerized applications.",
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/kubernetes.svg",
path: "../../integrations/kubernetes",
data: "Fetches Kubernetes cluster information including pods, deployments, and services.",
};
@@ -4,7 +4,6 @@ description: "Lidarr is a music management tool that automates the process of do
hide_title: true
---
import { IntegrationData } from '@site/src/components/integrations/data';
import { IntegrationHeader } from '@site/src/components/integrations/header';
import { IntegrationCapabilites } from '@site/src/components/integrations/widgets';
import { AddingIntegration } from '@site/src/components/integrations/adding';
@@ -19,10 +18,6 @@ import { calendarWidget } from '@site/docs/widgets/calendar';
categories={['Media manager', "Servarr"]}
/>
### Data
<IntegrationData integration={lidarrIntegration} />
### Widgets & Capabilities
<IntegrationCapabilites
items={[{
@@ -6,5 +6,4 @@ export const lidarrIntegration: IntegrationDefinition = {
"Lidarr is a music management tool that automates the process of downloading, sorting, and renaming music.",
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/lidarr.svg",
path: "../../integrations/lidarr",
data: "Fetches music album release calendar events from Lidarr.",
};
@@ -1,39 +0,0 @@
---
title: 'LinuxServer.io'
description: "LinuxServer.io is a platform for managing and deploying containerized applications."
hide_title: true
---
import { IntegrationData } from '@site/src/components/integrations/data';
import { IntegrationHeader } from '@site/src/components/integrations/header';
import { IntegrationCapabilites } from '@site/src/components/integrations/widgets';
import { AddingIntegration } from '@site/src/components/integrations/adding';
import { IntegrationSecrets } from '@site/src/components/integrations/secrets';
import { linuxServerIoIntegration } from '.';
import { releasesWidget } from '@site/docs/widgets/releases';
<IntegrationHeader
integration={linuxServerIoIntegration}
categories={['Container Management', 'Software']}
/>
### Data
<IntegrationData integration={linuxServerIoIntegration} />
### Widgets & Capabilities
<IntegrationCapabilites
items={[{
widget: releasesWidget
}]}
/>
### Adding the integration
<AddingIntegration />
### Secrets
<IntegrationSecrets secrets={[{
credentials: [],
steps: []
}]} />
@@ -1,9 +0,0 @@
import { IntegrationDefinition } from "@site/src/types";
export const linuxServerIoIntegration: IntegrationDefinition = {
name: "LinuxServer.io",
description: "LinuxServer.io is a platform for managing and deploying containerized applications.",
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons@master/svg/linuxserver-io.svg",
path: "../../integrations/linux-server-io",
data: "Fetches Docker image versions and changelogs from LinuxServer.io.",
};
@@ -4,7 +4,6 @@ description: "Navidrome is a self-hosted music server and streamer compatible wi
hide_title: true
---
import { IntegrationData } from '@site/src/components/integrations/data';
import { IntegrationHeader } from '@site/src/components/integrations/header';
import { IntegrationCapabilites } from '@site/src/components/integrations/widgets';
import { AddingIntegration } from '@site/src/components/integrations/adding';
@@ -20,10 +19,6 @@ import { audioStatsWidget } from '@site/docs/widgets/audio-stats';
Navidrome provides music library statistics including artist, album, and song counts, as well as now playing information via the Subsonic API.
### Data
<IntegrationData integration={navidromeIntegration} />
### Widgets & Capabilities
<IntegrationCapabilites
items={[
@@ -5,5 +5,4 @@ export const navidromeIntegration: IntegrationDefinition = {
description: "Navidrome is a self-hosted music server and streamer compatible with the Subsonic API.",
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/navidrome.svg",
path: "../../integrations/navidrome",
data: "Fetches library statistics and currently playing tracks from a Navidrome music server.",
};
@@ -4,7 +4,6 @@ description: "Nextcloud is a self-hosted productivity platform that provides fil
hide_title: true
---
import { IntegrationData } from '@site/src/components/integrations/data';
import { IntegrationHeader } from '@site/src/components/integrations/header';
import { IntegrationCapabilites } from '@site/src/components/integrations/widgets';
import { AddingIntegration } from '@site/src/components/integrations/adding';
@@ -20,10 +19,6 @@ import { notificationsWidget } from '@site/docs/widgets/notifications';
categories={['Calendar', 'Notifications']}
/>
### Data
<IntegrationData integration={nextcloudIntegration} />
### Widgets & Capabilities
<IntegrationCapabilites
items={[
@@ -6,5 +6,4 @@ export const nextcloudIntegration: IntegrationDefinition = {
"Nextcloud is a self-hosted productivity platform that provides file storage, collaboration tools, and more.",
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/nextcloud.svg",
path: "../../integrations/nextcloud",
data: "Fetches calendar events and notifications from a Nextcloud instance.",
};
-39
View File
@@ -1,39 +0,0 @@
---
title: 'NPM'
description: "NPM is a package manager for the JavaScript programming language, primarily used for managing Node.js packages."
hide_title: true
---
import { IntegrationData } from '@site/src/components/integrations/data';
import { IntegrationHeader } from '@site/src/components/integrations/header';
import { IntegrationCapabilites } from '@site/src/components/integrations/widgets';
import { AddingIntegration } from '@site/src/components/integrations/adding';
import { IntegrationSecrets } from '@site/src/components/integrations/secrets';
import { npmIntegration } from '.';
import { releasesWidget } from '@site/docs/widgets/releases';
<IntegrationHeader
integration={npmIntegration}
categories={['Package Management', 'Software']}
/>
### Data
<IntegrationData integration={npmIntegration} />
### Widgets & Capabilities
<IntegrationCapabilites
items={[{
widget: releasesWidget
}]}
/>
### Adding the integration
<AddingIntegration />
### Secrets
<IntegrationSecrets secrets={[{
credentials: [],
steps: []
}]} />
-10
View File
@@ -1,10 +0,0 @@
import { IntegrationDefinition } from "@site/src/types";
export const npmIntegration: IntegrationDefinition = {
name: "NPM",
description:
"NPM is a package manager for the JavaScript programming language, primarily used for managing Node.js packages.",
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/npm.svg",
path: "../../integrations/npm",
data: "Fetches the latest npm package version and metadata from the npm registry.",
};
@@ -6,7 +6,6 @@ hide_title: true
import { notificationsWidget } from '@site/docs/widgets/notifications';
import { AddingIntegration } from '@site/src/components/integrations/adding';
import { IntegrationData } from '@site/src/components/integrations/data';
import { IntegrationHeader } from '@site/src/components/integrations/header';
import { IntegrationSecrets } from '@site/src/components/integrations/secrets';
import { IntegrationCapabilites } from '@site/src/components/integrations/widgets';
@@ -18,10 +17,6 @@ import { ntfyIntegration } from '.';
categories={['Notifications', 'Messaging']}
/>
### Data
<IntegrationData integration={ntfyIntegration} />
### Widgets & Capabilities
<IntegrationCapabilites
items={[{
@@ -6,5 +6,4 @@ export const ntfyIntegration: IntegrationDefinition = {
"Ntfy is a simple, open-source notification service that allows you to send and receive notifications across devices.",
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/ntfy.svg",
path: "../../integrations/ntfy",
data: "Fetches recent push notifications from an ntfy.sh topic.",
};
@@ -4,7 +4,6 @@ description: "NZBGet is a lightweight and efficient Usenet downloader."
hide_title: true
---
import { IntegrationData } from '@site/src/components/integrations/data';
import { IntegrationHeader } from '@site/src/components/integrations/header';
import { IntegrationCapabilites } from '@site/src/components/integrations/widgets';
import { AddingIntegration } from '@site/src/components/integrations/adding';
@@ -20,10 +19,6 @@ import { downloadsWidget } from '@site/docs/widgets/downloads';
categories={['Usenet client']}
/>
### Data
<IntegrationData integration={nzbgetIntegration} />
### Widgets & Capabilities
<IntegrationCapabilites
items={[{
@@ -4,5 +4,4 @@ export const nzbgetIntegration: IntegrationDefinition = {
description: "NZBGet is a lightweight and efficient Usenet downloader.",
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/nzbget.svg",
path: "../../integrations/nzbget",
data: "Manages and monitors NZBGet usenet downloads including queue, history, and pause/resume/delete actions.",
};
@@ -4,7 +4,6 @@ description: "Open Media Vault is a free network-attached storage server based o
hide_title: true
---
import { IntegrationData } from '@site/src/components/integrations/data';
import { IntegrationHeader } from '@site/src/components/integrations/header';
import { IntegrationCapabilites } from '@site/src/components/integrations/widgets';
import { AddingIntegration } from '@site/src/components/integrations/adding';
@@ -20,10 +19,6 @@ import { systemResourcesWidget } from '@site/docs/widgets/system-resources';
categories={['System monitoring']}
/>
### Data
<IntegrationData integration={openMediaVaultIntegration} />
### Widgets & Capabilities
<IntegrationCapabilites
items={[{
@@ -4,5 +4,4 @@ export const openMediaVaultIntegration: IntegrationDefinition = {
description: "Open Media Vault is a free network-attached storage server based on the Debian operating system.",
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/openmediavault.svg",
path: "../../integrations/open-media-vault",
data: "Fetches system health data including CPU, memory, filesystem, SMART status, and CPU temperature from OpenMediaVault.",
};
@@ -4,7 +4,6 @@ description: "OPNsense is an open-source, easy-to-use, and easy-to-build firewal
hide_title: true
---
import { IntegrationData } from '@site/src/components/integrations/data';
import { IntegrationHeader } from '@site/src/components/integrations/header';
import { IntegrationCapabilites } from '@site/src/components/integrations/widgets';
import { AddingIntegration } from '@site/src/components/integrations/adding';
@@ -19,10 +18,6 @@ import { firewallWidget } from '../../widgets/firewall';
categories={['Firewall']}
/>
### Data
<IntegrationData integration={opnsenseIntegration} />
### Widgets & Capabilities
<IntegrationCapabilites
items={[{
@@ -4,5 +4,4 @@ export const opnsenseIntegration: IntegrationDefinition = {
description: "OPNsense is an open-source, easy-to-use, and easy-to-build firewall and routing platform",
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/opnsense.svg",
path: "../../integrations/opnsense",
data: "Fetches firewall summary data including version, interface traffic, memory, and CPU usage from OPNsense.",
};
@@ -4,7 +4,6 @@ description: "Overseerr is a self-hosted media request management system that in
hide_title: true
---
import { IntegrationData } from '@site/src/components/integrations/data';
import { IntegrationHeader } from '@site/src/components/integrations/header';
import { IntegrationCapabilites } from '@site/src/components/integrations/widgets';
import { AddingIntegration } from '@site/src/components/integrations/adding';
@@ -20,10 +19,6 @@ import { mediaRequestStatsWidget } from '@site/docs/widgets/media-request-stats'
categories={['Media requests']}
/>
### Data
<IntegrationData integration={overseerrIntegration} />
### Widgets & Capabilities
<IntegrationCapabilites
items={[{
@@ -4,5 +4,4 @@ export const overseerrIntegration: IntegrationDefinition = {
description: "Overseerr is a self-hosted media request management system that integrates with Plex.",
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/overseerr.svg",
path: "../../integrations/overseerr",
data: "Fetches media requests, search results, and user information from Overseerr with approve/decline actions.",
};
@@ -4,7 +4,6 @@ description: "Paperless-ngx is a document management system that transforms your
hide_title: true
---
import { IntegrationData } from '@site/src/components/integrations/data';
import { IntegrationHeader } from '@site/src/components/integrations/header';
import { IntegrationCapabilites } from '@site/src/components/integrations/widgets';
import { AddingIntegration } from '@site/src/components/integrations/adding';
@@ -20,10 +19,6 @@ import { paperlessNgxWidget } from '@site/docs/widgets/paperless-ngx';
Paperless-ngx provides document statistics including total documents, inbox count, correspondents, tags, and document types.
### Data
<IntegrationData integration={paperlessNgxIntegration} />
### Widgets & Capabilities
<IntegrationCapabilites
items={[
@@ -6,5 +6,4 @@ export const paperlessNgxIntegration: IntegrationDefinition = {
"Paperless-ngx is a document management system that transforms your physical documents into a searchable online archive.",
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/paperless-ngx.svg",
path: "../../integrations/paperless-ngx",
data: "Fetches document statistics including total documents, inbox count, tags, correspondents, and document types.",
};
@@ -4,7 +4,6 @@ description: 'A tiny dashboard for Network UPS Tools (NUT) servers.'
hide_title: true
---
import { IntegrationData } from '@site/src/components/integrations/data';
import { IntegrationHeader } from '@site/src/components/integrations/header';
import { IntegrationCapabilites } from '@site/src/components/integrations/widgets';
import { AddingIntegration } from '@site/src/components/integrations/adding';
@@ -20,10 +19,6 @@ import { upsWidget } from '@site/docs/widgets/ups';
[PeaNUT](https://github.com/Brandawg93/PeaNUT) exposes the data of your [Network UPS Tools](https://networkupstools.org/) servers
over a REST API, which Homarr reads to display the status of your UPS devices.
### Data
<IntegrationData integration={peaNutIntegration} />
### Widgets & Capabilities
<IntegrationCapabilites
items={[{
@@ -5,5 +5,4 @@ export const peaNutIntegration: IntegrationDefinition = {
description: "A tiny dashboard for Network UPS Tools (NUT) servers.",
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/peanut.svg",
path: "../../integrations/peanut",
data: "Fetches UPS device summaries including battery charge, runtime, load, and voltage from PeaNut (NUT).",
};
@@ -4,7 +4,6 @@ description: "Pi-hole is a network-wide ad blocker that acts as a DNS sinkhole,
hide_title: true
---
import { IntegrationData } from '@site/src/components/integrations/data';
import { IntegrationHeader } from '@site/src/components/integrations/header';
import { IntegrationCapabilites } from '@site/src/components/integrations/widgets';
import { AddingIntegration } from '@site/src/components/integrations/adding';
@@ -25,10 +24,6 @@ import { piHoleIntegration } from '.';
Homarr supports both Pi-hole v5 and v6. It automatically detects the version and uses the correct API.
</Alert>
### Data
<IntegrationData integration={piHoleIntegration} />
### Widgets & Capabilities
<IntegrationCapabilites
items={[{
@@ -6,5 +6,4 @@ export const piHoleIntegration: IntegrationDefinition = {
"Pi-hole is a network-wide ad blocker that acts as a DNS sinkhole, blocking unwanted content and improving your browsing experience.",
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/pi-hole.svg",
path: "../../integrations/pi-hole",
data: "Fetches DNS query statistics and blocking status from Pi-hole with enable/disable support (auto-detects v5 vs v6).",
};
@@ -4,7 +4,6 @@ description: "Plex is a media server platform that allows you to organize, manag
hide_title: true
---
import { IntegrationData } from '@site/src/components/integrations/data';
import { IntegrationHeader } from '@site/src/components/integrations/header';
import { IntegrationCapabilites } from '@site/src/components/integrations/widgets';
import { AddingIntegration } from '@site/src/components/integrations/adding';
@@ -20,10 +19,6 @@ import { mediaReleasesWidget } from '@site/docs/widgets/media-releases';
categories={['Media server']}
/>
### Data
<IntegrationData integration={plexIntegration} />
### Widgets & Capabilities
<IntegrationCapabilites
items={[
@@ -5,5 +5,4 @@ export const plexIntegration: IntegrationDefinition = {
"Plex is a media server platform that allows you to organize, manage, and stream your personal media collection.",
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/plex.svg",
path: "../../integrations/plex",
data: "Fetches active streams and recently added media from a Plex Media Server.",
};
@@ -4,7 +4,6 @@ description: "Prowlarr is an indexer manager for Usenet and BitTorrent, providin
hide_title: true
---
import { IntegrationData } from '@site/src/components/integrations/data';
import { IntegrationHeader } from '@site/src/components/integrations/header';
import { IntegrationCapabilites } from '@site/src/components/integrations/widgets';
import { AddingIntegration } from '@site/src/components/integrations/adding';
@@ -18,10 +17,6 @@ import { indexerManagerWidget } from '@site/docs/widgets/indexer-manager';
categories={['Indexer']}
/>
### Data
<IntegrationData integration={prowlarrIntegration} />
### Widgets & Capabilities
<IntegrationCapabilites
items={[{ widget: indexerManagerWidget }]}
@@ -5,5 +5,4 @@ export const prowlarrIntegration: IntegrationDefinition = {
"Prowlarr is an indexer manager for Usenet and BitTorrent, providing a unified interface to manage your indexers.",
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons@master/svg/prowlarr.svg",
path: "../../integrations/prowlarr",
data: "Fetches indexer status and health from Prowlarr with test-all-indexers support.",
};
@@ -4,7 +4,6 @@ description: "Proxmox is a powerful open-source virtualization platform that all
hide_title: true
---
import { IntegrationData } from '@site/src/components/integrations/data';
import { IntegrationHeader } from '@site/src/components/integrations/header';
import { IntegrationCapabilites } from '@site/src/components/integrations/widgets';
import { AddingIntegration } from '@site/src/components/integrations/adding';
@@ -20,10 +19,6 @@ import { systemResourcesWidget } from '@site/docs/widgets/system-resources';
categories={['System monitoring']}
/>
### Data
<IntegrationData integration={proxmoxIntegration} />
### Widgets & Capabilities
<IntegrationCapabilites
items={[
@@ -5,5 +5,4 @@ export const proxmoxIntegration: IntegrationDefinition = {
"Proxmox is a powerful open-source virtualization platform that allows you to run virtual machines and containers.",
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/proxmox.svg",
path: "../../integrations/proxmox",
data: "Fetches Proxmox cluster resources including nodes, VMs, containers, and storage information.",
};
@@ -4,7 +4,6 @@ description: "qBittorrent is a free and open-source BitTorrent client."
hide_title: true
---
import { IntegrationData } from '@site/src/components/integrations/data';
import { IntegrationHeader } from '@site/src/components/integrations/header';
import { IntegrationCapabilites } from '@site/src/components/integrations/widgets';
import { AddingIntegration } from '@site/src/components/integrations/adding';
@@ -20,10 +19,6 @@ import { downloadsWidget } from '@site/docs/widgets/downloads';
categories={['Torrent client']}
/>
### Data
<IntegrationData integration={qBittorentIntegration} />
### Widgets & Capabilities
<IntegrationCapabilites
items={[{ widget: downloadsWidget }]}
@@ -4,5 +4,4 @@ export const qBittorentIntegration: IntegrationDefinition = {
description: "qBittorrent is a free and open-source BitTorrent client.",
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/qbittorrent.svg",
path: "../../integrations/q-bittorent",
data: "Manages and monitors qBittorrent torrents including progress, speeds, and pause/resume/delete actions.",
};
@@ -1,42 +0,0 @@
---
title: 'Quay'
description: "Quay is a container registry for storing and managing container images."
hide_title: true
---
import { IntegrationData } from '@site/src/components/integrations/data';
import { IntegrationHeader } from '@site/src/components/integrations/header';
import { IntegrationCapabilites } from '@site/src/components/integrations/widgets';
import { AddingIntegration } from '@site/src/components/integrations/adding';
import { IntegrationSecrets } from '@site/src/components/integrations/secrets';
import { quayIntegration } from '.';
import { releasesWidget } from '@site/docs/widgets/releases';
<IntegrationHeader
integration={quayIntegration}
categories={['Container Registry', 'Software']}
/>
### Data
<IntegrationData integration={quayIntegration} />
### Widgets & Capabilities
<IntegrationCapabilites
items={[{
widget: releasesWidget
}]}
/>
### Adding the integration
<AddingIntegration />
### Secrets
<IntegrationSecrets secrets={[{
credentials: [],
steps: []
}, {
credentials: ["personalAccessToken"],
steps: []
}]} />
@@ -1,9 +0,0 @@
import { IntegrationDefinition } from "@site/src/types";
export const quayIntegration: IntegrationDefinition = {
name: "Quay",
description: "Quay is a container registry for storing and managing container images.",
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons@master/png/quay.png",
path: "../../integrations/quay",
data: "Fetches container image tags and repository metadata from a Quay.io registry.",
};
@@ -4,7 +4,6 @@ description: "Radarr is a movie management tool that automates the process of do
hide_title: true
---
import { IntegrationData } from '@site/src/components/integrations/data';
import { IntegrationHeader } from '@site/src/components/integrations/header';
import { IntegrationCapabilites } from '@site/src/components/integrations/widgets';
import { AddingIntegration } from '@site/src/components/integrations/adding';
@@ -19,10 +18,6 @@ import { calendarWidget } from '@site/docs/widgets/calendar';
categories={['Media manager', "Servarr"]}
/>
### Data
<IntegrationData integration={radarrIntegration} />
### Widgets & Capabilities
<IntegrationCapabilites
items={[{ widget: calendarWidget }]}
@@ -5,5 +5,4 @@ export const radarrIntegration: IntegrationDefinition = {
"Radarr is a movie management tool that automates the process of downloading, sorting, and renaming movies.",
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/radarr.svg",
path: "../../integrations/radarr",
data: "Fetches movie release calendar events including in-cinemas, physical, and digital release dates.",
};
@@ -4,7 +4,6 @@ description: "Readarr is a book management tool that automates the process of do
hide_title: true
---
import { IntegrationData } from '@site/src/components/integrations/data';
import { IntegrationHeader } from '@site/src/components/integrations/header';
import { IntegrationCapabilites } from '@site/src/components/integrations/widgets';
import { AddingIntegration } from '@site/src/components/integrations/adding';
@@ -19,10 +18,6 @@ import { calendarWidget } from '@site/docs/widgets/calendar';
categories={['Media manager', "Servarr"]}
/>
### Data
<IntegrationData integration={readarrIntegration} />
### Widgets & Capabilities
<IntegrationCapabilites
items={[{ widget: calendarWidget }]}
@@ -5,5 +5,4 @@ export const readarrIntegration: IntegrationDefinition = {
"Readarr is a book management tool that automates the process of downloading, sorting, and renaming books.",
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/readarr.svg",
path: "../../integrations/readarr",
data: "Fetches book release calendar events from Readarr.",
};
@@ -4,7 +4,6 @@ description: "SABnzbd is an Open Source Binary Newsreader."
hide_title: true
---
import { IntegrationData } from '@site/src/components/integrations/data';
import { IntegrationHeader } from '@site/src/components/integrations/header';
import { IntegrationCapabilites } from '@site/src/components/integrations/widgets';
import { AddingIntegration } from '@site/src/components/integrations/adding';
@@ -20,10 +19,6 @@ import { downloadsWidget } from '@site/docs/widgets/downloads';
categories={['Usenet client']}
/>
### Data
<IntegrationData integration={sabnzbdIntegration} />
### Widgets & Capabilities
<IntegrationCapabilites
items={[{ widget: downloadsWidget}]}
@@ -4,5 +4,4 @@ export const sabnzbdIntegration: IntegrationDefinition = {
description: "SABnzbd is an Open Source Binary Newsreader.",
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/sabnzbd.svg",
path: "../../integrations/sabnzbd",
data: "Manages and monitors SABnzbd usenet downloads including queue, history, and pause/resume/delete actions.",
};
@@ -1,33 +0,0 @@
---
title: 'Search.ch'
description: "Search.ch supports searching for timetables in Switzerland."
hide_title: true
---
import { IntegrationData } from '@site/src/components/integrations/data';
import { IntegrationHeader } from '@site/src/components/integrations/header';
import { IntegrationCapabilites } from '@site/src/components/integrations/widgets';
import { AddingIntegration } from '@site/src/components/integrations/adding';
import { IntegrationSecrets } from '@site/src/components/integrations/secrets';
import { IconDownload } from "@tabler/icons-react";
import { searchChIntegration } from '.';
import Alert from '@theme/Admonition';
import { timetableWidget } from '@site/docs/widgets/timetable';
<IntegrationHeader
integration={searchChIntegration}
categories={['Timetable']}
/>
### Data
<IntegrationData integration={searchChIntegration} />
### Widgets & Capabilities
<IntegrationCapabilites
items={[{ widget: timetableWidget }]}
/>
### Adding the integration
<AddingIntegration />
@@ -1,8 +0,0 @@
import { IntegrationDefinition } from "@site/src/types";
export const searchChIntegration: IntegrationDefinition = {
name: "Search.ch",
description: "Search.ch supports searching for timetables in Switzerland.",
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/png/search-ch.png",
path: "../../integrations/search-ch",
data: "Fetches Swiss public transport station information and departure timetables from search.ch.",
};
@@ -4,7 +4,6 @@ description: "Seerr is a self-hosted media request management system that integr
hide_title: true
---
import { IntegrationData } from '@site/src/components/integrations/data';
import { IntegrationHeader } from '@site/src/components/integrations/header';
import { IntegrationCapabilites } from '@site/src/components/integrations/widgets';
import { AddingIntegration } from '@site/src/components/integrations/adding';
@@ -20,10 +19,6 @@ import { mediaRequestStatsWidget } from '@site/docs/widgets/media-request-stats'
categories={['Media requests']}
/>
### Data
<IntegrationData integration={seerrIntegration} />
### Widgets & Capabilities
<IntegrationCapabilites
items={[{
@@ -4,5 +4,4 @@ export const seerrIntegration: IntegrationDefinition = {
description: "Seerr is a self-hosted media request management system that integrates with various media servers.",
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/seerr.svg",
path: "../../integrations/seerr",
data: "Fetches media requests, search results, and user information from Seerr (Overseerr-compatible API).",
};
Loaded 100 of 464 files, more files were not shown because too many files have changed in this diff. Show more