Build first. Upload second. Submit scores with a simple API.
EmilyGaming uses a simple API for global scores. Download the starter template before you upload, wire in your game slug, then submit the final score when a run ends.
Start with template
Download the starter ZIP and plug in your slug.
Upload ZIP
Include index.html and all required assets.
Submit final score
Use the API once at game over.
Starter Template
This is the recommended starting point for new EmilyGaming integrations. Enter your game slug and the template will be configured for you automatically before download.
Best use
- โข Download this before building your game
- โข Replace the sample code with your real gameplay
- โข Keep the score submit call at real game over
Whatโs inside
starter-game/ โโโ index.html โโโ game.js โโโ README.txt
Global Score API
Use the same route for score submission and leaderboard loading.
Submit score
await fetch('/api/games/YOUR-GAME-SLUG/scores', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: 'Bearer ' + localStorage.getItem('emilygamingUserToken')
},
credentials: 'include',
body: JSON.stringify({
score: finalScore
})
});
Get leaderboard
const res = await fetch('/api/games/YOUR-GAME-SLUG/scores', {
credentials: 'include'
});
const scores = await res.json();
Submit only once
let submitted = false;
async function endGame(score) {
if (submitted) return;
submitted = true;
await submitScore(score);
}
Realtime Multiplayer Standard
All future multiplayer games should use the same SDK and flow: login required, game-specific room key, Create Room, share code, Join Room.
Platform flow
- Player A logs in and clicks Create Room.
- Game gets a real room code from the server room contract.
- Player A shares the code or share link.
- Player B logs in and joins with that same room code.
- Both players are inside the same realtime room instance.
Load the SDK in your game
<script src="/js/emilygaming-multiplayer-sdk.js"></script>
<script>
const mp = EmilyGamingMultiplayer.createClient({
endpoint: "https://rt.emilygaming.com",
gameKey: "your-game-slug",
roomName: "game_room",
maxClients: 8
});
</script>
Create room and join room
// Host
const created = await mp.createRoom({ username: "HostPlayer" });
console.log("Room code:", created.roomCode);
// Friend
await mp.joinRoom("AB12CD", { username: "GuestPlayer" });
Realtime events
mp.on("presence", (msg) => console.log("presence", msg));
mp.on("input", (msg) => applyRemoteInput(msg));
mp.on("event", (msg) => applyRemoteEvent(msg));
mp.on("state", (msg) => hydrateSnapshot(msg.payload));
mp.sendInput({ moveX: 1, fire: false });
mp.sendEvent("ability", { id: "dash", at: performance.now() });
Game ZIP Requirements
Package your game like a clean browser app so EmilyGaming can extract and serve it correctly.
Required
- โข A main index.html file
- โข All CSS, JS, image, and audio assets inside the ZIP
- โข A browser-playable HTML game
Recommended
- โข Keep every path relative
- โข Include a thumbnail image
- โข Add instructions and controls
my-game.zip โโโ index.html โโโ css/ โ โโโ style.css โโโ js/ โ โโโ game.js โโโ assets/ โ โโโ images/ โ โโโ audio/ โโโ README.txt
Best Practices
Do
- โข Start from the template before upload
- โข Submit score only when the round is really over
- โข Use integers for scores
- โข Keep file paths relative
- โข Test while logged in
Avoid
- โข Downloading the template after upload
- โข Posting a score every frame
- โข Using floating point score values
- โข Depending on absolute file paths
- โข Submitting multiple times per run