grain.social is a photo sharing platform built on atproto.
1import { lexicons } from "$lexicon/lexicons.ts"; 2import { bff, oauth, route } from "@bigmoves/bff"; 3import { middlewares as xrpcApi } from "./api/mod.ts"; 4import { Root } from "./app.tsx"; 5import { LoginPage } from "./components/LoginPage.tsx"; 6import { PDS_HOST_URL } from "./env.ts"; 7import { onError } from "./lib/errors.ts"; 8import { middlewares as comments } from "./modules/comments.tsx"; 9import * as actions from "./routes/actions.tsx"; 10import { handler as communityGuidelinesHandler } from "./routes/community_guidelines.tsx"; 11import * as dialogs from "./routes/dialogs.tsx"; 12import { handler as exploreHandler } from "./routes/explore.tsx"; 13import { handler as followersHandler } from "./routes/followers.tsx"; 14import { handler as followsHandler } from "./routes/follows.tsx"; 15import { handler as galleryHandler } from "./routes/gallery.tsx"; 16import { handler as hashtagHandler } from "./routes/hashtag.tsx"; 17import * as legal from "./routes/legal.tsx"; 18import { handler as notificationsHandler } from "./routes/notifications.tsx"; 19import { handler as onboardHandler } from "./routes/onboard.tsx"; 20import { handler as profileHandler } from "./routes/profile.tsx"; 21import { handler as recordHandler } from "./routes/record.ts"; 22import { handler as robotsHandler } from "./routes/robots.tsx"; 23import { handler as supportHandler } from "./routes/support.tsx"; 24import { handler as timelineHandler } from "./routes/timeline.tsx"; 25import { handler as uploadHandler } from "./routes/upload.tsx"; 26import { appStateMiddleware } from "./state.ts"; 27import { onSignedIn } from "./utils.ts"; 28 29bff({ 30 appName: "Grain Social", 31 appLabelers: ["did:plc:nd45zozo34cr4pvxqu4rtr7e"], 32 appLabelerCollection: "social.grain.labeler.service", 33 collections: [ 34 "social.grain.actor.profile", 35 "social.grain.gallery", 36 "social.grain.gallery.item", 37 "social.grain.photo", 38 "social.grain.photo.exif", 39 "social.grain.favorite", 40 "social.grain.graph.follow", 41 ], 42 externalCollections: [ 43 "app.bsky.actor.profile", 44 "app.bsky.graph.follow", 45 "sh.tangled.actor.profile", 46 "sh.tangled.graph.follow", 47 ], 48 collectionKeyMap: { 49 "social.grain.favorite": ["subject"], 50 "social.grain.graph.follow": ["subject"], 51 "social.grain.gallery.item": ["gallery", "item"], 52 "social.grain.photo.exif": ["photo"], 53 "social.grain.comment": ["subject"], 54 }, 55 // Used to exchange jwt token with mobile app 56 tokenCallbackUrl: "grainflutter://auth/callback", 57 lexicons, 58 rootElement: Root, 59 onError, 60 middlewares: [ 61 ...xrpcApi, 62 appStateMiddleware, 63 oauth({ 64 onSignedIn, 65 LoginComponent: LoginPage, 66 createAccountPdsHost: PDS_HOST_URL, 67 }), 68 route("/", timelineHandler), 69 route("/explore", exploreHandler), 70 route("/notifications", notificationsHandler), 71 route("/profile/:handleOrDid", profileHandler), 72 route("/profile/:handle/followers", followersHandler), 73 route("/profile/:handle/follows", followsHandler), 74 route("/profile/:handle/gallery/:rkey", galleryHandler), 75 route("/hashtag/:tag", hashtagHandler), 76 route("/upload", uploadHandler), 77 route("/onboard", onboardHandler), 78 route("/support", supportHandler), 79 route("/support/privacy", legal.privacyHandler), 80 route("/support/terms", legal.termsHandler), 81 route("/support/copyright", legal.copyrightHandler), 82 route("/support/community-guidelines", communityGuidelinesHandler), 83 route("/dialogs/create-account", dialogs.createAccount), 84 route("/dialogs/gallery/new", dialogs.createGallery), 85 route("/dialogs/gallery/:rkey", dialogs.editGallery), 86 route("/dialogs/gallery/:rkey/photos", dialogs.galleryPhotoSelect), 87 route("/dialogs/gallery/:rkey/edit", dialogs.editGalleryDetails), 88 route("/dialogs/gallery/:rkey/sort", dialogs.sortGallery), 89 route("/dialogs/gallery/:rkey/library", dialogs.galleryAddFromLibrary), 90 route("/dialogs/:creatorDid/gallery/:rkey/share", dialogs.galleryShare), 91 route("/dialogs/gallery/:did/select", dialogs.gallerySelect), 92 route("/dialogs/label/:src/:val", dialogs.labelValueDefinition), 93 route("/dialogs/profile", dialogs.editProfile), 94 route("/dialogs/avatar/:handle", dialogs.avatar), 95 route("/dialogs/image", dialogs.image), 96 route("/dialogs/photo/:rkey/remove", dialogs.photoRemove), 97 route("/dialogs/photo/:rkey/alt", dialogs.photoAlt), 98 route("/dialogs/photo/:rkey/exif", dialogs.photoExif), 99 route("/dialogs/photo/:did/:rkey/exif-overlay", dialogs.photoExifOverlay), 100 route("/dialogs/exif-info", dialogs.exifInfo), 101 route("/actions/update-seen", ["POST"], actions.updateSeen), 102 route("/actions/follow/:followeeDid", ["POST"], actions.follow), 103 route("/actions/follow/:followeeDid/:rkey", ["DELETE"], actions.unfollow), 104 route("/actions/create-edit", ["POST"], actions.galleryCreateEdit), 105 route("/actions/gallery/delete", ["POST"], actions.galleryDelete), 106 route( 107 "/actions/gallery/:rkey/add-photos", 108 ["PUT"], 109 actions.galleryAddPhotos, 110 ), 111 route( 112 "/actions/gallery/:galleryRkey/add-photo/:photoRkey", 113 ["PUT"], 114 actions.galleryAddPhoto, 115 ), 116 route( 117 "/actions/gallery/:galleryRkey/remove-photo/:photoRkey", 118 ["PUT"], 119 actions.galleryRemovePhoto, 120 ), 121 route("/actions/photo/:rkey", ["PUT"], actions.photoEdit), 122 route("/actions/photo/:rkey", ["DELETE"], actions.photoDelete), 123 route("/actions/photo", ["POST"], actions.uploadPhoto), 124 route( 125 "/actions/:creatorDid/gallery/:rkey/favorite", 126 ["POST"], 127 actions.galleryFavorite, 128 ), 129 route( 130 "/actions/:creatorDid/gallery/:rkey/favorite/:favRkey", 131 ["DELETE"], 132 actions.galleryUnfavorite, 133 ), 134 route("/actions/profile", ["PUT"], actions.profileUpdate), 135 route("/actions/gallery/:rkey/sort", ["POST"], actions.gallerySort), 136 route("/actions/get-blob", ["GET"], actions.getBlob), 137 ...comments, 138 route("/:did/:collection/:rkey", recordHandler), 139 route("/robots.txt", robotsHandler), 140 ], 141});