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.
This commit is contained in:
Thomas Camlong committed 2026-07-20 17:04:30 +02:00
1 parent 070e186b57
commit 6d204c9aaa
3 files changed
+8 -52

No files matched your search

@@ -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,
);
}
-2
View File
@@ -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,
);
+8 -48
View File
@@ -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<WidgetKind>();
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,
});