extremely claude-assisted go game based on atproto! working on cleaning up and giving a more unique design, still has a bit of a slop vibe to it.
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Fix login flow and OAuth preview URLs

- Add login modal to Header with handle input
- Replace non-functional login link with modal trigger button
- Configure preview environment with correct PUBLIC_BASE_URL
- Fix OAuth redirects to use preview URLs instead of production

This allows users to log in from any page without navigation,
and enables testing OAuth on feature branches.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

+88 -2
+76 -2
src/lib/components/Header.svelte
··· 2 2 import { onMount } from 'svelte'; 3 3 import { fetchUserProfile, type UserProfile } from '$lib/atproto-client'; 4 4 import ProfileDropdown from './ProfileDropdown.svelte'; 5 - import { Card } from '$lib/components/ui'; 5 + import { Card, Modal, Input, Button } from '$lib/components/ui'; 6 6 7 7 type Session = { did: string } | null; 8 8 9 9 let { session }: { session: Session } = $props(); 10 10 11 11 let userProfile: UserProfile | null = $state(null); 12 + let showLoginModal = $state(false); 13 + let handle = $state(''); 14 + let isLoggingIn = $state(false); 12 15 13 16 onMount(async () => { 14 17 if (session) { 15 18 userProfile = await fetchUserProfile(session.did); 16 19 } 17 20 }); 21 + 22 + async function login() { 23 + if (!handle.trim()) return; 24 + 25 + isLoggingIn = true; 26 + try { 27 + const response = await fetch('/auth/login', { 28 + method: 'POST', 29 + headers: { 'Content-Type': 'application/json' }, 30 + body: JSON.stringify({ handle: handle.trim() }), 31 + }); 32 + 33 + if (!response.ok) { 34 + throw new Error(`Login failed: ${response.statusText}`); 35 + } 36 + 37 + const result = await response.json(); 38 + if (result.authorizationUrl) { 39 + window.location.href = result.authorizationUrl; 40 + } 41 + } catch (err) { 42 + console.error('Login failed:', err); 43 + alert('Login failed. Please try again.'); 44 + isLoggingIn = false; 45 + } 46 + } 18 47 </script> 19 48 20 49 <div class="header-wrapper"> ··· 33 62 <!-- Loading profile --> 34 63 <div class="avatar-placeholder"></div> 35 64 {:else} 36 - <a href="/" class="login-link">Login</a> 65 + <button class="login-link" onclick={() => showLoginModal = true}>Login</button> 37 66 {/if} 38 67 </div> 39 68 </div> 40 69 </Card> 70 + 71 + <Modal bind:isOpen={showLoginModal}> 72 + <div class="login-modal-content"> 73 + <h2>Login with @proto</h2> 74 + <form onsubmit={(e) => { e.preventDefault(); login(); }}> 75 + <Input 76 + bind:value={handle} 77 + placeholder="your-handle.bsky.social" 78 + disabled={isLoggingIn} 79 + class="login-input" 80 + /> 81 + <Button type="submit" disabled={isLoggingIn} variant="primary" class="login-button"> 82 + {isLoggingIn ? 'Logging in...' : 'Login'} 83 + </Button> 84 + </form> 85 + </div> 86 + </Modal> 41 87 </div> 42 88 43 89 <style> ··· 84 130 85 131 .login-link { 86 132 color: var(--sky-slate); 133 + background: transparent; 134 + border: none; 135 + cursor: pointer; 87 136 text-decoration: none; 88 137 font-weight: 500; 89 138 font-size: clamp(1rem, 2vw, 1.125rem); ··· 96 145 background: var(--sky-apricot-light); 97 146 color: var(--sky-apricot-dark); 98 147 box-shadow: 0 0 12px rgba(229, 168, 120, 0.5); 148 + } 149 + 150 + .login-modal-content { 151 + padding: 2rem; 152 + } 153 + 154 + .login-modal-content h2 { 155 + margin: 0 0 1.5rem 0; 156 + color: var(--sky-slate-dark); 157 + font-size: 1.75rem; 158 + text-align: center; 159 + } 160 + 161 + .login-modal-content form { 162 + display: flex; 163 + flex-direction: column; 164 + gap: 1rem; 165 + } 166 + 167 + .login-modal-content :global(.login-input) { 168 + width: 100%; 169 + } 170 + 171 + .login-modal-content :global(.login-button) { 172 + width: 100%; 99 173 } 100 174 101 175 .avatar-placeholder {
+12
wrangler.toml
··· 19 19 # [[kv_namespaces]] 20 20 # binding = "STATES_KV" 21 21 # id = "YOUR_STATES_KV_ID" 22 + 23 + [env.preview] 24 + compatibility_date = "2024-01-01" 25 + compatibility_flags = ["nodejs_compat"] 26 + 27 + [env.preview.vars] 28 + PUBLIC_BASE_URL = "https://feature-fix-login.atprotogo.pages.dev" 29 + 30 + [[env.preview.d1_databases]] 31 + binding = "DB" 32 + database_name = "atprotogo-db" 33 + database_id = "7509f118-4693-4dce-9d58-fdb8c768ae9c"