- 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>
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:
-
Build and test the changes:
# Backend cd backend && bun test # Frontend cd frontend && bun run build -
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>" -
Use conventional commit prefixes:
feat:- New featuresfix:- Bug fixesdocs:- Documentation changestest:- Test additions or updatesrefactor:- Code refactoringchore:- Maintenance tasksperf:- Performance improvements
-
Commit frequency: Create commits for each logical unit of work. Don't batch multiple unrelated changes into one commit.
-
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 testsbunx eslint .- Run linternode server.js- Start development server
Frontend (from /frontend)
bun test- Run all tests in watch modebun test -- --testNamePattern="test name"- Run single testbun run build- Production buildbun 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: "..." })orres.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
useStatefor 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 updatesroutes/: API route handlers for auth, streets, tasks, posts, events, rewards, reports, ai, payments, usersmodels/: CouchDB document models (User, Street, Task, Post, Event, Reward, Report)services/couchdbService.js: CouchDB connection and document management servicemiddleware/auth.js: JWT authentication middleware usingx-auth-tokenheader
Frontend Architecture
React SPA using React Router v6:
App.js: Main router with client-side routingcontext/AuthContext.js: Global authentication state managementcontext/SSEContext.js: SSE (Server-Sent Events) real-time connection managementcomponents/: 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 signingPORT(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/streamwith 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
- Always read existing code before making changes to understand patterns and conventions
- Follow the established code style and architectural patterns
- Test your changes before committing
- Commit frequently with descriptive messages following the conventional commit format
- Ask for clarification if requirements are unclear
- Document complex decisions in code comments or commit messages
- Consider performance implications of changes, especially for the Raspberry Pi deployment
- Maintain backward compatibility where possible, but remember breaking changes are allowed in development
Task Prioritization
- High Priority: Security fixes, critical bugs, deployment blockers
- Medium Priority: New features, performance improvements, test coverage
- 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.