grain.social is a photo sharing platform built on atproto.
1import { BffContext, RouteHandler } from "@bigmoves/bff";
2import { Breadcrumb } from "../components/Breadcrumb.tsx";
3import { FollowsList } from "../components/FollowsList.tsx";
4import { Header } from "../components/Header.tsx";
5import { getActorProfile } from "../lib/actor.ts";
6import { getFollowersWithProfiles } from "../lib/graph.ts";
7import { State } from "../state.ts";
8import { profileLink } from "../utils.ts";
9
10export const handler: RouteHandler = (
11 _req,
12 params,
13 ctx: BffContext<State>,
14) => {
15 const handle = params.handle;
16 if (!handle) return ctx.next();
17
18 const actor = ctx.indexService.getActorByHandle(handle);
19
20 if (!actor) return ctx.next();
21
22 const profile = getActorProfile(actor?.did, ctx);
23
24 if (!actor) return ctx.next();
25
26 const followers = getFollowersWithProfiles(actor.did, ctx);
27
28 ctx.state.meta = [{ title: `People following @${handle} — Grain` }];
29
30 return ctx.render(
31 <div class="p-4">
32 <Breadcrumb
33 items={[{ label: "profile", href: profileLink(handle) }, {
34 label: "followers",
35 }]}
36 />
37 <Header>{profile?.displayName}</Header>
38 <p class="mb-6 text-zinc-600 dark:text-zinc-500">
39 {followers.length ?? 0} followers
40 </p>
41 <FollowsList profiles={followers} />
42 </div>,
43 );
44};