This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
The name of this project is "Yeetsheet". Yeetsheet is a spreadsheet automation tool. It connects to Google Sheets, Excel, and Airtable. Core functionality: watch spreadsheets for changes, run transformations on cell data, sync data between multiple spreadsheet sources, and send notifications based on conditions. Users create automations through a visual node-based editor rather than code. Common use cases include consolidating data from multiple sheets into one, auto-populating templates when source data changes, and validating data against rules. Has a REST API for programmatic access. Data transformations support filtering, mapping, lookups, and basic aggregations.
bin/dev # Starts Rails server (port 3000), Vite, Tailwind CSS watcher, Redis, and Sidekiqbundle exec rails db:create # Create development and test databases
bundle exec rails db:migrate # Run pending migrations
bundle exec rails db:rollback # Rollback last migration
bundle exec rails db:seed # Load seed data
bundle exec rails db:setup # Create, load schema, and seed database
bundle exec rails db:reset # Drop, create, migrate, and seed databasebundle exec rubocop # Run Ruby linter
bundle exec rubocop -a # Auto-fix Ruby linting issues
bundle exec brakeman # Run security analysisbundle exec rails console # Start Rails console
bundle exec rails c # Shorthand for console
bundle exec rails routes # Show all application routes
bundle exec rails generate # List available generatorsbundle install # Install Ruby dependencies
npm install # Install JavaScript dependencies
bundle exec rails assets:precompile # Build assets for production- Rails ~8 with PostgreSQL - Server-side framework and database
- Inertia.js ~2.3 - Bridges Rails and React for SPA-like experience without API
- React ~19.2 - Frontend UI framework
- Vite ~5 - JavaScript bundler with HMR
- Tailwind CSS ~4 - Utility-first CSS framework
- Sidekiq 7 - Background job processing with scheduled jobs via sidekiq-scheduler
- Redis - Sessions, caching, and job queue
-
Inertia.js Pattern: Controllers render Inertia responses instead of JSON APIs:
render inertia: 'ComponentName', props: { data: value }
Shared data is provided via ApplicationController's
inertia_share. -
Authentication System:
- Rails 8 authentication system
- BCrypt password hashing via
has_secure_password - Password reset functionality with token expiration
Authenticationconcern handles authentication logic
-
Frontend Structure:
- Pages:
app/frontend/pages/- Inertia page components (organized by feature) - Components:
app/frontend/components/- Reusable React components - Entry points:
app/frontend/entrypoints/- Vite entry files - Types:
app/frontend/types/- TypeScript definitions - Authentication pages don't use Layout wrapper
- ShadCN Components: We use ShadCN UI components. When a necessary component is not yet added:
- First search available components at: https://ui.shadcn.com/docs/components
- Add the component with:
npx shadcn@latest add [ComponentName] - Components are installed to
app/frontend/components/ui/
- Pages:
-
Database Architecture:
- PostgreSQL
- UUID primary keys using pgcrypto extension
- JSONB columns for flexible metadata storage
- Encrypted fields for sensitive data (OAuth tokens)
-
Creating New Features:
- Generate controller:
bundle exec rails generate controller NAME - Add React page component in
app/frontend/pages/ - Define routes in
config/routes.rb - Pass data as Inertia props from controller
- Generate controller:
-
Form Handling:
- Use Inertia's
useFormhook for form state - Handle errors via props:
errors: model.errors.to_hash(true) - Show success via flash:
flash: { success: "Message" }
- Use Inertia's
-
Background Jobs:
- Use specific queues:
default,mailers, etc - Test jobs with:
bundle exec rails runner "JobName.perform_now(args)" - Monitor via Sidekiq web UI at
/sidekiq
- Use specific queues:
config/initializers/inertia_rails.rb- Inertia configurationvite.config.ts- Vite bundler configurationconfig/vite.json- Rails-specific Vite settingsProcfile.dev- Development process managementconfig/sidekiq.yml- Sidekiq queue configuration
bundle exec rails generate controller NAME [action action]
bundle exec rails generate model NAME [field:type field:type]
bundle exec rails generate migration NAME
bundle exec rails generate job NAMEbin/rails test- Run all testsbin/rails test:db- Run tests with database resetbin/rails test:system- Run system tests only (use sparingly - they take longer)bin/rails test test/models/account_test.rb- Run specific test filebin/rails test test/models/account_test.rb:42- Run specific test at linebin/ci- this runs all tests and other CI. This is the prerequisite to merging tomain
- ALWAYS use Minitest + fixtures (NEVER RSpec or factories)
- Keep fixtures minimal (2-3 per model for base cases)
- Create edge cases on-the-fly within test context
- Use Rails helpers for large fixture creation needs
- Write minimal, effective tests - system tests extremely sparingly, only for application critical flows
- Only test critical and important code paths
- Test boundaries correctly:
- Commands: test they were called with correct params
- Queries: test output
- Don't test implementation details of other classes
# GOOD - Testing critical domain business logic
test "good test example" do
DomainModel.any_instance.expects(:some_operation).returns([]).once
assert_difference "DomainModel.count", 2 do
DomainModel.do_something
end
end
# BAD - Testing ActiveRecord functionality
test "bad low value test" do
record = DomainModel.new(attr1: "value1", attr2: "value2")
assert record.save
end- Use
mochagem and VCR for external services (only in the providers layer) - Prefer
OpenStructfor mock instances - Only mock what's necessary
- Run
bundle exec rubocop -aafter significant code changes - Use
.rubocop.ymlfor style configuration - Security scanning with
bundle exec brakeman
- All tables use UUID primary keys (pgcrypto extension)
- Timestamps use
timestamptzfor timezone awareness - JSONB columns for flexible metadata storage
- Comprehensive indexing strategy for performance
- Encrypted fields for sensitive data (OAuth tokens, API keys)
When code examples, setup or configuration steps, or library/API documentation are requested, use the Context7 mcp server to get the information.
- Compare new code with existing rules
- Identify patterns that should be standardized
- Look for references to external documentation
- Check for consistent error handling patterns
- Monitor test patterns and coverage
Please ensure your implementation Always Works™ for: $ARGUMENTS.
Follow this systematic approach:
- "Should work" ≠ "does work" - Pattern matching isn't enough
- I'm not paid to write code, I'm paid to solve problems
- Untested code is just a guess, not a solution
- Did I run/build the code?
- Did I trigger the exact feature I changed?
- Did I see the expected result with my own observation (including GUI)?
- Did I check for error messages?
- Would I bet $100 this works?
- "This should work now"
- "I've fixed the issue" (especially 2nd+ time)
- "Try it now" (without trying it myself)
- "The logic is correct so..."
- UI Changes: Actually click the button/link/form
- API Changes: Make the actual API call
- Data Changes: Query the database
- Logic Changes: Run the specific scenario
- Config Changes: Restart and verify it loads
"If the user records trying this and it fails, will I feel embarrassed to see his face?"
- Time saved skipping tests: 30 seconds
- Time wasted when it doesn't work: 30 minutes
- User trust lost: Immeasurable
A user describing a bug for the third time isn't thinking "this AI is trying hard" - they're thinking "why am I wasting time with this incompetent tool?"
- Always use Tailwind classes instead of inline styles
- Before git committing and pushing any code, run rubocop with autofix
- Always use minitest
- All React components and views should be TSX
- Ask lots of clarifying questions when planning. The more the better. Make extensive use of AskUserQuestionTool to gather requirements and specifications. You can't ask too many questions.
- Do not use Kamal or Docker
- Do not use Rails "solid_*" components/systems
- Use Playwright to regularly verify E2E functionality
- When something new is added that will need some type of setup, ensure it's added to @README.md
When ending a work session, you MUST complete ALL steps below. Work is NOT complete until git push succeeds.
MANDATORY WORKFLOW:
- File issues for remaining work - Create issues for anything that needs follow-up
- Run quality gates (if code changed) - Tests, linters, builds
- Update issue status - Close finished work, update in-progress items
- PUSH TO REMOTE - This is MANDATORY:
git pull --rebase bd sync git push git status # MUST show "up to date with origin" - Clean up - Clear stashes, prune remote branches
- Verify - All changes committed AND pushed
- Hand off - Provide context for next session
CRITICAL RULES:
- Work is NOT complete until
git pushsucceeds - NEVER stop before pushing - that leaves work stranded locally
- NEVER say "ready to push when you are" - YOU must push
- If push fails, resolve and retry until it succeeds