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:
class Server {
// Define server functions here
add(a, b) {
return a + b;
}
}- Never export the Server class using module.exports or export default
- Avoid using setTimeout/setInterval - use room ticks instead
- File must be named exactly “server.js”
- 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
$roomparameter 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.roomIdexists). 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 }ornull- Default tier:
'basic'(additional tiers may be added in the future) - Only available from server-signed authentication tokens
- Default tier:
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 functionThis function is optional and only needed if you require recurring server-side logic.// Runs every 200-1000ms for active rooms $roomTick(deltaMillis, roomId) { // Handle recurring logic here // deltaMillis: time since last tick in milliseconds }
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 ShopProperty Type Description 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:
- Run deployment command:
npx -y @agent8/deploy- 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
-
No Timers
Use$roomTickinstead of setTimeout and setInterval: -
Class Instance Lifecycle
Each request creates a new Server instance. Class-level variables should only be used for constants -
No Module Exports
The Server class must remain unexported