fix: finish widget scaling and restore docs policy

This commit is contained in:
ajnart committed 2026-09-11 10:52:47 +02:00
1 parent 56cfe3992b
commit 33404dec95
8 files changed
+59 -36

No files matched your search

+1 -1
View File
@@ -37,4 +37,4 @@ Orient from the current checkout before editing. Treat package manifests, export
- Cron jobs: `packages/cron-jobs/src/jobs/`
- App routes: `apps/nextjs/src/app/[locale]/`
When a code change affects users, invoke `documentation-sync`. When exposing tRPC through MCP, invoke `mcp-integration`.
When a change affects setup, usage, troubleshooting, or the accuracy of existing docs, invoke `documentation-sync`. When exposing tRPC through MCP, invoke `mcp-integration`.
+13 -5
View File
@@ -1,13 +1,21 @@
---
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 Docusaurus documentation useful and accurate. Use when a change affects what users need to know to configure, use, or troubleshoot Homarr, or makes existing guidance inaccurate.
---
# Documentation Sync
Update `apps/docs/` in the same change as user-facing behavior. Inspect adjacent pages and the docs types before copying a pattern; the source and docs evolve together.
Update `apps/docs/` when users need new or corrected guidance to configure, use, or troubleshoot Homarr. Keep documentation straight to the point.
## Map the change
## Decide whether documentation is needed
Identify the user action, decision, prerequisite, limitation, or troubleshooting step that changes. Update the relevant docs when that information is missing or inaccurate. If nothing users need to know changes, leave the docs untouched.
Routine visual fixes such as icon sizing, spacing, alignment, responsive layout, and animation usually need no documentation. Describe them in the PR when useful for review. Document a visual change only when it changes a user workflow, setting, or meaningful limitation.
Write the minimum information needed to complete the user's task. Inspect adjacent pages and the docs types before editing.
## Map changes that need documentation
| Code change | Documentation target |
| ----------------------------------- | -------------------------------------------------------------------- |
@@ -44,8 +52,8 @@ For a widget:
## Completion criteria
1. Describe the shipped behavior, not an implementation plan.
1. Every addition helps a user configure, use, or troubleshoot Homarr; omit incidental rendering and implementation details.
2. Keep names, defaults, paths, screenshots, links, and prerequisites consistent with code.
3. Update every affected page and remove superseded guidance.
3. Correct affected guidance and remove superseded instructions. A code change alone does not require a docs edit.
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.
@@ -1,4 +1,4 @@
interface:
display_name: "Homarr Documentation Sync"
short_description: "Keep user-facing docs aligned with code"
default_prompt: "Use $documentation-sync to map this Homarr code change to the required documentation updates."
short_description: "Keep user docs concise, useful, and accurate"
default_prompt: "Use $documentation-sync to decide whether this Homarr change needs user guidance and update only what users need to know."
+1 -1
View File
@@ -10,7 +10,7 @@
- [ ] Pull request targets the intended base branch (`dev` by default; `release/v2` for v2 release work)
- [ ] Commits follow the [conventional commits guideline](https://www.conventionalcommits.org/en/v1.0.0/)
- [ ] No shorthand variable names are used (for example, `x`, `y`, `i`, or abbreviations)
- [ ] User-facing changes include matching documentation updates under `apps/docs`
- [ ] Changes to setup, usage, troubleshooting, or existing guidance include relevant documentation updates under `apps/docs` when needed
- [ ] When using AI, no temporary files are checked in and the code style follows the rest of the project
**When contributing a new integration or widget:**
+2 -2
View File
@@ -59,7 +59,7 @@ homarr/
The documentation site lives at `apps/docs/` (Docusaurus 3, `@homarr/docs`).
When modifying user-facing code, you MUST also update the corresponding documentation:
Update documentation when a change affects what users need to know to configure, use, or troubleshoot Homarr, or makes existing guidance inaccurate. Follow `.agents/skills/documentation-sync/SKILL.md` to decide whether an update is needed and keep it concise. For changes that need documentation:
- New integration → `apps/docs/docs/integrations/<slug>/index.mdx` + `index.ts`
- New widget → `apps/docs/docs/widgets/<slug>/index.mdx` + `index.ts`
@@ -99,6 +99,6 @@ When modifying user-facing code, you MUST also update the corresponding document
Portable skills live in `.agents/skills/`. Read the relevant `SKILL.md` before working in that domain; detailed references are loaded only when needed. Claude-compatible discovery is provided through `.claude/skills`.
- `codebase-context` — architecture, package boundaries, and shared utilities
- `documentation-sync` — required user-facing documentation updates
- `documentation-sync` — concise, relevant user guidance
- `mcp-integration` — safe tRPC-to-MCP exposure
- `homarr-custom-widget` — safe Custom JSX v2 authoring
@@ -31,9 +31,6 @@ Tiles use fixed `200 × 200` logical-pixel cells with a `24px` gap. Homarr scale
width instead of changing each widget's proportions. **Reset from Base** regenerates a Mobile or custom layout from the
current Base layout.
Widgets choose compact layouts from their visible size, including scaling inside nested Containers. Text and controls
retain readable sizing as the board shrinks; opening a widget's advanced view uses the available space in that view.
### Containers and rails
A **Container** groups apps, widgets, and nested Containers. It can have a label, collapse control, app-opening action,
+34 -18
View File
@@ -67,7 +67,8 @@
"type": "object",
"properties": {
"id": {
"type": "string"
"type": "string",
"maxLength": 64
},
"name": {
"type": "string"
@@ -205,7 +206,8 @@
"type": "object",
"properties": {
"id": {
"type": "string"
"type": "string",
"maxLength": 64
},
"name": {
"type": "string"
@@ -400,7 +402,8 @@
"type": "object",
"properties": {
"id": {
"type": "string"
"type": "string",
"maxLength": 64
},
"name": {
"type": "string"
@@ -539,7 +542,8 @@
"type": "object",
"properties": {
"id": {
"type": "string"
"type": "string",
"maxLength": 64
},
"name": {
"type": "string"
@@ -667,7 +671,8 @@
"type": "object",
"properties": {
"id": {
"type": "string"
"type": "string",
"maxLength": 64
},
"name": {
"type": "string"
@@ -783,7 +788,8 @@
"type": "object",
"properties": {
"id": {
"type": "string"
"type": "string",
"maxLength": 64
},
"name": {
"type": "string"
@@ -2304,7 +2310,8 @@
"traefik",
"customApi",
"assistant",
"wud"
"wud",
"llamacpp"
]
},
"options": {
@@ -2481,7 +2488,8 @@
"type": "object",
"properties": {
"id": {
"type": "string"
"type": "string",
"maxLength": 64
},
"expirationDate": {
"type": "string"
@@ -3108,7 +3116,8 @@
"type": "object",
"properties": {
"id": {
"type": "string"
"type": "string",
"maxLength": 64
},
"name": {
"anyOf": [
@@ -3341,7 +3350,8 @@
"type": "object",
"properties": {
"id": {
"type": "string"
"type": "string",
"maxLength": 64
},
"name": {
"anyOf": [
@@ -3486,7 +3496,8 @@
"type": "object",
"properties": {
"id": {
"type": "string"
"type": "string",
"maxLength": 64
},
"name": {
"anyOf": [
@@ -3604,7 +3615,8 @@
"type": "object",
"properties": {
"id": {
"type": "string"
"type": "string",
"maxLength": 64
},
"name": {
"anyOf": [
@@ -3647,12 +3659,14 @@
]
},
"provider": {
"type": "string"
"type": "string",
"maxLength": 64
},
"homeBoardId": {
"anyOf": [
{
"type": "string"
"type": "string",
"maxLength": 64
},
{
"type": "null"
@@ -3662,7 +3676,8 @@
"mobileHomeBoardId": {
"anyOf": [
{
"type": "string"
"type": "string",
"maxLength": 64
},
{
"type": "null"
@@ -3678,8 +3693,8 @@
},
"firstDayOfWeek": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
"minimum": -32768,
"maximum": 32767
},
"pingIconsEnabled": {
"type": "boolean"
@@ -3693,7 +3708,8 @@
"defaultSearchEngineId": {
"anyOf": [
{
"type": "string"
"type": "string",
"maxLength": 64
},
{
"type": "null"
+6 -4
View File
@@ -20,11 +20,11 @@ import { formatBytes, formatNumber } from "@homarr/common";
import { useI18n } from "@homarr/translation/client";
import { WidgetEmptyState } from "../common/empty-state";
import { getWidgetLayoutSize } from "../common/widget-layout-size";
import type { WidgetComponentProps } from "../definition";
import { NoIntegrationSelectedError } from "../errors/no-integration-selected";
// Board grid: a widget N cells wide is N*200 + (N-1)*12 px (1→200, 2→412, 3→624, 4→836).
// Width drives how much info fits side-by-side; height only matters for the
// Visible width drives how much info fits side-by-side; height only matters for the
// single-row (short) case where the widget must drop down to essentials.
const isNarrowWidth = (width: number) => width < 300; // 1 cell (200px)
const isWideWidth = (width: number) => width >= 550; // 3+ cells (624px+)
@@ -43,9 +43,11 @@ export default function LlamacppWidget({
options,
width,
height,
displayScale,
displayMode = "compact",
}: WidgetComponentProps<"llamacpp">) {
const integrationId = integrationIds[0];
const layoutSize = getWidgetLayoutSize({ width, height, displayScale, displayMode });
if (!integrationId) {
throw new NoIntegrationSelectedError();
}
@@ -54,8 +56,8 @@ export default function LlamacppWidget({
<LlamacppContent
integrationId={integrationId}
options={options}
width={width}
height={height}
width={layoutSize.width}
height={layoutSize.height}
displayMode={displayMode}
/>
);