- Merge NEW_FEATURES.md into MISSING_BACKEND_API.md as "Future Feature Proposals"
- Remove redundant NEW_FEATURES.md file
- Add CLAUDE.md to .gitignore (local development config)
- Include pending frontend component updates
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Shorten date format in match header (remove year)
- Change meta cards from grid to flex for better alignment
- Disable demo download for matches older than 4 weeks (Valve retention limit)
- Fix avg_rank card to only show valid CS Ratings (>1000)
- Remove min-h-screen from 8 pages to eliminate footer gap
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Wrap player name, avatar, and badges in a flex container to ensure
MVP badge and team-top trophy icon appear inline rather than breaking
to a new line.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Chat page:
- Fix player lookup using player_name instead of player_id to avoid
JavaScript number precision loss with 64-bit Steam IDs
- Update player filter dropdown to use names instead of IDs
Player page (Teammates):
- Construct full avatar URLs from hash when backend returns hash format
- Handle both full URLs and hashes with startsWith check
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add Steam avatars to match overview scoreboard (both teams)
- Add avatars to weapons page player table
- Add avatars to damage page player table and top dealer cards
- Add avatars to flashes page player table and Hall of Shame section
- Replace initial-based chat avatars with real Steam avatars
- Display actual Steam avatar on player profile page header
All avatar implementations include team-colored borders and fallback
to icons when avatar is unavailable.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Document implemented match analysis features (rounds, economy, weapons, etc.)
- Add player profile features with Premier rating
- Reference MISSING_BACKEND_API.md for backend requirements
- Update status to Phase 2 Complete
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Create economyUtils.ts with team-aware buy type classification
(CT has higher thresholds due to M4 cost)
- Add Economy Overview toggle to rounds page with charts
- Resolve player names/avatars in round economy display
- Remove standalone Economy tab (merged into Rounds)
- Document missing backend API data (round winner, win reason)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add player meta stats API endpoint with teammates, weapons, and map data
- Display avg_rank badge on match cards and match detail page
- Add tick rate and demo download improvements to match layout
- Create sitemap proxy routes to backend for SEO
- Document backend data limitations in transformers (rounds/weapons)
- Fix 400 error: backend limits meta stats to max 10 items
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add hero section with decorative blur orbs and grid pattern overlay
- Replace DaisyUI classes with neon design system (void backgrounds, neon accents)
- Add neon glow effects to avatar, stats, and section headers
- Add Combat Impact section with multi-kills (2K, 3K, 4K, Aces), MVPs, assists, ADR
- Add Rating Journey section with peak rating, current rating, delta, and range
- Add "Ace Hunter Detected" badge for players with 3+ aces
- Add "Flash Criminal Detected" badge for excessive team flashing
- Add empty state card when detailed match data unavailable (unparsed demos)
- Update chart colors to neon palette (blue for K/D, green for KAST)
- Reorganize utility stats with thematic descriptions
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Complete overhaul of all 7 match sub-pages (Overview, Flashes, Economy,
Details, Weapons, Damage, Chat) with consistent neon design system.
Key changes:
- Update Card/Tabs components with void backgrounds and neon accents
- Add decorative blur orbs and grid pattern to match layout hero
- Convert DaisyUI classes to custom Tailwind with neon colors
- Update chart components with neon-themed tooltips and grid styling
- Add RoundTimeline neon glow on selection with void-themed tooltips
Puns added throughout:
- "Hall of Shame" for players who flash teammates more than enemies
- "Needs Therapy Award" for high team damage
- "MVP (Most Violent Player)" badge
- "The Poverty Round", "YOLO Buy" economy labels
- "Multi-Threat Level", "Can't Touch This", "Molotov Mixologist"
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Create FAQ page with accordion-style Q&A sections and Terms of Service
page with comprehensive legal content. Redesign Privacy page with neon
styling. All legal pages use system font for headings to ensure
readability.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Convert error page to neon esports aesthetic with gold theme for
warning states, animated flash icon, and proper button semantics.
Remove API Docs link from footer navigation.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Convert the about page from DaisyUI to the custom neon design system
with decorative blur orbs, glowing icons, and contextual hover effects
on feature cards. External links now open in new tabs.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Convert the players page and related components from DaisyUI to the
custom neon design system, matching the landing page and matches page
visual style. Adds decorative blur orbs, neon glow effects, and
consistent color semantics across PlayerCard, RecentPlayers, and
TrackPlayerModal components.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Convert matches page from DaisyUI to neon esports design system
- Add colored left borders to cards for instant win/loss/tie scanning
- Add player count badges and demo status icons to match cards
- Implement filter state preservation across navigation
- Add staggered card animations and skeleton loading states
- Add slide transition for filter panel
- Make cards compact with horizontal layout for better density
- Update grid to 4 columns on xl screens
- Style DataTable, ShareCodeInput with neon theme
- Add external link support to NeonButton
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Extract SearchModal component from SearchBar for root-level rendering
- Add isModalOpen state to search store with open/close methods
- Simplify SearchBar to trigger button only
- Update Modal with proper overflow handling and scroll-to-close
- Fix layout background to use void color
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Delete ThemeToggle.svelte component
- Remove theme toggle from Header
- Set permanent cs2dark theme in app.html
- Add darkreader-lock meta tag to prevent extension conflicts
- Add color-scheme: dark meta for browser hints
- Update theme-color to void (#0a0a0f)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Apply void dark background with neon-blue border accents
- Add neon text-shadow glow to logo (cyan + gold)
- Update nav links to hover:text-neon-blue with focus-visible states
- Add grid pattern overlay to footer
- Use neon-red for heart icon and donation hover
- Add motion-reduce support and accessible focus rings
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Create HeroSection with animated search bar and stat counters
- Add LiveMatchTicker with auto-scrolling recent matches
- Build FlashLeaderboard "Wall of Shame" with podium display
- Implement FeatureShowcase with scroll-triggered animations
- Add NeonCTA call-to-action section with trust badges
- Create reusable NeonButton component with glow effects
Accessibility improvements:
- Add aria-labels, aria-hidden for decorative elements
- Implement focus-visible ring styles for keyboard navigation
- Support prefers-reduced-motion across all animations
- Use semantic HTML (article, nav, dl) for screen readers
- Improve color contrast ratios for WCAG compliance
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Complete site rebrand with flash-themed humor throughout:
- Update logo to "team" + "flash.rip" two-color design
- Add flash-themed error pages (404 = "You've Been Full-Blind")
- Revamp homepage hero with "Stop Flashing Your Teammates" tagline
- Update flash statistics page with playful labels ("Friendly Crimes", "Self-Inflicted L")
- Add loading messages store with flash-themed text
- Update all page meta titles and descriptions
- Update sitemap.xml and robots.txt with new domain
- Update package.json name and description
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add dynamic MR12/MR15 halftime calculation to RoundTimeline component
- Fix TrackPlayerModal API signature (remove shareCode, change isOpen to open binding)
- Update Player types for string IDs and add ban fields (vac_count, vac_date, game_ban_count, game_ban_date)
- Add target/rel props to Button component for external links
- Enhance homepage with processing matches indicator
- Update preferences store for string player IDs
- Document Phase 5 progress and TypeScript fixes in TODO.md
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Based on comprehensive research, CS2 implements a bifurcated ranking system:
- Premier Mode: CS Rating (numerical ELO, 0-30,000+) - launched Aug 31, 2023
- Competitive/Wingman: Skill Groups (0-18, Silver I to Global Elite)
- Legacy CS:GO: Skill Groups only (pre-Sept 27, 2023)
Changes:
- Add game_mode field to Match type ('premier' | 'competitive' | 'wingman')
- Create rankingSystem.ts utility with smart detection logic:
* Checks match date (CS:GO legacy vs CS2)
* Checks game_mode (Premier vs Competitive/Wingman)
* Falls back to rating value heuristic (0-18 vs 1000+)
- Update PremierRatingBadge to use new detection logic
- Pass match context from match detail page to badge component
- Update Match and schema documentation with dual-system details
- Add research.md documenting CS2's ranking system architecture
Key dates:
- August 31, 2023: Premier Mode and CS Rating launched
- September 27, 2023: CS2 officially replaced CS:GO
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Update Zod schemas to match raw API response formats
- Create transformation layer (rounds, weapons, chat) to convert raw API to structured format
- Add player name mapping in transformers for better UX
- Fix Svelte 5 reactivity issues in chat page (replace $effect with $derived)
- Fix Chart.js compatibility with Svelte 5 state proxies using JSON serialization
- Add economy advantage chart with halftime perspective flip (WIP)
- Remove stray comment from details page
- Update layout to load match data first, then pass to API methods
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Debug logging was added to troubleshoot rank detection logic.
Now that icons are working correctly, removing the console.log.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Set Rating column table cells to fixed height (h-12 = 48px)
- Wrap icons in flex container for vertical centering
- Reduce icon size from 14x14 to 11x11 to fit within row height
- Add max-h-11 constraint to prevent overflow
- Add inline-block and align-middle to icon for proper alignment
This ensures all table rows remain the same height regardless of
whether they show rank icons or Premier rating badges.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- sm: 6x6 → 10x10 (used in scoreboard tables)
- md: 8x8 → 12x12
- lg: 12x12 → 16x16
The icons were too small to see details at 6x6 pixels.
Now properly visible in the Rating column of match scoreboards.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
The API returns CS:GO skill groups (0-18) in BOTH rank_old and rank_new
fields for legacy matches. Updated detection logic to:
- Check if rating (rank_new) is in 0-18 range (CS:GO skill groups)
- CS2 ratings are typically 1000-30000, so no overlap
- Use rating value for RankIcon display (contains current skill group)
Debug output showed:
- rating: 15-17 (CS:GO skill groups)
- oldRating: same values (15-17)
- Previous logic failed because rating was not 0
This fix properly detects and displays CS:GO rank icons for legacy matches.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Update isLegacyRank check to properly detect CS:GO skill groups (0-18)
- Handle edge case where oldRating could be 0 (unranked)
- Add temporary debug logging to trace rank data values
- Fix detection for matches where rating is outside CS2 range
This will help identify if rank data is being passed correctly from the API.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implemented rank icon display system for pre-CS2 matches:
New Components:
- RankIcon.svelte: Displays CS:GO skill group icons (0-18)
- Supports sm/md/lg sizes
- Shows appropriate rank icon based on skill group
- Includes hover tooltips with rank names
- Handles all 19 rank tiers (Silver I → Global Elite)
Updated Components:
- PremierRatingBadge: Now intelligently switches between:
- CS:GO rank icons (when rank_old exists, rank_new doesn't)
- Premier rating badge (when rank_new exists)
- "Unranked" text (when neither exists)
Assets:
- Rank icons already present in static/images/rank_icons/
- Weapon icons already present in static/images/weapons/
- All icons in SVG format for crisp display at any size
Display Logic:
- Legacy matches (pre-Sept 2023): Show CS:GO rank icons
- Modern matches (CS2): Show Premier rating with trophy icon
- Automatically detects based on rank_old/rank_new fields
The scoreboard now displays the appropriate ranking visualization
based on match era, matching the original CSGO.WTF design.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implemented comprehensive visual overhaul based on UX feedback:
Background & Framing:
- Replace single gradient with dual-layer system for depth
- Add top-to-bottom gradient (30% → transparent → 40%) for framing
- Add left-to-right gradient (70% → 40% → 70%) for content focus
- Creates natural vignette effect that draws eye to center
Hero Info Panel:
- Wrap score and metadata in translucent panel (black/40 + backdrop-blur)
- Add subtle border (white/10) for definition
- Center-align and constrain width (max-w-3xl) for focused composition
- Cleaner hierarchy with reduced text shadows (rely on panel for contrast)
Typography & Layout:
- Increase map title to text-5xl, remove badge duplication
- Score numbers to text-6xl for prominence
- Team labels to text-xs with reduced opacity (70%)
- Metadata with bullet separators (•) for cleaner inline layout
- Smaller icons (3.5) and tighter spacing
Download Demo Button:
- Ghost style with translucent background (white/15)
- Subtle border (white/25) instead of solid primary color
- Hover effect (white/25) for interaction feedback
- Hide text on mobile (icon only) for space efficiency
Navigation:
- Reduce tabs background to 35% opacity with stronger backdrop-blur-lg
- Add border (white/10) for subtle definition
- Maintains readability while showing more background
Result: Modern, cinematic interface with improved visual hierarchy
and readability on both dark and bright map backgrounds.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Back button: solid black/60 background with backdrop-blur instead of ghost
- Download Demo button: solid primary background instead of outline
- Map name: triple-layer text shadow for maximum contrast
- Score labels: full white with strong shadows, uppercase styling
- Score numbers: triple shadow with glow effect (0.95/0.8/0.6 opacity layers)
- Colon separator: full white with strong shadow
- Metadata text/icons: strong text shadows and drop-shadow filters
- Tabs container: increased to black/70 with stronger backdrop-blur
All text elements now have multiple layers of shadows for readability
on bright map backgrounds like de_dust2.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Strengthen background gradient overlay from 90/70/50% to 95/85/75% opacity
- Add stronger text shadows to score numbers (double shadow for depth)
- Increase team label opacity from 70% to 90%
- Increase metadata text from white/80 to white with drop-shadow
- Increase tabs background from black/30 to black/50
- Improve colon separator contrast
Fixes readability issues on bright maps like de_dust2.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Use parseMatchWeaponsSafe instead of parseMatchWeapons
- Use parseMatchChatSafe instead of parseMatchChat
- Throw clear error message when demo not parsed yet
- Prevents Zod validation errors from reaching page loaders
- Matches the pattern already used for rounds endpoint
This fixes Zod errors when navigating to match detail pages where
the demo hasn't been fully parsed yet by the backend.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Fix toast notification imports: change from showToast to toast.success/error
- Remove hover preloading from app.html and Tabs component
- Fix match rounds API handling with safe parsing for incomplete data
- Fix pagination timestamp calculation (API returns Unix timestamp, not ISO string)
- Refactor matches page state management to fix reactivity issues:
- Replace separate state variables with single matchesState object
- Completely replace state object on updates to trigger reactivity
- Fix infinite loop in intersection observer effect
- Add keyed each blocks for proper list rendering
- Remove client-side filtering (temporarily) to isolate reactivity issues
- Add error state handling with nextPageTime in matches loader
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Create detailed privacy policy explaining data collection and usage practices.
## New Page: /privacy
### Content Sections
**Introduction**
- Overview of CS2.WTF's commitment to privacy
**Information We Collect**
- Public Steam Data: Steam ID, match stats, chat messages, VAC status
- Usage Data: Page visits and feature interactions
- Browser Storage: Theme, favorites, recent players (localStorage only)
**How We Use Information**
- Provide match statistics and analysis
- Track performance over time
- Generate visualizations
- Improve service quality
**Cookies and Local Storage**
- Details on localStorage usage for preferences
- No tracking cookies
- User-controllable through browser settings
**Data Sharing**
- No selling/trading of personal information
- Only share when legally required or for safety
- May use service providers
**Security**
- Reasonable security measures implemented
- Acknowledgment of inherent internet risks
- Note that Steam data is already public
**Your Rights**
- Access, correction, and deletion rights
- Opt-out by not using service
- Control via Steam privacy settings
**Third-Party Services**
- Links to Steam profiles
- Google Translate integration
- Not responsible for third-party privacy practices
**Children's Privacy**
- Not directed at children under 13
- No knowingly collected children's data
**Policy Changes**
- May update with notice
- Continued use implies acceptance
**Contact**
- Direct users to GitHub for questions/issues
### UI Implementation
- Clean, readable layout with Card components
- Icons for each section (Shield, Eye, Cookie, Server, Mail)
- Responsive design optimized for all screen sizes
- Proper semantic HTML and accessibility
- SEO-optimized with meta tags
- Current date automatically displayed
The policy is comprehensive yet clear, covering all necessary legal bases while
explaining data practices in user-friendly language. Already linked from the
footer navigation.
This completes Phase 3 Feature 3 - privacy compliance established.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add comprehensive match record breakdown showing wins, losses, and ties.
## Changes
### Data Calculation (+ page.ts)
- Enhanced playerStats mapping to detect tied matches
- Calculate `isTie` by comparing team scores (score_team_a === score_team_b)
- Add `tied` boolean field alongside existing `won` field
- Ensure wins exclude tied matches for accurate statistics
### Statistics Display (+page.svelte)
- Added "Match Record" card to Career Statistics section
- Calculate wins, losses, and ties from playerStats
- Display in compact format: "XW / YL / ZT"
- Color-coded: wins (green), losses (red), ties (blue)
- Show total matches analyzed below the record
### UI Improvements
- Expanded Career Statistics grid from 4 to 5 columns
- Responsive: 2 columns on mobile, 5 on desktop
- Consistent card styling with other career stats
- Trophy icon for Match Record card
## Implementation Details
**Tie Detection Logic:**
```typescript
const isTie = match.score_team_a === match.score_team_b;
const won = !isTie &&
((playerData.team_id === 2 && match.score_team_a > match.score_team_b) ||
(playerData.team_id === 3 && match.score_team_b > match.score_team_a));
```
**Record Format:**
- Wins: Green text, "W" suffix
- Losses: Red text, "L" suffix
- Ties: Blue text, "T" suffix
- Separators: Gray "/"
The statistics are calculated from the last 15 matches with full details,
providing accurate win/loss/tie breakdown for performance tracking.
This completes Phase 3 Feature 2 - match records now fully visible.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add direct link to Steam Community profile for easy access to player's Steam page.
## Changes
### UI Addition
- Added "Steam Profile" button to player page actions section
- Positioned alongside "Track Player" and "View All Matches" buttons
- Uses ExternalLink icon from lucide-svelte
- Ghost button variant for secondary action styling
### Link Implementation
- Opens Steam Community profile in new tab
- Uses player's Steam ID (uint64) to construct profile URL
- Format: `https://steamcommunity.com/profiles/{steamid64}`
- Includes `target="_blank"` and `rel="noopener noreferrer"` for security
### UX Improvements
- Changed actions container to use `flex-wrap` for responsive layout
- Buttons wrap on smaller screens to prevent overflow
- External link icon clearly indicates opening in new tab
**Security Note:** The `rel="noopener noreferrer"` attribute prevents:
- Potential security issues with window.opener access
- Referrer information leakage to external site
This provides users quick access to full Steam profile information including
inventory, game library, friends list, and other Steam-specific data not
available in CS2.WTF.
This completes Phase 3 Feature 1 - Steam profile integration added.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Enable translation of non-English chat messages to help users understand
international communications.
## Changes
### Translation Detection
- Added `mightNeedTranslation()` function to detect non-English text
- Checks for Cyrillic, Chinese, Japanese, Korean, and Arabic characters
- Uses Unicode range pattern matching for language detection
### Translation UI
- Added Languages icon from lucide-svelte
- Display translate button next to messages that contain non-English text
- Button shows icon only on mobile, "Translate" text on desktop
- Positioned using flexbox to prevent text wrapping issues
### Translation Functionality
- `translateMessage()` opens Google Translate in new popup window
- Auto-detects source language, translates to English
- Uses Google Translate's free web interface (no API key required)
- Opens in 800x600 popup for optimal translation viewing
## Implementation Details
The feature works by:
1. Scanning each message for non-ASCII character ranges
2. Showing translate button only for messages likely in foreign languages
3. Opening Google Translate web UI in popup when clicked
4. Preserving original message while providing translation access
**Why Google Translate Web Interface:**
- No API keys or authentication required
- Free and unlimited usage
- Familiar translation interface for users
- Supports all languages Google Translate offers
- Popup window keeps context while showing translation
This approach avoids the complexity and cost of translation APIs while
providing full-featured translation capabilities to users.
This completes Phase 2 Feature 4 and ALL Phase 2 features! 🎉🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implement dynamic sitemap.xml and robots.txt for search engine optimization.
## New Files
### src/routes/sitemap.xml/+server.ts
- Generate XML sitemap with all indexable pages
- Include static pages (home, matches list)
- Dynamically fetch and include recent 100 matches
- Set appropriate priority and changefreq for each URL type
- Cache response for 1 hour to reduce server load
### src/routes/robots.txt/+server.ts
- Allow all crawlers to index the site
- Point crawlers to sitemap.xml location
- Set crawl-delay of 1 second to be polite to server
- Cache response for 1 day
## Implementation Details
**Sitemap Structure:**
- Static pages: Priority 0.9-1.0, updated daily
- Match pages: Priority 0.7, updated weekly
- Fetches up to 100 most recent matches from API
- Uses match date as lastmod timestamp for accurate indexing
**SEO Benefits:**
- Helps search engines discover all match pages efficiently
- Provides crawlers with update frequency hints
- Improves indexing of dynamic content
- Reduces unnecessary crawling with robots.txt directives
The sitemap automatically stays current by fetching recent matches on each
request. The 1-hour cache balances freshness with server performance.
Note: Player profile pages not included in sitemap due to lack of bulk listing
API endpoint. Individual player pages will still be indexed via internal links.
This completes Phase 2 Feature 3 - site now properly configured for SEO.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Display average Premier rating for each team in match statistics cards.
## Changes
### Average Rating Calculation
- Calculate average rank_new across all ranked players on each team
- Filter out unranked players (rating = 0 or null/undefined)
- Round to nearest integer for clean display
### UI Display
- Add PremierRatingBadge below team name in statistics cards
- Small size badge with trophy icon
- Automatically styled with tier colors (gray/blue/purple/pink/red/gold)
- Only show badge if team has at least one ranked player
## Implementation Details
Extended `calcTeamStats()` function to compute `avgRating` by:
1. Filtering players with valid rank_new > 0
2. Computing average if any ranked players exist
3. Returning undefined if no players are ranked
The PremierRatingBadge component handles all tier styling automatically based
on the rating value using the existing formatPremierRating utility.
Team badges provide quick visual indication of match skill level and help
identify skill disparities between teams.
This completes Phase 2 Feature 2 - team ratings now prominently displayed.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Enhance match details scoreboard with additional visual information for better
player identification and context.
## Changes
### Avatar Column
- Display player profile images in first column (40x40px)
- Rounded style with border for consistent appearance
- Non-sortable for visual continuity
### Score Column
- Show in-game score for each player
- Sortable to identify top performers
- Monospace font for numeric alignment
### Player Color Indicators
- Add colored dot next to player names
- Map CS2 player colors (green, yellow, purple, blue, orange, grey) to hex values
- Visual indicator helps identify specific players during match review
## Implementation Details
Created `playerColors` mapping object to convert CS2's player color names to
hex color codes for display. Updated Player name column render function to
include inline colored dot element.
All columns maintain existing team color styling (terrorist/CT) for consistency.
Note: MVP and K/D ratio columns already existed in scoreboard.
This completes Phase 2 Feature 1 - scoreboard now provides comprehensive player
information at a glance.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implement localStorage-based player visit tracking with display on home page.
## New Features
### Recently Visited Players Component
- **RecentPlayers.svelte**: Grid display of up to 10 recently visited players
- **Responsive Layout**: 1-4 columns based on screen size
- **Player Cards**: Avatar, name, and time since last visit
- **Remove Functionality**: Individual player removal with X button
- **Auto-show/hide**: Component only renders when players have been visited
### Player Visit Tracking
- **recentPlayers utility**: localStorage management functions
- `getRecentPlayers()`: Retrieve sorted list by most recent
- `addRecentPlayer()`: Add/update player visit with timestamp
- `removeRecentPlayer()`: Remove specific player from list
- `clearRecentPlayers()`: Clear entire history
- **Auto-tracking**: Player profile page automatically records visits on mount
- **Smart deduplication**: Visiting same player updates timestamp, no duplicates
- **Max limit**: Maintains up to 10 most recent players
### Time Display
- Relative time formatting: "Just now", "5m ago", "2h ago", "3d ago"
- Real-time updates when component mounts
- Human-readable timestamps
### UX Features
- **Hover Effects**: Border highlights and shadow on card hover
- **Team Colors**: Player names inherit team colors from profiles
- **Remove on Hover**: X button appears only on hover for clean interface
- **Click Protection**: Remove button prevents navigation when clicked
- **Footer Info**: Shows count of displayed players
## Implementation Details
- **localStorage Key**: `cs2wtf_recent_players`
- **Data Structure**: Array of `{id, name, avatar, visitedAt}` objects
- **Sort Order**: Most recently visited first
- **SSR Safe**: All localStorage operations check for browser environment
- **Error Handling**: Try-catch wraps all storage operations with console errors
## Integration
- Added to home page between hero and featured matches
- Integrates seamlessly with existing layout and styling
- No data fetching required - pure client-side functionality
- Persists across sessions via localStorage
This completes Phase 1 (6/6) - all critical features now implemented!
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implement detailed weapon performance tracking and visualization.
## New Features
### Weapons Tab
- Added "Weapons" tab to match layout navigation
- Created `/match/[id]/weapons` route with server-side data loading
- Displays weapon statistics for all players in the match
### Statistics Displayed
**Overview Cards:**
- Total kills across all weapons
- Total damage dealt
- Total hits landed
**Charts & Visualizations:**
- Bar chart: Top 10 most-used weapons by kills
- Pie chart: Hit location distribution (head, chest, stomach, arms, legs)
- Legend with exact hit counts for each body part
**Player Performance Table:**
- Player name (with team color coding)
- Top weapon for each player
- Total kills per player
- Total damage per player
- Total hits per player
- Sortable columns for easy comparison
### Technical Implementation
- **Data Loading**: Server-side fetch of weapons data via `getMatchWeapons()` API
- **Type Safety**: Full TypeScript types with WeaponStats, PlayerWeaponStats, MatchWeaponsResponse
- **Error Handling**: Graceful fallback when weapons data unavailable
- **Aggregation**: Weapon stats aggregated across all players for match-wide insights
- **Team Colors**: Player names colored by team (terrorist/CT)
### UX Improvements
- Empty state with helpful message when no weapons data exists
- Responsive grid layouts for cards and charts
- Consistent styling with existing tabs
- Interactive data table with hover states and sorting
This completes Phase 1 feature 5 of 6 - comprehensive weapon performance analysis
gives players insight into their weapon choices and accuracy.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add per-player VAC and game ban status display in match details scoreboard.
## Changes
- **Types & Schema**: Add vac and game_ban optional boolean fields to MatchPlayer
- **Transformer**: Extract vac and game_ban from legacy player.vac and player.game_ban
- **UI**: Add "Status" column to details table showing VAC/BAN badges
- **Mocks**: Update mock player data with ban status fields
## Implementation Details
The backend API provides per-player ban status in match details via the player
object (player.vac and player.game_ban). These were previously not being extracted
by the transformer.
The new Status column displays:
- Red "VAC" badge if player has VAC ban
- Red "BAN" badge if player has game ban
- Both badges if player has both bans
- "-" if player has no bans
Users can identify banned players at a glance in the scoreboard, improving
transparency and match context.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
This commit completes the first phase of feature parity implementation and
resolves all API integration issues to match the backend API format.
## API Integration Fixes
- Remove all hardcoded default values from transformers (tick_rate, kast, player_count, steam_updated)
- Update TypeScript types to make fields optional where backend doesn't guarantee them
- Update Zod schemas to validate optional fields correctly
- Fix mock data to match real API response format (plain arrays, not wrapped objects)
- Update UI components to handle undefined values with proper fallbacks
- Add comprehensive API documentation for Match and Player endpoints
## Phase 1 Features Implemented (3/6)
### 1. Player Tracking System ✅
- Created TrackPlayerModal.svelte with auth code input
- Integrated track/untrack player API endpoints
- Added UI for providing optional share code
- Displays tracked status on player profiles
- Full validation and error handling
### 2. Share Code Parsing ✅
- Created ShareCodeInput.svelte component
- Added to matches page for easy match submission
- Real-time validation of share code format
- Parse status feedback with loading states
- Auto-redirect to match page on success
### 3. VAC/Game Ban Status ✅
- Added VAC and game ban count/date fields to Player type
- Display status badges on player profile pages
- Show ban count and date when available
- Visual indicators using DaisyUI badge components
## Component Improvements
- Modal.svelte: Added Svelte 5 Snippet types, actions slot support
- ThemeToggle.svelte: Removed deprecated svelte:component usage
- Tooltip.svelte: Fixed type safety with Snippet type
- All new components follow Svelte 5 runes pattern ($state, $derived, $bindable)
## Type Safety & Linting
- Fixed all ESLint errors (any types → proper types)
- Fixed form label accessibility issues
- Replaced error: any with error: unknown + proper type guards
- Added Snippet type imports where needed
- Updated all catch blocks to use instanceof Error checks
## Static Assets
- Migrated all files from public/ to static/ directory per SvelteKit best practices
- Moved 200+ map icons, screenshots, and other assets
- Updated all import paths to use /images/ (served from static/)
## Documentation
- Created IMPLEMENTATION_STATUS.md tracking all 15 missing features
- Updated API.md with optional field annotations
- Created MATCHES_API.md with comprehensive endpoint documentation
- Added inline comments marking optional vs required fields
## Testing
- Updated mock fixtures to remove default values
- Fixed mock handlers to return plain arrays like real API
- Ensured all components handle undefined gracefully
## Remaining Phase 1 Tasks
- [ ] Add VAC status column to match scoreboard
- [ ] Create weapons statistics tab for matches
- [ ] Implement recently visited players on home page
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add LegacyPlayerProfile transformer to handle API response format mismatch
- Transform avatar hashes to full Steam CDN URLs
- Map team IDs correctly (API 1/2 -> Schema 2/3)
- Calculate aggregate stats (avg_kills, avg_deaths, win_rate) from matches
- Reduce featured matches on homepage from 6 to 3
- Show 4 recent matches on player profile instead of 10
- Display recent matches in 4-column grid on desktop (side-by-side)
Fixes "Player not found" error for all player profiles.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Enable SSR for match pages by detecting server vs client context in API client
- Fix 500 errors on economy, chat, and details tabs by adding data loaders
- Handle unparsed matches gracefully with "Match Not Parsed" messages
- Fix dynamic team ID detection instead of hardcoding team IDs 2/3
- Fix DataTable component to properly render HTML in render functions
- Add fixed column widths to tables for visual consistency
- Add meta titles to all tab page loaders
- Fix Svelte 5 $derived syntax errors
- Fix ESLint errors (unused imports, any types, reactive state)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>