docs: migrate documentation to Fumadocs

This commit is contained in:
ajnart committed 2026-09-10 20:33:21 +02:00
1 parent 6db26a0d99
commit 2356fc56f7
257 files changed
+6024 -11022

No files matched your search

+2 -2
View File
@@ -1,6 +1,6 @@
---
name: documentation-sync
description: Keep Homarr's Docusaurus documentation aligned with user-facing code. Use when adding or changing integrations, widgets, APIs, environment variables, CLI commands, authentication, permissions, cron jobs, settings, or UI behavior that users must understand.
description: Keep Homarr's Fumadocs documentation aligned with user-facing code. Use when adding or changing integrations, widgets, APIs, environment variables, CLI commands, authentication, permissions, cron jobs, settings, or UI behavior that users must understand.
---
# Documentation Sync
@@ -48,4 +48,4 @@ For a widget:
2. Keep names, defaults, paths, screenshots, links, and prerequisites consistent with code.
3. Update every affected page and remove superseded guidance.
4. Run the narrowest useful docs validation. Use `pnpm turbo build --filter=@homarr/docs` when links, MDX, generated definitions, or navigation can fail; otherwise run the docs package formatter on touched files.
5. Treat broken links and anchors as failures; Docusaurus checks them strictly.
5. Treat broken links and anchors as failures; run `pnpm --filter @homarr/docs validate:links` after the static build.
+1 -1
View File
@@ -42,7 +42,7 @@ jobs:
- name: Upload pages artifact
uses: actions/upload-pages-artifact@v5
with:
path: "apps/docs/build"
path: "apps/docs/out"
deploy:
runs-on: ubuntu-latest
@@ -1,58 +0,0 @@
name: "[Docs] Algolia Recrawl"
on:
workflow_run:
workflows: ["[Deployment] Documentation"]
types: [completed]
branches: [dev]
workflow_dispatch:
permissions:
contents: read
jobs:
recrawl:
if: >-
${{
(github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.event != 'pull_request')
|| github.event_name == 'workflow_dispatch'
}}
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v7
- name: Setup
uses: ./tooling/github/setup
- name: Check Algolia crawler secrets
run: |
missing=0
for secret in ALGOLIA_CRAWLER_ID ALGOLIA_CRAWLER_USER_ID ALGOLIA_CRAWLER_API_KEY; do
if [ -z "${!secret}" ]; then
echo "::warning::Missing repository secret: $secret"
missing=1
fi
done
if [ "$missing" -eq 1 ]; then
echo "Add crawler secrets to enable automatic recrawls."
exit 1
fi
env:
ALGOLIA_CRAWLER_ID: ${{ secrets.ALGOLIA_CRAWLER_ID }}
ALGOLIA_CRAWLER_USER_ID: ${{ secrets.ALGOLIA_CRAWLER_USER_ID }}
ALGOLIA_CRAWLER_API_KEY: ${{ secrets.ALGOLIA_CRAWLER_API_KEY }}
- name: Wait for GitHub Pages to serve the new deployment
run: sleep 60
- name: Trigger Algolia DocSearch recrawl
uses: cssnr/algolia-crawler-action@v2
with:
crawler_id: ${{ secrets.ALGOLIA_CRAWLER_ID }}
crawler_user_id: ${{ secrets.ALGOLIA_CRAWLER_USER_ID }}
crawler_api_key: ${{ secrets.ALGOLIA_CRAWLER_API_KEY }}
- name: Verify search index
working-directory: apps/docs
run: pnpm verify:search
@@ -33,7 +33,7 @@ jobs:
- name: Commit updated contributors
uses: EndBug/add-and-commit@v10
with:
add: "apps/docs/static"
add: "apps/docs/public"
default_author: github_actor
message: "chore(docs): update contributors"
push: true
+2 -2
View File
@@ -54,13 +54,13 @@ jobs:
exit 1
}
cp /tmp/openapi.json apps/docs/static/api/open-api-schema.json
cp /tmp/openapi.json apps/docs/public/api/open-api-schema.json
echo "OpenAPI spec updated ($(jq '.paths | length' /tmp/openapi.json) paths)"
- name: Commit updated spec
uses: EndBug/add-and-commit@v10
with:
add: "apps/docs/static/api/"
add: "apps/docs/public/api/"
default_author: github_actor
message: "chore(docs): update OpenAPI spec"
push: true
+3 -3
View File
@@ -6,7 +6,7 @@
homarr/
├── apps/
│ ├── nextjs/ # Main Next.js application (port 3000)
│ ├── docs/ # Docusaurus 3 documentation site (@homarr/docs)
│ ├── docs/ # Next.js + Fumadocs documentation site (@homarr/docs)
│ ├── tasks/ # Cron-job initialization and scheduling runtime
│ ├── websocket/ # Standalone tRPC WebSocket server (port 3001)
│ └── workshop/ # Go/PocketBase Workshop service
@@ -57,7 +57,7 @@ homarr/
## Documentation Sync
The documentation site lives at `apps/docs/` (Docusaurus 3, `@homarr/docs`).
The documentation site lives at `apps/docs/` (Next.js + Fumadocs, `@homarr/docs`).
When modifying user-facing code, you MUST also update the corresponding documentation:
@@ -75,7 +75,7 @@ When modifying user-facing code, you MUST also update the corresponding document
- `pnpm dev:cli -- dev` — run the developer CLI without installing a global binary
- `pnpm db:seed` — seed default database data explicitly
- `pnpm docker:dev:up` — start the Redis development service in the background
- `pnpm dev:docs` — Docusaurus docs site only
- `pnpm dev:docs` — Fumadocs site only
- `pnpm turbo build` — build all packages
- `pnpm turbo build --filter=@homarr/docs` — build docs only
- `pnpm turbo typecheck` — typecheck all packages
+2 -1
View File
@@ -13,6 +13,7 @@
# next.js
/.next/
/out/
/.source/
# production
/build
@@ -55,4 +56,4 @@ static/data/configs
# CI Stuff
screenshots
test-results
test-results
+9
View File
@@ -0,0 +1,9 @@
<!-- BEGIN:nextjs-agent-rules -->
# This is NOT the Next.js you know
This version has breaking changes — APIs, conventions, and file structure may all differ from your training data. Read the relevant guide in `node_modules/next/dist/docs/` (resolved from this file's directory; in monorepos the `next` package may not be visible from the repo root) before writing any code. Heed deprecation notices.
This block is written and re-added by `next dev` — verify at `node_modules/next/dist/server/lib/generate-agent-files.js`. Removing it from a diff only re-creates the uncommitted change; committing it with your work keeps the tree clean.
<!-- END:nextjs-agent-rules -->
+1
View File
@@ -0,0 +1 @@
@AGENTS.md
+37
View File
@@ -0,0 +1,37 @@
# Homarr Documentation
## Register
product
## Users
People who run Homarr, administrators configuring self-hosted infrastructure, and contributors extending Homarr. They arrive with a concrete task such as installing Homarr, connecting a service, configuring a widget, managing users, or building a custom widget, and need an answer they can scan and apply quickly.
## Product Purpose
The documentation is the complete, authoritative operating guide for Homarr. It keeps setup steps, configuration contracts, screenshots, generated integration and widget metadata, API references, and Workshop tooling next to the application code. Success means a reader can find the right page quickly, understand the next action, copy reliable instructions, and verify the result without searching elsewhere.
## Brand Personality
Focused, dependable, and approachable. The writing is direct and practical. The interface should feel calm and familiar during long technical sessions while retaining Homarr's red identity.
## Anti-references
- Generic marketing layouts that replace Homarr's product identity with unrelated slogans or decorative conversion copy.
- Decorative dashboard aesthetics that compete with reading, including glass effects, large radii, card grids, and gratuitous motion.
- Generic generated-docs styling that obscures Homarr's identity or makes navigation feel detached from the main product.
- Dense reference portals that expose structure without giving readers a clear path through a task.
## Design Principles
1. Put the reader's task first: search, navigation, page outline, and the answer must remain easy to reach.
2. Preserve one source of truth: typed Homarr metadata and existing custom components stay connected to the monorepo.
3. Prefer familiar documentation patterns: the interface should disappear while a reader scans, copies, and follows instructions.
4. Make complete content feel manageable through strong hierarchy, progressive disclosure, and precise cross-links.
5. Treat machine readers as users through canonical Markdown, structured metadata, and standard LLM discovery endpoints.
6. Keep the root landing page recognizably Homarr: preserve its self-hosted dashboard promise and real product evidence while documentation routes remain task-first.
## Accessibility & Inclusion
Meet WCAG 2.2 AA for color contrast, keyboard operation, focus visibility, landmarks, headings, and interactive controls. Respect reduced-motion and system color-scheme preferences. Diagrams, screenshots, icons, and emoji must have meaningful text alternatives when they carry information.
+30 -90
View File
@@ -1,112 +1,52 @@
# Homarr Documentation (`@homarr/docs`)
# Homarr documentation (`@homarr/docs`)
The official [homarr.dev](https://homarr.dev) documentation site, built with [Docusaurus 3](https://docusaurus.io/) and living inside the Homarr monorepo.
The source for [homarr.dev](https://homarr.dev), built with Next.js and Fumadocs UI inside the Homarr monorepo.
## Why it's in the monorepo
## Develop
Having documentation alongside the application code enables:
- **Two-way linking** — the docs app imports from `@homarr/definitions` for type-safe integration/widget metadata, and the main app references doc paths via generated sitemap types
- **Atomic PRs** — code changes and their documentation updates ship in the same pull request
- **Shared tooling** — same Node version, pnpm catalog, oxlint/oxfmt, CI pipeline
- **Build-time validation** — Docusaurus strict mode catches broken links and references at build time
## Development
From the **monorepo root**:
From the repository root:
```bash
# Start the docs dev server (port 3003)
pnpm dev:docs
```
# Or from within this directory
pnpm dev
The site runs on `http://127.0.0.1:3003`. To use a local Workshop API:
# Point the docs at a local PocketBase instance
```bash
WORKSHOP_API_URL=http://127.0.0.1:8090 pnpm dev:docs
```
The standalone docs use `WORKSHOP_API_URL` for PocketBase and `HOMARR_WEBSITE_URL` for the public site origin. The old
`WORKSHOP_URL` name is a deprecated one-release alias.
## Build
## Validate
```bash
# Build docs only
pnpm turbo build --filter=@homarr/docs
# Build everything (docs + main app + tasks + websocket)
pnpm build
pnpm --filter @homarr/docs typecheck
pnpm --filter @homarr/docs build
pnpm --filter @homarr/docs validate:links
```
## Lint & Format
The static export is written to `out/`. The build validates that every registered integration and widget has a docs
page. The link check validates internal Markdown and MDX links against that export.
Uses oxlint and oxfmt (same as the rest of the monorepo):
## Write content
```bash
pnpm lint # oxlint
pnpm format # oxfmt (check)
pnpm format:fix # oxfmt (fix)
```
Documentation lives in `docs/`; project posts live in `blog/`. Navigation is controlled by the nearest `meta.json`.
Integration and widget folders pair typed `index.ts` metadata with `index.mdx` content.
## Typecheck
Use standard Markdown and MDX. Shared components live in `src/components/`. Mermaid fences, tabs, callouts, zoomable
images, and syntax-highlighted code are supported by the Fumadocs pipeline.
```bash
pnpm typecheck
```
When a user-facing change affects setup or behavior, update the matching page in the same pull request. See the
[documentation-sync skill](../../.agents/skills/documentation-sync/SKILL.md) for the code-to-content map.
## Content Structure
## Published formats
```
docs/
├── getting-started/ # Installation guides, glossary, prerequisites
├── management/ # Boards, apps, users, integrations, settings, tasks, API
├── integrations/ # 56 integration guides (one folder each)
├── widgets/ # 43 widget guides (one folder each)
├── advanced/ # SSO, env vars, proxy, styling, CLI, development
└── community/ # FAQ, donate, license, translations, get-in-touch
```
- `/docs` — searchable documentation with typed navigation
- `/api-reference` — interactive reference generated from the OpenAPI schema
- `/llms.txt` — compact documentation and blog index for agents
- `/llms-full.txt` — complete processed Markdown corpus
- `/llms.mdx/docs/.../content.md` — raw Markdown for each docs page
- `/llms.mdx/blog/.../content.md` — raw Markdown for each blog post
- `/blog/rss.xml` — RSS feed for project posts
Each integration/widget doc follows a consistent pattern:
- `index.ts` — typed metadata (`IntegrationDefinition` / `WidgetDefinition`)
- `index.mdx` — content using shared React components (`IntegrationHeader`, `WidgetHeader`, etc.)
## Importing from homarr packages
The docs app has `@homarr/definitions` as a workspace dependency. You can import integration kinds, widget kinds, and other definitions directly:
```typescript
import { IntegrationKind } from "@homarr/definitions";
```
This enables type-safe references to homarr domain concepts within documentation code.
## Search (Algolia DocSearch)
Search uses the `Docusaurus` Algolia index (crawler `cd77a285-2756-4557-bf21-ee703748df15`). A separate `markdown` index is built for LLM markdown indexing.
Crawler reference config: [`docsearch.config.js`](docsearch.config.js).
**Verify search health:**
```bash
pnpm verify:search
```
## Tech Stack
| Layer | Technology |
| -------------- | ------------------------------------------- |
| Site generator | Docusaurus 3 (`@docusaurus/preset-classic`) |
| Styling | Tailwind CSS 4 + Docusaurus Infima |
| Icons | `@tabler/icons-react` |
| Diagrams | Mermaid (`@docusaurus/theme-mermaid`) |
| Search | Algolia DocSearch |
| Analytics | PostHog |
| Charts | @nivo/line |
## Contributing
When a Homarr change affects user-facing behavior, update the corresponding documentation in this app. See the
[documentation-sync skill](../../.agents/skills/documentation-sync/SKILL.md) for the code-to-documentation mapping.
Every docs page and blog post includes copy-Markdown and view-source actions. Search is generated at build time and
runs locally in the browser; it does not depend on an external crawler.
@@ -1,6 +1,7 @@
---
slug: documentation-migration
title: Migration of Documentation
date: 2022-06-22
authors:
- ajnart
- manuel-rw
@@ -12,7 +13,7 @@ The documentation has been re-written partly and includes now many animations, g
We are still figuring things out and highly depend on your feedback.
<!-- truncate -->
{/* Historical excerpt boundary. */}
## Why we migrated
@@ -32,4 +33,4 @@ After we've reviewed your changes, we'll merge your PR and this documentation wi
## TL;DR
The documentation on GitHub Wiki will soon disappear. It will be replaced with this Docusaurus-powered website. You'll find much more information here with higher detail and searchability.
The documentation on GitHub Wiki will soon disappear. It will be replaced with this Docusaurus-powered website. You'll find much more information here with higher detail and searchability.
@@ -1,6 +1,7 @@
---
slug: translations
title: Help us make Homarr multilingual
date: 2022-08-28
authors:
- ajnart
- manuel-rw
@@ -13,8 +14,8 @@ We've been working hard to offer Homarr in many languages. The next update of Ho
![](img/homarr-we-need-you.webp) <br/>
Yes, we need **YOU**! We want to make Homarr accessible to as many people as possible. Thus, we need to translate all content into many different languages. We need your help for that! [You can help us now to translate Homarr into as many languages as possible](/docs/community/translations).
<!-- truncate -->
{/* Historical excerpt boundary. */}
### About global translations / translations per user
We are aware that many people would like to configure translations globally or configure language per user. Currently, translations are stored in the Cookies, which will expire after some time (currently, it's set to 30 days). We will implement more granular language settings in future versions of Homarr, since it requires major changes to Homarr. Stay tuned! 😎
We are aware that many people would like to configure translations globally or configure language per user. Currently, translations are stored in the Cookies, which will expire after some time (currently, it's set to 30 days). We will implement more granular language settings in future versions of Homarr, since it requires major changes to Homarr. Stay tuned! 😎
@@ -1,5 +1,6 @@
---
title: "We present: Homarr 0.11 - the most complex Homarr version yet!"
date: 2023-01-11
authors:
- ajnart
- manuel-rw
@@ -20,7 +21,7 @@ It contains many breaking changes and huge improvements to your favourite dashbo
- Huge design and usability improvements to older components to Homarr
- Better handeling of exceptions and unexpected issues
<!-- truncate -->
{/* Historical excerpt boundary. */}
## Complete implementation of highly customizable drag and drop library "Gridstack"
@@ -1,5 +1,6 @@
---
title: "We present: Homarr 0.12 - The fastest homarr version ever!"
date: 2023-04-16
authors:
- ajnart
- manuel-rw
@@ -15,14 +16,12 @@ This applies to all widgets, but in the case of the IFrame widget, it enables yo
- Integrate monitoring tools like Grafana, Splunk or Elasticsearch
- Integrate your services (for example Sonarr, Radarr and Overseerr) directly into Homarr
![](https://media.discordapp.net/attachments/988335098493542410/1094665745226539168/update-teaser.png?width=1046&height=666)
## Edit mode password
We've added a setting to disable editing completely. This will allow you to restrict edit access without password-protection.
use the `EDIT_MODE_PASSWORD` ENV variable to set a password for edit mode.
turn on `DISABLE_EDIT_MODE=TRUE` to disable edit mode on startup.
<!-- truncate -->
{/* Historical excerpt boundary. */}
## 😎 Blazingly fast
We've implemented a new caching system, that will cache all data in your browser, meaning that Homarr will load within milliseconds, as if it was *powered by rust and blazingly fast* !!!
@@ -72,4 +71,4 @@ Now, you can use the following environment variables to configure this:
- ``DOCKER_HOST``
- ``DOCKER_PORT``
**Full Changelog**: https://github.com/ajnart/homarr/compare/v0.11.5...v0.12.0
**Full Changelog**: https://github.com/ajnart/homarr/compare/v0.11.5...v0.12.0
@@ -1,5 +1,6 @@
---
title: "Authentication in Homarr - 0.14 is here!"
date: 2023-11-10
authors:
- ajnart
- manuel-rw
@@ -23,7 +24,7 @@ provide you a viable solution today.
- 📝 Overhauled notepad widget with a complex graphical editor that enables easy editing right from your browser.
- :globe_with_meridians: Live Translation on Crowdin that enable you to directly translate using images to see what exactly you're translating
<!-- truncate -->
{/* Historical excerpt boundary. */}
## Breaking changes
@@ -83,4 +84,4 @@ We are aware that this update has many breaking changes and may confuse some use
For that reason, we updated our documentation and will enhance it further within the next few weeks.
We've also added this small button at the bottom of the page were you can ask **your questions** to an AI assistant:
![image](https://github.com/ajnart/homarr/assets/30572287/a56f721a-d022-42ad-813a-d85c89462a8c)
![image](https://github.com/ajnart/homarr/assets/30572287/a56f721a-d022-42ad-813a-d85c89462a8c)
@@ -1,5 +1,6 @@
---
title: "Updated documentation with better organization & design"
date: 2023-12-22
authors:
- manuel-rw
tags: [homarr, documentation, design, docs]
@@ -8,7 +9,7 @@ tags: [homarr, documentation, design, docs]
We'd like to let you know that we've updated our documentation and reorganized the pages.
This means, that some links may no longer be valid - we apologise if this causes any inconvenience for you.
<!-- truncate -->
{/* Historical excerpt boundary. */}
A few highlights include:
@@ -18,4 +19,4 @@ A few highlights include:
- Bug fixes for image zoom
- Added documentation for management pages and [new CLI tool](/docs/advanced/command-line/password-recovery/)
Please [let us know](/docs/community/get-in-touch) is something is not working as expected.
Please [let us know](/docs/community/get-in-touch) is something is not working as expected.
@@ -1,9 +1,10 @@
---
title: Homarr 1.0 - complete rewrite of all systems
date: 2024-09-23
authors:
- manuel-rw
---
# Homarr 1.0 - complete rewrite of all systems
We proudly present to you - Homarr ``1.0``.
We have started work on this new version back in 2023 and have worked tirelessly for months on this brand-new dashboard.
@@ -28,7 +29,7 @@ reliability and scalability compared to < ``1.0``.
- **Improved performance**: We have upgraded the underlying framework of Homarr and take advantage
of an in-memory message bus and websockets to deliver data near realtime to you.
<!-- truncate -->
{/* Historical excerpt boundary. */}
## Breaking changes
:::warning
@@ -1,16 +1,16 @@
---
title: Open Beta 1.0
date: 2024-12-17
authors:
- meierschlumpf
---
# Open Beta 1.0
We are proud to announce the open beta of Homarr 1.0. This is a major milestone for us and we are excited to share it with you.
The open beta allows us to polish the last rough edges and gather feedback from you.
We are looking forward to your feedback and hope you enjoy the new features.
Let us know throgh discord or a [github issues](https://github.com/homarr-labs/homarr/issues/new/choose) if you encounter any issues.
<!-- truncate -->
{/* Historical excerpt boundary. */}
## How to use the beta with docker
@@ -36,4 +36,4 @@ services:
Then, run `docker compose up -d` in the same directory. This will start the Homarr container in the background.
Please note that the mounts have changed and it's not backwards compatible with versions before 1.0.0-beta.1.
You can find a list of all breaking changes [here](/blog/2024/09/23/version-1.0)
You can find a list of all breaking changes [here](/blog/2024/09/23/version-1.0)
@@ -1,14 +1,14 @@
---
title: Migrate from 0.15.10+ to 1.0.0
date: 2025-01-19
authors:
- meierschlumpf
---
# Migrate from 0.15.10+ to 1.0.0
In this guide, we will show you how to migrate from Homarr 0.15.10+ to 1.0.0.
If you are still on a version before 0.15.10, please update to 0.15.10 where we introduced the migration export page.
<!-- truncate -->
{/* Historical excerpt boundary. */}
## Preserve your old installation
@@ -1,14 +1,14 @@
---
title: How to use Argus with Homarr
date: 2025-08-02
authors:
- meierschlumpf
---
# How to use Argus with Homarr
In `v1.32.0` we added the endpoint `/api/info` which returns the current version of Homarr and can therefore be used in Argus to watch for updates.
This guide will show you how to set up a user with apiKey to access the endpoint without providing admin access through it.
<!-- truncate -->
{/* Historical excerpt boundary. */}
![Argus](./img/argus.png)
@@ -64,4 +64,4 @@ Now you can configure Argus to use the user and apiKey we created.
![Argus configuration](./img/argus-configuration.png)
Replace the `<secret>` with the apiKey you created and the deployed version url with the url of your Homarr instance.
Replace the `<secret>` with the apiKey you created and the deployed version url with the url of your Homarr instance.
@@ -1,4 +1,6 @@
---
title: Homarr 2.0.0 - Workshop, Custom Widgets and a rebuilt board
date: 2026-09-03
authors:
- ajnart
tags: [homarr, update, version, assistant, custom widgets, dashboards, docker]
@@ -17,7 +19,7 @@ Homarr 2.0 is an upgrade, not a brand-new app wearing the same logo. Here is wha
![A populated Homarr 2.0 dashboard with compact widgets, an Assistant, and an application rail](./img/homarr-v2-dashboard.webp)
<!-- truncate -->
{/* Historical excerpt boundary. */}
:::warning Back up before upgrading
+1 -1
View File
@@ -5,7 +5,7 @@
"tsx": true,
"tailwind": {
"config": "",
"css": "src/css/custom.css",
"css": "src/app/global.css",
"baseColor": "mist",
"cssVariables": true,
"prefix": ""
-9
View File
@@ -1,9 +0,0 @@
{
"label": "Advanced",
"collapsed": true,
"position": 5,
"link": {
"type": "generated-index",
"title": "Advanced Concepts or features"
}
}
@@ -1,4 +0,0 @@
{
"collapsed": true,
"label": "Command line interface"
}
@@ -0,0 +1,4 @@
{
"title": "Command line interface",
"pages": ["index", "users", "integrations", "password-recovery", "fix-usernames", "development"]
}
@@ -1,8 +0,0 @@
{
"label": "Developer guides",
"position": 6,
"collapsed": true,
"link": {
"type": "generated-index"
}
}
@@ -57,8 +57,8 @@ Homarr becomes the instance administrator.
Use `pnpm docker:dev:up` instead when you only need Redis in the background. Running the migration also seeds the
default data; use `pnpm db:seed` to seed it explicitly later.
Workshop contributors can set up PocketBase and Docusaurus with the dedicated
[Workshop development guide](./workshop).
Workshop contributors can set up PocketBase and Fumadocs with the dedicated
[Workshop development guide](/docs/advanced/development/workshop).
### Useful commands
@@ -69,7 +69,7 @@ Workshop contributors can set up PocketBase and Docusaurus with the dedicated
- `pnpm dev:cli -- build --pr <number>` — build a pull request from a temporary checkout.
- `pnpm dev:cli -- rebuild <name>` — rebuild an image from its recorded checkout or pull request.
- `pnpm dev:cli:install` — optionally install the developer CLI as a `homarr` binary.
- `pnpm dev:docs` — Docusaurus only on port 3003.
- `pnpm dev:docs` — Fumadocs on port 3003.
- `pnpm docker:dev:up` — Redis development service in the background.
- `pnpm cli` — Homarr operations CLI.
- `pnpm db:migration:sqlite:run` — create or update a SQLite database.
@@ -0,0 +1,4 @@
{
"title": "Developer guides",
"pages": ["getting-started", "widgets-and-integrations", "kubernetes", "workshop", "workshop-operator"]
}
@@ -4,13 +4,13 @@ sidebar_position: 4
tags:
- Workshop
- Developer
- Docusaurus
- Fumadocs
- PocketBase
---
# Workshop development
See the [main development guide](./getting-started) for repository prerequisites.
See the [main development guide](/docs/advanced/development/getting-started) for repository prerequisites.
Start PocketBase:
@@ -19,7 +19,7 @@ cp apps/workshop/.env.example apps/workshop/.env
docker compose --env-file apps/workshop/.env -f apps/workshop/docker-compose.yml up --build workshop
```
Start Docusaurus in another terminal:
Start Fumadocs in another terminal:
```sh
WORKSHOP_API_URL=http://127.0.0.1:8090 pnpm dev:docs
@@ -139,4 +139,4 @@ The advanced deployments environment variables should only be used if you know w
| `DB_MIGRATIONS_DISABLED` | Disable db migrations. For example for helm charts. |
All public URL variables reject non-HTTP protocols, embedded credentials, query strings, and fragments, and normalize
trailing slashes when Homarr or Docusaurus starts.
trailing slashes when Homarr or the documentation site starts.
+60
View File
@@ -0,0 +1,60 @@
---
title: Advanced configuration
description: Configure deployment, authentication, networking, styling, automation, and development workflows.
---
import {
IconCode,
IconIcons,
IconKey,
IconKeyboard,
IconNetwork,
IconPalette,
IconTerminal2,
IconUserCog,
IconVariable,
} from "@tabler/icons-react";
These guides cover changes that affect how Homarr is deployed, secured, operated, or extended.
## Deploy and secure
<Cards>
<Card icon={<IconVariable />} title="Environment variables" href="/docs/advanced/environment-variables">
Configure Homarr at deployment time.
</Card>
<Card icon={<IconKey />} title="Single sign-on" href="/docs/advanced/single-sign-on">
Connect an external identity provider.
</Card>
<Card icon={<IconNetwork />} title="Proxies and certificates" href="/docs/advanced/proxy">
Run Homarr behind a reverse proxy.
</Card>
<Card icon={<IconUserCog />} title="Run as a different user" href="/docs/advanced/running-as-different-user">
Change the user and group used by the container.
</Card>
</Cards>
## Customize
<Cards>
<Card icon={<IconPalette />} title="Custom styling" href="/docs/advanced/styling">
Apply custom CSS to Homarr.
</Card>
<Card icon={<IconIcons />} title="Icons" href="/docs/advanced/icons">
Configure icon sources and behavior.
</Card>
<Card icon={<IconKeyboard />} title="Keyboard shortcuts" href="/docs/advanced/keyboard-shortcuts">
Navigate and operate Homarr with the keyboard.
</Card>
</Cards>
## Develop and automate
<Cards>
<Card icon={<IconTerminal2 />} title="Command line interface" href="/docs/advanced/command-line">
Use administrative commands from the terminal.
</Card>
<Card icon={<IconCode />} title="Developer guides" href="/docs/advanced/development/getting-started">
Set up a development environment and contribute code.
</Card>
</Cards>
+19
View File
@@ -0,0 +1,19 @@
{
"title": "Advanced",
"defaultOpen": false,
"pages": [
"index",
"---Deploy and secure---",
"environment-variables",
"single-sign-on",
"proxy",
"running-as-different-user",
"---Customize---",
"styling",
"icons",
"keyboard-shortcuts",
"---Develop and automate---",
"command-line",
"development"
]
}
+3 -3
View File
@@ -9,14 +9,14 @@ tags:
- Security
---
import Tabs from "@theme/Tabs";
import TabItem from "@theme/TabItem";
import Tabs from "@/components/mdx/legacy-tabs";
import { TabItem } from "@/components/mdx/legacy-tabs";
## Allowing self-signed certificates
Some users may come across a barrier, where they're unable to receive a 200 response from the Ping widget for some apps, while using self-signed certificates or a local certificate authory.
:::note What's going on?
:::note[What's going on?]
Homarr is trying to communicate to your apps via the integrations.
It usually doesn't matter if Homarr is running on `http` or `https`.
@@ -10,9 +10,6 @@ tags:
- Active Directory
---
import Tabs from "@theme/Tabs";
import TabItem from "@theme/TabItem";
# Single Sign On
Homarr supports multiple authentication options, from internal userbase (credentials), to LDAP (with Active directory support), and OIDC.
@@ -247,7 +244,7 @@ Homarr supports multiple authentication options, from internal userbase (credent
Generate `SECRET_ENCRYPTION_KEY` with `openssl rand -hex 32`; do not copy an example key between installs.
```env
```bash
OIDC_CLIENT_ID=<REPLACE_WITH_OIDC_CLIENT_ID>
OIDC_CLIENT_SECRET=<REPLACE_WITH_OIDC_CLIENT_SECRET>
OIDC_SLUG=homarr #Application slug in Authentik
@@ -326,7 +323,7 @@ Homarr supports multiple authentication options, from internal userbase (credent
Generate `SECRET_ENCRYPTION_KEY` with `openssl rand -hex 32`; do not copy an example key between installs.
```env
```bash
OIDC_CLIENT_ID=<REPLACE_WITH_GOOGLE_CLIENT_ID>
OIDC_CLIENT_SECRET=<REPLACE_WITH_GOOGLE_CLIENT_SECRET>
HOMARR_FQDN=homarr.example.com #Homarr FQDN
-8
View File
@@ -1,8 +0,0 @@
{
"label": "Community",
"position": 6,
"collapsed": true,
"link": {
"type": "generated-index"
}
}
+10
View File
@@ -0,0 +1,10 @@
---
title: Community
description: Get help, contribute to Homarr, and support the project.
---
- [Frequently asked questions](/docs/community/faq): resolve common setup and operation issues.
- [Get in touch](/docs/community/get-in-touch): choose the right support or discussion channel.
- [Translations](/docs/community/translations): improve Homarr in your language.
- [Donate](/docs/community/donate): support ongoing development.
- [License](/docs/community/license): understand how Homarr is licensed.
+5
View File
@@ -0,0 +1,5 @@
{
"title": "Community",
"defaultOpen": false,
"pages": ["index", "faq", "get-in-touch", "translations", "donate", "license"]
}
@@ -1,9 +0,0 @@
{
"label": "Getting started",
"position": 1,
"collapsed": false,
"link": {
"type": "generated-index",
"title": "Getting started"
}
}
@@ -6,11 +6,68 @@ tags:
- Configuration
---
On first launch, onboarding creates the administrator, connects optional services, and builds the first board. A
compatible SQLite backup can also be restored from the welcome screen.
import {
IconAdjustments,
IconChecklist,
IconLayoutDashboard,
IconPlugConnected,
IconSearch,
IconSparkles,
} from "@tabler/icons-react";
If onboarding returns after a restart, check that `/appdata` is writable and persisted. See the
[Docker installation guide](/docs/getting-started/installation/docker).
import onboardingWelcome from "./img/onboarding-v2-welcome.png";
import onboardingBoard from "./img/onboarding-v2-board.png";
import onboardingReview from "./img/onboarding-v2-review.png";
After Homarr starts, open its URL. An unfinished installation redirects to the onboarding screen at `/init`. Choose
**Get started** for a new installation or **Restore backup** to import a compatible SQLite backup.
<Callout type="info" title="Persist /appdata before you continue">
Onboarding writes the administrator and board configuration to the database. If onboarding returns after a restart,
check that `/appdata` is writable and persisted. See the
[Docker installation guide](/docs/getting-started/installation/docker).
</Callout>
## Complete onboarding
Onboarding is split into six short sections. Integrations, Workshop, Assistant, and MCP are optional; skip them when you
only need a working board.
<Cards>
<Card icon={<IconAdjustments />} title="1. Essentials">
Choose the language, theme, usual server address, and anonymous analytics preference.
</Card>
<Card icon={<IconSearch />} title="2. Discover">
Review the database, Docker, Kubernetes, Assistant, and Workshop capabilities Homarr can reach.
</Card>
<Card icon={<IconPlugConnected />} title="3. Connect">
Import detected services or add integrations manually. Unfinished integrations can be skipped.
</Card>
<Card icon={<IconLayoutDashboard />} title="4. Board">
Set the board name, colors, corner radius, column count, and optional sidebars.
</Card>
<Card icon={<IconSparkles />} title="5. Extend">
Optionally connect the Workshop, configure an Assistant provider, or review the MCP endpoint.
</Card>
<Card icon={<IconChecklist />} title="6. Review">
Check the final summary, then build the board. Homarr opens the exact board it configured.
</Card>
</Cards>
The final screen links directly to the new board and the management area. Board layout, integrations, apps, and
appearance can all be changed later.
<Cards>
<Card title="Start or restore">
<img src={onboardingWelcome.src} alt="Homarr onboarding welcome screen with Get started and Restore backup actions" />
</Card>
<Card title="Configure the board">
<img src={onboardingBoard.src} alt="Board onboarding section for colors, columns, corner radius, and sidebars" />
</Card>
<Card title="Review before building">
<img src={onboardingReview.src} alt="Onboarding review showing the board settings Homarr will create" />
</Card>
</Cards>
## Core concepts
@@ -40,7 +97,7 @@ Docker. Integrations provide data and actions to widgets. They can also be linke
![Integration catalog with compatible widgets](./img/after-installation-integrations.png)
See [Managing integrations](/docs/management/integrations) and the
[integration catalog](/docs/category/integrations).
[integration catalog](/docs/integrations).
### Widgets
@@ -49,7 +106,7 @@ supported integrations, and non-obvious limitations are documented on each widge
![Board in edit mode with the add-content menu](./img/after-installation-widgets.png)
See the [widget catalog](/docs/category/widgets).
See the [widget catalog](/docs/widgets).
### Containers and rails
Binary file not shown.

After

Width:  |  Height:  |  Size: 289 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 289 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 368 KiB

@@ -1,9 +0,0 @@
{
"label": "Installation",
"position": 1,
"collapsed": true,
"link": {
"type": "generated-index",
"title": "Getting started"
}
}
@@ -0,0 +1,84 @@
---
title: Install Homarr
description: Choose the installation method that matches your infrastructure.
full: true
---
import {
IconApps,
IconBox,
IconBrandDocker,
IconBrandGithub,
IconCloud,
IconContainer,
IconDatabase,
IconHexagons,
IconHome,
IconLayoutDashboard,
IconServer2,
IconTrain,
} from "@tabler/icons-react";
Docker Compose is the best starting point for most self-hosters. Choose a platform-specific guide when Homarr will run inside an existing server manager or managed service.
<Callout type="idea" title="Not sure which guide to choose?">
Start with **Docker Compose**. It is the recommended path, has the broadest community support, and makes updates and
backups straightforward.
</Callout>
## Recommended
<Cards>
<Card icon={<IconBrandDocker />} title="Docker Compose" href="/docs/getting-started/installation/docker">
The recommended installation for most Linux and Windows servers.
</Card>
<Card icon={<IconHexagons />} title="Kubernetes with Helm" href="/docs/getting-started/installation/helm">
Deploy Homarr into an existing Kubernetes cluster.
</Card>
<Card icon={<IconBrandGithub />} title="Build from source" href="/docs/getting-started/installation/source">
Build and run Homarr directly from the repository.
</Card>
</Cards>
## Self-hosting platforms
<Cards>
<Card icon={<IconServer2 />} title="Unraid" href="/docs/getting-started/installation/unraid">
Install Homarr from the Unraid Community Apps catalog.
</Card>
<Card icon={<IconDatabase />} title="Synology" href="/docs/getting-started/installation/synology">
Run Homarr on a Synology NAS with Container Manager.
</Card>
<Card icon={<IconServer2 />} title="Proxmox" href="/docs/getting-started/installation/proxmox">
Add Homarr to a Proxmox-based homelab.
</Card>
<Card icon={<IconHome />} title="Home Assistant Add-on" href="/docs/getting-started/installation/home-assistant">
Install Homarr alongside your Home Assistant environment.
</Card>
<Card icon={<IconContainer />} title="Portainer" href="/docs/getting-started/installation/portainer">
Deploy and manage Homarr through Portainer stacks.
</Card>
<Card icon={<IconDatabase />} title="QNAP" href="/docs/getting-started/installation/qnap">
Run Homarr on a QNAP NAS.
</Card>
<Card icon={<IconApps />} title="Runtipi" href="/docs/getting-started/installation/runtipi">
Add Homarr from the Runtipi app store.
</Card>
</Cards>
## Managed and app platforms
<Cards>
<Card icon={<IconLayoutDashboard />} title="EasyPanel" href="/docs/getting-started/installation/easy-panel">
Deploy Homarr from an Easypanel template.
</Card>
<Card icon={<IconTrain />} title="Railway" href="/docs/getting-started/installation/railway">
Launch Homarr as a managed Railway service.
</Card>
<Card icon={<IconCloud />} title="PikaPods" href="/docs/getting-started/installation/pika-pods">
Use a hosted Homarr instance without managing a server.
</Card>
<Card icon={<IconBox />} title="Saltbox" href="/docs/getting-started/installation/saltbox">
Add Homarr to a Saltbox deployment.
</Card>
</Cards>
@@ -0,0 +1,24 @@
{
"title": "Installation",
"defaultOpen": false,
"pages": [
"index",
"---Recommended---",
"docker",
"helm",
"source",
"---Self-hosting platforms---",
"unraid",
"synology",
"proxmox",
"home-assistant",
"portainer",
"qnap",
"runtipi",
"---Managed and app platforms---",
"easy-panel",
"railway",
"pika-pods",
"saltbox"
]
}
@@ -1,4 +1,4 @@
import Link from "@docusaurus/Link";
import Link from "@/components/mdx/link";
import { IconDownload } from "@tabler/icons-react";
# Unraid
+5
View File
@@ -0,0 +1,5 @@
{
"title": "Getting started",
"defaultOpen": false,
"pages": ["index", "installation", "after-the-installation", "upgrade-v2", "glossary"]
}
+72
View File
@@ -0,0 +1,72 @@
---
title: Homarr documentation
description: Install, configure, operate, and extend Homarr.
---
import {
IconApi,
IconArrowUp,
IconBuildingStore,
IconChecklist,
IconCode,
IconComponents,
IconDownload,
IconLayoutDashboard,
IconPlugConnected,
IconSettings,
IconUsers,
IconVocabulary,
} from "@tabler/icons-react";
Use these guides to get Homarr running, connect your services, build useful boards, and manage an installation over time.
## Install or upgrade
<Cards>
<Card icon={<IconDownload />} title="Install Homarr" href="/docs/getting-started/installation">
Choose the installation method for your system.
</Card>
<Card icon={<IconArrowUp />} title="Upgrade from v1" href="/docs/getting-started/upgrade-v2">
Move an existing Homarr installation to v2.
</Card>
<Card icon={<IconChecklist />} title="Finish setup" href="/docs/getting-started/after-the-installation">
Add apps, integrations, and widgets after installation.
</Card>
<Card icon={<IconVocabulary />} title="Learn the concepts" href="/docs/getting-started">
Understand boards, apps, integrations, and widgets.
</Card>
</Cards>
## Configure Homarr
<Cards>
<Card icon={<IconLayoutDashboard />} title="Boards and content" href="/docs/management">
Configure boards, apps, users, settings, and administration.
</Card>
<Card icon={<IconPlugConnected />} title="Connect services" href="/docs/integrations">
Find the setup guide for an integration.
</Card>
<Card icon={<IconComponents />} title="Choose widgets" href="/docs/widgets">
Find the content and controls available for boards.
</Card>
<Card icon={<IconSettings />} title="Advanced configuration" href="/docs/advanced">
Configure deployment, authentication, networking, and automation.
</Card>
</Cards>
## Extend and contribute
<Cards>
<Card icon={<IconCode />} title="Custom Widgets" href="/docs/management/custom-widgets">
Author and publish Custom JSX widgets.
</Card>
<Card icon={<IconBuildingStore />} title="Community Workshop" href="/docs/workshop">
Use and operate the community extension registry.
</Card>
<Card icon={<IconApi />} title="API reference" href="/api-reference">
Inspect Homarr's HTTP API.
</Card>
<Card icon={<IconUsers />} title="Get help and contribute" href="/docs/community">
Find support and ways to contribute.
</Card>
</Cards>
@@ -1,10 +0,0 @@
{
"label": "Integrations",
"collapsed": true,
"position": 3,
"link": {
"type": "generated-index",
"title": "Integrations",
"description": "Integration are a principal part of homarr, it's where you can connect your other apps to interact with them with widgets or other capabilities, Homarr currently integrates with the following applications:"
}
}
@@ -21,7 +21,7 @@ import { coolifyWidget } from "../../widgets/coolify";
<AddingIntegration />
:::info URL configuration
:::info[URL configuration]
Use the root URL of your Coolify instance, for example `https://coolify.example.com`. Homarr calls Coolify endpoints under `/api` and `/api/v1` automatically.
:::
+1 -1
View File
@@ -9,7 +9,7 @@ import { IntegrationCapabilites } from "@site/src/components/integrations/widget
import { AddingIntegration } from "@site/src/components/integrations/adding";
import { IntegrationSecrets } from "@site/src/components/integrations/secrets";
import { IconDownload } from "@tabler/icons-react";
import Alert from "@theme/Admonition";
import Alert from "@/components/mdx/admonition";
import { delugeIntegration } from ".";
import { downloadsWidget } from "@site/docs/widgets/downloads";
+1 -1
View File
@@ -117,7 +117,7 @@ updating a Homarr resource still requires confirmation. If one endpoint is unava
endpoints remain visible.
The `homarr.hide` label excludes a container. Other `homarr.*` labels can provide apps, integrations, groups, and widgets
during onboarding; see [Docker label discovery](../docker-labels).
during onboarding; see [Docker label discovery](/docs/integrations/docker-labels).
## Security
+21
View File
@@ -0,0 +1,21 @@
---
title: Integrations
description: Connect Homarr to the applications and infrastructure you operate.
---
import { DocsDirectory } from "@/components/docs/docs-directory";
An integration stores the connection and authentication details Homarr needs to communicate with another service. Widgets and management tools can then reuse that connection.
Each guide identifies the required URL and credentials, supported capabilities, and the widgets that use the integration.
<DocsDirectory section="integrations" />
## Before you connect a service
1. Confirm that Homarr can reach the service from its own network.
2. Create the least-privileged account, token, or API key supported by the service.
3. Add the integration in **Manage → Integrations**.
4. Test the connection before adding dependent widgets.
See [Manage integrations](/docs/management/integrations) for the shared workflow.
+5
View File
@@ -0,0 +1,5 @@
{
"title": "Integrations",
"defaultOpen": false,
"pages": ["index", "..."]
}
@@ -9,7 +9,7 @@ import { IntegrationCapabilites } from "@site/src/components/integrations/widget
import { AddingIntegration } from "@site/src/components/integrations/adding";
import { IntegrationSecrets } from "@site/src/components/integrations/secrets";
import { IconCalendar } from "@tabler/icons-react";
import Alert from "@theme/Admonition";
import Alert from "@/components/mdx/admonition";
import { nextcloudIntegration } from ".";
import { calendarWidget } from "@site/docs/widgets/calendar";
import { notificationsWidget } from "@site/docs/widgets/notifications";
+1 -1
View File
@@ -10,7 +10,7 @@ import { AddingIntegration } from "@site/src/components/integrations/adding";
import { IntegrationSecrets } from "@site/src/components/integrations/secrets";
import { IconDownload } from "@tabler/icons-react";
import { nzbgetIntegration } from ".";
import Alert from "@theme/Admonition";
import Alert from "@/components/mdx/admonition";
import { downloadsWidget } from "@site/docs/widgets/downloads";
<IntegrationHeader integration={nzbgetIntegration} categories={["Usenet client"]} />
@@ -10,7 +10,7 @@ import { AddingIntegration } from "@site/src/components/integrations/adding";
import { IntegrationSecrets } from "@site/src/components/integrations/secrets";
import { IconHeartRateMonitor } from "@tabler/icons-react";
import { openMediaVaultIntegration } from ".";
import Alert from "@theme/Admonition";
import Alert from "@/components/mdx/admonition";
import { healthMonitoringWidget } from "@site/docs/widgets/health-monitoring";
import { systemResourcesWidget } from "@site/docs/widgets/system-resources";
@@ -8,7 +8,6 @@ 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 Alert from "@theme/Admonition";
import { dnsHoleSummaryWidget } from "@site/docs/widgets/dns-hole-summary";
import { dnsHoleControlsWidget } from "@site/docs/widgets/dns-hole-controls";
import { piHoleIntegration } from ".";
@@ -10,7 +10,7 @@ import { AddingIntegration } from "@site/src/components/integrations/adding";
import { IntegrationSecrets } from "@site/src/components/integrations/secrets";
import { IconDownload } from "@tabler/icons-react";
import { qBittorentIntegration } from ".";
import Alert from "@theme/Admonition";
import Alert from "@/components/mdx/admonition";
import { downloadsWidget } from "@site/docs/widgets/downloads";
<IntegrationHeader integration={qBittorentIntegration} categories={["Torrent client"]} />
@@ -10,7 +10,7 @@ import { AddingIntegration } from "@site/src/components/integrations/adding";
import { IntegrationSecrets } from "@site/src/components/integrations/secrets";
import { IconDownload } from "@tabler/icons-react";
import { sabnzbdIntegration } from ".";
import Alert from "@theme/Admonition";
import Alert from "@/components/mdx/admonition";
import { downloadsWidget } from "@site/docs/widgets/downloads";
<IntegrationHeader integration={sabnzbdIntegration} categories={["Usenet client"]} />
@@ -12,7 +12,7 @@ import { synologyIntegration } from ".";
import { systemResourcesWidget } from "@site/docs/widgets/system-resources";
import { systemDisksWidget } from "@site/docs/widgets/system-disks";
import { healthMonitoringWidget } from "@site/docs/widgets/health-monitoring";
import Alert from "@theme/Admonition";
import Alert from "@/components/mdx/admonition";
<IntegrationHeader integration={synologyIntegration} categories={["NAS", "Hardware"]} />
@@ -8,7 +8,7 @@ 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 Alert from "@theme/Admonition";
import Alert from "@/components/mdx/admonition";
import { technitiumDnsIntegration } from ".";
import { dnsHoleSummaryWidget } from "@site/docs/widgets/dns-hole-summary";
import { dnsHoleControlsWidget } from "@site/docs/widgets/dns-hole-controls";
@@ -21,11 +21,11 @@ import { traefikWidget } from "../../widgets/traefik";
<AddingIntegration />
:::info URL configuration
:::info[URL configuration]
Use the URL where Traefik exposes its dashboard/API, for example `http://traefik:8080` or `https://traefik.example.com`. Homarr calls Traefik endpoints under `/api` automatically.
:::
:::warning API requirement
:::warning[API requirement]
Traefik must have the API enabled. For local or internal setups this is commonly exposed through `api.insecure=true`; for production setups, expose the `api@internal` service through an authenticated router.
:::
@@ -10,7 +10,7 @@ import { AddingIntegration } from "@site/src/components/integrations/adding";
import { IntegrationSecrets } from "@site/src/components/integrations/secrets";
import { IconDownload } from "@tabler/icons-react";
import { transmissionIntegration } from ".";
import Alert from "@theme/Admonition";
import Alert from "@/components/mdx/admonition";
import { downloadsWidget } from "@site/docs/widgets/downloads";
<IntegrationHeader integration={transmissionIntegration} categories={["Torrent client"]} />
@@ -11,7 +11,7 @@ import { IntegrationSecrets } from "@site/src/components/integrations/secrets";
import { truenasIntegration } from ".";
import { systemResourcesWidget } from "@site/docs/widgets/system-resources";
import { healthMonitoringWidget } from "@site/docs/widgets/health-monitoring";
import Alert from "@theme/Admonition";
import Alert from "@/components/mdx/admonition";
<IntegrationHeader integration={truenasIntegration} categories={["NAS", "Hardware"]} />
+1 -1
View File
@@ -21,7 +21,7 @@ import { umamiWidget } from "../../widgets/umami";
<AddingIntegration />
:::tip URL configuration
:::tip[URL configuration]
- **Umami Cloud:** Use `https://api.umami.is/v1`
- **Self-hosted:** Use `http://your-umami-host:3000/api`
@@ -23,7 +23,7 @@ The What's Up Docker integration lets Homarr connect to your [WUD](https://githu
<AddingIntegration />
:::info URL configuration
:::info[URL configuration]
Use the root URL of your WUD instance, for example `https://wud.example.com`. Homarr calls the `/api/app` and `/api/containers` endpoints under that URL automatically.
:::
@@ -1,9 +0,0 @@
{
"label": "Management",
"collapsed": true,
"position": 2,
"link": {
"type": "generated-index",
"title": "Management pages"
}
}
+2 -2
View File
@@ -75,5 +75,5 @@ integration fails, the query returns an error.
Authenticated administrators can retrieve the current Custom Widget authoring prompt, schema, component catalog, skill,
and focused references under `/api/custom-widgets/`.
Use [Custom Widget agent authoring](../custom-widgets/agent-authoring) for the lifecycle and
[MCP](../mcp) when the client supports Model Context Protocol.
Use [Custom Widget agent authoring](/docs/management/custom-widgets/agent-authoring) for the lifecycle and
[MCP](/docs/management/mcp) when the client supports Model Context Protocol.
+4 -4
View File
@@ -27,13 +27,13 @@ model, and enable Assistant. Users can choose another available model for a conv
Provider presets cover common APIs. **Custom endpoint** accepts an OpenAI-compatible Chat Completions API. For a model
server outside the Homarr container, use a hostname that the container can resolve instead of `localhost`.
The [Homarr provider](../workshop/homarr-provider) is available through the Community Workshop without an administrator
The [Homarr provider](/docs/workshop/homarr-provider) is available through the Community Workshop without an administrator
API key and has a daily request allowance.
## Access
Open Assistant from the user menu, with `Shift+A`, from search with `Cmd/Ctrl+/`, or through the
[Assistant widget](../widgets/assistant).
[Assistant widget](/docs/widgets/assistant).
Assistant can work with boards, apps, integrations, widgets, Custom Widgets, and supported connected services. Mention
Homarr resources with `@`; the model loads additional live context only when needed.
@@ -47,8 +47,8 @@ Conversations are stored per user and can be searched, renamed, exported, or del
- Provider keys and custom headers are encrypted and are not returned to the browser.
- Prompts, attachments, tool definitions, and tool results are sent to the selected model provider.
See [MCP](./mcp) to connect an external AI client and
[Custom Widget agent authoring](./custom-widgets/agent-authoring) for widget generation.
See [MCP](/docs/management/mcp) to connect an external AI client and
[Custom Widget agent authoring](/docs/management/custom-widgets/agent-authoring) for widget generation.
## Troubleshooting
+1 -1
View File
@@ -91,4 +91,4 @@ inside a board.
Defaults can be set for a user, group, or the whole server. User settings take priority, followed by matching groups,
the `Everyone` group, and server defaults. Server-wide fallback boards must be public.
See [Users and groups](../users) and [Server settings](../settings#boards).
See [Users and groups](/docs/management/users) and [Server settings](/docs/management/settings#boards).
@@ -1,9 +0,0 @@
{
"label": "Custom Widgets",
"collapsed": true,
"position": 8,
"link": {
"type": "doc",
"id": "management/custom-widgets/index"
}
}
@@ -41,5 +41,5 @@ authenticated administrator completes it in Homarr; the agent receives the statu
Agents can also search, inspect, install, and configure existing Workshop widgets instead of regenerating them.
See [MCP](/docs/management/mcp) for client configuration and [requests and security](./requests-and-security) for the
See [MCP](/docs/management/mcp) for client configuration and [requests and security](/docs/management/custom-widgets/requests-and-security) for the
runtime limits.
@@ -17,8 +17,9 @@ Changing the definition, options, or credentials invalidates the previous previe
Widget options support text, textarea, number, switch, select, multi-select, slider, date, time, color, icon, URL,
duration, time zone, and JSON controls. Dynamic choices can come from a load query.
See the [safe JSX runtime](./custom-jsx), [component reference](./component-reference), and
[request reference](./requests-and-security) for the authoring contract.
See the [safe JSX runtime](/docs/management/custom-widgets/custom-jsx),
[component reference](/docs/management/custom-widgets/component-reference), and
[request reference](/docs/management/custom-widgets/requests-and-security) for the authoring contract.
## Create with another AI service
@@ -26,4 +27,4 @@ See the [safe JSX runtime](./custom-jsx), [component reference](./component-refe
must return one fenced `json` block containing the complete definition. Paste that block into the workbench, add
credentials separately, and validate it against a real preview.
For an MCP-connected agent, use the [Homarr Custom Widget skill](./agent-authoring) instead.
For an MCP-connected agent, use the [Homarr Custom Widget skill](/docs/management/custom-widgets/agent-authoring) instead.
@@ -35,12 +35,12 @@ boards; actions require authentication and the permission declared by the reques
## Authoring
- [Create a Custom Widget](./authoring) in the workbench or from a copied AI prompt.
- [Use the safe JSX runtime](./custom-jsx) for data bindings, temporary inputs, and components.
- [Browse the component reference](./component-reference).
- [Configure requests and security](./requests-and-security).
- [Connect an agent](./agent-authoring) through MCP and the Homarr skill.
- [Troubleshoot a definition](./troubleshooting).
- [Create a Custom Widget](/docs/management/custom-widgets/authoring) in the workbench or from a copied AI prompt.
- [Use the safe JSX runtime](/docs/management/custom-widgets/custom-jsx) for data bindings, temporary inputs, and components.
- [Browse the component reference](/docs/management/custom-widgets/component-reference).
- [Configure requests and security](/docs/management/custom-widgets/requests-and-security).
- [Connect an agent](/docs/management/custom-widgets/agent-authoring) through MCP and the Homarr skill.
- [Troubleshoot a definition](/docs/management/custom-widgets/troubleshooting).
The workbench validates the same schema used by imports, Workshop, HTTP authoring resources, and MCP. Test every query
and simulate relevant actions before saving. Live preview actions are opt-in because they can change the source service.
@@ -0,0 +1,12 @@
{
"title": "Custom Widgets",
"pages": [
"index",
"authoring",
"agent-authoring",
"custom-jsx",
"component-reference",
"requests-and-security",
"troubleshooting"
]
}
@@ -39,7 +39,7 @@ stale cached query on another replica.
## Runtime warnings
`UNKNOWN_MANTINE_PROP` means the installed Mantine component does not document that property. Check the
[component reference](./component-reference). `BLOCKED_CAPABILITY` means the runtime rejected an unsafe component,
[component reference](/docs/management/custom-widgets/component-reference). `BLOCKED_CAPABILITY` means the runtime rejected an unsafe component,
property, URL, or style capability.
## Workshop unavailable
+82
View File
@@ -0,0 +1,82 @@
---
title: Manage Homarr
description: Configure boards, content, access, automation, and server-wide behavior.
---
import {
IconApi,
IconApps,
IconCertificate,
IconChecklist,
IconComponents,
IconDatabaseExport,
IconLayoutDashboard,
IconLogs,
IconPhoto,
IconPlugConnected,
IconRobot,
IconSearch,
IconSettings,
IconTerminal2,
IconUsers,
} from "@tabler/icons-react";
## Everyday configuration
<Cards>
<Card icon={<IconLayoutDashboard />} title="Boards" href="/docs/management/boards">
Create, organize, share, and configure boards.
</Card>
<Card icon={<IconApps />} title="Apps" href="/docs/management/apps">
Add the services and links shown on boards.
</Card>
<Card icon={<IconPlugConnected />} title="Integrations" href="/docs/management/integrations">
Configure reusable service connections.
</Card>
<Card icon={<IconUsers />} title="Users and groups" href="/docs/management/users">
Control access and permissions.
</Card>
<Card icon={<IconSettings />} title="Settings" href="/docs/management/settings">
Change server and user preferences.
</Card>
</Cards>
## Content and extensions
<Cards>
<Card icon={<IconPhoto />} title="Media" href="/docs/management/media">
Manage uploaded assets.
</Card>
<Card icon={<IconSearch />} title="Search engines" href="/docs/management/search-engines">
Configure search shortcuts.
</Card>
<Card icon={<IconComponents />} title="Custom Widgets" href="/docs/management/custom-widgets">
Build Custom JSX widgets.
</Card>
<Card icon={<IconRobot />} title="Assistant" href="/docs/management/assistant">
Configure Homarr's assistant features.
</Card>
</Cards>
## Operations
<Cards>
<Card icon={<IconApi />} title="API" href="/docs/management/api">
Configure API keys and use the generated reference.
</Card>
<Card icon={<IconTerminal2 />} title="Model Context Protocol" href="/docs/management/mcp">
Connect external assistants to Homarr.
</Card>
<Card icon={<IconChecklist />} title="Tasks" href="/docs/management/tasks">
Inspect scheduled and background tasks.
</Card>
<Card icon={<IconLogs />} title="Logs" href="/docs/management/logs">
Inspect application logs.
</Card>
<Card icon={<IconCertificate />} title="Certificates" href="/docs/management/certificates">
Trust certificates used by connected services.
</Card>
<Card icon={<IconDatabaseExport />} title="Backups" href="/docs/management/backup">
Export and restore Homarr data.
</Card>
</Cards>
@@ -14,7 +14,7 @@ actions to widgets and can be linked to apps.
![The integration catalog](../img/integrations-catalog.png)
See the [integration catalog](/docs/category/integrations) for service-specific URLs, credentials, and supported
See the [integration catalog](/docs/integrations) for service-specific URLs, credentials, and supported
widgets.
## Browser and server routes
@@ -57,6 +57,6 @@ If a connection test fails:
1. Check the integration page for the required base URL and credentials.
2. Test name resolution and HTTP access from the Homarr container or pod, not only from the host or browser.
3. Check Homarr and upstream-service logs, then any reverse proxy, firewall, VLAN, VPN, or DNS between them.
4. For a self-signed certificate, add the expected certificate under [Certificates](../certificates).
4. For a self-signed certificate, add the expected certificate under [Certificates](/docs/management/certificates).
Do not disable upstream security controls as a general troubleshooting step.
+2 -2
View File
@@ -85,8 +85,8 @@ Homarr procedures. Queries are read-only; mutations change state. The exact cata
user permissions, so inspect `tools/list` or the table in Homarr instead of relying on a static list.
For Custom Widgets, install the official skill and follow the preview-and-evidence workflow described in
[Connect an agent](./custom-widgets/agent-authoring). Secret values are configured in Homarr and are never returned
[Connect an agent](/docs/management/custom-widgets/agent-authoring). Secret values are configured in Homarr and are never returned
through MCP.
The built-in [Assistant](./assistant) uses the same tool catalog with the current Homarr session and asks for approval
The built-in [Assistant](/docs/management/assistant) uses the same tool catalog with the current Homarr session and asks for approval
before mutations by default.
+25
View File
@@ -0,0 +1,25 @@
{
"title": "Management",
"defaultOpen": false,
"pages": [
"index",
"---Everyday configuration---",
"boards",
"apps",
"integrations",
"users",
"settings",
"---Content and extensions---",
"search-engines",
"media",
"custom-widgets",
"assistant",
"---Operations---",
"api",
"mcp",
"tasks",
"logs",
"certificates",
"backup"
]
}
+1 -1
View File
@@ -62,7 +62,7 @@ specific users or groups:
- Board access uses View, Modify, and Full levels.
- Integration access uses Use, Interact, and Full levels.
See [Boards](../boards#access-control) and [Integrations](../integrations#permissions).
See [Boards](/docs/management/boards#access-control) and [Integrations](/docs/management/integrations#permissions).
## Invitations
+3
View File
@@ -0,0 +1,3 @@
{
"pages": ["index", "getting-started", "management", "integrations", "widgets", "workshop", "advanced", "community"]
}
-11
View File
@@ -1,11 +0,0 @@
{
"label": "Widgets",
"position": 3,
"collapsed": true,
"link": {
"type": "generated-index",
"title": "Widgets",
"description": "Widgets allow you to show data on your board or control applications. Click on one of the widgets below for further information:",
"image": "/img/docusaurus.png"
}
}
+2 -2
View File
@@ -9,8 +9,8 @@ import { WidgetInteractionGuide } from "@site/src/components/widgets/interaction
import { WidgetHeader } from "@site/src/components/widgets/header";
import { AddingWidget } from "@site/src/components/widgets/adding";
import { WidgetIntegrations } from "@site/src/components/widgets/integrations";
import Tabs from "@theme/Tabs";
import TabItem from "@theme/TabItem";
import Tabs from "@/components/mdx/legacy-tabs";
import { TabItem } from "@/components/mdx/legacy-tabs";
import { firewallWidget } from ".";
import { opnsenseIntegration } from "../../integrations/opnsense";
@@ -11,8 +11,8 @@ import { AddingWidget } from "@site/src/components/widgets/adding";
import { WidgetConfig } from "@site/src/components/widgets/configuration";
import { WidgetIntegrations } from "@site/src/components/widgets/integrations";
import { IconAd } from "@tabler/icons-react";
import Tabs from "@theme/Tabs";
import TabItem from "@theme/TabItem";
import Tabs from "@/components/mdx/legacy-tabs";
import { TabItem } from "@/components/mdx/legacy-tabs";
import { healthMonitoringWidget } from ".";
import { dashDotIntegration } from "@site/docs/integrations/dash-dot";
import { openMediaVaultIntegration } from "@site/docs/integrations/open-media-vault";
+21
View File
@@ -0,0 +1,21 @@
---
title: Widgets
description: Configure the information and controls shown on Homarr boards.
---
import { DocsDirectory } from "@/components/docs/docs-directory";
Widgets turn apps, integrations, and Homarr data into useful board content. Some work on their own; others require one or more configured integrations.
Each widget guide explains its configuration, required integrations, supported interactions, permissions, and important empty or error states.
## Add a widget
1. Open a board and enter edit mode.
2. Select **Add item**, then choose **Widget**.
3. Pick a widget and complete its configuration.
4. Move or resize it, then leave edit mode to use it.
<DocsDirectory section="widgets" />
See [After installation](/docs/getting-started/after-the-installation) for the complete first-board workflow.
@@ -11,8 +11,8 @@ import { AddingWidget } from "@site/src/components/widgets/adding";
import { WidgetConfig } from "@site/src/components/widgets/configuration";
import { WidgetIntegrations } from "@site/src/components/widgets/integrations";
import { IconAd } from "@tabler/icons-react";
import Tabs from "@theme/Tabs";
import TabItem from "@theme/TabItem";
import Tabs from "@/components/mdx/legacy-tabs";
import { TabItem } from "@/components/mdx/legacy-tabs";
import { mediaRequestListWidget } from ".";
import { jellyseerrIntegration } from "@site/docs/integrations/jellyseerr";
import { overseerrIntegration } from "@site/docs/integrations/overseerr";
@@ -11,8 +11,8 @@ import { AddingWidget } from "@site/src/components/widgets/adding";
import { WidgetConfig } from "@site/src/components/widgets/configuration";
import { WidgetIntegrations } from "@site/src/components/widgets/integrations";
import { IconAd } from "@tabler/icons-react";
import Tabs from "@theme/Tabs";
import TabItem from "@theme/TabItem";
import Tabs from "@/components/mdx/legacy-tabs";
import { TabItem } from "@/components/mdx/legacy-tabs";
import { mediaRequestStatsWidget } from ".";
import { jellyseerrIntegration } from "@site/docs/integrations/jellyseerr";
import { overseerrIntegration } from "@site/docs/integrations/overseerr";
@@ -11,8 +11,8 @@ import { AddingWidget } from "@site/src/components/widgets/adding";
import { WidgetConfig } from "@site/src/components/widgets/configuration";
import { WidgetIntegrations } from "@site/src/components/widgets/integrations";
import { IconAd } from "@tabler/icons-react";
import Tabs from "@theme/Tabs";
import TabItem from "@theme/TabItem";
import Tabs from "@/components/mdx/legacy-tabs";
import { TabItem } from "@/components/mdx/legacy-tabs";
import { mediaTranscodingWidget } from ".";
import { tdarrIntegration } from "@site/docs/integrations/tdarr";
+5
View File
@@ -0,0 +1,5 @@
{
"title": "Widgets",
"defaultOpen": false,
"pages": ["index", "..."]
}
@@ -11,8 +11,8 @@ import { WidgetConfig } from "@site/src/components/widgets/configuration";
import { WidgetHeader } from "@site/src/components/widgets/header";
import { WidgetIntegrations } from "@site/src/components/widgets/integrations";
import { IconAd } from "@tabler/icons-react";
import TabItem from "@theme/TabItem";
import Tabs from "@theme/Tabs";
import { TabItem } from "@/components/mdx/legacy-tabs";
import Tabs from "@/components/mdx/legacy-tabs";
import { minecraftServerStatusWidget } from ".";
<WidgetHeader widget={minecraftServerStatusWidget} categories={["Gaming", "Minecraft"]} />
-9
View File
@@ -1,9 +0,0 @@
{
"label": "Workshop",
"collapsed": true,
"position": 4,
"link": {
"type": "doc",
"id": "workshop/index"
}
}
+2 -2
View File
@@ -11,7 +11,7 @@ import { WorkshopFlowDiagram } from "@site/src/components/pages/core-concepts/te
# Community Workshop
The [Community Workshop](pathname:///workshop) hosts community Custom Widgets and dashboard CSS.
The [Community Workshop](/workshop) hosts community Custom Widgets and dashboard CSS.
:::warning Experimental
@@ -23,7 +23,7 @@ Workshop content is community-maintained. Review its source and permissions befo
<WorkshopFlowDiagram />
Workshop also exposes the [Homarr Assistant provider](./homarr-provider). Its model-routing and quota path is separate
Workshop also exposes the [Homarr Assistant provider](/docs/workshop/homarr-provider). Its model-routing and quota path is separate
from Custom Widget and CSS submissions.
## Install content
+5
View File
@@ -0,0 +1,5 @@
{
"title": "Workshop",
"defaultOpen": false,
"pages": ["index", "homarr-provider"]
}
-134
View File
@@ -1,134 +0,0 @@
// Algolia DocSearch crawler for homarr.dev
// Crawler ID: cd77a285-2756-4557-bf21-ee703748df15
// Paste this in the Algolia crawler editor.
new Crawler({
appId: "N69WSPZTID",
apiKey: "YOUR_CRAWLER_ADMIN_API_KEY",
indexPrefix: "",
rateLimit: 32,
maxDepth: 4,
startUrls: ["https://homarr.dev/"],
sitemaps: ["https://homarr.dev/sitemap.xml"],
ignoreCanonicalTo: true,
discoveryPatterns: ["https://homarr.dev/**"],
exclusionPatterns: [
"https://homarr.dev/docs/tags/**",
"https://homarr.dev/blog/tags/**",
"https://homarr.dev/blog/authors/**",
"https://homarr.dev/blog/archive/**",
"https://homarr.dev/search/**",
"https://homarr.dev/docs/category/**",
],
actions: [
{
indexName: "Docusaurus",
pathsToMatch: ["https://homarr.dev/**"],
recordExtractor: ({ $, helpers }) => {
const lvl0 =
$(".menu__link.menu__link--sublist.menu__link--active, .navbar__item.navbar__link--active").last().text() ||
"Documentation";
return helpers.docsearch({
recordProps: {
lvl0: {
selectors: "",
defaultValue: lvl0,
},
lvl1: ["header h1", "article h1"],
lvl2: "article h2",
lvl3: "article h3",
lvl4: "article h4",
lvl5: "article h5, article td:first-child",
lvl6: "article h6",
content: "article p, article li, article td:last-child",
},
indexHeadings: true,
aggregateContent: true,
recordVersion: "v3",
});
},
},
{
indexName: "markdown",
pathsToMatch: ["https://homarr.dev/**"],
recordExtractor: ({ $, url, helpers }) => {
const text = helpers.markdown("article > *:not(nav):not(header):not(.breadcrumb)");
if (text === "") {
return [];
}
const language = $("html").attr("lang") || "en";
const title = $("head > title").text();
const h1 = $("article h1").first().text();
return helpers.splitTextIntoRecords({
text,
baseRecord: {
url,
objectID: url,
title: title || h1,
heading: h1,
lang: language,
language,
version: "current",
docusaurus_tag: "docs-default-current",
},
maxRecordBytes: 100000,
orderingAttributeName: "part",
});
},
},
],
initialIndexSettings: {
Docusaurus: {
attributesForFaceting: ["type", "lang", "language", "version", "docusaurus_tag"],
attributesToRetrieve: ["hierarchy", "content", "anchor", "url", "url_without_anchor", "type"],
attributesToHighlight: ["hierarchy", "content"],
attributesToSnippet: ["content:10"],
camelCaseAttributes: ["hierarchy", "content"],
searchableAttributes: [
"unordered(hierarchy.lvl0)",
"unordered(hierarchy.lvl1)",
"unordered(hierarchy.lvl2)",
"unordered(hierarchy.lvl3)",
"unordered(hierarchy.lvl4)",
"unordered(hierarchy.lvl5)",
"unordered(hierarchy.lvl6)",
"content",
],
distinct: true,
attributeForDistinct: "url",
customRanking: ["desc(weight.pageRank)", "desc(weight.level)", "asc(weight.position)"],
ranking: ["words", "filters", "typo", "attribute", "proximity", "exact", "custom"],
highlightPreTag: '<span class="algolia-docsearch-suggestion--highlight">',
highlightPostTag: "</span>",
minWordSizefor1Typo: 3,
minWordSizefor2Typos: 7,
allowTyposOnNumericTokens: false,
minProximity: 1,
ignorePlurals: true,
advancedSyntax: true,
attributeCriteriaComputedByMinProximity: true,
removeWordsIfNoResults: "allOptional",
},
markdown: {
attributesForFaceting: ["lang", "language", "version", "docusaurus_tag"],
ignorePlurals: true,
minProximity: 1,
removeStopWords: false,
searchableAttributes: ["title", "heading", "unordered(text)"],
removeWordsIfNoResults: "lastWords",
attributesToHighlight: ["title", "text"],
typoTolerance: false,
advancedSyntax: false,
},
},
apiKey: "YOUR_CRAWLER_ADMIN_API_KEY",
schedule: "on saturday",
renderJavaScript: false,
maxUrls: null,
cache: { enabled: false },
safetyChecks: { beforeIndexPublishing: { maxLostRecordsPercentage: 99 } },
});
-422
View File
@@ -1,422 +0,0 @@
import type * as Preset from "@docusaurus/preset-classic";
import type { Config } from "@docusaurus/types";
import { themes as prismThemes } from "prism-react-renderer";
import { resolveHomarrUrlConfig } from "@homarr/workshop/schema";
const a11yEmoji = require("@fec/remark-a11y-emoji");
const deprecatedWorkshopUrl = process.env.WORKSHOP_URL;
if (deprecatedWorkshopUrl && !process.env.WORKSHOP_API_URL) {
console.warn("WORKSHOP_URL is deprecated; use WORKSHOP_API_URL instead.");
}
const publicUrls = resolveHomarrUrlConfig({
homarrWebsiteUrl: process.env.HOMARR_WEBSITE_URL,
workshopApiUrl: process.env.WORKSHOP_API_URL ?? deprecatedWorkshopUrl,
workshopWebUrl: process.env.WORKSHOP_WEB_URL,
});
const config: Config = {
title: "Homarr documentation",
tagline: "A simple yet powerful dashboard for your server.",
url: publicUrls.homarrWebsiteUrl,
baseUrl: "/",
trailingSlash: undefined,
favicon: "img/logo.png",
organizationName: "homarr-labs",
projectName: "homarr",
customFields: {
workshopUrl: publicUrls.workshopApiUrl,
workshopWebUrl: publicUrls.workshopWebUrl,
},
scripts: [{ src: "/workshop-runtime-config.js" }],
i18n: {
defaultLocale: "en",
locales: ["en"],
},
onBrokenLinks: "throw",
onBrokenAnchors: "throw",
onDuplicateRoutes: "throw",
future: {
v4: {
removeLegacyPostBuildHeadAttribute: true,
useCssCascadeLayers: true,
siteStorageNamespacing: true,
fasterByDefault: true,
mdx1CompatDisabledByDefault: false,
},
faster: {
swcHtmlMinimizer: false,
},
},
markdown: {
mermaid: true,
format: "detect",
hooks: {
onBrokenMarkdownLinks: "throw",
},
},
themes: ["@docusaurus/theme-mermaid"],
presets: [
[
"classic",
{
docs: {
sidebarPath: require.resolve("./sidebars.js"),
editUrl: ({ docPath }) => `https://github.com/homarr-labs/homarr/edit/dev/apps/docs/docs/${docPath}`,
remarkPlugins: [a11yEmoji],
exclude: [],
showLastUpdateAuthor: false,
showLastUpdateTime: false,
},
blog: {
showReadingTime: true,
// Please change this to your repo.
// Remove this to remove the "edit this page" links.
editUrl: "https://github.com/homarr-labs/homarr/edit/dev/apps/docs",
authorsMapPath: "authors.yml",
},
theme: {
customCss: require.resolve("./src/css/custom.css"),
},
sitemap: {
changefreq: "weekly",
priority: 0.5,
ignorePatterns: ["/tags/**", "/docs/category/**"],
filename: "sitemap.xml",
createSitemapItems: async ({ routes, siteConfig, defaultCreateSitemapItems }) => {
const items = await defaultCreateSitemapItems({ routes, siteConfig });
return items.map((item) => {
const path = new URL(item.url).pathname;
if (path === "/" || path === "") {
return { ...item, priority: 1.0, changefreq: "weekly" };
}
if (path.startsWith("/docs/")) {
return { ...item, priority: 0.7, changefreq: "monthly" };
}
if (path.startsWith("/blog/")) {
return { ...item, priority: 0.3, changefreq: "never" };
}
if (path.startsWith("/about-us")) {
return { ...item, priority: 0.4, changefreq: "yearly" };
}
return item;
});
},
},
} satisfies Preset.Options,
],
],
themeConfig: {
navbar: {
title: "Homarr",
logo: {
alt: "Homarr Logo",
src: "img/logo.png",
},
items: [
{
label: "Documentation",
type: "doc",
position: "left",
docId: "getting-started/index",
},
{
label: "Blog",
position: "left",
to: "/blog",
className: "navbar-item--secondary",
},
{
label: "Workshop",
position: "left",
to: "/workshop",
},
{
label: "About us",
position: "left",
to: "/about-us",
className: "navbar-item--collapse-first",
},
{
to: "https://demo.homarr.dev/",
label: "Demo",
position: "right",
className: "navbar-item--secondary",
},
{
to: "https://opencollective.com/homarr",
label: "💴 Donate",
position: "right",
className: "navbar-item--collapse-first",
},
{
type: "dropdown",
label: "Community",
position: "right",
items: [
{
to: "https://discord.com/invite/aCsmEV5RgA",
label: "Discord",
},
{
to: "https://github.com/homarr-labs/homarr",
label: "GitHub",
},
{
to: "https://www.answeroverflow.com/c/972958686051962910",
label: "Answer Overflow",
},
{
to: "https://crowdin.com/project/homarr_labs",
label: "Community translations (Crowdin)",
},
{
to: "https://www.reddit.com/r/homarr/",
label: "Reddit",
},
{
to: "https://opencollective.com/homarr",
label: "OpenCollective",
},
{
to: "https://x.com/homarr_labs",
label: "X / Twitter",
},
],
},
{
type: "search",
position: "right",
},
],
hideOnScroll: false,
},
algolia: {
appId: "N69WSPZTID",
apiKey: "b2b00f4ed8ca3dc87b5d211c55121416",
indexName: "Docusaurus",
contextualSearch: false,
searchPagePath: "search",
insights: false,
replaceSearchResultPathname: {
from: "/docs/(next|\\d+(?:\\.\\d+)*)/",
to: "/docs/",
},
},
footer: {
links: [
{
title: "Documentation",
items: [
{
label: "Installation",
to: "/docs/category/getting-started",
},
],
},
{
title: "Community",
items: [
{
label: "Discord",
to: "https://discord.com/invite/aCsmEV5RgA",
},
{
label: "GitHub",
to: "https://github.com/homarr-labs/homarr",
},
{
label: "Donate",
to: "https://opencollective.com/homarr",
},
],
},
{
title: "More",
items: [
{
label: "Blog",
to: "/blog",
},
{
label: "About us",
to: "/about-us",
},
],
},
],
logo: {
alt: "Homarr home",
src: "img/logo.svg",
href: "/",
width: 86,
height: 58,
},
copyright: `
<div class="footer__brand-copy">
<strong class="footer__brand-name">Homarr</strong>
<span class="footer__brand-tagline">Your dashboard for the services you run.</span>
<span class="copyright_text">© ${new Date().getFullYear()} Homarr · <a href="/docs/community/license">License</a></span>
</div>
`,
},
prism: {
theme: prismThemes.github,
darkTheme: prismThemes.dracula,
defaultLanguage: "bash",
},
colorMode: {
defaultMode: "dark",
respectPrefersColorScheme: true,
},
metadata: [
{
name: "keywords",
content: "Homarr, Dashboard, Selfhosted, Hosting, Modules, Open-Source",
},
],
zoom: {
selector: ".markdown :not(em) > img",
background: {
light: "rgb(255, 255, 255)",
dark: "rgb(50, 50, 50)",
},
config: {
// options you can specify via https://github.com/francoischalifour/medium-zoom#usage
margin: 80,
},
},
tableOfContents: {
minHeadingLevel: 2,
maxHeadingLevel: 4,
},
} satisfies Preset.ThemeConfig,
plugins: [
function homarrPackagesPlugin() {
return {
name: "resolve-homarr-packages",
configureWebpack(_config, isServer, { getJSLoader }) {
return {
resolve: {
symlinks: false,
alias: { "@": require("path").resolve(__dirname, "src") },
},
module: {
rules: [
{
test: /\.[jt]sx?$/iu,
include: /node_modules[\\/]@homarr/u,
use: [getJSLoader({ isServer })],
},
],
},
};
},
};
},
[
"posthog-docusaurus",
{
apiKey: "phc_pWxeD1hbl4ip02JYReX1Crjkt5DhB3dduigirHMCtFE",
appUrl: "https://hog.homarr.dev",
enableInDevelopment: true,
ui_host: "https://eu.posthog.com",
defaults: "2026-01-30",
autocapture: true,
disable_session_recording: true,
advanced_disable_feature_flags: true,
},
],
"docusaurus-plugin-image-zoom",
require.resolve("./plugins/validate-docs-coverage"),
function disableExpensiveBundlerOptimizationPlugin() {
return {
name: "disable-expensive-bundler-optimizations",
configureWebpack(_config: unknown, isServer: boolean) {
return {
optimization: {
concatenateModules: process.env.CI != null && process.env.CI !== "false" ? !isServer : false,
},
};
},
};
},
function workshopRoutesPlugin() {
return {
name: "workshop-routes",
injectHtmlTags() {
return {
headTags: [
{
tagName: "style",
innerHTML: `
#workshop-detail-route-fallback { display: none; }
html[data-workshop-detail-loading] #__docusaurus { display: none; }
html[data-workshop-detail-loading] #workshop-detail-route-fallback {
align-items: center;
background: #fff;
box-sizing: border-box;
color: #4b5563;
display: flex;
font: 500 0.875rem/1.5 "Work Sans", system-ui, sans-serif;
justify-content: center;
min-height: 100vh;
padding: 2rem;
}
@media (prefers-color-scheme: dark) {
html[data-workshop-detail-loading] #workshop-detail-route-fallback {
background: #18191a;
color: #d1d5db;
}
}`,
},
{
tagName: "script",
innerHTML: `(function () {
var match = window.location.pathname.match(/^\\/workshop\\/([^/]+)\\/?$/);
if (match && match[1] !== "admin") {
document.documentElement.setAttribute("data-workshop-detail-loading", "");
}
})();`,
},
],
preBodyTags: [
{
tagName: "div",
attributes: {
id: "workshop-detail-route-fallback",
role: "status",
"aria-live": "polite",
},
innerHTML: "Loading Workshop…",
},
],
};
},
async contentLoaded({ actions }) {
actions.addRoute({
path: "/workshop/:id",
component: "@site/src/components/workshop/WorkshopDetailRoutePage",
exact: true,
priority: -1,
});
},
};
},
async function tailwindCssPlugin() {
return {
name: "docusaurus-tailwindcss",
configurePostCss(postcssOptions) {
postcssOptions.plugins.push(require("@tailwindcss/postcss"));
return postcssOptions;
},
};
},
],
};
export default config;
+16
View File
@@ -0,0 +1,16 @@
import { createMDX } from "fumadocs-mdx/next";
const withMDX = createMDX();
/** @type {import("next").NextConfig} */
const config = {
output: "export",
reactStrictMode: true,
trailingSlash: true,
images: {
unoptimized: true,
},
transpilePackages: ["@homarr/custom-widgets", "@homarr/definitions", "@homarr/workshop"],
};
export default withMDX(config);
+25 -42
View File
@@ -3,37 +3,28 @@
"version": "0.2.3",
"private": true,
"license": "Apache-2.0",
"type": "module",
"scripts": {
"docusaurus": "docusaurus",
"dev": "docusaurus start --no-open --port 3003",
"start": "docusaurus start --port 3003",
"build": "docusaurus build",
"serve": "docusaurus serve",
"clear": "docusaurus clear",
"typecheck": "tsc --noEmit",
"dev": "next dev --port 3003",
"start": "serve out --listen 3003",
"build": "pnpm validate:coverage && next build",
"typecheck": "next typegen && tsc --noEmit",
"lint": "oxlint",
"format": "oxfmt .",
"clean": "rm -rf build .docusaurus",
"swizzle": "docusaurus swizzle",
"write-translations": "docusaurus write-translations",
"write-heading-ids": "docusaurus write-heading-ids",
"clean": "git clean -xdf .next out node_modules",
"api-dump-contributors": "node ./scripts/dump-contributors.mjs",
"verify:search": "node ./scripts/verify-algolia-search.mjs"
"validate:coverage": "tsx ./scripts/validate-docs-coverage.ts",
"validate:links": "tsx ./scripts/validate-links.ts"
},
"dependencies": {
"@base-ui/react": "^1.5.0",
"@docusaurus/core": "^3.10.1",
"@docusaurus/faster": "^3.10.1",
"@docusaurus/plugin-content-docs": "^3.10.1",
"@docusaurus/plugin-sitemap": "^3.10.1",
"@docusaurus/preset-classic": "^3.10.1",
"@homarr/custom-widgets": "workspace:^",
"@homarr/definitions": "workspace:^",
"@homarr/workshop": "workspace:^",
"@mantine/core": "catalog:",
"@mdx-js/react": "^3.1.1",
"@nivo/line": "^0.99.0",
"@scalar/api-reference-react": "catalog:",
"@scalar/api-client-react": "catalog:",
"@shadcn/react": "catalog:",
"@tabler/icons-react": "catalog:",
"@tailwindcss/postcss": "^4.3.2",
@@ -42,51 +33,43 @@
"cmdk": "catalog:",
"date-fns": "catalog:",
"dayjs": "catalog:",
"docusaurus-plugin-image-zoom": "^3.0.1",
"embla-carousel-react": "catalog:",
"feed": "catalog:",
"fumadocs-core": "catalog:",
"fumadocs-mdx": "catalog:",
"fumadocs-openapi": "catalog:",
"fumadocs-ui": "catalog:",
"input-otp": "catalog:",
"leader-line-new": "^1.1.9",
"json-schema-typed": "catalog:",
"mermaid": "catalog:",
"next": "catalog:",
"next-themes": "catalog:",
"pocketbase": "catalog:",
"postcss": "^8.5.16",
"posthog-docusaurus": "^2.0.5",
"prism-react-renderer": "^2.4.1",
"posthog-js": "catalog:",
"react": "catalog:",
"react-day-picker": "catalog:",
"react-dom": "catalog:",
"react-resizable-panels": "catalog:",
"recharts": "3.8.0",
"remark-directive": "catalog:",
"shiki": "catalog:",
"sonner": "catalog:",
"swiper": "^14.0.5",
"tailwind-merge": "^3.6.0",
"tailwindcss": "^4.3.2"
},
"devDependencies": {
"@docusaurus/module-type-aliases": "^3.10.1",
"@docusaurus/tsconfig": "^3.10.1",
"@docusaurus/types": "^3.10.1",
"@fec/remark-a11y-emoji": "^4.0.2",
"@tsconfig/docusaurus": "^2.0.9",
"@types/mdx": "catalog:",
"@types/node": "catalog:",
"@types/react": "catalog:",
"@types/react-dom": "catalog:",
"cheerio": "^1.2.0",
"next-validate-link": "1.6.7",
"serve": "catalog:",
"tsx": "catalog:",
"typescript": "catalog:",
"zod": "catalog:"
},
"peerDependencies": {
"@docusaurus/theme-common": "^3.10.1",
"@docusaurus/theme-mermaid": "^3.10.1"
},
"browserslist": {
"production": [
">0.5%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
Loaded 100 of 257 files, more files were not shown because too many files have changed in this diff. Show more