GitHub Copilot Instructions for Reports Application
Project Overview
This is a Rails 7.0 application with a React/TypeScript frontend, serving as a content management and reporting system. The application integrates with various third-party services including Stripe for payments, SendGrid for emails, and various social media platforms.
Setup Instructions
To set up the development environment for this project:
# Install Ruby 3.3.9 (using rbenv, rvm, or asdf)
rbenv install 3.3.9
rbenv local 3.3.9
# Install Node.js 14.x (using nvm or asdf)
nvm install 14
nvm use 14
# Install dependencies
bundle install
yarn install
# Setup environment variables
cp example.env .env
# Edit .env with appropriate values for your environment
# Start test services (PostgreSQL and Redis)
docker compose -f docker-compose.test.yaml up -d
# Wait for services to be ready
sleep 5
# Setup database (requires PostgreSQL and Redis running)
rails db:create
rails db:migrate
rails db:seed
# Verify setup
bundle exec rspec
yarn lint
bundle exec rubocop
# Stop test services when done
docker compose -f docker-compose.test.yaml down
Technology Stack
Backend
- Ruby: 3.3.9
- Rails: 7.0
- Database: PostgreSQL
- Background Jobs: Sidekiq with Redis
- Authentication: Devise with OAuth (Google, TikTok)
- Authorization: Pundit
- Search: Ransack, Algolia
- APIs: GraphQL, REST (with Swagger/OpenAPI documentation)
Frontend
- JavaScript Framework: React ^16.13.0 with React Redux
- Language: TypeScript (mixed with JavaScript)
- Build Tool: Webpacker 4.2.2
- UI Framework: Bootstrap 3.4.1 with Bootstrap SASS
- State Management: Redux Toolkit with Redux Thunk
Testing & Quality
- Testing Framework: RSpec
- Feature Testing: Capybara with Cuprite (headless Chrome)
- Code Quality: Rubocop (Ruby), ESLint (JavaScript)
- Security: Brakeman
- API Documentation: RSwag
Project Structure
app/
├── avo/ # Avo admin panel resources
├── controllers/ # Rails controllers (API and web)
├── javascript/ # React/TypeScript frontend code
├── models/ # ActiveRecord models
├── services/ # Business logic services
├── jobs/ # Sidekiq background jobs
├── policies/ # Pundit authorization policies
├── mailers/ # Action Mailer classes
├── notifications/ # Noticed notification classes
└── views/ # ERB templates
spec/
├── api/ # API endpoint tests (RSwag)
├── models/ # Model unit tests
├── controllers/ # Controller tests
├── services/ # Service object tests
├── features/ # Capybara integration tests
└── factories/ # FactoryBot factories
Coding Standards & Conventions
Ruby/Rails
-
Style Guide: Follow Rubocop configuration (
.rubocop.yml)- Run:
bundle exec rubocop - Auto-fix:
bundle exec rubocop -a
- Run:
-
Code Organization:
- Keep controllers thin, move business logic to service objects
- Use service objects in
app/services/for complex operations - Extract shared model behavior into concerns in
app/models/concerns/ - Use Pundit policies for all authorization logic
-
Testing:
- Write RSpec tests for all new features
- Use FactoryBot for test data
- Feature tests should use Capybara for user workflows
- API tests should use RSwag format (see
spec/api/) - Aim for meaningful test coverage, not 100% coverage
-
Database:
- Always create migrations for schema changes
- Add appropriate indexes for foreign keys and frequently queried columns
- Use strong migrations practices (avoid breaking production)
-
Background Jobs:
- Use Sidekiq for asynchronous tasks
- Keep jobs idempotent when possible
- Handle job failures gracefully
JavaScript/TypeScript
-
Style Guide: Follow ESLint configuration (
.eslintrc.js)- Run:
yarn lint
- Run:
-
React Components:
- Use functional components when possible
- Leverage React Hooks for state and effects
- Keep components focused and single-purpose
- Use TypeScript for new components when possible
-
State Management:
- Use Redux Toolkit for global state
- Use Redux Thunk for async actions
- Keep Redux state normalized
-
Code Style:
- Use ES6+ features
- Prefer arrow functions
- Use destructuring for props and state
- Console statements are allowed during development
Development Workflow
Running the Application
# Install dependencies
bundle install
yarn install
# Setup database
rails db:setup
# Start the application
foreman start -f Procfile.dev
# Or individually:
# rails server
# bin/webpack-dev-server
# sidekiq -C config/sidekiq.yml
Testing
# Start test services (PostgreSQL and Redis) if not already running
docker compose -f docker-compose.test.yaml up -d
# Set required environment variables for testing
export DATABASE_URL="postgres://postgres:[email protected]:5432/reports"
export RAILS_ENV=test
export DD_TRACE_ENABLED=false
# Run all tests
bundle exec rspec
# Run specific test file
bundle exec rspec spec/models/user_spec.rb
# Run specific test
bundle exec rspec spec/models/user_spec.rb:10
# Run with format
bundle exec rspec --format documentation
# Stop test services when done
docker compose -f docker-compose.test.yaml down
Note: When running tests, make sure to:
- Start the required services (PostgreSQL and Redis) using docker compose
- Set the
DATABASE_URLto point to the test database - Set
DD_TRACE_ENABLED=falseto disable Datadog tracing during tests
Linting
# Ruby linting
bundle exec rubocop
# JavaScript linting
yarn lint
Building Assets
# Compile assets for production
rails assets:precompile
# Watch and compile assets during development
bin/webpack-dev-server
API Documentation
OpenAPI/Swagger
The application provides OpenAPI documentation for its REST APIs:
- Write API specs in
spec/api/using RSwag format - Write reusable components and schemas in
swagger/schemas/directory - Main OpenAPI specs are in
swagger/directory (e.g.,campaigns.yaml,subscriptions.yaml) - Generate documentation:
RSWAG_DRY_RUN=0 RAILS_ENV=test rails rswag - Access at
/api-docswhen running the app
Architecture Patterns
Service Objects
Use service objects for complex business logic:
class MyService
def initialize(params)
@params = params
end
def call
# Business logic here
end
end
# Usage
MyService.new(params).call
Background Jobs
class MyJob < ApplicationJob
queue_as :default
def perform(arg)
# Job logic here
end
end
# Usage
MyJob.perform_later(arg)
Authorization
Use Pundit policies for authorization:
class PostPolicy < ApplicationPolicy
def update?
user.admin? || record.author == user
end
end
# In controller
authorize @post
Common Integrations
- Stripe: Payment processing (see
app/models/concerns/stripe_*) - SendGrid: Email delivery (via Griddler for incoming)
- Cloudinary: Image hosting and transformation
- Facebook: Social login and Graph API integration
- TikTok: LoginKit integration
- Algolia: Search functionality
- Google Analytics: Analytics tracking
Environment Configuration
- Use
.envfile for local configuration (copy fromexample.env) - Never commit secrets or credentials
- Use Rails credentials for sensitive data in production
- Feature flags managed through Flipper
Important Notes
- Timezone: Application uses
Europe/Rometimezone - I18n: Supports multiple locales, managed through locale files
- Sessions: Uses Redis for session storage
- Caching: Uses Redis for caching
- File Storage: ActiveStorage with AWS S3 in production
Security Considerations
- Run Brakeman for security scanning:
brakeman - Use strong parameters in controllers
- Use
attr_encryptedfor sensitive data in database - Validate and sanitize user input
- Use CORS configuration appropriately
- Keep dependencies up to date
Getting Help
- Check existing code patterns in the codebase
- Review RSpec tests for usage examples
- Check the
docsite/directory for additional documentation - Review
Changelog.mdfor recent changes and patterns
When Writing Code
- Consistency: Match the existing code style and patterns
- Testing: Always write tests for new features
- Documentation: Update relevant documentation
- Security: Consider security implications
- Performance: Consider the performance impact of changes
- Dependencies: Avoid adding new dependencies unless necessary
- Error Handling: Handle errors gracefully with appropriate user feedback
- Logging: Use semantic logger for structured logging
- Validation: Validate data at model level, not just in forms
- Transactions: Use database transactions for operations that must succeed or fail together