diff --git a/.changeset/fn-7874-storage-banner-get-help.md b/.changeset/fn-7874-storage-banner-get-help.md
new file mode 100644
index 0000000000..9916d61453
--- /dev/null
+++ b/.changeset/fn-7874-storage-banner-get-help.md
@@ -0,0 +1,7 @@
+---
+"@runfusion/fusion": minor
+---
+
+summary: Storage update banner now has a Get help (Discord) button and notes project DBs move to the central Fusion database.
+category: feature
+dev: Adds `storageMigrationNotice.getHelp`/`getHelpLabel` i18n keys and a hardened Discord link in `StorageMigrationNoticeBanner`; revised body copy in `en/app.json` and component default.
diff --git a/packages/dashboard/app/components/StorageMigrationNoticeBanner.css b/packages/dashboard/app/components/StorageMigrationNoticeBanner.css
index ced2063d6d..bc8affaeb3 100644
--- a/packages/dashboard/app/components/StorageMigrationNoticeBanner.css
+++ b/packages/dashboard/app/components/StorageMigrationNoticeBanner.css
@@ -37,6 +37,23 @@
color: var(--text-muted);
}
+.storage-migration-notice-banner__actions {
+ display: flex;
+ flex-wrap: wrap;
+ align-items: center;
+ gap: var(--space-xs);
+}
+
+.storage-migration-notice-banner__help {
+ align-self: flex-start;
+ text-decoration: none;
+}
+
+.storage-migration-notice-banner__help:focus-visible {
+ outline: none;
+ box-shadow: var(--focus-ring-strong);
+}
+
.storage-migration-notice-banner__dismiss {
display: inline-flex;
align-items: center;
@@ -67,6 +84,15 @@
align-items: stretch;
}
+ .storage-migration-notice-banner__actions {
+ align-items: stretch;
+ }
+
+ .storage-migration-notice-banner__help {
+ justify-content: center;
+ width: 100%;
+ }
+
.storage-migration-notice-banner__dismiss {
align-self: flex-start;
}
diff --git a/packages/dashboard/app/components/StorageMigrationNoticeBanner.tsx b/packages/dashboard/app/components/StorageMigrationNoticeBanner.tsx
index 3fc63155bf..a9e325b779 100644
--- a/packages/dashboard/app/components/StorageMigrationNoticeBanner.tsx
+++ b/packages/dashboard/app/components/StorageMigrationNoticeBanner.tsx
@@ -8,6 +8,9 @@ export const STORAGE_MIGRATION_NOTICE_DISMISS_KEY = "fusion:storage-migration-no
/*
FNXC:StorageMigrationNotice 2026-07-12-00:00:
The dashboard must announce the next-version SQLite → embedded Postgres storage change before operators upgrade. Dismissal is global rather than project-scoped because the notice describes an app-wide on-disk storage engine change, not a per-project condition; localStorage persistence makes the one-time acknowledgement permanent on this browser profile.
+
+FNXC:StorageMigrationNotice 2026-07-12-00:10:
+Operators need immediate support and clear storage-impact wording from the notice itself, so the banner links to the hardened Fusion Discord destination and states that project databases will be served from the central Fusion database instead of each project's local SQLite file.
*/
function isDismissed(): boolean {
if (typeof window === "undefined") return false;
@@ -48,9 +51,20 @@ export function StorageMigrationNoticeBanner() {
{t(
"storageMigrationNotice.body",
- "The next Fusion version will replace the current SQLite data store with an embedded Postgres backend for data storage. No migration runs from this notice; it is an advance heads-up for operators who rely on the current .fusion/fusion.db SQLite file.",
+ "The next Fusion version will replace the current SQLite data store with an embedded Postgres backend for data storage, and project databases will be served from the central Fusion database instead of each project's local .fusion/fusion.db SQLite file. No migration runs from this notice; it is an advance heads-up for operators who rely on the current storage layout.",
)}
+
{
@@ -29,12 +31,18 @@ describe("StorageMigrationNoticeBanner", () => {
window.localStorage.clear();
});
- it("renders the storage notice when the dismissal key is absent", () => {
+ it("renders the storage notice and hardened Discord help link when the dismissal key is absent", () => {
render( );
expect(screen.getByRole("status")).toBeInTheDocument();
expect(screen.getByText(title)).toBeInTheDocument();
expect(screen.getByText(body)).toBeInTheDocument();
+ const getHelpLink = screen.getByRole("link", { name: getHelpLabel });
+ expect(getHelpLink).toHaveAttribute("href", discordUrl);
+ expect(getHelpLink).toHaveAttribute("target", "_blank");
+ expect(getHelpLink.getAttribute("rel")?.split(" ")).toEqual(
+ expect.arrayContaining(["noopener", "noreferrer"]),
+ );
expect(screen.getByRole("button", { name: dismissLabel })).toBeInTheDocument();
});
@@ -46,6 +54,7 @@ describe("StorageMigrationNoticeBanner", () => {
expect(window.localStorage.getItem(STORAGE_MIGRATION_NOTICE_DISMISS_KEY)).toBe("1");
expect(screen.queryByRole("status")).not.toBeInTheDocument();
expect(screen.queryByRole("button", { name: dismissLabel })).not.toBeInTheDocument();
+ expect(screen.queryByRole("link", { name: getHelpLabel })).not.toBeInTheDocument();
});
it("returns null on a fresh mount when the dismissal key is already persisted", () => {
@@ -56,6 +65,7 @@ describe("StorageMigrationNoticeBanner", () => {
expect(screen.queryByRole("status")).not.toBeInTheDocument();
expect(screen.queryByText(title)).not.toBeInTheDocument();
expect(screen.queryByRole("button", { name: dismissLabel })).not.toBeInTheDocument();
+ expect(screen.queryByRole("link", { name: getHelpLabel })).not.toBeInTheDocument();
});
it("does not crash when localStorage getItem or setItem throws", () => {
@@ -73,6 +83,8 @@ describe("StorageMigrationNoticeBanner", () => {
expect(() => render( )).not.toThrow();
expect(screen.getByRole("status")).toBeInTheDocument();
+ expect(screen.getByText(body)).toBeInTheDocument();
+ expect(screen.getByRole("link", { name: getHelpLabel })).toHaveAttribute("href", discordUrl);
expect(() => {
fireEvent.click(screen.getByRole("button", { name: dismissLabel }));
diff --git a/packages/i18n/locales/en/app.json b/packages/i18n/locales/en/app.json
index 2cdb6c5e44..84cdb350ae 100644
--- a/packages/i18n/locales/en/app.json
+++ b/packages/i18n/locales/en/app.json
@@ -1421,8 +1421,10 @@
"versionMismatchSuffix": "Update to stay in sync."
},
"storageMigrationNotice": {
- "body": "The next Fusion version will replace the current SQLite data store with an embedded Postgres backend for data storage. No migration runs from this notice; it is an advance heads-up for operators who rely on the current .fusion/fusion.db SQLite file.",
+ "body": "The next Fusion version will replace the current SQLite data store with an embedded Postgres backend for data storage, and project databases will be served from the central Fusion database instead of each project's local .fusion/fusion.db SQLite file. No migration runs from this notice; it is an advance heads-up for operators who rely on the current storage layout.",
"dismissLabel": "Dismiss storage update notice",
+ "getHelp": "Get help",
+ "getHelpLabel": "Get help on Discord",
"title": "Storage update coming in the next Fusion version"
},
"cliBinary": {
diff --git a/packages/i18n/locales/es/app.json b/packages/i18n/locales/es/app.json
index b9405bb4d8..e560b85988 100644
--- a/packages/i18n/locales/es/app.json
+++ b/packages/i18n/locales/es/app.json
@@ -1413,6 +1413,8 @@
"storageMigrationNotice": {
"body": "",
"dismissLabel": "",
+ "getHelp": "",
+ "getHelpLabel": "",
"title": ""
},
"cliBinary": {
@@ -2446,6 +2448,7 @@
"previewTitle": "Vista previa de {{file}}"
},
"fileEditor": {
+ "autoSave": "",
"edit": "Editar",
"editMode": "Modo editar",
"editorFor": "Editor para {{filePath}}",
@@ -2453,6 +2456,7 @@
"lineNumber": "Línea #",
"preview": "Vista previa",
"previewMode": "Modo vista previa",
+ "toggleAutoSave": "",
"toggleLineNumbers": "Alternar números de línea",
"toggleOptions": "Alternar opciones del editor",
"toggleWordWrap": "Alternar ajuste de palabra",
@@ -8357,6 +8361,7 @@
},
"todo": {
"addItemPlaceholder": "Agregar elemento de tarea",
+ "allDoneHidden": "",
"addList": "Agregar lista",
"assignAgent": "Asignar {{text}} al agente",
"cancelItemEdit": "Cancelar edición de elemento",
@@ -8386,6 +8391,7 @@
"failedToCreateTask": "Error al crear la tarea: {{error}}",
"failedToLoadAgents": "Error al cargar agentes: {{error}}",
"failedUpdateItem": "Error al actualizar el elemento",
+ "hideDone": "",
"failedUpdateItemToast": "Error al actualizar el elemento de tareas pendientes",
"itemsLabel": "Elementos de tareas",
"lists": "Listas",
@@ -8405,6 +8411,7 @@
"saveListRename": "Guardar cambio de nombre de lista",
"selectList": "Seleccionar lista {{title}}",
"selectListEmpty": "Seleccione una lista de la barra lateral",
+ "showDone": "",
"startPlanning": "Comenzar a planificar desde {{text}}",
"taskCreatedAndAssigned": "Creado {{id}} y asignado a {{agent}}",
"taskCreatedFromTodo": "Creado {{id}} desde la lista de tareas",
diff --git a/packages/i18n/locales/fr/app.json b/packages/i18n/locales/fr/app.json
index da274989b5..bc546d757d 100644
--- a/packages/i18n/locales/fr/app.json
+++ b/packages/i18n/locales/fr/app.json
@@ -1413,6 +1413,8 @@
"storageMigrationNotice": {
"body": "",
"dismissLabel": "",
+ "getHelp": "",
+ "getHelpLabel": "",
"title": ""
},
"cliBinary": {
@@ -2446,6 +2448,7 @@
"previewTitle": "Aperçu de {{file}}"
},
"fileEditor": {
+ "autoSave": "",
"edit": "Modifier",
"editMode": "Mode édition",
"editorFor": "Éditeur pour {{filePath}}",
@@ -2453,6 +2456,7 @@
"lineNumber": "Ligne #",
"preview": "Aperçu",
"previewMode": "Mode aperçu",
+ "toggleAutoSave": "",
"toggleLineNumbers": "Basculer les numéros de ligne",
"toggleOptions": "Basculer les options de l'éditeur",
"toggleWordWrap": "Basculer le retour à la ligne automatique",
@@ -8357,6 +8361,7 @@
},
"todo": {
"addItemPlaceholder": "Ajouter un élément de tâche",
+ "allDoneHidden": "",
"addList": "Ajouter une liste",
"assignAgent": "Assigner {{text}} à l'agent",
"cancelItemEdit": "Annuler la modification de l'élément",
@@ -8386,6 +8391,7 @@
"failedToCreateTask": "Échec de la création de la tâche : {{error}}",
"failedToLoadAgents": "Échec du chargement des agents : {{error}}",
"failedUpdateItem": "Échec de la mise à jour de l'élément",
+ "hideDone": "",
"failedUpdateItemToast": "Échec de la mise à jour de la tâche à faire",
"itemsLabel": "Éléments de la liste de tâches",
"lists": "Listes",
@@ -8405,6 +8411,7 @@
"saveListRename": "Enregistrer le renommage de la liste",
"selectList": "Sélectionner la liste {{title}}",
"selectListEmpty": "Sélectionnez une liste dans la barre latérale",
+ "showDone": "",
"startPlanning": "Commencer à planifier à partir de {{text}}",
"taskCreatedAndAssigned": "Créé {{id}} et assigné à {{agent}}",
"taskCreatedFromTodo": "Créé {{id}} à partir de la liste de tâches",
diff --git a/packages/i18n/locales/ko/app.json b/packages/i18n/locales/ko/app.json
index a7057ec042..705304995c 100644
--- a/packages/i18n/locales/ko/app.json
+++ b/packages/i18n/locales/ko/app.json
@@ -1413,6 +1413,8 @@
"storageMigrationNotice": {
"body": "",
"dismissLabel": "",
+ "getHelp": "",
+ "getHelpLabel": "",
"title": ""
},
"cliBinary": {
@@ -2446,6 +2448,7 @@
"previewTitle": "{{file}} 미리보기"
},
"fileEditor": {
+ "autoSave": "",
"edit": "편집",
"editMode": "편집 모드",
"editorFor": "{{filePath}} 편집기",
@@ -2453,6 +2456,7 @@
"lineNumber": "줄 번호",
"preview": "미리보기",
"previewMode": "미리보기 모드",
+ "toggleAutoSave": "",
"toggleLineNumbers": "줄 번호 표시 토글",
"toggleOptions": "편집기 옵션 토글",
"toggleWordWrap": "자동 줄 바꿈 토글",
@@ -8357,6 +8361,7 @@
},
"todo": {
"addItemPlaceholder": "할 일 항목 추가",
+ "allDoneHidden": "",
"addList": "목록 추가",
"assignAgent": "{{text}}을(를) 에이전트에 할당",
"cancelItemEdit": "항목 편집 취소",
@@ -8386,6 +8391,7 @@
"failedToCreateTask": "작업 생성 실패: {{error}}",
"failedToLoadAgents": "에이전트 불러오기 실패: {{error}}",
"failedUpdateItem": "항목 업데이트 실패",
+ "hideDone": "",
"failedUpdateItemToast": "할 일 항목 업데이트에 실패했습니다",
"itemsLabel": "할 일 항목",
"lists": "목록",
@@ -8405,6 +8411,7 @@
"saveListRename": "목록 이름 바꾸기 저장",
"selectList": "{{title}} 목록 선택",
"selectListEmpty": "사이드바에서 목록을 선택하세요",
+ "showDone": "",
"startPlanning": "{{text}}에서 계획 시작",
"taskCreatedAndAssigned": "{{id}} 생성 후 {{agent}}에 할당됨",
"taskCreatedFromTodo": "할 일에서 {{id}} 생성됨",
diff --git a/packages/i18n/locales/zh-CN/app.json b/packages/i18n/locales/zh-CN/app.json
index 428e021674..b83200f334 100644
--- a/packages/i18n/locales/zh-CN/app.json
+++ b/packages/i18n/locales/zh-CN/app.json
@@ -1413,6 +1413,8 @@
"storageMigrationNotice": {
"body": "",
"dismissLabel": "",
+ "getHelp": "",
+ "getHelpLabel": "",
"title": ""
},
"cliBinary": {
@@ -2446,6 +2448,7 @@
"previewTitle": "{{file}} 的预览"
},
"fileEditor": {
+ "autoSave": "",
"edit": "编辑",
"editMode": "编辑模式",
"editorFor": "{{filePath}}编辑器",
@@ -2453,6 +2456,7 @@
"lineNumber": "行号",
"preview": "预览",
"previewMode": "预览模式",
+ "toggleAutoSave": "",
"toggleLineNumbers": "切换行号",
"toggleOptions": "切换编辑器选项",
"toggleWordWrap": "切换自动换行",
@@ -8357,6 +8361,7 @@
},
"todo": {
"addItemPlaceholder": "添加待办事项",
+ "allDoneHidden": "",
"addList": "添加列表",
"assignAgent": "将 {{text}} 分配给代理",
"cancelItemEdit": "取消项目编辑",
@@ -8386,6 +8391,7 @@
"failedToCreateTask": "创建任务失败:{{error}}",
"failedToLoadAgents": "加载代理失败:{{error}}",
"failedUpdateItem": "更新项失败",
+ "hideDone": "",
"failedUpdateItemToast": "更新待办事项失败",
"itemsLabel": "待办事项",
"lists": "列表",
@@ -8405,6 +8411,7 @@
"saveListRename": "保存列表重命名",
"selectList": "选择列表 {{title}}",
"selectListEmpty": "从边栏选择一个列表",
+ "showDone": "",
"startPlanning": "从 {{text}} 开始规划",
"taskCreatedAndAssigned": "创建了 {{id}} 并分配给 {{agent}}",
"taskCreatedFromTodo": "从待办事项创建了 {{id}}",
diff --git a/packages/i18n/locales/zh-TW/app.json b/packages/i18n/locales/zh-TW/app.json
index c075b47ebe..7524e3db8d 100644
--- a/packages/i18n/locales/zh-TW/app.json
+++ b/packages/i18n/locales/zh-TW/app.json
@@ -1413,6 +1413,8 @@
"storageMigrationNotice": {
"body": "",
"dismissLabel": "",
+ "getHelp": "",
+ "getHelpLabel": "",
"title": ""
},
"cliBinary": {
@@ -2446,6 +2448,7 @@
"previewTitle": "{{file}} 的預覽"
},
"fileEditor": {
+ "autoSave": "",
"edit": "編輯",
"editMode": "編輯模式",
"editorFor": "{{filePath}}編輯器",
@@ -2453,6 +2456,7 @@
"lineNumber": "行號",
"preview": "預覽",
"previewMode": "預覽模式",
+ "toggleAutoSave": "",
"toggleLineNumbers": "切換行號",
"toggleOptions": "切換編輯器選項",
"toggleWordWrap": "切換自動換行",
@@ -8357,6 +8361,7 @@
},
"todo": {
"addItemPlaceholder": "新增待辦事項",
+ "allDoneHidden": "",
"addList": "新增清單",
"assignAgent": "將 {{text}} 指派給代理",
"cancelItemEdit": "取消項目編輯",
@@ -8386,6 +8391,7 @@
"failedToCreateTask": "建立任務失敗:{{error}}",
"failedToLoadAgents": "加載代理失敗:{{error}}",
"failedUpdateItem": "更新項目失敗",
+ "hideDone": "",
"failedUpdateItemToast": "更新待辦項目失敗",
"itemsLabel": "待辦事項",
"lists": "清單",
@@ -8405,6 +8411,7 @@
"saveListRename": "保存清單重新命名",
"selectList": "選擇清單 {{title}}",
"selectListEmpty": "從側邊欄選擇清單",
+ "showDone": "",
"startPlanning": "從 {{text}} 開始規劃",
"taskCreatedAndAssigned": "建立了 {{id}} 並指派給 {{agent}}",
"taskCreatedFromTodo": "從待辦事項建立了 {{id}}",
diff --git a/packages/i18n/src/resources.d.ts b/packages/i18n/src/resources.d.ts
index 11061a4058..1b553d56f9 100644
--- a/packages/i18n/src/resources.d.ts
+++ b/packages/i18n/src/resources.d.ts
@@ -1412,6 +1412,13 @@ export default interface Resources {
"versionMismatchPrefix": "Your installed",
"versionMismatchSuffix": "Update to stay in sync."
},
+ "storageMigrationNotice": {
+ "body": "The next Fusion version will replace the current SQLite data store with an embedded Postgres backend for data storage, and project databases will be served from the central Fusion database instead of each project's local .fusion/fusion.db SQLite file. No migration runs from this notice; it is an advance heads-up for operators who rely on the current storage layout.",
+ "dismissLabel": "Dismiss storage update notice",
+ "getHelp": "Get help",
+ "getHelpLabel": "Get help on Discord",
+ "title": "Storage update coming in the next Fusion version"
+ },
"cliBinary": {
"binaryLabel": "Binary:",
"checking": "Checking…",