Files
adopt-a-street/AGENTS.md
William Valentin bb9c8ec1c3 feat: Migrate from Socket.IO to Server-Sent Events (SSE)
- Replace Socket.IO with SSE for real-time server-to-client communication
- Add SSE service with client management and topic-based subscriptions
- Implement SSE authentication middleware and streaming endpoints
- Update all backend routes to emit SSE events instead of Socket.IO
- Create SSE context provider for frontend with EventSource API
- Update all frontend components to use SSE instead of Socket.IO
- Add comprehensive SSE tests for both backend and frontend
- Remove Socket.IO dependencies and legacy files
- Update documentation to reflect SSE architecture

Benefits:
- Simpler architecture using native browser EventSource API
- Lower bundle size (removed socket.io-client dependency)
- Better compatibility with reverse proxies and load balancers
- Reduced resource usage for Raspberry Pi deployment
- Standard HTTP-based real-time communication

🤖 Generated with [AI Assistant]

Co-Authored-By: AI Assistant <noreply@ai-assistant.com>
2025-12-05 22:49:22 -08:00

11 KiB

Agent Guidelines for Adopt-a-Street

This file provides comprehensive guidance for all AI models (Claude, Gemini, and others) when working with code in this repository.

Project Overview

Adopt-a-Street is a community street adoption platform with a React frontend and Node.js/Express backend. Users can adopt streets, complete maintenance tasks, participate in events, and earn rewards through a gamification system.

Development Status

This project is in active development and NOT in production. Breaking changes are allowed and encouraged to improve code quality, architecture, and maintainability. Feel free to:

  • Refactor code structures and patterns
  • Change APIs and data models
  • Update dependencies and migrate to better solutions
  • Restructure the codebase for improved architecture
  • Make backward-incompatible changes that enhance the application

Development Workflow

IMPORTANT: Commit to Git After Every Feature/Fix/Update

After implementing any feature, fix, or update, you MUST:

  1. Build and test the changes:

    # Backend
    cd backend && bun test
    
    # Frontend
    cd frontend && bun run build
    
  2. Create a git commit with a descriptive message:

    git add <files>
    git commit -m "feat/fix/docs: descriptive message
    
    Detailed explanation of changes...
    
    🤖 Generated with [AI Assistant]
    
    Co-Authored-By: AI Assistant <noreply@ai-assistant.com>"
    
  3. Use conventional commit prefixes:

    • feat: - New features
    • fix: - Bug fixes
    • docs: - Documentation changes
    • test: - Test additions or updates
    • refactor: - Code refactoring
    • chore: - Maintenance tasks
    • perf: - Performance improvements
  4. Commit frequency: Create commits for each logical unit of work. Don't batch multiple unrelated changes into one commit.

  5. Push regularly: Push commits to origin after completing features or at end of session:

    git push origin main
    

This ensures:

  • Clear history of all changes
  • Easy rollback if needed
  • Better collaboration and code review
  • Deployment tracking
  • CI/CD pipeline triggers

Commands

Backend (from /backend)

  • bun test - Run all tests
  • bunx eslint . - Run linter
  • node server.js - Start development server

Frontend (from /frontend)

  • bun test - Run all tests in watch mode
  • bun test -- --testNamePattern="test name" - Run single test
  • bun run build - Production build
  • bun start - Start development server

Code Style

Backend (Node.js/Express)

  • Imports: Use require() for CommonJS modules; group by: built-in → third-party → local (models, middleware, routes)
  • Formatting: 2-space indent, trailing commas in objects/arrays, double quotes for strings
  • Naming: camelCase for variables/functions, PascalCase for models/schemas, lowercase for routes
  • Error Handling: Use try-catch in async routes; log errors with console.error(err.message); return generic "Server error" (500) or specific error messages (400)
  • Responses: Return JSON with res.json() for success, res.status(code).json({ msg: "..." }) or res.status(code).send("...") for errors

Frontend (React)

  • Imports: ES6 import; group by: React → third-party → local components → context → styles
  • Components: Functional components with hooks; export default at end
  • Naming: PascalCase for components, camelCase for functions/variables
  • State: Use useState for local state, Context API for global state (AuthContext pattern)
  • Error Handling: Handle errors in async operations, display user-friendly messages

General

  • Types: No TypeScript configured; use JSDoc comments for complex functions if needed
  • ESLint: Follows eslint config in backend; "no-unused-vars" and "no-undef" set to warn

Architecture

Monorepo Structure

  • frontend/: React application (Create React App)
  • backend/: Express API server with CouchDB

Backend Architecture

The backend follows a standard Express MVC pattern:

  • server.js: Main entry point with SSE (Server-Sent Events) for real-time updates
  • routes/: API route handlers for auth, streets, tasks, posts, events, rewards, reports, ai, payments, users
  • models/: CouchDB document models (User, Street, Task, Post, Event, Reward, Report)
  • services/couchdbService.js: CouchDB connection and document management service
  • middleware/auth.js: JWT authentication middleware using x-auth-token header

Frontend Architecture

React SPA using React Router v6:

  • App.js: Main router with client-side routing
  • context/AuthContext.js: Global authentication state management
  • context/SSEContext.js: SSE (Server-Sent Events) real-time connection management
  • components/: Feature components (MapView, TaskList, SocialFeed, Profile, Events, Rewards, Premium, Login, Register, Navbar, ErrorBoundary)
  • Real-time updates via SSE (Server-Sent Events) for events, posts, and tasks
  • Interactive map with Leaflet for street visualization
  • Comprehensive error handling with ErrorBoundary

Authentication flow: JWT tokens stored in localStorage and sent via x-auth-token header on all API requests.

Frontend proxies API requests to http://localhost:5000 in development.

Note: This is a true monorepo - both frontend and backend are tracked in the same Git repository for simplified development and deployment.

Environment Variables

Backend requires .env file:

  • COUCHDB_URL: CouchDB connection URL (e.g., http://localhost:5984)
  • COUCHDB_DB_NAME: CouchDB database name (e.g., adopt-a-street)
  • JWT_SECRET: Secret for JWT signing
  • PORT (optional): Server port (defaults to 5000)

API Endpoints

  • /api/auth: Registration, login, and user authentication
  • /api/streets: Street data and adoption management
  • /api/tasks: Maintenance task CRUD operations
  • /api/posts: Social feed posts
  • /api/events: Community events with SSE real-time updates
  • /api/rewards: Points and rewards system
  • /api/reports: Street condition reports
  • /api/ai: AI-powered suggestions and insights
  • /api/payments: Premium subscription management (currently mocked)
  • /api/users: User profile management

Key Technologies

  • Frontend: React 19, React Router v6, Leaflet (mapping), Axios, Stripe.js
  • Backend: Express, CouchDB (NoSQL database), Nano (CouchDB client), JWT, bcryptjs, Stripe, Multer (file uploads)
  • Testing: React Testing Library, Jest

SSE Real-time Events

Real-time features using Server-Sent Events:

  • Topics: Clients subscribe to topics via /api/sse/subscribe
  • Event Types: eventUpdate, taskUpdate, newPost, postUpdate, newComment, streetUpdate, achievementUnlocked
  • Connection: /api/sse/stream with JWT authentication
  • Heartbeat: 30-second keepalive messages

Deployment

Kubernetes Raspberry Pi Cluster

This application is deployed on a Kubernetes cluster running on Raspberry Pi hardware:

Cluster Configuration:

  • 2x Raspberry Pi 5 (8GB RAM) - Primary worker nodes for application workloads
  • 1x Raspberry Pi 3B+ (1GB RAM) - Worker node for lightweight services

Architecture Considerations:

  • ARM64 architecture (Pi 5) and ARMv7 architecture (Pi 3B+)
  • Multi-arch Docker images required (linux/arm64, linux/arm/v7)
  • Resource-constrained environment - optimize for low memory usage
  • Frontend and backend should be containerized separately
  • CouchDB should run as a StatefulSet with persistent storage
  • Consider resource limits and requests appropriate for Pi hardware

Deployment Strategy:

  • Use Kubernetes manifests or Helm charts
  • Implement horizontal pod autoscaling based on available resources
  • Place memory-intensive workloads (backend, CouchDB) on Pi 5 nodes
  • Place frontend static serving on any node (lightweight)
  • Use NodeAffinity/NodeSelector to control pod placement
  • Implement health checks and readiness probes
  • Use ConfigMaps for environment variables
  • Use Secrets for sensitive data (JWT_SECRET, CLOUDINARY credentials, CouchDB credentials, etc.)

See deployment documentation for Kubernetes manifests and deployment instructions.

Testing

Comprehensive test infrastructure is in place for both backend and frontend.

Running Tests

Backend:

cd backend
bun test              # Run all tests
bun run test:coverage # Run with coverage report
bun run test:watch    # Run in watch mode

Frontend:

cd frontend
bun test              # Run in watch mode
bun run test:coverage # Run with coverage report

Test Coverage

  • Backend: ~55% coverage (109 passing tests)

    • Route tests for auth, streets, tasks, posts, events, rewards, reports
    • Model tests for User, Street, Task, Post
    • Middleware tests for authentication
    • Using Jest + Supertest + CouchDB testing utilities
  • Frontend: MSW infrastructure in place

    • Component tests for Login, Register, ErrorBoundary
    • Integration tests for authentication flow
    • Using React Testing Library + Jest + MSW

See TESTING.md for detailed testing documentation.

Gemini AI Agents

Gemini LLM can be used to spawn AI agents for various tasks. There are two models available:

  • gemini-2.5-flash: Quick responses that don't require thinking mode
  • gemini-2.5-pro: Thinking model for more demanding tasks

Usage Commands

gemini --model gemini-2.5-flash -p "<PROMPT>"
gemini --model gemini-2.5-pro -p "<PROMPT>"

Use flash for simple, quick tasks and pro for complex reasoning, analysis, or creative tasks that require deeper thinking.

AI Assistant Guidelines

For All AI Models

  1. Always read existing code before making changes to understand patterns and conventions
  2. Follow the established code style and architectural patterns
  3. Test your changes before committing
  4. Commit frequently with descriptive messages following the conventional commit format
  5. Ask for clarification if requirements are unclear
  6. Document complex decisions in code comments or commit messages
  7. Consider performance implications of changes, especially for the Raspberry Pi deployment
  8. Maintain backward compatibility where possible, but remember breaking changes are allowed in development

Task Prioritization

  1. High Priority: Security fixes, critical bugs, deployment blockers
  2. Medium Priority: New features, performance improvements, test coverage
  3. Low Priority: Code refactoring, documentation updates, minor UI improvements

Communication

  • Be clear and concise in commit messages and code comments
  • Explain the "why" behind complex changes
  • Flag any potential breaking changes or security concerns
  • Suggest follow-up tasks or improvements when relevant

Quality Assurance

  • Run linting and tests before committing
  • Ensure code follows established patterns
  • Verify functionality works end-to-end
  • Check for potential security vulnerabilities
  • Consider edge cases and error handling

Remember: This is a collaborative development environment. Your contributions help build a robust community platform for street adoption and maintenance.