Back to Portfolio
Feng Shui 2

Chi War

Real-time RPG Management System for Feng Shui 2
Ruby on Rails
Next.js
TypeScript
WebSockets
AI Integration

Project Overview

Chi War is a comprehensive web application designed to manage remote tabletop RPG sessions for Feng Shui 2, the action movie RPG. Born out of necessity during the pandemic when in-person gaming became impossible, this project solves the unique challenge of managing Feng Shui 2's fast-paced, cinematic combat system in a digital environment.

Chi War DashboardMain dashboard showing active campaigns, character lists, and quick access to fights
Chi War Fights ListFights management page with cinematic backgrounds and session organization

Unlike traditional turn-based RPGs, Feng Shui 2 uses a "shot counter" system where actions happen on specific numbered shots throughout a sequence. This creates a dynamic, movie-like flow of action that's difficult to track manually, especially when playing remotely. Chi War automates this complex system while maintaining the excitement and spontaneity that makes Feng Shui 2 special.

The Technical Challenge

Real-time State Synchronization

The biggest challenge was ensuring that all players see the same game state in real-time. When one player takes an action, everyone else needs to see the updated shot counter, character positions, and status effects immediately. This required implementing WebSocket connections between the Next.js frontend and Ruby on Rails backend, with careful state management to prevent conflicts when multiple players act simultaneously.

Complex Game Mechanics

Feng Shui 2's shot counter system is deceptively complex. Different actions take different amounts of time, characters can act multiple times per sequence, and various supernatural powers can modify the timeline. The application had to faithfully implement these rules while remaining intuitive for players who might not understand the underlying mathematics.

Chi War Fight DetailFight detail page with cinematic background and start fight interface
User Experience Design

Creating an interface that captures the cinematic feel of Feng Shui 2 while remaining functional for actual gameplay was crucial. The UI needed to be fast and responsive, showing information clearly without overwhelming players with too many options. Every click had to feel immediate and impactful, matching the rapid-fire action of the game itself.

Chi War Character DetailCharacter detail page showing custom artwork
Chi War Character StatsMobile responsive view showing character stats

Technical Architecture

Backend: Ruby on Rails API

The Rails backend handles game state management, player authentication, and real-time communication. It implements the complex Feng Shui 2 rules engine and provides RESTful APIs for game operations. Action Cable manages WebSocket connections for real-time updates, ensuring low latency between player actions and state changes.

Frontend: Next.js with TypeScript

The React-based frontend provides an intuitive interface for players and game masters. TypeScript ensures type safety for complex game state objects, while Material UI components create a consistent, professional appearance. The application is fully responsive, working equally well on desktop and mobile devices for players who want to manage their characters from anywhere.

Database Design

PostgreSQL stores game sessions, character data, and action history. The schema supports the flexible nature of Feng Shui 2 characters while maintaining referential integrity. Careful indexing ensures fast queries even for games with extensive action histories.

Development Challenge: Generic Filter System

One of the most interesting technical challenges in Chi War was creating a reusable filter system that could work across all different entity types (characters, fights, campaigns, etc.) without code duplication. The solution was a generic filter component that dynamically renders different input types based on configuration.

The Problem

Each entity type in Chi War needed filtering capabilities, but they all had different field types: autocomplete dropdowns for related entities, string searches for names, static options for predefined values, and free-text search. Writing separate filter components for each would have led to significant code duplication and maintenance overhead.

The Solution: GenericFilter Component

The GenericFilter component uses TypeScript generics and configuration objects to dynamically render the appropriate input types. Here's the core implementation:

interface FilterFieldConfig {
  name: string
  type: "entity" | "string" | "static" | "search"
  staticOptions?: string[]
  allowNone?: boolean
  responseKey?: string
  displayName?: string
}

export function GenericFilter({
  entity,
  formState,
  onChange,
  onFiltersUpdate,
  omit = [],
  excludeIds = [],
}: GenericFilterProps) {
  const config = filterConfigs[entity]
  
  const renderField = (field: FilterFieldConfig) => {
    if (field.type === "static") {
      const Autocomplete = createStringAutocomplete(displayName)
      return (
        <Autocomplete
          value={filters?.[field.name] as string}
          onChange={newValue => changeFilter(field.name, newValue)}
          records={field.staticOptions || []}
          allowNone={field.allowNone ?? true}
        />
      )
    }
    
    if (field.type === "entity") {
      const Autocomplete = createAutocomplete(entityName)
      return (
        <Autocomplete
          value={filters?.[field.name] as AutocompleteOption | null}
          onChange={newValue => 
            changeFilter(field.name + "_id", newValue, true)
          }
          records={data[responseKey] || []}
          excludeIds={isPrimaryField ? excludeIds : undefined}
        />
      )
    }
    // ... other field types
  }
  
  return (
    <Stack direction="row" spacing={1} alignItems="center">
      {config.fields.map(field => renderField(field))}
    </Stack>
  )
}
Key Benefits

Type Safety: TypeScript ensures configuration objects match expected interfaces
Reusability: One component handles filtering for characters, fights, campaigns, and more
Maintainability: Changes to filter logic only need to be made in one place
Flexibility: New entity types can be added with just configuration, no new components
Consistency: All filters look and behave the same across the application

This pattern demonstrates how thoughtful abstraction can solve real-world development challenges while maintaining code quality and developer experience. The component has saved countless hours of development time and ensures consistent user experience across Chi War's interface.

Real-World Implementation

Here's the GenericFilter component in action, powering the character selection interface. Notice how it seamlessly combines different filter types: entity dropdowns for faction and archetype, string search for names, and static options for character types.

Chi War Character Selection with Generic FiltersCharacter selection modal demonstrating the GenericFilter system with multiple filter types working together

AI Integration and Content Generation

One of Chi War's most innovative features is its integration with the Grok API for AI-powered content generation. This allows game masters to dynamically create visual and narrative content during gameplay, enhancing the cinematic experience that Feng Shui 2 is known for.

Custom Image Generation

The Grok API integration enables real-time generation of custom artwork for any game element. Game masters can create unique visuals for characters, dramatic fight scenes, exotic locations, or specific story moments. This feature transforms static game sessions into visually rich experiences, with each campaign developing its own distinctive visual style.

Dynamic Villain and Monster Creation

Beyond just images, Chi War leverages AI to generate complete villains and monsters with full game statistics, backstories, and motivations. Game masters can specify parameters like threat level, archetype, or faction, and the system creates balanced opponents complete with appropriate Feng Shui 2 mechanics. This feature dramatically reduces prep time while ensuring fresh, unpredictable encounters for players.

AI Character Generation Workflow
AI Character PromptStep 1: GM enters character description prompt
AI Generation LoadingStep 2: AI processes the request with loading indicator
AI Character Generation CompleteStep 3: Complete character with stats and backstory
Generated Character: Victor Hargrove
AI Generated Character ProfileAI-generated portrait and action values
AI Character DetailsPersonal details, skills, and appearance description
AI Character BackgroundRich backstory and character motivation
Technical Implementation

The AI integration required careful API management and prompt engineering to ensure generated content fits Feng Shui 2's specific tone and mechanical requirements. The system validates generated statistics against game rules and provides fallbacks for API failures, maintaining game flow even when external services are unavailable.

Impact and Lessons Learned

Chi War successfully enabled our gaming group to continue playing Feng Shui 2 throughout the pandemic and beyond. The application has handled sessions with up to 8 players simultaneously, managing complex combats that would have been nearly impossible to track manually.

The AI integration proved particularly valuable, with game masters reporting 50% reduction in prep time while maintaining higher visual engagement. Players consistently noted how the custom-generated artwork enhanced their immersion in the cinematic action sequences.

This project taught me valuable lessons about real-time application architecture, API integration patterns, and the importance of user experience in specialized software. The challenge of maintaining game flow while ensuring technical accuracy required constant iteration and feedback from actual players.

Most importantly, Chi War demonstrates how modern AI can enhance rather than replace human creativity. By handling both mechanical complexity and content generation, it allows players and game masters to focus on storytelling and character development – the heart of what makes tabletop RPGs special.

Backend CodeFrontend CodeTechnical Article