create-airjam 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/dist/index.js +11 -3
  2. package/package.json +6 -3
  3. package/templates/pong/.env.example +11 -0
  4. package/templates/pong/.env.local +10 -0
  5. package/templates/pong/AI_INSTRUCTIONS.md +44 -0
  6. package/templates/pong/README.md +111 -0
  7. package/templates/pong/airjam-docs/getting-started/architecture/page.md +165 -0
  8. package/templates/pong/airjam-docs/getting-started/game-ideas/page.md +114 -0
  9. package/templates/pong/airjam-docs/getting-started/introduction/page.md +122 -0
  10. package/templates/pong/airjam-docs/how-it-works/host-system/page.md +241 -0
  11. package/templates/pong/airjam-docs/sdk/hooks/page.md +403 -0
  12. package/templates/pong/airjam-docs/sdk/input-system/page.md +336 -0
  13. package/templates/pong/airjam-docs/sdk/networked-state/page.md +575 -0
  14. package/templates/pong/dist/assets/index-B9l0NKly.js +269 -0
  15. package/templates/pong/dist/assets/index-CHKqdIQG.css +1 -0
  16. package/templates/pong/dist/index.html +14 -0
  17. package/templates/pong/eslint.config.js +33 -0
  18. package/templates/pong/index.html +6 -1
  19. package/templates/pong/node_modules/.bin/air-jam-server +17 -0
  20. package/templates/pong/node_modules/.bin/eslint +17 -0
  21. package/templates/pong/node_modules/.bin/eslint-config-prettier +17 -0
  22. package/templates/pong/node_modules/.bin/jiti +17 -0
  23. package/templates/pong/node_modules/.bin/tsc +17 -0
  24. package/templates/pong/node_modules/.bin/tsserver +17 -0
  25. package/templates/pong/node_modules/.bin/tsx +17 -0
  26. package/templates/pong/node_modules/.bin/vite +17 -0
  27. package/templates/pong/node_modules/.vite/deps/@air-jam_sdk.js +66143 -0
  28. package/templates/pong/node_modules/.vite/deps/@air-jam_sdk.js.map +7 -0
  29. package/templates/pong/node_modules/.vite/deps/_metadata.json +73 -0
  30. package/templates/pong/node_modules/.vite/deps/chunk-3TUQC5ZT.js +292 -0
  31. package/templates/pong/node_modules/.vite/deps/chunk-3TUQC5ZT.js.map +7 -0
  32. package/templates/pong/node_modules/.vite/deps/chunk-DC5AMYBS.js +38 -0
  33. package/templates/pong/node_modules/.vite/deps/chunk-DC5AMYBS.js.map +7 -0
  34. package/templates/pong/node_modules/.vite/deps/chunk-QUPSG5AV.js +280 -0
  35. package/templates/pong/node_modules/.vite/deps/chunk-QUPSG5AV.js.map +7 -0
  36. package/templates/pong/node_modules/.vite/deps/chunk-TYOCAO5S.js +13810 -0
  37. package/templates/pong/node_modules/.vite/deps/chunk-TYOCAO5S.js.map +7 -0
  38. package/templates/pong/node_modules/.vite/deps/chunk-YG4BJP3V.js +1004 -0
  39. package/templates/pong/node_modules/.vite/deps/chunk-YG4BJP3V.js.map +7 -0
  40. package/templates/pong/node_modules/.vite/deps/package.json +3 -0
  41. package/templates/pong/node_modules/.vite/deps/react-dom.js +6 -0
  42. package/templates/pong/node_modules/.vite/deps/react-dom.js.map +7 -0
  43. package/templates/pong/node_modules/.vite/deps/react-dom_client.js +20217 -0
  44. package/templates/pong/node_modules/.vite/deps/react-dom_client.js.map +7 -0
  45. package/templates/pong/node_modules/.vite/deps/react-router-dom.js +13900 -0
  46. package/templates/pong/node_modules/.vite/deps/react-router-dom.js.map +7 -0
  47. package/templates/pong/node_modules/.vite/deps/react.js +5 -0
  48. package/templates/pong/node_modules/.vite/deps/react.js.map +7 -0
  49. package/templates/pong/node_modules/.vite/deps/react_jsx-dev-runtime.js +278 -0
  50. package/templates/pong/node_modules/.vite/deps/react_jsx-dev-runtime.js.map +7 -0
  51. package/templates/pong/node_modules/.vite/deps/react_jsx-runtime.js +6 -0
  52. package/templates/pong/node_modules/.vite/deps/react_jsx-runtime.js.map +7 -0
  53. package/templates/pong/node_modules/.vite/deps/zod.js +476 -0
  54. package/templates/pong/node_modules/.vite/deps/zod.js.map +7 -0
  55. package/templates/pong/package.json +12 -1
  56. package/templates/pong/src/App.tsx +2 -2
  57. package/templates/pong/src/controller-view.tsx +143 -0
  58. package/templates/pong/src/host-view.tsx +401 -0
  59. package/templates/pong/src/main.tsx +2 -1
  60. package/templates/pong/src/store.ts +80 -0
  61. package/templates/pong/tsconfig.json +3 -2
  62. package/templates/pong/vite.config.ts +3 -0
  63. package/templates/pong/src/ControllerView.tsx +0 -64
  64. package/templates/pong/src/HostView.tsx +0 -148
package/dist/index.js CHANGED
@@ -49,7 +49,12 @@ async function main() {
49
49
  console.log(kleur.cyan(`
50
50
  Creating project in ${targetDir}...
51
51
  `));
52
- await fs.copy(templateDir, targetDir);
52
+ await fs.copy(templateDir, targetDir, {
53
+ filter: (src) => {
54
+ const relativePath = path.relative(templateDir, src);
55
+ return !relativePath.includes("node_modules") && !relativePath.endsWith("pnpm-lock.yaml") && !relativePath.endsWith(".npmrc");
56
+ }
57
+ });
53
58
  const pkgPath = path.join(targetDir, "package.json");
54
59
  if (fs.existsSync(pkgPath)) {
55
60
  const pkg = await fs.readJson(pkgPath);
@@ -59,8 +64,11 @@ Creating project in ${targetDir}...
59
64
  console.log(kleur.green("\u2713 Project created successfully!\n"));
60
65
  console.log("Next steps:\n");
61
66
  console.log(kleur.cyan(` cd ${projectName}`));
62
- console.log(kleur.cyan(" npm install"));
63
- console.log(kleur.cyan(" npm run dev"));
67
+ console.log(kleur.cyan(" pnpm install"));
68
+ console.log(kleur.cyan(" cp env.example .env"));
69
+ console.log(kleur.cyan(" # Edit .env and set AIR_JAM_MASTER_KEY"));
70
+ console.log(kleur.cyan(" pnpm run dev:server # Terminal 1 - Start server"));
71
+ console.log(kleur.cyan(" pnpm run dev # Terminal 2 - Start game"));
64
72
  console.log("");
65
73
  console.log(
66
74
  kleur.dim("Then open http://localhost:5173 and scan the QR code with your phone!")
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-airjam",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "CLI to scaffold Air Jam game projects",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -29,8 +29,10 @@
29
29
  "templates"
30
30
  ],
31
31
  "scripts": {
32
- "build": "tsup",
33
- "dev": "tsup --watch"
32
+ "extract-docs": "tsx scripts/extract-docs.ts",
33
+ "build": "pnpm extract-docs && tsup",
34
+ "dev": "tsup --watch",
35
+ "prepublishOnly": "pnpm build"
34
36
  },
35
37
  "dependencies": {
36
38
  "commander": "^14.0.0",
@@ -42,6 +44,7 @@
42
44
  "@types/fs-extra": "^11.0.4",
43
45
  "@types/prompts": "^2.4.9",
44
46
  "tsup": "^8.5.1",
47
+ "tsx": "^4.19.2",
45
48
  "typescript": "~5.9.3"
46
49
  }
47
50
  }
@@ -0,0 +1,11 @@
1
+ # ============================================================================
2
+ # Game Configuration
3
+ # ============================================================================
4
+ # Server URL - defaults to localhost:4000 in development
5
+ # For production, set to your official Air Jam server URL: wss://api.air-jam.app
6
+ VITE_AIR_JAM_SERVER_URL=http://localhost:4000
7
+
8
+ # API Key - optional for local development (not required when using local server)
9
+ # Required for production - get from Air Jam platform
10
+ VITE_AIR_JAM_API_KEY=
11
+
@@ -0,0 +1,10 @@
1
+ # ============================================================================
2
+ # Game Configuration
3
+ # ============================================================================
4
+ # Server URL - defaults to localhost:4000 in development
5
+ # For production, set to your official Air Jam server URL: wss://api.air-jam.app
6
+ VITE_AIR_JAM_SERVER_URL=http://localhost:4000
7
+
8
+ # API Key - optional for local development (not required when using local server)
9
+ # Required for production - get from Air Jam platform
10
+ VITE_AIR_JAM_API_KEY=aj_live_972f8d8063e5413fa23d2981906d24fe
@@ -0,0 +1,44 @@
1
+ ---
2
+ description: Universal project rules and tech stack standards
3
+ globs: "**/*.ts, **/*.tsx, **/*.js, **/*.jsx, **/*.json"
4
+ alwaysApply: true
5
+ ---
6
+ # Identity & Goals
7
+ - You are a senior frontend architect and full-stack engineer.
8
+ - Focus on modern, type-safe, and functional programming patterns.
9
+ - Prioritize maintainability and strict type safety over brevity.
10
+ - Use airjam-docs for documentation on the Air Jam SDK.
11
+
12
+ # Tech Stack (Strict)
13
+ - **Manager**: pnpm (monorepo structure)
14
+ - **Framework**: React (Frontend), Vite (Build)
15
+ - **Language**: TypeScript (Strict mode)
16
+ - **Styling**: Tailwind CSS + Shadcn UI
17
+ - **State**: Zustand (Global)
18
+
19
+ # Coding Conventions
20
+ - **Naming**:
21
+ - `camelCase` for variables and functions.
22
+ - `PascalCase` for React components and Type definitions.
23
+ - `kebab-case` for all file names (e.g., `user-profile-card.tsx`).
24
+ - **Component Syntax**: Use `const Component = (props: Props) => {}`. Avoid `React.FC`.
25
+ - **Exports**: Use named exports. Do NOT use default exports.
26
+ - **Direct Access**: Do NOT pass props (prop drilling) if data is available via Zustand store or React Context.
27
+
28
+ # Type Safety & Linting & State Management
29
+ - **Zod First**: Define schema validation with Zod before implementing logic.
30
+ - **No Any**: `any` are strictly forbidden. Use generic types or specific interfaces.
31
+ - **TSC**: Code must pass `tsc` check without errors.
32
+ - **JSDoc**: Use JSDoc for utility functions to describe behavior (omit @param/@returns unless complex).
33
+ - **Zustand**: Use atomic selectors when consuming state to prevent unnecessary re-renders.
34
+
35
+ # File Structure & Refactoring
36
+ - **Co-location**:
37
+ - If a component is used only once, keep it in the same file as the parent.
38
+ - If a component is used >1 time, extract to `components/` folder.
39
+ - **Shared Code**: All shared schemas/types must reside in the `packages/shared` workspace.
40
+
41
+ # Agent Behavior
42
+ - **Dependencies**: Always use `pnpm add` to install new packages.
43
+ - **Verification**: Verify file paths before creation. Ensure imports match the `kebab-case` filename convention.
44
+ - **Cleanliness**: Remove unused imports and dead code immediately; do not comment them out.
@@ -0,0 +1,111 @@
1
+ # Air Jam Game Template - Pong
2
+
3
+ A starter template for building multiplayer games with Air Jam. This template includes a simple Pong game that demonstrates the core Air Jam features.
4
+
5
+ ## Getting Started
6
+
7
+ ### Installation
8
+
9
+ 1. Install dependencies:
10
+ ```bash
11
+ pnpm install
12
+ ```
13
+
14
+ 2. Configure environment variables (optional - defaults work for local dev):
15
+ ```bash
16
+ mv .env.example .env.local
17
+ ```
18
+
19
+ Then edit `.env.local` with your settings if needed.
20
+
21
+ ## Local Development
22
+
23
+ ### Option 1: Run Server and Game Separately (Recommended)
24
+
25
+ **Terminal 1 - Start the local server:**
26
+ ```bash
27
+ pnpm run dev:server
28
+ ```
29
+
30
+ The server will start on `http://localhost:4000` in development mode (no authentication required).
31
+
32
+ **Terminal 2 - Start the game:**
33
+ ```bash
34
+ pnpm run dev
35
+ ```
36
+
37
+ The game will be available at `http://localhost:5173` (or the port Vite assigns).
38
+
39
+ ### Option 2: Use the Official Air Jam Server
40
+
41
+ If you prefer to use the official Air Jam server instead of running locally:
42
+
43
+ 1. Get your API key from the [Air Jam Platform](https://air-jam.app)
44
+ 2. Set in `.env.local`:
45
+ ```bash
46
+ VITE_AIR_JAM_SERVER_URL=https://api.air-jam.app
47
+ VITE_AIR_JAM_API_KEY=your-api-key-here
48
+ ```
49
+ 3. Run only the game:
50
+ ```bash
51
+ pnpm run dev
52
+ ```
53
+
54
+ ## Playing the Game
55
+
56
+ 1. Open the game URL in your browser (host view)
57
+ 2. Scan the QR code with your phone to open the controller / open the controller view in your browser
58
+ 3. Use the controller to play Pong!
59
+
60
+ ## Project Structure
61
+
62
+ ```
63
+ src/
64
+ ├── App.tsx # Main app component with routing
65
+ ├── host-view.tsx # Game host view (runs the game)
66
+ ├── controller-view.tsx # Controller view (mobile interface)
67
+ ├── types.ts # Game input schema and types
68
+ ├── store.ts # Shared networked state store
69
+ └── main.tsx # Entry point
70
+ ```
71
+
72
+ ## Environment Variables
73
+
74
+ See `.env.example` for all available environment variables. Key variables:
75
+
76
+ - `VITE_AIR_JAM_SERVER_URL` - Server URL (defaults to localhost:4000 for local dev)
77
+ - `VITE_AIR_JAM_API_KEY` - API key (optional for local dev, required for production)
78
+
79
+ ## Production Deployment
80
+
81
+ ### Deploying to Vercel
82
+
83
+ 1. Set environment variables in Vercel:
84
+ - `VITE_AIR_JAM_SERVER_URL` - Your official Air Jam server URL
85
+ - `VITE_AIR_JAM_API_KEY` - Your API key from the Air Jam platform
86
+
87
+ 2. Deploy:
88
+ ```bash
89
+ vercel
90
+ ```
91
+
92
+ The game will connect to the official Air Jam server - no local server needed!
93
+
94
+ ### Building for Production
95
+
96
+ ```bash
97
+ pnpm run build
98
+ ```
99
+
100
+ The built files will be in the `dist/` directory.
101
+
102
+ ## Learn More
103
+
104
+ - [Air Jam Documentation](https://air-jam.app/docs)
105
+ - [Platform](https://air-jam.app)
106
+ - [Examples](https://github.com/vucinatim/air-jam/tree/main/apps)
107
+
108
+ ## License
109
+
110
+ MIT
111
+
@@ -0,0 +1,165 @@
1
+ # Architecture
2
+
3
+ Air Jam consists of four main components in a monorepo structure. This page explains how they work together to enable multiplayer gaming with smartphone controllers.
4
+
5
+ ## System Overview
6
+
7
+ ## Components
8
+
9
+ ### 1. Platform (`apps/platform`)
10
+
11
+ **Role:** Central hub for the Air Jam ecosystem
12
+
13
+ **Technology:** Next.js 15, TypeScript, tRPC, BetterAuth, PostgreSQL (Drizzle ORM)
14
+
15
+ **Key Features:**
16
+ - **Developer Portal** - Account management, API key generation, analytics
17
+ - **Game Catalog** - Submit, manage, and discover Air Jam games
18
+ - **Arcade Mode** - Browse and launch games from a unified interface
19
+ - **Controller Shell** - Persistent mobile wrapper that loads game controllers
20
+
21
+ **Arcade Mode Flow:**
22
+ ```
23
+ 1. Player scans QR on arcade screen
24
+ 2. Platform loads controller shell on phone
25
+ 3. Player browses games using phone as remote
26
+ 4. Game launches → controller switches to game's joypad
27
+ 5. Game ends → returns to arcade browser
28
+ ```
29
+
30
+ ### 2. Server (`packages/server`)
31
+
32
+ **Role:** Real-time communication backbone
33
+
34
+ **Technology:** Node.js, Express, Socket.IO, PostgreSQL
35
+
36
+ **Core Services:**
37
+
38
+ **Socket Events:**
39
+
40
+ ### 3. SDK (`packages/sdk`)
41
+
42
+ **Role:** Developer toolkit for building Air Jam games
43
+
44
+ **Technology:** React, TypeScript, Socket.IO Client, Zustand, Zod
45
+
46
+ **Architecture:**
47
+
48
+ **Key Design Decisions:**
49
+
50
+ 1. **Provider Pattern** - Single provider for configuration, multiple hooks for access
51
+ 2. **Lightweight Hooks** - `useGetInput`, `useSendSignal` don't trigger re-renders
52
+ 3. **Input Latching** - Ensures rapid button taps are never missed
53
+ 4. **Schema Validation** - Type-safe input with runtime validation
54
+
55
+ ### 4. Prototype Game (`apps/prototype-game`)
56
+
57
+ **Role:** Reference implementation showcasing SDK capabilities
58
+
59
+ **Technology:** React, Vite, React Three Fiber, Rapier Physics
60
+
61
+ **Demonstrates:**
62
+ - Host-side game logic with physics
63
+ - Controller UI with joystick and buttons
64
+ - Player spawning/despawning on join/leave
65
+ - Haptic feedback on collisions
66
+ - Multiple game modes (CTF, survival)
67
+
68
+ ## Run Modes
69
+
70
+ The SDK automatically detects and adapts to different deployment scenarios:
71
+
72
+ ### Standalone Mode
73
+
74
+ Your game runs independently with direct WebSocket connection.
75
+
76
+ ```
77
+ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐
78
+ │ Your Game │◀───▶│ AirJam │◀───▶│ Controller │
79
+ │ (Host) │ │ Server │ │ (Phone) │
80
+ └──────────────┘ └──────────────┘ └──────────────┘
81
+ ```
82
+
83
+ **Use case:** Self-hosted games, development, custom deployments
84
+
85
+ ### Arcade Mode
86
+
87
+ Game runs inside an iframe on the Air Jam Platform.
88
+
89
+ ```
90
+ ┌─────────────────────────────────────────┐
91
+ │ Air Jam Platform (Parent) │
92
+ │ ┌───────────────────────────────────┐ │
93
+ │ │ Your Game (iframe) │ │
94
+ │ │ • Receives join token │ │
95
+ │ │ • Controlled player routing │ │
96
+ │ └───────────────────────────────────┘ │
97
+ └─────────────────────────────────────────┘
98
+ ```
99
+
100
+ **Use case:** Featured on Air Jam arcade, game discovery
101
+
102
+ ### Bridge Mode
103
+
104
+ Controller runs inside platform's shell (iframe communication).
105
+
106
+ ```
107
+ ┌─────────────────────────────────────────┐
108
+ │ Platform Controller Shell (Parent) │
109
+ │ ┌───────────────────────────────────┐ │
110
+ │ │ Your Controller UI (iframe) │ │
111
+ │ │ • Input via postMessage │ │
112
+ │ │ • Seamless game switching │ │
113
+ │ └───────────────────────────────────┘ │
114
+ └─────────────────────────────────────────┘
115
+ ```
116
+
117
+ **Use case:** Arcade mode controllers, persistent session
118
+
119
+ ## Data Flow
120
+
121
+ ### Input Path (Controller → Game)
122
+
123
+ ```
124
+ 1. Player moves joystick on phone
125
+ 2. Controller calls sendInput({ vector: {x, y}, action: false })
126
+ 3. SDK sends controller:input event to server
127
+ 4. Server routes to host socket
128
+ 5. Host SDK's InputManager receives input
129
+ 6. InputManager validates with Zod schema
130
+ 7. InputManager applies latching if configured
131
+ 8. Game calls getInput(playerId) in game loop
132
+ 9. Returns typed, validated, latched input
133
+ ```
134
+
135
+ ### Signal Path (Game → Controller)
136
+
137
+ ```
138
+ 1. Game detects collision
139
+ 2. Host calls sendSignal("HAPTIC", { pattern: "heavy" }, playerId)
140
+ 3. SDK sends host:signal event to server
141
+ 4. Server routes to target controller(s)
142
+ 5. Controller SDK receives signal
143
+ 6. SDK triggers navigator.vibrate() with pattern
144
+ 7. Player feels haptic feedback
145
+ ```
146
+
147
+ ## Security
148
+
149
+ ### API Key Authentication
150
+
151
+ - Games must provide valid API key for production
152
+ - Keys are validated against platform database
153
+ - Rate limiting prevents abuse
154
+
155
+ ### Room Isolation
156
+
157
+ - Each room has unique 4-character code
158
+ - Controllers can only join with correct code
159
+ - Input is only routed to the designated host
160
+
161
+ ### Input Validation
162
+
163
+ - Zod schemas validate all incoming input
164
+ - Invalid input is rejected with console warning
165
+ - Protects game logic from malformed data
@@ -0,0 +1,114 @@
1
+ # Game Ideas for Air Jam
2
+
3
+ A collection of game concepts that leverage Air Jam's unique architecture: **High-Frequency Input Streams** (Socket.IO) + **Reliable Shared State** (AirJam Store).
4
+
5
+ ---
6
+
7
+ ## Tier 1: Arcade Classics (Easy)
8
+
9
+ ### Neon Tanks
10
+
11
+ - Top-down arena shooter (4-8 players)
12
+ - Dual stick controls: movement + turret aiming
13
+ - Tap to fire
14
+ - **Key Feature:** Demonstrates dual stick capability on touchscreen
15
+
16
+ ### Super Sumo Balls
17
+
18
+ - Rolling balls on tilting platform
19
+ - Use phone gyroscope/accelerometer to tilt
20
+ - Haptic feedback on collisions
21
+ - **Key Feature:** Phone sensors + haptic signals
22
+
23
+ ---
24
+
25
+ ## Tier 2: Party & Social Games (Medium)
26
+
27
+ ### The Traitor (Among Us style)
28
+
29
+ - 8 players: 6 crew, 2 traitors
30
+ - Hidden roles shown only on phone
31
+ - Task minigames on controller
32
+ - Voting UI on phone
33
+ - **Key Feature:** Secret information per player (killer app for phone controllers)
34
+
35
+ ### Sketchy Business (Pictionary style)
36
+
37
+ - Draw prompts on phone canvas
38
+ - Drawings appear on TV
39
+ - **Key Feature:** Touchscreen as natural drawing pad
40
+
41
+ ### Quiz Show Royale
42
+
43
+ - Fastest finger first trivia
44
+ - Personalized feedback (green/red + vibration)
45
+ - **Key Feature:** Input timestamping for speed
46
+
47
+ ---
48
+
49
+ ## Tier 3: Co-op Chaos (Medium-Hard)
50
+
51
+ ### Starship Bridge Simulator
52
+
53
+ - 4 players with different roles
54
+ - Each player gets different UI on phone
55
+ - Asymmetrical gameplay
56
+ - **Key Feature:** Different React components per controller
57
+
58
+ ### Ghost Hunter
59
+
60
+ - 1 vs 3 asymmetrical gameplay
61
+ - Ghost sees minimap on phone only
62
+ - Hunters use joysticks on TV
63
+ - **Key Feature:** Private screen advantage
64
+
65
+ ---
66
+
67
+ ## Tier 4: Strategy & Card Games (Hard)
68
+
69
+ ### Poker Night / Blackjack
70
+
71
+ - Private cards on phone
72
+ - Betting UI on phone
73
+ - Public table on TV
74
+ - **Key Feature:** Hidden information per player
75
+
76
+ ### Artillery Wars (Worms style)
77
+
78
+ - Turn-based tank battle
79
+ - Aiming interface on phone (angle/power sliders)
80
+ - Weapon selection on phone
81
+ - **Key Feature:** Complex menus on touchscreen
82
+
83
+ ---
84
+
85
+ ## Tier 5: Experimental (Advanced)
86
+
87
+ ### The Crowd Pixel (r/place style)
88
+
89
+ - 50+ players
90
+ - Each controls a pixel/cursor
91
+ - Collaborative painting
92
+ - **Key Feature:** Tests scalability
93
+
94
+ ### Minority Report UI
95
+
96
+ - Phone as trackpad
97
+ - Gesture controls
98
+ - **Key Feature:** Phone as input device
99
+
100
+ ---
101
+
102
+ ## Key Mechanics Enabled
103
+
104
+ ```
105
+ | Mechanic | Example | Technical Feature |
106
+ |-------------------|-------------------|-----------------------------------------|
107
+ | Secret Roles | Mafia / Traitor | `useSharedState` (filter by `playerId`) |
108
+ | Private Inventory | RPG / Poker | Shared Store + React UI on Phone |
109
+ | Motion Steering | Racing / Rolling | Device Accelerometer → Input Stream |
110
+ | Fastest Finger | Quiz Show | Input Latching (Timestamps) |
111
+ | Physical Feedback | Fighting / Action | `host.sendSignal("HAPTIC")` |
112
+ | Drawing | Pictionary | Canvas API + Data Packet |
113
+ | Asymmetry | Ghost Hunter | Different Views per Role |
114
+ ```
@@ -0,0 +1,122 @@
1
+ # Introduction
2
+
3
+ Air Jam is a platform for building **"AirConsole-style" multiplayer games** where a computer/TV acts as the host display and smartphones become game controllers. The platform enables developers to create interactive games with minimal setup while providing players with an intuitive, scan-and-play experience.
4
+
5
+ ## Key Features
6
+
7
+ - **Zero App Download**: Players join by scanning a QR code—no app store required
8
+ - **Instant Multiplayer**: Seamlessly connect up to 8 smartphones as controllers
9
+ - **Developer Friendly**: Built with modern web technologies (React, TypeScript)
10
+ - **Type Safe**: End-to-end type safety with Zod schema validation
11
+ - **Performance Optimized**: Latching system ensures no input is ever missed
12
+ - **Haptic Feedback**: Send vibration patterns to controllers for game events
13
+
14
+ ## How It Works
15
+
16
+ ## Quick Start
17
+
18
+ ### 1. Install the SDK
19
+
20
+ ```bash
21
+ pnpm add @air-jam/sdk
22
+ ```
23
+
24
+ ### 2. Wrap Your App
25
+
26
+ ```tsx filename="src/App.tsx"
27
+ import { AirJamProvider } from "@air-jam/sdk";
28
+ import { z } from "zod";
29
+
30
+ // Define your input schema
31
+ const gameInputSchema = z.object({
32
+ vector: z.object({ x: z.number(), y: z.number() }),
33
+ action: z.boolean(),
34
+ ability: z.boolean(),
35
+ timestamp: z.number(),
36
+ });
37
+
38
+ export const App = () => (
39
+ <AirJamProvider
40
+ input={{
41
+ schema: gameInputSchema,
42
+ latch: {
43
+ booleanFields: ["action", "ability"],
44
+ vectorFields: ["vector"],
45
+ },
46
+ }}
47
+ >
48
+ <Routes>
49
+ <Route path="/" element={<HostView />} />
50
+ <Route path="/joypad" element={<ControllerView />} />
51
+ </Routes>
52
+ </AirJamProvider>
53
+ );
54
+ ```
55
+
56
+ ### 3. Create Your Host View
57
+
58
+ ```tsx filename="src/components/HostView.tsx"
59
+ import { useAirJamHost } from "@air-jam/sdk";
60
+ import { QRCode } from "./QRCode";
61
+
62
+ const HostView = () => {
63
+ const host = useAirJamHost({
64
+ onPlayerJoin: (player) => {
65
+ console.log(`${player.label} joined!`);
66
+ spawnPlayer(player.id, player.color);
67
+ },
68
+ onPlayerLeave: (id) => {
69
+ console.log(`Player ${id} left`);
70
+ removePlayer(id);
71
+ },
72
+ });
73
+
74
+ return (
75
+ <div>
76
+ <h1>Room: {host.roomId}</h1>
77
+ <QRCode value={host.joinUrl} />
78
+ <p>Players: {host.players.length}</p>
79
+
80
+ {/* Your game canvas */}
81
+ <GameCanvas players={host.players} getInput={host.getInput} />
82
+ </div>
83
+ );
84
+ };
85
+ ```
86
+
87
+ ### 4. Create Your Controller View
88
+
89
+ ```tsx filename="src/components/ControllerView.tsx"
90
+ import { useAirJamController } from "@air-jam/sdk";
91
+ import { Joystick, Button } from "./ui";
92
+
93
+ const ControllerView = () => {
94
+ const controller = useAirJamController();
95
+
96
+ const handleInput = (vector: { x: number; y: number }, action: boolean) => {
97
+ controller.sendInput({
98
+ vector,
99
+ action,
100
+ ability: false,
101
+ timestamp: Date.now(),
102
+ });
103
+ };
104
+
105
+ if (controller.connectionStatus !== "connected") {
106
+ return <div>Connecting to room {controller.roomId}...</div>;
107
+ }
108
+
109
+ return (
110
+ <div>
111
+ <Joystick onMove={(x, y) => handleInput({ x, y }, false)} />
112
+ <Button onPress={() => handleInput({ x: 0, y: 0 }, true)}>Fire</Button>
113
+ </div>
114
+ );
115
+ };
116
+ ```
117
+
118
+ ## Next Steps
119
+
120
+ - [Architecture](/docs/getting-started/architecture) - Understand the system design
121
+ - [Hooks Reference](/docs/sdk/hooks) - Complete API documentation
122
+ - [Input System](/docs/sdk/input-system) - Learn about latching and validation