commits
Update PUBLIC_BASE_URL to feature-study-tab preview URL for OAuth callback.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Enhancements:
- Made study board interactive for puzzle solving
- Players can now place stones to work through puzzles
- Added reset board button to restore initial puzzle position
- Track move history and turn state
- Created boo.sky.go.studied lexicon for tracking completed puzzles
- Added /api/study endpoint for marking and fetching studied puzzles
- Added "Mark as Studied" button (visible only when logged in)
- Visual indicator shows ✓ Studied for completed puzzles
- Studied status persists via ATProto records
- Fetches user's studied puzzles on mount
Users can now interactively solve puzzles and track their progress
across devices via the ATProto network.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Implements study mode with 2,500+ Go problems from scrapeGo repository:
Features:
- Enhanced SGF parser supporting AB/AW properties for puzzle positions
- Multi-problem SGF parsing for collection files
- Puzzle collection management with GitHub fetching and caching
- Study route with collection selector, puzzle display, and navigation
- 5 puzzle collections: Cho's Encyclopedia (Vols 1-3), Gokyo Shumyo, Hatsuyoron
- Deep linking support via URL parameters (?collection=cho-1&problem=42)
- Cloud-themed UI consistent with existing design
- Full credits and attribution section for source materials
Collections from https://github.com/mango314/scrapeGo
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
The tutorial popup was auto-opening on first visit and causing
issues on mobile that blocked all tap events, making the site
unusable. Temporarily disabled auto-open behavior.
- Tutorial still accessible via Footer "Tutorial" link
- Added better error handling for localStorage access
- Added error handling for SGF loading failures
- TODO: Re-enable auto-open with proper mobile testing
Fixes mobile usability issue.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Create spectating store for cross-component state sharing
- Show header login button when spectating on homepage
- Remove "Want to play?" banner (replaced by header login button)
- Add explicit Enter key handler to main login form input
Fixes:
- Login button now shows when spectating (games view)
- No login button on home login screen (avoids duplicate UI)
- Enter key explicitly triggers login on main form
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Hide login button on homepage (avoid duplicate login UI)
- Add actor-typeahead to login modal for handle autocompletion
- Add z-index: 1000 to actor-typeahead for proper layering
- Add onchange handler to modal input for typeahead sync
Fixes:
- No more confusing dual login UI on homepage
- Modal now has same typeahead functionality as main form
- Typeahead dropdown renders above all page content
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Move z-index from .header to .header-wrapper to avoid creating
stacking context that traps ProfileDropdown
- Add z-index: 50 to ProverbBanner to ensure it stays below header
- Header wrapper now at z-index: 100, higher than page content
This fixes:
- ProfileDropdown now renders above ProverbBanner
- ProfileDropdown renders above login form separator line
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Changed from bind:value to oninput handler to properly support
form submission. The Input component doesn't support two-way
binding, so we need to use the oninput callback pattern.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Add keyboard handler to close modals with ESC key
- Add close button (X) in top-right corner of modals
- Style close button with hover rotation effect
- Both login forms already support Enter key submission
Improves UX by preventing users from getting stuck in modals.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- 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>
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Issues fixed:
- Section header elements were cramped on one line
- Game count and filter toggles were breaking awkwardly
- Text was getting truncated
Changes:
- Add flex-wrap to .section-header to allow wrapping
- Add flex-wrap to .section-title-row for responsive layout
- Add flex-wrap to .filter-toggles for better mobile support
- Add white-space: nowrap to .game-count to prevent mid-text breaks
- Add gap spacing to section-header for consistent spacing
Now the layout gracefully wraps when space is limited, preventing
awkward text breaking and maintaining readability.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Header:
- Replace custom cloud card styling with Card component (variant="large")
- Remove duplicate CSS for cloud effects
- Keep only header-specific positioning and layout styles
Footer:
- Replace custom buttons with Button components (secondary, primary)
- Replace custom modal with Modal component
- Remove duplicate button and modal CSS
This reduces code duplication and ensures consistent styling across
the application using the unified component library.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Create reusable cloud-themed components:
- Card: cloud-styled containers with variants (default, large, compact)
- Button: primary, secondary, ghost variants with hover effects
- Input: form inputs with focus states
- Badge: status badges (success, warning, danger, info)
- StatusGlow: glowing status indicators for player states
- Modal: cloud-styled modal overlays
All components follow the 0.6s ease transition pattern and integrate
with existing design tokens for consistent cloud aesthetic.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Card.svelte: Unified card with variants (default, large, compact)
- Button.svelte: Unified button with variants (primary, secondary, ghost)
- Input.svelte: Unified input styling
- Badge.svelte: Status badges with color variants
- Modal.svelte: Reusable modal wrapper
Reduces CSS duplication from ~1,480 lines to ~460 lines (69% reduction)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Preview config is branch-specific and should only live in worktrees,
not on master.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Set emoji size to 28px, fine-tune position offset
- Show only most recent emoji per stone, skip reactions without emoji
- Add hover shrink animation (0.3s ease to 80%) for interactivity hint
- Click an emoji to rewind board history to that move
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When "All Reactions" mode is toggled, reaction emojis are overlaid
directly on the stones they reference, making it easy to see which
moves received reactions at a glance.
- Add reactionOverlay prop to Board component
- Compute overlay data mapping move reactions to stone coordinates
- Position emojis with drop shadow for visibility on both stone colors
- Show up to 3 unique emojis per stone, with +N count for more
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add custom DID resolvers for Cloudflare Workers (did:plc and did:web)
- Simplify db.ts to D1-only (removes better-sqlite3 for Workers compatibility)
- Remove dotenv dependency from hooks (not needed in Cloudflare)
- Pass platform context to OAuth endpoints for env var access
- Add deploy script and npm run deploy command
- Add backfill script to sync games from UFOS/Constellation to D1
- Configure D1 database binding in wrangler.toml
- Set PUBLIC_BASE_URL to go.sky.boo
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Auth routes now pass event.platform to getOAuthClient so environment
variables can be read from Cloudflare's platform.env in production.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Document all completed features including reactions
- List testing checklist
- Document known issues and workarounds
- Add next steps for deployment
- Status: Ready for testing
- Document all OAuth API fixes
- Document local development fallbacks
- Document ESM/CommonJS module fixes
- Add development setup instructions
- Update to use generateClientAssertionKey from @atcute/oauth-crypto
- Fix detection of existing keys to ignore commented lines
- Successfully generates EC keys for OAuth
- Add try-catch around database initialization
- Verify Kysely instance has selectFrom method before returning
- Add detailed error logging
- Return cached instance when available
- Use createRequire from module to enable CommonJS require in ESM
- Keep getDb synchronous to avoid breaking all callers
- Fix 'require is not defined' error in local development
- Add dotenv back for local development
- Database falls back to better-sqlite3 when D1 not available
- OAuth falls back to MemoryStore when KV not available
- Create .env file with local development settings
- Support hybrid local/production deployment
- Remove importJwkKey which no longer exists in v1.1.0
- Parse PRIVATE_KEY_JWK directly as JSON and provide as ClientAssertionPrivateJwk array
- Update imports to use ClientAssertionPrivateJwk type
Add no-cache headers to prevent stale data after structure changes.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Server now returns pre-filtered activeGames, waitingGames, completedGames
- Removed double filtering (server filtered, then client re-filtered)
- Client now uses server's pre-filtered arrays directly
- Keeps player_two inference from moves for backward compatibility
This fixes games showing in wrong sections due to filtering mismatch.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
During migration to on-protocol, many active games lack complete
Constellation data and are misclassified as 'waiting'. Using loose
filter (status != completed) until migration is complete.
TODO: Revert to strict filter (status === active) after migration.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Changed filter from 'status != completed' to 'status === active'.
This prevents games waiting for players from appearing in Current Games.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Prevent errors when resolving null DIDs to handles.
Returns 'Unknown' for null DIDs instead of crashing.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Check that action_count > 0 before determining if it's user's turn.
This prevents board preview loading issues for games that haven't started.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Replace database status with client-side derived status based on PDS data
- Game page now computes status from moves, resigns, and scores
- Homepage fetches backlinks from Constellation for moves, passes, resigns
- Fix Constellation API response handling (use 'records' not 'backlinks')
- Add resign detection for both boo.sky.go.resign and boo.sky.go.action
- Remove stale game.status field from homepage logic
- Add debug logging for game status computation
- Reduce verbose logging of full Constellation records
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit adds comprehensive support for handicap games and player color
selection when creating games.
Features:
- Players can choose their color (black, white, or random) when creating games
- Handicap option for 13x13 (max 5 stones) and 19x19 (max 9 stones) boards
- Handicap stones are automatically placed at star points in canonical order
- When handicap is selected, creator is forced to play as white
- Extra options UI: color and handicap settings hidden behind collapsible toggle
Implementation:
- Updated boo.sky.go.game lexicon to include handicap and handicapStones fields
- Added handicap column to games database table with migration
- Added creator_did column to track who owns the game record in ATProto
- Turn order reversed for handicap games (white plays first after handicap stones)
- Fixed game record fetching to use actual creator DID from AT URI
- Fixed move/pass validation to account for handicap turn order
- Fixed score submission to update correct repo (creator's, not always player_one)
- Handicap stones displayed in move history with H1, H2, etc. labels
- Updated join logic to handle games where player_one might be empty
- Fixed player resolution to use game record's actual playerOne/playerTwo values
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Winner Display:
- Add winner field to database schema
- Display winner's avatar in archive cards instead of "completed" badge
- Emphasize winner's name in player list with bold styling
- Fetch user profiles for avatars
- Show trophy emoji placeholder if no avatar available
Opponent Invite:
- Add opponent handle input field to create game form
- Resolve Bluesky handle to DID on server-side
- Create game directly with opponent (status=active) instead of waiting room
- Add validation (handle not found, can't play self)
- Update button text based on whether opponent is specified
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Keep database as index for homepage game discovery
- Keep database for game page lookups (rkey -> full game data)
- Database remains necessary for efficient discovery of games user is not involved in
- ATProtocol remains source of truth, database is kept in sync
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Add findGameByRkey() to search for game by rkey
- Remove database dependency from game page
- Fetch game metadata directly from Constellation
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Add fetchAllGamesFromConstellation() to query all game records
- Remove database dependency from homepage
- Filter games by time windows after fetching from Constellation
- Maintain same filtering logic (12h for active, 7d for completed)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Add fetchGameResigns() to get resign records from Constellation
- Add calculateGameMetadata() to compute action counts and last action
- Add listPlayerGames() to fetch all games from a player's PDS
- Add fetchAllGames() to aggregate games from multiple players
- Add GameWithMetadata interface with computed fields
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Added beginner mode toggle to game page with Go stone checkbox style
- Integrated tenuki library for liberty calculation
- Display liberty counts on stones with dynamic sizing and coloring:
- 1 liberty: Red with "1!" and pulsing animation (atari warning)
- 2-3 liberties: Progressive orange/yellow scaling
- 4+ liberties: Normal size with appropriate contrast
- Added wins/losses stats to profile page
- Created visual game history with opponent avatars
- Implemented segmented arc borders showing W/L/A record per opponent
- Sort opponents by most games, limit to 30 for performance
- Fixed profile page to reload data when navigating between profiles
- Handle resigned games as wins/losses in stats
- Treat completed games without scores as pending (yellow)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Add rotation effect to archive cards and waiting game items
- Fix inconsistent spacing in waiting-games section
- Update game-item-compact padding/gap to match game-item (1rem/1.25rem)
- All game lists now have consistent floating cloud rotation effect
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Replace translateX with rotate for off-kilter effect
- Apply small rotations (0.25deg to 1deg) to game list items
- Alternating left/right rotation creates natural cloud-like float
- 5 rotation variations for organic, non-repetitive pattern
- Makes game cards feel like they're drifting at different angles
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Remove global card drifting that affected all cards
- Apply subtle left/right shifts only to game-item elements
- Create staggered tiling effect in games lists
- Alternating pattern with 4 variations for visual variety
- Keeps main cards (header, login, etc) centered and stable
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Use Nunito for headers: friendly rounded sans-serif
- Keep Inter for body: clean, readable sans-serif
- Add drifting effect with alternating translateX on cards
- Cards shift left/right to create floating cloud aesthetic
- Buttons use rounded heading font for consistency
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This reverts commit 6c6dc24fada6efe9b241028428a2f6da524a5303.
- Use Crimson Text for body: elegant, readable serif without flourish
- Use Libre Baskerville for headings: strong traditional typography
- Add .sharp-card variant with angular corners for design contrast
- Update button styling with sharper corners and better typography
- Increase base font size to 18px for better readability
- Mix rounded cloud cards with angular elements for visual interest
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This reverts commit f31851ccdb6b58e918716c4abfda1bebc93c554a.
- Body text: Iowan Old Style (warm, readable serif)
- Headings: Hoefler Text (elegant traditional serif)
- Site title: Zapfino (calligraphic accent font)
- Add font CSS variables for consistent typography
- Update main h1 to use accent font with larger size
- Fallback to similar system fonts for compatibility
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Add TutorialPopup component with multi-step wizard and SGF-based diagrams
- Add Footer with Claude logo and AI transparency modal
- Create Rules page with interactive move navigation
- Add SGF parser utility for loading game diagrams
- Make Board component reactive to gameState changes
- Add modal/footer CSS styling
- Include SGF files for tutorial examples (single capture, group capture, scoring)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
1. Game list spacing: Fixed inconsistent game item heights by using
flexbox gap and making game-info flex: 1
2. Board hover: The interactive check was already correct - verified
hover only shows when it's your turn
3. Move submission: Removed page reload after moves/passes - now
updates local state directly. Only reloads if game ends (double-pass)
4. Stone-style checkboxes: Styled "My games" and "Your turn" checkboxes
to look like Go stones (white unchecked, black checked)
5. Share button: Made lighter/subtler with cloud background and border,
replaced butterfly emoji with Bluesky SVG logo, shortened to "Share"
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Created shared board-svg.ts utility for generating board SVGs
- Added /api/games/[id]/board endpoint that returns SVG images
- Mini boards now use simple <img> tags pointing to the SVG endpoint
- SVGs are cached (30s for active games, 1hr for completed)
- Removed client-side MiniBoard.svelte component
- Refactored og-image to use shared buildBoardStateFromMoves
This approach is:
- Simpler (just img tags)
- More performant (server-side rendering, caching)
- Scalable (SVG format)
- Consistent with OG image styling
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Update PUBLIC_BASE_URL to feature-study-tab preview URL for OAuth callback.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Enhancements:
- Made study board interactive for puzzle solving
- Players can now place stones to work through puzzles
- Added reset board button to restore initial puzzle position
- Track move history and turn state
- Created boo.sky.go.studied lexicon for tracking completed puzzles
- Added /api/study endpoint for marking and fetching studied puzzles
- Added "Mark as Studied" button (visible only when logged in)
- Visual indicator shows ✓ Studied for completed puzzles
- Studied status persists via ATProto records
- Fetches user's studied puzzles on mount
Users can now interactively solve puzzles and track their progress
across devices via the ATProto network.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Implements study mode with 2,500+ Go problems from scrapeGo repository:
Features:
- Enhanced SGF parser supporting AB/AW properties for puzzle positions
- Multi-problem SGF parsing for collection files
- Puzzle collection management with GitHub fetching and caching
- Study route with collection selector, puzzle display, and navigation
- 5 puzzle collections: Cho's Encyclopedia (Vols 1-3), Gokyo Shumyo, Hatsuyoron
- Deep linking support via URL parameters (?collection=cho-1&problem=42)
- Cloud-themed UI consistent with existing design
- Full credits and attribution section for source materials
Collections from https://github.com/mango314/scrapeGo
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
The tutorial popup was auto-opening on first visit and causing
issues on mobile that blocked all tap events, making the site
unusable. Temporarily disabled auto-open behavior.
- Tutorial still accessible via Footer "Tutorial" link
- Added better error handling for localStorage access
- Added error handling for SGF loading failures
- TODO: Re-enable auto-open with proper mobile testing
Fixes mobile usability issue.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Create spectating store for cross-component state sharing
- Show header login button when spectating on homepage
- Remove "Want to play?" banner (replaced by header login button)
- Add explicit Enter key handler to main login form input
Fixes:
- Login button now shows when spectating (games view)
- No login button on home login screen (avoids duplicate UI)
- Enter key explicitly triggers login on main form
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Hide login button on homepage (avoid duplicate login UI)
- Add actor-typeahead to login modal for handle autocompletion
- Add z-index: 1000 to actor-typeahead for proper layering
- Add onchange handler to modal input for typeahead sync
Fixes:
- No more confusing dual login UI on homepage
- Modal now has same typeahead functionality as main form
- Typeahead dropdown renders above all page content
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Move z-index from .header to .header-wrapper to avoid creating
stacking context that traps ProfileDropdown
- Add z-index: 50 to ProverbBanner to ensure it stays below header
- Header wrapper now at z-index: 100, higher than page content
This fixes:
- ProfileDropdown now renders above ProverbBanner
- ProfileDropdown renders above login form separator line
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Add keyboard handler to close modals with ESC key
- Add close button (X) in top-right corner of modals
- Style close button with hover rotation effect
- Both login forms already support Enter key submission
Improves UX by preventing users from getting stuck in modals.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- 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>
Issues fixed:
- Section header elements were cramped on one line
- Game count and filter toggles were breaking awkwardly
- Text was getting truncated
Changes:
- Add flex-wrap to .section-header to allow wrapping
- Add flex-wrap to .section-title-row for responsive layout
- Add flex-wrap to .filter-toggles for better mobile support
- Add white-space: nowrap to .game-count to prevent mid-text breaks
- Add gap spacing to section-header for consistent spacing
Now the layout gracefully wraps when space is limited, preventing
awkward text breaking and maintaining readability.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Header:
- Replace custom cloud card styling with Card component (variant="large")
- Remove duplicate CSS for cloud effects
- Keep only header-specific positioning and layout styles
Footer:
- Replace custom buttons with Button components (secondary, primary)
- Replace custom modal with Modal component
- Remove duplicate button and modal CSS
This reduces code duplication and ensures consistent styling across
the application using the unified component library.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Create reusable cloud-themed components:
- Card: cloud-styled containers with variants (default, large, compact)
- Button: primary, secondary, ghost variants with hover effects
- Input: form inputs with focus states
- Badge: status badges (success, warning, danger, info)
- StatusGlow: glowing status indicators for player states
- Modal: cloud-styled modal overlays
All components follow the 0.6s ease transition pattern and integrate
with existing design tokens for consistent cloud aesthetic.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Card.svelte: Unified card with variants (default, large, compact)
- Button.svelte: Unified button with variants (primary, secondary, ghost)
- Input.svelte: Unified input styling
- Badge.svelte: Status badges with color variants
- Modal.svelte: Reusable modal wrapper
Reduces CSS duplication from ~1,480 lines to ~460 lines (69% reduction)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Preview config is branch-specific and should only live in worktrees,
not on master.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When "All Reactions" mode is toggled, reaction emojis are overlaid
directly on the stones they reference, making it easy to see which
moves received reactions at a glance.
- Add reactionOverlay prop to Board component
- Compute overlay data mapping move reactions to stone coordinates
- Position emojis with drop shadow for visibility on both stone colors
- Show up to 3 unique emojis per stone, with +N count for more
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add custom DID resolvers for Cloudflare Workers (did:plc and did:web)
- Simplify db.ts to D1-only (removes better-sqlite3 for Workers compatibility)
- Remove dotenv dependency from hooks (not needed in Cloudflare)
- Pass platform context to OAuth endpoints for env var access
- Add deploy script and npm run deploy command
- Add backfill script to sync games from UFOS/Constellation to D1
- Configure D1 database binding in wrangler.toml
- Set PUBLIC_BASE_URL to go.sky.boo
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Server now returns pre-filtered activeGames, waitingGames, completedGames
- Removed double filtering (server filtered, then client re-filtered)
- Client now uses server's pre-filtered arrays directly
- Keeps player_two inference from moves for backward compatibility
This fixes games showing in wrong sections due to filtering mismatch.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
During migration to on-protocol, many active games lack complete
Constellation data and are misclassified as 'waiting'. Using loose
filter (status != completed) until migration is complete.
TODO: Revert to strict filter (status === active) after migration.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Replace database status with client-side derived status based on PDS data
- Game page now computes status from moves, resigns, and scores
- Homepage fetches backlinks from Constellation for moves, passes, resigns
- Fix Constellation API response handling (use 'records' not 'backlinks')
- Add resign detection for both boo.sky.go.resign and boo.sky.go.action
- Remove stale game.status field from homepage logic
- Add debug logging for game status computation
- Reduce verbose logging of full Constellation records
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit adds comprehensive support for handicap games and player color
selection when creating games.
Features:
- Players can choose their color (black, white, or random) when creating games
- Handicap option for 13x13 (max 5 stones) and 19x19 (max 9 stones) boards
- Handicap stones are automatically placed at star points in canonical order
- When handicap is selected, creator is forced to play as white
- Extra options UI: color and handicap settings hidden behind collapsible toggle
Implementation:
- Updated boo.sky.go.game lexicon to include handicap and handicapStones fields
- Added handicap column to games database table with migration
- Added creator_did column to track who owns the game record in ATProto
- Turn order reversed for handicap games (white plays first after handicap stones)
- Fixed game record fetching to use actual creator DID from AT URI
- Fixed move/pass validation to account for handicap turn order
- Fixed score submission to update correct repo (creator's, not always player_one)
- Handicap stones displayed in move history with H1, H2, etc. labels
- Updated join logic to handle games where player_one might be empty
- Fixed player resolution to use game record's actual playerOne/playerTwo values
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Winner Display:
- Add winner field to database schema
- Display winner's avatar in archive cards instead of "completed" badge
- Emphasize winner's name in player list with bold styling
- Fetch user profiles for avatars
- Show trophy emoji placeholder if no avatar available
Opponent Invite:
- Add opponent handle input field to create game form
- Resolve Bluesky handle to DID on server-side
- Create game directly with opponent (status=active) instead of waiting room
- Add validation (handle not found, can't play self)
- Update button text based on whether opponent is specified
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Keep database as index for homepage game discovery
- Keep database for game page lookups (rkey -> full game data)
- Database remains necessary for efficient discovery of games user is not involved in
- ATProtocol remains source of truth, database is kept in sync
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Add fetchGameResigns() to get resign records from Constellation
- Add calculateGameMetadata() to compute action counts and last action
- Add listPlayerGames() to fetch all games from a player's PDS
- Add fetchAllGames() to aggregate games from multiple players
- Add GameWithMetadata interface with computed fields
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Added beginner mode toggle to game page with Go stone checkbox style
- Integrated tenuki library for liberty calculation
- Display liberty counts on stones with dynamic sizing and coloring:
- 1 liberty: Red with "1!" and pulsing animation (atari warning)
- 2-3 liberties: Progressive orange/yellow scaling
- 4+ liberties: Normal size with appropriate contrast
- Added wins/losses stats to profile page
- Created visual game history with opponent avatars
- Implemented segmented arc borders showing W/L/A record per opponent
- Sort opponents by most games, limit to 30 for performance
- Fixed profile page to reload data when navigating between profiles
- Handle resigned games as wins/losses in stats
- Treat completed games without scores as pending (yellow)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Add rotation effect to archive cards and waiting game items
- Fix inconsistent spacing in waiting-games section
- Update game-item-compact padding/gap to match game-item (1rem/1.25rem)
- All game lists now have consistent floating cloud rotation effect
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Replace translateX with rotate for off-kilter effect
- Apply small rotations (0.25deg to 1deg) to game list items
- Alternating left/right rotation creates natural cloud-like float
- 5 rotation variations for organic, non-repetitive pattern
- Makes game cards feel like they're drifting at different angles
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Remove global card drifting that affected all cards
- Apply subtle left/right shifts only to game-item elements
- Create staggered tiling effect in games lists
- Alternating pattern with 4 variations for visual variety
- Keeps main cards (header, login, etc) centered and stable
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Use Nunito for headers: friendly rounded sans-serif
- Keep Inter for body: clean, readable sans-serif
- Add drifting effect with alternating translateX on cards
- Cards shift left/right to create floating cloud aesthetic
- Buttons use rounded heading font for consistency
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Use Crimson Text for body: elegant, readable serif without flourish
- Use Libre Baskerville for headings: strong traditional typography
- Add .sharp-card variant with angular corners for design contrast
- Update button styling with sharper corners and better typography
- Increase base font size to 18px for better readability
- Mix rounded cloud cards with angular elements for visual interest
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Body text: Iowan Old Style (warm, readable serif)
- Headings: Hoefler Text (elegant traditional serif)
- Site title: Zapfino (calligraphic accent font)
- Add font CSS variables for consistent typography
- Update main h1 to use accent font with larger size
- Fallback to similar system fonts for compatibility
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Add TutorialPopup component with multi-step wizard and SGF-based diagrams
- Add Footer with Claude logo and AI transparency modal
- Create Rules page with interactive move navigation
- Add SGF parser utility for loading game diagrams
- Make Board component reactive to gameState changes
- Add modal/footer CSS styling
- Include SGF files for tutorial examples (single capture, group capture, scoring)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
1. Game list spacing: Fixed inconsistent game item heights by using
flexbox gap and making game-info flex: 1
2. Board hover: The interactive check was already correct - verified
hover only shows when it's your turn
3. Move submission: Removed page reload after moves/passes - now
updates local state directly. Only reloads if game ends (double-pass)
4. Stone-style checkboxes: Styled "My games" and "Your turn" checkboxes
to look like Go stones (white unchecked, black checked)
5. Share button: Made lighter/subtler with cloud background and border,
replaced butterfly emoji with Bluesky SVG logo, shortened to "Share"
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Created shared board-svg.ts utility for generating board SVGs
- Added /api/games/[id]/board endpoint that returns SVG images
- Mini boards now use simple <img> tags pointing to the SVG endpoint
- SVGs are cached (30s for active games, 1hr for completed)
- Removed client-side MiniBoard.svelte component
- Refactored og-image to use shared buildBoardStateFromMoves
This approach is:
- Simpler (just img tags)
- More performant (server-side rendering, caching)
- Scalable (SVG format)
- Consistent with OG image styling
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>