diff --git a/src/pages/blog/reportAction.ts b/src/actions/report.ts
similarity index 80%
rename from src/pages/blog/reportAction.ts
rename to src/actions/report.ts
index c39e593..d36faa0 100644
--- a/src/pages/blog/reportAction.ts
+++ b/src/actions/report.ts
@@ -15,9 +15,14 @@ import {
   signAndPublish
 } from 'utils'
 
-export const blogReportRouteAction =
+export const reportRouteAction =
   (ndkContext: NDKContextType) =>
   async ({ params, request }: ActionFunctionArgs) => {
+    // Check which post type is reported
+    const url = new URL(request.url)
+    const isModReport = url.pathname.startsWith('/mod/')
+    const isBlogReport = url.pathname.startsWith('/blog/')
+    const title = isModReport ? 'Mod' : isBlogReport ? 'Blog' : 'Post'
     const requestData = await request.formData()
     const { naddr } = params
     if (!naddr) {
@@ -30,7 +35,12 @@ export const blogReportRouteAction =
     try {
       const decoded = nip19.decode<'naddr'>(naddr as `naddr1${string}`)
       const { identifier, kind, pubkey } = decoded.data
+
       aTag = `${kind}:${pubkey}:${identifier}`
+
+      if (isModReport) {
+        aTag = identifier
+      }
     } catch (error) {
       log(true, LogType.Error, 'Failed to decode naddr')
       return false
@@ -82,7 +92,7 @@ export const blogReportRouteAction =
         const alreadyExists =
           tags.findIndex((item) => item[0] === 'a' && item[1] === aTag) !== -1
         if (alreadyExists) {
-          toast.warn(`Blog reference is already in user's mute list`)
+          toast.warn(`${title} reference is already in user's mute list`)
           return false
         }
         tags.push(['a', aTag])
@@ -109,10 +119,12 @@ export const blogReportRouteAction =
         log(
           true,
           LogType.Error,
-          'Could not get pubkey for reporting blog!',
+          `Could not get pubkey for reporting ${title.toLowerCase()}!`,
           error
         )
-        toast.error('Could not get pubkey for reporting blog!')
+        toast.error(
+          `Could not get pubkey for reporting ${title.toLowerCase()}!`
+        )
         return false
       }
 
@@ -122,7 +134,7 @@ export const blogReportRouteAction =
         ndkContext.publish
       )
       return { isSent: isUpdated }
-    } else {
+    } else if (reportingPubkey) {
       const href = window.location.href
       let message = `I'd like to report ${href} due to following reasons:\n`
       Object.entries(formSubmit).forEach(([key, value]) => {
@@ -133,14 +145,26 @@ export const blogReportRouteAction =
       try {
         const isSent = await sendDMUsingRandomKey(
           message,
-          reportingPubkey!,
+          reportingPubkey,
           ndkContext.ndk,
           ndkContext.publish
         )
         return { isSent: isSent }
       } catch (error) {
-        log(true, LogType.Error, 'Failed to send a blog report', error)
+        log(
+          true,
+          LogType.Error,
+          `Failed to send a ${title.toLowerCase()} report`,
+          error
+        )
         return false
       }
+    } else {
+      log(
+        true,
+        LogType.Error,
+        `Failed to send a ${title.toLowerCase()} report: VITE_REPORTING_NPUB missing`
+      )
+      return false
     }
   }
diff --git a/src/components/Filters/BlogsFilter.tsx b/src/components/Filters/BlogsFilter.tsx
new file mode 100644
index 0000000..71b4098
--- /dev/null
+++ b/src/components/Filters/BlogsFilter.tsx
@@ -0,0 +1,165 @@
+import { useAppSelector, useLocalStorage } from 'hooks'
+import React from 'react'
+import {
+  FilterOptions,
+  ModeratedFilter,
+  NSFWFilter,
+  SortBy,
+  WOTFilterOptions
+} from 'types'
+import { DEFAULT_FILTER_OPTIONS } from 'utils'
+import { Dropdown } from './Dropdown'
+import { Option } from './Option'
+import { Filter } from '.'
+
+type Props = {
+  author?: string | undefined
+  filterKey?: string | undefined
+}
+
+export const BlogsFilter = React.memo(
+  ({ author, filterKey = 'filter-blog' }: Props) => {
+    const userState = useAppSelector((state) => state.user)
+    const [filterOptions, setFilterOptions] = useLocalStorage<FilterOptions>(
+      filterKey,
+      DEFAULT_FILTER_OPTIONS
+    )
+
+    return (
+      <Filter>
+        {/* sort filter options */}
+        <Dropdown label={filterOptions.sort}>
+          {Object.values(SortBy).map((item, index) => (
+            <div
+              key={`sortByItem-${index}`}
+              className='dropdown-item dropdownMainMenuItem'
+              onClick={() =>
+                setFilterOptions((prev) => ({
+                  ...prev,
+                  sort: item
+                }))
+              }
+            >
+              {item}
+            </div>
+          ))}
+        </Dropdown>
+
+        {/* moderation filter options */}
+        <Dropdown label={filterOptions.moderated}>
+          {Object.values(ModeratedFilter).map((item) => {
+            if (item === ModeratedFilter.Unmoderated_Fully) {
+              const isAdmin =
+                userState.user?.npub === import.meta.env.VITE_REPORTING_NPUB
+
+              const isOwnProfile =
+                author && userState.auth && userState.user?.pubkey === author
+
+              if (!(isAdmin || isOwnProfile)) return null
+            }
+
+            return (
+              <Option
+                key={`sort-${item}`}
+                onClick={() =>
+                  setFilterOptions((prev) => ({
+                    ...prev,
+                    moderated: item
+                  }))
+                }
+              >
+                {item}
+              </Option>
+            )
+          })}
+        </Dropdown>
+
+        {/* wot filter options */}
+        <Dropdown label={<>Trust: {filterOptions.wot}</>}>
+          {Object.values(WOTFilterOptions).map((item, index) => {
+            // when user is not logged in
+            if (item === WOTFilterOptions.Site_And_Mine && !userState.auth) {
+              return null
+            }
+
+            // when logged in user not admin
+            if (
+              item === WOTFilterOptions.None ||
+              item === WOTFilterOptions.Mine_Only ||
+              item === WOTFilterOptions.Exclude
+            ) {
+              const isWoTNpub =
+                userState.user?.npub === import.meta.env.VITE_SITE_WOT_NPUB
+
+              const isOwnProfile =
+                author && userState.auth && userState.user?.pubkey === author
+
+              if (!(isWoTNpub || isOwnProfile)) return null
+            }
+
+            return (
+              <Option
+                key={`wotFilterOption-${index}`}
+                onClick={() =>
+                  setFilterOptions((prev) => ({
+                    ...prev,
+                    wot: item
+                  }))
+                }
+              >
+                {item}
+              </Option>
+            )
+          })}
+        </Dropdown>
+
+        {/* nsfw filter options */}
+        <Dropdown label={filterOptions.nsfw}>
+          {Object.values(NSFWFilter).map((item, index) => (
+            <Option
+              key={`nsfwFilterItem-${index}`}
+              onClick={() =>
+                setFilterOptions((prev) => ({
+                  ...prev,
+                  nsfw: item
+                }))
+              }
+            >
+              {item}
+            </Option>
+          ))}
+        </Dropdown>
+
+        {/* source filter options */}
+        <Dropdown
+          label={
+            filterOptions.source === window.location.host
+              ? `Show From: ${filterOptions.source}`
+              : 'Show All'
+          }
+        >
+          <Option
+            onClick={() =>
+              setFilterOptions((prev) => ({
+                ...prev,
+                source: window.location.host
+              }))
+            }
+          >
+            Show From: {window.location.host}
+          </Option>
+          <Option
+            onClick={() =>
+              setFilterOptions((prev) => ({
+                ...prev,
+                source: 'Show All'
+              }))
+            }
+          >
+            Show All
+          </Option>
+        </Dropdown>
+      </Filter>
+    )
+  }
+)
diff --git a/src/components/Filters/Dropdown.tsx b/src/components/Filters/Dropdown.tsx
new file mode 100644
index 0000000..1bfb02f
--- /dev/null
+++ b/src/components/Filters/Dropdown.tsx
@@ -0,0 +1,25 @@
+import { PropsWithChildren } from 'react'
+
+interface DropdownProps {
+  label: React.ReactNode
+}
+export const Dropdown = ({
+  label,
+  children
+}: PropsWithChildren<DropdownProps>) => {
+  return (
+    <div className='FiltersMainElement'>
+      <div className='dropdown dropdownMain'>
+        <button
+          className='btn dropdown-toggle btnMain btnMainDropdown'
+          aria-expanded='false'
+          data-bs-toggle='dropdown'
+          type='button'
+        >
+          {label}
+        </button>
+        <div className='dropdown-menu dropdownMainMenu'>{children}</div>
+      </div>
+    </div>
+  )
+}
diff --git a/src/components/Filters/ModsFilter.tsx b/src/components/Filters/ModsFilter.tsx
new file mode 100644
index 0000000..afa43c4
--- /dev/null
+++ b/src/components/Filters/ModsFilter.tsx
@@ -0,0 +1,182 @@
+import { useAppSelector, useLocalStorage } from 'hooks'
+import React from 'react'
+import {
+  FilterOptions,
+  SortBy,
+  ModeratedFilter,
+  WOTFilterOptions,
+  NSFWFilter,
+  RepostFilter
+} from 'types'
+import { DEFAULT_FILTER_OPTIONS } from 'utils'
+import { Filter } from '.'
+import { Dropdown } from './Dropdown'
+import { Option } from './Option'
+
+type Props = {
+  author?: string | undefined
+  filterKey?: string | undefined
+}
+
+export const ModFilter = React.memo(
+  ({ author, filterKey = 'filter' }: Props) => {
+    const userState = useAppSelector((state) => state.user)
+    const [filterOptions, setFilterOptions] = useLocalStorage<FilterOptions>(
+      filterKey,
+      DEFAULT_FILTER_OPTIONS
+    )
+
+    return (
+      <Filter>
+        {/* sort filter options */}
+        <Dropdown label={filterOptions.sort}>
+          {Object.values(SortBy).map((item, index) => (
+            <Option
+              key={`sortByItem-${index}`}
+              onClick={() =>
+                setFilterOptions((prev) => ({
+                  ...prev,
+                  sort: item
+                }))
+              }
+            >
+              {item}
+            </Option>
+          ))}
+        </Dropdown>
+
+        {/* moderation filter options */}
+        <Dropdown label={filterOptions.moderated}>
+          {Object.values(ModeratedFilter).map((item, index) => {
+            if (item === ModeratedFilter.Unmoderated_Fully) {
+              const isAdmin =
+                userState.user?.npub === import.meta.env.VITE_REPORTING_NPUB
+
+              const isOwnProfile =
+                author && userState.auth && userState.user?.pubkey === author
+
+              if (!(isAdmin || isOwnProfile)) return null
+            }
+
+            return (
+              <Option
+                key={`moderatedFilterItem-${index}`}
+                onClick={() =>
+                  setFilterOptions((prev) => ({
+                    ...prev,
+                    moderated: item
+                  }))
+                }
+              >
+                {item}
+              </Option>
+            )
+          })}
+        </Dropdown>
+
+        {/* wot filter options */}
+        <Dropdown label={<>Trust: {filterOptions.wot}</>}>
+          {Object.values(WOTFilterOptions).map((item, index) => {
+            // when user is not logged in
+            if (item === WOTFilterOptions.Site_And_Mine && !userState.auth) {
+              return null
+            }
+
+            // when logged in user not admin
+            if (
+              item === WOTFilterOptions.None ||
+              item === WOTFilterOptions.Mine_Only ||
+              item === WOTFilterOptions.Exclude
+            ) {
+              const isWoTNpub =
+                userState.user?.npub === import.meta.env.VITE_SITE_WOT_NPUB
+
+              const isOwnProfile =
+                author && userState.auth && userState.user?.pubkey === author
+
+              if (!(isWoTNpub || isOwnProfile)) return null
+            }
+
+            return (
+              <Option
+                key={`wotFilterOption-${index}`}
+                onClick={() =>
+                  setFilterOptions((prev) => ({
+                    ...prev,
+                    wot: item
+                  }))
+                }
+              >
+                {item}
+              </Option>
+            )
+          })}
+        </Dropdown>
+
+        {/* nsfw filter options */}
+        <Dropdown label={filterOptions.nsfw}>
+          {Object.values(NSFWFilter).map((item, index) => (
+            <Option
+              key={`nsfwFilterItem-${index}`}
+              onClick={() =>
+                setFilterOptions((prev) => ({
+                  ...prev,
+                  nsfw: item
+                }))
+              }
+            >
+              {item}
+            </Option>
+          ))}
+        </Dropdown>
+
+        {/* repost filter options */}
+        <Dropdown label={filterOptions.repost}>
+          {Object.values(RepostFilter).map((item, index) => (
+            <Option
+              key={`repostFilterItem-${index}`}
+              onClick={() =>
+                setFilterOptions((prev) => ({
+                  ...prev,
+                  repost: item
+                }))
+              }
+            >
+              {item}
+            </Option>
+          ))}
+        </Dropdown>
+
+        {/* source filter options */}
+        <Dropdown
+          label={
+            filterOptions.source === window.location.host
+              ? `Show From: ${filterOptions.source}`
+              : 'Show All'
+          }
+        >
+          <Option
+            onClick={() =>
+              setFilterOptions((prev) => ({
+                ...prev,
+                source: window.location.host
+              }))
+            }
+          >
+            Show From: {window.location.host}
+          </Option>
+          <Option
+            onClick={() =>
+              setFilterOptions((prev) => ({
+                ...prev,
+                source: 'Show All'
+              }))
+            }
+          >
+            Show All
+          </Option>
+        </Dropdown>
+      </Filter>
+    )
+  }
+)
diff --git a/src/components/Filters/Option.tsx b/src/components/Filters/Option.tsx
new file mode 100644
index 0000000..1f854e8
--- /dev/null
+++ b/src/components/Filters/Option.tsx
@@ -0,0 +1,16 @@
+import { PropsWithChildren } from 'react'
+
+interface OptionProps {
+  onClick: React.MouseEventHandler<HTMLDivElement>
+}
+
+export const Option = ({
+  onClick,
+  children
+}: PropsWithChildren<OptionProps>) => {
+  return (
+    <div className='dropdown-item dropdownMainMenuItem' onClick={onClick}>
+      {children}
+    </div>
+  )
+}
diff --git a/src/components/Filters/index.tsx b/src/components/Filters/index.tsx
new file mode 100644
index 0000000..4260f79
--- /dev/null
+++ b/src/components/Filters/index.tsx
@@ -0,0 +1,9 @@
+import { PropsWithChildren } from 'react'
+
+export const Filter = ({ children }: PropsWithChildren) => {
+  return (
+    <div className='IBMSecMain'>
+      <div className='FiltersMain'>{children}</div>
+    </div>
+  )
+}
diff --git a/src/components/Inputs.tsx b/src/components/Inputs.tsx
index 38d48af..95b4f48 100644
--- a/src/components/Inputs.tsx
+++ b/src/components/Inputs.tsx
@@ -7,7 +7,7 @@ import '../styles/styles.css'
 import '../styles/tiptap.scss'
 
 interface InputFieldProps {
-  label: string
+  label: string | React.ReactElement
   description?: string
   type?: 'text' | 'textarea' | 'richtext'
   placeholder: string
diff --git a/src/components/LoadingSpinner/index.tsx b/src/components/LoadingSpinner/index.tsx
index 9f22262..f1f79af 100644
--- a/src/components/LoadingSpinner/index.tsx
+++ b/src/components/LoadingSpinner/index.tsx
@@ -1,3 +1,4 @@
+import { useNavigation } from 'react-router-dom'
 import styles from '../../styles/loadingSpinner.module.scss'
 
 interface Props {
@@ -16,3 +17,14 @@ export const LoadingSpinner = (props: Props) => {
     </div>
   )
 }
+
+export const RouterLoadingSpinner = () => {
+  const navigation = useNavigation()
+
+  if (navigation.state === 'idle') return null
+
+  const desc =
+    navigation.state.charAt(0).toUpperCase() + navigation.state.slice(1)
+
+  return <LoadingSpinner desc={`${desc}...`} />
+}
diff --git a/src/components/ModCard.tsx b/src/components/ModCard.tsx
index c54b300..108d33f 100644
--- a/src/components/ModCard.tsx
+++ b/src/components/ModCard.tsx
@@ -57,6 +57,11 @@ export const ModCard = React.memo((props: ModDetails) => {
               <p>NSFW</p>
             </div>
           )}
+          {props.repost && (
+            <div className='IBMSMSMBSSTagsTag IBMSMSMBSSTagsTagRepost IBMSMSMBSSTagsTagRepostCard'>
+              <p>REPOST</p>
+            </div>
+          )}
         </div>
         <div className='cMMBody'>
           <h3 className='cMMBodyTitle'>{props.title}</h3>
diff --git a/src/components/ModForm.tsx b/src/components/ModForm.tsx
index 7411c47..ea54912 100644
--- a/src/components/ModForm.tsx
+++ b/src/components/ModForm.tsx
@@ -29,6 +29,7 @@ import {
 import { CheckboxField, InputError, InputField } from './Inputs'
 import { LoadingSpinner } from './LoadingSpinner'
 import { NDKEvent } from '@nostr-dev-kit/ndk'
+import { OriginalAuthor } from './OriginalAuthor'
 
 interface FormErrors {
   game?: string
@@ -40,6 +41,8 @@ interface FormErrors {
   screenshotsUrls?: string[]
   tags?: string
   downloadUrls?: string[]
+  author?: string
+  originalAuthor?: string
 }
 
 interface GameOption {
@@ -198,36 +201,42 @@ export const ModForm = ({ existingModData }: ModFormProps) => {
     const aTag =
       formState.aTag || `${kinds.ClassifiedListing}:${hexPubkey}:${uuid}`
 
+    const tags = [
+      ['d', uuid],
+      ['a', aTag],
+      ['r', formState.rTag],
+      ['t', T_TAG_VALUE],
+      [
+        'published_at',
+        existingModData
+          ? existingModData.published_at.toString()
+          : currentTimeStamp.toString()
+      ],
+      ['game', formState.game],
+      ['title', formState.title],
+      ['featuredImageUrl', formState.featuredImageUrl],
+      ['summary', formState.summary],
+      ['nsfw', formState.nsfw.toString()],
+      ['repost', formState.repost.toString()],
+      ['screenshotsUrls', ...formState.screenshotsUrls],
+      ['tags', ...formState.tags.split(',')],
+      [
+        'downloadUrls',
+        ...formState.downloadUrls.map((downloadUrl) =>
+          JSON.stringify(downloadUrl)
+        )
+      ]
+    ]
+    if (formState.repost && formState.originalAuthor) {
+      tags.push(['originalAuthor', formState.originalAuthor])
+    }
+
     const unsignedEvent: UnsignedEvent = {
       kind: kinds.ClassifiedListing,
       created_at: currentTimeStamp,
       pubkey: hexPubkey,
       content: formState.body,
-      tags: [
-        ['d', uuid],
-        ['a', aTag],
-        ['r', formState.rTag],
-        ['t', T_TAG_VALUE],
-        [
-          'published_at',
-          existingModData
-            ? existingModData.published_at.toString()
-            : currentTimeStamp.toString()
-        ],
-        ['game', formState.game],
-        ['title', formState.title],
-        ['featuredImageUrl', formState.featuredImageUrl],
-        ['summary', formState.summary],
-        ['nsfw', formState.nsfw.toString()],
-        ['screenshotsUrls', ...formState.screenshotsUrls],
-        ['tags', ...formState.tags.split(',')],
-        [
-          'downloadUrls',
-          ...formState.downloadUrls.map((downloadUrl) =>
-            JSON.stringify(downloadUrl)
-          )
-        ]
-      ]
+      tags
     }
 
     const signedEvent = await window.nostr
@@ -318,6 +327,13 @@ export const ModForm = ({ existingModData }: ModFormProps) => {
       }
     }
 
+    if (
+      formState.repost &&
+      (!formState.originalAuthor || formState.originalAuthor === '')
+    ) {
+      errors.originalAuthor = 'Original author field can not be empty'
+    }
+
     if (formState.tags === '') {
       errors.tags = 'Tags field can not be empty'
     }
@@ -397,6 +413,31 @@ export const ModForm = ({ existingModData }: ModFormProps) => {
         handleChange={handleCheckboxChange}
         type='stylized'
       />
+      <CheckboxField
+        label='This is a repost of a mod I did not create'
+        name='repost'
+        isChecked={formState.repost}
+        handleChange={handleCheckboxChange}
+        type='stylized'
+      />
+      {formState.repost && (
+        <>
+          <InputField
+            label={
+              <span>
+                Created by:{' '}
+                {<OriginalAuthor value={formState.originalAuthor || ''} />}
+              </span>
+            }
+            type='text'
+            placeholder="Original author's name, npub or nprofile"
+            name='originalAuthor'
+            value={formState.originalAuthor || ''}
+            error={formErrors.originalAuthor || ''}
+            onChange={handleInputChange}
+          />
+        </>
+      )}
       <div className='inputLabelWrapperMain'>
         <div className='labelWrapperMain'>
           <label className='form-label labelMain'>Screenshots URLs</label>
diff --git a/src/components/ModsFilter.tsx b/src/components/ModsFilter.tsx
deleted file mode 100644
index 8d733c7..0000000
--- a/src/components/ModsFilter.tsx
+++ /dev/null
@@ -1,235 +0,0 @@
-import { useAppSelector, useLocalStorage } from 'hooks'
-import React from 'react'
-import {
-  FilterOptions,
-  ModeratedFilter,
-  NSFWFilter,
-  SortBy,
-  WOTFilterOptions
-} from 'types'
-import { DEFAULT_FILTER_OPTIONS } from 'utils'
-
-type Props = {
-  author?: string | undefined
-  filterKey?: string | undefined
-}
-
-export const ModFilter = React.memo(
-  ({ author, filterKey = 'filter' }: Props) => {
-    const userState = useAppSelector((state) => state.user)
-    const [filterOptions, setFilterOptions] = useLocalStorage<FilterOptions>(
-      filterKey,
-      DEFAULT_FILTER_OPTIONS
-    )
-
-    return (
-      <div className='IBMSecMain'>
-        <div className='FiltersMain'>
-          {/* sort filter options */}
-          <div className='FiltersMainElement'>
-            <div className='dropdown dropdownMain'>
-              <button
-                className='btn dropdown-toggle btnMain btnMainDropdown'
-                aria-expanded='false'
-                data-bs-toggle='dropdown'
-                type='button'
-              >
-                {filterOptions.sort}
-              </button>
-
-              <div className='dropdown-menu dropdownMainMenu'>
-                {Object.values(SortBy).map((item, index) => (
-                  <div
-                    key={`sortByItem-${index}`}
-                    className='dropdown-item dropdownMainMenuItem'
-                    onClick={() =>
-                      setFilterOptions((prev) => ({
-                        ...prev,
-                        sort: item
-                      }))
-                    }
-                  >
-                    {item}
-                  </div>
-                ))}
-              </div>
-            </div>
-          </div>
-
-          {/* moderation filter options */}
-          <div className='FiltersMainElement'>
-            <div className='dropdown dropdownMain'>
-              <button
-                className='btn dropdown-toggle btnMain btnMainDropdown'
-                aria-expanded='false'
-                data-bs-toggle='dropdown'
-                type='button'
-              >
-                {filterOptions.moderated}
-              </button>
-              <div className='dropdown-menu dropdownMainMenu'>
-                {Object.values(ModeratedFilter).map((item, index) => {
-                  if (item === ModeratedFilter.Unmoderated_Fully) {
-                    const isAdmin =
-                      userState.user?.npub ===
-                      import.meta.env.VITE_REPORTING_NPUB
-
-                    const isOwnProfile =
-                      author &&
-                      userState.auth &&
-                      userState.user?.pubkey === author
-
-                    if (!(isAdmin || isOwnProfile)) return null
-                  }
-
-                  return (
-                    <div
-                      key={`moderatedFilterItem-${index}`}
-                      className='dropdown-item dropdownMainMenuItem'
-                      onClick={() =>
-                        setFilterOptions((prev) => ({
-                          ...prev,
-                          moderated: item
-                        }))
-                      }
-                    >
-                      {item}
-                    </div>
-                  )
-                })}
-              </div>
-            </div>
-          </div>
-
-          {/* wot filter options */}
-          <div className='FiltersMainElement'>
-            <div className='dropdown dropdownMain'>
-              <button
-                className='btn dropdown-toggle btnMain btnMainDropdown'
-                aria-expanded='false'
-                data-bs-toggle='dropdown'
-                type='button'
-              >
-                Trust: {filterOptions.wot}
-              </button>
-              <div className='dropdown-menu dropdownMainMenu'>
-                {Object.values(WOTFilterOptions).map((item, index) => {
-                  // when user is not logged in
-                  if (
-                    item === WOTFilterOptions.Site_And_Mine &&
-                    !userState.auth
-                  ) {
-                    return null
-                  }
-
-                  // when logged in user not admin
-                  if (
-                    item === WOTFilterOptions.None ||
-                    item === WOTFilterOptions.Mine_Only ||
-                    item === WOTFilterOptions.Exclude
-                  ) {
-                    const isWoTNpub =
-                      userState.user?.npub ===
-                      import.meta.env.VITE_SITE_WOT_NPUB
-
-                    const isOwnProfile =
-                      author &&
-                      userState.auth &&
-                      userState.user?.pubkey === author
-
-                    if (!(isWoTNpub || isOwnProfile)) return null
-                  }
-
-                  return (
-                    <div
-                      key={`wotFilterOption-${index}`}
-                      className='dropdown-item dropdownMainMenuItem'
-                      onClick={() =>
-                        setFilterOptions((prev) => ({
-                          ...prev,
-                          wot: item
-                        }))
-                      }
-                    >
-                      {item}
-                    </div>
-                  )
-                })}
-              </div>
-            </div>
-          </div>
-
-          {/* nsfw filter options */}
-          <div className='FiltersMainElement'>
-            <div className='dropdown dropdownMain'>
-              <button
-                className='btn dropdown-toggle btnMain btnMainDropdown'
-                aria-expanded='false'
-                data-bs-toggle='dropdown'
-                type='button'
-              >
-                {filterOptions.nsfw}
-              </button>
-              <div className='dropdown-menu dropdownMainMenu'>
-                {Object.values(NSFWFilter).map((item, index) => (
-                  <div
-                    key={`nsfwFilterItem-${index}`}
-                    className='dropdown-item dropdownMainMenuItem'
-                    onClick={() =>
-                      setFilterOptions((prev) => ({
-                        ...prev,
-                        nsfw: item
-                      }))
-                    }
-                  >
-                    {item}
-                  </div>
-                ))}
-              </div>
-            </div>
-          </div>
-
-          {/* source filter options */}
-          <div className='FiltersMainElement'>
-            <div className='dropdown dropdownMain'>
-              <button
-                className='btn dropdown-toggle btnMain btnMainDropdown'
-                aria-expanded='false'
-                data-bs-toggle='dropdown'
-                type='button'
-              >
-                {filterOptions.source === window.location.host
-                  ? `Show From: ${filterOptions.source}`
-                  : 'Show All'}
-              </button>
-              <div className='dropdown-menu dropdownMainMenu'>
-                <div
-                  className='dropdown-item dropdownMainMenuItem'
-                  onClick={() =>
-                    setFilterOptions((prev) => ({
-                      ...prev,
-                      source: window.location.host
-                    }))
-                  }
-                >
-                  Show From: {window.location.host}
-                </div>
-                <div
-                  className='dropdown-item dropdownMainMenuItem'
-                  onClick={() =>
-                    setFilterOptions((prev) => ({
-                      ...prev,
-                      source: 'Show All'
-                    }))
-                  }
-                >
-                  Show All
-                </div>
-              </div>
-            </div>
-          </div>
-        </div>
-      </div>
-    )
-  }
-)
diff --git a/src/components/OriginalAuthor.tsx b/src/components/OriginalAuthor.tsx
new file mode 100644
index 0000000..60dc4dc
--- /dev/null
+++ b/src/components/OriginalAuthor.tsx
@@ -0,0 +1,48 @@
+import { nip19 } from 'nostr-tools'
+import { appRoutes, getProfilePageRoute } from 'routes'
+import { npubToHex } from 'utils'
+import { ProfileLink } from './ProfileLink'
+
+interface OriginalAuthorProps {
+  value: string
+  fallback?: boolean
+}
+
+export const OriginalAuthor = ({
+  value,
+  fallback = false
+}: OriginalAuthorProps) => {
+  let profilePubkey
+  let displayName = '[name not set up]'
+
+  // Try to decode/encode depending on what we send to link
+  let profileRoute = appRoutes.home
+  try {
+    if (value.startsWith('nprofile1')) {
+      const decoded = nip19.decode(value as `nprofile1${string}`)
+      profileRoute = getProfilePageRoute(value)
+      profilePubkey = decoded?.data.pubkey
+    } else if (value.startsWith('npub1')) {
+      profilePubkey = npubToHex(value)
+      const nprofile = profilePubkey
+        ? nip19.nprofileEncode({
+            pubkey: profilePubkey
+          })
+        : undefined
+
+      if (nprofile) {
+        profileRoute = getProfilePageRoute(nprofile)
+      }
+    } else {
+      displayName = value
+    }
+  } catch (error) {
+    console.error('Failed to create profile link:', error)
+    displayName = value
+  }
+
+  if (profileRoute && profilePubkey)
+    return <ProfileLink pubkey={profilePubkey} profileRoute={profileRoute} />
+
+  return fallback ? displayName : null
+}
diff --git a/src/components/ProfileLink.tsx b/src/components/ProfileLink.tsx
new file mode 100644
index 0000000..0fcdfca
--- /dev/null
+++ b/src/components/ProfileLink.tsx
@@ -0,0 +1,15 @@
+import { useProfile } from 'hooks/useProfile'
+import { Link } from 'react-router-dom'
+
+interface ProfileLinkProps {
+  pubkey: string
+  profileRoute: string
+}
+
+export const ProfileLink = ({ pubkey, profileRoute }: ProfileLinkProps) => {
+  const profile = useProfile(pubkey)
+  const displayName =
+    profile?.displayName || profile?.name || '[name not set up]'
+
+  return <Link to={profileRoute}>{displayName}</Link>
+}
diff --git a/src/pages/blog/report.tsx b/src/components/ReportPopup.tsx
similarity index 84%
rename from src/pages/blog/report.tsx
rename to src/components/ReportPopup.tsx
index bbbd880..d31e4b3 100644
--- a/src/pages/blog/report.tsx
+++ b/src/components/ReportPopup.tsx
@@ -1,22 +1,23 @@
 import { useFetcher } from 'react-router-dom'
 import { CheckboxFieldUncontrolled } from 'components/Inputs'
 import { useEffect } from 'react'
+import { ReportReason } from 'types/report'
+import { LoadingSpinner } from './LoadingSpinner'
 
 type ReportPopupProps = {
+  openedAt: number
+  reasons: ReportReason[]
   handleClose: () => void
 }
 
-const BLOG_REPORT_REASONS = [
-  { label: 'Actually CP', key: 'actuallyCP' },
-  { label: 'Spam', key: 'spam' },
-  { label: 'Scam', key: 'scam' },
-  { label: 'Malware', key: 'malware' },
-  { label: `Wasn't tagged NSFW`, key: 'wasntTaggedNSFW' },
-  { label: 'Other', key: 'otherReason' }
-]
-
-export const ReportPopup = ({ handleClose }: ReportPopupProps) => {
-  const fetcher = useFetcher()
+export const ReportPopup = ({
+  openedAt,
+  reasons,
+  handleClose
+}: ReportPopupProps) => {
+  // Use openedAt to allow for multiple reports
+  // by default, fetcher will remember the data
+  const fetcher = useFetcher({ key: openedAt.toString() })
 
   // Close automatically if action succeeds
   useEffect(() => {
@@ -30,6 +31,7 @@ export const ReportPopup = ({ handleClose }: ReportPopupProps) => {
 
   return (
     <>
+      {fetcher.state !== 'idle' && <LoadingSpinner desc={''} />}
       <div className='popUpMain'>
         <div className='ContainerMain'>
           <div className='popUpMainCardWrapper'>
@@ -64,7 +66,7 @@ export const ReportPopup = ({ handleClose }: ReportPopupProps) => {
                     >
                       Why are you reporting this?
                     </label>
-                    {BLOG_REPORT_REASONS.map((r) => (
+                    {reasons.map((r) => (
                       <CheckboxFieldUncontrolled
                         key={r.key}
                         label={r.label}
diff --git a/src/hooks/useCuratedSet.tsx b/src/hooks/useCuratedSet.tsx
new file mode 100644
index 0000000..85ecaab
--- /dev/null
+++ b/src/hooks/useCuratedSet.tsx
@@ -0,0 +1,15 @@
+import { useState } from 'react'
+import { useNDKContext } from './useNDKContext'
+import { useDidMount } from './useDidMount'
+import { CurationSetIdentifiers, getReportingSet } from 'utils'
+
+export const useCuratedSet = (type: CurationSetIdentifiers) => {
+  const ndkContext = useNDKContext()
+  const [curatedSet, setCuratedSet] = useState<string[]>([])
+
+  useDidMount(async () => {
+    setCuratedSet(await getReportingSet(type, ndkContext))
+  })
+
+  return curatedSet
+}
diff --git a/src/hooks/useFilteredMods.ts b/src/hooks/useFilteredMods.ts
index 7c16b18..ef7c249 100644
--- a/src/hooks/useFilteredMods.ts
+++ b/src/hooks/useFilteredMods.ts
@@ -6,6 +6,7 @@ import {
   ModeratedFilter,
   MuteLists,
   NSFWFilter,
+  RepostFilter,
   SortBy,
   WOTFilterOptions
 } from 'types'
@@ -22,6 +23,7 @@ export const useFilteredMods = (
     admin: MuteLists
     user: MuteLists
   },
+  repostList: string[],
   author?: string | undefined
 ) => {
   const { siteWot, siteWotLevel, userWot, userWotLevel } = useAppSelector(
@@ -53,6 +55,30 @@ export const useFilteredMods = (
       }
     }
 
+    const repostFilter = (mods: ModDetails[]) => {
+      if (filterOptions.repost !== RepostFilter.Hide_Repost) {
+        // Add repost tag to mods included in repostList
+        mods = mods.map((mod) => {
+          return !mod.repost && repostList.includes(mod.aTag)
+            ? { ...mod, repost: true }
+            : mod
+        })
+      }
+      // Determine the filtering logic based on the Repost filter option
+      switch (filterOptions.repost) {
+        case RepostFilter.Hide_Repost:
+          return mods.filter(
+            (mod) => !mod.repost && !repostList.includes(mod.aTag)
+          )
+        case RepostFilter.Show_Repost:
+          return mods
+        case RepostFilter.Only_Repost:
+          return mods.filter(
+            (mod) => mod.repost || repostList.includes(mod.aTag)
+          )
+      }
+    }
+
     const wotFilter = (mods: ModDetails[]) => {
       // Determine the filtering logic based on the WOT filter option and user state
       // when user is not logged in use Site_Only
@@ -93,7 +119,7 @@ export const useFilteredMods = (
     }
 
     let filtered = nsfwFilter(mods)
-
+    filtered = repostFilter(filtered)
     filtered = wotFilter(filtered)
 
     const isAdmin = userState.user?.npub === import.meta.env.VITE_REPORTING_NPUB
@@ -135,10 +161,12 @@ export const useFilteredMods = (
     filterOptions.moderated,
     filterOptions.wot,
     filterOptions.nsfw,
+    filterOptions.repost,
     author,
     mods,
     muteLists,
     nsfwList,
+    repostList,
     siteWot,
     siteWotLevel,
     userWot,
diff --git a/src/pages/blog/index.tsx b/src/pages/blog/index.tsx
index c2ce709..0c26a57 100644
--- a/src/pages/blog/index.tsx
+++ b/src/pages/blog/index.tsx
@@ -22,7 +22,16 @@ import { BlogCard } from 'components/BlogCard'
 import { copyTextToClipboard } from 'utils'
 import { toast } from 'react-toastify'
 import { useAppSelector, useBodyScrollDisable } from 'hooks'
-import { ReportPopup } from './report'
+import { ReportPopup } from 'components/ReportPopup'
+
+const BLOG_REPORT_REASONS = [
+  { label: 'Actually CP', key: 'actuallyCP' },
+  { label: 'Spam', key: 'spam' },
+  { label: 'Scam', key: 'scam' },
+  { label: 'Malware', key: 'malware' },
+  { label: `Wasn't tagged NSFW`, key: 'wasntTaggedNSFW' },
+  { label: 'Other', key: 'otherReason' }
+]
 
 export const BlogPage = () => {
   const { blog, latest, isAddedToNSFW, isBlocked } =
@@ -53,8 +62,8 @@ export const BlogPage = () => {
     [sanitized]
   )
 
-  const [showReportPopUp, setShowReportPopUp] = useState(false)
-  useBodyScrollDisable(showReportPopUp)
+  const [showReportPopUp, setShowReportPopUp] = useState<number>()
+  useBodyScrollDisable(!!showReportPopUp)
 
   const submit = useSubmit()
   const handleBlock = () => {
@@ -190,7 +199,7 @@ export const BlogPage = () => {
                           <a
                             className='dropdown-item dropdownMainMenuItem'
                             id='reportPost'
-                            onClick={() => setShowReportPopUp(true)}
+                            onClick={() => setShowReportPopUp(Date.now())}
                           >
                             <svg
                               xmlns='http://www.w3.org/2000/svg'
@@ -309,8 +318,12 @@ export const BlogPage = () => {
                 {navigation.state !== 'idle' && (
                   <LoadingSpinner desc={'Loading...'} />
                 )}
-                {showReportPopUp && (
-                  <ReportPopup handleClose={() => setShowReportPopUp(false)} />
+                {!!showReportPopUp && (
+                  <ReportPopup
+                    openedAt={showReportPopUp}
+                    reasons={BLOG_REPORT_REASONS}
+                    handleClose={() => setShowReportPopUp(undefined)}
+                  />
                 )}
               </>
             )}
diff --git a/src/pages/blogs/index.tsx b/src/pages/blogs/index.tsx
index 08d0848..2155b39 100644
--- a/src/pages/blogs/index.tsx
+++ b/src/pages/blogs/index.tsx
@@ -11,6 +11,9 @@ import '../../styles/styles.css'
 import { PaginationWithPageNumbers } from 'components/Pagination'
 import { scrollIntoView } from 'utils'
 import { LoadingSpinner } from 'components/LoadingSpinner'
+import { Filter } from 'components/Filters'
+import { Dropdown } from 'components/Filters/Dropdown'
+import { Option } from 'components/Filters/Option'
 
 export const BlogsPage = () => {
   const navigation = useNavigation()
@@ -126,66 +129,39 @@ export const BlogsPage = () => {
             </div>
           </div>
 
-          <div className='IBMSecMain'>
-            <div className='FiltersMain'>
-              <div className='FiltersMainElement'>
-                <div className='dropdown dropdownMain'>
-                  <button
-                    className='btn dropdown-toggle btnMain btnMainDropdown'
-                    aria-expanded='false'
-                    data-bs-toggle='dropdown'
-                    type='button'
-                  >
-                    {filterOptions.sort}
-                  </button>
-                  <div className='dropdown-menu dropdownMainMenu'>
-                    {Object.values(SortBy).map((item, index) => (
-                      <div
-                        key={`sortByItem-${index}`}
-                        className='dropdown-item dropdownMainMenuItem'
-                        onClick={() =>
-                          setFilterOptions((prev) => ({
-                            ...prev,
-                            sort: item
-                          }))
-                        }
-                      >
-                        {item}
-                      </div>
-                    ))}
-                  </div>
-                </div>
-              </div>
-              <div className='FiltersMainElement'>
-                <div className='dropdown dropdownMain'>
-                  <button
-                    className='btn dropdown-toggle btnMain btnMainDropdown'
-                    aria-expanded='false'
-                    data-bs-toggle='dropdown'
-                    type='button'
-                  >
-                    {filterOptions.nsfw}
-                  </button>
-                  <div className='dropdown-menu dropdownMainMenu'>
-                    {Object.values(NSFWFilter).map((item, index) => (
-                      <div
-                        key={`nsfwFilterItem-${index}`}
-                        className='dropdown-item dropdownMainMenuItem'
-                        onClick={() =>
-                          setFilterOptions((prev) => ({
-                            ...prev,
-                            nsfw: item
-                          }))
-                        }
-                      >
-                        {item}
-                      </div>
-                    ))}
-                  </div>
-                </div>
-              </div>
-            </div>
-          </div>
+          <Filter>
+            <Dropdown label={filterOptions.sort}>
+              {Object.values(SortBy).map((item, index) => (
+                <Option
+                  key={`sortByItem-${index}`}
+                  onClick={() =>
+                    setFilterOptions((prev) => ({
+                      ...prev,
+                      sort: item
+                    }))
+                  }
+                >
+                  {item}
+                </Option>
+              ))}
+            </Dropdown>
+
+            <Dropdown label={filterOptions.nsfw}>
+              {Object.values(NSFWFilter).map((item, index) => (
+                <Option
+                  key={`nsfwFilterItem-${index}`}
+                  onClick={() =>
+                    setFilterOptions((prev) => ({
+                      ...prev,
+                      nsfw: item
+                    }))
+                  }
+                >
+                  {item}
+                </Option>
+              ))}
+            </Dropdown>
+          </Filter>
 
           <div className='IBMSecMain IBMSMListWrapper'>
             <div className='IBMSMList'>
diff --git a/src/pages/game.tsx b/src/pages/game.tsx
index 6f82493..da49f87 100644
--- a/src/pages/game.tsx
+++ b/src/pages/game.tsx
@@ -4,7 +4,7 @@ import {
   NDKSubscriptionCacheUsage
 } from '@nostr-dev-kit/ndk'
 import { ModCard } from 'components/ModCard'
-import { ModFilter } from 'components/ModsFilter'
+import { ModFilter } from 'components/Filters/ModsFilter'
 import { PaginationWithPageNumbers } from 'components/Pagination'
 import { SearchInput } from 'components/SearchInput'
 import { MAX_MODS_PER_PAGE, T_TAG_VALUE } from 'constants.ts'
@@ -20,11 +20,13 @@ import { useEffect, useMemo, useRef, useState } from 'react'
 import { useParams, useSearchParams } from 'react-router-dom'
 import { FilterOptions, ModDetails } from 'types'
 import {
+  CurationSetIdentifiers,
   DEFAULT_FILTER_OPTIONS,
   extractModData,
   isModDataComplete,
   scrollIntoView
 } from 'utils'
+import { useCuratedSet } from 'hooks/useCuratedSet'
 
 export const GamePage = () => {
   const scrollTargetRef = useRef<HTMLDivElement>(null)
@@ -33,6 +35,7 @@ export const GamePage = () => {
   const { ndk } = useNDKContext()
   const muteLists = useMuteLists()
   const nsfwList = useNSFWList()
+  const repostList = useCuratedSet(CurationSetIdentifiers.Repost)
 
   const [filterOptions] = useLocalStorage<FilterOptions>(
     'filter',
@@ -101,7 +104,8 @@ export const GamePage = () => {
     userState,
     filterOptions,
     nsfwList,
-    muteLists
+    muteLists,
+    repostList
   )
 
   // Pagination logic
diff --git a/src/pages/home.tsx b/src/pages/home.tsx
index 78f722c..ef3d845 100644
--- a/src/pages/home.tsx
+++ b/src/pages/home.tsx
@@ -430,9 +430,7 @@ const DisplayLatestBlogs = () => {
 
   return (
     <div className='IBMSecMain IBMSMListWrapper'>
-      {navigation.state !== 'idle' && (
-        <LoadingSpinner desc={'Fetching blog...'} />
-      )}
+      {navigation.state !== 'idle' && <LoadingSpinner desc={'Fetching...'} />}
       <div className='IBMSMTitleMain'>
         <h2 className='IBMSMTitleMainHeading'>Blog Posts</h2>
       </div>
diff --git a/src/pages/mod/action.ts b/src/pages/mod/action.ts
new file mode 100644
index 0000000..5f7f477
--- /dev/null
+++ b/src/pages/mod/action.ts
@@ -0,0 +1,233 @@
+import { NDKFilter } from '@nostr-dev-kit/ndk'
+import { NDKContextType } from 'contexts/NDKContext'
+import { kinds, nip19, UnsignedEvent } from 'nostr-tools'
+import { ActionFunctionArgs } from 'react-router-dom'
+import { toast } from 'react-toastify'
+import { store } from 'store'
+import { UserRelaysType } from 'types'
+import {
+  addToCurationSet,
+  CurationSetIdentifiers,
+  log,
+  LogType,
+  now,
+  removeFromCurationSet,
+  signAndPublish
+} from 'utils'
+
+export const modRouteAction =
+  (ndkContext: NDKContextType) =>
+  async ({ params, request }: ActionFunctionArgs) => {
+    const { naddr } = params
+    if (!naddr) {
+      log(true, LogType.Error, 'Required naddr.')
+      return null
+    }
+
+    // Decode author from naddr
+    let aTag: string | undefined
+    try {
+      const decoded = nip19.decode<'naddr'>(naddr as `naddr1${string}`)
+
+      // We encode mods naddr identifier as a whole aTag
+      const { identifier } = decoded.data
+      aTag = identifier
+    } catch (error) {
+      log(true, LogType.Error, 'Failed to decode naddr')
+      return null
+    }
+
+    if (!aTag) {
+      log(true, LogType.Error, 'Missing #a Tag')
+      return null
+    }
+
+    const userState = store.getState().user
+    let hexPubkey: string
+    if (userState.auth && userState.user?.pubkey) {
+      hexPubkey = userState.user.pubkey as string
+    } else {
+      hexPubkey = (await window.nostr?.getPublicKey()) as string
+    }
+
+    if (!hexPubkey) {
+      toast.error('Failed to get the pubkey')
+      return null
+    }
+
+    const isAdmin =
+      userState.user?.npub &&
+      userState.user.npub === import.meta.env.VITE_REPORTING_NPUB
+
+    const handleBlock = async () => {
+      // Define the event filter to search for the user's mute list events.
+      // We look for events of a specific kind (Mutelist) authored by the given hexPubkey.
+      const filter: NDKFilter = {
+        kinds: [kinds.Mutelist],
+        authors: [hexPubkey]
+      }
+
+      // Fetch the mute list event from the relays. This returns the event containing the user's mute list.
+      const muteListEvent = await ndkContext.fetchEventFromUserRelays(
+        filter,
+        hexPubkey,
+        UserRelaysType.Write
+      )
+
+      let unsignedEvent: UnsignedEvent
+      if (muteListEvent) {
+        // get a list of tags
+        const tags = muteListEvent.tags
+        const alreadyExists =
+          tags.findIndex((item) => item[0] === 'a' && item[1] === aTag) !== -1
+
+        if (alreadyExists) {
+          toast.warn(`Mod reference is already in user's mute list`)
+          return null
+        }
+
+        tags.push(['a', aTag])
+
+        unsignedEvent = {
+          pubkey: muteListEvent.pubkey,
+          kind: kinds.Mutelist,
+          content: muteListEvent.content,
+          created_at: now(),
+          tags: [...tags]
+        }
+      } else {
+        unsignedEvent = {
+          pubkey: hexPubkey,
+          kind: kinds.Mutelist,
+          content: '',
+          created_at: now(),
+          tags: [['a', aTag]]
+        }
+      }
+
+      const isUpdated = await signAndPublish(
+        unsignedEvent,
+        ndkContext.ndk,
+        ndkContext.publish
+      )
+
+      if (!isUpdated) {
+        toast.error("Failed to update user's mute list")
+      }
+      return null
+    }
+
+    const handleUnblock = async () => {
+      const filter: NDKFilter = {
+        kinds: [kinds.Mutelist],
+        authors: [hexPubkey]
+      }
+      const muteListEvent = await ndkContext.fetchEventFromUserRelays(
+        filter,
+        hexPubkey,
+        UserRelaysType.Write
+      )
+      if (!muteListEvent) {
+        toast.error(`Couldn't get user's mute list event from relays`)
+        return null
+      }
+
+      const tags = muteListEvent.tags
+      const unsignedEvent: UnsignedEvent = {
+        pubkey: muteListEvent.pubkey,
+        kind: kinds.Mutelist,
+        content: muteListEvent.content,
+        created_at: now(),
+        tags: tags.filter((item) => item[0] !== 'a' || item[1] !== aTag)
+      }
+
+      const isUpdated = await signAndPublish(
+        unsignedEvent,
+        ndkContext.ndk,
+        ndkContext.publish
+      )
+      if (!isUpdated) {
+        toast.error("Failed to update user's mute list")
+      }
+      return null
+    }
+    const handleAddNSFW = async () => {
+      const success = await addToCurationSet(
+        {
+          dTag: CurationSetIdentifiers.NSFW,
+          pubkey: hexPubkey,
+          ndkContext
+        },
+        aTag
+      )
+      log(true, LogType.Info, `ModAction - NSFW - Add - ${success}`)
+      return null
+    }
+    const handleRemoveNSFW = async () => {
+      const success = await removeFromCurationSet(
+        {
+          dTag: CurationSetIdentifiers.NSFW,
+          pubkey: hexPubkey,
+          ndkContext
+        },
+        aTag
+      )
+      log(true, LogType.Info, `ModAction - Repost - Remove - ${success}`)
+      return null
+    }
+
+    const handleRepost = async () => {
+      const success = await addToCurationSet(
+        {
+          dTag: CurationSetIdentifiers.Repost,
+          pubkey: hexPubkey,
+          ndkContext
+        },
+        aTag
+      )
+      log(true, LogType.Info, `ModAction - NSFW - Add - ${success}`)
+      return null
+    }
+
+    const handleRemoveRepost = async () => {
+      const success = await removeFromCurationSet(
+        {
+          dTag: CurationSetIdentifiers.Repost,
+          pubkey: hexPubkey,
+          ndkContext
+        },
+        aTag
+      )
+      log(true, LogType.Info, `ModAction - Repost - Remove - ${success}`)
+      return null
+    }
+
+    const requestData = (await request.json()) as {
+      intent: 'nsfw' | 'block' | 'repost'
+      value: boolean
+    }
+
+    switch (requestData.intent) {
+      case 'block':
+        await (requestData.value ? handleBlock() : handleUnblock())
+        break
+
+      case 'repost':
+        await (requestData.value ? handleRepost() : handleRemoveRepost())
+        break
+
+      case 'nsfw':
+        if (!isAdmin) {
+          log(true, LogType.Error, 'Unable to update NSFW list. No permission')
+          return null
+        }
+        await (requestData.value ? handleAddNSFW() : handleRemoveNSFW())
+        break
+
+      default:
+        log(true, LogType.Error, 'Missing intent for mod action')
+        break
+    }
+
+    return null
+  }
diff --git a/src/pages/mod/index.tsx b/src/pages/mod/index.tsx
index bb36a1a..cc77765 100644
--- a/src/pages/mod/index.tsx
+++ b/src/pages/mod/index.tsx
@@ -1,22 +1,20 @@
-import { NDKFilter, NDKKind } from '@nostr-dev-kit/ndk'
 import Link from '@tiptap/extension-link'
 import { EditorContent, useEditor } from '@tiptap/react'
 import StarterKit from '@tiptap/starter-kit'
 import FsLightbox from 'fslightbox-react'
-import { kinds, nip19, UnsignedEvent } from 'nostr-tools'
-import { useEffect, useRef, useState } from 'react'
-import { Link as ReactRouterLink, useParams } from 'react-router-dom'
+import { nip19 } from 'nostr-tools'
+import { useRef, useState } from 'react'
+import {
+  Link as ReactRouterLink,
+  useLoaderData,
+  useNavigation,
+  useParams,
+  useSubmit
+} from 'react-router-dom'
 import { toast } from 'react-toastify'
 import { BlogCard } from '../../components/BlogCard'
-import { LoadingSpinner } from '../../components/LoadingSpinner'
 import { ProfileSection } from '../../components/ProfileSection'
-import {
-  useAppSelector,
-  useBodyScrollDisable,
-  useDidMount,
-  useNDKContext,
-  useNSFWList
-} from '../../hooks'
+import { useAppSelector, useBodyScrollDisable } from '../../hooks'
 import { getGamePageRoute, getModsEditPageRoute } from '../../routes'
 import '../../styles/comments.css'
 import '../../styles/downloads.css'
@@ -28,77 +26,47 @@ import '../../styles/styles.css'
 import '../../styles/tabs.css'
 import '../../styles/tags.css'
 import '../../styles/write.css'
-import {
-  BlogCardDetails,
-  DownloadUrl,
-  ModDetails,
-  UserRelaysType
-} from '../../types'
+import { DownloadUrl, ModPageLoaderResult } from '../../types'
 import {
   copyTextToClipboard,
   downloadFile,
-  extractModData,
-  getFilenameFromUrl,
-  log,
-  LogType,
-  now,
-  npubToHex,
-  sendDMUsingRandomKey,
-  signAndPublish
+  getFilenameFromUrl
 } from '../../utils'
 import { Comments } from '../../components/comment'
-import { CheckboxField } from 'components/Inputs'
 import { PublishDetails } from 'components/Internal/PublishDetails'
 import { Interactions } from 'components/Internal/Interactions'
-import { extractBlogCardDetails } from 'utils/blog'
+import { ReportPopup } from 'components/ReportPopup'
+import { Spinner } from 'components/Spinner'
+import { RouterLoadingSpinner } from 'components/LoadingSpinner'
+import { OriginalAuthor } from 'components/OriginalAuthor'
+
+const MOD_REPORT_REASONS = [
+  { label: 'Actually CP', key: 'actuallyCP' },
+  { label: 'Spam', key: 'spam' },
+  { label: 'Scam', key: 'scam' },
+  { label: 'Not a game mod', key: 'notAGameMod' },
+  { label: 'Stolen game mod', key: 'stolenGameMod' },
+  { label: `Repost of a game mod`, key: 'repost' },
+  { label: `Wasn't tagged NSFW`, key: 'wasntTaggedNSFW' },
+  { label: 'Other reason', key: 'otherReason' }
+]
 
 export const ModPage = () => {
+  const { mod } = useLoaderData() as ModPageLoaderResult
+
+  // We can get author right away from naddr, no need to wait for mod data
   const { naddr } = useParams()
-  const { fetchEvent } = useNDKContext()
-  const [mod, setMod] = useState<ModDetails>()
-  const [isFetching, setIsFetching] = useState(true)
-  const [commentCount, setCommentCount] = useState(0)
-
-  // Make sure to mark non-nsfw mods as NSFW if found in nsfwList
-  const nsfwList = useNSFWList()
-  const isMissingNsfwTag =
-    !mod?.nsfw && mod?.aTag && nsfwList && nsfwList.includes(mod.aTag)
-  const modData = isMissingNsfwTag
-    ? ({ ...mod, nsfw: true } as ModDetails)
-    : mod
-
-  useDidMount(async () => {
-    if (naddr) {
+  let author = mod?.author
+  if (naddr && !author) {
+    try {
       const decoded = nip19.decode<'naddr'>(naddr as `naddr1${string}`)
-      const { identifier, kind, pubkey } = decoded.data
-
-      const filter: NDKFilter = {
-        '#a': [identifier],
-        authors: [pubkey],
-        kinds: [kind]
-      }
-
-      fetchEvent(filter)
-        .then((event) => {
-          if (event) {
-            const extracted = extractModData(event)
-            setMod(extracted)
-          }
-        })
-        .catch((err) => {
-          log(
-            true,
-            LogType.Error,
-            'An error occurred in fetching mod details from relays',
-            err
-          )
-          toast.error('An error occurred in fetching mod details from relays')
-        })
-        .finally(() => {
-          setIsFetching(false)
-        })
+      author = decoded.data.pubkey
+    } catch (error) {
+      // Silently ignore - we will get author eventually from mods
     }
-  })
+  }
+
+  const [commentCount, setCommentCount] = useState(0)
 
   const oldDownloadListRef = useRef<HTMLDivElement>(null)
 
@@ -119,404 +87,172 @@ export const ModPage = () => {
     }
   }
 
-  if (isFetching)
-    return <LoadingSpinner desc='Fetching mod details from relays' />
-
-  if (!modData) return null
-
   return (
-    <div className='InnerBodyMain'>
-      <div className='ContainerMain'>
-        <div className='IBMSecMainGroup IBMSecMainGroupAlt'>
-          <div className='IBMSMSplitMain'>
-            <div className='IBMSMSplitMainBigSide'>
-              <div className='IBMSMSplitMainBigSideSec'>
-                <Game
-                  naddr={naddr!}
-                  game={modData.game}
-                  author={modData.author}
-                  aTag={modData.aTag}
-                />
-                <Body
-                  featuredImageUrl={modData.featuredImageUrl}
-                  title={modData.title}
-                  body={modData.body}
-                  screenshotsUrls={modData.screenshotsUrls}
-                  tags={modData.tags}
-                  nsfw={modData.nsfw}
-                />
-                <Interactions
-                  addressable={modData}
-                  commentCount={commentCount}
-                />
-                <PublishDetails
-                  published_at={modData.published_at}
-                  edited_at={modData.edited_at}
-                  site={modData.rTag}
-                />
-              </div>
-              <div className='IBMSMSplitMainBigSideSec'>
-                <div className='IBMSMSMBSSDownloadsWrapper'>
-                  <h4 className='IBMSMSMBSSDownloadsTitle'>Mod Download</h4>
-                  {modData.downloadUrls.length > 0 && (
-                    <div className='IBMSMSMBSSDownloadsPrime'>
-                      <Download {...modData.downloadUrls[0]} />
+    <>
+      <RouterLoadingSpinner />
+      <div className='InnerBodyMain'>
+        <div className='ContainerMain'>
+          <div className='IBMSecMainGroup IBMSecMainGroupAlt'>
+            <div className='IBMSMSplitMain'>
+              <div className='IBMSMSplitMainBigSide'>
+                {mod ? (
+                  <>
+                    <div className='IBMSMSplitMainBigSideSec'>
+                      <Game />
+                      <Body
+                        featuredImageUrl={mod.featuredImageUrl}
+                        title={mod.title}
+                        body={mod.body}
+                        screenshotsUrls={mod.screenshotsUrls}
+                        tags={mod.tags}
+                        nsfw={mod.nsfw}
+                        repost={mod.repost}
+                        originalAuthor={mod.originalAuthor}
+                      />
+                      <Interactions
+                        addressable={mod}
+                        commentCount={commentCount}
+                      />
+                      <PublishDetails
+                        published_at={mod.published_at}
+                        edited_at={mod.edited_at}
+                        site={mod.rTag}
+                      />
                     </div>
-                  )}
-                  {modData.downloadUrls.length > 1 && (
-                    <>
-                      <div className='IBMSMSMBSSDownloadsActions'>
-                        <button
-                          className='btn btnMain'
-                          id='viewOldLinks'
-                          type='button'
-                          onClick={handleViewOldLinks}
-                        >
-                          View other links
-                        </button>
+                    <div className='IBMSMSplitMainBigSideSec'>
+                      <div className='IBMSMSMBSSDownloadsWrapper'>
+                        <h4 className='IBMSMSMBSSDownloadsTitle'>
+                          Mod Download
+                        </h4>
+                        {mod.downloadUrls.length > 0 && (
+                          <div className='IBMSMSMBSSDownloadsPrime'>
+                            <Download {...mod.downloadUrls[0]} />
+                          </div>
+                        )}
+                        {mod.downloadUrls.length > 1 && (
+                          <>
+                            <div className='IBMSMSMBSSDownloadsActions'>
+                              <button
+                                className='btn btnMain'
+                                id='viewOldLinks'
+                                type='button'
+                                onClick={handleViewOldLinks}
+                              >
+                                View other links
+                              </button>
+                            </div>
+                            <div
+                              ref={oldDownloadListRef}
+                              id='oldDownloadList'
+                              className='IBMSMSMBSSDownloads'
+                              style={{
+                                padding: 0,
+                                height: '0px',
+                                border: 'unset'
+                              }}
+                            >
+                              {mod.downloadUrls
+                                .slice(1)
+                                .map((download, index) => (
+                                  <Download
+                                    key={`downloadUrl-${index}`}
+                                    {...download}
+                                  />
+                                ))}
+                            </div>
+                          </>
+                        )}
                       </div>
-                      <div
-                        ref={oldDownloadListRef}
-                        id='oldDownloadList'
-                        className='IBMSMSMBSSDownloads'
-                        style={{ padding: 0, height: '0px', border: 'unset' }}
-                      >
-                        {modData.downloadUrls
-                          .slice(1)
-                          .map((download, index) => (
-                            <Download
-                              key={`downloadUrl-${index}`}
-                              {...download}
-                            />
-                          ))}
-                      </div>
-                    </>
-                  )}
-                </div>
-              </div>
-              <DisplayModAuthorBlogs />
-              <div className='IBMSMSplitMainBigSideSec'>
-                <Comments
-                  addressable={modData}
-                  setCommentCount={setCommentCount}
-                />
+                    </div>
+                    <DisplayModAuthorBlogs />
+                    <div className='IBMSMSplitMainBigSideSec'>
+                      <Comments
+                        addressable={mod}
+                        setCommentCount={setCommentCount}
+                      />
+                    </div>
+                  </>
+                ) : (
+                  <Spinner />
+                )}
               </div>
+              {typeof author !== 'undefined' && (
+                <ProfileSection pubkey={author} />
+              )}
             </div>
-            <ProfileSection pubkey={modData.author} />
           </div>
         </div>
       </div>
-    </div>
+    </>
   )
 }
 
-type GameProps = {
-  naddr: string
-  game: string
-  author: string
-  aTag: string
-}
-
-const Game = ({ naddr, game, author, aTag }: GameProps) => {
-  const { ndk, fetchEventFromUserRelays, publish } = useNDKContext()
-
+const Game = () => {
+  const { naddr } = useParams()
+  const navigation = useNavigation()
+  const { mod, isAddedToNSFW, isBlocked, isRepost } =
+    useLoaderData() as ModPageLoaderResult
   const userState = useAppSelector((state) => state.user)
-  const [isLoading, setIsLoading] = useState(false)
-  const [loadingSpinnerDesc, setLoadingSpinnerDesc] = useState('')
-  const [showReportPopUp, setShowReportPopUp] = useState(false)
-  const [isBlocked, setIsBlocked] = useState(false)
-  const [isAddedToNSFW, setIsAddedToNSFW] = useState(false)
+  const [showReportPopUp, setShowReportPopUp] = useState<number | undefined>()
 
-  useBodyScrollDisable(showReportPopUp)
+  useBodyScrollDisable(!!showReportPopUp)
 
-  useEffect(() => {
-    if (userState.auth && userState.user?.pubkey) {
-      const pubkey = userState.user.pubkey as string
-
-      const muteListFilter: NDKFilter = {
-        kinds: [NDKKind.MuteList],
-        authors: [pubkey]
-      }
-
-      fetchEventFromUserRelays(
-        muteListFilter,
-        pubkey,
-        UserRelaysType.Write
-      ).then((event) => {
-        if (event) {
-          // get a list of tags
-          const tags = event.tags
-          const blocked =
-            tags.findIndex((item) => item[0] === 'a' && item[1] === aTag) !== -1
-
-          setIsBlocked(blocked)
+  const submit = useSubmit()
+  const handleBlock = () => {
+    if (navigation.state === 'idle') {
+      submit(
+        {
+          intent: 'block',
+          value: !isBlocked
+        },
+        {
+          method: 'post',
+          encType: 'application/json'
         }
-      })
+      )
+    }
+  }
 
-      if (
-        userState.user.npub &&
-        userState.user.npub === import.meta.env.VITE_REPORTING_NPUB
-      ) {
-        const nsfwListFilter: NDKFilter = {
-          kinds: [NDKKind.ArticleCurationSet],
-          authors: [pubkey],
-          '#d': ['nsfw']
+  const handleNSFW = () => {
+    if (navigation.state === 'idle') {
+      submit(
+        {
+          intent: 'nsfw',
+          value: !isAddedToNSFW
+        },
+        {
+          method: 'post',
+          encType: 'application/json'
         }
-
-        fetchEventFromUserRelays(
-          nsfwListFilter,
-          pubkey,
-          UserRelaysType.Write
-        ).then((event) => {
-          if (event) {
-            // get a list of tags
-            const tags = event.tags
-            const existsInNSFWList =
-              tags.findIndex((item) => item[0] === 'a' && item[1] === aTag) !==
-              -1
-
-            setIsAddedToNSFW(existsInNSFWList)
-          }
-        })
-      }
+      )
     }
-  }, [userState, aTag, fetchEventFromUserRelays])
-
-  const handleBlock = async () => {
-    let hexPubkey: string
-
-    setIsLoading(true)
-    setLoadingSpinnerDesc('Getting user pubkey')
-
-    if (userState.auth && userState.user?.pubkey) {
-      hexPubkey = userState.user.pubkey as string
-    } else {
-      hexPubkey = (await window.nostr?.getPublicKey()) as string
-    }
-
-    if (!hexPubkey) {
-      toast.error('Could not get pubkey for updating mute list')
-      setIsLoading(false)
-      return
-    }
-
-    setLoadingSpinnerDesc(`Finding user's mute list`)
-
-    // Define the event filter to search for the user's mute list events.
-    // We look for events of a specific kind (Mutelist) authored by the given hexPubkey.
-    const filter: NDKFilter = {
-      kinds: [NDKKind.MuteList],
-      authors: [hexPubkey]
-    }
-
-    // Fetch the mute list event from the relays. This returns the event containing the user's mute list.
-    const muteListEvent = await fetchEventFromUserRelays(
-      filter,
-      hexPubkey,
-      UserRelaysType.Write
-    )
-
-    let unsignedEvent: UnsignedEvent
-
-    if (muteListEvent) {
-      // get a list of tags
-      const tags = muteListEvent.tags
-      const alreadyExists =
-        tags.findIndex((item) => item[0] === 'a' && item[1] === aTag) !== -1
-
-      if (alreadyExists) {
-        setIsLoading(false)
-        setIsBlocked(true)
-        return toast.warn(`Mod reference is already in user's mute list`)
-      }
-
-      tags.push(['a', aTag])
-
-      unsignedEvent = {
-        pubkey: muteListEvent.pubkey,
-        kind: NDKKind.MuteList,
-        content: muteListEvent.content,
-        created_at: now(),
-        tags: [...tags]
-      }
-    } else {
-      unsignedEvent = {
-        pubkey: hexPubkey,
-        kind: NDKKind.MuteList,
-        content: '',
-        created_at: now(),
-        tags: [['a', aTag]]
-      }
-    }
-
-    setLoadingSpinnerDesc('Updating mute list event')
-
-    const isUpdated = await signAndPublish(unsignedEvent, ndk, publish)
-    if (isUpdated) {
-      setIsBlocked(true)
-    }
-    setIsLoading(false)
   }
 
-  const handleUnblock = async () => {
-    const pubkey = userState.user?.pubkey as string
-
-    const filter: NDKFilter = {
-      kinds: [NDKKind.MuteList],
-      authors: [pubkey]
+  const handleRepost = () => {
+    if (navigation.state === 'idle') {
+      submit(
+        {
+          intent: 'repost',
+          value: !isRepost
+        },
+        {
+          method: 'post',
+          encType: 'application/json'
+        }
+      )
     }
-
-    setIsLoading(true)
-    setLoadingSpinnerDesc(`Finding user's mute list`)
-
-    // Fetch the mute list event from the relays. This returns the event containing the user's mute list.
-    const muteListEvent = await fetchEventFromUserRelays(
-      filter,
-      pubkey,
-      UserRelaysType.Write
-    )
-
-    if (!muteListEvent) {
-      toast.error(`Couldn't get user's mute list event from relays`)
-      return
-    }
-
-    const tags = muteListEvent.tags
-
-    const unsignedEvent: UnsignedEvent = {
-      pubkey: muteListEvent.pubkey,
-      kind: NDKKind.MuteList,
-      content: muteListEvent.content,
-      created_at: now(),
-      tags: tags.filter((item) => item[0] !== 'a' || item[1] !== aTag)
-    }
-
-    setLoadingSpinnerDesc('Updating mute list event')
-    const isUpdated = await signAndPublish(unsignedEvent, ndk, publish)
-    if (isUpdated) {
-      setIsBlocked(false)
-    }
-
-    setIsLoading(false)
-  }
-
-  const handleBlockNSFW = async () => {
-    const pubkey = userState.user?.pubkey as string | undefined
-
-    if (!pubkey) return
-
-    const filter: NDKFilter = {
-      kinds: [NDKKind.ArticleCurationSet],
-      authors: [pubkey],
-      '#d': ['nsfw']
-    }
-
-    setIsLoading(true)
-    setLoadingSpinnerDesc('Finding NSFW list')
-
-    const nsfwListEvent = await fetchEventFromUserRelays(
-      filter,
-      pubkey,
-      UserRelaysType.Write
-    )
-
-    let unsignedEvent: UnsignedEvent
-
-    if (nsfwListEvent) {
-      // get a list of tags
-      const tags = nsfwListEvent.tags
-      const alreadyExists =
-        tags.findIndex((item) => item[0] === 'a' && item[1] === aTag) !== -1
-
-      if (alreadyExists) {
-        setIsLoading(false)
-        setIsAddedToNSFW(true)
-        return toast.warn(`Mod reference is already in user's nsfw list`)
-      }
-
-      tags.push(['a', aTag])
-
-      unsignedEvent = {
-        pubkey: nsfwListEvent.pubkey,
-        kind: NDKKind.ArticleCurationSet,
-        content: nsfwListEvent.content,
-        created_at: now(),
-        tags: [...tags]
-      }
-    } else {
-      unsignedEvent = {
-        pubkey: pubkey,
-        kind: NDKKind.ArticleCurationSet,
-        content: '',
-        created_at: now(),
-        tags: [
-          ['a', aTag],
-          ['d', 'nsfw']
-        ]
-      }
-    }
-
-    setLoadingSpinnerDesc('Updating nsfw list event')
-
-    const isUpdated = await signAndPublish(unsignedEvent, ndk, publish)
-    if (isUpdated) {
-      setIsAddedToNSFW(true)
-    }
-    setIsLoading(false)
-  }
-
-  const handleUnblockNSFW = async () => {
-    const pubkey = userState.user?.pubkey as string
-
-    const filter: NDKFilter = {
-      kinds: [NDKKind.ArticleCurationSet],
-      authors: [pubkey],
-      '#d': ['nsfw']
-    }
-
-    setIsLoading(true)
-    setLoadingSpinnerDesc('Finding NSFW list')
-
-    const nsfwListEvent = await fetchEventFromUserRelays(
-      filter,
-      pubkey,
-      UserRelaysType.Write
-    )
-
-    if (!nsfwListEvent) {
-      toast.error(`Couldn't get nsfw list event from relays`)
-      return
-    }
-
-    const tags = nsfwListEvent.tags
-
-    const unsignedEvent: UnsignedEvent = {
-      pubkey: nsfwListEvent.pubkey,
-      kind: NDKKind.ArticleCurationSet,
-      content: nsfwListEvent.content,
-      created_at: now(),
-      tags: tags.filter((item) => item[0] !== 'a' || item[1] !== aTag)
-    }
-
-    setLoadingSpinnerDesc('Updating nsfw list event')
-    const isUpdated = await signAndPublish(unsignedEvent, ndk, publish)
-    if (isUpdated) {
-      setIsAddedToNSFW(false)
-    }
-
-    setIsLoading(false)
   }
 
   const isAdmin =
     userState.user?.npub &&
     userState.user.npub === import.meta.env.VITE_REPORTING_NPUB
 
+  const game = mod?.game || ''
   const gameRoute = getGamePageRoute(game)
-  const editRoute = getModsEditPageRoute(naddr)
+  const editRoute = getModsEditPageRoute(naddr ? naddr : '')
 
   return (
     <>
-      {isLoading && <LoadingSpinner desc={loadingSpinnerDesc} />}
       <div className='IBMSMSMBSSModFor'>
         <p className='IBMSMSMBSSModForPara'>
           Mod for:&nbsp;
@@ -547,7 +283,7 @@ const Game = ({ naddr, game, author, aTag }: GameProps) => {
             </svg>
           </button>
           <div className={`dropdown-menu dropdown-menu-end dropdownMainMenu`}>
-            {userState.auth && userState.user?.pubkey === author && (
+            {userState.auth && userState.user?.pubkey === mod?.author && (
               <ReactRouterLink
                 className='dropdown-item dropdownMainMenuItem'
                 to={editRoute}
@@ -602,7 +338,9 @@ const Game = ({ naddr, game, author, aTag }: GameProps) => {
             <a
               className='dropdown-item dropdownMainMenuItem'
               id='reportPost'
-              onClick={() => setShowReportPopUp(true)}
+              onClick={() => {
+                setShowReportPopUp(Date.now())
+              }}
             >
               <svg
                 xmlns='http://www.w3.org/2000/svg'
@@ -618,7 +356,7 @@ const Game = ({ naddr, game, author, aTag }: GameProps) => {
             </a>
             <a
               className='dropdown-item dropdownMainMenuItem'
-              onClick={isBlocked ? handleUnblock : handleBlock}
+              onClick={handleBlock}
             >
               <svg
                 xmlns='http://www.w3.org/2000/svg'
@@ -633,233 +371,55 @@ const Game = ({ naddr, game, author, aTag }: GameProps) => {
               {isBlocked ? 'Unblock' : 'Block'} Post
             </a>
             {isAdmin && (
-              <a
-                className='dropdown-item dropdownMainMenuItem'
-                onClick={isAddedToNSFW ? handleUnblockNSFW : handleBlockNSFW}
-              >
-                <svg
-                  xmlns='http://www.w3.org/2000/svg'
-                  viewBox='-32 0 512 512'
-                  width='1em'
-                  height='1em'
-                  fill='currentColor'
-                  className='IBMSMSMSSS_Author_Top_Icon'
+              <>
+                <a
+                  className='dropdown-item dropdownMainMenuItem'
+                  onClick={handleNSFW}
                 >
-                  <path d='M323.5 51.25C302.8 70.5 284 90.75 267.4 111.1C240.1 73.62 206.2 35.5 168 0C69.75 91.12 0 210 0 281.6C0 408.9 100.2 512 224 512s224-103.1 224-230.4C448 228.4 396 118.5 323.5 51.25zM304.1 391.9C282.4 407 255.8 416 226.9 416c-72.13 0-130.9-47.73-130.9-125.2c0-38.63 24.24-72.64 65.13-83.3c10.14-2.656 19.94 4.78 19.94 15.27c0 6.941-4.469 13.16-11.16 15.19c-17.5 4.578-34.41 23.94-34.41 52.84c0 50.81 39.31 94.81 91.41 94.81c24.66 0 45.22-6.5 63.19-18.75c11.75-8 27.91 3.469 23.91 16.69C314.6 384.7 309.8 388.4 304.1 391.9z'></path>
-                </svg>
-                {isAddedToNSFW ? 'Un-mark' : 'Mark'} as NSFW
-              </a>
+                  <svg
+                    xmlns='http://www.w3.org/2000/svg'
+                    viewBox='-32 0 512 512'
+                    width='1em'
+                    height='1em'
+                    fill='currentColor'
+                    className='IBMSMSMSSS_Author_Top_Icon'
+                  >
+                    <path d='M323.5 51.25C302.8 70.5 284 90.75 267.4 111.1C240.1 73.62 206.2 35.5 168 0C69.75 91.12 0 210 0 281.6C0 408.9 100.2 512 224 512s224-103.1 224-230.4C448 228.4 396 118.5 323.5 51.25zM304.1 391.9C282.4 407 255.8 416 226.9 416c-72.13 0-130.9-47.73-130.9-125.2c0-38.63 24.24-72.64 65.13-83.3c10.14-2.656 19.94 4.78 19.94 15.27c0 6.941-4.469 13.16-11.16 15.19c-17.5 4.578-34.41 23.94-34.41 52.84c0 50.81 39.31 94.81 91.41 94.81c24.66 0 45.22-6.5 63.19-18.75c11.75-8 27.91 3.469 23.91 16.69C314.6 384.7 309.8 388.4 304.1 391.9z'></path>
+                  </svg>
+                  {isAddedToNSFW ? 'Un-mark' : 'Mark'} as NSFW
+                </a>
+                <a
+                  className='dropdown-item dropdownMainMenuItem'
+                  onClick={handleRepost}
+                >
+                  <svg
+                    xmlns='http://www.w3.org/2000/svg'
+                    viewBox='-32 0 512 512'
+                    width='1em'
+                    height='1em'
+                    fill='currentColor'
+                    className='IBMSMSMSSS_Author_Top_Icon'
+                  >
+                    <path d='M323.5 51.25C302.8 70.5 284 90.75 267.4 111.1C240.1 73.62 206.2 35.5 168 0C69.75 91.12 0 210 0 281.6C0 408.9 100.2 512 224 512s224-103.1 224-230.4C448 228.4 396 118.5 323.5 51.25zM304.1 391.9C282.4 407 255.8 416 226.9 416c-72.13 0-130.9-47.73-130.9-125.2c0-38.63 24.24-72.64 65.13-83.3c10.14-2.656 19.94 4.78 19.94 15.27c0 6.941-4.469 13.16-11.16 15.19c-17.5 4.578-34.41 23.94-34.41 52.84c0 50.81 39.31 94.81 91.41 94.81c24.66 0 45.22-6.5 63.19-18.75c11.75-8 27.91 3.469 23.91 16.69C314.6 384.7 309.8 388.4 304.1 391.9z'></path>
+                  </svg>
+                  {isRepost ? 'Un-mark' : 'Mark'} as Repost
+                </a>
+              </>
             )}
           </div>
         </div>
       </div>
-      {showReportPopUp && (
+      {!!showReportPopUp && (
         <ReportPopup
-          aTag={aTag}
-          handleClose={() => setShowReportPopUp(false)}
+          openedAt={showReportPopUp}
+          reasons={MOD_REPORT_REASONS}
+          handleClose={() => setShowReportPopUp(undefined)}
         />
       )}
     </>
   )
 }
 
-type ReportPopupProps = {
-  aTag: string
-  handleClose: () => void
-}
-
-const MOD_REPORT_REASONS = [
-  { label: 'Actually CP', key: 'actuallyCP' },
-  { label: 'Spam', key: 'spam' },
-  { label: 'Scam', key: 'scam' },
-  { label: 'Not a game mod', key: 'notAGameMod' },
-  { label: 'Stolen game mod', key: 'stolenGameMod' },
-  { label: `Wasn't tagged NSFW`, key: 'wasntTaggedNSFW' },
-  { label: 'Other reason', key: 'otherReason' }
-]
-
-const ReportPopup = ({ aTag, handleClose }: ReportPopupProps) => {
-  const { ndk, fetchEventFromUserRelays, publish } = useNDKContext()
-  const userState = useAppSelector((state) => state.user)
-  const [selectedOptions, setSelectedOptions] = useState(
-    MOD_REPORT_REASONS.reduce((acc: { [key: string]: boolean }, cur) => {
-      acc[cur.key] = false
-      return acc
-    }, {})
-  )
-  const [isLoading, setIsLoading] = useState(false)
-  const [loadingSpinnerDesc, setLoadingSpinnerDesc] = useState('')
-
-  const handleCheckboxChange = (option: keyof typeof selectedOptions) => {
-    setSelectedOptions((prevState) => ({
-      ...prevState,
-      [option]: !prevState[option]
-    }))
-  }
-
-  const handleSubmit = async () => {
-    const selectedOptionsCount = Object.values(selectedOptions).filter(
-      (isSelected) => isSelected
-    ).length
-
-    if (selectedOptionsCount === 0) {
-      toast.error('At least one option should be checked!')
-      return
-    }
-    let hexPubkey: string
-
-    setIsLoading(true)
-    setLoadingSpinnerDesc('Getting user pubkey')
-
-    if (userState.auth && userState.user?.pubkey) {
-      hexPubkey = userState.user.pubkey as string
-    } else {
-      hexPubkey = (await window.nostr?.getPublicKey()) as string
-    }
-
-    if (!hexPubkey) {
-      toast.error('Could not get pubkey for reporting mod!')
-      setIsLoading(false)
-      return
-    }
-
-    const reportingNpub = import.meta.env.VITE_REPORTING_NPUB
-    const reportingPubkey = npubToHex(reportingNpub)
-
-    if (reportingPubkey === hexPubkey) {
-      setLoadingSpinnerDesc(`Finding user's mute list`)
-      // Define the event filter to search for the user's mute list events.
-      // We look for events of a specific kind (Mutelist) authored by the given hexPubkey.
-      const filter: NDKFilter = {
-        kinds: [NDKKind.MuteList],
-        authors: [hexPubkey]
-      }
-
-      // Fetch the mute list event from the relays. This returns the event containing the user's mute list.
-      const muteListEvent = await fetchEventFromUserRelays(
-        filter,
-        hexPubkey,
-        UserRelaysType.Write
-      )
-
-      let unsignedEvent: UnsignedEvent
-
-      if (muteListEvent) {
-        // get a list of tags
-        const tags = muteListEvent.tags
-        const alreadyExists =
-          tags.findIndex((item) => item[0] === 'a' && item[1] === aTag) !== -1
-
-        if (alreadyExists) {
-          setIsLoading(false)
-          return toast.warn(`Mod reference is already in user's mute list`)
-        }
-
-        tags.push(['a', aTag])
-
-        unsignedEvent = {
-          pubkey: muteListEvent.pubkey,
-          kind: NDKKind.MuteList,
-          content: muteListEvent.content,
-          created_at: now(),
-          tags: [...tags]
-        }
-      } else {
-        unsignedEvent = {
-          pubkey: hexPubkey,
-          kind: NDKKind.MuteList,
-          content: '',
-          created_at: now(),
-          tags: [['a', aTag]]
-        }
-      }
-
-      setLoadingSpinnerDesc('Updating mute list event')
-      const isUpdated = await signAndPublish(unsignedEvent, ndk, publish)
-      if (isUpdated) handleClose()
-    } else {
-      const href = window.location.href
-      let message = `I'd like to report ${href} due to following reasons:\n`
-
-      Object.entries(selectedOptions).forEach(([key, value]) => {
-        if (value) {
-          message += `* ${key}\n`
-        }
-      })
-
-      setLoadingSpinnerDesc('Sending report')
-      const isSent = await sendDMUsingRandomKey(
-        message,
-        reportingPubkey!,
-        ndk,
-        publish
-      )
-      if (isSent) handleClose()
-    }
-    setIsLoading(false)
-  }
-
-  return (
-    <>
-      {isLoading && <LoadingSpinner desc={loadingSpinnerDesc} />}
-      <div className='popUpMain'>
-        <div className='ContainerMain'>
-          <div className='popUpMainCardWrapper'>
-            <div className='popUpMainCard popUpMainCardQR'>
-              <div className='popUpMainCardTop'>
-                <div className='popUpMainCardTopInfo'>
-                  <h3>Report Post</h3>
-                </div>
-                <div className='popUpMainCardTopClose' onClick={handleClose}>
-                  <svg
-                    xmlns='http://www.w3.org/2000/svg'
-                    viewBox='-96 0 512 512'
-                    width='1em'
-                    height='1em'
-                    fill='currentColor'
-                    style={{ zIndex: 1 }}
-                  >
-                    <path d='M310.6 361.4c12.5 12.5 12.5 32.75 0 45.25C304.4 412.9 296.2 416 288 416s-16.38-3.125-22.62-9.375L160 301.3L54.63 406.6C48.38 412.9 40.19 416 32 416S15.63 412.9 9.375 406.6c-12.5-12.5-12.5-32.75 0-45.25l105.4-105.4L9.375 150.6c-12.5-12.5-12.5-32.75 0-45.25s32.75-12.5 45.25 0L160 210.8l105.4-105.4c12.5-12.5 32.75-12.5 45.25 0s12.5 32.75 0 45.25l-105.4 105.4L310.6 361.4z'></path>
-                  </svg>
-                </div>
-              </div>
-              <div className='pUMCB_Zaps'>
-                <div className='pUMCB_ZapsInside'>
-                  <div className='inputLabelWrapperMain'>
-                    <label
-                      className='form-label labelMain'
-                      style={{ fontWeight: 'bold' }}
-                    >
-                      Why are you reporting this?
-                    </label>
-                    {MOD_REPORT_REASONS.map((r) => (
-                      <CheckboxField
-                        key={r.key}
-                        label={r.label}
-                        name={r.key}
-                        isChecked={selectedOptions[r.key]}
-                        handleChange={() => handleCheckboxChange(r.key)}
-                      />
-                    ))}
-                  </div>
-                  <button
-                    className='btn btnMain pUMCB_Report'
-                    type='button'
-                    style={{ width: '100%' }}
-                    onClick={handleSubmit}
-                  >
-                    Submit Report
-                  </button>
-                </div>
-              </div>
-            </div>
-          </div>
-        </div>
-      </div>
-    </>
-  )
-}
-
 type BodyProps = {
   featuredImageUrl: string
   title: string
@@ -867,6 +427,8 @@ type BodyProps = {
   screenshotsUrls: string[]
   tags: string[]
   nsfw: boolean
+  repost: boolean
+  originalAuthor?: string
 }
 
 const Body = ({
@@ -875,7 +437,9 @@ const Body = ({
   body,
   screenshotsUrls,
   tags,
-  nsfw
+  nsfw,
+  repost,
+  originalAuthor
 }: BodyProps) => {
   const postBodyRef = useRef<HTMLDivElement>(null)
   const viewFullPostBtnRef = useRef<HTMLDivElement>(null)
@@ -936,8 +500,8 @@ const Body = ({
               <img
                 className='IBMSMSMBSSShotsImg'
                 src={url}
-                alt={`ScreenShot-${index}`}
-                key={url}
+                alt=''
+                key={`ScreenShot-${index}`}
                 onClick={() => openLightBoxOnSlide(index + 1)}
               />
             ))}
@@ -949,6 +513,20 @@ const Body = ({
               </div>
             )}
 
+            {repost && (
+              <div className='IBMSMSMBSSTagsTag IBMSMSMBSSTagsTagRepost'>
+                <p>
+                  REPOST
+                  {originalAuthor && originalAuthor !== '' && (
+                    <>
+                      . Original Author:{' '}
+                      <OriginalAuthor value={originalAuthor} fallback={true} />
+                    </>
+                  )}
+                </p>
+              </div>
+            )}
+
             {tags.map((tag, index) => (
               <a className='IBMSMSMBSSTagsTag' href='#' key={`tag-${index}`}>
                 {tag}
@@ -1225,43 +803,16 @@ const Download = ({
 }
 
 const DisplayModAuthorBlogs = () => {
-  const { naddr } = useParams()
-  const [blogs, setBlogs] = useState<Partial<BlogCardDetails>[]>()
-  const { fetchEvents } = useNDKContext()
+  const { latest } = useLoaderData() as ModPageLoaderResult
 
-  useDidMount(() => {
-    const fetchBlogs = async () => {
-      try {
-        const decoded = nip19.decode<'naddr'>(naddr as `naddr1${string}`)
-        const { pubkey } = decoded.data
-        const latestBlogPosts = await fetchEvents({
-          authors: [pubkey],
-          kinds: [kinds.LongFormArticle],
-          limit: 3
-        })
-        setBlogs(latestBlogPosts.map(extractBlogCardDetails))
-      } catch (error) {
-        log(
-          true,
-          LogType.Error,
-          'An error occurred in fetching blog details from relays',
-          error
-        )
-        return null
-      }
-    }
-
-    fetchBlogs()
-  })
-
-  if (!blogs?.length) return null
+  if (!latest?.length) return null
 
   return (
     <div className='IBMSMSplitMainBigSideSec'>
       <div className='IBMSMSMBSSPostsWrapper'>
         <h4 className='IBMSMSMBSSPostsTitle'>Creator's Blog Posts</h4>
         <div className='IBMSMList IBMSMListAlt'>
-          {blogs?.map((b) => (
+          {latest?.map((b) => (
             <BlogCard key={b.id} {...b} />
           ))}
         </div>
diff --git a/src/pages/mod/loader.ts b/src/pages/mod/loader.ts
new file mode 100644
index 0000000..22476f1
--- /dev/null
+++ b/src/pages/mod/loader.ts
@@ -0,0 +1,253 @@
+import { NDKFilter } from '@nostr-dev-kit/ndk'
+import { PROFILE_BLOG_FILTER_LIMIT } from '../../constants'
+import { NDKContextType } from 'contexts/NDKContext'
+import { kinds, nip19 } from 'nostr-tools'
+import { LoaderFunctionArgs, redirect } from 'react-router-dom'
+import { appRoutes } from 'routes'
+import { store } from 'store'
+import {
+  FilterOptions,
+  ModeratedFilter,
+  ModPageLoaderResult,
+  NSFWFilter
+} from 'types'
+import {
+  CurationSetIdentifiers,
+  DEFAULT_FILTER_OPTIONS,
+  extractBlogCardDetails,
+  extractModData,
+  getLocalStorageItem,
+  getReportingSet,
+  log,
+  LogType
+} from 'utils'
+
+export const modRouteLoader =
+  (ndkContext: NDKContextType) =>
+  async ({ params }: LoaderFunctionArgs) => {
+    const { naddr } = params
+    if (!naddr) {
+      log(true, LogType.Error, 'Required naddr.')
+      return redirect(appRoutes.blogs)
+    }
+
+    // Decode from naddr
+    let pubkey: string | undefined
+    let identifier: string | undefined
+    let kind: number | undefined
+    try {
+      const decoded = nip19.decode<'naddr'>(naddr as `naddr1${string}`)
+      identifier = decoded.data.identifier
+      kind = decoded.data.kind
+      pubkey = decoded.data.pubkey
+    } catch (error) {
+      log(true, LogType.Error, `Failed to decode naddr: ${naddr}`, error)
+      throw new Error('Failed to fetch the blog. The address might be wrong')
+    }
+
+    const userState = store.getState().user
+    const loggedInUserPubkey = userState?.user?.pubkey as string | undefined
+
+    try {
+      // Set up the filters
+      // Main mod content
+      const modFilter: NDKFilter = {
+        '#a': [identifier],
+        authors: [pubkey],
+        kinds: [kind]
+      }
+
+      // Get the blog filter options for latest blogs
+      const filterOptions = JSON.parse(
+        getLocalStorageItem('filter-blog', DEFAULT_FILTER_OPTIONS)
+      ) as FilterOptions
+
+      // Fetch more in case the current blog is included in the latest and filters remove some
+      const latestFilter: NDKFilter = {
+        authors: [pubkey],
+        kinds: [kinds.LongFormArticle],
+        limit: PROFILE_BLOG_FILTER_LIMIT
+      }
+      // Add source filter
+      if (filterOptions.source === window.location.host) {
+        latestFilter['#r'] = [filterOptions.source]
+      }
+      // Filter by NSFW tag
+      // NSFWFilter.Only_NSFW -> fetch with content-warning label
+      // NSFWFilter.Show_NSFW -> filter not needed
+      // NSFWFilter.Hide_NSFW -> up the limit and filter after fetch
+      if (filterOptions.nsfw === NSFWFilter.Only_NSFW) {
+        latestFilter['#L'] = ['content-warning']
+      }
+
+      // Parallel fetch blog event, latest events, mute, and nsfw lists
+      const settled = await Promise.allSettled([
+        ndkContext.fetchEvent(modFilter),
+        ndkContext.fetchEvents(latestFilter),
+        ndkContext.getMuteLists(loggedInUserPubkey), // Pass pubkey for logged-in users
+        getReportingSet(CurationSetIdentifiers.NSFW, ndkContext),
+        getReportingSet(CurationSetIdentifiers.Repost, ndkContext)
+      ])
+
+      const result: ModPageLoaderResult = {
+        mod: undefined,
+        latest: [],
+        isAddedToNSFW: false,
+        isBlocked: false,
+        isRepost: false
+      }
+
+      // Check the mod event result
+      const fetchEventResult = settled[0]
+      if (fetchEventResult.status === 'fulfilled' && fetchEventResult.value) {
+        // Extract the mod data from the event
+        result.mod = extractModData(fetchEventResult.value)
+      } else if (fetchEventResult.status === 'rejected') {
+        log(
+          true,
+          LogType.Error,
+          'Unable to fetch the blog event.',
+          fetchEventResult.reason
+        )
+      }
+
+      // Throw an error if we are missing the main mod result
+      // Handle it with the react-router's errorComponent
+      if (!result.mod) {
+        throw new Error('We are unable to find the mod on the relays')
+      }
+
+      // Check the lateast blog events
+      const fetchEventsResult = settled[1]
+      if (fetchEventsResult.status === 'fulfilled' && fetchEventsResult.value) {
+        // Extract the blog card details from the events
+        result.latest = fetchEventsResult.value.map(extractBlogCardDetails)
+      } else if (fetchEventsResult.status === 'rejected') {
+        log(
+          true,
+          LogType.Error,
+          'Unable to fetch the latest blog events.',
+          fetchEventsResult.reason
+        )
+      }
+
+      const muteLists = settled[2]
+      if (muteLists.status === 'fulfilled' && muteLists.value) {
+        if (muteLists && muteLists.value) {
+          if (result.mod && result.mod.aTag) {
+            if (
+              muteLists.value.admin.replaceableEvents.includes(
+                result.mod.aTag
+              ) ||
+              muteLists.value.user.replaceableEvents.includes(result.mod.aTag)
+            ) {
+              result.isBlocked = true
+            }
+          }
+
+          // Moderate the latest
+          const isAdmin =
+            userState.user?.npub === import.meta.env.VITE_REPORTING_NPUB
+          const isOwner =
+            userState.user?.pubkey && userState.user.pubkey === pubkey
+          const isUnmoderatedFully =
+            filterOptions.moderated === ModeratedFilter.Unmoderated_Fully
+
+          // Only apply filtering if the user is not an admin or the admin has not selected "Unmoderated Fully"
+          // Allow "Unmoderated Fully" when author visits own profile
+          if (!((isAdmin || isOwner) && isUnmoderatedFully)) {
+            result.latest = result.latest.filter(
+              (b) =>
+                !muteLists.value.admin.authors.includes(b.author!) &&
+                !muteLists.value.admin.replaceableEvents.includes(b.aTag!)
+            )
+          }
+
+          if (filterOptions.moderated === ModeratedFilter.Moderated) {
+            result.latest = result.latest.filter(
+              (b) =>
+                !muteLists.value.user.authors.includes(b.author!) &&
+                !muteLists.value.user.replaceableEvents.includes(b.aTag!)
+            )
+          }
+        }
+      } else if (muteLists.status === 'rejected') {
+        log(true, LogType.Error, 'Issue fetching mute list', muteLists.reason)
+      }
+
+      const nsfwList = settled[3]
+      if (nsfwList.status === 'fulfilled' && nsfwList.value) {
+        // Check if the mod is marked as NSFW
+        // Mark it as NSFW only if it's missing the tag
+        if (result.mod) {
+          const isMissingNsfwTag =
+            !result.mod.nsfw &&
+            result.mod.aTag &&
+            nsfwList.value.includes(result.mod.aTag)
+
+          if (isMissingNsfwTag) {
+            result.mod.nsfw = true
+          }
+
+          if (result.mod.aTag && nsfwList.value.includes(result.mod.aTag)) {
+            result.isAddedToNSFW = true
+          }
+        }
+        // Check the latest blogs too
+        result.latest = result.latest.map((b) => {
+          // Add nsfw tag if it's missing
+          const isMissingNsfwTag =
+            !b.nsfw && b.aTag && nsfwList.value.includes(b.aTag)
+
+          if (isMissingNsfwTag) {
+            b.nsfw = true
+          }
+          return b
+        })
+      } else if (nsfwList.status === 'rejected') {
+        log(true, LogType.Error, 'Issue fetching nsfw list', nsfwList.reason)
+      }
+
+      const repostList = settled[4]
+      if (repostList.status === 'fulfilled' && repostList.value) {
+        // Check if the mod is marked as Repost
+        // Mark it as Repost only if it's missing the tag
+        if (result.mod) {
+          const isMissingRepostTag =
+            !result.mod.repost &&
+            result.mod.aTag &&
+            repostList.value.includes(result.mod.aTag)
+
+          if (isMissingRepostTag) {
+            result.mod.repost = true
+          }
+
+          if (result.mod.aTag && repostList.value.includes(result.mod.aTag)) {
+            result.isRepost = true
+          }
+        }
+      } else if (repostList.status === 'rejected') {
+        log(true, LogType.Error, 'Issue fetching nsfw list', repostList.reason)
+      }
+
+      // Filter latest, sort and take only three
+      result.latest = result.latest
+        .filter(
+          // Filter out the NSFW if selected
+          (b) => !(b.nsfw && filterOptions.nsfw === NSFWFilter.Hide_NSFW)
+        )
+        .sort((a, b) =>
+          a.published_at && b.published_at ? b.published_at - a.published_at : 0
+        )
+        .slice(0, 3)
+
+      return result
+    } catch (error) {
+      let message = 'An error occurred in fetching mod details from relays'
+      log(true, LogType.Error, message, error)
+      if (error instanceof Error) {
+        message = error.message
+        throw new Error(message)
+      }
+    }
+  }
diff --git a/src/pages/mods.tsx b/src/pages/mods/index.tsx
similarity index 83%
rename from src/pages/mods.tsx
rename to src/pages/mods/index.tsx
index 31dd301..abd9870 100644
--- a/src/pages/mods.tsx
+++ b/src/pages/mods/index.tsx
@@ -1,29 +1,34 @@
-import { ModFilter } from 'components/ModsFilter'
+import { ModFilter } from 'components/Filters/ModsFilter'
 import { Pagination } from 'components/Pagination'
 import React, { useCallback, useEffect, useRef, useState } from 'react'
-import { createSearchParams, useNavigate } from 'react-router-dom'
-import { LoadingSpinner } from '../components/LoadingSpinner'
-import { ModCard } from '../components/ModCard'
-import { MOD_FILTER_LIMIT } from '../constants'
+import {
+  createSearchParams,
+  useLoaderData,
+  useNavigate
+} from 'react-router-dom'
+import { LoadingSpinner } from '../../components/LoadingSpinner'
+import { ModCard } from '../../components/ModCard'
+import { MOD_FILTER_LIMIT } from '../../constants'
 import {
   useAppSelector,
   useFilteredMods,
   useLocalStorage,
-  useMuteLists,
-  useNDKContext,
-  useNSFWList
-} from '../hooks'
-import { appRoutes } from '../routes'
-import '../styles/filters.css'
-import '../styles/pagination.css'
-import '../styles/search.css'
-import '../styles/styles.css'
-import { FilterOptions, ModDetails } from '../types'
+  useNDKContext
+} from '../../hooks'
+import { appRoutes } from '../../routes'
+import '../../styles/filters.css'
+import '../../styles/pagination.css'
+import '../../styles/search.css'
+import '../../styles/styles.css'
+import { FilterOptions, ModDetails } from '../../types'
 import { DEFAULT_FILTER_OPTIONS, scrollIntoView } from 'utils'
 import { SearchInput } from 'components/SearchInput'
+import { ModsPageLoaderResult } from './loader'
 
 export const ModsPage = () => {
   const scrollTargetRef = useRef<HTMLDivElement>(null)
+  const { repostList, muteLists, nsfwList } =
+    useLoaderData() as ModsPageLoaderResult
   const { fetchMods } = useNDKContext()
   const [isFetching, setIsFetching] = useState(false)
   const [mods, setMods] = useState<ModDetails[]>([])
@@ -32,8 +37,6 @@ export const ModsPage = () => {
     'filter',
     DEFAULT_FILTER_OPTIONS
   )
-  const muteLists = useMuteLists()
-  const nsfwList = useNSFWList()
 
   const [page, setPage] = useState(1)
 
@@ -94,7 +97,8 @@ export const ModsPage = () => {
     userState,
     filterOptions,
     nsfwList,
-    muteLists
+    muteLists,
+    repostList
   )
 
   return (
diff --git a/src/pages/mods/loader.ts b/src/pages/mods/loader.ts
new file mode 100644
index 0000000..24fc3a4
--- /dev/null
+++ b/src/pages/mods/loader.ts
@@ -0,0 +1,77 @@
+import { NDKContextType } from 'contexts/NDKContext'
+import { store } from 'store'
+import { MuteLists } from 'types'
+import { getReportingSet, CurationSetIdentifiers, log, LogType } from 'utils'
+
+export interface ModsPageLoaderResult {
+  muteLists: {
+    admin: MuteLists
+    user: MuteLists
+  }
+  nsfwList: string[]
+  repostList: string[]
+}
+
+export const modsRouteLoader = (ndkContext: NDKContextType) => async () => {
+  // Empty result
+  const result: ModsPageLoaderResult = {
+    muteLists: {
+      admin: {
+        authors: [],
+        replaceableEvents: []
+      },
+      user: {
+        authors: [],
+        replaceableEvents: []
+      }
+    },
+    nsfwList: [],
+    repostList: []
+  }
+
+  // Get the current state
+  const userState = store.getState().user
+
+  // Check if current user is logged in
+  let userPubkey: string | undefined
+  if (userState.auth && userState.user?.pubkey) {
+    userPubkey = userState.user.pubkey as string
+  }
+
+  const settled = await Promise.allSettled([
+    ndkContext.getMuteLists(userPubkey),
+    getReportingSet(CurationSetIdentifiers.NSFW, ndkContext),
+    getReportingSet(CurationSetIdentifiers.Repost, ndkContext)
+  ])
+
+  // Check the mutelist event result
+  const muteListResult = settled[0]
+  if (muteListResult.status === 'fulfilled' && muteListResult.value) {
+    result.muteLists = muteListResult.value
+  } else if (muteListResult.status === 'rejected') {
+    log(true, LogType.Error, 'Failed to fetch mutelist.', muteListResult.reason)
+  }
+
+  // Check the nsfwlist event result
+  const nsfwListResult = settled[1]
+  if (nsfwListResult.status === 'fulfilled' && nsfwListResult.value) {
+    result.nsfwList = nsfwListResult.value
+  } else if (nsfwListResult.status === 'rejected') {
+    log(true, LogType.Error, 'Failed to fetch nsfwlist.', nsfwListResult.reason)
+  }
+
+  // Check the repostlist event result
+  const repostListResult = settled[2]
+  if (repostListResult.status === 'fulfilled' && repostListResult.value) {
+    result.repostList = repostListResult.value
+  } else if (repostListResult.status === 'rejected') {
+    log(
+      true,
+      LogType.Error,
+      'Failed to fetch repost list.',
+      repostListResult.reason
+    )
+  }
+
+  return result
+}
diff --git a/src/pages/profile/index.tsx b/src/pages/profile/index.tsx
index 56758a6..3761a5b 100644
--- a/src/pages/profile/index.tsx
+++ b/src/pages/profile/index.tsx
@@ -1,7 +1,7 @@
 import { NDKFilter, NDKKind } from '@nostr-dev-kit/ndk'
 import { LoadingSpinner } from 'components/LoadingSpinner'
 import { ModCard } from 'components/ModCard'
-import { ModFilter } from 'components/ModsFilter'
+import { ModFilter } from 'components/Filters/ModsFilter'
 import { Pagination } from 'components/Pagination'
 import { ProfileSection } from 'components/ProfileSection'
 import { Tabs } from 'components/Tabs'
@@ -10,9 +10,7 @@ import {
   useAppSelector,
   useFilteredMods,
   useLocalStorage,
-  useMuteLists,
-  useNDKContext,
-  useNSFWList
+  useNDKContext
 } from 'hooks'
 import { kinds, UnsignedEvent } from 'nostr-tools'
 import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
@@ -41,13 +39,17 @@ import {
 import { CheckboxField } from 'components/Inputs'
 import { ProfilePageLoaderResult } from './loader'
 import { BlogCard } from 'components/BlogCard'
+import { BlogsFilter } from 'components/Filters/BlogsFilter'
 
 export const ProfilePage = () => {
   const {
     profilePubkey,
     profile,
     isBlocked: _isBlocked,
-    isOwnProfile
+    isOwnProfile,
+    repostList,
+    muteLists,
+    nsfwList
   } = useLoaderData() as ProfilePageLoaderResult
   const scrollTargetRef = useRef<HTMLDivElement>(null)
   const { ndk, publish, fetchEventFromUserRelays, fetchMods } = useNDKContext()
@@ -200,8 +202,6 @@ export const ProfilePage = () => {
   const [filterOptions] = useLocalStorage<FilterOptions>(filterKey, {
     ...DEFAULT_FILTER_OPTIONS
   })
-  const muteLists = useMuteLists()
-  const nsfwList = useNSFWList()
 
   const handleNext = useCallback(() => {
     setIsLoading(true)
@@ -263,12 +263,14 @@ export const ProfilePage = () => {
         break
     }
   }, [filterOptions.source, tab, fetchMods, profilePubkey])
+
   const filteredModList = useFilteredMods(
     mods,
     userState,
     filterOptions,
     nsfwList,
     muteLists,
+    repostList,
     profilePubkey
   )
 
@@ -824,7 +826,10 @@ const ProfileTabBlogs = () => {
         <LoadingSpinner desc={'Loading...'} />
       )}
 
-      <ModFilter filterKey={'filter-blog'} author={profile?.pubkey as string} />
+      <BlogsFilter
+        filterKey={'filter-blog'}
+        author={profile?.pubkey as string}
+      />
 
       <div className='IBMSMList IBMSMListAlt'>
         {moderatedAndSortedBlogs.map((b) => (
diff --git a/src/pages/profile/loader.ts b/src/pages/profile/loader.ts
index f3ac4c0..f5bc1b6 100644
--- a/src/pages/profile/loader.ts
+++ b/src/pages/profile/loader.ts
@@ -4,7 +4,13 @@ import { LoaderFunctionArgs, redirect } from 'react-router-dom'
 import { appRoutes, getProfilePageRoute } from 'routes'
 import { store } from 'store'
 import { MuteLists, UserProfile } from 'types'
-import { log, LogType, npubToHex } from 'utils'
+import {
+  CurationSetIdentifiers,
+  getReportingSet,
+  log,
+  LogType,
+  npubToHex
+} from 'utils'
 
 export interface ProfilePageLoaderResult {
   profilePubkey: string
@@ -16,6 +22,7 @@ export interface ProfilePageLoaderResult {
     user: MuteLists
   }
   nsfwList: string[]
+  repostList: string[]
 }
 
 export const profileRouteLoader =
@@ -87,7 +94,8 @@ export const profileRouteLoader =
           replaceableEvents: []
         }
       },
-      nsfwList: []
+      nsfwList: [],
+      repostList: []
     }
 
     // Check if user the user is logged in
@@ -98,7 +106,8 @@ export const profileRouteLoader =
     const settled = await Promise.allSettled([
       ndkContext.findMetadata(profilePubkey),
       ndkContext.getMuteLists(userPubkey),
-      ndkContext.getNSFWList()
+      getReportingSet(CurationSetIdentifiers.NSFW, ndkContext),
+      getReportingSet(CurationSetIdentifiers.Repost, ndkContext)
     ])
 
     // Check the profile event result
@@ -114,7 +123,7 @@ export const profileRouteLoader =
       )
     }
 
-    // Check the profile event result
+    // Check the mutelist event result
     const muteListResult = settled[1]
     if (muteListResult.status === 'fulfilled' && muteListResult.value) {
       result.muteLists = muteListResult.value
@@ -130,7 +139,7 @@ export const profileRouteLoader =
       )
     }
 
-    // Check the profile event result
+    // Check the nsfwlist event result
     const nsfwListResult = settled[2]
     if (nsfwListResult.status === 'fulfilled' && nsfwListResult.value) {
       result.nsfwList = nsfwListResult.value
@@ -138,10 +147,23 @@ export const profileRouteLoader =
       log(
         true,
         LogType.Error,
-        'Failed to fetch mutelist.',
+        'Failed to fetch nsfwlist.',
         nsfwListResult.reason
       )
     }
 
+    // Check the repostlist event result
+    const repostListResult = settled[3]
+    if (repostListResult.status === 'fulfilled' && repostListResult.value) {
+      result.repostList = repostListResult.value
+    } else if (repostListResult.status === 'rejected') {
+      log(
+        true,
+        LogType.Error,
+        'Failed to fetch repost list.',
+        repostListResult.reason
+      )
+    }
+
     return result
   }
diff --git a/src/pages/search.tsx b/src/pages/search.tsx
index f94be8f..683696f 100644
--- a/src/pages/search.tsx
+++ b/src/pages/search.tsx
@@ -10,7 +10,7 @@ import {
 import { ErrorBoundary } from 'components/ErrorBoundary'
 import { GameCard } from 'components/GameCard'
 import { ModCard } from 'components/ModCard'
-import { ModFilter } from 'components/ModsFilter'
+import { ModFilter } from 'components/Filters/ModsFilter'
 import { Pagination } from 'components/Pagination'
 import { Profile } from 'components/ProfileSection'
 import { SearchInput } from 'components/SearchInput'
@@ -32,11 +32,13 @@ import React, { useEffect, useMemo, useRef, useState } from 'react'
 import { useSearchParams } from 'react-router-dom'
 import { FilterOptions, ModDetails, ModeratedFilter, MuteLists } from 'types'
 import {
+  CurationSetIdentifiers,
   DEFAULT_FILTER_OPTIONS,
   extractModData,
   isModDataComplete,
   scrollIntoView
 } from 'utils'
+import { useCuratedSet } from 'hooks/useCuratedSet'
 
 enum SearchKindEnum {
   Mods = 'Mods',
@@ -50,6 +52,7 @@ export const SearchPage = () => {
 
   const muteLists = useMuteLists()
   const nsfwList = useNSFWList()
+  const repostList = useCuratedSet(CurationSetIdentifiers.Repost)
   const searchTermRef = useRef<HTMLInputElement>(null)
 
   const searchKind =
@@ -115,6 +118,7 @@ export const SearchPage = () => {
               filterOptions={filterOptions}
               muteLists={muteLists}
               nsfwList={nsfwList}
+              repostList={repostList}
               el={scrollTargetRef.current}
             />
           )}
@@ -233,6 +237,7 @@ type ModsResultProps = {
     user: MuteLists
   }
   nsfwList: string[]
+  repostList: string[]
   el: HTMLElement | null
 }
 
@@ -241,6 +246,7 @@ const ModsResult = ({
   searchTerm,
   muteLists,
   nsfwList,
+  repostList,
   el
 }: ModsResultProps) => {
   const { ndk } = useNDKContext()
@@ -313,7 +319,8 @@ const ModsResult = ({
     userState,
     filterOptions,
     nsfwList,
-    muteLists
+    muteLists,
+    repostList
   )
 
   const handleNext = () => {
diff --git a/src/pages/write/action.tsx b/src/pages/write/action.ts
similarity index 100%
rename from src/pages/write/action.tsx
rename to src/pages/write/action.ts
diff --git a/src/routes/index.tsx b/src/routes/index.tsx
index aec86c6..ffa0bef 100644
--- a/src/routes/index.tsx
+++ b/src/routes/index.tsx
@@ -5,12 +5,15 @@ import { SearchPage } from '../pages/search'
 import { AboutPage } from '../pages/about'
 import { GamesPage } from '../pages/games'
 import { HomePage } from '../pages/home'
-import { ModPage } from '../pages/mod'
 import { ModsPage } from '../pages/mods'
+import { ModPage } from '../pages/mod'
+import { modsRouteLoader } from '../pages/mods/loader'
+import { modRouteLoader } from '../pages/mod/loader'
+import { modRouteAction } from '../pages/mod/action'
+import { SubmitModPage } from '../pages/submitMod'
 import { ProfilePage } from '../pages/profile'
 import { profileRouteLoader } from 'pages/profile/loader'
 import { SettingsPage } from '../pages/settings'
-import { SubmitModPage } from '../pages/submitMod'
 import { GamePage } from '../pages/game'
 import { NotFoundPage } from '../pages/404'
 import { FeedLayout } from '../layout/feed'
@@ -18,12 +21,12 @@ import { FeedPage } from '../pages/feed'
 import { NotificationsPage } from '../pages/notifications'
 import { WritePage } from '../pages/write'
 import { writeRouteAction } from '../pages/write/action'
-import { BlogsPage } from 'pages/blogs'
-import { blogsRouteLoader } from 'pages/blogs/loader'
-import { BlogPage } from 'pages/blog'
-import { blogRouteLoader } from 'pages/blog/loader'
-import { blogRouteAction } from 'pages/blog/action'
-import { blogReportRouteAction } from 'pages/blog/reportAction'
+import { BlogsPage } from '../pages/blogs'
+import { blogsRouteLoader } from '../pages/blogs/loader'
+import { BlogPage } from '../pages/blog'
+import { blogRouteLoader } from '../pages/blog/loader'
+import { blogRouteAction } from '../pages/blog/action'
+import { reportRouteAction } from '../actions/report'
 
 export const appRoutes = {
   index: '/',
@@ -32,6 +35,7 @@ export const appRoutes = {
   game: '/game/:name',
   mods: '/mods',
   mod: '/mod/:naddr',
+  modReport_actionOnly: '/mod/:naddr/report',
   about: '/about',
   blogs: '/blog',
   blog: '/blog/:naddr',
@@ -84,11 +88,19 @@ export const routerWithNdkContext = (context: NDKContextType) =>
         },
         {
           path: appRoutes.mods,
-          element: <ModsPage />
+          element: <ModsPage />,
+          loader: modsRouteLoader(context)
         },
         {
           path: appRoutes.mod,
-          element: <ModPage />
+          element: <ModPage />,
+          loader: modRouteLoader(context),
+          action: modRouteAction(context),
+          errorElement: <NotFoundPage title={'Something went wrong.'} />
+        },
+        {
+          path: appRoutes.modReport_actionOnly,
+          action: reportRouteAction(context)
         },
         {
           path: appRoutes.about,
@@ -115,7 +127,7 @@ export const routerWithNdkContext = (context: NDKContextType) =>
         },
         {
           path: appRoutes.blogReport_actionOnly,
-          action: blogReportRouteAction(context)
+          action: reportRouteAction(context)
         },
         {
           path: appRoutes.submitMod,
diff --git a/src/types/blog.ts b/src/types/blog.ts
index 7b76549..075a63c 100644
--- a/src/types/blog.ts
+++ b/src/types/blog.ts
@@ -1,3 +1,5 @@
+import { SortBy, NSFWFilter, ModeratedFilter } from './modsFilter'
+
 export interface BlogForm {
   title: string
   content: string
@@ -40,3 +42,10 @@ export interface BlogPageLoaderResult {
   isAddedToNSFW: boolean
   isBlocked: boolean
 }
+
+export interface BlogsFilterOptions {
+  sort: SortBy
+  nsfw: NSFWFilter
+  source: string
+  moderated: ModeratedFilter
+}
diff --git a/src/types/mod.ts b/src/types/mod.ts
index c9d14f8..bc27e18 100644
--- a/src/types/mod.ts
+++ b/src/types/mod.ts
@@ -1,4 +1,5 @@
 import { Event } from 'nostr-tools'
+import { BlogDetails } from 'types'
 
 export enum CommentEventStatus {
   Publishing = 'Publishing comment...',
@@ -26,6 +27,8 @@ export interface ModFormState {
   featuredImageUrl: string
   summary: string
   nsfw: boolean
+  repost: boolean
+  originalAuthor?: string
   screenshotsUrls: string[]
   tags: string
   downloadUrls: DownloadUrl[]
@@ -52,3 +55,11 @@ export interface MuteLists {
   authors: string[]
   replaceableEvents: string[]
 }
+
+export interface ModPageLoaderResult {
+  mod: ModDetails | undefined
+  latest: Partial<BlogDetails>[]
+  isAddedToNSFW: boolean
+  isBlocked: boolean
+  isRepost: boolean
+}
diff --git a/src/types/modsFilter.ts b/src/types/modsFilter.ts
index b0ae63b..6310f1d 100644
--- a/src/types/modsFilter.ts
+++ b/src/types/modsFilter.ts
@@ -25,10 +25,17 @@ export enum WOTFilterOptions {
   Exclude = 'Exclude'
 }
 
+export enum RepostFilter {
+  Hide_Repost = 'Hide Repost',
+  Show_Repost = 'Show Repost',
+  Only_Repost = 'Only Repost'
+}
+
 export interface FilterOptions {
   sort: SortBy
   nsfw: NSFWFilter
   source: string
   moderated: ModeratedFilter
   wot: WOTFilterOptions
+  repost: RepostFilter
 }
diff --git a/src/types/report.ts b/src/types/report.ts
new file mode 100644
index 0000000..907cbe9
--- /dev/null
+++ b/src/types/report.ts
@@ -0,0 +1,4 @@
+export interface ReportReason {
+  label: string
+  key: string
+}
diff --git a/src/utils/consts.ts b/src/utils/consts.ts
index 611a3a8..38da842 100644
--- a/src/utils/consts.ts
+++ b/src/utils/consts.ts
@@ -3,7 +3,8 @@ import {
   SortBy,
   NSFWFilter,
   ModeratedFilter,
-  WOTFilterOptions
+  WOTFilterOptions,
+  RepostFilter
 } from 'types'
 
 export const DEFAULT_FILTER_OPTIONS: FilterOptions = {
@@ -11,5 +12,6 @@ export const DEFAULT_FILTER_OPTIONS: FilterOptions = {
   nsfw: NSFWFilter.Hide_NSFW,
   source: window.location.host,
   moderated: ModeratedFilter.Moderated,
-  wot: WOTFilterOptions.Site_Only
+  wot: WOTFilterOptions.Site_Only,
+  repost: RepostFilter.Show_Repost
 }
diff --git a/src/utils/curationSets.ts b/src/utils/curationSets.ts
new file mode 100644
index 0000000..e117789
--- /dev/null
+++ b/src/utils/curationSets.ts
@@ -0,0 +1,187 @@
+import { NDKFilter, NDKList } from '@nostr-dev-kit/ndk'
+import { NDKContextType } from 'contexts/NDKContext'
+import { UnsignedEvent, kinds } from 'nostr-tools'
+import { toast } from 'react-toastify'
+import { UserRelaysType } from 'types'
+import { now, npubToHex, signAndPublish } from './nostr'
+
+interface CurationSetArgs {
+  dTag: CurationSetIdentifiers
+  pubkey: string
+  ndkContext: NDKContextType
+}
+
+/**
+ * Used for dTag when updating
+ */
+export enum CurationSetIdentifiers {
+  NSFW = 'nsfw',
+  Repost = 'repost'
+}
+
+/**
+ * Create the article curation set (kind: 30004) for the user (pubkey)
+ * with initial article (optional)
+ * @see https://github.com/nostr-protocol/nips/blob/master/51.md#sets
+ */
+export async function createCurationSet(
+  { dTag, pubkey, ndkContext }: CurationSetArgs,
+  initialArticle?: string
+) {
+  const curationSetName = `${dTag} - Degmods's curation set`
+  const tags = [
+    ['d', dTag],
+    ['title', curationSetName]
+  ]
+  if (initialArticle) {
+    tags.push(['a', initialArticle])
+  }
+  const unsignedEvent: UnsignedEvent = {
+    pubkey: pubkey,
+    kind: kinds.Curationsets,
+    content: '',
+    created_at: now(),
+    tags
+  }
+  const isUpdated = await signAndPublish(
+    unsignedEvent,
+    ndkContext.ndk,
+    ndkContext.publish
+  )
+  if (!isUpdated) {
+    toast.error(`Failed to create user's ${dTag} curation set`)
+  }
+  return isUpdated
+}
+
+export async function getReportingSet(
+  dTag: CurationSetIdentifiers,
+  ndkContext: NDKContextType
+) {
+  const result: string[] = []
+  const reportingNpub = import.meta.env.VITE_REPORTING_NPUB
+  const hexKey = npubToHex(reportingNpub)
+
+  if (hexKey) {
+    const event = await ndkContext.fetchEvent({
+      kinds: [kinds.Curationsets],
+      authors: [hexKey],
+      '#d': [dTag]
+    })
+
+    if (event) {
+      const list = NDKList.from(event)
+      list.items.forEach((item) => {
+        if (item[0] === 'a') {
+          result.push(item[1])
+        }
+      })
+    }
+  }
+
+  return result
+}
+
+export async function getCurationSet({
+  dTag,
+  pubkey,
+  ndkContext
+}: CurationSetArgs) {
+  const filter: NDKFilter = {
+    kinds: [kinds.Curationsets],
+    authors: [pubkey],
+    '#d': [dTag]
+  }
+
+  const nsfwListEvent = await ndkContext.fetchEventFromUserRelays(
+    filter,
+    pubkey,
+    UserRelaysType.Write
+  )
+
+  return nsfwListEvent
+}
+
+/**
+ * Update the article curation set (kind: 30004) for the user (pubkey)
+ * Add the aTag to the dTag list
+ * @see https://github.com/nostr-protocol/nips/blob/master/51.md#sets
+ */
+export async function addToCurationSet(
+  curationSetArgs: CurationSetArgs,
+  aTag: string
+) {
+  const curationSetEvent = await getCurationSet(curationSetArgs)
+
+  let isUpdated = false
+  if (curationSetEvent) {
+    const { dTag, pubkey, ndkContext } = curationSetArgs
+    const tags = curationSetEvent.tags
+    const alreadyExists =
+      tags.findIndex((item) => item[0] === 'a' && item[1] === aTag) !== -1
+
+    if (alreadyExists) {
+      toast.warn(`Already in user's ${dTag} list`)
+      return false
+    }
+
+    tags.push(['a', aTag])
+
+    const unsignedEvent = {
+      pubkey: pubkey,
+      kind: kinds.Curationsets,
+      content: curationSetEvent.content,
+      created_at: now(),
+      tags: [...tags]
+    }
+
+    isUpdated = await signAndPublish(
+      unsignedEvent,
+      ndkContext.ndk,
+      ndkContext.publish
+    )
+    if (!isUpdated) {
+      toast.error(`Failed to update user's ${dTag} list`)
+    }
+  } else {
+    isUpdated = await createCurationSet(curationSetArgs, aTag)
+  }
+
+  return isUpdated
+}
+
+/**
+ * Update the article curation set (kind: 30004) for the user (pubkey)
+ * Remove the aTag from the dTag list
+ */
+export async function removeFromCurationSet(
+  curationSetArgs: CurationSetArgs,
+  aTag: string
+) {
+  const curationSetEvent = await getCurationSet(curationSetArgs)
+  const { dTag, pubkey, ndkContext } = curationSetArgs
+
+  if (!curationSetEvent) {
+    toast.error(`Couldn't get ${dTag} list event from relays`)
+    return false
+  }
+  const tags = curationSetEvent.tags
+
+  const unsignedEvent: UnsignedEvent = {
+    pubkey: pubkey,
+    kind: kinds.Curationsets,
+    content: curationSetEvent.content,
+    created_at: now(),
+    tags: tags.filter((item) => item[0] !== 'a' || item[1] !== aTag)
+  }
+
+  const isUpdated = await signAndPublish(
+    unsignedEvent,
+    ndkContext.ndk,
+    ndkContext.publish
+  )
+  if (!isUpdated) {
+    toast.error(`Failed to update user's ${dTag} list`)
+  }
+  return isUpdated
+}
diff --git a/src/utils/index.ts b/src/utils/index.ts
index 3391eb9..91fe37b 100644
--- a/src/utils/index.ts
+++ b/src/utils/index.ts
@@ -6,3 +6,4 @@ export * from './zap'
 export * from './localStorage'
 export * from './consts'
 export * from './blog'
+export * from './curationSets'
diff --git a/src/utils/mod.ts b/src/utils/mod.ts
index 09537fe..24b59bd 100644
--- a/src/utils/mod.ts
+++ b/src/utils/mod.ts
@@ -39,6 +39,8 @@ export const extractModData = (event: Event | NDKEvent): ModDetails => {
     featuredImageUrl: getFirstTagValue('featuredImageUrl'),
     summary: getFirstTagValue('summary'),
     nsfw: getFirstTagValue('nsfw') === 'true',
+    repost: getFirstTagValue('repost') === 'true',
+    originalAuthor: getFirstTagValue('originalAuthor'),
     screenshotsUrls: getTagValue(event, 'screenshotsUrls') || [],
     tags: getTagValue(event, 'tags') || [],
     downloadUrls: (getTagValue(event, 'downloadUrls') || []).map((item) =>
@@ -118,6 +120,8 @@ export const initializeFormState = (
   featuredImageUrl: existingModData?.featuredImageUrl || '',
   summary: existingModData?.summary || '',
   nsfw: existingModData?.nsfw || false,
+  repost: existingModData?.repost || false,
+  originalAuthor: existingModData?.originalAuthor || undefined,
   screenshotsUrls: existingModData?.screenshotsUrls || [''],
   tags: existingModData?.tags.join(',') || '',
   downloadUrls: existingModData?.downloadUrls || [