Free & open source

Air Jam

Multiplayer games. Phones are the controllers.

Make. Join. Play. Repeat.

The whole point is one loop:
build something playable, get friends in fast, play it together, tweak it, and go again.

01

Make

Start with one command, write your game logic, and let Air Jam handle the room, controllers, and networking.

02

Join

Players scan a QR code or tap a link. Their phone opens the right controller in the browser with no install friction.

03

Play

Inputs hit the big screen in real time, the room comes alive, and the payoff happens immediately.

From Prompt to Playable

A real one-shot build in a minimal Air Jam project.
Claude Code scaffolds the game, opens preview, uses the controllers, and gets to a working result.

Built with Air Jam

Real games you can play right now.
Different genres, different controllers, same instant join.

Everything you need, out of the box

Free public server

No infra to manage. Your game connects to a hosted server automatically -- free for development and production.

Instant QR join

Every room gets a QR code and shareable link. Players join in seconds from any phone browser.

Publish to the Arcade

Ship your game to the Arcade with one command. Players discover and play it instantly.

Built-in analytics

Session counts, player metrics, and performance data from day one. No third-party setup.

Cross-device debugging

Stream logs from every connected phone and the host into one unified view.

First-class agent support

Typed agent contracts let coding agents read state and play your game to verify it works.

airjam.config.ts

One config, two surfaces

Define your input schema once. The host and every controller share the same typed contract.

The docs cover the full host, controller, and store setup.

Read the docs

airjam.config.ts
import { createAirJamApp, env } from "@air-jam/sdk";
import { z } from "zod";

const inputSchema = z.object({
  vector: z.object({ x: z.number(), y: z.number() }),
  action: z.boolean(),
});

export const airjam = createAirJamApp({
  runtime: env.vite(import.meta.env),
  controllerPath: "/controller",
  input: { schema: inputSchema },
});

store.ts

Shared state that just works

Create a store on the host, read it from any phone. Actions go through the host so the source of truth stays in one place.

Full action contract and flow diagrams in the docs.

Read the docs

store.ts
import { createAirJamStore } from "@air-jam/sdk";

export const useGameStore = createAirJamStore((set) => ({
  score: 0,
  actions: {
    addPoint: (_ctx, { delta }) =>
      set((s) => ({ score: s.score + delta })),
  },
}));

const actions = useGameStore.useActions();
const score = useGameStore((s) => s.score);

Who it's for

type AirJam = AirPlay & GameJam;

Developers

Typed APIs, predictable networking, and a clear host/controller model you can reason about.

Tinkerers & vibe-coders

Skip the infrastructure and get to a playable room with friends in minutes.

First-time game makers

Easy to start, no ceiling when you're ready to go deeper.

And of course, for any party of players :)

Ready to build your first game?

Start with the docs, then jump into the arcade to see the kind of thing you can make.