diff --git a/components/common/CommonPaginator.vue b/components/common/CommonPaginator.vue
index 9d26aaba..2cd07162 100644
--- a/components/common/CommonPaginator.vue
+++ b/components/common/CommonPaginator.vue
@@ -10,6 +10,7 @@ const {
   keyProp = 'id',
   virtualScroller = false,
   eventType = 'update',
+  buffer = 10,
   preprocess,
 } = defineProps<{
   paginator: Paginator<T[], O>
@@ -17,6 +18,10 @@ const {
   virtualScroller?: boolean
   stream?: Promise<WsEvents>
   eventType?: 'notification' | 'update'
+  // When preprocess is used, buffer is the number of items that will be hidden
+  // until the next pagination to avoid border effect between pages when reordering
+  // and grouping items
+  buffer?: number
   preprocess?: (items: T[]) => any[]
 }>()
 
diff --git a/components/status/edit/StatusEditHistory.vue b/components/status/edit/StatusEditHistory.vue
index c5d29343..2d6f2f80 100644
--- a/components/status/edit/StatusEditHistory.vue
+++ b/components/status/edit/StatusEditHistory.vue
@@ -13,12 +13,13 @@ const showHistory = (edit: mastodon.v1.StatusEdit) => {
 }
 const timeAgoOptions = useTimeAgoOptions()
 
+// TODO: rework, this is only reversing the first page of edits
 const reverseHistory = (items: mastodon.v1.StatusEdit[]) =>
   [...items].reverse()
 </script>
 
 <template>
-  <CommonPaginator :paginator="paginator" key-prop="createdAt" :preprocess="reverseHistory">
+  <CommonPaginator :paginator="paginator" key-prop="createdAt" :preprocess="reverseHistory" :buffer="0">
     <template #default="{ items, item, index }">
       <CommonDropdownItem
         px="0.5"
diff --git a/components/timeline/TimelineHome.vue b/components/timeline/TimelineHome.vue
index 4404ea7c..6450cc8f 100644
--- a/components/timeline/TimelineHome.vue
+++ b/components/timeline/TimelineHome.vue
@@ -1,5 +1,5 @@
 <script setup lang="ts">
-const paginator = useMasto().v1.timelines.listHome()
+const paginator = useMasto().v1.timelines.listHome({ limit: 30 })
 const stream = useMasto().v1.stream.streamUser()
 onBeforeUnmount(() => stream?.then(s => s.disconnect()))
 </script>
diff --git a/components/timeline/TimelinePaginator.vue b/components/timeline/TimelinePaginator.vue
index 49d7cc84..ea013bee 100644
--- a/components/timeline/TimelinePaginator.vue
+++ b/components/timeline/TimelinePaginator.vue
@@ -4,12 +4,13 @@ import { DynamicScrollerItem } from 'vue-virtual-scroller'
 import 'vue-virtual-scroller/dist/vue-virtual-scroller.css'
 import type { Paginator, WsEvents, mastodon } from 'masto'
 
-const { paginator, stream, account } = defineProps<{
+const { paginator, stream, account, buffer = 10 } = defineProps<{
   paginator: Paginator<mastodon.v1.Status[], mastodon.v1.ListAccountStatusesParams>
   stream?: Promise<WsEvents>
   context?: mastodon.v2.FilterContext
   account?: mastodon.v1.Account
   preprocess?: (items: mastodon.v1.Status[]) => mastodon.v1.Status[]
+  buffer?: number
 }>()
 
 const { formatNumber } = useHumanReadableNumber()
@@ -21,7 +22,7 @@ const showOriginSite = $computed(() =>
 </script>
 
 <template>
-  <CommonPaginator v-bind="{ paginator, stream, preprocess }" :virtual-scroller="virtualScroller">
+  <CommonPaginator v-bind="{ paginator, stream, preprocess, buffer }" :virtual-scroller="virtualScroller">
     <template #updater="{ number, update }">
       <button py-4 border="b base" flex="~ col" p-3 w-full text-primary font-bold @click="update">
         {{ $t('timeline.show_new_items', number, { named: { v: formatNumber(number) } }) }}
diff --git a/components/timeline/TimelinePublic.vue b/components/timeline/TimelinePublic.vue
index 06122783..3cf34d32 100644
--- a/components/timeline/TimelinePublic.vue
+++ b/components/timeline/TimelinePublic.vue
@@ -1,5 +1,5 @@
 <script setup lang="ts">
-const paginator = useMasto().v1.timelines.listPublic()
+const paginator = useMasto().v1.timelines.listPublic({ limit: 30 })
 const stream = useMasto().v1.stream.streamPublicTimeline()
 onBeforeUnmount(() => stream.then(s => s.disconnect()))
 </script>
diff --git a/components/timeline/TimelinePublicLocal.vue b/components/timeline/TimelinePublicLocal.vue
index 4db8e093..546d5a24 100644
--- a/components/timeline/TimelinePublicLocal.vue
+++ b/components/timeline/TimelinePublicLocal.vue
@@ -1,5 +1,5 @@
 <script setup lang="ts">
-const paginator = useMasto().v1.timelines.listPublic({ local: true })
+const paginator = useMasto().v1.timelines.listPublic({ limit: 30, local: true })
 const stream = useMasto().v1.stream.streamCommunityTimeline()
 onBeforeUnmount(() => stream.then(s => s.disconnect()))
 </script>
diff --git a/composables/paginator.ts b/composables/paginator.ts
index 9689dcb8..08716b10 100644
--- a/composables/paginator.ts
+++ b/composables/paginator.ts
@@ -7,6 +7,7 @@ export function usePaginator<T, P>(
   stream?: Promise<WsEvents>,
   eventType: 'notification' | 'update' = 'update',
   preprocess: (items: T[]) => T[] = (items: T[]) => items,
+  buffer = 10,
 ) {
   const state = ref<PaginatorState>(isMastoInitialised.value ? 'idle' : 'loading')
   const items = ref<T[]>([])
@@ -66,8 +67,10 @@ export function usePaginator<T, P>(
       const result = await paginator.next()
 
       if (result.value?.length) {
-        nextItems.value = preprocess(result.value) as any
-        items.value.push(...nextItems.value)
+        const preprocessedItems = preprocess([...nextItems.value, ...result.value]) as any
+        const itemsToShowCount = preprocessedItems.length - buffer
+        nextItems.value = preprocessedItems.slice(itemsToShowCount)
+        items.value.push(...preprocessedItems.slice(0, itemsToShowCount))
         state.value = 'idle'
       }
       else {
@@ -136,7 +139,6 @@ export function usePaginator<T, P>(
   return {
     items,
     prevItems,
-    nextItems,
     update,
     state,
     error,
diff --git a/pages/[[server]]/@[account]/index/index.vue b/pages/[[server]]/@[account]/index/index.vue
index 7eba1a71..ec484285 100644
--- a/pages/[[server]]/@[account]/index/index.vue
+++ b/pages/[[server]]/@[account]/index/index.vue
@@ -8,7 +8,7 @@ const { t } = useI18n()
 
 const account = await fetchAccountByHandle(handle)
 
-const paginator = useMasto().v1.accounts.listStatuses(account.id, { excludeReplies: true })
+const paginator = useMasto().v1.accounts.listStatuses(account.id, { limit: 30, excludeReplies: true })
 
 if (account) {
   useHeadFixed({