A tool for fighting game enthusiasts to create, save, and share combos.
For the FGC
If you play fighting games seriously, you know the struggle. You find a sick combo on Twitter, try to write it down, and end up with illegible shorthand. Or you spend an hour in training mode, finally land something optimal, then forget it by next week.
Combo Forge gives you a proper place to document, organize, and share your tech.
Core Features
Combo Builder - Visual interface for constructing combos. Select your game, pick your character, then chain together moves using standard notation. The builder validates as you go - no more 'is this even possible?' moments.
Notation Support - Works with standard fighting game notation:
- Numpad notation (236P, 623K, etc.)
- Common abbreviations (QCF, DP, HCB)
- Game-specific moves (Just Frame inputs, links, cancels)
- Combo markers (>, xx, delay, micro-walk)
Damage Calculator - See your combo's damage, meter gain, and scaling in real-time. Compare routes to find the optimal balance between damage and meter efficiency.
Character Databases - Frame data, move properties, and hitbox information for supported games. Know exactly why your combo works (or doesn't).
Organization & Sharing
Collections - Group combos by character, game, or situation. Create collections like 'Sol BnBs', 'Anti-Air Confirms', or 'Tournament Winners'.
Tags & Search - Tag combos with situations (corner, midscreen, counterhit, etc.) and search your library instantly.
Share Links - Generate shareable links to individual combos or entire collections. Perfect for Discord, Twitter, or helping your local scene level up.
Import/Export - Bulk export your combos as JSON. Import other people's collections. Backup your years of lab work.
Supported Games
Currently building support for:
- Guilty Gear Strive
- Street Fighter 6
- Tekken 8
- More planned based on community interest
Community Features (Planned)
- Public combo repository
- Upvotes and comments
- Character-specific leaderboards (highest damage, most practical)
- Pro player combo collections
A single-page application demonstrating clean REST API design, OAuth integration, and vanilla JS frontend patterns.
Architecture Overview
public/ # Frontend (ES modules)
index.html
js/
main.js # Entry point, router
api.js # API client
components/ # UI components
pages/ # Page views
css/
styles.css
app/ # Backend (Starlette)
server.py # ASGI app, routes
routes/
api.py # Combo CRUD endpoints
auth.py # OAuth flows
models/
combo.py # Combo data model
game.py # Game/character definitions
services/
validator.py # Combo validation logic
calculator.py # Damage calculations
API Design
RESTful endpoints with JSON payloads:
GET /api/combos # List user's combos
POST /api/combos # Create combo
GET /api/combos/{id} # Get combo details
PUT /api/combos/{id} # Update combo
DELETE /api/combos/{id} # Delete combo
POST /api/combos/validate # Validate combo notation
POST /api/combos/calculate # Calculate damage/meter
GET /api/games # List supported games
GET /api/games/{id}/chars # List characters for game
GET /api/characters/{id} # Character frame data
Combo Model:
class Combo(AppModel):
id: str
user_id: str
game_id: str
character_id: str
name: str
notation: str # '5H > 6H > 236K > 236K'
parsed_moves: list[Move] # Structured representation
damage: int
meter_gain: float
tags: list[str]
notes: str
created_at: datetime
updated_at: datetime
Combo Validation
The validator parses notation and checks against game data:
def validate_combo(notation: str, character: Character) -> ValidationResult:
moves = parse_notation(notation)
for i, move in enumerate(moves):
# Check move exists
if move.input not in character.moves:
return ValidationResult(
valid=False, error=f'Unknown: {move.input}')
# Check cancel/link is possible
if i > 0:
prev_move = character.moves[moves[i-1].input]
curr_move = character.moves[move.input]
if not can_connect(prev_move, curr_move, move.connector):
return ValidationResult(
valid=False,
error=f'Cannot connect {prev_move.name}'
)
return ValidationResult(valid=True, moves=moves)
Authentication
Authlib handles OAuth flows:
- Discord OAuth (primary - where the FGC lives)
- Google OAuth (fallback)
Session Management:
- itsdangerous for secure cookie signing
- Session middleware stores user ID
- No passwords - OAuth only
Frontend Patterns
ES Modules - No bundler, no build step. Browser-native imports:
// main.js
import { Router } from './router.js';
import { ComboBuilder } from './components/combo-builder.js';
Component Pattern - Each UI element as a class:
class ComboBuilder {
constructor(container) {
this.container = container;
this.render();
}
render() {
this.container.innerHTML = `...`;
this.bindEvents();
}
}
Why no framework? - The UI is simple enough that vanilla JS is cleaner than React/Vue setup. No build step means instant iteration.