···5566huge thanks to [Microcosm](https://microcosm.blue/) for making this possible
7788+## running dev and build
99+in the `vite.config.ts` file you should change these values
1010+```ts
1111+const PROD_URL = "https://reddwarf.whey.party"
1212+const DEV_URL = "https://local3768forumtest.whey.party"
1313+```
1414+the PROD_URL is what will compile your oauth client metadata so it is very important to change that. same for DEV_URL if you are using a tunnel for dev work
1515+1616+run dev with `npm run dev` (port 3768) and build with `npm run build` (the output is the `dist` folder)
1717+818## useQuery
919Red 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!
1020···2232### Slingshot
2333though Red Dwarf was made before Microcosm [Slingshot](https://slingshot.microcosm.blue) existed, it now uses Slingshot to reduce load from each respective PDS server. Slignshot
24342525-## PassAuthProvider
2626-a really bad app-password auth provider, inherited from TestFront and used in all my projects from TestFront to ForumTest (im very good at naming things). in ForumTest, its been superseded by the [OAuthProvider](https://tangled.sh/@whey.party/forumtest/blob/main/src/providers/OAuthProvider.tsx). i havent backported it here and maybe soon, although oauth makes it slightly more annoying to do development because it requires a tunnel so maybe someday if i managed to merge the password and oauth logins to provide both options
3535+## UnifiedAuthProvider
3636+a merged auth provider with oauth and password based login. oauth makes it slightly more annoying to do development because it requires a tunnel, so so the password auth option is still here if you do prefer password login for whatever reason.
3737+3838+### Pass Auth
3939+a really bad app-password auth provider, inherited from TestFront and used in all my projects from TestFront to ForumTest (im very good at naming things).
4040+4141+### OAuth
4242+taken from ForumTest [OAuthProvider](https://tangled.sh/@whey.party/forumtest/blob/main/src/providers/OAuthProvider.tsx)
27432844## Custom Feeds
2945they work, but i havent implemented a simple way of viewing arbitraty feeds. currently it either loads discover (logged out) or your saved feeds (logged in) and its not a technical limitation i just havent implemented it yet
···66 UniversalPostRendererATURILoader,
77} from "~/components/UniversalPostRenderer";
88import * as React from "react";
99-import { useAuth } from "~/providers/PassAuthProvider";
99+import { useAuth } from "~/providers/UnifiedAuthProvider";
1010//import { usePersistentStore } from "~/providers/PersistentStoreProvider";
1111import {
1212 useQueryIdentity,
···9999function Home() {
100100 const {
101101 agent,
102102- loginStatus,
103103- login,
102102+ status,
103103+ authMethod,
104104+ loginWithPassword,
105105+ loginWithOAuth,
104106 logout,
105105- loading: loadering,
106106- authed,
107107 } = useAuth();
108108+ const authed = !!agent?.did;
108109109110 useEffect(() => {
110111 if (agent?.did) {
···112113 } else {
113114 store.set(authedAtom, false);
114115 }
115115- }, [loginStatus, agent, authed]);
116116+ }, [status, agent, authed]);
116117 useEffect(() => {
117118 if (agent) {
119119+ // is it just me or is the type really weird here it should be Agent not AtpAgent
118120 store.set(agentAtom, agent);
119121 } else {
120122 store.set(agentAtom, null);
121123 }
122122- }, [loginStatus, agent, authed]);
124124+ }, [status, agent, authed]);
123125124126 //const { get, set } = usePersistentStore();
125127 // const [feed, setFeed] = React.useState<any[]>([]);
+2-2
src/utils/atoms.ts
···11-import type AtpAgent from "@atproto/api";
11+import type Agent from "@atproto/api";
22import { atom, createStore } from "jotai";
33import { atomWithStorage } from 'jotai/utils';
44···2121 {}
2222);
23232424-export const agentAtom = atom<AtpAgent|null>(null);
2424+export const agentAtom = atom<Agent|null>(null);
2525export const authedAtom = atom<boolean>(false);
+16
src/utils/oauthClient.ts
···11+// src/helpers/oauthClient.ts
22+import { BrowserOAuthClient, type ClientMetadata } from '@atproto/oauth-client-browser';
33+44+// This is your app's PDS for resolving handles if not provided.
55+// You might need to host your own or use a public one.
66+const handleResolverPDS = 'https://bsky.social';
77+88+// This assumes your client-metadata.json is in the /public folder
99+// and will be served at the root of your domain.
1010+import clientMetadata from '../../public/client-metadata.json' assert { type: 'json' };
1111+1212+export const oauthClient = new BrowserOAuthClient({
1313+ // The type assertion is needed because the static import isn't strictly typed
1414+ clientMetadata: clientMetadata as ClientMetadata,
1515+ handleResolver: handleResolverPDS,
1616+});