From 6d204c9aaa391f4679b3de5d530e9f3a3b9f451b Mon Sep 17 00:00:00 2001 From: Thomas Camlong Date: Mon, 20 Jul 2026 17:04:30 +0200 Subject: [PATCH] fix: remove auto-placement of widgets for all integrations on new boards The seed pipeline and onboarding flow auto-placed a widget for every integration that existed in the database. This is overly aggressive and places obscure widgets (like ArchiveTeam Warrior) on every new dashboard. Now only explicitly listed default widgets (clock, weather, bookmarks) and apps are placed automatically. --- .../api/src/router/onboard/onboard-router.ts | 2 - packages/db/migrations/seed.ts | 2 - packages/db/queries/widget-placement.ts | 56 +++---------------- 3 files changed, 8 insertions(+), 52 deletions(-) diff --git a/packages/api/src/router/onboard/onboard-router.ts b/packages/api/src/router/onboard/onboard-router.ts index 4f43a9533..e7e5c4f0d 100644 --- a/packages/api/src/router/onboard/onboard-router.ts +++ b/packages/api/src/router/onboard/onboard-router.ts @@ -271,7 +271,6 @@ export const onboardRouter = createTRPCRouter({ setupIntegrations: onboardingProcedure.requiresStep("integrations").mutation(async ({ ctx }) => { const db = ctx.db; - const allIntegrations = await db.query.integrations.findMany(); const allApps = await db.query.apps.findMany(); const board = await db.query.boards.findFirst({ @@ -316,7 +315,6 @@ export const onboardRouter = createTRPCRouter({ layoutId: layout.id, columnCount: layout.columnCount, }, - allIntegrations, allApps, ); } diff --git a/packages/db/migrations/seed.ts b/packages/db/migrations/seed.ts index 6ec906cec..fb624b69e 100644 --- a/packages/db/migrations/seed.ts +++ b/packages/db/migrations/seed.ts @@ -698,13 +698,11 @@ const seedBoardWidgetsAsync = async (db: Database) => { const layout = board.layouts[0]; if (!section || !layout) return; - const allIntegrations = await db.query.integrations.findMany(); const allApps = await db.query.apps.findMany(); const count = await placeAllWidgetsAsync( db, { boardId: board.id, sectionId: section.id, layoutId: layout.id, columnCount: layout.columnCount }, - allIntegrations, allApps, ); diff --git a/packages/db/queries/widget-placement.ts b/packages/db/queries/widget-placement.ts index 1d0b529f9..f0e24937e 100644 --- a/packages/db/queries/widget-placement.ts +++ b/packages/db/queries/widget-placement.ts @@ -1,19 +1,11 @@ -import superjson from "superjson"; +import { stringify } from "superjson"; import { createId } from "@homarr/common"; -import { - defaultBookmarkApps, - defaultWidgetConfigs, - emptySuperJSON, - getWidgetKindsForIntegration, -} from "@homarr/definitions"; +import { defaultBookmarkApps, defaultWidgetConfigs, emptySuperJSON } from "@homarr/definitions"; import type { WidgetKind } from "@homarr/definitions"; import type { Database } from ".."; import { integrationItems, itemLayouts, items } from "../schema"; -import type { Integration } from "../schema"; - -const widgetConfigMap = new Map(defaultWidgetConfigs.map((config) => [config.kind, config])); interface BoardTarget { boardId: string; @@ -77,12 +69,7 @@ interface App { name: string; } -export const placeAllWidgetsAsync = async ( - db: Database, - target: BoardTarget, - allIntegrations: Integration[], - allApps: App[], -) => { +export const placeAllWidgetsAsync = async (db: Database, target: BoardTarget, allApps: App[]) => { const ctx: PlacementContext = { ...target, xOffset: 0, @@ -92,38 +79,11 @@ export const placeAllWidgetsAsync = async ( const placedWidgets = new Set(); - for (const integration of allIntegrations) { - for (const widgetKind of getWidgetKindsForIntegration(integration.kind)) { - if (placedWidgets.has(widgetKind)) continue; - const config = widgetConfigMap.get(widgetKind); - if (config?.skip) continue; - placedWidgets.add(widgetKind); - - const matchingIds = allIntegrations - .filter((row) => getWidgetKindsForIntegration(row.kind).includes(widgetKind)) - .map((row) => row.id); - - const options = config?.options ? superjson.stringify(config.options) : undefined; - await placeWidgetAsync( - db, - ctx, - widgetKind, - matchingIds, - options, - config && { width: config.width, height: config.height }, - ); - } - } - for (const app of allApps) { - await placeWidgetAsync( - db, - ctx, - "app", - [], - superjson.stringify({ appId: app.id, openInNewTab: true, showTitle: true }), - { width: 1, height: 1 }, - ); + await placeWidgetAsync(db, ctx, "app", [], stringify({ appId: app.id, openInNewTab: true, showTitle: true }), { + width: 1, + height: 1, + }); } const bookmarkAppNames = new Set(defaultBookmarkApps.map((bookmark) => bookmark.name)); @@ -138,7 +98,7 @@ export const placeAllWidgetsAsync = async ( options = { ...options, items: bookmarkAppIds }; } - await placeWidgetAsync(db, ctx, config.kind, [], options ? superjson.stringify(options) : undefined, { + await placeWidgetAsync(db, ctx, config.kind, [], options ? stringify(options) : undefined, { width: config.width, height: config.height, });