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 "social.grain.comment", 42 ], 43 externalCollections: [ 44 "app.bsky.actor.profile", 45 "app.bsky.graph.follow", 46 "sh.tangled.actor.profile", 47 "sh.tangled.graph.follow", 48 ], 49 collectionKeyMap: { 50 "social.grain.favorite": ["subject"], 51 "social.grain.graph.follow": ["subject"], 52 "social.grain.gallery.item": ["gallery", "item"], 53 "social.grain.photo.exif": ["photo"], 54 "social.grain.comment": ["subject"], 55 }, 56 // Used to exchange jwt token with mobile app 57 tokenCallbackUrl: "grainflutter://auth/callback", 58 lexicons, 59 rootElement: Root, 60 onError, 61 middlewares: [ 62 ...xrpcApi, 63 appStateMiddleware, 64 oauth({ 65 onSignedIn, 66 LoginComponent: LoginPage, 67 createAccountPdsHost: PDS_HOST_URL, 68 }), 69 route("/", timelineHandler), 70 route("/explore", exploreHandler), 71 route("/notifications", notificationsHandler), 72 route("/profile/:handleOrDid", profileHandler), 73 route("/profile/:handle/followers", followersHandler), 74 route("/profile/:handle/follows", followsHandler), 75 route("/profile/:handle/gallery/:rkey", galleryHandler), 76 route("/hashtag/:tag", hashtagHandler), 77 route("/upload", uploadHandler), 78 route("/onboard", onboardHandler), 79 route("/support", supportHandler), 80 route("/support/privacy", legal.privacyHandler), 81 route("/support/terms", legal.termsHandler), 82 route("/support/copyright", legal.copyrightHandler), 83 route("/support/community-guidelines", communityGuidelinesHandler), 84 route("/dialogs/create-account", dialogs.createAccount), 85 route("/dialogs/gallery/new", dialogs.createGallery), 86 route("/dialogs/gallery/:rkey", dialogs.editGallery), 87 route("/dialogs/gallery/:rkey/photos", dialogs.galleryPhotoSelect), 88 route("/dialogs/gallery/:rkey/edit", dialogs.editGalleryDetails), 89 route("/dialogs/gallery/:rkey/sort", dialogs.sortGallery), 90 route("/dialogs/gallery/:rkey/library", dialogs.galleryAddFromLibrary), 91 route("/dialogs/:creatorDid/gallery/:rkey/share", dialogs.galleryShare), 92 route("/dialogs/gallery/:did/select", dialogs.gallerySelect), 93 route("/dialogs/label/:src/:val", dialogs.labelValueDefinition), 94 route("/dialogs/profile", dialogs.editProfile), 95 route("/dialogs/avatar/:handle", dialogs.avatar), 96 route("/dialogs/image", dialogs.image), 97 route("/dialogs/photo/:rkey/remove", dialogs.photoRemove), 98 route("/dialogs/photo/:rkey/alt", dialogs.photoAlt), 99 route("/dialogs/photo/:rkey/exif", dialogs.photoExif), 100 route("/dialogs/photo/:did/:rkey/exif-overlay", dialogs.photoExifOverlay), 101 route("/dialogs/exif-info", dialogs.exifInfo), 102 route("/actions/update-seen", ["POST"], actions.updateSeen), 103 route("/actions/follow/:followeeDid", ["POST"], actions.follow), 104 route("/actions/follow/:followeeDid/:rkey", ["DELETE"], actions.unfollow), 105 route("/actions/create-edit", ["POST"], actions.galleryCreateEdit), 106 route("/actions/gallery/delete", ["POST"], actions.galleryDelete), 107 route( 108 "/actions/gallery/:rkey/add-photos", 109 ["PUT"], 110 actions.galleryAddPhotos, 111 ), 112 route( 113 "/actions/gallery/:galleryRkey/add-photo/:photoRkey", 114 ["PUT"], 115 actions.galleryAddPhoto, 116 ), 117 route( 118 "/actions/gallery/:galleryRkey/remove-photo/:photoRkey", 119 ["PUT"], 120 actions.galleryRemovePhoto, 121 ), 122 route("/actions/photo/:rkey", ["PUT"], actions.photoEdit), 123 route("/actions/photo/:rkey", ["DELETE"], actions.photoDelete), 124 route("/actions/photo", ["POST"], actions.uploadPhoto), 125 route( 126 "/actions/:creatorDid/gallery/:rkey/favorite", 127 ["POST"], 128 actions.galleryFavorite, 129 ), 130 route( 131 "/actions/:creatorDid/gallery/:rkey/favorite/:favRkey", 132 ["DELETE"], 133 actions.galleryUnfavorite, 134 ), 135 route("/actions/profile", ["PUT"], actions.profileUpdate), 136 route("/actions/gallery/:rkey/sort", ["POST"], actions.gallerySort), 137 route("/actions/get-blob", ["GET"], actions.getBlob), 138 ...comments, 139 route("/:did/:collection/:rkey", recordHandler), 140 route("/robots.txt", robotsHandler), 141 ], 142});