diff --git a/packages/desktop-client/e2e/reports.test.js-snapshots/Reports-loads-cash-flow-graph-and-checks-visuals-1-chromium-linux.png b/packages/desktop-client/e2e/reports.test.js-snapshots/Reports-loads-cash-flow-graph-and-checks-visuals-1-chromium-linux.png
index 7ee3aa5afa31bb300e22542905fba7cbc6769e66..48901464a065658245c7a3ed25b6d42e5bf08cca 100644
Binary files a/packages/desktop-client/e2e/reports.test.js-snapshots/Reports-loads-cash-flow-graph-and-checks-visuals-1-chromium-linux.png and b/packages/desktop-client/e2e/reports.test.js-snapshots/Reports-loads-cash-flow-graph-and-checks-visuals-1-chromium-linux.png differ
diff --git a/packages/desktop-client/e2e/reports.test.js-snapshots/Reports-loads-cash-flow-graph-and-checks-visuals-2-chromium-linux.png b/packages/desktop-client/e2e/reports.test.js-snapshots/Reports-loads-cash-flow-graph-and-checks-visuals-2-chromium-linux.png
index e2547a23cbe856ad07b8012a0a6fd8587a3d6496..aa2e7d20f4b9276db56d69cf4acd7e63b7a7bf1e 100644
Binary files a/packages/desktop-client/e2e/reports.test.js-snapshots/Reports-loads-cash-flow-graph-and-checks-visuals-2-chromium-linux.png and b/packages/desktop-client/e2e/reports.test.js-snapshots/Reports-loads-cash-flow-graph-and-checks-visuals-2-chromium-linux.png differ
diff --git a/packages/desktop-client/e2e/reports.test.js-snapshots/Reports-loads-cash-flow-graph-and-checks-visuals-3-chromium-linux.png b/packages/desktop-client/e2e/reports.test.js-snapshots/Reports-loads-cash-flow-graph-and-checks-visuals-3-chromium-linux.png
index 3ca0d4d3aff6d21623295272e55185ab199c2f09..42b40b2ca0a8df0fc972ddb49d3a68654724abd1 100644
Binary files a/packages/desktop-client/e2e/reports.test.js-snapshots/Reports-loads-cash-flow-graph-and-checks-visuals-3-chromium-linux.png and b/packages/desktop-client/e2e/reports.test.js-snapshots/Reports-loads-cash-flow-graph-and-checks-visuals-3-chromium-linux.png differ
diff --git a/packages/desktop-client/e2e/reports.test.js-snapshots/Reports-loads-net-worth-graph-and-checks-visuals-1-chromium-linux.png b/packages/desktop-client/e2e/reports.test.js-snapshots/Reports-loads-net-worth-graph-and-checks-visuals-1-chromium-linux.png
index 6e65aea4e2462823f73f189281ab10337b84d671..cbfaf0d8c686f84dd41f7c072e8c0cb0fbbb2647 100644
Binary files a/packages/desktop-client/e2e/reports.test.js-snapshots/Reports-loads-net-worth-graph-and-checks-visuals-1-chromium-linux.png and b/packages/desktop-client/e2e/reports.test.js-snapshots/Reports-loads-net-worth-graph-and-checks-visuals-1-chromium-linux.png differ
diff --git a/packages/desktop-client/e2e/reports.test.js-snapshots/Reports-loads-net-worth-graph-and-checks-visuals-2-chromium-linux.png b/packages/desktop-client/e2e/reports.test.js-snapshots/Reports-loads-net-worth-graph-and-checks-visuals-2-chromium-linux.png
index cd3672d33309f39b09630637836daa75babc2f06..22495266223823edbd448818b8440bba7a8c4430 100644
Binary files a/packages/desktop-client/e2e/reports.test.js-snapshots/Reports-loads-net-worth-graph-and-checks-visuals-2-chromium-linux.png and b/packages/desktop-client/e2e/reports.test.js-snapshots/Reports-loads-net-worth-graph-and-checks-visuals-2-chromium-linux.png differ
diff --git a/packages/desktop-client/e2e/reports.test.js-snapshots/Reports-loads-net-worth-graph-and-checks-visuals-3-chromium-linux.png b/packages/desktop-client/e2e/reports.test.js-snapshots/Reports-loads-net-worth-graph-and-checks-visuals-3-chromium-linux.png
index 386eaeb60e1b7ead9505ba877d432c233f804614..480c10477584c972a94a1b63df2b6dbc026f2312 100644
Binary files a/packages/desktop-client/e2e/reports.test.js-snapshots/Reports-loads-net-worth-graph-and-checks-visuals-3-chromium-linux.png and b/packages/desktop-client/e2e/reports.test.js-snapshots/Reports-loads-net-worth-graph-and-checks-visuals-3-chromium-linux.png differ
diff --git a/packages/desktop-client/src/components/common/Button2.tsx b/packages/desktop-client/src/components/common/Button2.tsx
index a48c1bb8dc3ebfa31fbf575370428e60905f4edb..0fb4860fff6c98eca467771f6d2ab9ec9c81a4fc 100644
--- a/packages/desktop-client/src/components/common/Button2.tsx
+++ b/packages/desktop-client/src/components/common/Button2.tsx
@@ -1,4 +1,10 @@
-import React, { forwardRef, type ComponentPropsWithoutRef } from 'react';
+import React, {
+  forwardRef,
+  type ComponentPropsWithoutRef,
+  type ComponentType,
+  type ReactNode,
+  type SVGProps,
+} from 'react';
 import {
   type ButtonRenderProps as ReactAriaButtonRenderProps,
   Button as ReactAriaButton,
@@ -121,13 +127,21 @@ const _getActiveStyles = (
 type ButtonProps = ComponentPropsWithoutRef<typeof ReactAriaButton> & {
   variant?: ButtonVariant;
   bounce?: boolean;
+  Icon?: ComponentType<SVGProps<SVGSVGElement>>;
+  children?: ReactNode;
 };
 
 type ButtonVariant = 'normal' | 'primary' | 'bare' | 'menu' | 'menuSelected';
 
 export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
   (props, ref) => {
-    const { children, variant = 'normal', bounce = true, ...restProps } = props;
+    const {
+      children,
+      variant = 'normal',
+      bounce = true,
+      Icon,
+      ...restProps
+    } = props;
 
     const variantWithDisabled: ButtonVariant | `${ButtonVariant}Disabled` =
       props.isDisabled ? `${variant}Disabled` : variant;
@@ -161,6 +175,7 @@ export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
           ...styles.smallText,
           ...(renderProps.isDisabled ? {} : { ':hover': hoveredStyle }),
           ...(renderProps.isDisabled ? {} : { ':active': activeStyle }),
+          ...(Icon ? { paddingLeft: 0 } : {}),
         }),
       );
 
@@ -177,6 +192,9 @@ export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
           `${renderProps.defaultClassName} ${defaultButtonClassName(renderProps)} ${buttonClassName(renderProps)}`
         }
       >
+        {Icon && (
+          <Icon style={{ height: 15, paddingLeft: 5, paddingRight: 3 }} />
+        )}
         {children}
       </ReactAriaButton>
     );
@@ -203,34 +221,30 @@ export const ButtonWithLoading = forwardRef<
         ...(typeof style === 'function' ? style(buttonRenderProps) : style),
       })}
     >
-      {renderProps => (
-        <>
-          {isLoading && (
-            <View
-              style={{
-                position: 'absolute',
-                top: 0,
-                left: 0,
-                right: 0,
-                bottom: 0,
-                alignItems: 'center',
-                justifyContent: 'center',
-              }}
-            >
-              <AnimatedLoading style={{ width: 20, height: 20 }} />
-            </View>
-          )}
-          <View
-            style={{
-              opacity: isLoading ? 0 : 1,
-              flexDirection: 'row',
-              alignItems: 'center',
-            }}
-          >
-            {typeof children === 'function' ? children(renderProps) : children}
-          </View>
-        </>
+      {isLoading && (
+        <View
+          style={{
+            position: 'absolute',
+            top: 0,
+            left: 0,
+            right: 0,
+            bottom: 0,
+            alignItems: 'center',
+            justifyContent: 'center',
+          }}
+        >
+          <AnimatedLoading style={{ width: 20, height: 20 }} />
+        </View>
       )}
+      <View
+        style={{
+          opacity: isLoading ? 0 : 1,
+          flexDirection: 'row',
+          alignItems: 'center',
+        }}
+      >
+        {children}
+      </View>
     </Button>
   );
 });
diff --git a/packages/desktop-client/src/components/reports/Header.jsx b/packages/desktop-client/src/components/reports/Header.tsx
similarity index 67%
rename from packages/desktop-client/src/components/reports/Header.jsx
rename to packages/desktop-client/src/components/reports/Header.tsx
index 1f8e4bc78d146b10ca1e963a5c4c5c6e3691d394..3414909928b576ba4be5b1052bb2875d39075959 100644
--- a/packages/desktop-client/src/components/reports/Header.jsx
+++ b/packages/desktop-client/src/components/reports/Header.tsx
@@ -1,7 +1,14 @@
+import { type ComponentProps, type ReactNode } from 'react';
 import { useLocation } from 'react-router-dom';
 
 import * as monthUtils from 'loot-core/src/shared/months';
+import {
+  type RuleConditionEntity,
+  type TimeFrame,
+} from 'loot-core/types/models';
 
+import { useFeatureFlag } from '../../hooks/useFeatureFlag';
+import { SvgPause, SvgPlay } from '../../icons/v1';
 import { useResponsive } from '../../ResponsiveProvider';
 import { Button } from '../common/Button2';
 import { Select } from '../common/Select';
@@ -16,9 +23,32 @@ import {
   validateStart,
 } from './reportRanges';
 
+type HeaderProps = {
+  start: TimeFrame['start'];
+  end: TimeFrame['end'];
+  mode?: TimeFrame['mode'];
+  show1Month?: boolean;
+  allMonths: Array<{ name: string; pretty: string }>;
+  onChangeDates: (
+    start: TimeFrame['start'],
+    end: TimeFrame['end'],
+    mode: TimeFrame['mode'],
+  ) => void;
+  filters?: RuleConditionEntity[];
+  conditionsOp: 'and' | 'or';
+  onApply?: (conditions: RuleConditionEntity) => void;
+  onUpdateFilter: ComponentProps<typeof AppliedFilters>['onUpdate'];
+  onDeleteFilter: ComponentProps<typeof AppliedFilters>['onDelete'];
+  onConditionsOpChange: ComponentProps<
+    typeof AppliedFilters
+  >['onConditionsOpChange'];
+  children?: ReactNode;
+};
+
 export function Header({
   start,
   end,
+  mode,
   show1Month,
   allMonths,
   onChangeDates,
@@ -28,9 +58,9 @@ export function Header({
   onUpdateFilter,
   onDeleteFilter,
   onConditionsOpChange,
-  headerPrefixItems,
   children,
-}) {
+}: HeaderProps) {
+  const isDashboardsFeatureEnabled = useFeatureFlag('dashboards');
   const location = useLocation();
   const path = location.pathname;
   const { isNarrowWidth } = useResponsive();
@@ -52,7 +82,21 @@ export function Header({
             gap: 15,
           }}
         >
-          {headerPrefixItems}
+          {isDashboardsFeatureEnabled && mode && (
+            <Button
+              variant={mode === 'static' ? 'normal' : 'primary'}
+              onPress={() =>
+                onChangeDates(
+                  start,
+                  end,
+                  mode === 'static' ? 'sliding-window' : 'static',
+                )
+              }
+              Icon={mode === 'static' ? SvgPause : SvgPlay}
+            >
+              {mode === 'static' ? 'Paused' : 'Live'}
+            </Button>
+          )}
 
           <View
             style={{
@@ -90,13 +134,6 @@ export function Header({
               options={allMonths.map(({ name, pretty }) => [name, pretty])}
               buttonStyle={{ marginRight: 10 }}
             />
-            {filters && (
-              <FilterButton
-                compact={isNarrowWidth}
-                onApply={onApply}
-                type="accounts"
-              />
-            )}
           </View>
 
           <View
@@ -143,18 +180,34 @@ export function Header({
             >
               All Time
             </Button>
+
+            {filters && (
+              <FilterButton
+                compact={isNarrowWidth}
+                onApply={onApply}
+                hover={false}
+                exclude={undefined}
+              />
+            )}
           </View>
-          {children || <View style={{ flex: 1 }} />}
+
+          {children ? (
+            <View
+              style={{
+                flex: 1,
+                flexDirection: 'row',
+                justifyContent: 'flex-end',
+              }}
+            >
+              {children}
+            </View>
+          ) : (
+            <View style={{ flex: 1 }} />
+          )}
         </View>
       )}
       {filters && filters.length > 0 && (
-        <View
-          style={{ marginTop: 5 }}
-          spacing={2}
-          direction="row"
-          justify="flex-start"
-          align="flex-start"
-        >
+        <View style={{ marginTop: 5 }}>
           <AppliedFilters
             conditions={filters}
             onUpdate={onUpdateFilter}
diff --git a/packages/desktop-client/src/components/reports/Overview.tsx b/packages/desktop-client/src/components/reports/Overview.tsx
index c775077666f51b99ac7cb798ff2f43c69f73d833..f234cf8122049c0a4bac8b04171fbd3f56d95120 100644
--- a/packages/desktop-client/src/components/reports/Overview.tsx
+++ b/packages/desktop-client/src/components/reports/Overview.tsx
@@ -528,6 +528,7 @@ export function Overview() {
               <div key={item.i}>
                 {item.type === 'net-worth-card' ? (
                   <NetWorthCard
+                    widgetId={item.i}
                     isEditing={isEditing}
                     accounts={accounts}
                     meta={item.meta}
diff --git a/packages/desktop-client/src/components/reports/ReportRouter.tsx b/packages/desktop-client/src/components/reports/ReportRouter.tsx
index 2fadf9f39b0b4e4273c8f603399dbda1d574a783..795658e1aaa2cf2f1f5af83e7779d66f0980bfaf 100644
--- a/packages/desktop-client/src/components/reports/ReportRouter.tsx
+++ b/packages/desktop-client/src/components/reports/ReportRouter.tsx
@@ -12,6 +12,7 @@ export function ReportRouter() {
     <Routes>
       <Route path="/" element={<Overview />} />
       <Route path="/net-worth" element={<NetWorth />} />
+      <Route path="/net-worth/:id" element={<NetWorth />} />
       <Route path="/cash-flow" element={<CashFlow />} />
       <Route path="/custom" element={<CustomReport />} />
       <Route path="/spending" element={<Spending />} />
diff --git a/packages/desktop-client/src/components/reports/ReportSidebar.tsx b/packages/desktop-client/src/components/reports/ReportSidebar.tsx
index 0424fba5b6062e7d598e2610845e2e671382db23..0c07319a88d20e19fc33549e2a5ac95223d495f4 100644
--- a/packages/desktop-client/src/components/reports/ReportSidebar.tsx
+++ b/packages/desktop-client/src/components/reports/ReportSidebar.tsx
@@ -3,6 +3,7 @@ import React, { useMemo, useRef, useState } from 'react';
 import * as monthUtils from 'loot-core/src/shared/months';
 import { type CategoryEntity } from 'loot-core/types/models/category';
 import { type CategoryGroupEntity } from 'loot-core/types/models/category-group';
+import { type TimeFrame } from 'loot-core/types/models/dashboard';
 import { type CustomReportEntity } from 'loot-core/types/models/reports';
 import { type SyncedPrefs } from 'loot-core/types/prefs';
 
@@ -44,7 +45,11 @@ type ReportSidebarProps = {
   setShowUncategorized: (value: boolean) => void;
   setIncludeCurrentInterval: (value: boolean) => void;
   setSelectedCategories: (value: CategoryEntity[]) => void;
-  onChangeDates: (dateStart: string, dateEnd: string) => void;
+  onChangeDates: (
+    dateStart: string,
+    dateEnd: string,
+    mode: TimeFrame['mode'],
+  ) => void;
   onReportChange: ({
     savedReport,
     type,
@@ -419,6 +424,7 @@ export function ReportSidebar({
               onChangeDates(
                 customReportItems.startDate,
                 customReportItems.endDate,
+                'static',
               );
             }}
           >
diff --git a/packages/desktop-client/src/components/reports/getLiveRange.ts b/packages/desktop-client/src/components/reports/getLiveRange.ts
index 22b2eef43551100a547d0438287a8bc4f2d8cf60..f76a2d7b09ab104addbbabe5bf1ad72d0ef11e5d 100644
--- a/packages/desktop-client/src/components/reports/getLiveRange.ts
+++ b/packages/desktop-client/src/components/reports/getLiveRange.ts
@@ -1,4 +1,5 @@
 import * as monthUtils from 'loot-core/src/shared/months';
+import { type TimeFrame } from 'loot-core/types/models';
 import { type SyncedPrefs } from 'loot-core/types/prefs';
 
 import { ReportOptions } from './ReportOptions';
@@ -9,7 +10,7 @@ export function getLiveRange(
   earliestTransaction: string,
   includeCurrentInterval: boolean,
   firstDayOfWeekIdx?: SyncedPrefs['firstDayOfWeekIdx'],
-): [string, string] {
+): [string, string, TimeFrame['mode']] {
   let dateStart = earliestTransaction;
   let dateEnd = monthUtils.currentDay();
   const rangeName = ReportOptions.dateRangeMap.get(cond);
@@ -50,5 +51,5 @@ export function getLiveRange(
       }
   }
 
-  return [dateStart, dateEnd];
+  return [dateStart, dateEnd, 'sliding-window'];
 }
diff --git a/packages/desktop-client/src/components/reports/reportRanges.ts b/packages/desktop-client/src/components/reports/reportRanges.ts
index d3f634ef138bcad7768c7477f74497a7dbf73f8e..631b56665c95fc531197adf8fb935905d1a8acd1 100644
--- a/packages/desktop-client/src/components/reports/reportRanges.ts
+++ b/packages/desktop-client/src/components/reports/reportRanges.ts
@@ -1,4 +1,5 @@
 import * as monthUtils from 'loot-core/src/shared/months';
+import { type TimeFrame } from 'loot-core/types/models';
 import { type SyncedPrefs } from 'loot-core/types/prefs';
 
 export function validateStart(
@@ -7,9 +8,9 @@ export function validateStart(
   end: string,
   interval?: string,
   firstDayOfWeekIdx?: SyncedPrefs['firstDayOfWeekIdx'],
-): [string, string] {
-  let addDays;
-  let dateStart;
+): [string, string, TimeFrame['mode']] {
+  let addDays: number;
+  let dateStart: string;
   switch (interval) {
     case 'Monthly':
       dateStart = start + '-01';
@@ -47,9 +48,9 @@ export function validateEnd(
   end: string,
   interval?: string,
   firstDayOfWeekIdx?: SyncedPrefs['firstDayOfWeekIdx'],
-): [string, string] {
-  let subDays;
-  let dateEnd;
+): [string, string, TimeFrame['mode']] {
+  let subDays: number;
+  let dateEnd: string;
   switch (interval) {
     case 'Monthly':
       dateEnd = monthUtils.getMonthEnd(end + '-01');
@@ -98,8 +99,8 @@ function boundedRange(
   end: string,
   interval?: string,
   firstDayOfWeekIdx?: SyncedPrefs['firstDayOfWeekIdx'],
-): [string, string] {
-  let latest;
+): [string, string, 'static'] {
+  let latest: string;
   switch (interval) {
     case 'Daily':
       latest = monthUtils.currentDay();
@@ -124,7 +125,7 @@ function boundedRange(
   if (start < earliest) {
     start = earliest;
   }
-  return [start, end];
+  return [start, end, 'static'];
 }
 
 export function getSpecificRange(
@@ -150,16 +151,33 @@ export function getSpecificRange(
     );
   }
 
-  return [dateStart, dateEnd];
+  return [dateStart, dateEnd, 'static'];
 }
 
 export function getFullRange(start: string) {
   const end = monthUtils.currentMonth();
-  return [start, end];
+  return [start, end, 'full'] as const;
 }
 
 export function getLatestRange(offset: number) {
   const end = monthUtils.currentMonth();
   const start = monthUtils.subMonths(end, offset);
-  return [start, end];
+  return [start, end, 'sliding-window'] as const;
+}
+
+export function calculateTimeRange(
+  { start, end, mode }: TimeFrame = {
+    start: monthUtils.subMonths(monthUtils.currentMonth(), 5),
+    end: monthUtils.currentMonth(),
+    mode: 'sliding-window',
+  },
+) {
+  if (mode === 'full') {
+    return getFullRange(start);
+  }
+  if (mode === 'sliding-window') {
+    return getLatestRange(monthUtils.differenceInCalendarMonths(end, start));
+  }
+
+  return [start, end, 'static'];
 }
diff --git a/packages/desktop-client/src/components/reports/reports/CashFlow.tsx b/packages/desktop-client/src/components/reports/reports/CashFlow.tsx
index 88f6733ef4f12afc925b21438faae174e13d410f..0ac91664750d3ea5d58603c3895b518b3cb88097 100644
--- a/packages/desktop-client/src/components/reports/reports/CashFlow.tsx
+++ b/packages/desktop-client/src/components/reports/reports/CashFlow.tsx
@@ -134,19 +134,10 @@ export function CashFlow() {
         onDeleteFilter={onDeleteFilter}
         conditionsOp={conditionsOp}
         onConditionsOpChange={onConditionsOpChange}
-        headerPrefixItems={undefined}
       >
-        <View
-          style={{
-            flex: 1,
-            flexDirection: 'row',
-            justifyContent: 'flex-end',
-          }}
-        >
-          <Button onPress={() => setShowBalance(state => !state)}>
-            {showBalance ? 'Hide balance' : 'Show balance'}
-          </Button>
-        </View>
+        <Button onPress={() => setShowBalance(state => !state)}>
+          {showBalance ? 'Hide balance' : 'Show balance'}
+        </Button>
       </Header>
       <View
         style={{
diff --git a/packages/desktop-client/src/components/reports/reports/NetWorth.jsx b/packages/desktop-client/src/components/reports/reports/NetWorth.jsx
index 4a3d0f9afbf530eedadc05dec1a5e8e9740e90da..73cdfec8952cf171682b00ce527ea87d53004296 100644
--- a/packages/desktop-client/src/components/reports/reports/NetWorth.jsx
+++ b/packages/desktop-client/src/components/reports/reports/NetWorth.jsx
@@ -1,7 +1,12 @@
 import React, { useState, useEffect, useMemo } from 'react';
+import { Trans, useTranslation } from 'react-i18next';
+import { useDispatch } from 'react-redux';
+import { useParams } from 'react-router-dom';
 
 import * as d from 'date-fns';
 
+import { addNotification } from 'loot-core/src/client/actions';
+import { useWidget } from 'loot-core/src/client/data-hooks/widget';
 import { send } from 'loot-core/src/platform/client/fetch';
 import * as monthUtils from 'loot-core/src/shared/months';
 import { integerToCurrency } from 'loot-core/src/shared/util';
@@ -11,6 +16,7 @@ import { useFilters } from '../../../hooks/useFilters';
 import { useNavigate } from '../../../hooks/useNavigate';
 import { useResponsive } from '../../../ResponsiveProvider';
 import { theme, styles } from '../../../style';
+import { Button } from '../../common/Button2';
 import { Paragraph } from '../../common/Paragraph';
 import { View } from '../../common/View';
 import { MobileBackButton } from '../../mobile/MobileBackButton';
@@ -19,11 +25,27 @@ import { PrivacyFilter } from '../../PrivacyFilter';
 import { Change } from '../Change';
 import { NetWorthGraph } from '../graphs/NetWorthGraph';
 import { Header } from '../Header';
+import { LoadingIndicator } from '../LoadingIndicator';
+import { calculateTimeRange } from '../reportRanges';
 import { createSpreadsheet as netWorthSpreadsheet } from '../spreadsheets/net-worth-spreadsheet';
 import { useReport } from '../useReport';
 import { fromDateRepr } from '../util';
 
 export function NetWorth() {
+  const params = useParams();
+  const { data: widget, isLoading } = useWidget(params.id ?? '');
+
+  if (isLoading) {
+    return <LoadingIndicator />;
+  }
+
+  return <NetWorthInner widget={widget} />;
+}
+
+function NetWorthInner({ widget }) {
+  const dispatch = useDispatch();
+  const { t } = useTranslation();
+
   const accounts = useAccounts();
   const {
     conditions,
@@ -33,19 +55,22 @@ export function NetWorth() {
     onDelete: onDeleteFilter,
     onUpdate: onUpdateFilter,
     onConditionsOpChange,
-  } = useFilters();
+  } = useFilters(widget?.meta?.conditions, widget?.meta?.conditionsOp);
 
   const [allMonths, setAllMonths] = useState(null);
-  const [start, setStart] = useState(
-    monthUtils.subMonths(monthUtils.currentMonth(), 5),
+
+  const [initialStart, initialEnd, initialMode] = calculateTimeRange(
+    widget?.meta?.timeFrame,
   );
-  const [end, setEnd] = useState(monthUtils.currentMonth());
+  const [start, setStart] = useState(initialStart);
+  const [end, setEnd] = useState(initialEnd);
+  const [mode, setMode] = useState(initialMode);
 
-  const params = useMemo(
+  const reportParams = useMemo(
     () => netWorthSpreadsheet(start, end, accounts, conditions, conditionsOp),
     [start, end, accounts, conditions, conditionsOp],
   );
-  const data = useReport('net_worth', params);
+  const data = useReport('net_worth', reportParams);
   useEffect(() => {
     async function run() {
       const trans = await send('get-earliest-transaction');
@@ -75,14 +100,39 @@ export function NetWorth() {
     run();
   }, []);
 
-  function onChangeDates(start, end) {
+  function onChangeDates(start, end, mode) {
     setStart(start);
     setEnd(end);
+    setMode(mode);
+  }
+
+  async function onSaveWidget() {
+    await send('dashboard-update-widget', {
+      id: widget?.id,
+      meta: {
+        ...(widget.meta ?? {}),
+        conditions,
+        conditionsOp,
+        timeFrame: {
+          start,
+          end,
+          mode,
+        },
+      },
+    });
+    dispatch(
+      addNotification({
+        type: 'message',
+        message: t('Dashboard widget successfully saved.'),
+      }),
+    );
   }
 
   const navigate = useNavigate();
   const { isNarrowWidth } = useResponsive();
 
+  const title = widget?.meta?.name ?? t('Net Worth');
+
   if (!allMonths || !data) {
     return null;
   }
@@ -92,13 +142,13 @@ export function NetWorth() {
       header={
         isNarrowWidth ? (
           <MobilePageHeader
-            title="Net Worth"
+            title={title}
             leftContent={
               <MobileBackButton onClick={() => navigate('/reports')} />
             }
           />
         ) : (
-          <PageHeader title="Net Worth" />
+          <PageHeader title={title} />
         )
       }
       padding={0}
@@ -107,6 +157,7 @@ export function NetWorth() {
         allMonths={allMonths}
         start={start}
         end={end}
+        mode={mode}
         onChangeDates={onChangeDates}
         filters={conditions}
         saved={saved}
@@ -115,7 +166,13 @@ export function NetWorth() {
         onDeleteFilter={onDeleteFilter}
         conditionsOp={conditionsOp}
         onConditionsOpChange={onConditionsOpChange}
-      />
+      >
+        {widget && (
+          <Button variant="primary" onPress={onSaveWidget}>
+            <Trans>Save widget</Trans>
+          </Button>
+        )}
+      </Header>
 
       <View
         style={{
@@ -155,16 +212,18 @@ export function NetWorth() {
         />
 
         <View style={{ marginTop: 30, userSelect: 'none' }}>
-          <Paragraph>
-            <strong>How is net worth calculated?</strong>
-          </Paragraph>
-          <Paragraph>
-            Net worth shows the balance of all accounts over time, including all
-            of your investments. Your “net worth” is considered to be the amount
-            you’d have if you sold all your assets and paid off as much debt as
-            possible. If you hover over the graph, you can also see the amount
-            of assets and debt individually.
-          </Paragraph>
+          <Trans>
+            <Paragraph>
+              <strong>How is net worth calculated?</strong>
+            </Paragraph>
+            <Paragraph>
+              Net worth shows the balance of all accounts over time, including
+              all of your investments. Your “net worth” is considered to be the
+              amount you’d have if you sold all your assets and paid off as much
+              debt as possible. If you hover over the graph, you can also see
+              the amount of assets and debt individually.
+            </Paragraph>
+          </Trans>
         </View>
       </View>
     </Page>
diff --git a/packages/desktop-client/src/components/reports/reports/NetWorthCard.tsx b/packages/desktop-client/src/components/reports/reports/NetWorthCard.tsx
index 5ba5ff082e1fcc1ebfa7982cf94df80a3358b3f8..3c1ed32402c12044d5992cb0f454a5e44f8318a7 100644
--- a/packages/desktop-client/src/components/reports/reports/NetWorthCard.tsx
+++ b/packages/desktop-client/src/components/reports/reports/NetWorthCard.tsx
@@ -1,13 +1,13 @@
 import React, { useState, useMemo, useCallback } from 'react';
 import { useTranslation } from 'react-i18next';
 
-import * as monthUtils from 'loot-core/src/shared/months';
 import { integerToCurrency } from 'loot-core/src/shared/util';
 import {
   type AccountEntity,
   type NetWorthWidget,
 } from 'loot-core/src/types/models';
 
+import { useFeatureFlag } from '../../../hooks/useFeatureFlag';
 import { useResponsive } from '../../../ResponsiveProvider';
 import { styles } from '../../../style';
 import { Block } from '../../common/Block';
@@ -19,10 +19,12 @@ import { NetWorthGraph } from '../graphs/NetWorthGraph';
 import { LoadingIndicator } from '../LoadingIndicator';
 import { ReportCard } from '../ReportCard';
 import { ReportCardName } from '../ReportCardName';
+import { calculateTimeRange } from '../reportRanges';
 import { createSpreadsheet as netWorthSpreadsheet } from '../spreadsheets/net-worth-spreadsheet';
 import { useReport } from '../useReport';
 
 type NetWorthCardProps = {
+  widgetId: string;
   isEditing?: boolean;
   accounts: AccountEntity[];
   meta?: NetWorthWidget['meta'];
@@ -31,33 +33,45 @@ type NetWorthCardProps = {
 };
 
 export function NetWorthCard({
+  widgetId,
   isEditing,
   accounts,
   meta = {},
   onMetaChange,
   onRemove,
 }: NetWorthCardProps) {
+  const isDashboardsFeatureEnabled = useFeatureFlag('dashboards');
   const { t } = useTranslation();
   const { isNarrowWidth } = useResponsive();
 
   const [nameMenuOpen, setNameMenuOpen] = useState(false);
 
-  const end = monthUtils.currentMonth();
-  const start = monthUtils.subMonths(end, 5);
+  const [start, end] = calculateTimeRange(meta?.timeFrame);
   const [isCardHovered, setIsCardHovered] = useState(false);
   const onCardHover = useCallback(() => setIsCardHovered(true), []);
   const onCardHoverEnd = useCallback(() => setIsCardHovered(false), []);
 
   const params = useMemo(
-    () => netWorthSpreadsheet(start, end, accounts),
-    [start, end, accounts],
+    () =>
+      netWorthSpreadsheet(
+        start,
+        end,
+        accounts,
+        meta?.conditions,
+        meta?.conditionsOp,
+      ),
+    [start, end, accounts, meta?.conditions, meta?.conditionsOp],
   );
   const data = useReport('net_worth', params);
 
   return (
     <ReportCard
       isEditing={isEditing}
-      to="/reports/net-worth"
+      to={
+        isDashboardsFeatureEnabled
+          ? `/reports/net-worth/${widgetId}`
+          : '/reports/net-worth'
+      }
       menuItems={[
         {
           name: 'rename',
diff --git a/packages/desktop-client/src/hooks/useFilters.ts b/packages/desktop-client/src/hooks/useFilters.ts
index 7fb50a1d74678628e35cac722518cfdb6f1ee858..1bd75ac2525ec40f116478c7a281727ced3dc379 100644
--- a/packages/desktop-client/src/hooks/useFilters.ts
+++ b/packages/desktop-client/src/hooks/useFilters.ts
@@ -4,9 +4,12 @@ import { type RuleConditionEntity } from 'loot-core/types/models/rule';
 
 export function useFilters<T extends RuleConditionEntity>(
   initialConditions: T[] = [],
+  initialConditionsOp: 'and' | 'or' = 'and',
 ) {
   const [conditions, setConditions] = useState<T[]>(initialConditions);
-  const [conditionsOp, setConditionsOp] = useState<'and' | 'or'>('and');
+  const [conditionsOp, setConditionsOp] = useState<'and' | 'or'>(
+    initialConditionsOp,
+  );
   const [saved, setSaved] = useState<T[] | null>(null);
 
   const onApply = useCallback(
diff --git a/packages/loot-core/src/client/data-hooks/widget.ts b/packages/loot-core/src/client/data-hooks/widget.ts
new file mode 100644
index 0000000000000000000000000000000000000000..367957b4f0eb5ff2c28e11e54f8b76bd88c19829
--- /dev/null
+++ b/packages/loot-core/src/client/data-hooks/widget.ts
@@ -0,0 +1,20 @@
+import { useMemo } from 'react';
+
+import { q } from '../../shared/query';
+import { type Widget } from '../../types/models';
+import { useLiveQuery } from '../query-hooks';
+
+export function useWidget(id: string) {
+  const data = useLiveQuery<Widget[]>(
+    () => q('dashboard').filter({ id }).select('*'),
+    [id],
+  );
+
+  return useMemo(
+    () => ({
+      isLoading: data === null,
+      data: data?.[0],
+    }),
+    [data],
+  );
+}
diff --git a/packages/loot-core/src/types/models/dashboard.d.ts b/packages/loot-core/src/types/models/dashboard.d.ts
index 6dc20360f4aac4ed6d2656c1e40b1477b8b248e3..40b00633324c57641f658cdaeaf87aa6534790b8 100644
--- a/packages/loot-core/src/types/models/dashboard.d.ts
+++ b/packages/loot-core/src/types/models/dashboard.d.ts
@@ -1,4 +1,11 @@
 import { type CustomReportEntity } from './reports';
+import { type RuleConditionEntity } from './rule';
+
+export type TimeFrame = {
+  start: string;
+  end: string;
+  mode: 'sliding-window' | 'static' | 'full';
+};
 
 type AbstractWidget<
   T extends string,
@@ -16,7 +23,12 @@ type AbstractWidget<
 
 export type NetWorthWidget = AbstractWidget<
   'net-worth-card',
-  { name?: string } | null
+  {
+    name?: string;
+    conditions?: RuleConditionEntity[];
+    conditionsOp?: 'and' | 'or';
+    timeFrame?: TimeFrame;
+  } | null
 >;
 export type CashFlowWidget = AbstractWidget<
   'cash-flow-card',
diff --git a/upcoming-release-notes/3364.md b/upcoming-release-notes/3364.md
new file mode 100644
index 0000000000000000000000000000000000000000..4eed1fc45c0898dfb271fa2be71f07c1ec0e246c
--- /dev/null
+++ b/upcoming-release-notes/3364.md
@@ -0,0 +1,6 @@
+---
+category: Enhancements
+authors: [MatissJanis, carkom]
+---
+
+Dashboards: ability to save filters & time-range on net-worth widgets.