SDK para juegos web HTML/JS que viven en la plataforma Jugafy. Da tracking, leaderboards, persistencia de progreso, identidad del jugador, feedback widget y UI chrome compartido. Sin build step — un <script type="module"> que importa lo que necesitás.
Versión actual:
v0.0.1-beta. La API puede cambiar antes dev1.0.0. Los uploads ya servidos quedan apuntando a su versión — no rompemos lo que ya está en prod.
Cómo importar el SDK
Desde un upload servido por Jugafy
Tu juego se sirve desde https://jugafy.com/games-bundle/<tu-slug>/index.html. Importás same-origin con path absoluto:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Mi juego</title>
</head>
<body>
<canvas id="game"></canvas>
<!-- Importante: declarar NEON_GAME ANTES del SDK. Es el slug del juego.
El SDK lo usa para namespacing de storage, tracking y leaderboards. -->
<script>window.NEON_GAME = "tu-slug";</script>
<script type="module">
import { storage, track, submitScore } from "/sdk/v0.0.1-beta/jugafy.js";
await storage.ready();
track("game_loaded");
// ... tu código
</script>
</body>
</html>
Desde dev local
Mientras corrés tu juego en localhost:8000, vite dev, lo que sea — usá la URL absoluta:
<script type="module">
import { storage, track } from "https://jugafy.com/sdk/v0.0.1-beta/jugafy.js";
// El SDK detecta same-origin (no estás en iframe sandboxed) y usa
// localStorage directo. Mismo código andaría sin cambios cuando subas.
</script>
CORS habilitado (Access-Control-Allow-Origin: *) en el archivo del SDK. Funciona desde cualquier dominio.
Como global (sin import)
Si preferís no usar ES modules, después de cargar el SDK queda colgado en window.NeonArcade:
<script type="module" src="https://jugafy.com/sdk/v0.0.1-beta/jugafy.js"></script>
<script>
window.NeonArcade.track("custom_event", { foo: 1 });
window.NeonArcade.storage.set("level", 5);
</script>
El nombre NeonArcade quedó por compatibilidad histórica (rebrand del 2026-04-22 a Jugafy mantuvo la API).
Convenciones globales
window.NEON_GAME antes del import
<script>window.NEON_GAME = "mi-juego";</script>
<script type="module" src="...jugafy.js"></script>
El SDK lo usa para:
- Tracking —
event.gameen cadatrack()lleva este valor. - Storage — namespace de
Jugafy.storage(jugafy:store:<game>:<key>). - Bridge iframe→parent — el evento
na:game-endedque dispara el modal “no pierdas tu progreso” lleva el slug.
Si no está seteado, track() es no-op y storage cae a slug _anon. No omitir.
Slug rules
[a-z0-9-]{2,32}— minúsculas, dígitos, guion. 2-32 chars.- Único en la plataforma — el upload lo valida.
- No cambia post-aprobación. Si querés rebrand, subís uno nuevo con otro slug y rejectás el viejo.
Sandbox del iframe
Cuando tu juego se sirve desde Jugafy en /games-bundle/<slug>/, el iframe tiene sandbox="allow-scripts allow-pointer-lock allow-orientation-lock" — sin allow-same-origin. Implicaciones:
localStoragedirecto del juego falla conSecurityError. Usá storage.parent.foootop.footiraSecurityError. No accedas al window padre.document.cookieno funciona.postMessageal parent funciona — el SDK ya bridgea los eventos terminales.- APIs estándar (Canvas, Audio, RAF, IndexedDB, fullscreen) funcionan.
- Fetch a
https://*.supabase.coyhttps://jugafy.comfunciona — son los hosts trusted del SDK.
En dev local (cuando corrés el juego standalone), el iframe NO está sandboxed y todo lo de arriba funciona normal. Por eso un código que funciona local puede romper en prod si depende de cosas bloqueadas en sandbox. Testeá siempre el bundle subido vía el botón “Probar” en /devs antes de aprobar.
Scan estático del bundle
Cuando subís un ZIP, el edge upload-game corre regex sobre tu HTML/JS para flaggear patterns sospechosos (eval, document.cookie, parent.*, fetch a hosts no-trusted, etc). Los resultados aparecen en /devs junto al row del juego. No bloquea el upload — sólo asiste el review humano.
Si tu juego usa algún pattern flageado por buena razón, no pasa nada — el owner ve el flag al revisar y decide.
API reference rápida
Storage
storage.ready()/storage.set(k,v)/storage.get(k)/storage.remove(k)/storage.clear()/storage.keys()/storage.mode/storage.slug. → storage
Tracking
track(name, params?)→ tracking
Scores
submitScore(game, name, score, durationMs?, extras?)/getTopScores(game, limit?, opts?)/persistRun(game, opts)→ scores
Player
getPlayerName()/setPlayerName(name)/ensurePlayerName()/sanitizeName(raw)→ player
UI chrome
mountFeedbackWidget()/submitFeedback(payload)/mountTopBar(name, slug)/mountDiscordFooter(target, opts?)/mountLangToggle(target)
i18n
t(key)/getLang()/setLang(lang)/onLangChange(fn)/applyI18nTo(root)/SUPPORTED_LANGS
Constantes
JUGAFY_SDK_VERSION/DISCORD_URL
Roadmap
- Cross-device sync de storage (tabla
game_progressserver-side) — gated a 5+ devs activos con users logueados sosteniendo progreso. - Publicación a npm + jsdelivr (
@jugafy/sdk@0.0.1) — gated al mismo número. - TypeScript types — hoy el SDK es JS plano. Si hay demanda en Discord, sale.
v1.0.0API freeze — cuando 3+ devs externos hayan shippeado a prod sin issues por el SDK.
¿Falta algo? Tirá feedback en #feedback-sdk del Discord (link en el SDK via mountFeedbackWidget).