Skip to Content

server.js Overview

Location & Basic Structure

server.js must be placed in your project’s root directory. This file contains your server-side logic as a class definition:

server.js
class Server { // Define server functions here add(a, b) { return a + b; } }
⚠️
  1. Never export the Server class using module.exports or export default
  2. Avoid using setTimeout/setInterval - use room ticks instead
  3. File must be named exactly “server.js”
  4. Class-level variables will reset per request - use only for constants

Predefined Variables & Functions

The Server class comes with several predefined variables and functions you can use:

State Management

  • $global - Variable for managing global state across all rooms

    // Get global state const state = $global.getGlobalState(); // Update global state $global.updateGlobalState({ key: "value" });
  • $room - Variable for managing room-specific state.

    // Get room state const state = $room.getRoomState(); // Update room state $room.updateRoomState({ key: "value" });

    The $room parameter automatically manages the state for the room identified by $sender.roomId. This means it can only be used when a user is in a room (when $sender.roomId exists). Server functions that need to access or modify room state require the client to be connected to a room first.

Request Context

  • $sender - Contains information about the client making the request

    // Access requester information const { account, roomId, isFollower, isSubscriber, subscription } = $sender;

    Available Properties

    • account - User’s wallet address (0x…)
    • roomId - Current room ID (null if not in a room)
    • isFollower - Whether the user is following the creator (boolean)
    • isSubscriber - Whether the user has an active subscription (boolean, checks expiration)
    • subscription - Detailed subscription info { tier: string, exp: number } or null
      • Default tier: 'basic' (additional tiers may be added in the future)
      • Only available from server-signed authentication tokens

    Usage Example

    class Server { getMyStatus() { return { isFollower: $sender.isFollower, isSubscriber: $sender.isSubscriber, subscription: $sender.subscription, }; } } // Returns: // { // isFollower: true | false, // isSubscriber: true | false, // subscription: { tier: 'basic', exp: 1234567890 } | null // }

Recurring Logic

  • $roomTick(deltaMillis, roomId) { } - Automatically executed function
    // Runs every 200-1000ms for active rooms $roomTick(deltaMillis, roomId) { // Handle recurring logic here // deltaMillis: time since last tick in milliseconds }
    This function is optional and only needed if you require recurring server-side logic.

System Event Handlers

Special handlers called automatically by the system. Protected from direct client calls ($on prefix).

  • $onItemPurchased(data) - Called when a user purchases an item from VX Shop

    PropertyTypeDescription
    accountstringUser’s wallet address
    purchaseIdnumberUnique purchase ID
    productIdstringProduct identifier from VX Shop
    quantitynumberNumber of items purchased
    metadataobject?Optional additional data
    async $onItemPurchased({ account, purchaseId, productId, quantity }) { // Grant items based on productId switch (productId) { case 'gold_pack': await $asset.mint('gold', 100 * quantity); break; case 'premium_skin': const user = await $global.getMyState(); await $global.updateMyState({ skins: [...(user.skins || []), productId] }); break; default: await $asset.mint(productId, quantity); } return { success: true }; }

Deployment Process

After creating/updating server.js:

  1. Run deployment command:
npx -y @agent8/deploy
  1. This will:
  • Create/update VITE_AGENT8_VERSE in .env
  • Upload server.js to Agent8 cloud
  • Generate required API endpoints
🚫

You MUST redeploy after any server.js changes for them to take effect

Client Invocation

Call server functions from client code using:

const { server } = useGameServer(); // Standard call const result = await server.remoteFunction("add", [1, 2]); // Throttled call server.remoteFunction("updatePosition", [position], { throttle: 50, });

Key Constraints

  1. No Timers
    Use $roomTick instead of setTimeout and setInterval:

  2. Class Instance Lifecycle
    Each request creates a new Server instance. Class-level variables should only be used for constants

  3. No Module Exports
    The Server class must remain unexported

Last updated on