League The k4sen (LTK) 2025 tournament website built with Astro and TypeScript.
- Tournament: League The k4sen: League of Legends Streamer's Championship
- Season: 精霊の花祭り 幽明の境 (Spirit Flower Festival: Border of Light and Dark)
- Host: k4sen (ZETA DIVISION)
- Supported by: Riot Games
- Duration: June 25 - August 27, 2025
- Teams: 4 teams, 48 streamers total
- Framework: Astro v4.15.9 - Static Site Generator with API Routes
- Language: TypeScript v5.6.2 - Type Safety
- Styling: Tailwind CSS v3.4.17 - Utility-first CSS
- Testing: Playwright v1.54.1 - Visual regression testing
- Package Manager: pnpm - Fast, disk space efficient
- Video Data: YouTube Data API v3 - Automated video collection
- Automation: GitHub Actions - Scheduled video updates
- Container: Podman/Docker compatible
- Deployment: Netlify (Production), Static hosting compatible
ltk-astro/
├── src/
│ ├── components/ # Reusable Astro components
│ │ ├── Header.astro # Navigation header
│ │ ├── TeamCard.astro # Team information display
│ │ ├── StandingsTable.astro # Tournament standings
│ │ ├── BanPickDisplay.astro # LoL ban/pick information
│ │ └── Footer.astro # Site footer
│ ├── layouts/
│ │ └── Layout.astro # Base page layout
│ ├── pages/
│ │ ├── index.astro # Main tournament page
│ │ ├── clips.astro # Video clips page with YouTube integration
│ │ ├── admin/ # Admin management panel
│ │ │ └── index.astro # Admin dashboard
│ │ └── api/ # API Routes
│ │ ├── videos.ts # Video data API
│ │ ├── refresh-videos.ts # YouTube API integration
│ │ └── admin/ # Admin API endpoints
│ ├── types/ # TypeScript type definitions
│ │ ├── teams.ts # Team and player types
│ │ ├── matches.ts # Match and tournament types
│ │ ├── common.ts # Shared utility types
│ │ └── index.ts # Type exports
│ ├── utils/ # Utility functions
│ │ ├── youtubeApi.ts # YouTube Data API integration
│ │ └── adminAuth.ts # Admin authentication utilities
│ └── data/ # Static tournament and video data
│ ├── ltk-sbb-teams.json # Team rosters and info
│ ├── ltk-sbb-matches.json # Match results, schedule, ban/pick data
│ ├── ltk-videos.json # YouTube video data (auto-updated)
│ ├── ltk-videos-metadata.json # Video management settings
│ └── ltk-custom-videos.json # Manually added videos
├── tests/ # Playwright test files
│ └── ban-pick-layout.spec.ts # Visual regression tests
├── playwright.config.ts # Playwright configuration
├── tailwind.config.mjs # Tailwind CSS configuration
├── astro.config.mjs # Astro configuration
├── netlify.toml # Netlify deployment settings
├── Dockerfile # Multi-stage container build
├── docker-compose.yml # Container orchestration
├── nginx.conf # Production web server config
└── package.json # Dependencies and scripts
- Node.js 18+
- pnpm (recommended) or npm/yarn
- YouTube Data API v3 Key (for video features)
- Podman or Docker (for containerized development, optional)
# Clone and navigate to the project
cd ltk-astro
# Install dependencies
pnpm install
# Set up environment variables
cp .env.example .env
# Edit .env file with your API keys
# YOUTUBE_API_KEY=your_youtube_api_key_here
# ADMIN_PASSWORD=your_secure_admin_password
# Start development server
pnpm dev
# Open browser to http://localhost:4321pnpm dev # Start development server with HMR
pnpm build # Build for production (standard build)
pnpm build:check # Build with TypeScript type checking
pnpm preview # Preview production build locally
pnpm check # Run TypeScript type checking only
pnpm lint # Run ESLint for code quality
# Testing Commands
pnpm playwright test # Run all Playwright tests
pnpm playwright test --grep "responsive" # Run responsive tests only
pnpm playwright test --ui # Interactive test mode
pnpm exec playwright show-report # View test resultsThe LTK website includes an automated video clips section that aggregates content from YouTube.
- Automatic Collection: YouTube Data API integration fetches #LTK videos every 4 hours
- Smart Categorization: Automatically separates regular videos and YouTube Shorts
- Manual Management: Admin panel for adding custom videos and managing visibility
- Search & Filter: Real-time search with category filters (regular/shorts/all)
- Responsive Design: Optimized layout for all devices with lazy loading
-
Get YouTube Data API Key:
# Visit: https://console.developers.google.com # Create a new project or select existing # Enable YouTube Data API v3 # Create credentials (API Key)
-
Configure Environment Variables:
# In .env file YOUTUBE_API_KEY=your_youtube_api_key_here ADMIN_PASSWORD=your_secure_admin_password -
Test API Integration:
# Start development server pnpm dev # Visit admin panel: http://localhost:4321/admin # Login with your admin password # Click "動画を更新" to test YouTube API
Access the admin panel at /admin with your configured password:
- Dashboard: View video counts, API usage, and last update time
- Video Management: Toggle video visibility, delete custom videos
- Manual Add: Add videos that API might miss (private/unlisted)
- Bulk Operations: Refresh all videos from YouTube API
- Real-time Stats: Monitor API quota usage and update schedules
GitHub Actions automatically updates video data:
# Runs every 4 hours via cron schedule
# Fetches new LTK videos from YouTube
# Commits updated data to repository
# Triggers Netlify rebuildGET /api/videos- Fetch video data with filtering/sortingPOST /api/refresh-videos- Manual video refresh (admin only)POST /api/admin/login- Admin authenticationGET/POST /api/admin/videos- Video management (admin only)
## 🐳 Container Development with Podman
### Development Environment
```bash
# Build development image
podman build -t ltk-astro:dev --target development .
# Run development container
podman run -d \
--name ltk-dev \
-p 4321:4321 \
-v "${PWD}":/app:Z \
ltk-astro:dev
# View logs
podman logs -f ltk-dev
# Access the application at http://localhost:4321
# Build production image
podman build -t ltk-astro:prod --target production .
# Run production container
podman run -d \
--name ltk-prod \
-p 8080:80 \
ltk-astro:prod
# Access the application at http://localhost:8080# Development mode
podman-compose up ltk-dev
# Production mode
podman-compose --profile production up ltk-prod
# With reverse proxy
podman-compose --profile proxy up
# Stop all services
podman-compose down# List running containers
podman ps
# Stop a container
podman stop ltk-dev
# Remove a container
podman rm ltk-dev
# View container logs
podman logs ltk-dev
# Execute commands in running container
podman exec -it ltk-dev sh
# Clean up images
podman image prune# Create production build
pnpm build
# Output will be in ./dist/ directory# Build production image
podman build -t ltk-astro:latest --target production .
# Tag for registry (optional)
podman tag ltk-astro:latest registry.example.com/ltk-astro:latest
# Push to registry (optional)
podman push registry.example.com/ltk-astro:latest-
Netlify (Current Production - Recommended)
- Live Site: https://ltk-sbb.shiai.games
- Netlify URL: https://ltk-fansite.netlify.app
- Build Command:
pnpm build - Publish Directory:
dist - Auto-deploy from
mainbranch - Custom domain with HTTPS
-
Vercel
- Import project from GitHub
- Automatic Astro detection
-
GitHub Pages
- Enable Pages in repository settings
- Use GitHub Actions for automated builds
-
Surge.sh
npm install -g surge npm run build surge dist/
- Railway: Connect GitHub and deploy
- Render: Docker container deployment
- DigitalOcean App Platform: Container support
- Google Cloud Run: Serverless containers
- AWS ECS/Fargate: Enterprise container deployment
# Run TypeScript type checking
pnpm check
# Watch mode for development
pnpm astro check --watch# Run all Playwright tests
pnpm playwright test
# Run specific test suites
pnpm playwright test --grep "responsive" # Responsive design tests
pnpm playwright test --grep "ban-pick" # Ban/pick layout tests
# Interactive testing with UI
pnpm playwright test --ui
# View detailed test reports
pnpm exec playwright show-report- Layout Validation: Ensures components don't overflow containers
- Responsive Design: Tests across mobile (375px), tablet (768px), desktop (1920px)
- Visual Screenshots: Automated screenshot capture for manual review
- Ban/Pick Testing: Specific tests for League of Legends draft information display
# Check container health
podman inspect ltk-dev | grep -A 5 "Health"
# Manual health check
curl http://localhost:4321/health- Static Generation: All pages pre-rendered at build time
- Tailwind CSS: Utility-first styling with purged CSS in production
- JavaScript Islands: Minimal client-side JavaScript with Astro
- Image Optimization: WebP support and responsive images
- TypeScript: Full type safety with zero-runtime overhead
- Multi-stage Build: Separate build and runtime environments
- Alpine Linux: Minimal base image size
- Layer Caching: Optimized Dockerfile layer ordering
- Health Checks: Built-in container monitoring
# Development
NODE_ENV=development
ASTRO_HOST=0.0.0.0
ASTRO_PORT=4321
# Production
NODE_ENV=productionEdit astro.config.mjs for:
- Output mode (static/hybrid/server)
- Integrations (React, Vue, Svelte, etc.)
- Build settings
- Server configuration
- Teams: Edit
src/data/ltk-sbb-teams.jsonfor roster changes - Matches: Edit
src/data/ltk-sbb-matches.jsonfor schedule, results, and ban/pick data - Types: Update
src/types/*.tsif schema changes - Test: Run
pnpm playwright testto verify responsive design - Rebuild: Run
pnpm buildor restart dev server
Add League of Legends draft information to match results:
{
"result": {
"winner": "team_name",
"score": "1-0",
"draft": {
"bans": {
"team1": ["Yasuo", "Zed", "Katarina"],
"team2": ["Jinx", "Thresh", "Lee Sin"]
},
"picks": {
"team1": ["Azir", "Graves", "Nautilus", "Kai'Sa", "Ornn"],
"team2": ["Syndra", "Kindred", "Leona", "Aphelios", "Shen"]
}
}
}
}- Fully Typed: Complete TypeScript interfaces for all data structures
- League of Legends Integration:
ChampionDraftinterface for ban/pick data - Type Safety: Compile-time validation of all data imports
- Auto-completion: Full IDE support with typed data access
- Non-root user in production
- Minimal attack surface with Alpine Linux
- Security headers in Nginx configuration
- Health checks for monitoring
- Content Security Policy (CSP)
- XSS Protection headers
- HTTPS enforcement (in production)
- CORS configuration
Port already in use:
# Kill process using port 4321
lsof -ti:4321 | xargs kill -9
# Or use different port
pnpm dev --port 3000Container build fails:
# Clean up Docker/Podman cache
podman system prune -a
# Rebuild without cache
podman build --no-cache -t ltk-astro:dev .TypeScript errors:
# Clear TypeScript cache
rm -rf .astro/
pnpm checkPlaywright test failures:
# View test report
pnpm exec playwright show-report
# Run tests in debug mode
pnpm playwright test --debug
# Update test snapshots (if visual changes are expected)
pnpm playwright test --update-snapshotsResponsive design issues:
# Run responsive tests specifically
pnpm playwright test --grep "responsive"
# Check mobile viewport behavior
pnpm playwright test --grep "mobile"Volume mounting issues (SELinux):
# Add :Z flag for SELinux systems
podman run -v "${PWD}":/app:Z ltk-astro:dev- Live Site: ltk-fansite.netlify.app
- Tournament Info: k4sen Twitch
- Technical Issues: Check container logs, TypeScript errors, and Playwright test reports
- Astro Documentation: docs.astro.build
- Tailwind CSS: tailwindcss.com
- Playwright Documentation: playwright.dev
- Podman Documentation: podman.io
This project is for educational and informational purposes.
- League of Legends © Riot Games, Inc.
- Tournament Content © k4sen / ZETA DIVISION
- Website Code © LTK Development Team
Built with ❤️ using Astro, TypeScript, Tailwind CSS, and Playwright
Current Status: ✅ Live on Netlify | 🧪 Visual Testing | 📱 Mobile Optimized