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