Getting Started
    Core Concepts
    Building Features
    API Reference
    Configuration
    Deployment
    Upgrading
    Migrating
    Pro
    Misc
    Shakacode logoShakaCodeDeveloped by

    Copyright 2026 ShakaCode

    Press Ctrl+K to search anytime
    Burger
    ShakaCode WebsiteCommunityReact on Rails ProGithubSmallView on Github
    Documentation
      Getting Started
      Core Concepts
      Building Features
      API Reference
      Configuration
      Deployment
      Upgrading
      Migrating
      Pro
      Misc
      Shakacode logoShakaCodeDeveloped by

      Copyright 2026 ShakaCode

      Recommended Project Structure

      React on Rails supports two main organizational approaches for your React components.

      The current React on Rails generator creates a component-based structure optimized for automatic bundle generation:

      app/javascript/
      ├── src/
      │   ├── HelloWorld/
      │   │   ├── HelloWorld.module.css
      │   │   └── ror_components/          # Auto-discovered by React on Rails
      │   │       ├── HelloWorld.jsx       # Client & server rendering
      │   │       └── HelloWorld.server.js # Optional: server-only code
      │   └── AnotherComponent/
      │       └── ror_components/
      │           ├── AnotherComponent.client.jsx  # Client-only rendering
      │           └── AnotherComponent.server.jsx  # Server-only rendering
      └── packs/
          ├── generated/                   # Auto-generated entry points (gitignored)
          │   ├── HelloWorld.js
          │   └── AnotherComponent.js
          └── server-bundle.js             # Server rendering entry point

      Key features:

      • Components in ror_components/ directories are automatically discovered and registered
      • Each component gets its own webpack bundle for optimal code splitting
      • No manual ReactOnRails.register() calls needed
      • Supports separate .client.jsx and .server.jsx files for different rendering logic

      For details, see Auto-Bundling Guide and Generator Details.

      Traditional Manual Structure (Legacy)

      For projects requiring explicit control over webpack entry points:

      app/javascript/
      ├── bundles/
      │   └── HelloWorld/
      │       ├── components/
      │       │   └── HelloWorld.jsx
      │       └── startup/
      │           └── registration.js      # Manual ReactOnRails.register()
      └── packs/
          └── hello-world-bundle.js        # Webpack entry point

      This approach requires manual component registration and webpack configuration but offers complete control over bundling strategy.

      Choosing Your Structure

      Use modern auto-bundling if:

      • Starting a new project
      • Want automatic code splitting per component
      • Prefer convention over configuration
      • Want to minimize boilerplate

      Use traditional manual structure if:

      • Have complex custom webpack requirements
      • Need fine-grained control over bundle composition
      • Migrating from older React on Rails versions

      For most projects, we recommend the modern auto-bundling approach.

      Steps to convert from the generator defaults to use a /client directory for source code

      1. Move the directory:
      mv app/javascript client
      1. Edit your /config/shakapacker.yml file. Change the default/source_path:
      source_path: client

      Styling Your Components

      React on Rails supports multiple approaches for styling your components. The modern recommended approach uses CSS Modules with co-located stylesheets.

      The generator creates components with CSS Module support out of the box:

      app/javascript/src/HelloWorld/
      ├── ror_components/
      │   ├── HelloWorld.client.jsx
      │   └── HelloWorld.module.css    # Co-located with component

      Example usage:

      import React from 'react';
      import * as style from './HelloWorld.module.css';
      
      const HelloWorld = () => <label className={style.bright}>Hello World</label>;

      Benefits:

      • Scoped styles: Class names are automatically scoped to prevent conflicts
      • Co-location: Styles live next to their components for better organization
      • Type safety: Works seamlessly with TypeScript
      • Hot reloading: Style changes reload instantly without page refresh
      • Zero configuration: Works out of the box with the generator

      Alternative: Rails Asset Pipeline

      You can continue using Rails' traditional asset pipeline with sass-rails or similar gems:

      <%# app/views/layouts/application.html.erb %>
      <%= stylesheet_link_tag 'application', media: 'all' %>

      Use this approach when:

      • You have existing Rails stylesheets you want to keep
      • You prefer keeping styles completely separate from JavaScript
      • You don't need component-scoped styling

      Advanced: Global Styles with Webpack

      For global styles (fonts, resets, variables), you can create additional webpack entry points:

      app/javascript/
      ├── packs/
      │   ├── application.css    # Global styles
      │   └── server-bundle.js
      └── src/
          └── HelloWorld/
              └── ror_components/
                  ├── HelloWorld.jsx
                  └── HelloWorld.module.css

      Import global styles in your layout:

      <%= stylesheet_pack_tag 'application' %>