a a vibe-coded abomination experiment of a fragrance review platform built on the atmosphere.
drydown.social
1# Existing Code Reference
2
3**Related Documents**:
4- [Architecture Overview](../architecture/overview.md) - System design
5- CLAUDE.md (project root) - Project overview
6
7## Current Codebase (🟢 Implemented)
8
9### Authentication Module
10
11**File**: `/src/auth.ts`
12
13**Key Functions**:
14- `getClient()` - Returns singleton BrowserOAuthClient instance
15- `initAuth()` - Initializes OAuth and checks for existing sessions
16- `login(handle)` - Initiates OAuth sign-in flow with Bluesky handle
17
18**OAuth Configuration**:
19- `client_id`: Special format using localhost with encoded redirect_uri
20- `redirect_uris`: `['http://127.0.0.1:5173']`
21- `handleResolver`: `'https://bsky.social'`
22- **CRITICAL**: Must run on `127.0.0.1:5173` (not `localhost`)
23
24**Example Usage**:
25```typescript
26// Initialize on app mount
27useEffect(() => {
28 initAuth().then(session => {
29 if (session) setSession(session)
30 })
31}, [])
32
33// Login
34const handleLogin = async (handle: string) => {
35 await login(handle) // Redirects to Bluesky OAuth
36}
37```
38
39---
40
41### App Component
42
43**File**: `/src/app.tsx`
44
45**Responsibilities**:
46- Session state management (`session: OAuthSession | null`)
47- Loading state during auth initialization
48- Conditional rendering: LoginForm vs authenticated UI
49- Sign out action
50
51**State**:
52```typescript
53const [session, setSession] = useState<OAuthSession | null>(null)
54const [isInitializing, setIsInitializing] = useState(true)
55```
56
57**Flow**:
581. App mounts → call `initAuth()`
592. If session exists → show authenticated UI
603. If no session → show LoginForm
61
62---
63
64### LoginForm Component
65
66**File**: `/src/components/LoginForm.tsx`
67
68**Features**:
69- Text input for Bluesky handle (placeholder: "alice.bsky.social")
70- Loading state during OAuth redirect
71- Error message display
72- Form submission handling
73
74**Example**:
75```typescript
76<form onSubmit={handleSubmit}>
77 <input
78 type="text"
79 placeholder="alice.bsky.social"
80 value={handle}
81 onChange={(e) => setHandle(e.target.value)}
82 />
83 <button type="submit" disabled={loading}>
84 {loading ? 'Signing in...' : 'Sign In'}
85 </button>
86 {error && <div class="error">{error}</div>}
87</form>
88```
89
90---
91
92### Development Server Configuration
93
94**File**: `/vite.config.ts`
95
96**Key Settings**:
97- Server host: `127.0.0.1` (NOT `localhost`)
98- Server port: `5173`
99- This is REQUIRED for OAuth to work
100
101```typescript
102export default defineConfig({
103 plugins: [preact()],
104 server: {
105 host: '127.0.0.1',
106 port: 5173
107 }
108})
109```
110
111---
112
113### Known Limitations
114
115**Logout Implementation** (`/src/app.tsx`):
116- Currently only clears UI state (`setSession(null)`)
117- Does NOT revoke OAuth tokens
118- Does NOT clear browser storage
119- SDK limitation: `BrowserOAuthClient` doesn't expose token revocation
120
121**Future Improvement**: Investigate SDK updates for proper logout
122
123---
124
125## Project Structure
126
127```
128/src
129├── main.tsx # App entry point
130├── app.tsx # Main App component (session mgmt)
131├── auth.ts # OAuth client singleton
132├── index.css # Global styles
133├── app.css # App-specific styles
134└── components/
135 └── LoginForm.tsx # Login form component
136
137/public
138├── vite.svg # Vite logo
139└── client-metadata.json # OAuth metadata (served statically)
140
141index.html # HTML entry point
142vite.config.ts # Vite config (127.0.0.1:5173)
143CLAUDE.md # Project documentation
144```
145
146---
147
148**Related Documents**:
149- [Architecture Overview](../architecture/overview.md) - Where new code will fit
150- [Implementation Roadmap](../implementation/overview.md) - What to build next
151- CLAUDE.md - Original project overview