Skip to content

Fix RSC install generator layout wiring and post-install helper hint#2429

Merged
ihabadham merged 7 commits intomasterfrom
codex/fix-rsc-generator-layout-and-message
Feb 23, 2026
Merged

Fix RSC install generator layout wiring and post-install helper hint#2429
ihabadham merged 7 commits intomasterfrom
codex/fix-rsc-generator-layout-and-message

Conversation

@justin808
Copy link
Member

@justin808 justin808 commented Feb 16, 2026

Summary

  • always copy app/views/layouts/hello_world.html.erb during install so --rsc apps have a pack-driven layout available
  • set generated HelloServerController to layout "hello_world" so fresh Rails apps do not depend on javascript_pack_tag "application"
  • update post-install messaging to show stream_react_component(...) when --rsc is used
  • extend generator specs to assert the RSC layout/controller behavior and install message helper output

Why

Generating a fresh Rails app with rails g react_on_rails:install --rsc --typescript produced a runtime Shakapacker::Manifest::MissingEntryError because application layout references javascript_pack_tag "application" while no application pack is generated in this flow.

Verification

  • mise exec ruby@3.3 -- bundle exec rspec react_on_rails/spec/react_on_rails/generators/install_generator_spec.rb react_on_rails/spec/react_on_rails/generators/generator_messages_spec.rb
  • mise exec ruby@3.3 -- bundle exec rubocop react_on_rails/lib/generators/react_on_rails/base_generator.rb react_on_rails/lib/generators/react_on_rails/templates/rsc/base/app/controllers/hello_server_controller.rb react_on_rails/lib/generators/react_on_rails/generator_messages.rb react_on_rails/lib/generators/react_on_rails/install_generator.rb react_on_rails/spec/react_on_rails/generators/install_generator_spec.rb react_on_rails/spec/react_on_rails/generators/generator_messages_spec.rb

Summary by CodeRabbit

  • New Features

    • Post-install messages now show the appropriate render example for React Server Components (RSC) vs non-RSC installs.
  • Improvements

    • Installer guidance dynamically reflects RSC vs non-RSC setups for clearer next steps.
  • Bug Fixes

    • Installer now ensures the app layout and controller wiring for server-rendered setups are created to prevent missing-layout errors on fresh installs.
  • Tests

    • Added tests verifying RSC and non-RSC post-install messages and layout/controller behavior.

Note

Low Risk
Generator/template and messaging changes with limited runtime impact beyond newly generated apps; risk is mainly incorrect layout selection affecting fresh RSC installs.

Overview
Fixes a fresh rails g react_on_rails:install --rsc runtime failure where HelloServerController could fall back to Rails’ default application.html.erb (referencing a non-existent application pack), causing Shakapacker::Manifest::MissingEntryError.

The generator now always copies app/views/layouts/hello_world.html.erb, sets the RSC HelloServerController template to layout "hello_world", and updates the post-install message to show stream_react_component(...) for RSC (with new specs covering the updated messaging and RSC file generation).

Written by Cursor Bugbot for commit 95306eb. Configure here.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 16, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 95306eb and 6000172.

📒 Files selected for processing (2)
  • react_on_rails/lib/generators/react_on_rails/generator_messages.rb
  • react_on_rails/spec/react_on_rails/generators/install_generator_spec.rb
🚧 Files skipped from review as they are similar to previous changes (1)
  • react_on_rails/spec/react_on_rails/generators/install_generator_spec.rb

Walkthrough

The generator now always copies app/views/layouts/hello_world.html.erb; it generates hello_world_controller.rb only when not an RSC-without-Redux install. HelloServerController is set to layout "hello_world". Post-install messaging selects stream_react_component for RSC installs or react_component(..., prerender: true) otherwise.

Changes

Cohort / File(s) Summary
Layout & Controller Generation
react_on_rails/lib/generators/react_on_rails/base_generator.rb, react_on_rails/lib/generators/react_on_rails/templates/rsc/base/app/controllers/hello_server_controller.rb
Always adds app/views/layouts/hello_world.html.erb to generated base files. hello_world_controller.rb is added only unless using RSC without Redux. HelloServerController now declares layout "hello_world".
Post-install Messages & Generator
react_on_rails/lib/generators/react_on_rails/generator_messages.rb, react_on_rails/lib/generators/react_on_rails/install_generator.rb
helpful_message_after_installation signature gains rsc:; message construction uses build_render_example and a dynamic label to output stream_react_component for RSC installs or react_component(..., prerender: true) otherwise. install_generator forwards rsc: use_rsc?.
Specs
react_on_rails/spec/react_on_rails/generators/generator_messages_spec.rb, react_on_rails/spec/react_on_rails/generators/install_generator_spec.rb
Adds tests asserting RSC message contains stream_react_component and excludes prerender: true; non-RSC message contains react_component(..., prerender: true). Tests updated to expect hello_world.html.erb generation and HelloServerController using the layout across generator options.
Changelog
CHANGELOG.md
Adds an Unreleased Fixed entry describing the RSC generator layout wiring fix and updated post-install messaging.
Manifest / Misc
manifest_file
Minor manifest adjustments (+6/-5).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐇 I hopped a patch across the rails,

a layout landed, tidy trails,
whether stream or prerendered art,
controllers find their proper part,
tiny whiskers cheer the build’s new start 🥕

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly describes the main fix: addressing RSC generator layout wiring issues and updating post-install messaging, which aligns with the core changes across multiple files.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch codex/fix-rsc-generator-layout-and-message

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@greptile-apps
Copy link

greptile-apps bot commented Feb 16, 2026

Greptile Summary

Fixes RSC install generator to prevent Shakapacker::Manifest::MissingEntryError on fresh Rails apps by ensuring the hello_world.html.erb layout is always generated and setting HelloServerController to use it.

Key changes:

  • Always copies app/views/layouts/hello_world.html.erb during install (previously skipped for RSC-only setups)
  • Sets generated HelloServerController to layout "hello_world" so fresh Rails apps don't depend on non-existent javascript_pack_tag "application"
  • Updates post-install messaging to show stream_react_component(...) when --rsc is used instead of react_component(...)
  • Extends generator specs to assert RSC layout/controller behavior and install message helper output

Impact:
This resolves a critical runtime error when running rails g react_on_rails:install --rsc --typescript on a fresh Rails app, where the default application layout would reference a non-existent application pack.

Confidence Score: 5/5

  • This PR is safe to merge with minimal risk
  • The changes are well-targeted to fix a specific runtime error, with comprehensive test coverage added for both the fix and the messaging changes. All modifications are isolated to generator code with clear logic flow, and the fix aligns with the framework's architecture by using a pack-driven layout instead of hardcoded dependencies.
  • No files require special attention

Important Files Changed

Filename Overview
react_on_rails/lib/generators/react_on_rails/base_generator.rb Refactored layout file copying logic to always include hello_world.html.erb for RSC apps, ensuring generated packs can be injected without hardcoded application.js dependency
react_on_rails/lib/generators/react_on_rails/generator_messages.rb Added rsc parameter and build_render_example method to display stream_react_component in RSC install messages instead of react_component
react_on_rails/lib/generators/react_on_rails/templates/rsc/base/app/controllers/hello_server_controller.rb Added layout "hello_world" declaration to prevent MissingEntryError on fresh Rails apps by using pack-driven layout instead of application layout
react_on_rails/spec/react_on_rails/generators/install_generator_spec.rb Extended RSC generator specs to assert hello_world.html.erb layout creation and layout "hello_world" declaration in HelloServerController

Flowchart

flowchart TD
    A[rails g react_on_rails:install --rsc] --> B{RSC Flag?}
    B -->|Yes| C[base_generator: Copy hello_world.html.erb]
    B -->|No| D[base_generator: Copy hello_world.html.erb]
    
    C --> E[Generate HelloServerController template]
    E --> F[Set layout hello_world]
    
    F --> G[install_generator: Call helpful_message_after_installation]
    G --> H[Pass rsc: true]
    
    H --> I[generator_messages: build_render_example]
    I --> J[Return stream_react_component helper]
    
    D --> K[Generate HelloWorldController]
    K --> L[Uses default application layout]
    L --> M[install_generator: Call helpful_message_after_installation]
    M --> N[Pass rsc: false]
    N --> O[generator_messages: build_render_example]
    O --> P[Return react_component helper]
    
    F --> Q[Fresh Rails app runs without MissingEntryError]
    L --> R[Uses javascript_pack_tag application]
Loading

Last reviewed commit: 1722d8a

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@react_on_rails/lib/generators/react_on_rails/generator_messages.rb`:
- Around line 92-95: The generator example incorrectly shows passing prerender:
true for stream_react_component; update build_render_example to omit the
prerender param when helper_name is "stream_react_component" (i.e., when rsc is
true) by returning "<%= #{helper_name}(\"#{component_name}\", props:
@#{route}_props) %>" for that case; change the logic in the build_render_example
method (referenced by its name and the helper_name/rsc variables) so it doesn't
include "prerender: true" for stream_react_component.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@CHANGELOG.md`:
- Line 32: Update the CHANGELOG entry to correct the root cause: state that
HelloServerController lacked an explicit layout and fell back to Rails'
application.html.erb (which contained javascript_pack_tag "application" not
produced by the RSC flow), and that the fix was to declare layout "hello_world"
on HelloServerController and ensure hello_world.html.erb is always copied by the
generator; also mention the layout now references the correct pack
(hello-server-bundle) and that post-install messaging was improved to mention
react_on_rails_helper for RSC setups.

@justin808 justin808 force-pushed the codex/fix-rsc-generator-layout-and-message branch from c297787 to 95306eb Compare February 23, 2026 00:37
@claude
Copy link

claude bot commented Feb 23, 2026

PR Review: Fix RSC install generator layout wiring and post-install helper hint

The root cause fix is correct and well-targeted. The MissingEntryError arose because the RSC flow doesn't generate an application pack, so falling back to Rails' default application.html.erb (which calls javascript_pack_tag "application") breaks. Unconditionally copying hello_world.html.erb and explicitly declaring layout "hello_world" in HelloServerController resolves this cleanly and aligns with how HelloWorldController already behaves.

Notable Issues

1. Test coverage gap for --rsc combinations

The with --rsc --redux, with --rsc --typescript, and with --rsc --rspack spec contexts assert a "copies common files" set that does not include app/views/layouts/hello_world.html.erb. Since the fix makes this layout unconditional for all generator runs (including RSC combos), these three contexts should each include the layout assertion. Currently only the plain --rsc context (line 694–699) verifies it.

2. Redundant branching in build_render_example

def build_render_example(component_name:, route:, rsc:)
  helper_name = rsc ? "stream_react_component" : "react_component"
  if rsc
    "<%= #{helper_name}(\"#{component_name}\", props: @#{route}_props) %>"
  else
    "<%= #{helper_name}(\"#{component_name}\", props: @#{route}_props, prerender: true) %>"
  end
end

The helper_name assignment and the subsequent if rsc both branch on the same boolean. helper_name ends up used exactly once per branch, so the variable adds noise rather than clarity. The two branches can each hardcode the helper name directly, removing the need for the intermediate variable.

Minor Observations

  • The spec assertion expect(message).to include('stream_react_component("HelloServer", props: @hello_server_props)') is correct but would be slightly more precise if it included the surrounding ERB tags (<%= ... %>) to guard against false positives from unrelated strings.
  • CHANGELOG entry is clear and includes the PR link and author attribution — looks good.


private

def build_render_example(component_name:, route:, rsc:)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

helper_name is set by branching on rsc, then immediately the same if rsc branch decides which string to produce — helper_name is used exactly once in each branch. The intermediate variable adds indirection without benefit. Each branch can embed the helper name directly:

Suggested change
def build_render_example(component_name:, route:, rsc:)
def build_render_example(component_name:, route:, rsc:)
if rsc
"<%= stream_react_component(\"#{component_name}\", props: @#{route}_props) %>"
else
"<%= react_component(\"#{component_name}\", props: @#{route}_props, prerender: true) %>"
end
end

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
react_on_rails/spec/react_on_rails/generators/install_generator_spec.rb (1)

806-810: Missing app/views/layouts/hello_world.html.erb assertion in --rsc --redux "copies common files" test.

base_generator.rb now adds the layout unconditionally for every install flow, so the --rsc --redux combo should assert its presence too. The --rsc context already covers it (line 699), but RSC+Redux is a distinct path that also exercises the same code path — and is the scenario most likely to regress.

🧪 Suggested test coverage addition
     it "copies common files" do
       %w[config/initializers/react_on_rails.rb
          Procfile.dev
          Procfile.dev-static-assets
-         Procfile.dev-prod-assets].each { |file| assert_file(file) }
+         Procfile.dev-prod-assets
+         app/views/layouts/hello_world.html.erb].each { |file| assert_file(file) }
     end
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@react_on_rails/spec/react_on_rails/generators/install_generator_spec.rb`
around lines 806 - 810, The "copies common files" example in
react_on_rails/spec/react_on_rails/generators/install_generator_spec.rb for the
--rsc --redux path is missing an assertion for the layout added by
base_generator.rb; update the test example (the it "copies common files" block)
to include an assert_file("app/views/layouts/hello_world.html.erb") alongside
the existing %w[...] assertions so the RSC+Redux install flow verifies the
layout is copied.
react_on_rails/lib/generators/react_on_rails/generator_messages.rb (1)

92-99: Previous prerender: true concern is correctly resolved — stream_react_component path omits it.

The if rsc branch correctly drops prerender: true for stream_react_component. The helper_name intermediate variable is slightly redundant since the if rsc condition already drives both the helper name and the argument list; consider collapsing:

♻️ Optional simplification of `build_render_example`
 def build_render_example(component_name:, route:, rsc:)
-  helper_name = rsc ? "stream_react_component" : "react_component"
   if rsc
-    "<%= #{helper_name}(\"#{component_name}\", props: @#{route}_props) %>"
+    "<%= stream_react_component(\"#{component_name}\", props: @#{route}_props) %>"
   else
-    "<%= #{helper_name}(\"#{component_name}\", props: @#{route}_props, prerender: true) %>"
+    "<%= react_component(\"#{component_name}\", props: @#{route}_props, prerender: true) %>"
   end
 end
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@react_on_rails/lib/generators/react_on_rails/generator_messages.rb` around
lines 92 - 99, The build_render_example method currently sets helper_name then
uses an if rsc branch to return two different render strings; simplify by
removing the intermediate helper_name variable and directly return the
appropriate string based on rsc so the logic is clearer: in build_render_example
use the rsc flag to choose between returning "<%= stream_react_component(...,
props: @#{route}_props) %>" and "<%= react_component(..., props:
@#{route}_props, prerender: true) %>" (referencing component_name and route),
eliminating helper_name while preserving existing output.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@react_on_rails/lib/generators/react_on_rails/generator_messages.rb`:
- Around line 92-99: The build_render_example method currently sets helper_name
then uses an if rsc branch to return two different render strings; simplify by
removing the intermediate helper_name variable and directly return the
appropriate string based on rsc so the logic is clearer: in build_render_example
use the rsc flag to choose between returning "<%= stream_react_component(...,
props: @#{route}_props) %>" and "<%= react_component(..., props:
@#{route}_props, prerender: true) %>" (referencing component_name and route),
eliminating helper_name while preserving existing output.

In `@react_on_rails/spec/react_on_rails/generators/install_generator_spec.rb`:
- Around line 806-810: The "copies common files" example in
react_on_rails/spec/react_on_rails/generators/install_generator_spec.rb for the
--rsc --redux path is missing an assertion for the layout added by
base_generator.rb; update the test example (the it "copies common files" block)
to include an assert_file("app/views/layouts/hello_world.html.erb") alongside
the existing %w[...] assertions so the RSC+Redux install flow verifies the
layout is copied.

Copy link
Collaborator

@ihabadham ihabadham left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fix itself looks right. Before this merges though:

1. hello_world.html.erb naming debt

The fix is correct and low-risk. The layout file needs to exist and the controller needs to declare it explicitly. But in a --rsc-only install there is no HelloWorld controller, component, or route anywhere. A developer opening their generated app will find app/views/layouts/hello_world.html.erb with no HelloWorld anything, and HelloServerController declaring layout "hello_world". The name does not reflect what the file actually does (inject pack tags via the empty javascript_pack_tag / stylesheet_pack_tag pattern). Worth a follow-up to introduce a neutral layout name so the layout is decoupled from the HelloWorld demo.

2. prerender: true in the generated view template is a no-op

react_on_rails/lib/generators/react_on_rails/templates/rsc/base/app/views/hello_server/index.html.erb#L19 (not changed in this PR) generates:

<%= stream_react_component('HelloServer', props: @hello_server_props, prerender: true) %>

But stream_react_component always forces options[:prerender] = true internally (see react_on_rails_pro/app/helpers/react_on_rails_pro_helper.rb#L127-L129) and its own comment says it "doesn't have the prerender option." This PR correctly drops prerender: true from the post-install hint but leaves it in the generated view file, so a developer reading the template is still taught a no-op option. The comment above it on line 13 even says "prerender: true enables server-side rendering with streaming," which is misleading since the flag does nothing. Worth cleaning up the template in a follow-up.

Comment on lines 92 to 99
def build_render_example(component_name:, route:, rsc:)
helper_name = rsc ? "stream_react_component" : "react_component"
if rsc
"<%= #{helper_name}(\"#{component_name}\", props: @#{route}_props) %>"
else
"<%= #{helper_name}(\"#{component_name}\", props: @#{route}_props, prerender: true) %>"
end
end
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

helper_name is derived from rsc on this line, then if rsc is evaluated again in the very next line. The variable is used exactly once per branch and adds no clarity. Each branch can embed the name directly:

Suggested change
def build_render_example(component_name:, route:, rsc:)
helper_name = rsc ? "stream_react_component" : "react_component"
if rsc
"<%= #{helper_name}(\"#{component_name}\", props: @#{route}_props) %>"
else
"<%= #{helper_name}(\"#{component_name}\", props: @#{route}_props, prerender: true) %>"
end
end
def build_render_example(component_name:, route:, rsc:)
if rsc
"<%= stream_react_component(\"#{component_name}\", props: @#{route}_props) %>"
else
"<%= react_component(\"#{component_name}\", props: @#{route}_props, prerender: true) %>"
end
end

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agree

Procfile.dev-static-assets
Procfile.dev-prod-assets].each { |file| assert_file(file) }
Procfile.dev-prod-assets
app/views/layouts/hello_world.html.erb].each { |file| assert_file(file) }
Copy link
Collaborator

@ihabadham ihabadham Feb 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The --rsc context now asserts hello_world.html.erb, but the --rsc --redux context and --rsc --typescript context have the same "copies common files" block without this assertion. The fix in base_generator.rb is unconditional so the file is always copied for all install types. Both contexts should also verify it:

      %w[config/initializers/react_on_rails.rb
         Procfile.dev
         Procfile.dev-static-assets
         Procfile.dev-prod-assets
         app/views/layouts/hello_world.html.erb].each { |file| assert_file(file) }

it "creates HelloServer controller and view" do
assert_file "app/controllers/hello_server_controller.rb" do |content|
expect(content).to include("class HelloServerController")
expect(content).to include('layout "hello_world"')
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This assertion was added for --rsc, but --rsc --redux also creates HelloServerController and has no assertion on its content. If the layout "hello_world" declaration were missing or regressed in the Redux combination, no test would catch it. Suggest adding to the --rsc --redux context:

    it "creates HelloServer controller with hello_world layout" do
      assert_file "app/controllers/hello_server_controller.rb" do |content|
        expect(content).to include("class HelloServerController")
        expect(content).to include('layout "hello_world"')
        expect(content).to include("ReactOnRailsPro::Stream")
      end
    end

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fine, although I'm not sure we need the support for RSC and Redux, which is adding a bunch more stuff for us to test. I'm not sure it makes sense in the context of RSC.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did consider blocking this combination, but kept it for the upgrade path: existing apps with Redux that want to add RSC on top. For new installs it doesn't make much sense, agreed.

@ihabadham ihabadham dismissed their stale review February 23, 2026 16:21

Superseded by updated review

ihabadham and others added 3 commits February 23, 2026 22:51
The intermediate variable added no clarity — each branch already uses a
distinct helper name inline. Inline the strings directly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The --rsc --redux, --rsc --typescript, and --rsc --rspack contexts were
missing assertions that app/views/layouts/hello_world.html.erb is generated.
Add it to each context's "copies common files" test to match coverage in
the plain --rsc context.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…texts

The --rsc --redux, --rsc --typescript, and --rsc --rspack contexts were
missing assertions that HelloServerController is generated with
layout "hello_world". Add a matching test block to each context.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@ihabadham ihabadham dismissed their stale review February 23, 2026 20:52

All review comments addressed.

ihabadham
ihabadham approved these changes Feb 23, 2026
Copy link
Collaborator

@ihabadham ihabadham left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All inline comments addressed: helper_name refactored away, and test coverage extended to --rsc --redux, --rsc --typescript, and --rsc --rspack contexts for both the layout file copy and HelloServerController layout declaration. Follow-up items (layout naming debt, prerender no-op in generated template) tracked for a separate PR.

@claude
Copy link

claude bot commented Feb 23, 2026

Review Summary

The fix correctly addresses the MissingEntryError on fresh RSC installs. By always copying hello_world.html.erb and explicitly setting layout \"hello_world\" in HelloServerController, the generator no longer falls back to application.html.erb (which references a non-existent application pack in RSC flows). The post-install messaging improvement is a nice UX touch.

A few observations:

Test isolation in generator_messages_spec.rb

The spec accumulates state across tests — there is no before { described_class.clear } between examples. Tests that call add_error/add_warning/add_info leave messages in the module-level @output array, so contain_exactly assertions in later tests will fail if they run after message-adding tests. The new tests in this PR call helpful_message_after_installation (which returns a string and does not touch messages), so they're safe, but the pre-existing tests are fragile and this file is a good place to fix it while it's being touched.

render_label style inconsistency

render_example is extracted to a private build_render_example method, but the analogous render_label is computed inline. For consistency both should be private helpers or both should be inline.

Spec duplication

The "creates HelloServer controller with hello_world layout" test body is identical in the --rsc, --rsc --redux, --rsc --typescript, and --rsc --rspack contexts. A shared example group would eliminate the repetition and make future changes to this assertion easier to maintain.

Layout naming clarity

The hello_world.html.erb layout is now always copied — including in pure RSC installs where no HelloWorldController is generated. The comment in base_generator.rb explains the reason well, but a developer reading the layout name without that context could find it surprising. This is a minor documentation concern, not a bug.

Overall this is a solid, focused fix with good test coverage.

.to contain_exactly(described_class.format_info("Test info message"))
end

it "shows stream_react_component in RSC install message" do
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The spec file has no before { described_class.clear } between examples. GeneratorMessages stores messages in a module-level @output array, so the existing tests that call add_error/add_warning/add_info accumulate state. If those tests run before others, any contain_exactly assertion will see unexpected extra messages.

The new tests here are safe (they call helpful_message_after_installation, which returns a string without touching @output), but the file overall is fragile. Consider adding a before { described_class.clear } at the top of the describe block.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No action needed — generator_spec_helper.rb has a global config.after { GeneratorMessages.clear } that clears state after every example.

"• Streaming server rendering in app/views/#{route}/index.html.erb:"
else
"• Server-side rendering - Enabled with prerender option in app/views/#{route}/index.html.erb:"
end
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

render_label is computed inline here while render_example is extracted to the private build_render_example method. For consistency, consider extracting this to a build_render_label private method alongside build_render_example.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pre-existing, not introduced in this PR. Agreed it's worth cleaning up — will track as a follow-up.

end
end

it "creates HelloServer controller with hello_world layout" do
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test body is identical across --rsc, --rsc --redux, --rsc --typescript, and --rsc --rspack contexts. A shared example group would eliminate the duplication:

shared_examples "hello_server_controller_uses_hello_world_layout" do
  it "creates HelloServer controller with hello_world layout" do
    assert_file "app/controllers/hello_server_controller.rb" do |content|
      expect(content).to include("class HelloServerController")
      expect(content).to include('layout "hello_world"')
      expect(content).to include("ReactOnRailsPro::Stream")
    end
  end
end

Then each context can use include_examples "hello_server_controller_uses_hello_world_layout".

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The --rsc context test at line 774 is different (also asserts the view file), so there are 3 identical blocks, not 4. Agreed on the style point — will track as a follow-up.

@ihabadham ihabadham merged commit b088857 into master Feb 23, 2026
36 checks passed
@ihabadham ihabadham deleted the codex/fix-rsc-generator-layout-and-message branch February 23, 2026 21:10
@justin808 justin808 added the codex PRs created from codex-named branches label Feb 25, 2026
AbanoubGhadban pushed a commit that referenced this pull request Feb 25, 2026
HelloServerController had no explicit layout declaration, causing Rails to fall
back to application.html.erb, which references javascript_pack_tag "application"
— a pack that does not exist in the RSC webpack flow. This triggered a
Shakapacker::Manifest::MissingEntryError on the first request.

Changes:
- Always copy app/views/layouts/hello_world.html.erb during install so RSC apps
  have a pack-driven layout available (empty javascript_pack_tag /
  stylesheet_pack_tag, filled by React on Rails auto-registration)
- Set generated HelloServerController to layout "hello_world" so fresh Rails
  apps never fall back to application.html.erb
- Update post-install messaging to show stream_react_component(...) for RSC
  installs instead of react_component(...) with prerender: true
- Extend generator specs to assert layout file copy and HelloServerController
  layout declaration across --rsc, --rsc --redux, --rsc --typescript, and
  --rsc --rspack contexts
- Refactor build_render_example to inline helper names directly

Verified manually with a fresh Rails app: GET /hello_server returns 200 with
layouts/hello_world.html.erb and RSC-specific packs injected correctly.

Closes #2429
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

codex PRs created from codex-named branches

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants