| name | cocos-backend-integrator |
| description | Use when working on server communication, data synchronization, cloud services integration, and backend architecture in Cocos Creator projects. |
Cocos Backend Integrator
Overview
This Codex skill adapts the upstream Cocos Creator Claude agent guidance for use in Codex.
Expert in integrating Cocos Creator games with backend services, APIs, and server infrastructure. Use this skill for server communication, data synchronization, cloud services integration, and backend architecture in Cocos Creator projects.
Expertise
- REST API integration and GraphQL clients
- WebSocket real-time communication
- Authentication and authorization systems
- Cloud service integration (Firebase, AWS, Azure)
- Data synchronization and offline support
- Server-side game logic integration
- Analytics and telemetry integration
- Push notification systems
Usage Examples
Example 1: API Integration
Context: Need to connect game to backend API
User: "Integrate player profiles with our REST API"
Assistant: "I will use $cocos-backend-integrator"
Commentary: Creates robust API client with error handling and caching
Example 2: Real-time Features
Context: Multiplayer game needs real-time sync
User: "Add WebSocket communication for live matches"
Assistant: "I will use $cocos-backend-integrator"
Commentary: Implements efficient real-time communication with reconnection logic
Example 3: Cloud Services
Context: Need cloud storage for game data
User: "Integrate Firebase for user data and leaderboards"
Assistant: "I will use $cocos-backend-integrator"
Commentary: Sets up Firebase SDK with proper data models and sync
API Integration Patterns
HTTP Client Implementation
export interface APIResponse<T> {
success: boolean;
data?: T;
error?: string;
statusCode: number;
}
@ccclass('APIClient')
export class APIClient extends Component {
@property
baseURL: string = '';
@property
timeout: number = 10000;
private _authToken: string = '';
private _requestCache: Map<string, any> = new Map();
async request<T>(
endpoint: string,
options: RequestInit = {}
): Promise<APIResponse<T>> {
const url = `${this.baseURL}${endpoint}`;
const cacheKey = `${options.method || 'GET'}:${url}`;
if (!options.method || options.method === 'GET') {
const cached = this._requestCache.get(cacheKey);
if (cached && this.isCacheValid(cached)) {
return cached.data;
}
}
try {
const response = await fetch(url, {
...options,
headers: {
'Content-Type': 'application/json',
'Authorization': this._authToken ? `Bearer ${this._authToken}` : '',
...options.headers
},
signal: AbortSignal.timeout(this.timeout)
});
const data = await response.json();
const result: APIResponse<T> = {
success: response.ok,
data: response.ok ? data : undefined,
error: response.ok ? undefined : data.message,
statusCode: response.status
};
if (result.success && (!options.method || options.method === 'GET')) {
this._requestCache.set(cacheKey, {
data: result,
timestamp: Date.now()
});
}
return result;
} catch (error) {
return {
success: false,
error: error.message,
statusCode: 0
};
}
}
setAuthToken(token: string) {
this._authToken = token;
}
}
WebSocket Manager
@ccclass('WebSocketManager')
export class WebSocketManager extends Component {
@property
serverURL: string = '';
@property
reconnectAttempts: number = 5;
@property
heartbeatInterval: number = 30000;
private _socket: WebSocket = null;
private _reconnectCount: number = 0;
private _heartbeatTimer: number = 0;
private _messageQueue: any[] = [];
connect() {
if (this._socket?.readyState === WebSocket.OPEN) {
return;
}
this._socket = new WebSocket(this.serverURL);
this._socket.onopen = this.onSocketOpen.bind(this);
this._socket.onmessage = this.onSocketMessage.bind(this);
this._socket.onclose = this.onSocketClose.bind(this);
this._socket.onerror = this.onSocketError.bind(this);
}
private onSocketOpen() {
console.log('WebSocket connected');
this._reconnectCount = 0;
while (this._messageQueue.length > 0) {
const message = this._messageQueue.shift();
this.send(message);
}
this.startHeartbeat();
this.node.emit('socket-connected');
}
private onSocketMessage(event: MessageEvent) {
try {
const data = JSON.parse(event.data);
if (data.type === 'heartbeat') {
return;
}
this.node.emit('socket-message', data);
} catch (error) {
console.error('Failed to parse WebSocket message:', error);
}
}
private onSocketClose() {
console.log('WebSocket disconnected');
this.stopHeartbeat();
this.attemptReconnect();
this.node.emit('socket-disconnected');
}
send(data: any) {
if (this._socket?.readyState === WebSocket.OPEN) {
this._socket.send(JSON.stringify(data));
} else {
this._messageQueue.push(data);
}
}
private attemptReconnect() {
if (this._reconnectCount < this.reconnectAttempts) {
this._reconnectCount++;
const delay = Math.pow(2, this._reconnectCount) * 1000;
setTimeout(() => {
console.log(`Reconnect attempt ${this._reconnectCount}`);
this.connect();
}, delay);
}
}
}
Cloud Services Integration
Firebase Integration
export class FirebaseManager extends Component {
private _db: any = null;
private _auth: any = null;
async initialize() {
const firebaseConfig = {
};
}
async savePlayerData(playerId: string, data: any) {
try {
await this._db.collection('players').doc(playerId).set(data, { merge: true });
return { success: true };
} catch (error) {
return { success: false, error: error.message };
}
}
async getLeaderboard(limit: number = 10) {
try {
const snapshot = await this._db
.collection('leaderboard')
.orderBy('score', 'desc')
.limit(limit)
.get();
const leaderboard = [];
snapshot.forEach(doc => {
leaderboard.push({ id: doc.id, ...doc.data() });
});
return { success: true, data: leaderboard };
} catch (error) {
return { success: false, error: error.message };
}
}
}
AWS Integration
export class AWSManager extends Component {
@property
region: string = 'us-east-1';
@property
identityPoolId: string = '';
private _cognitoIdentity: any = null;
private _s3: any = null;
async initialize() {
}
async uploadSaveFile(fileName: string, data: string) {
const params = {
Bucket: 'game-saves',
Key: fileName,
Body: data,
ContentType: 'application/json'
};
try {
return { success: true, url: 'result.Location' };
} catch (error) {
return { success: false, error: error.message };
}
}
}
Authentication Systems
JWT Authentication
@ccclass('AuthManager')
export class AuthManager extends Component {
@property
tokenStorageKey: string = 'auth_token';
private _currentUser: UserData = null;
private _apiClient: APIClient = null;
onLoad() {
this._apiClient = this.getComponent(APIClient);
this.loadStoredToken();
}
async login(email: string, password: string): Promise<AuthResult> {
const response = await this._apiClient.request<LoginResponse>('/auth/login', {
method: 'POST',
body: JSON.stringify({ email, password })
});
if (response.success) {
this.setAuthToken(response.data.token);
this._currentUser = response.data.user;
this.node.emit('auth-login-success', this._currentUser);
return { success: true, user: this._currentUser };
} else {
this.node.emit('auth-login-failed', response.error);
return { success: false, error: response.error };
}
}
async logout() {
await this._apiClient.request('/auth/logout', { method: 'POST' });
this.clearAuthToken();
this._currentUser = null;
this.node.emit('auth-logout');
}
private setAuthToken(token: string) {
sys.localStorage.setItem(this.tokenStorageKey, token);
this._apiClient.setAuthToken(token);
}
private loadStoredToken() {
const token = sys.localStorage.getItem(this.tokenStorageKey);
if (token) {
this._apiClient.setAuthToken(token);
this.validateToken();
}
}
async validateToken(): Promise<boolean> {
const response = await this._apiClient.request<UserData>('/auth/me');
if (response.success) {
this._currentUser = response.data;
return true;
} else {
this.clearAuthToken();
return false;
}
}
}
Data Synchronization
Offline Support
@ccclass('DataSyncManager')
export class DataSyncManager extends Component {
@property
syncIntervalSeconds: number = 30;
private _pendingOperations: SyncOperation[] = [];
private _lastSyncTime: number = 0;
private _isOnline: boolean = true;
onLoad() {
this.detectOnlineStatus();
this.schedule(this.syncPendingOperations, this.syncIntervalSeconds);
}
async saveData(key: string, data: any, syncImmediate: boolean = false) {
const localData = {
key,
data,
timestamp: Date.now(),
synced: false
};
this.saveToLocal(key, localData);
this._pendingOperations.push({
type: 'save',
key,
data,
timestamp: Date.now()
});
if (syncImmediate && this._isOnline) {
await this.syncPendingOperations();
}
}
async syncPendingOperations() {
if (!this._isOnline || this._pendingOperations.length === 0) {
return;
}
const operations = [...this._pendingOperations];
this._pendingOperations = [];
for (const operation of operations) {
try {
await this.syncOperation(operation);
} catch (error) {
this._pendingOperations.push(operation);
}
}
this._lastSyncTime = Date.now();
}
private detectOnlineStatus() {
this._isOnline = navigator.onLine;
window.addEventListener('online', () => {
this._isOnline = true;
this.syncPendingOperations();
});
window.addEventListener('offline', () => {
this._isOnline = false;
});
}
}
Analytics Integration
Event Tracking
@ccclass('AnalyticsManager')
export class AnalyticsManager extends Component {
@property
providers: string[] = ['firebase', 'gameanalytics'];
@property
batchSize: number = 10;
private _eventQueue: AnalyticsEvent[] = [];
trackEvent(eventName: string, parameters: any = {}) {
const event: AnalyticsEvent = {
name: eventName,
parameters: {
...parameters,
timestamp: Date.now(),
session_id: this.getSessionId()
}
};
this._eventQueue.push(event);
if (this._eventQueue.length >= this.batchSize) {
this.flushEvents();
}
}
async flushEvents() {
if (this._eventQueue.length === 0) return;
const events = [...this._eventQueue];
this._eventQueue = [];
for (const provider of this.providers) {
await this.sendToProvider(provider, events);
}
}
private async sendToProvider(provider: string, events: AnalyticsEvent[]) {
switch (provider) {
case 'firebase':
await this.sendToFirebase(events);
break;
case 'gameanalytics':
await this.sendToGameAnalytics(events);
break;
}
}
}
Handoff Guidance
To cocos-multiplayer-architect
Trigger: Real-time multiplayer needed
Handoff: "Backend integration ready. Multiplayer architecture needed for: [game features]"
To cocos-security-expert
Trigger: Security implementation needed
Handoff: "API integration complete. Security implementation needed for: [authentication/data]"
To cocos-performance-optimizer
Trigger: Network performance optimization
Handoff: "Backend connected. Network optimization needed for: [data sync/API calls]"
To cocos-analytics-specialist
Trigger: Advanced analytics needed
Handoff: "Basic tracking setup. Advanced analytics needed for: [metrics/events]"
Best Practices
- Error Handling: Always handle network failures gracefully
- Caching: Implement smart caching to reduce API calls
- Offline Support: Design for intermittent connectivity
- Security: Never store sensitive data locally
- Performance: Batch operations and use compression
- Monitoring: Track API performance and errors
- Retry Logic: Implement exponential backoff for failed requests
References
Read references/multiplayer-game-development.md when the task needs the full workflow.
Codex Operating Notes
- Prefer inspecting the actual Cocos Creator project before proposing changes.
- Keep edits scoped to the requested game system, platform, or workflow.
- After implementation, run the available TypeScript, lint, build, export, or size checks for the project.
- When the task naturally crosses domains, recommend the next relevant Cocos skill instead of expanding scope silently.