solution:
metadata:
id: agycade
title: "Antigravity Arcade: from prompt to real game in minutes"
description: Explore how Antigravity and AI skills can generate web games in minutes with best practices skills and deployment workflows to an online games portal powered by Firebase and Google Cloud.
fallbackCta:
title: Download Antigravity
icon: antigravity
url: https://antigravity.google/
githubCta:
url: https://github.com/GoogleCloudPlatform/devrel-demos/tree/main/other/antigravity-arcade
accentColor:
foreground: "white"
background: "#141e2a"
compactUI: true
code:
assetsPath: external-assets/agycade/
remotePath: https://github.com/GoogleCloudPlatform/devrel-demos/tree/main/other/antigravity-arcade/
sections:
- type: watch
youtubeId: 8I7wr2hYFec
title: "Antigravity Arcade: from prompt to real game in minutes"
description: Explore how Antigravity and AI skills can generate web games in minutes with best practices skills and deployment workflows to an online games portal powered by Firebase and Google Cloud.
technologies:
- icon: /external-assets/antigravity.png
label: Antigravity
url: https://antigravity.google/
- icon: /external-assets/cloud-run.svg
label: Cloud Run
url: https://cloud.google.com/run
- icon: /external-assets/cloud-functions.png
label: Cloud Run Functions
url: https://cloud.google.com/functions
- icon: /external-assets/firebase-auth.svg
label: Firebase Authentication
url: https://firebase.google.com/docs/auth
- icon: /external-assets/firebase-firestore.svg
label: Cloud Firestore
url: https://firebase.google.com/docs/firestore
- icon: /external-assets/cloud-storage.svg
label: Cloud Storage
url: https://cloud.google.com/storage
- type: explore
mode: video
timeline: dark
subsections:
- id: example-games
title: Game Montage
description: |
Watch a video montage of premade retro arcade games created with Antigravity skills. The montage demonstrates specialized AI game design sub-skills across Space Shooter, Gravity Platformer, and Survivor Arcade.
videoPath: external-assets/agycade/game-montage.mp4
orientation: landscape
frame: none
layout: aboveandbelow
logs:
- timestamp: 100
summary: Game Quality Skill used for ambient space particles feature
detail: Antigravity retrieves the Game Quality skill to initialize ambient space particle effects in the Space Shooter game.
sequence:
- antigravity
- fun-skills
inspect: fun-skills/fun-skills-0
- timestamp: 1200
summary: User Input Skill used for space ship movement and firing lasers
detail: Antigravity handles keyboard and Gamepad API inputs to control space ship movement and fire laser weapons.
sequence:
- antigravity
- input-output-skills
inspect: input-output-skills/input-output-skills-1
- timestamp: 2400
summary: Game Quality Skill used for enemy destruction feature
detail: Space Shooter triggers dynamic enemy destruction particle emitters upon weapon impact.
sequence:
- antigravity
- fun-skills
inspect: fun-skills/fun-skills-0
- timestamp: 5600
summary: Platformer Skill used in game dev for Coyote time feature
detail: Antigravity loads the Platformer skill, calibrating jump strength, gravity curves, and coyote time grace windows for smooth platform navigation.
sequence:
- antigravity
- fun-skills
inspect: fun-skills/fun-skills-2
- timestamp: 8000
summary: Game Quality Skill used for player destruction feature
detail: Space Shooter triggers player destruction particle effects during critical collision.
sequence:
- antigravity
- fun-skills
inspect: fun-skills/fun-skills-0
- timestamp: 12500
summary: Easter Egg Skill used in game dev for cheat code feature
detail: Antigravity activates the Easter Egg skill, listening for secret cheat code inputs (Up, Up, Down, Down, Left, Right, Left, Right, B, A) to transform retro color palettes.
sequence:
- antigravity
- fun-skills
inspect: fun-skills/fun-skills-1
- timestamp: 14000
summary: Arcade Visuals Skill used for HUD UI layer and CRT shader
detail: Antigravity applies a custom CRT shader to the main camera while keeping the HUD UI clean on a separate camera layer in Gravity Platformer.
sequence:
- antigravity
- input-output-skills
inspect: input-output-skills/input-output-skills-0
- id: game-portal
title: Game Portal
description: |
The game portal is a web-based interface loaded by arcade machines using Google Chrome in kiosk mode. This portal enables attendees to browse and play video games created with Antigravity.
videoPath: external-assets/agycade/game-portal.mp4
orientation: landscape
frame: none
layout: aboveandbelow
logs:
- timestamp: 1000
summary: "The cabinet loads the secure catalog view authenticated via HTTP-only session cookies"
detail: "When the cabinet requests 'GET /', the Express router verifies the user's HTTP-only session cookies against Firebase Authentication (`verifyAuth` middleware). If the short-lived ID token is expired, the server transparently refreshes it on the fly (`refreshSessionToken`) to maintain uninterrupted multi-day arcade sessions without exposing unencrypted tokens in browser storage."
sequence:
- game-portal
- firebase-auth
- timestamp: 2000
summary: "The portal queries Firestore to render approved cataloged games"
detail: "The server queries the 'games' collection in Cloud Firestore (`GET /api/games/`) to retrieve all approved and featured game records (`G-0420`, `G-0413`, `G-0010`, etc.) and renders them onto the cabinet selection carousel."
sequence:
- game-portal
- firestore
inspect: portal-backend/portal-backend-2
- timestamp: 2500
summary: "The player uses the arcade joystick to select a game from the catalog"
sequence:
- game-portal
- timestamp: 3000
summary: "The player selects G-0005 (Space Shooter), logging analytics and initializing the iframe"
detail: "When the cabinet loads `GET /game/G-0005`, the server records a new telemetry document in the 'loads' collection in Firestore and updates the user's `lastLoadedGame` state. The cabinet wrapper opens an isolated iframe for the game."
sequence:
- game-portal
- firestore
inspect: portal-backend/portal-backend-1
- timestamp: 4000
summary: "The Asset Proxy Engine streams private game files from Google Cloud Storage"
detail: "To keep game assets private and sandboxed, the Express Asset Proxy Engine (`GET /game/:id/play/*`) uses regex path parsing to stream static client files directly from the secure 'games' GCS bucket to the iframe."
sequence:
- game-portal
- bucket-replay
inspect: portal-backend/portal-backend-3
- timestamp: 6000
summary: "The player plays the Space Shooter game"
detail: "Inside the sandboxed iframe, the Phaser 3 engine initializes with retro CRT shader post-processing. The player controls their starship, shooting procedural alien waves."
sequence:
- game-portal
- phaser-engine
- timestamp: 33000
summary: 'The player presses the "Home" button to return to main menu'
detail: "Using standard cabinet hardware navigation, the game wrapper posts a `GO_HOME` window message to the parent container (`window.parent.postMessage({action: 'GO_HOME'}, '*')`), returning cleanly to the catalog selection screen."
sequence:
- game-portal
- timestamp: 36000
summary: "Using the joystick, the player selects G-0008 (Gravity Runner)"
detail: "The portal loads `GET /game/G-0008` and the Asset Proxy Engine streams Gravity Runner's compiled bundles (`Game.js`, spritesheets, and audio) from the 'games' GCS bucket into the player's iframe."
sequence:
- game-portal
- bucket-replay
inspect: portal-backend/portal-backend-3
- timestamp: 38000
summary: "The player plays the Gravity Runner game"
sequence:
- game-portal
- phaser-engine
- timestamp: 40000
summary: "Using game buttons, the player flips gravity to traverse obstacle courses and pits in Gravity Runner"
detail: "The runner game runs inside the upscaled dual-camera viewport (`320x240` logical buffer scaled 4x). The player manipulates vertical gravity pull to dodge spikes and jump across platform ledges."
sequence:
- game-portal
- timestamp: 46000
summary: 'The player presses the "Restart" button to restart the game'
sequence:
- game-portal
inspect: portal-backend/portal-backend-0
- timestamp: 66000
summary: 'The player presses the "Home" button to return to main menu'
detail: "The cabinet posts a `GO_HOME` telemetry event, returning the physical machine to the `GET /` game catalog interface."
sequence:
- game-portal
- id: modify-workflow
title: Modify Workflow
description: |
Using agent skills developed for Antigravity Arcade, attendees may easily modify game using natural language.
videoPath: external-assets/agycade/modify-a-game.mp4
orientation: landscape
frame: none
layout: aboveandbelow
logs:
- timestamp: 1000
summary: "The user types the text 'Modify a game' into the terminal prompt."
sequence:
- antigravity
inspect:
- timestamp: 7000
summary: "The agent reads the 'helping-the-user' agent skill"
detail: "The Agent infers that the skill '.agents/skills/helping-the-user/SKILL.md' is needed to handle the user's prompt so it reads the skill's instructions into the context window. This skill instructs the agent on how to query the user for more information to get started."
sequence:
- antigravity
- orchestration-skills
inspect: orchestration-skills/orchestration-skills-0
- timestamp: 7100
summary: "The agent executes the 'helping-the-user' skill"
sequence:
- antigravity
- orchestration-skills
inspect: orchestration-skills/orchestration-skills-0
- timestamp: 8000
summary: "The agent asks which game would the user like to modify"
detail: "Using the `ask_question` tool, the agent presents a native UI modal with options to modify specific games like gravity-runner, icy-hockey, space-shooter, or survivor-arcade."
sequence:
- antigravity
inspect:
- timestamp: 11000
summary: "The user selects option 2, 'Modify icy-hockey'"
sequence:
- antigravity
inspect:
- timestamp: 12000
summary: "The agent analyzes the game code for 'icy-hockey'"
detail: "The agent processes the request by loading all relevant game scene scripts so that it can recommend game modifications."
sequence:
- antigravity
inspect:
- timestamp: 17000
summary: "The agent asks which modification would the user like to make"
detail: "Using the `ask_question` tool, the agent presents a native UI modal with its recommended modification choices for the Icy Hockey game."
sequence:
- antigravity
inspect:
- timestamp: 26000
summary: "The user chooses the 'Add a new obstacle' option"
sequence:
- antigravity
inspect:
- timestamp: 31000
summary: "The agent reads the 'adding-easter-egg' skill"
detail: "The Agent infers that the skill '.agents/skills/adding-easter-egg/SKILL.md' is needed to handle the user's request so it reads the skill's instructions into the context window. This skill instructs the agent how to add an easter egg to the game."
sequence:
- antigravity
- fun-skills
inspect: fun-skills/fun-skills-1
- timestamp: 32000
summary: "The agent reads the 'ensuring-arcade-visuals' skill"
detail: "The Agent infers that the skill '.agents/skills/ensuring-arcade-visuals/SKILL.md' is needed to handle the user's request so it reads the skill's instructions into the context window. This skill instructs the agent about our opinionated visual design to ensure aesthetic consistency for all games."
sequence:
- antigravity
- input-output-skills
inspect: input-output-skills/input-output-skills-0
- timestamp: 33000
summary: "The agent reads the 'handling-user-input' skill"
detail: "The Agent infers that the skill '.agents/skills/handling-user-input/SKILL.md' is needed to handle the user's request so it reads the skill's instructions into the context window. This skill instructs the user to our desired physical hardware configuration so that it can wire up inputs correctly."
sequence:
- antigravity
- input-output-skills
inspect: input-output-skills/input-output-skills-1
- timestamp: 34000
summary: "The agent reads the 'config.json' file"
detail: "The Agent infers that the 'config.json' file is needed to handle the user's request so it reads the file contents into the context window. This file is used to inform the Web UI how inputs are mapped for this particular game."
sequence:
- antigravity
inspect: deployer-backend/deployer-backend-1
- timestamp: 35000
summary: "The agent reads the 'messaging-game-over' skill"
detail: "The Agent infers that the skill '.agents/skills/messaging-game-over/SKILL.md' is needed to handle the user's request so it reads the skill's instructions into the context window. This skill instructs the agent how to handle the Game Over state for our Web UI."
sequence:
- antigravity
- fun-skills
inspect: fun-skills/fun-skills-3
- timestamp: 36000
summary: "The agent reads the 'improving-game-quality' skill"
detail: "The Agent infers that the skill '.agents/skills/improving-game-quality/SKILL.md' is needed to handle the user's request so it reads the skill's instructions into the context window. This skill instructs the agent how to implement our opinionated features for what makes a good game."
sequence:
- antigravity
- fun-skills
inspect: fun-skills/fun-skills-0
- timestamp: 52000
summary: "The agent reads the 'package.json' file"
detail: "The Agent infers that the 'package.json' file is needed to understand the project structure so it is added to the context window."
sequence:
- antigravity
- timestamp: 60000
summary: "The agent reads project files"
detail: "The Agent reads various project files to better understand the game code syntax and structure so that it can make the necessary changes."
sequence:
- antigravity
inspect:
- timestamp: 90000
summary: "The agent begins to make code edits"
sequence:
- antigravity
- timestamp: 98000
summary: "The agent reads the 'playing-the-game' skill"
detail: "The Agent infers that the skill '.agents/skills/playing-the-game/SKILL.md' is needed to handle the user's request so it reads the skill's instructions into the context window. This skill instructs the agent how to build and run the game so the user can play it locally."
sequence:
- antigravity
- input-output-skills
inspect: input-output-skills/input-output-skills-2
- timestamp: 103000
summary: "The agent requests permission to run the game server"
detail: "Antigravity permissions have been set requiring the agent to ask before running `npm run` so the agent must ask permission before continuing."
sequence:
- antigravity
inspect:
- timestamp: 106000
summary: "The user grants permission to continue"
sequence:
- antigravity
inspect:
- timestamp: 107000
summary: "The agent starts the game server at localhost:1573"
sequence:
- antigravity
inspect: portal-backend/portal-backend-3
- timestamp: 115000
summary: "The agent opens the Chrome browser to localhost:1573"
sequence:
- antigravity
- phaser-engine
inspect: portal-backend/portal-backend-1
- timestamp: 123000
summary: "The user play tests the game"
sequence:
- phaser-engine
- timestamp: 131000
summary: "The user returns to Antigravity"
sequence:
- antigravity
- timestamp: 132000
summary: "The agent explains the work completed"
detail: "The agent provides a detailed explanation of the work completed and provides instructions for how the user can play test the game locally."
sequence:
- antigravity
- id: deploy-workflow
title: Deploy Workflow
description: |
Using a custom deploy workflow, attendees can prompt the agent to deploy their game to the Antigravity Arcade game server.
videoPath: external-assets/agycade/deploy-a-game.mp4
orientation: landscape
frame: none
layout: aboveandbelow
logs:
- timestamp: 1000
summary: 'The user prompts the agent "Deploy"'
sequence:
- antigravity
- timestamp: 6000
summary: 'The agent executes the "Deloy" workflow'
detail: "The agent infers from the user's prompt that they wish to deploy a game. The agent reads the '.agents/workflows/deploy.md' file and executes it's instructions. The workflow instructs the agent on all of the proper execution steps for building and deploying a game to the game server."
sequence:
- antigravity
inspect: workflows/workflows-0
- timestamp: 9000
summary: "Step 1: The agent asks the user which game they would like to deploy"
detail: "Following the deploy workflow instructions, the agent uses the `ask_question` tool to present the user with a list of possible games to deploy."
sequence:
- antigravity
- timestamp: 10000
summary: 'The user selects choice 1, "Icy Hockey" to deploy'
sequence:
- antigravity
- timestamp: 15000
summary: "Step 2: The agent builds the game."
sequence:
- antigravity
- timestamp: 16000
summary: "The agent executes the deploy tool"
detail: "Provided to the agent is a CLI program for deploying the application. The agent executes this CLI tool with the appropriate arguments and waits for a response."
sequence:
- antigravity
- timestamp: 17000
summary: "The deployer binary elevates privileges to read protected cabinet secrets"
detail: "Using the Unix `setuid` bit, the native `deploy_osx` binary runs as the restricted `agycade` system user. This secure proxy model allows the binary to read the deploy token and user info without exposing sensitive credentials to terminal user accounts."
sequence:
- deployer-workflow
- timestamp: 18000
summary: "The deployer compiles the Phaser 3 game via Vite build"
detail: "The deployer invokes `npm run build` as a subprocess (`os/exec`) inside the target game project folder (`icy-hockey`). Vite compiles and minifies the client-side game assets into the `dist/` directory."
sequence:
- deployer-workflow
- timestamp: 19000
summary: "The deployer packages the compiled assets into a clean ZIP archive"
detail: "To keep payload size minimal and avoid recursive loops, the deployer bundles the project into `game.zip` inside the workspace-local `./tmp` folder while strictly excluding `node_modules` and existing `.zip` files. Go's `defer` mechanism guarantees the temporary archive is removed upon termination."
sequence:
- deployer-workflow
- timestamp: 20000
summary: "The deployer computes MD5 checksum and negotiates a GCS Signed URL"
detail: "The deployer computes a base64 MD5 checksum of `game.zip` and sends a `POST /api/games/get-upload-url` request with the deploy token and uploader ID to the server. The server verifies the token against `DEPLOY_TOKEN`, checks the `builds` collection in Firestore for MD5 deduplication, and generates a 5-minute GCS Signed PUT URL bound to the MD5 header."
sequence:
- deployer-workflow
- firestore
inspect: portal-backend/portal-backend-4
- timestamp: 21000
summary: "The deployer streams the ZIP archive directly to Google Cloud Storage"
detail: "Using the short-lived Signed URL, the deployer issues a direct `PUT` request to Google Cloud Storage (`uploads` bucket under `uploads/[buildId].zip`) with the `Content-MD5` header attached. GCS validates the checksum on the fly, ensuring zero packet truncation during transfer."
sequence:
- deployer-workflow
- bucket-upload
- timestamp: 22000
summary: "The deployer cloud function extracts the ZIP into high-speed memory"
detail: "When GCS registers the completed upload in `uploads` bucket, an EventArc trigger invokes the `upload-processor` Cloud Run function. To bypass disk I/O overhead, the function downloads and unzippers `game.zip` directly into the `/tmp/[buildId]` high-speed RAM mount."
sequence:
- deployer-function
- bucket-upload
inspect: deployer-backend/deployer-backend-0
- timestamp: 23000
summary: "The cloud function executes NSFW filtering and `config.json` schema validation"
detail: "The processor scans all code files and validates `config.json` to verify proper syntax, required fields (`title`, `objective`), and the exact mapping of the four cabinet-compliant buttons (`A`, `B`, `X`, `Y`). If either check fails, processing halts immediately."
sequence:
- deployer-function
inspect: deployer-backend/deployer-backend-1
- timestamp: 24000
summary: "The cloud function relocates production assets and registers the game in Firestore"
detail: "Upon passing safety and review checks, the processor copies the `dist/` assets into the production `games` bucket under `[buildId]/`. It then runs an atomic Firestore transaction (`system/gameCounter`) to generate a sequential 4-digit ID (`G-XXXX`) and registers the game document in the `games` collection with status `PENDING_HUMAN_REVIEW`."
sequence:
- deployer-function
- bucket-replay
- firestore
inspect: deployer-backend/deployer-backend-3
- timestamp: 25000
summary: "The agent waits for the tool to return a repsonse."
detail: "By setting scheduled checks for tool completion, the agent frees itself for continued conversation with the user."
sequence:
- antigravity
- timestamp: 50000
summary: "Step 3: The tool completes and the agent gives the user an update"
detail: "When the tool completes, the agent reviews the tool's response and formats detailed information about the deployed game."
sequence:
- antigravity
- id: reset-workflow
title: Reset Workflow
description: |
Using the reset workflow developed for Antigravity Arcade, attendees may easily revert game modifications or restore entire workspace repositories back to their pristine baseline templates using natural language.
videoPath: external-assets/agycade/reset-a-game.mp4
orientation: landscape
frame: none
layout: aboveandbelow
logs:
- timestamp: 1000
summary: 'The user prompts the agent "Reset game"'
sequence:
- antigravity
- timestamp: 5000
summary: 'The agent executes the "Reset" workflow'
detail: "The agent infers from the user's prompt that they wish to reset the workspace. The agent checks the workspace contents and reads the '.agents/workflows/reset.md' file to execute its instructions for restoring the environment to its initial state."
sequence:
- antigravity
- reset-workflow
inspect: workflows/workflows-1
- timestamp: 8000
summary: "Step 1: The agent asks the user which game they would like to reset"
detail: "Following the reset workflow instructions, the agent uses the 'ask_question' tool to present the user with options to reset 'All games' or a specific game such as 'space-shooter', 'gravity-runner', 'survivor-arcade', or 'icy-hockey'."
sequence:
- antigravity
- reset-workflow
- timestamp: 11000
summary: 'The user selects choice 3, "gravity-runner" to reset'
sequence:
- antigravity
- timestamp: 15000
summary: "Step 2: The agent executes the reset utility for gravity-runner"
detail: "The agent runs './utils/reset.sh gravity-runner' from the workspace root. The reset utility purges the modified game directory and synchronizes a pristine baseline from the read-only backup directory '/opt/AntigravityArcade/utils/backup' using 'rsync -rlv' while preserving core platform scaffolding and 'node_modules'."
sequence:
- antigravity
- reset-workflow
- timestamp: 16000
summary: "Step 3: The reset completes and the agent confirms success to the user"
detail: "The agent replies with the exact completion template: 'Workspace Reset Successful: The game gravity-runner has been restored to its default state. All modifications to the game folder have been reverted, and new files have been removed. Your environment is ready for a new session.'"
sequence:
- antigravity
- reset-workflow
- type: inspect
subsections:
- id: orchestration-skills
title: Orchestration skills
description: |
Orchestration skills act as the high-level brain for Antigravity's game generation lifecycle. They govern context retrieval, orchestrate code-editing agents, manage workspace setup from game templates, and execute automated validation and playtesting loops.
mode: html
architecture:
- antigravity
- orchestration-skills
- phaser-engine
examples:
- title: Helping the user skill
icons:
- /external-assets/antigravity.png
mode: markdown
info: |
This skill guides the AI agent in helping the user with game development tasks. It infers context from the chat history, maintains session continuity, and either suggests modifications for existing games or delegates game creation and testing to specialized orchestration skills.
code:
language: markdown
linkify: true
repoPath: games/.agents/skills/helping-the-user/SKILL.md
- title: Creating a game
icons:
- /external-assets/antigravity.png
mode: markdown
info: |
Serving as the primary high-level orchestrator for new game projects, this skill initializes workspace directories from a template, coordinates sub-skills (such as input handling, visuals, and game feel), and enforces an automatic build-validation loop after every code edit.
code:
language: markdown
linkify: true
repoPath: games/.agents/skills/creating-a-game/SKILL.md
- title: Playing a game
icons:
- /external-assets/antigravity.png
mode: markdown
info: |
This orchestration skill automates the testing process by starting the local Vite dev server on a strict port, launching Google Chrome to display the game, and presenting a standardized cabinet control mapping reference for physical and keyboard inputs.
code:
language: markdown
linkify: true
repoPath: games/.agents/skills/playing-the-game/SKILL.md
- id: input-output-skills
title: Input / Output skills
description: |
Input/Output skills guide the agent in establishing a consistent experience across physical hardware configurations. They define strict instructions for mapping keyboard bindings to the Web Gamepad API, and dictate visual rendering requirements like the retro CRT camera post-processing.
mode: html
architecture:
- antigravity
- input-output-skills
- phaser-engine
examples:
- title: Arcade visuals
icons:
- /external-assets/antigravity.png
mode: markdown
info: |
This instruction file defines mandatory visual guidelines for retro arcade games created by Antigravity. It ensures all text utilizes the designated retro pixel font and enforces the implementation of a custom CRT shader on the primary Phaser camera, guaranteeing a consistent arcade machine aesthetic across the entire repository.
code:
language: markdown
linkify: true
repoPath: games/.agents/skills/ensuring-arcade-visuals/SKILL.md
- title: User input
icons:
- /external-assets/antigravity.png
mode: markdown
info: |
This guideline instructs Antigravity to consistently map arrow keys and standard keyboard buttons to the Web Gamepad API layout. Furthermore, it enforces a critical start-gate mechanism that blocks the main game simulation from running until the user explicitly confirms they are ready via controller or keyboard interaction.
code:
language: markdown
linkify: true
repoPath: games/.agents/skills/handling-user-input/SKILL.md
- id: fun-skills
title: Fun skills
description: |
Fun skills define opinionated gameplay quality guidelines for retro games. They instruct the agent on implementing viewport UI margins, continuous loops with lose conditions, visual polish (like screen shake and particle emitters), and secret easter egg palette filters.
mode: html
architecture:
- antigravity
- fun-skills
- phaser-engine
examples:
- title: Game quality
icons:
- /external-assets/antigravity.png
mode: markdown
info: |
Followed when creating or modifying a game, this skill ensures high quality user experience by mandating viewport UI margins, a continuous game loop with reachable lose conditions, animated background particles, screen shake on impact, and dynamic updates to the game's config.json controls layout.
code:
language: markdown
linkify: true
repoPath: games/.agents/skills/improving-game-quality/SKILL.md
- title: Easter egg
icons:
- /external-assets/antigravity.png
mode: markdown
info: |
To boost engagement and developer enjoyment, this skill instructs the agent to incorporate a standardized cheat code listener. When the classic sequence is entered by the player, it triggers a temporary screen effect (such as monochrome, sepia, gameboy monotone, or negative) that alters the gameplay experience for 10 seconds.
code:
language: markdown
linkify: true
repoPath: games/.agents/skills/adding-easter-egg/SKILL.md
- title: Building platformer games
icons:
- /external-assets/antigravity.png
mode: markdown
info: |
Used when creating or refining platformer games, this skill ensures movement feels responsive and jumps are satisfying. It covers jump mechanics calibration, wall/double jump logic, and game feel enhancements like coyote time, jump buffering, variable jump heights, and slide or charge jump mechanics.
code:
language: markdown
linkify: true
repoPath: games/.agents/skills/building-platformer-games/SKILL.md
- id: workflows
title: Agentic workflows
description: |
Agentic workflows compile step-by-step procedure rules for complex developer operations. They define precise sequencing guidelines for the AI assistant to safely build and deploy user game folders or restore development environments back to their pristine baseline.
model: html
architecture:
- antigravity
- deploy-workflow
- reset-workflow
examples:
- title: Deploy workflow
icons:
- /external-assets/agycade/workflow-deploy.svg
mode: markdown
info: |
This agentic workflow guides the AI developer assistant through selecting the right game, building/bundling compiled assets, invoking the appropriate native deployment binary, and formatting user-facing notifications for each state of the upload pipeline.
code:
language: markdown
linkify: true
repoPath: games/.agents/workflows/deploy.md
- title: Reset workflow
icons:
- /external-assets/agycade/workflow-reset.svg
mode: markdown
info: |
This workflow instructs the AI developer assistant on how to reset a modified game workspace or restore all game repositories back to their pristine baseline template by invoking local backup scripts.
code:
language: markdown
linkify: true
repoPath: games/.agents/workflows/reset.md
- id: deployer-backend
title: Deployer Backend
description: |
The deployer backend acts as the autonomous serverless ingestion and publishing pipeline for the arcade catalog. Decoupled from local development workflows by receiving ZIP payloads directly via GCS Signed URLs, an event-driven Cloud Run function (`upload-processor`) automatically verifies incoming builds through multi-stage safety and compatibility checks—including NSFW content screening and physical cabinet controller schema verification (`config.json`). Once validated, the backend promotes clean assets to the production storage bucket and runs an atomic Firestore transaction to assign a human-readable 4-digit cabinet ID (`G-XXXX`).
mode: html
architecture:
- deployer-workflow
- deployer-function
- bucket-upload
- bucket-replay
- firestore
examples:
- title: Upload Processor Entry Point
icons:
- /external-assets/cloud-functions.png
mode: javascript
info: |
This event-driven Cloud Run function serves as the automated safety and validation gatekeeper between raw GCS uploads and the live arcade catalog. Using dependency injection (`createHandler`) for seamless local testing with cloud emulators, it responds to `object.finalize` events by downloading uploaded ZIP archives to container memory (`/tmp`), initializing real-time status tracking in Firestore, and kicking off automated NSFW safety scans and cabinet controller checks.
code:
language: javascript
linkify: false
repoPath: server/functions/upload-processor/index.js
regionTag: upload_processor_gcs_io
- title: Automatic file scans
icons:
- /external-assets/cloud-functions.png
mode: javascript
info: |
Once the archive is downloaded to container memory (`/tmp`), the processor unzips the files into an in-memory `tmpfs` mount—monitoring RAM limits to prevent OOM extraction crashes. It then executes two sequential automated validation gates: first, `runNsfwScan` checks all text and asset contents against a blacklist (`bad-words.json`) to block inappropriate material (`FAILED_NSFW_SCAN`). Next, it parses `config.json` to verify required game metadata (`title`, `objective`) and mandatory physical cabinet button bindings (`controls.A/B/X/Y`). If any check fails, the handler immediately updates Firestore (`FAILED_CODE_REVIEW`) and purges `/tmp` space.
code:
language: javascript
linkify: false
repoPath: server/functions/upload-processor/index.js
regionTag: upload_processor_automatic_scans
- title: Asset Promotion & Idempotency Check
icons:
- /external-assets/cloud-functions.png
mode: javascript
info: |
After passing automated scans, the processor updates the build status to `PENDING_HUMAN_REVIEW` and selectively promotes static assets from `/tmp/[buildId]/dist` into the production `agycade-games` bucket under a dedicated `buildId` prefix. By copying only the `dist/` build artifacts (and raising an error if missing), it ensures clean separation from raw upload source files. Finally, it queries Firestore to verify idempotency—skipping record creation and purging `/tmp` if a game document with this `buildId` already exists.
code:
language: javascript
linkify: false
repoPath: server/functions/upload-processor/index.js
regionTag: upload_processor_gcs_publish
- title: Finalize Game Registration
icons:
- /external-assets/cloud-functions.png
mode: javascript
info: |
To finalize cabinet registration, the handler executes an atomic Firestore transaction over a shared counter document (`system/gameCounter`) to safely compute and pad the next sequential 4-digit ID (`G-XXXX`) without race conditions. It then retrieves the original `uploaderId` from the staging build document and creates the authoritative game record (`games/G-XXXX`) with all validated `config.json` metadata (`title`, `objective`, `controls`). Finally, it purges the unzipped payload (`/tmp/[buildId]`) and local `.zip` archive to reclaim container memory for future invocations.
code:
language: javascript
linkify: false
repoPath: server/functions/upload-processor/index.js
regionTag: upload_processor_firestore_register
- id: portal-backend
title: Game Portal Backend
description: |
The game portal backend handles routing, player authentication, and private file streaming for the arcade console catalog. It proxies client-side GCS file requests through Express to prevent framing and hotlinking, and records gameplay telemetry to Firestore documents.
mode: html
architecture:
- game-portal
- bucket-replay
- firestore
examples:
- title: HMAC Time-Window Token Generator
icons:
- /external-assets/cloud-run.svg
mode: javascript
info: |
To prevent external scraping without breaking relative subresource paths, this helper computes short-lived 15-second HMAC SHA-256 tokens (`currentToken` and `prevToken`). By checking both the current and previous time windows, it gracefully handles rollover during cabinet page loads while ensuring the `index.html` entrypoint remains locked to authenticated sessions.
code:
language: javascript
linkify: false
repoPath: server/routes/game.js
regionTag: get_game_token
- title: SSR Game Console & Telemetry
icons:
- /external-assets/cloud-run.svg
mode: javascript
info: |
When rendering the arcade cabinet screen (`game.ejs`), this server-side route verifies player and uploader moderation permissions (`VERIFIED`, `admin`, `PENDING_HUMAN_REVIEW`). Before returning the view, it logs gameplay telemetry to the Firestore `loads` collection and updates the user's `lastLoadedGame` field to synchronize recent activity across arcade machines.
code:
language: javascript
linkify: false
repoPath: server/routes/game.js
regionTag: get_game_screen
- title: Get Games Catalog
icons:
- /external-assets/cloud-run.svg
mode: javascript
info: |
Mounted at `/api/games/`, this endpoint retrieves and filters the authoritative arcade catalog based on the authenticated user's credentials. While `admin` accounts receive the entire unfiltered catalog (including unmoderated builds for testing), regular players and developers only receive games marked as `APPROVED` or `FEATURED`—plus any builds currently `PENDING_HUMAN_REVIEW` where their account (`userId`) matches the game's original `uploaderId`.
code:
language: javascript
linkify: false
repoPath: server/routes/api/games.js
regionTag: get_game_catalog
- title: Private Asset Proxy & Security Gate
icons:
- /external-assets/cloud-run.svg
mode: javascript
info: |
This wildcard proxy route (`/game/:id/play/*`) enforces strict same-origin boundaries and private GCS asset streaming. It verifies `sec-fetch-dest` to block direct top-level tab navigation (preventing `sandbox="allow-scripts"` bypasses), validates the 15-second HMAC token on `.html` requests, injects `frame-ancestors 'self'` headers, and streams files directly from the private storage bucket (`or local emulator disk`).
code:
language: javascript
linkify: false
repoPath: server/routes/game.js
regionTag: proxy_game_through_api
- title: Signed GCS Upload URL API
icons:
- /external-assets/cloud-run.svg
mode: javascript
info: |
This API route generates 5-minute `v4` GCS signed PUT URLs for direct-to-cloud archive uploads (`uploads/[buildId].zip`). Before signing, it queries Firestore (`builds` collection) to check whether a build with the requested `MD5` checksum already exists—skipping duplicate file transfers and immediately initializing build tracking.
code:
language: javascript
linkify: false
repoPath: server/routes/api/games.js
regionTag: get_upload_url
- title: Real-Time Build & Game Status API
icons:
- /external-assets/cloud-run.svg
mode: javascript
info: |
Mounted at `/api/games/status/:buildId`, this endpoint enables the developer CLI and frontend dashboard to poll or inspect real-time ingestion progress. It retrieves the authoritative `status` (`PENDING_NSFW_SCAN`, `PENDING_HUMAN_REVIEW`, etc.) and returns the sequential cabinet `gameId` (`G-XXXX`) once registration completes.
code:
language: javascript
linkify: false
repoPath: server/routes/api/games.js
regionTag: get_game_status
- type: quiz
questions:
- title: What is the main purpose of Antigravity skills?
answers:
- answer: Database schemas defining how high scores are stored in Firestore.
- answer: Synchronizing multiplayer game states across Cloud Run instances.
- answer: They provide guidelines and constraints that guide AI agents to implement features consistently.
correct: true
- answer: Executing high-performance physics calculations directly inside the PhaserJS game engine.
- title: When should the game start according to the user input skill?
answers:
- answer: Following a countdown timer.
- answer: Only when the player interacts with a button or controller.
correct: true
- answer: Instantly upon page load.
- title: How should the CRT shader be applied according to arcade visuals guidelines?
answers:
- answer: Individual game sprites separately.
- answer: The HUD layer exclusively.
- answer: The main camera, leaving the UI/HUD unaffected.
correct: true
- title: How does the server support secure 3-day sessions without service account keys?
answers:
- answer: Generating standard session cookies using the Firebase Admin SDK.
- answer: Caching session state in a server-side Redis database.
- answer: Saving credentials in the client's localStorage and using a service worker.
- answer: Storing ID and refresh tokens in HTTP-only cookies and renewing them in middleware.
correct: true
- title: What checks does the upload Cloud Run Function perform on game zip files?
answers:
- answer: Verifying developer digital signatures against a manifest.xml file.
- answer: Runs an NSFW text scan and verifies config.json contains required metadata and A/B/X/Y controls.
correct: true
- answer: Asset conversion to WebP format and verifying a Google Analytics tag.
- answer: A virus scan on the archive and a syntax check on Game.js.
- title: How are database update requests to Firestore authorized by the server?
answers:
- answer: Retrieving an access token from the Google Cloud metadata server.
correct: true
- answer: Signing a JWT using the client-side Firebase Auth library.
- answer: Establishing a secure WebSocket connection with the database.
- answer: Embedding an API key directly in the request query parameters.
- title: Why does the portal use an API proxy instead of serving directly from a public storage bucket?
answers:
- answer: To enforce iframe-only execution boundaries, require short-lived HMAC time-window tokens on index.html, and inject security headers.
correct: true
- answer: To convert audio files from WAV to MP3 on the fly during game loading.
- answer: Because Google Cloud Storage cannot serve static files like HTML or JavaScript directly.
- answer: To compress game textures using server-side WebAssembly before sending to Chrome.
- title: How does the server lock down game entrypoints without breaking relative subresource paths?
answers:
- answer: It enforces short-lived HMAC time-window tokens exclusively on index.html, while allowing subsequent relative asset requests to stream cleanly inside an authenticated cabinet session.
correct: true
- answer: By requiring every single image and audio request to include a unique 5-minute signed URL.
- answer: By injecting a secret API key directly into the global JavaScript window object.
- answer: By restricting all requests to static IP addresses registered inside Firebase Security Rules.
- title: How does the upload processor ensure idempotent game registration and avoid duplicate IDs on retry?
answers:
- answer: It queries Firestore by build ID before creation to skip duplicates, and runs an atomic transaction over the system counter when assigning new cabinet IDs.
correct: true
- answer: By deleting all existing games in the catalog whenever a new build arrives.
- answer: By using random UUIDs that are guaranteed to never collide under any circumstances.
- answer: By locking the entire games collection using Redis mutexes for 10 minutes during upload.
- title: Why do games communicate with the parent container via postMessage rather than calling window.location.reload?
answers:
- answer: Because iframe sandboxing creates an isolated null origin under the Same-Origin Policy, and reloading the parent host page generates a fresh HMAC token.
correct: true
- answer: Because window.location.reload is deprecated and removed from modern web browsers.
- answer: Because postMessage executes twice as fast as local DOM methods.
- answer: Because Phaser 3 overrides window.location during canvas initialization.
- type: build
promoType: antigravity
links:
- url: https://github.com/GoogleCloudPlatform/devrel-demos/tree/main/other/antigravity-arcade
label: Open on GitHub
- url: https://developers.google.com/solutions
label: Explore more Solutions
architecture:
boxes:
- id: google-cloud-box
label: "Google Cloud"
entities:
- game-portal
- deployer-function
- firebase-auth
- firestore
- bucket-replay
- bucket-upload
- id: agent-skills-box
label: "Agent Skills"
entities:
- orchestration-skills
- input-output-skills
- fun-skills
- id: agent-workflows-box
label: "Agent Workflows"
entities:
- deployer-workflow
- reset-workflow
entities:
- id: orchestration-skills
icon: /external-assets/agycade/skill-orchestration.svg
label: "Orchestration skills"
x: 0
y: -1
inspect: orchestration-skills
connections:
- from: orchestration-skills
to: antigravity
- id: input-output-skills
icon: /external-assets/agycade/skill-input-output.svg
label: "Input / Output skills"
x: 0
y: 1
inspect: input-output-skills
connections:
- from: input-output-skills
to: antigravity
- id: fun-skills
icon: /external-assets/agycade/skill-fun.svg
label: "Fun skills"
x: 0
y: 3
inspect: fun-skills
- id: phaser-engine
icon: /external-assets/phaserjs.png
label: "PhaserJS Game Engine"
x: 2
y: -1
connections:
- from: phaser-engine
to: game-portal
- from: phaser-engine
to: antigravity
line: dashed
- id: antigravity
icon: /external-assets/antigravity.png
label: "Antigravity 2.0"
x: 2
y: 1
connections:
- from: antigravity
to: deployer-workflow
- from: antigravity
to: reset-workflow
- from: antigravity
to: fun-skills
- id: deployer-workflow
icon: /external-assets/agycade/workflow-deploy.svg
label: '"Deployer" Workflow'
x: 4
y: 1
inspect: workflows
connections:
- from: deployer-workflow
to: deployer-function
- id: reset-workflow
icon: /external-assets/agycade/workflow-reset.svg
label: '"Reset" Workflow'
x: 4
y: 3
inspect: workflows
- id: game-portal
icon: /external-assets/cloud-run.svg
label: 'Cloud Run "Game Portal"'
x: 6
y: -1
inspect: portal-backend
connections:
- from: game-portal
to: firebase-auth
- from: game-portal
to: firestore
- from: game-portal
to: bucket-replay
- id: deployer-function
icon: /external-assets/cloud-functions.png
label: '"Deployer" Cloud Run Function'
x: 6
y: 1
inspect: deployer-backend
connections:
- from: deployer-function
to: firestore
- from: deployer-function
to: bucket-replay
- from: deployer-function
to: bucket-upload
- id: firebase-auth
icon: /external-assets/firebase-auth.svg
label: "Firebase Auth"
x: 8
y: -3
- id: firestore
icon: /external-assets/firebase-firestore.svg
label: "Firestore"
x: 8
y: -1
- id: bucket-replay
icon: /external-assets/cloud-storage.svg
label: 'GCP Bucket "Replay"'
x: 8
y: 1
- id: bucket-upload
icon: /external-assets/cloud-storage.svg
label: "GCP Bucket Upload"
x: 8
y: 3
badges:
startBadge: https://developers.google.com/profile/badges/playlists/solutions/antigravity-arcade/view
exploreBadge: https://developers.google.com/profile/badges/playlists/solutions/antigravity-arcade/learn
quizBadge: https://developers.google.com/profile/badges/playlists/solutions/antigravity-arcade/quiz
buildBadge: https://developers.google.com/profile/badges/playlists/solutions/antigravity-arcade/action