diff --git a/src/components/FeedSuggestedFollows/index.tsx b/src/components/FeedSuggestedFollows/index.tsx
new file mode 100644
index 0000000000..0c8993f8ce
--- /dev/null
+++ b/src/components/FeedSuggestedFollows/index.tsx
@@ -0,0 +1,156 @@
+import React from 'react'
+import {View} from 'react-native'
+import {ScrollView} from 'react-native-gesture-handler'
+import {AppBskyActorDefs, moderateProfile} from '@atproto/api'
+import {msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
+
+import {useProfileShadow} from '#/state/cache/profile-shadow'
+import {useModerationOpts} from '#/state/queries/preferences'
+import {useSuggestedFollowsQuery} from '#/state/queries/suggested-follows'
+import {isJustAMute} from 'lib/moderation'
+import {sanitizeDisplayName} from 'lib/strings/display-names'
+import {sanitizeHandle} from 'lib/strings/handles'
+import {PreviewableUserAvatar} from '#/view/com/util/UserAvatar'
+import {atoms as a, useTheme} from '#/alf'
+import {Button, ButtonIcon} from '#/components/Button'
+import {useFollowMethods} from '#/components/hooks/useFollowMethods'
+import {useRichText} from '#/components/hooks/useRichText'
+import {Check_Stroke2_Corner0_Rounded as Check} from '#/components/icons/Check'
+import {PlusLarge_Stroke2_Corner0_Rounded as Plus} from '#/components/icons/Plus'
+import {RichText} from '#/components/RichText'
+import {Text} from '#/components/Typography'
+
+export function SuggestedFollowCard({
+ profile: profileUnshadowed,
+}: {
+ profile: AppBskyActorDefs.ProfileViewBasic
+}) {
+ const t = useTheme()
+ const {_} = useLingui()
+ const profile = useProfileShadow(profileUnshadowed)
+ const moderationOpts = useModerationOpts()
+ const {follow, unfollow} = useFollowMethods({
+ profile,
+ // @ts-ignore TODO
+ logContext: 'FeedSuggestedFollowsCard',
+ })
+ // @ts-ignore TODO
+ const [descriptionRT] = useRichText(profileUnshadowed?.description ?? '')
+
+ if (!moderationOpts) return null
+ const moderation = moderateProfile(profile, moderationOpts)
+ const modui = moderation.ui('profileList')
+ if (modui.filter && !isJustAMute(modui)) return null
+
+ return (
+
+
+
+
+
+
+
+ {sanitizeDisplayName(
+ profile.displayName || sanitizeHandle(profile.handle),
+ moderation.ui('displayName'),
+ )}
+
+
+ {sanitizeHandle(profile.handle, '@')}
+
+
+
+
+
+
+
+
+
+
+
+ )
+}
+
+export function FeedSuggestedFollows() {
+ const t = useTheme()
+ const {isLoading, data: suggestions, error} = useSuggestedFollowsQuery()
+
+ const profiles: AppBskyActorDefs.ProfileViewBasic[] = []
+ if (suggestions) {
+ // Currently the responses contain duplicate items.
+ // Needs to be fixed on backend, but let's dedupe to be safe.
+ let seen = new Set()
+ for (const page of suggestions.pages) {
+ for (const actor of page.actors) {
+ if (!seen.has(actor.did)) {
+ seen.add(actor.did)
+ profiles.push(actor)
+ }
+ }
+ }
+ }
+
+ return (
+
+
+
+ Suggested for you
+
+
+
+
+
+ {isLoading
+ ? null
+ : error || !profiles.length
+ ? null
+ : profiles.map((profile, i) => (
+
+ ))}
+
+
+
+ )
+}