···15151616run dev with `npm run dev` (port 3768) and build with `npm run build` (the output is the `dist` folder)
17171818+1919+2020+you probably dont need to change these
2121+```ts
2222+const PROD_HANDLE_RESOLVER_PDS = "https://pds-nd.whey.party"
2323+const DEV_HANDLE_RESOLVER_PDS = "https://bsky.social"
2424+```
2525+if you do want to change these, i recommend changing both of these to your own PDS url. i separate the prod and dev urls so that you can change it as needed. here i separated it because if the prod resolver and prod url shares the same domain itll error and prevent logins
2626+1827## useQuery
1928Red Dwarf has been upgraded from its original bespoke caching system to Tanstack Query (react query). this migration was done to achieve a more robust and maintainable approach to data fetching and caching and state synchronization. ive seen serious performance gains from this switch!
2029
+62-30
oauthdev.mts
···11-import fs from 'fs';
22-import path from 'path';
11+import fs from "fs";
22+import path from "path";
33//import { generateClientMetadata } from './src/helpers/oauthClient'
44export const generateClientMetadata = (appOrigin: string) => {
55- const callbackPath = '/callback';
55+ const callbackPath = "/callback";
6677 return {
88- "client_id": `${appOrigin}/client-metadata.json`,
99- "client_name": "ForumTest",
1010- "client_uri": appOrigin,
1111- "logo_uri": `${appOrigin}/logo192.png`,
1212- "tos_uri": `${appOrigin}/terms-of-service`,
1313- "policy_uri": `${appOrigin}/privacy-policy`,
1414- "redirect_uris": [`${appOrigin}${callbackPath}`] as [string, ...string[]],
1515- "scope": "atproto transition:generic",
1616- "grant_types": ["authorization_code", "refresh_token"] as ["authorization_code", "refresh_token"],
1717- "response_types": ["code"] as ["code"],
1818- "token_endpoint_auth_method": "none" as "none",
1919- "application_type": "web" as "web",
2020- "dpop_bound_access_tokens": true
2121- };
2222-}
2323-88+ client_id: `${appOrigin}/client-metadata.json`,
99+ client_name: "ForumTest",
1010+ client_uri: appOrigin,
1111+ logo_uri: `${appOrigin}/logo192.png`,
1212+ tos_uri: `${appOrigin}/terms-of-service`,
1313+ policy_uri: `${appOrigin}/privacy-policy`,
1414+ redirect_uris: [`${appOrigin}${callbackPath}`] as [string, ...string[]],
1515+ scope: "atproto transition:generic",
1616+ grant_types: ["authorization_code", "refresh_token"] as [
1717+ "authorization_code",
1818+ "refresh_token",
1919+ ],
2020+ response_types: ["code"] as ["code"],
2121+ token_endpoint_auth_method: "none" as "none",
2222+ application_type: "web" as "web",
2323+ dpop_bound_access_tokens: true,
2424+ };
2525+};
24262525-export function generateMetadataPlugin({prod, dev}:{prod: string, dev: string}) {
2727+export function generateMetadataPlugin({
2828+ prod,
2929+ dev,
3030+ prodResolver = "https://bsky.social",
3131+ devResolver = prodResolver,
3232+}: {
3333+ prod: string;
3434+ dev: string;
3535+ prodResolver?: string;
3636+ devResolver?: string;
3737+}) {
2638 return {
2727- name: 'vite-plugin-generate-metadata',
3939+ name: "vite-plugin-generate-metadata",
2840 config(_config: any, { mode }: any) {
2929- let appOrigin;
3030- if (mode === 'production') {
3131- appOrigin = prod
3232- if (!appOrigin || !appOrigin.startsWith('https://')) {
3333- throw new Error('VITE_APP_ORIGIN environment variable must be set to a valid HTTPS URL for production build.');
4141+ console.log('๐ก vite mode =', mode)
4242+ let appOrigin, resolver;
4343+ if (mode === "production") {
4444+ appOrigin = prod;
4545+ resolver = prodResolver;
4646+ if (!appOrigin || !appOrigin.startsWith("https://")) {
4747+ throw new Error(
4848+ "VITE_APP_ORIGIN environment variable must be set to a valid HTTPS URL for production build."
4949+ );
3450 }
3551 } else {
3652 appOrigin = dev;
5353+ resolver = devResolver;
3754 }
3838-3939-5555+4056 const metadata = generateClientMetadata(appOrigin);
4141- const outputPath = path.resolve(process.cwd(), 'public', 'client-metadata.json');
5757+ const outputPath = path.resolve(
5858+ process.cwd(),
5959+ "public",
6060+ "client-metadata.json"
6161+ );
42624363 fs.writeFileSync(outputPath, JSON.stringify(metadata, null, 2));
44646565+ const resolvers = {
6666+ resolver: resolver,
6767+ };
6868+ const resolverOutPath = path.resolve(
6969+ process.cwd(),
7070+ "public",
7171+ "resolvers.json"
7272+ );
7373+7474+ fs.writeFileSync(resolverOutPath, JSON.stringify(resolvers, null, 2));
7575+7676+4577 // /*mass comment*/ console.log(`โ Generated client-metadata.json for ${appOrigin}`);
4678 },
4779 };
4848-}8080+}
···11+import { useAtom } from "jotai";
22+import { useCallback } from "react";
33+44+import { type LikeRecord,useLikeMutationQueue as useLikeMutationQueueFromProvider } from "~/providers/LikeMutationQueueProvider";
55+import { useAuth } from "~/providers/UnifiedAuthProvider";
66+77+import { internalLikedPostsAtom } from "./atoms";
88+99+export function useFastLike(target: string, cid: string) {
1010+ const { agent } = useAuth();
1111+ const { fastState, fastToggle, backfillState } = useLikeMutationQueueFromProvider();
1212+1313+ const liked = fastState(target);
1414+ const toggle = () => fastToggle(target, cid);
1515+ /**
1616+ *
1717+ * @deprecated dont use it yet, will cause infinite rerenders
1818+ */
1919+ const backfill = () => agent?.did && backfillState(target, agent.did);
2020+2121+ return { liked, toggle, backfill };
2222+}
2323+2424+export function useFastSetLikesFromFeed() {
2525+ const [_, setLikedPosts] = useAtom(internalLikedPostsAtom);
2626+2727+ const setFastState = useCallback(
2828+ (target: string, record: LikeRecord | null) =>
2929+ setLikedPosts((prev) => ({ ...prev, [target]: record })),
3030+ [setLikedPosts]
3131+ );
3232+3333+ return { setFastState };
3434+}
+2-2
src/utils/oauthClient.ts
···11import { BrowserOAuthClient, type ClientMetadata } from '@atproto/oauth-client-browser';
2233-// i tried making this https://pds-nd.whey.party but cors is annoying as fuck
44-const handleResolverPDS = 'https://bsky.social';
33+import resolvers from '../../public/resolvers.json' with { type: 'json' };
44+const handleResolverPDS = resolvers.resolver || 'https://bsky.social';
5566// eslint-disable-next-line @typescript-eslint/ban-ts-comment
77// @ts-ignore this should be fine ? the vite plugin should generate this before errors