diff --git a/packages/desktop-client/src/components/reports/ChooseGraph.tsx b/packages/desktop-client/src/components/reports/ChooseGraph.tsx
index ad8f0c3a857ccb3bbbacb3d789185737886cf95a..dce8850f8fa77517e06f826de4a23932c546515c 100644
--- a/packages/desktop-client/src/components/reports/ChooseGraph.tsx
+++ b/packages/desktop-client/src/components/reports/ChooseGraph.tsx
@@ -176,4 +176,5 @@ export function ChooseGraph({
       </View>
     );
   }
+  return null;
 }
diff --git a/packages/desktop-client/src/components/reports/Overview.jsx b/packages/desktop-client/src/components/reports/Overview.jsx
index 539aeda890fa57448a3ef9ed7516e4d0f092cd48..ce0c49b44990a1c6ea1309315e2a32c2d7182155 100644
--- a/packages/desktop-client/src/components/reports/Overview.jsx
+++ b/packages/desktop-client/src/components/reports/Overview.jsx
@@ -4,11 +4,12 @@ import { useReports } from 'loot-core/src/client/data-hooks/reports';
 
 import { useAccounts } from '../../hooks/useAccounts';
 import { useFeatureFlag } from '../../hooks/useFeatureFlag';
-import { styles } from '../../style';
+import { theme, styles } from '../../style';
 import { View } from '../common/View';
 
 import { CashFlowCard } from './reports/CashFlowCard';
 import { CustomReportCard } from './reports/CustomReportCard';
+import { CustomReportListCards } from './reports/CustomReportListCards';
 import { NetWorthCard } from './reports/NetWorthCard';
 import { SankeyCard } from './reports/SankeyCard';
 
@@ -18,6 +19,8 @@ export function Overview() {
 
   const customReportsFeatureFlag = useFeatureFlag('customReports');
 
+  const featureCount =
+    3 - (sankeyFeatureFlag ? 1 : 0) - (customReportsFeatureFlag ? 1 : 0);
   const accounts = useAccounts();
   return (
     <View
@@ -42,13 +45,25 @@ export function Overview() {
         }}
       >
         {sankeyFeatureFlag && <SankeyCard />}
-        {customReportsFeatureFlag ? (
-          <CustomReportCard reports={customReports} />
-        ) : (
-          <div style={{ flex: 1 }} />
-        )}
-        {!sankeyFeatureFlag && <div style={{ flex: 1 }} />}
+        {customReportsFeatureFlag && <CustomReportCard />}
+        {featureCount !== 3 &&
+          [...Array(featureCount)].map((e, i) => (
+            <View key={i} style={{ padding: 15, flex: 1 }} />
+          ))}
       </View>
+      {customReportsFeatureFlag && (
+        <>
+          <View
+            style={{
+              height: 1,
+              backgroundColor: theme.pillBorderDark,
+              marginTop: 10,
+              flexShrink: 0,
+            }}
+          />
+          <CustomReportListCards reports={customReports} />
+        </>
+      )}
     </View>
   );
 }
diff --git a/packages/desktop-client/src/components/reports/SaveReport.tsx b/packages/desktop-client/src/components/reports/SaveReport.tsx
index 37ca8e4e9c5fe7fead14cda2be83fd4c18a2d440..4200d781fcf47db63e90b7b57eaddd62045a22c2 100644
--- a/packages/desktop-client/src/components/reports/SaveReport.tsx
+++ b/packages/desktop-client/src/components/reports/SaveReport.tsx
@@ -1,8 +1,6 @@
 import React, { createRef, useState } from 'react';
 
-import { v4 as uuidv4 } from 'uuid';
-
-//import { send, sendCatch } from 'loot-core/src/platform/client/fetch';
+import { send, sendCatch } from 'loot-core/src/platform/client/fetch';
 import { type CustomReportEntity } from 'loot-core/src/types/models';
 
 import { SvgExpandArrow } from '../../icons/v0';
@@ -38,59 +36,54 @@ export function SaveReport({
   const [menuOpen, setMenuOpen] = useState(false);
   const [menuItem, setMenuItem] = useState('');
   const [err, setErr] = useState('');
-  const [res, setRes] = useState('');
   const [name, setName] = useState(report.name ?? '');
   const inputRef = createRef<HTMLInputElement>();
 
   const onAddUpdate = async (menuChoice: string) => {
-    let savedReport: CustomReportEntity;
-    //save existing states
-    savedReport = {
-      ...report,
-      ...customReportItems,
-    };
-
     if (menuChoice === 'save-report') {
-      setRes('');
-      //create new flow
-      /*
-      res = await sendCatch('report/create', {
-        ...savedReport,
-      });
-      */
-      savedReport = {
-        ...savedReport,
-        id: uuidv4(),
+      const newSavedReport = {
+        ...report,
+        ...customReportItems,
         name,
       };
-    }
 
-    if (menuChoice === 'rename-report') {
-      //rename
-      savedReport = {
-        ...savedReport,
-        name,
-      };
-    }
+      const response = await sendCatch('report/create', newSavedReport);
+
+      if (response.error) {
+        setErr(response.error.message);
+        setNameMenuOpen(true);
+        return;
+      }
 
-    if (menuChoice === 'update-report') {
-      //send update and rename to DB
-      /*
-      res = await sendCatch('report/update', {
-        ...savedReport,
-      });
-      */
-    }
-    if (res !== '') {
-      setErr(res);
-      setNameMenuOpen(true);
-    } else {
       setNameMenuOpen(false);
       onReportChange({
-        savedReport,
-        type: menuChoice === 'rename-report' ? 'rename' : 'add-update',
+        savedReport: {
+          ...newSavedReport,
+          id: response.data,
+        },
+        type: 'add-update',
       });
+      return;
     }
+
+    const updatedReport = {
+      ...report,
+      ...(menuChoice === 'rename-report' ? { name } : customReportItems),
+    };
+
+    const response = await sendCatch('report/update', updatedReport);
+
+    if (response.error) {
+      setErr(response.error.message);
+      setNameMenuOpen(true);
+      return;
+    }
+
+    setNameMenuOpen(false);
+    onReportChange({
+      savedReport: updatedReport,
+      type: menuChoice === 'rename-report' ? 'rename' : 'add-update',
+    });
   };
 
   const onMenuSelect = async (item: string) => {
@@ -103,7 +96,8 @@ export function SaveReport({
         break;
       case 'delete-report':
         setMenuOpen(false);
-        //await send('report/delete', id);
+        setName('');
+        await send('report/delete', report.id);
         onResetReports();
         break;
       case 'update-report':
@@ -122,6 +116,7 @@ export function SaveReport({
         break;
       case 'reset-report':
         setMenuOpen(false);
+        setName('');
         onResetReports();
         break;
       default:
diff --git a/packages/desktop-client/src/components/reports/graphs/AreaGraph.tsx b/packages/desktop-client/src/components/reports/graphs/AreaGraph.tsx
index 54b1420301fe7a17b177765ac5b52b563f6c5f6e..276c15a401b39d1d916116d3cf37405be030a00a 100644
--- a/packages/desktop-client/src/components/reports/graphs/AreaGraph.tsx
+++ b/packages/desktop-client/src/components/reports/graphs/AreaGraph.tsx
@@ -23,7 +23,6 @@ import { usePrivacyMode } from '../../../hooks/usePrivacyMode';
 import { theme } from '../../../style';
 import { type CSSProperties } from '../../../style';
 import { AlignedText } from '../../common/AlignedText';
-import { PrivacyFilter } from '../../PrivacyFilter';
 import { Container } from '../Container';
 import { numberFormatterTooltip } from '../numberFormatter';
 
@@ -68,30 +67,28 @@ const CustomTooltip = ({
             <strong>{payload[0].payload.date}</strong>
           </div>
           <div style={{ lineHeight: 1.5 }}>
-            <PrivacyFilter>
-              {['totalAssets', 'totalTotals'].includes(balanceTypeOp) && (
-                <AlignedText
-                  left="Assets:"
-                  right={amountToCurrency(payload[0].payload.totalAssets)}
-                />
-              )}
-              {['totalDebts', 'totalTotals'].includes(balanceTypeOp) && (
-                <AlignedText
-                  left="Debt:"
-                  right={amountToCurrency(payload[0].payload.totalDebts)}
-                />
-              )}
-              {['totalTotals'].includes(balanceTypeOp) && (
-                <AlignedText
-                  left="Net:"
-                  right={
-                    <strong>
-                      {amountToCurrency(payload[0].payload.totalTotals)}
-                    </strong>
-                  }
-                />
-              )}
-            </PrivacyFilter>
+            {['totalAssets', 'totalTotals'].includes(balanceTypeOp) && (
+              <AlignedText
+                left="Assets:"
+                right={amountToCurrency(payload[0].payload.totalAssets)}
+              />
+            )}
+            {['totalDebts', 'totalTotals'].includes(balanceTypeOp) && (
+              <AlignedText
+                left="Debt:"
+                right={amountToCurrency(payload[0].payload.totalDebts)}
+              />
+            )}
+            {['totalTotals'].includes(balanceTypeOp) && (
+              <AlignedText
+                left="Net:"
+                right={
+                  <strong>
+                    {amountToCurrency(payload[0].payload.totalTotals)}
+                  </strong>
+                }
+              />
+            )}
           </div>
         </div>
       </div>
diff --git a/packages/desktop-client/src/components/reports/graphs/BarGraph.tsx b/packages/desktop-client/src/components/reports/graphs/BarGraph.tsx
index 6263c66513c0a9c5b7c1c03e1d221fdbf06ab240..8489e92dddf27e500390636f841bd744f2061993 100644
--- a/packages/desktop-client/src/components/reports/graphs/BarGraph.tsx
+++ b/packages/desktop-client/src/components/reports/graphs/BarGraph.tsx
@@ -25,7 +25,6 @@ import { usePrivacyMode } from '../../../hooks/usePrivacyMode';
 import { theme } from '../../../style';
 import { type CSSProperties } from '../../../style';
 import { AlignedText } from '../../common/AlignedText';
-import { PrivacyFilter } from '../../PrivacyFilter';
 import { Container } from '../Container';
 import { getCustomTick } from '../getCustomTick';
 import { numberFormatterTooltip } from '../numberFormatter';
@@ -83,30 +82,28 @@ const CustomTooltip = ({
             <strong>{payload[0].payload[yAxis]}</strong>
           </div>
           <div style={{ lineHeight: 1.5 }}>
-            <PrivacyFilter>
-              {['totalAssets', 'totalTotals'].includes(balanceTypeOp) && (
-                <AlignedText
-                  left="Assets:"
-                  right={amountToCurrency(payload[0].payload.totalAssets)}
-                />
-              )}
-              {['totalDebts', 'totalTotals'].includes(balanceTypeOp) && (
-                <AlignedText
-                  left="Debt:"
-                  right={amountToCurrency(payload[0].payload.totalDebts)}
-                />
-              )}
-              {['totalTotals'].includes(balanceTypeOp) && (
-                <AlignedText
-                  left="Net:"
-                  right={
-                    <strong>
-                      {amountToCurrency(payload[0].payload.totalTotals)}
-                    </strong>
-                  }
-                />
-              )}
-            </PrivacyFilter>
+            {['totalAssets', 'totalTotals'].includes(balanceTypeOp) && (
+              <AlignedText
+                left="Assets:"
+                right={amountToCurrency(payload[0].payload.totalAssets)}
+              />
+            )}
+            {['totalDebts', 'totalTotals'].includes(balanceTypeOp) && (
+              <AlignedText
+                left="Debt:"
+                right={amountToCurrency(payload[0].payload.totalDebts)}
+              />
+            )}
+            {['totalTotals'].includes(balanceTypeOp) && (
+              <AlignedText
+                left="Net:"
+                right={
+                  <strong>
+                    {amountToCurrency(payload[0].payload.totalTotals)}
+                  </strong>
+                }
+              />
+            )}
           </div>
         </div>
       </div>
diff --git a/packages/desktop-client/src/components/reports/graphs/DonutGraph.tsx b/packages/desktop-client/src/components/reports/graphs/DonutGraph.tsx
index e60bfa1e07e39f34f48893f9cf4e0423350c4259..8714290b0b8c16a15dfcd4265a5d2751a2f43199 100644
--- a/packages/desktop-client/src/components/reports/graphs/DonutGraph.tsx
+++ b/packages/desktop-client/src/components/reports/graphs/DonutGraph.tsx
@@ -32,15 +32,17 @@ const ActiveShapeMobile = props => {
 
   return (
     <g>
-      <text x={cx} y={cy + 65} dy={-8} textAnchor="middle" fill={fill}>
+      <text x={cx} y={cy + 70} dy={-8} textAnchor="middle" fill={fill}>
         {`${yAxis}`}
       </text>
-      <text x={cx - 30} y={cy + 40} dy={0} textAnchor="end" fill={fill}>
-        {`${amountToCurrency(value)}`}
-      </text>
-      <text x={cx + 30} y={cy + 40} dy={0} textAnchor="start" fill="#999">
-        {`${(percent * 100).toFixed(2)}%`}
-      </text>
+      <PrivacyFilter>
+        <text x={cx - 40} y={cy + 40} dy={0} textAnchor="end" fill={fill}>
+          {`${amountToCurrency(value)}`}
+        </text>
+        <text x={cx + 45} y={cy + 40} dy={0} textAnchor="start" fill="#999">
+          {`${(percent * 100).toFixed(2)}%`}
+        </text>
+      </PrivacyFilter>
       <Sector
         cx={cx}
         cy={cy}
diff --git a/packages/desktop-client/src/components/reports/graphs/StackedBarGraph.tsx b/packages/desktop-client/src/components/reports/graphs/StackedBarGraph.tsx
index 777f4be4c7cfb762ee1c553e7a92f502b194f0c0..3f1d5849b497908512479978eca8888849604b47 100644
--- a/packages/desktop-client/src/components/reports/graphs/StackedBarGraph.tsx
+++ b/packages/desktop-client/src/components/reports/graphs/StackedBarGraph.tsx
@@ -23,7 +23,6 @@ import { usePrivacyMode } from '../../../hooks/usePrivacyMode';
 import { theme } from '../../../style';
 import { type CSSProperties } from '../../../style';
 import { AlignedText } from '../../common/AlignedText';
-import { PrivacyFilter } from '../../PrivacyFilter';
 import { Container } from '../Container';
 import { getCustomTick } from '../getCustomTick';
 import { numberFormatterTooltip } from '../numberFormatter';
@@ -41,12 +40,18 @@ type PayloadItem = {
 };
 
 type CustomTooltipProps = {
+  compact: boolean;
   active?: boolean;
   payload?: PayloadItem[];
   label?: string;
 };
 
-const CustomTooltip = ({ active, payload, label }: CustomTooltipProps) => {
+const CustomTooltip = ({
+  compact,
+  active,
+  payload,
+  label,
+}: CustomTooltipProps) => {
   if (active && payload && payload.length) {
     let sumTotals = 0;
     return (
@@ -65,32 +70,32 @@ const CustomTooltip = ({ active, payload, label }: CustomTooltipProps) => {
           <div style={{ marginBottom: 10 }}>
             <strong>{label}</strong>
           </div>
-          <div style={{ lineHeight: 1.5 }}>
-            <PrivacyFilter>
-              {payload
-                .slice(0)
-                .reverse()
-                .map(pay => {
-                  sumTotals += pay.value;
-                  return (
-                    pay.value !== 0 && (
-                      <AlignedText
-                        key={pay.name}
-                        left={pay.name}
-                        right={amountToCurrency(pay.value)}
-                        style={{ color: pay.color }}
-                      />
-                    )
-                  );
-                })}
-              <AlignedText
-                left="Total"
-                right={amountToCurrency(sumTotals)}
-                style={{
-                  fontWeight: 600,
-                }}
-              />
-            </PrivacyFilter>
+          <div style={{ lineHeight: 1.4 }}>
+            {payload
+              .slice(0)
+              .reverse()
+              .map((pay, i) => {
+                sumTotals += pay.value;
+                return (
+                  pay.value !== 0 &&
+                  (compact ? i < 5 : true) && (
+                    <AlignedText
+                      key={pay.name}
+                      left={pay.name}
+                      right={amountToCurrency(pay.value)}
+                      style={{ color: pay.color }}
+                    />
+                  )
+                );
+              })}
+            {payload.length > 5 && compact && '...'}
+            <AlignedText
+              left="Total"
+              right={amountToCurrency(sumTotals)}
+              style={{
+                fontWeight: 600,
+              }}
+            />
           </div>
         </div>
       </div>
@@ -161,7 +166,7 @@ export function StackedBarGraph({
                 margin={{ top: 0, right: 0, left: leftMargin, bottom: 0 }}
               >
                 <Tooltip
-                  content={<CustomTooltip />}
+                  content={<CustomTooltip compact={compact} />}
                   formatter={numberFormatterTooltip}
                   isAnimationActive={false}
                   cursor={{ fill: 'transparent' }}
diff --git a/packages/desktop-client/src/components/reports/reports/CustomReport.jsx b/packages/desktop-client/src/components/reports/reports/CustomReport.jsx
index 139f4716f95070e22427b4a0378337327bbd62de..32b8b7fc278d7a013a77e4156530812885641ae8 100644
--- a/packages/desktop-client/src/components/reports/reports/CustomReport.jsx
+++ b/packages/desktop-client/src/components/reports/reports/CustomReport.jsx
@@ -96,6 +96,7 @@ export function CustomReport() {
 
   useEffect(() => {
     async function run() {
+      report.conditions.forEach(condition => onApplyFilter(condition));
       const trans = await send('get-earliest-transaction');
       const currentMonth = monthUtils.currentMonth();
       let earliestMonth = trans
diff --git a/packages/desktop-client/src/components/reports/reports/CustomReportListCards.tsx b/packages/desktop-client/src/components/reports/reports/CustomReportListCards.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..40d7742a73cef56e7a6db0188cd33402b5e76d64
--- /dev/null
+++ b/packages/desktop-client/src/components/reports/reports/CustomReportListCards.tsx
@@ -0,0 +1,209 @@
+import React, { useMemo, useState } from 'react';
+
+import { send } from 'loot-core/src/platform/client/fetch';
+import { type CustomReportEntity } from 'loot-core/types/models/reports';
+
+import { styles } from '../../../style';
+import { Block } from '../../common/Block';
+import { Menu } from '../../common/Menu';
+import { MenuButton } from '../../common/MenuButton';
+import { MenuTooltip } from '../../common/MenuTooltip';
+import { View } from '../../common/View';
+import { ChooseGraph } from '../ChooseGraph';
+import { DateRange } from '../DateRange';
+import { LoadingIndicator } from '../LoadingIndicator';
+import { ReportCard } from '../ReportCard';
+
+type CardMenuProps = {
+  onClose: () => void;
+  onMenuSelect: (item: string, reportId: string) => void;
+  reportId: string;
+};
+
+function CardMenu({ onClose, onMenuSelect, reportId }: CardMenuProps) {
+  return (
+    <MenuTooltip onClose={onClose} width={120}>
+      <Menu
+        onMenuSelect={item => {
+          onMenuSelect(item, reportId);
+        }}
+        items={[
+          {
+            name: 'rename',
+            text: 'Rename report',
+            disabled: true,
+          },
+          {
+            name: 'delete',
+            text: 'Delete report',
+          },
+        ]}
+      />
+    </MenuTooltip>
+  );
+}
+
+function index(data: CustomReportEntity[]): { [key: string]: boolean }[] {
+  return data.reduce((carry, report) => {
+    const reportId: string = report.id === undefined ? '' : report.id;
+
+    return {
+      ...carry,
+      [reportId]: false,
+    };
+  }, []);
+}
+
+export function CustomReportListCards({
+  reports,
+}: {
+  reports: CustomReportEntity[];
+}) {
+  const result: { [key: string]: boolean }[] = index(reports);
+  const [reportMenu, setReportMenu] = useState(result);
+
+  const [isCardHovered, setIsCardHovered] = useState('');
+
+  const onMenuSelect = async (item: string, reportId: string) => {
+    if (item === 'delete') {
+      onMenuOpen(reportId, false);
+      await send('report/delete', reportId);
+    }
+  };
+
+  const onMenuOpen = (item: string, state: boolean) => {
+    setReportMenu({ ...reportMenu, [item]: state });
+  };
+
+  const chunkSize = 3;
+
+  const groups = useMemo(() => {
+    return reports
+      .map((report: CustomReportEntity, i: number) => {
+        return i % chunkSize === 0 ? reports.slice(i, i + chunkSize) : null;
+      })
+      .filter(e => {
+        return e;
+      });
+  }, [reports]);
+
+  const remainder = 3 - (reports.length % 3);
+
+  if (reports.length === 0) return null;
+  return (
+    <View>
+      {groups.map((group, i) => (
+        <View
+          key={i}
+          style={{
+            flex: '0 0 auto',
+            flexDirection: 'row',
+          }}
+        >
+          {group &&
+            group.map((report, id) => (
+              <View key={id} style={{ position: 'relative', flex: '1' }}>
+                <View style={{ width: '100%', height: '100%' }}>
+                  <ReportCard to="/reports/custom" report={report}>
+                    <View
+                      style={{ flex: 1, padding: 10 }}
+                      onMouseEnter={() =>
+                        setIsCardHovered(
+                          report.id === undefined ? '' : report.id,
+                        )
+                      }
+                      onMouseLeave={() => {
+                        setIsCardHovered('');
+                        onMenuOpen(
+                          report.id === undefined ? '' : report.id,
+                          false,
+                        );
+                      }}
+                    >
+                      <View
+                        style={{
+                          flexDirection: 'row',
+                          flexShrink: 0,
+                          paddingBottom: 5,
+                        }}
+                      >
+                        <View style={{ flex: 1 }}>
+                          <Block
+                            style={{
+                              ...styles.mediumText,
+                              fontWeight: 500,
+                              marginBottom: 5,
+                            }}
+                            role="heading"
+                          >
+                            {report.name}
+                          </Block>
+                          <DateRange
+                            start={report.startDate}
+                            end={report.endDate}
+                          />
+                        </View>
+                      </View>
+
+                      {report.data ? (
+                        <ChooseGraph
+                          startDate={report.startDate}
+                          endDate={report.endDate}
+                          data={report.data}
+                          mode={report.mode}
+                          graphType={report.graphType}
+                          balanceType={report.balanceType}
+                          groupBy={report.groupBy}
+                          compact={true}
+                          style={{ height: 'auto', flex: 1 }}
+                        />
+                      ) : (
+                        <LoadingIndicator />
+                      )}
+                    </View>
+                  </ReportCard>
+                </View>
+                <View
+                  style={{
+                    textAlign: 'right',
+                    position: 'absolute',
+                    right: 25,
+                    top: 25,
+                  }}
+                >
+                  <MenuButton
+                    onClick={() =>
+                      onMenuOpen(report.id === undefined ? '' : report.id, true)
+                    }
+                    style={{
+                      color:
+                        isCardHovered === report.id ? 'inherit' : 'transparent',
+                    }}
+                  />
+                  {report.id === undefined
+                    ? null
+                    : reportMenu[report.id as keyof typeof reportMenu] && (
+                        <CardMenu
+                          onMenuSelect={onMenuSelect}
+                          onClose={() =>
+                            onMenuOpen(
+                              report.id === undefined ? '' : report.id,
+                              false,
+                            )
+                          }
+                          reportId={report.id}
+                        />
+                      )}
+                </View>
+              </View>
+            ))}
+          {remainder !== 3 &&
+            i + 1 === groups.length &&
+            [...Array(remainder)].map((e, i) => (
+              <View key={i} style={{ flex: 1 }} />
+            ))}
+        </View>
+      ))}
+    </View>
+  );
+}
diff --git a/packages/desktop-client/src/components/reports/spreadsheets/filterHiddenItems.ts b/packages/desktop-client/src/components/reports/spreadsheets/filterHiddenItems.ts
index f3e76a95824762e88cd6fec18de116e2b439ebf9..538f5c599d1e6891b535d7480e224c2f9190beeb 100644
--- a/packages/desktop-client/src/components/reports/spreadsheets/filterHiddenItems.ts
+++ b/packages/desktop-client/src/components/reports/spreadsheets/filterHiddenItems.ts
@@ -27,11 +27,10 @@ export function filterHiddenItems(
             f.transferAccount !== null
         : showUncategorized
           ? //false, true
-            f.accountOffBudget === false && f.transferAccount === null
-          : //false false
-            f.category !== null &&
             f.accountOffBudget === false &&
-            f.transferAccount === null,
+            (f.transferAccount === null || f.category !== null)
+          : //false false
+            f.category !== null && f.accountOffBudget === false,
     );
 
   return showHide.filter(query => {
diff --git a/packages/loot-core/migrations/1707267033000_reports.sql b/packages/loot-core/migrations/1707267033000_reports.sql
new file mode 100644
index 0000000000000000000000000000000000000000..2f6705895f90b5932fc7195816722d2ba1b98ff1
--- /dev/null
+++ b/packages/loot-core/migrations/1707267033000_reports.sql
@@ -0,0 +1,28 @@
+BEGIN TRANSACTION;
+
+CREATE TABLE custom_reports
+  (
+    id TEXT PRIMARY KEY,
+    name TEXT,
+    start_date TEXT,
+    end_date TEXT,
+    date_static INTEGER DEFAULT 0,
+    date_range TEXT,
+    mode TEXT DEFAULT 'total',
+    group_by TEXT DEFAULT 'Category',
+    balance_type TEXT DEFAULT 'Expense',
+    show_empty INTEGER DEFAULT 0,
+    show_offbudget INTEGER DEFAULT 0,
+    show_hidden INTEGER DEFAULT 0,
+    show_uncategorized INTEGER DEFAULT 0,
+    selected_categories TEXT,
+    graph_type TEXT DEFAULT 'BarGraph',
+    conditions TEXT,
+    conditions_op TEXT DEFAULT 'and',
+    metadata TEXT,
+    interval TEXT DEFAULT 'Monthly',
+    color_scheme TEXT,
+    tombstone INTEGER DEFAULT 0
+  );
+
+COMMIT;
\ No newline at end of file
diff --git a/packages/loot-core/src/client/data-hooks/reports.ts b/packages/loot-core/src/client/data-hooks/reports.ts
index 95b023ff34ee1520e5e6f76364b9e4ce63b3c39b..78246e4779b810c324350e9e9c3a788a5fa6b689 100644
--- a/packages/loot-core/src/client/data-hooks/reports.ts
+++ b/packages/loot-core/src/client/data-hooks/reports.ts
@@ -34,17 +34,12 @@ function toJS(rows: CustomReportData[]) {
   return reports;
 }
 
-/*
-leaving as a placeholder for saved reports implementation return an 
-empty array because "reports" db table doesn't exist yet
-*/
 export function useReports(): CustomReportEntity[] {
   const reports: CustomReportEntity[] = toJS(
-    //useLiveQuery(() => q('reports').select('*'), []) || [],
-    useLiveQuery(() => q('transaction_filters').select('*'), []) || [],
+    useLiveQuery(() => q('custom_reports').select('*'), []) || [],
   );
 
-  /** Sort reports by alphabetical order */
+  // Sort reports by alphabetical order
   function sort(reports: CustomReportEntity[]) {
     return reports.sort((a, b) =>
       a.name && b.name
@@ -55,11 +50,5 @@ export function useReports(): CustomReportEntity[] {
     );
   }
 
-  //return useMemo(() => sort(reports), [reports]);
-
-  //everything below this line will be removed once db table is created
-  const order: CustomReportEntity[] = useMemo(() => sort(reports), [reports]);
-  const flag = true;
-  const emptyReports: CustomReportEntity[] = flag ? [] : order;
-  return emptyReports;
+  return useMemo(() => sort(reports), [reports]);
 }
diff --git a/packages/loot-core/src/server/aql/schema/index.ts b/packages/loot-core/src/server/aql/schema/index.ts
index c129710188dc4f22ff9f5aa7b2c8b959cc01bc78..cb466d6f8e1295fc887efc6e4ef2292e3753285a 100644
--- a/packages/loot-core/src/server/aql/schema/index.ts
+++ b/packages/loot-core/src/server/aql/schema/index.ts
@@ -131,18 +131,21 @@ export const schema = {
     name: f('string'),
     start_date: f('string', { default: '2023-06' }),
     end_date: f('string', { default: '2023-09' }),
+    date_static: f('integer', { default: 0 }),
+    date_range: f('string'),
     mode: f('string', { default: 'total' }),
     group_by: f('string', { default: 'Category' }),
     balance_type: f('string', { default: 'Expense' }),
-    interval: f('string', { default: 'Monthly' }),
     show_empty: f('integer', { default: 0 }),
-    show_offbudgethidden: f('integer', { default: 0 }),
+    show_offbudget: f('integer', { default: 0 }),
+    show_hidden: f('integer', { default: 0 }),
     show_uncategorized: f('integer', { default: 0 }),
     selected_categories: f('json'),
     graph_type: f('string', { default: 'BarGraph' }),
     conditions: f('json'),
     conditions_op: f('string'),
     metadata: f('json'),
+    interval: f('string'),
     color_scheme: f('json'),
     tombstone: f('boolean'),
   },
diff --git a/upcoming-release-notes/2335.md b/upcoming-release-notes/2335.md
new file mode 100644
index 0000000000000000000000000000000000000000..cdc4f48b3c5dd287dcc907047fe75ecf7bee84ec
--- /dev/null
+++ b/upcoming-release-notes/2335.md
@@ -0,0 +1,6 @@
+---
+category: Enhancements
+authors: [carkom]
+---
+
+Allows for saving custom reports. Also changes reports dashboard to display saved reports.