React Vite Upload Guide

Learn how to prepare and upload your React games built with Vite

Back to guides

Preparing Your React Vite Game

React with Vite provides a fast and efficient way to build web games. Follow these steps to prepare your game for our platform:

Set Up Your React Vite Project

If you haven't already, create a new React project with Vite:

# Using yarn (recommended) yarn create vite my-game --template react # Using npm npm create vite@latest my-game -- --template react # Navigate to your project cd my-game

Note: We recommend using yarn as your package manager for React projects.

Configure Your Project

Update your vite.config.js file to ensure proper asset handling:

import { defineConfig } from 'vite' import react from '@vitejs/plugin-react' // https://vitejs.dev/config/ export default defineConfig({ plugins: [react()], base: './', // This ensures assets use relative paths build: { outDir: 'dist', assetsDir: 'assets', // Optimize the build minify: 'terser', rollupOptions: { output: { manualChunks: { vendor: ['react', 'react-dom'], }, }, }, }, })

Build Your Game

Run the build command to create a production-ready version of your game:

# Using yarn yarn build # Using npm npm run build

This will create a dist folder containing your built application with the following structure:

dist/ ├── index.html ├── assets/ │ ├── index-[hash].js │ ├── index-[hash].css │ └── ... └── ...

Test Your Build Locally

Before uploading, test your built game to ensure everything works correctly:

# Using a simple HTTP server npx serve -s dist # Or with Vite's preview yarn preview

Check that all game features, assets, and interactions work as expected.

Zip Your Build

Compress the entire dist folder into a ZIP file:

# On macOS/Linux cd dist zip -r ../my-game.zip ./* # On Windows # Right-click the dist folder > Send to > Compressed (zipped) folder

Important: Make sure to zip the contents of the dist folder, not the dist folder itself.

Common Issues and Solutions

Missing Assets

If your game assets (images, sounds, etc.) aren't loading:

Routing Issues

If you're using React Router and experiencing issues:

Performance Optimization

To improve your game's performance:

Implementing Game Session Tracking

All games uploaded to our platform must implement session tracking functionality. This allows us to track player sessions and maintain leaderboards for your game.

Important: Your game bundle must include API calls to our session tracking endpoints. Our validation system will check for these calls during the upload process. Games without proper session tracking implementation will be rejected.

Option 1: Use Our SDK (Recommended)

The easiest way to implement session tracking is to use our JavaScript SDK. You can download the SDK here or view an example implementation.

Include the following script in your index.html or import it in your React component:

// In index.html
<script src="/sdk/game-session-tracker.js"></script>

// OR in your React component
import { useEffect } from 'react';

useEffect(() => {
  const script = document.createElement('script');
  script.src = '/sdk/game-session-tracker.js';
  script.async = true;
  document.body.appendChild(script);
  
  return () => {
    document.body.removeChild(script);
  };
}, []);

Then initialize and use the tracker in your game component:

import { useState, useEffect } from 'react';

function Game() {
  const [tracker, setTracker] = useState(null);
  
  useEffect(() => {
    // Initialize the tracker once the SDK is loaded
    const initTracker = () => {
      if (window.GameSessionTracker) {
        const trackerInstance = new window.GameSessionTracker();
        setTracker(trackerInstance);
      }
    };
    
    // Check if SDK is already loaded
    if (window.GameSessionTracker) {
      initTracker();
    } else {
      // Wait for SDK to load
      window.addEventListener('game-session-tracker-loaded', initTracker);
    }
    
    return () => {
      window.removeEventListener('game-session-tracker-loaded', initTracker);
    };
  }, []);
  
  // Function to call when game ends
  const handleGameOver = (score) => {
    if (tracker) {
      tracker.endSession(score)
        .then(response => {
          console.log("Session recorded successfully", response);
        })
        .catch(error => {
          console.error("Failed to record session", error);
        });
    }
  };
  
  // Function to display leaderboard
  const showLeaderboard = () => {
    if (tracker) {
      tracker.getLeaderboard(10)
        .then(response => {
          const leaderboard = response.data.leaderboard;
          // Display leaderboard in your UI
        })
        .catch(error => {
          console.error("Failed to fetch leaderboard", error);
        });
    }
  };
  
  return (
    <div>
      {/* Your game UI */}
      <button onClick={() => handleGameOver(1500)}>End Game</button>
      <button onClick={showLeaderboard}>Show Leaderboard</button>
    </div>
  );
}

Option 2: Custom Implementation

If you prefer to implement session tracking yourself, follow these steps:

1. Parse URL parameters when your game loads:

import { useState, useEffect } from 'react';

function Game() {
  const [sessionData, setSessionData] = useState({
    token: '',
    appVersion: '',
    language: '',
    sessionStartTime: null
  });
  
  useEffect(() => {
    const urlParams = new URLSearchParams(window.location.search);
    const token = urlParams.get('token') || generateRandomToken();
    const appVersion = urlParams.get('appVersion') || '1.0.0';
    const language = urlParams.get('language') || 'en';
    
    setSessionData({
      token,
      appVersion,
      language,
      sessionStartTime: new Date()
    });
  }, []);

2. When the game ends, send session data to our API:

const endSession = async (score) => {
  const sessionEndTime = new Date();
  
  // Get the subdomain from the current hostname
  const hostname = window.location.hostname;
  const parts = hostname.split('.');
  const subdomain = parts.length > 2 ? parts[0] : '';
  
  const payload = {
    token: sessionData.token,
    session_start_time: sessionData.sessionStartTime.toISOString(),
    session_end_time: sessionEndTime.toISOString(),
    score: score,
    app_version: sessionData.appVersion,
    language: sessionData.language
  };

  // REQUIRED: This exact endpoint must be called when a game session ends
  try {
    const response = await fetch(`/api/v1/games/${subdomain}/session-ended`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(payload)
    });
    
    const data = await response.json();
    console.log("Session recorded successfully", data);
    return data;
  } catch (error) {
    console.error("Failed to record session", error);
    throw error;
  }
}

Testing Your Implementation

Before uploading, test your session tracking implementation:

  1. Use our example implementation at /sdk/example-implementation.html as a reference
  2. Add URL parameters to your local development URL (e.g., http://localhost:5173/?token=test123&appVersion=1.0.0&language=en)
  3. Use browser developer tools to verify network requests are being made correctly

In browser developer tools, check that the POST request to /api/v1/games/:subdomain/session-ended is being made with all required parameters.

Uploading to Jiran Games

Log in to Your Account

Sign in to your Jiran Games developer account.

Create a New Game

Click on "Add New Game" and fill in the required information:

  • Game Name
  • Description
  • Game Logo (recommended size: 512x512px)
  • Tags (to help users find your game)
  • Subdomain (this will be your game's URL: yourgame.jiran.games)

Upload Your Game Bundle

Select the ZIP file containing your React Vite build and upload it.

Note: Our system will automatically detect your React Vite build structure and serve it correctly.

Submit for Review

After uploading, your game will be marked as "pending_review". Our team will review it to ensure it meets our guidelines.

The review process typically takes 1-2 business days.