diff --git a/packages/frontend/src/components/MkNotifications.vue b/packages/frontend/src/components/MkNotifications.vue
index 77e66f0165..0c817bd64c 100644
--- a/packages/frontend/src/components/MkNotifications.vue
+++ b/packages/frontend/src/components/MkNotifications.vue
@@ -96,6 +96,10 @@ onUnmounted(() => {
 onDeactivated(() => {
 	if (connection) connection.dispose();
 });
+
+defineExpose({
+	reload,
+});
 </script>
 
 <style lang="scss" module>
diff --git a/packages/frontend/src/ui/deck/antenna-column.vue b/packages/frontend/src/ui/deck/antenna-column.vue
index a93a14648c..1f4600d949 100644
--- a/packages/frontend/src/ui/deck/antenna-column.vue
+++ b/packages/frontend/src/ui/deck/antenna-column.vue
@@ -4,7 +4,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 -->
 
 <template>
-<XColumn :menu="menu" :column="column" :isStacked="isStacked">
+<XColumn :menu="menu" :column="column" :isStacked="isStacked" :refresher="() => timeline.reloadTimeline()">
 	<template #header>
 		<i class="ti ti-antenna"></i><span style="margin-left: 8px;">{{ column.name }}</span>
 	</template>
diff --git a/packages/frontend/src/ui/deck/channel-column.vue b/packages/frontend/src/ui/deck/channel-column.vue
index 4b982073ad..d2d279e5d7 100644
--- a/packages/frontend/src/ui/deck/channel-column.vue
+++ b/packages/frontend/src/ui/deck/channel-column.vue
@@ -4,7 +4,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 -->
 
 <template>
-<XColumn :menu="menu" :column="column" :isStacked="isStacked">
+<XColumn :menu="menu" :column="column" :isStacked="isStacked" :refresher="() => timeline.reloadTimeline()">
 	<template #header>
 		<i class="ti ti-device-tv"></i><span style="margin-left: 8px;">{{ column.name }}</span>
 	</template>
diff --git a/packages/frontend/src/ui/deck/column.vue b/packages/frontend/src/ui/deck/column.vue
index 269b9d57d5..1a6b833b45 100644
--- a/packages/frontend/src/ui/deck/column.vue
+++ b/packages/frontend/src/ui/deck/column.vue
@@ -57,6 +57,7 @@ const props = withDefaults(defineProps<{
 	isStacked?: boolean;
 	naked?: boolean;
 	menu?: MenuItem[];
+	refresher?: () => Promise<void>;
 }>(), {
 	isStacked: false,
 	naked: false,
@@ -183,6 +184,18 @@ function getMenu() {
 		items = props.menu.concat(items);
 	}
 
+	if (props.refresher) {
+		items = [{
+			icon: 'ti ti-refresh',
+			text: i18n.ts.reload,
+			action: () => {
+				if (props.refresher) {
+					props.refresher();
+				}
+			},
+		}, ...items];
+	}
+
 	return items;
 }
 
diff --git a/packages/frontend/src/ui/deck/direct-column.vue b/packages/frontend/src/ui/deck/direct-column.vue
index 940d2d7609..d8389949dd 100644
--- a/packages/frontend/src/ui/deck/direct-column.vue
+++ b/packages/frontend/src/ui/deck/direct-column.vue
@@ -4,10 +4,10 @@ SPDX-License-Identifier: AGPL-3.0-only
 -->
 
 <template>
-<XColumn :column="column" :isStacked="isStacked">
+<XColumn :column="column" :isStacked="isStacked" :refresher="() => reloadTimeline()">
 	<template #header><i class="ti ti-mail" style="margin-right: 8px;"></i>{{ column.name }}</template>
 
-	<MkNotes :pagination="pagination"/>
+	<MkNotes ref="tlComponent" :pagination="pagination"/>
 </XColumn>
 </template>
 
@@ -16,6 +16,7 @@ import { } from 'vue';
 import XColumn from './column.vue';
 import { Column } from './deck-store.js';
 import MkNotes from '@/components/MkNotes.vue';
+import { reloadStream } from '@/stream.js';
 
 defineProps<{
 	column: Column;
@@ -29,4 +30,15 @@ const pagination = {
 		visibility: 'specified',
 	},
 };
+
+const tlComponent: InstanceType<typeof MkNotes> = $ref();
+
+function reloadTimeline() {
+	return new Promise<void>((res) => {
+		tlComponent.pagingComponent?.reload().then(() => {
+			reloadStream();
+			res();
+		});
+	});
+}
 </script>
diff --git a/packages/frontend/src/ui/deck/list-column.vue b/packages/frontend/src/ui/deck/list-column.vue
index 14bc6917a3..40e4dcee7e 100644
--- a/packages/frontend/src/ui/deck/list-column.vue
+++ b/packages/frontend/src/ui/deck/list-column.vue
@@ -4,7 +4,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 -->
 
 <template>
-<XColumn :menu="menu" :column="column" :isStacked="isStacked">
+<XColumn :menu="menu" :column="column" :isStacked="isStacked" :refresher="() => timeline.reloadTimeline()">
 	<template #header>
 		<i class="ti ti-list"></i><span style="margin-left: 8px;">{{ column.name }}</span>
 	</template>
diff --git a/packages/frontend/src/ui/deck/mentions-column.vue b/packages/frontend/src/ui/deck/mentions-column.vue
index 381a9d02f2..7965444538 100644
--- a/packages/frontend/src/ui/deck/mentions-column.vue
+++ b/packages/frontend/src/ui/deck/mentions-column.vue
@@ -4,10 +4,10 @@ SPDX-License-Identifier: AGPL-3.0-only
 -->
 
 <template>
-<XColumn :column="column" :isStacked="isStacked">
+<XColumn :column="column" :isStacked="isStacked" :refresher="() => reloadTimeline()">
 	<template #header><i class="ti ti-at" style="margin-right: 8px;"></i>{{ column.name }}</template>
 
-	<MkNotes :pagination="pagination"/>
+	<MkNotes ref="tlComponent" :pagination="pagination"/>
 </XColumn>
 </template>
 
@@ -16,12 +16,24 @@ import { } from 'vue';
 import XColumn from './column.vue';
 import { Column } from './deck-store.js';
 import MkNotes from '@/components/MkNotes.vue';
+import { reloadStream } from '@/stream.js';
 
 defineProps<{
 	column: Column;
 	isStacked: boolean;
 }>();
 
+const tlComponent: InstanceType<typeof MkNotes> = $ref();
+
+function reloadTimeline() {
+	return new Promise<void>((res) => {
+		tlComponent.pagingComponent?.reload().then(() => {
+			reloadStream();
+			res();
+		});
+	});
+}
+
 const pagination = {
 	endpoint: 'notes/mentions' as const,
 	limit: 10,
diff --git a/packages/frontend/src/ui/deck/notifications-column.vue b/packages/frontend/src/ui/deck/notifications-column.vue
index b6bbf1fb55..770e8ea820 100644
--- a/packages/frontend/src/ui/deck/notifications-column.vue
+++ b/packages/frontend/src/ui/deck/notifications-column.vue
@@ -4,10 +4,10 @@ SPDX-License-Identifier: AGPL-3.0-only
 -->
 
 <template>
-<XColumn :column="column" :isStacked="isStacked" :menu="menu">
+<XColumn :column="column" :isStacked="isStacked" :menu="menu" :refresher="() => notificationsComponent.reload()">
 	<template #header><i class="ti ti-bell" style="margin-right: 8px;"></i>{{ column.name }}</template>
 
-	<XNotifications :excludeTypes="props.column.excludeTypes"/>
+	<XNotifications ref="notificationsComponent" :excludeTypes="props.column.excludeTypes"/>
 </XColumn>
 </template>
 
@@ -24,6 +24,8 @@ const props = defineProps<{
 	isStacked: boolean;
 }>();
 
+let notificationsComponent = $shallowRef<InstanceType<typeof XNotifications>>();
+
 function func() {
 	os.popup(defineAsyncComponent(() => import('@/components/MkNotificationSelectWindow.vue')), {
 		excludeTypes: props.column.excludeTypes,
diff --git a/packages/frontend/src/ui/deck/role-timeline-column.vue b/packages/frontend/src/ui/deck/role-timeline-column.vue
index e986b1f7d3..86d8878820 100644
--- a/packages/frontend/src/ui/deck/role-timeline-column.vue
+++ b/packages/frontend/src/ui/deck/role-timeline-column.vue
@@ -4,7 +4,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 -->
 
 <template>
-<XColumn :menu="menu" :column="column" :isStacked="isStacked">
+<XColumn :menu="menu" :column="column" :isStacked="isStacked" :refresher="() => timeline.reloadTimeline()">
 	<template #header>
 		<i class="ti ti-badge"></i><span style="margin-left: 8px;">{{ column.name }}</span>
 	</template>
diff --git a/packages/frontend/src/ui/deck/tl-column.vue b/packages/frontend/src/ui/deck/tl-column.vue
index c5629f69a4..9f24ea31ed 100644
--- a/packages/frontend/src/ui/deck/tl-column.vue
+++ b/packages/frontend/src/ui/deck/tl-column.vue
@@ -4,7 +4,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 -->
 
 <template>
-<XColumn :menu="menu" :column="column" :isStacked="isStacked">
+<XColumn :menu="menu" :column="column" :isStacked="isStacked" :refresher="() => timeline.reloadTimeline()">
 	<template #header>
 		<i v-if="column.tl === 'home'" class="ti ti-home"></i>
 		<i v-else-if="column.tl === 'local'" class="ti ti-planet"></i>
@@ -48,6 +48,7 @@ const props = defineProps<{
 }>();
 
 let disabled = $ref(false);
+let timeline = $shallowRef<InstanceType<typeof MkTimeline>>();
 
 const isLocalTimelineAvailable = (($i == null && instance.policies.ltlAvailable) || ($i != null && $i.policies.ltlAvailable));
 const isGlobalTimelineAvailable = (($i == null && instance.policies.gtlAvailable) || ($i != null && $i.policies.gtlAvailable));