@puzzmo/sdk
v1.0.14
Published
Puzzmo runtime SDK for game developers
Readme
Puzzmo Game Infra
Over the years we have a pretty refined route for making web games: prototype in HTML with no concern for code quality, share with people you like, then migrate it to a "real" codebase.
LLMs have changed this, and we're finding that the 'prototype in HTML' phase is getting close enough to production quality that it does not always warrant a a multi-month conversion to React/TypeScript/Redux to ensure the codebase can live forever.
So, after shipping two full games with this pipeline, we've knocked enough kinks out that it's ready for a more public space.
So, how do you make a game? Well first, you need a game - we can't help there! However, once you do, then you can start migrating it to run on Puzzmo by: yarn create puzzmo game.
@puzzmo/sdk
This repo is the SDK for building games on the Puzzmo platform. Handles communication between your game and Puzzmo.
There are a few parts here!
- The SDK, e.g. the runtime API for launching a game, completing it and other essentials
- The simulator, which provides the same message sending infrastructure Puzzmo.com will send to your game
- App integration information, e.g. how to make custom thumbnails for your puzzles (and more)
- Vite plugins which can help you get up and running faster
Install
npm install @puzzmo/sdk
yarn add @puzzmo/sdkQuick Start
import { createPuzzmoSDK } from "@puzzmo/sdk"
const sdk = createPuzzmoSDK()
// 1. Wait for puzzle data from Puzzmo
const { puzzleString, inputString, theme, completed } = await sdk.gameReady()
// 2. Set up your game with the puzzle data
const puzzle = JSON.parse(puzzleString)
initializeGame(puzzle)
if (inputString) restoreState(inputString)
// 3. Signal that you're ready
sdk.gameLoaded()
// 4. Listen for lifecycle events
sdk.on("start", () => startGameLoop())
sdk.on("pause", () => pauseGameLoop())
sdk.on("resume", () => resumeGameLoop())
sdk.on("retry", () => resetGame())API
createPuzzmoSDK(options?)
Creates an SDK instance. Options:
timeout- Timeout in ms waiting for puzzle data (default: 5000)
Lifecycle
| Method | Description |
| ------------------------- | ------------------------------------------------------------------------- |
| sdk.gameReady() | Async. Signals readiness, returns puzzle data and theme. |
| sdk.gameLoaded(state?) | Signals game UI is ready. Host will send start. |
| sdk.on(event, handler) | Listen for events: start, pause, resume, retry, settingsUpdate. |
| sdk.off(event, handler) | Remove an event listener. |
Game State
| Method | Description |
| --------------------------------------------------------- | ---------------------------------------------------- |
| sdk.updateGameState(stateString, play?) | Save current game state for persistence. |
| sdk.gameCompleted(play, config?) | Signal game completion with metrics and deeds. |
| sdk.showCompletionScreen(results, gameplay, showRetry?) | Show the Puzzmo completion UI. |
| sdk.hitCheckpoint(name, config, augConfig?) | Signal a gameplay milestone (for ads, leaderboards). |
Timer
The SDK manages a timer automatically (starts on start, pauses on pause, resets on retry).
sdk.timer.timeMs() // Elapsed time in ms
sdk.timer.timeSecs() // Elapsed time in seconds
sdk.timer.display() // ["1:23", "0:05"] (elapsed, penalty)
sdk.timer.addPenalty(5000) // Add 5s penalty
sdk.timer.isPaused() // Check if paused
sdk.timer.isRunning() // Check if runningTheme
The theme object from gameReady() contains color tokens for the current Puzzmo theme:
const { theme } = await sdk.gameReady()
// Key colors
theme.g_bg // Game background
theme.fg // Foreground text
theme.key // Primary accent
theme.player // Player color (blue)
theme.alt1 // Accent green
theme.alt2 // Accent yellow
theme.alt3 // Accent purple
theme.type // "light" or "dark"See the Theme type export for the full list of tokens.
Deeds
Deeds are gameplay statistics sent on completion:
sdk.gameCompleted(metrics, {
deeds: [
{ id: "moves", value: 42 },
{ id: "accuracy", value: 95 },
{ id: "hit-streak", value: 8 },
],
})The SDK automatically adds points and time deeds.
On-Screen Keyboard
For games that need text input on touch devices, the SDK can show Puzzmo's on-screen keyboard. The keyboard is only visible on touch devices — calling these methods on desktop is a no-op.
import { createPuzzmoSDK, defaultKeyboardConfig } from "@puzzmo/sdk"
const sdk = createPuzzmoSDK()
// Show the keyboard when the player selects an input
sdk.keyboard.show(defaultKeyboardConfig)
// Listen for key presses
sdk.on("keyboardKeyPress", ({ key }) => {
if (key === "⌫") handleBackspace()
else if (key === "↵") handleEnter()
else handleLetter(key)
})
// Hide when input is dismissed
sdk.keyboard.hide()defaultKeyboardConfig is a standard QWERTY layout with Enter and Backspace. Customize it by spreading:
// Disable letters that are no longer valid given the current game state
sdk.keyboard.show({ ...defaultKeyboardConfig, disabled: usedLetters })For games with a spatial input model (e.g. selecting a grid cell by dragging across the keyboard), enable drag cursor support and listen for the additional events:
sdk.keyboard.show({ ...defaultKeyboardConfig, supportsDragCursor: true })
sdk.on("keyboardCursorChange", ({ position }) => highlightCellAtPosition(position))
sdk.on("keyboardCursorEnd", () => confirmCellSelection())See the KeyboardConfig type export and the add-keyboard-support skill for full field documentation.
App Integration
For games to show a dynamic thumbnail, you will need an App Bundle
import type { EditorBundle, ValidationReport } from "@puzzmo/sdk"
import { puzzleToSVG } from "./src/puzzleToSVG"
export const AppBundle = {
renderThumbnail(puzzleString, inputString, config) {
return puzzleToSVG(puzzleString, inputString, config)
},
} satisfies EditorBundleThis and the editor bundle are separate JavaScript files from your main game.
There are Vite plugins to make this easy, but otherwise, they should be files in your upload named app-bundle.js and editor-bundle.js with ESM exports which match the shapes of the TypeScript types.
Editor Integration
For games that support puzzle editing in Puzzmo Workshop, you will need an Editor Bundle:
import type { EditorBundle, ValidationReport } from "@puzzmo/sdk"
export const validator = {
validate(data) {
return { success: true, issues: [] }
},
} satisfies EditorBundle