Development Guide
Comprehensive development guide for the Toto ecosystem - from local setup to production deployment.
π Project-Specific Setup: For detailed setup instructions for individual projects, see:
- Toto App Setup Guide - Main application setup
- Toto Backoffice Setup Guide - Backoffice setup
- Development Setup Guide - General ecosystem setup
π Quick Startβ
Prerequisitesβ
- Node.js: Version 18 or higher
- npm: Latest version
- Git: Version control system
- Firebase CLI: For deployment and configuration
- Code Editor: VS Code recommended
Environment Setupβ
# Install Firebase CLI
npm install -g firebase-tools
# Login to Firebase
firebase login
# Clone repositories
git clone <toto-repo>
git clone <toto-bo-repo>
git clone <toto-ai-hub-repo>
git clone <toto-wallet-repo>
π Project Structureβ
Repository Organizationβ
toto-ecosystem/
βββ toto/ # Main application
βββ toto-bo/ # Backoffice
βββ toto-ai-hub/ # AI system
βββ toto-wallet/ # Payment system
βββ toto-docs/ # Documentation
Technology Stackβ
- Frontend: Next.js 15 with TypeScript
- Backend: Next.js API Routes
- Database: Firestore
- Deployment: Firebase App Hosting
- Authentication: Firebase Auth + NextAuth.js
- AI: Multi-agent AI system
- Payments: Stellar blockchain
π§ Local Development Setupβ
For project-specific setup instructions, see:
- Toto App Setup - Main application (port 4000)
- Toto Backoffice Setup - Backoffice (port 5000)
- Development Setup - General ecosystem setup
Development Serversβ
Main App (toto-app):
cd toto-app
npm run dev # Runs on http://localhost:4000
Backoffice (toto-bo):
cd toto-bo
npm run dev # Runs on http://localhost:5000
π§ͺ Testing Setupβ
Unit Testingβ
# Run unit tests
npm run test
# Run tests with coverage
npm run test:coverage
# Run tests in watch mode
npm run test:watch
Integration Testingβ
# Run integration tests
npm run test:integration
# Run API tests
npm run test:api
E2E Testingβ
# Run E2E tests
npm run test:e2e
# Run E2E tests in headless mode
npm run test:e2e:headless
π§ Development Toolsβ
Code Qualityβ
# Lint code
npm run lint
# Fix linting issues
npm run lint:fix
# Type checking
npm run type-check
# Format code
npm run format
Database Managementβ
# Start Firestore emulator
firebase emulators:start --only firestore
# Export data
firebase firestore:export ./backup
# Import data
firebase firestore:import ./backup
API Testingβ
# Test API endpoints
npm run test:api
# Test with Postman collection
newman run postman_collection.json
π Deployment Workflowβ
Development Environmentβ
# Build for development
npm run build:dev
# Deploy to development
firebase use development
firebase deploy
Staging Environmentβ
# Build for staging
npm run build:staging
# Deploy to staging
firebase use staging
firebase deploy
Production Environmentβ
# Build for production
npm run build:prod
# Deploy to production
firebase use production
firebase deploy
π Monitoring & Debuggingβ
Loggingβ
// Structured logging
import { logger } from '@/lib/logger';
logger.info('User action', {
userId: 'user-123',
action: 'case_created',
caseId: 'case-456'
});
logger.error('Error occurred', {
error: error.message,
stack: error.stack,
context: 'api/cases'
});
Performance Monitoringβ
// Performance tracking
import { performance } from 'firebase/apphosting';
const trace = performance.trace('api_request');
trace.start();
// ... API logic
trace.stop();
Error Trackingβ
// Error monitoring
import { captureException } from '@sentry/nextjs';
try {
// ... code that might fail
} catch (error) {
captureException(error, {
tags: {
component: 'cases-api',
action: 'create-case'
}
});
throw error;
}
π Security Best Practicesβ
Authenticationβ
// JWT token validation
import { verifyIdToken } from 'firebase-admin/auth';
const validateToken = async (token: string) => {
try {
const decodedToken = await verifyIdToken(token);
return decodedToken;
} catch (error) {
throw new Error('Invalid token');
}
};
Authorizationβ
// Role-based access control
const canAccessResource = (user: User, resource: string, action: string) => {
const permissions = getUserPermissions(user.role);
return permissions.includes(`${action}_${resource}`);
};
Input Validationβ
// Request validation
import { z } from 'zod';
const createCaseSchema = z.object({
name: z.string().min(1).max(100),
description: z.string().min(1).max(1000),
guardianId: z.string().uuid(),
donationGoal: z.number().positive()
});
const validateCreateCase = (data: unknown) => {
return createCaseSchema.parse(data);
};
π Database Managementβ
Schema Designβ
// Firestore schema
interface Case {
id: string;
name: string;
description: string;
status: 'active' | 'urgent' | 'completed';
guardianId: string;
donationGoal: number;
donationsReceived: number;
createdAt: Timestamp;
updatedAt: Timestamp;
}
interface User {
id: string;
email: string;
name: string;
role: 'user' | 'guardian' | 'admin';
phone?: string;
createdAt: Timestamp;
}
Indexing Strategyβ
// Firestore indexes
// Collection: cases
// Fields: status (Ascending), createdAt (Descending)
// Query: where('status', '==', 'active').orderBy('createdAt', 'desc')
// Collection: users
// Fields: role (Ascending), createdAt (Descending)
// Query: where('role', '==', 'guardian').orderBy('createdAt', 'desc')
Data Migrationβ
// Migration script
const migrateUserRoles = async () => {
const usersRef = db.collection('users');
const snapshot = await usersRef.get();
const batch = db.batch();
snapshot.docs.forEach(doc => {
const user = doc.data();
if (!user.role) {
batch.update(doc.ref, { role: 'user' });
}
});
await batch.commit();
};
π§ͺ Testing Strategiesβ
Unit Testsβ
// Example unit test
import { render, screen } from '@testing-library/react';
import { CaseCard } from '@/components/CaseCard';
describe('CaseCard', () => {
it('renders case information correctly', () => {
const caseData = {
id: 'case-123',
name: 'Max the Dog',
description: 'Rescue case for Max',
status: 'active'
};
render(<CaseCard case={caseData} />);
expect(screen.getByText('Max the Dog')).toBeInTheDocument();
expect(screen.getByText('Rescue case for Max')).toBeInTheDocument();
});
});
Integration Testsβ
// Example integration test
import { createMocks } from 'node-mocks-http';
import handler from '@/pages/api/cases';
describe('/api/cases', () => {
it('returns cases list', async () => {
const { req, res } = createMocks({
method: 'GET',
query: { limit: '10' }
});
await handler(req, res);
expect(res._getStatusCode()).toBe(200);
expect(JSON.parse(res._getData())).toHaveProperty('cases');
});
});
E2E Testsβ
// Example E2E test
import { test, expect } from '@playwright/test';
test('user can create a case', async ({ page }) => {
await page.goto('/cases/new');
await page.fill('[data-testid="case-name"]', 'Max the Dog');
await page.fill('[data-testid="case-description"]', 'Rescue case for Max');
await page.click('[data-testid="submit-button"]');
await expect(page).toHaveURL(/\/cases\/\d+/);
await expect(page.locator('h1')).toContainText('Max the Dog');
});
π Documentationβ
Code Documentationβ
/**
* Creates a new case in the system
* @param caseData - The case data to create
* @param userId - The ID of the user creating the case
* @returns Promise<Case> - The created case
* @throws {ValidationError} - If case data is invalid
* @throws {AuthorizationError} - If user lacks permission
*/
const createCase = async (caseData: CreateCaseData, userId: string): Promise<Case> => {
// Implementation
};
API Documentationβ
/**
* @api {post} /api/cases Create Case
* @apiName CreateCase
* @apiGroup Cases
* @apiVersion 1.0.0
*
* @apiParam {String} name Case name
* @apiParam {String} description Case description
* @apiParam {String} guardianId Guardian ID
* @apiParam {Number} donationGoal Donation goal amount
*
* @apiSuccess {Object} case Created case object
* @apiSuccess {String} case.id Case ID
* @apiSuccess {String} case.name Case name
*
* @apiError {Object} 400 Validation error
* @apiError {Object} 401 Unauthorized
* @apiError {Object} 403 Forbidden
*/
π Related Resourcesβ
- Next.js: Next.js Documentation
- Firebase: Firebase Documentation
- TypeScript: TypeScript Handbook
- Testing: Jest Documentation
- Playwright: Playwright Documentation