{"id":38171798,"url":"https://github.com/ibfleming/ruby-rails-demo","last_synced_at":"2026-01-16T23:27:51.087Z","repository":{"id":319215456,"uuid":"1073293284","full_name":"ibfleming/ruby-rails-demo","owner":"ibfleming","description":null,"archived":false,"fork":false,"pushed_at":"2025-10-17T18:26:51.000Z","size":261,"stargazers_count":0,"open_issues_count":2,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-10-18T07:25:42.679Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ibfleming.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-10-09T22:34:07.000Z","updated_at":"2025-10-14T05:23:46.000Z","dependencies_parsed_at":"2025-10-18T13:19:33.851Z","dependency_job_id":"b578ba99-59eb-4359-9c0a-7ac1ed3748ca","html_url":"https://github.com/ibfleming/ruby-rails-demo","commit_stats":null,"previous_names":["ibfleming/ruby-rails-demo"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/ibfleming/ruby-rails-demo","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ibfleming%2Fruby-rails-demo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ibfleming%2Fruby-rails-demo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ibfleming%2Fruby-rails-demo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ibfleming%2Fruby-rails-demo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ibfleming","download_url":"https://codeload.github.com/ibfleming/ruby-rails-demo/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ibfleming%2Fruby-rails-demo/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28487586,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-16T22:54:02.790Z","status":"ssl_error","status_checked_at":"2026-01-16T22:50:10.344Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-01-16T23:27:50.371Z","updated_at":"2026-01-16T23:27:51.066Z","avatar_url":"https://github.com/ibfleming.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Ruby on Rails + React Demo Application\n\nA modern full-stack web application demonstrating the integration of Ruby on Rails 8 (8-0-stable branch) with React 19, featuring server-side rendering (SSR), hot module replacement (HMR), and a contemporary asset pipeline.\n\n## Table of Contents\n\n- [Overview](#overview)\n- [Ruby Version](#ruby-version)\n- [System Dependencies](#system-dependencies)\n- [Technology Stack](#technology-stack)\n- [Why React on Rails \u0026 Shakapacker?](#why-react-on-rails--shakapacker)\n- [Configuration](#configuration)\n- [Database](#database)\n- [Installation](#installation)\n- [Running the Application](#running-the-application)\n- [Testing](#testing)\n- [Deployment](#deployment)\n- [Project Structure](#project-structure)\n\n## Overview\n\nThis application showcases a modern approach to building full-stack web applications by combining Rails' robust backend framework with React's powerful frontend capabilities. It uses **React on Rails** for seamless integration and **Shakapacker** (the spiritual successor to Webpacker) for asset compilation.\n\n## Ruby Version\n\n- **Ruby 3.4.7** (Latest stable version)\n- Managed via `.ruby-version` file\n\n## System Dependencies\n\n### Core Requirements\n- **Ruby**: 3.4.7\n- **Node.js**: 22.20.0+ (managed via npm 10.9.2)\n- **Rails**: 8.0 (8-0-stable branch)\n- **SQLite3**: 2.1+ (development/test databases)\n\n### Key Gems\n- **react_on_rails** (16.1.1) - React integration with Rails\n- **shakapacker** (9.2) - Modern webpack integration for Rails\n- **propshaft** - Modern asset pipeline for Rails\n- **puma** - Web server\n- **tailwindcss-rails** - Utility-first CSS framework\n- **solid_cache**, **solid_queue**, **solid_cable** - Database-backed adapters for Rails.cache, Active Job, and Action Cable\n- **foreman** (0.90.0) - Process management for development\n- **kamal** - Docker-based deployment tool\n- **thruster** - HTTP asset caching/compression for production\n\n### JavaScript Dependencies\n- **React**: 19.2.0 (Latest version with concurrent features)\n- **React DOM**: 19.2.0\n- **Webpack**: 5.102.1+\n- **Babel**: For JavaScript transpilation\n- **SWC**: Fast Rust-based compiler (alternative to Babel)\n\n### Development Tools\n- **brakeman** - Security vulnerability scanner\n- **rubocop-rails-omakase** - Ruby code style enforcement\n- **debug** - Interactive debugging\n- **capybara** \u0026 **selenium-webdriver** - System testing\n\n## Technology Stack\n\n### Backend\n- **Ruby on Rails 8.0** - Modern web application framework\n- **SQLite3** - Lightweight database (development/test)\n- **Puma** - Multi-threaded web server\n- **Jbuilder** - JSON API builder\n\n### Frontend\n- **React 19** - Component-based UI library\n- **React on Rails** - Server-side rendering \u0026 Rails integration\n- **Tailwind CSS** - Utility-first CSS framework\n- **Webpack 5** - Module bundler via Shakapacker\n\n### Asset Pipeline\n- **Shakapacker** - Webpack integration\n- **Propshaft** - Static asset serving\n- **Babel/SWC** - JavaScript compilation\n- **PostCSS** - CSS processing\n\n### Infrastructure\n- **Docker** - Containerization (production deployment)\n- **Kamal** - Deployment orchestration\n- **Thruster** - Production web server with caching\n\n## Why React on Rails \u0026 Shakapacker?\n\n### React on Rails: The Bridge Between Two Worlds\n\n**React on Rails** is the integration layer that allows React components to seamlessly work within a Rails application. Here's why it's essential for this architecture:\n\n#### Key Benefits:\n\n1. **Server-Side Rendering (SSR)**\n   - Renders React components on the server for faster initial page loads\n   - Improves SEO by delivering fully-rendered HTML to search engines\n   - Provides better user experience with immediate content visibility\n   - Configured via `config.server_bundle_js_file` in `react_on_rails.rb`\n\n2. **Unified Data Flow**\n   - Props are passed directly from Rails controllers to React components\n   - Example: `@hello_world_props = { name: \"Stranger\" }` flows seamlessly to React\n   - Uses the `react_component()` helper in ERB views: `\u003c%= react_component(\"HelloWorld\", props: @hello_world_props, prerender: true) %\u003e`\n\n3. **Component Registration System**\n   - Automatically registers React components for use in Rails views\n   - Server bundle (`server-bundle.js`) contains all SSR-capable components\n   - Client bundle handles hydration and interactivity\n\n4. **Development Experience**\n   - Hot Module Replacement (HMR) for instant updates without page refresh\n   - React Refresh preserves component state during development\n   - Separate webpack dev server for optimal development workflow\n\n5. **Production Optimization**\n   - Automatic code splitting and lazy loading\n   - Separate client and server bundles for optimal performance\n   - Integration with Rails asset pipeline for cache management\n\n### Shakapacker: Modern Webpack for Rails\n\n**Shakapacker** is the actively maintained successor to Webpacker, providing modern webpack integration for Rails applications.\n\n#### Why Shakapacker Over Alternatives:\n\n1. **Active Maintenance**\n   - Webpacker is no longer maintained (archived)\n   - Shakapacker provides ongoing updates and webpack 5 support\n   - Community-driven with regular releases\n\n2. **Webpack 5 Support**\n   - Latest webpack features and performance improvements\n   - Module federation support\n   - Better tree-shaking and code splitting\n   - Persistent caching for faster builds\n\n3. **Flexible Build Options**\n   - Supports multiple compilers: Babel (default), SWC, or esbuild\n   - Configured via `webpack_loader` in `shakapacker.yml`\n   - Current setup: Babel with React preset\n\n4. **Development Features**\n   - Hot Module Replacement (HMR) via webpack-dev-server\n   - Live reload capability\n   - Source maps for debugging\n   - Fast incremental builds using `mtime` strategy in development\n\n5. **Production Optimization**\n   - Content hashing for cache busting\n   - CSS extraction via mini-css-extract-plugin\n   - Compression via terser-webpack-plugin\n   - Subresource integrity (SRI) support for security\n\n6. **Rails Integration**\n   - Automatic manifest.json generation for asset lookup\n   - Seamless integration with Propshaft\n   - Environment-specific configurations\n   - Supports Rails 7+ and 8.0\n\n#### The Shakapacker Architecture in This App:\n\n```\nconfig/webpack/\n├── commonWebpackConfig.js      # Shared configuration\n├── clientWebpackConfig.js      # Client-side bundle config\n├── serverWebpackConfig.js      # SSR bundle config\n├── generateWebpackConfigs.js   # Dynamic config generation\n├── development.js              # Dev-specific settings\n├── production.js               # Production optimizations\n└── webpack.config.js           # Entry point\n```\n\nThis setup enables:\n- **Dual Bundle System**: Separate client and server bundles for optimal SSR\n- **Conditional Building**: Build client-only, server-only, or both based on environment\n- **HMR Support**: Fast refresh during development without full page reloads\n- **Asset Optimization**: Automatic minification, compression, and code splitting\n\n## Configuration\n\n### Environment Files\n- `config/application.rb` - Main application configuration\n- `config/environments/` - Environment-specific settings (development, test, production)\n- `config/database.yml` - Database configuration\n- `config/shakapacker.yml` - Webpack/asset pipeline configuration\n- `config/master.key` - Encrypted credentials key (not in version control)\n\n### React on Rails Configuration\nLocated in `config/initializers/react_on_rails.rb`:\n- Server bundle: `server-bundle.js` (output to `ssr-generated/`)\n- Test command: `RAILS_ENV=test bin/shakapacker`\n- Supports prerendering with server-side rendering\n\n### Webpack Configuration\nManaged by Shakapacker in `config/webpack/`:\n- Source path: `client/` directory\n- Entry path: `client/packs/`\n- Public output: `public/packs/`\n- Development: HMR enabled on port 3035\n- Production: Content hashing, minification, compression\n\n### Tailwind CSS\n- Configuration: `app/assets/tailwind/`\n- Build output: `app/assets/builds/tailwind.css`\n- Integrated with the asset pipeline\n\n## Database\n\n### Development \u0026 Test\n- **Adapter**: SQLite3\n- **Database Files**:\n  - Development: `storage/development.sqlite3`\n  - Test: `storage/test.sqlite3`\n\n### Production\nUses multiple SQLite databases for different Rails 8 features:\n- **Primary**: `storage/production.sqlite3` - Main application data\n- **Cache**: `storage/production_cache.sqlite3` - Solid Cache (database-backed caching)\n- **Queue**: `storage/production_queue.sqlite3` - Solid Queue (background jobs)\n- **Cable**: `storage/production_cable.sqlite3` - Solid Cable (WebSocket connections)\n\n### Database Creation\n```bash\nbin/rails db:create\n```\n\n### Database Initialization\n```bash\nbin/rails db:migrate\nbin/rails db:seed  # If seed data exists\n```\n\n## Installation\n\n### Prerequisites\nEnsure Ruby 3.4.7 and Node.js 22+ are installed.\n\n### Setup Steps\n\n1. **Clone the repository**\n   ```bash\n   git clone \u003crepository-url\u003e\n   cd ruby-rails-react-demo\n   ```\n\n2. **Run the setup script**\n   ```bash\n   bin/setup\n   ```\n   This will:\n   - Install Ruby dependencies (gems)\n   - Install JavaScript dependencies (npm packages)\n   - Prepare the database\n   - Clear logs and temp files\n\n3. **Manual setup (alternative)**\n   ```bash\n   bundle install\n   npm install\n   bin/rails db:prepare\n   ```\n\n## Running the Application\n\n### Development Mode with HMR (Recommended)\n\nUses Foreman to run multiple processes concurrently:\n\n```bash\nbin/dev\n```\n\nThis starts three processes:\n- **Rails server** on port 3000\n- **Webpack dev server** (client bundle) with HMR on port 3035\n- **Webpack watch** (server bundle) for SSR\n\nThe `Procfile.dev` defines:\n```\nrails: bundle exec rails s -p 3000\nwp-client: WEBPACK_SERVE=true bin/shakapacker-dev-server\nwp-server: SERVER_BUNDLE_ONLY=yes bin/shakapacker --watch\n```\n\nAccess the application at: **http://localhost:3000**\n\n### Alternative Development Modes\n\n**Static asset compilation (no HMR)**:\n```bash\nforeman start -f Procfile.dev-static-assets\n```\n\n**Production assets in development**:\n```bash\nforeman start -f Procfile.dev-prod-assets\n```\n\n### Manual Process Management\n\nRun in separate terminals:\n\n**Terminal 1 - Rails Server**:\n```bash\nbundle exec rails server -p 3000\n```\n\n**Terminal 2 - Client Webpack Dev Server**:\n```bash\nWEBPACK_SERVE=true bin/shakapacker-dev-server\n```\n\n**Terminal 3 - Server Bundle Watch**:\n```bash\nSERVER_BUNDLE_ONLY=yes bin/shakapacker --watch\n```\n\n### Production Mode\n\n```bash\nRAILS_ENV=production rails server\n```\n\nEnsure assets are precompiled first:\n```bash\nRAILS_ENV=production rails assets:precompile\n```\n\n## Testing\n\n### Running the Test Suite\n\n**All tests**:\n```bash\nbin/rails test\n```\n\n**System tests** (with browser automation):\n```bash\nbin/rails test:system\n```\n\n**Specific test file**:\n```bash\nbin/rails test test/controllers/hello_world_controller_test.rb\n```\n\n### Test Framework\n- **Minitest** - Rails default testing framework\n- **Capybara** - Integration testing with browser simulation\n- **Selenium WebDriver** - Browser automation for system tests\n\n### Test Environment\n- Configured in `config/environments/test.rb`\n- Uses `storage/test.sqlite3` database\n- Webpack compilation controlled via `config.build_test_command` in React on Rails\n\n## Deployment\n\n### Docker Deployment (Recommended)\n\nThis application includes Docker support for containerized deployment.\n\n**Build Docker image**:\n```bash\ndocker build -t ruby_rails_react_demo .\n```\n\n**Run container**:\n```bash\ndocker run -d -p 80:80 \\\n  -e RAILS_MASTER_KEY=\u003cyour-master-key\u003e \\\n  --name ruby_rails_react_demo \\\n  ruby_rails_react_demo\n```\n\n### Kamal Deployment\n\nKamal is included for zero-downtime Docker deployments:\n\n```bash\nkamal setup    # Initial setup\nkamal deploy   # Deploy updates\n```\n\nConfiguration in `config/deploy.yml`\n\n### Production Considerations\n\n1. **Asset Precompilation**:\n   ```bash\n   RAILS_ENV=production SECRET_KEY_BASE_DUMMY=1 rails assets:precompile\n   ```\n\n2. **Environment Variables**:\n   - `RAILS_MASTER_KEY` - For encrypted credentials\n   - `SECRET_KEY_BASE` - Session encryption\n   - `DATABASE_URL` - If using external database\n\n3. **Web Server**:\n   - Uses **Thruster** by default (included with Rails 8)\n   - Provides HTTP caching, compression, and X-Sendfile\n   - Production command: `./bin/thrust ./bin/rails server`\n\n4. **Database Setup**:\n   - Ensure production databases are created\n   - Run migrations: `RAILS_ENV=production rails db:migrate`\n\n## Project Structure\n\n```\n.\n├── app/\n│   ├── assets/          # Static assets (images, stylesheets)\n│   ├── controllers/     # Rails controllers\n│   ├── models/          # ActiveRecord models\n│   ├── views/           # ERB templates\n│   │   ├── hello_world/ # Example React-integrated view\n│   │   └── layouts/     # Application layouts\n│   ├── helpers/         # View helpers\n│   ├── jobs/            # Background jobs (Solid Queue)\n│   └── mailers/         # Action Mailer classes\n│\n├── client/              # React application code\n│   ├── src/             # React components\n│   │   └── HelloWorld/  # Example component\n│   │       └── ror_components/\n│   │           ├── HelloWorld.client.jsx  # Client-side component\n│   │           ├── HelloWorld.server.jsx  # SSR entry point\n│   │           └── HelloWorld.module.css  # Component styles\n│   ├── packs/           # Webpack entry points\n│   │   ├── application.js    # Client bundle entry\n│   │   └── server-bundle.js  # Server bundle entry\n│   └── generated/       # Auto-generated React on Rails code\n│\n├── config/              # Application configuration\n│   ├── webpack/         # Webpack configuration files\n│   ├── initializers/    # Rails initializers\n│   │   └── react_on_rails.rb\n│   ├── environments/    # Environment configs\n│   ├── application.rb   # Main app config\n│   ├── routes.rb        # Route definitions\n│   ├── database.yml     # Database config\n│   └── shakapacker.yml  # Webpack/Shakapacker config\n│\n├── db/                  # Database files and migrations\n│   ├── migrate/         # Database migrations\n│   └── seeds.rb         # Seed data\n│\n├── public/              # Static files served directly\n│   └── packs/           # Compiled webpack assets\n│\n├── ssr-generated/       # Server-side rendered bundles\n│\n├── test/                # Test suite\n│   ├── controllers/     # Controller tests\n│   ├── models/          # Model tests\n│   ├── system/          # System/integration tests\n│   └── fixtures/        # Test fixtures\n│\n├── bin/                 # Executable scripts\n│   ├── dev              # Development server launcher\n│   ├── setup            # Setup script\n│   ├── rails            # Rails CLI\n│   └── shakapacker*     # Webpack commands\n│\n├── Gemfile              # Ruby dependencies\n├── package.json         # JavaScript dependencies\n├── Dockerfile           # Production container image\n├── Procfile.dev         # Development processes\n└── babel.config.js      # Babel configuration\n```\n\n### Key Directories Explained\n\n- **`client/`**: All React/JavaScript code lives here, following React on Rails conventions\n- **`config/webpack/`**: Custom webpack configurations for advanced build customization\n- **`ssr-generated/`**: Output directory for server-rendered bundles\n- **`public/packs/`**: Compiled webpack assets with manifest.json for asset lookup\n- **`app/views/hello_world/`**: Demonstrates Rails view with React component integration\n\n## Example: Hello World Component\n\n### Rails Controller\n```ruby\nclass HelloWorldController \u003c ApplicationController\n  def index\n    @hello_world_props = { name: \"Stranger\" }\n  end\nend\n```\n\n### Rails View (ERB)\n```erb\n\u003ch1\u003eHello World\u003c/h1\u003e\n\u003c%= react_component(\"HelloWorld\", props: @hello_world_props, prerender: true) %\u003e\n```\n\n### React Component\n```jsx\nconst HelloWorld = (props) =\u003e {\n  const [name, setName] = useState(props.name);\n  return (\n    \u003cdiv\u003e\n      \u003ch3\u003eHello, {name}!\u003c/h3\u003e\n      \u003cinput value={name} onChange={(e) =\u003e setName(e.target.value)} /\u003e\n    \u003c/div\u003e\n  );\n};\n```\n\nThis demonstrates:\n- **Server-side rendering** (prerender: true)\n- **Props passing** from Rails to React\n- **Client-side hydration** for interactivity\n- **State management** within React\n\n## Services\n\n### Background Jobs\n- **Solid Queue** - Database-backed job processing\n- Jobs defined in `app/jobs/`\n- Configuration: `config/queue.yml`\n\n### Caching\n- **Solid Cache** - Database-backed caching (Rails.cache)\n- Configuration: `config/cache.yml`\n\n### WebSockets\n- **Solid Cable** - Database-backed Action Cable adapter\n- Configuration: `config/cable.yml`\n\n### Asset Pipeline\n- **Propshaft** - Static asset serving\n- **Shakapacker** - JavaScript/CSS compilation via Webpack\n\n## Additional Resources\n\n- [React on Rails Documentation](https://github.com/shakacode/react_on_rails)\n- [Shakapacker Documentation](https://github.com/shakacode/shakapacker)\n- [Rails 8.0 Guides](https://guides.rubyonrails.org/)\n- [React Documentation](https://react.dev/)\n- [Tailwind CSS](https://tailwindcss.com/)\n\n## Contributing\n\n1. Fork the repository\n2. Create a feature branch (`git checkout -b feature/amazing-feature`)\n3. Commit your changes (`git commit -m 'Add amazing feature'`)\n4. Push to the branch (`git push origin feature/amazing-feature`)\n5. Open a Pull Request\n\n## License\n\nThis project is available as open source under the terms of your chosen license.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fibfleming%2Fruby-rails-demo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fibfleming%2Fruby-rails-demo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fibfleming%2Fruby-rails-demo/lists"}