0
/devs documentation v0.0.1-beta Getting started

SDK · v0.0.1-beta

Getting started

Esqueleto mínimo de juego con el SDK Jugafy en 50 líneas

Quickstart. Ponés esto en un index.html, lo zipeás, lo subís via /devs → tenés un juego con tracking + leaderboard + storage funcionando.

Esqueleto mínimo

<!doctype html>
<html lang="es">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover">
  <meta name="theme-color" content="#0a0118">
  <title>Mi juego</title>
  <style>
    html, body { margin: 0; padding: 0; height: 100%; background: #0a0118; color: #fff;
                 font-family: system-ui, sans-serif; overscroll-behavior: none; }
    #stage { display: grid; place-items: center; height: 100vh; }
    button { padding: 12px 24px; font-size: 18px; cursor: pointer; }
  </style>
</head>
<body>
  <div id="stage">
    <div>
      <h1 id="score">Score: 0</h1>
      <button id="bump">+1</button>
      <button id="finish">Game over</button>
    </div>
  </div>

  <!-- 1. Slug del juego ANTES del SDK. -->
  <script>window.NEON_GAME = "mi-juego";</script>

  <!-- 2. Importar el SDK. -->
  <script type="module">
    import {
      storage,
      track,
      submitScore,
      ensurePlayerName,
    } from "https://jugafy.com/sdk/v0.0.1-beta/jugafy.js";

    // 3. Esperar al storage (importante en sandbox).
    await storage.ready();

    // 4. Cargar progreso si lo había.
    let score = storage.get("highscore") ?? 0;
    document.getElementById("score").textContent = `Score: ${score}`;

    track("session_start"); // ya lo dispara el SDK al boot, pero podés re-emitir custom

    // 5. Loop de juego (mock — un botón que suma).
    document.getElementById("bump").addEventListener("click", () => {
      score++;
      document.getElementById("score").textContent = `Score: ${score}`;
      track("score_bump", { score });
    });

    // 6. Game over: ensurar nick → submit al leaderboard → guardar highscore.
    document.getElementById("finish").addEventListener("click", async () => {
      const name = await ensurePlayerName(); // muestra modal si es la 1ra vez
      try {
        await submitScore(window.NEON_GAME, name, score);
        track(`${window.NEON_GAME}_run_ended`, { score });
        storage.set("highscore", Math.max(storage.get("highscore") ?? 0, score));
        alert(`Score ${score} submited al leaderboard.`);
      } catch (err) {
        alert(`Error submit: ${err.code || err.message}`);
      }
    });
  </script>
</body>
</html>

Qué hace este esqueleto

  • Tracking dualsession_start, score_bump, <slug>_run_ended van a GA4 + tabla events del backend.
  • Modal de nickname la 1ra vez que el user hace game over. Cross-game: si jugó otro juego de Jugafy antes, ya lo recordamos (no se repite el modal).
  • Score submit al leaderboard global de tu juego. El backend dedupea por name (1 row por player por juego, mejor score gana).
  • Storage del highscore — sobrevive reload, namespaced por slug (no choca con otros juegos).
  • Auto-bridge al parent — la plataforma detecta <slug>_run_ended y dispara el modal “no pierdas tu progreso” si el user no está logueado.

Workflow recomendado

1. Desarrollo local

# en tu carpeta del juego
python3 -m http.server 8000
# o vite, serve, busybox httpd, etc

Abrí http://localhost:8000. El SDK detecta same-origin → todo funciona normal con localStorage del browser.

2. Subir a /devs

  • Empacá el ZIP. Dos formatos aceptados (ambos andan):

    # Formato A — archivos sueltos en root del ZIP
    mi-juego.zip
      ├── index.html
      ├── game.js
      └── assets/
          └── sprite.png
    
    # Formato B — todo dentro de una carpeta única
    mi-juego.zip
      └── mi-juego/
          ├── index.html
          ├── game.js
          └── assets/
              └── sprite.png

    El formato B es lo que sale del right-click → “Comprimir” sobre la carpeta del juego en Mac/Windows. El sistema detecta el common root folder y lo strippea automáticamente. No tenés que pensarlo — comprimí como te resulte natural.

  • Logueate en https://jugafy.com/devs y “Subir nuevo juego”.

  • Slug, título, categoría, descripción. Thumbnail opcional (recomendado: 600×900 PNG/JPG).

3. Probar pre-approve

En /devs, fila del juego pending: botón “Probar” abre un modal con el iframe sandboxed real. Validá que el juego carga y que el progreso se persiste entre opens del modal.

4. Aprobar / re-publish

  • Owner: aprueba → Vercel rebuilds → ruta pública /<categoría>/<slug> viva en ~60-90s.
  • Subir nueva versión: en /devs, fila del juego, botón “Editar” → file input “Nuevo bundle ZIP”. El status vuelve a pending, hay que re-aprobar. La versión vieja queda viva en prod hasta que el rebuild ship la nueva.

Errores comunes

Jugafy.storage.set no persiste post-reload

  • Confirmá window.NEON_GAME está seteado antes del import.
  • En consola: NeonArcade.storage.mode debería decir same-origin (dev local) o sandboxed-bridge (prod en Jugafy).
  • En prod, confirmá que host.js cargó: window.JugafyHost?.version en consola del parent (jugafy.com, no del iframe) debería decir "v0.0.1-beta".

submitScore 401 / 403

  • name requerido — ensurePlayerName() antes resuelve esto.
  • Si tu user está en una sesión Supabase muy vieja, el backend puede rechazar el token. Logueate de nuevo en jugafy.com.

track() parece no enviar nada

  • Es fire-and-forget. No tira errores. Para verificar: abrí DevTools → Network → filtrá por track-event. Si no ves requests, probablemente window.NEON_GAME no está seteado o un ad-blocker está cortando.

El juego anda local pero no en prod

Diferencia más común: localStorage directo en lugar de Jugafy.storage. En sandbox prod, localStorage tira SecurityError. Migrate: ver storage.

Próximos pasos

  • Player identity — cómo manejar el nickname y la identidad anon entre runs.
  • Tracking — eventos estándar (session_start, *_run_started, *_run_ended) + el aggregator pattern.
  • ScoressubmitScore con extras (level, duration_ms), getTopScores con scope diario, persistRun para URLs compartibles.
  • Storage — API completa + caveats del sandbox.

Ingresá a Jugafy

Guardá tus scores, subí al leaderboard y sincronizá progreso entre dispositivos.

Contanos

Bug, idea, crítica — todo nos sirve para hacer esto mejor.