Add TanStack Router demo with SSR and TypeScript#104
Add TanStack Router demo with SSR and TypeScript#104
Conversation
|
Warning Rate limit exceeded
⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ⛔ Files ignored due to path filters (3)
📒 Files selected for processing (8)
WalkthroughAdds a complete new Rails 8 demo app "basic-v16-rspack-tanstack" integrating React on Rails v16 + ReactOnRails Pro Node renderer, Rspack/Shakapacker, TanStack Router (file-based + SSR), TypeScript, Playwright e2e tests, many bin/Procfile utilities, Webpack/Rspack config, and extensive docs/metadata. Changes
Sequence Diagram(s)sequenceDiagram
participant Browser as Client
participant Rails as Rails Server
participant Node as Node Renderer
participant React as React App
Browser->>Rails: GET /users/123
Rails->>React: instantiate TanStackApp.server with initialUrl
React->>Node: request SSR render (server bundle)
Node->>React: rendered HTML + hydration payload
React-->>Rails: return server-rendered HTML
Rails-->>Browser: HTML response (prerendered)
Browser->>React: hydrate with TanStackApp.client
Browser->>React: client navigation -> router handles route (no full reload)
sequenceDiagram
participant Dev as Developer
participant Shakapacker as Bundler (Rspack/Webpack)
participant Rails as Rails App
Dev->>Shakapacker: start dev (bin/shakapacker or bin/shakapacker-dev-server)
Shakapacker->>Shakapacker: build client bundle (HMR)
Shakapacker->>Shakapacker: build server bundle -> private_output_path
Shakapacker-->>Rails: emit routeTree.gen.ts, server-bundle.js
Rails->>Node: Node renderer uses server-bundle for SSR
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related issues
Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches🧪 Generate unit tests (beta)
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. Comment |
PR Review: TanStack Router Demo with SSR and TypeScriptGreat work on this comprehensive demo! The implementation showcases TanStack Router integration with React on Rails in an exemplary way. ✅ Strengths1. Excellent SSR Implementation
2. Well-Structured Configuration
3. Comprehensive Testing
4. TypeScript Configuration
🔍 Observations & Suggestions1. Potential SSR/Client Mismatch (Minor)Location: TanStackApp.client.tsx:9 The client component ignores the initialUrl prop - this is actually fine since the browser will use its current location, but the prop definition is misleading. Suggestion: Either remove initialUrl? from the interface or document why it's intentionally unused on the client. 2. Missing routeTree.gen.ts DocumentationThe .gitignore correctly excludes routeTree.gen.ts, but there's no note in the README about running the TanStack Router plugin to generate it. Suggestion: Add setup instructions to the README mentioning bin/shakapacker generates this file. 3. TypeScript Strictness EnhancementGreat use of noUncheckedIndexedAccess! Consider adding noUnusedLocals, noUnusedParameters, and exactOptionalPropertyTypes for even stricter type safety. 🔒 Security Review✅ Good Practices
No Issues Found
📊 Performance Considerations✅ Optimizations Present
🧪 Test Coverage AssessmentWell Covered
For a demo app, the E2E coverage is excellent. 📝 Code Quality✅ Excellent
Minor Nitpicks
🎯 Alignment with CLAUDE.md Guidelines✅ Follows Best Practices
🏁 Final RecommendationAPPROVE ✅ This is a high-quality demo that effectively showcases:
Before Merging (Optional)
After Merging
Great work showcasing React on Rails 16.2.0.rc1 capabilities! This demo will be valuable for users wanting to integrate TanStack Router with SSR. Reviewed by: Claude Code |
There was a problem hiding this comment.
Actionable comments posted: 13
🤖 Fix all issues with AI agents
In `@demos/basic-v16-rspack-tanstack/app/controllers/application_controller.rb`:
- Around line 1-4: Add an explicit CSRF protection call in ApplicationController
by invoking protect_from_forgery with an appropriate strategy (e.g.,
protect_from_forgery with: :exception) so the controller explicitly enforces
CSRF defenses; update the ApplicationController class (where allow_browser is
set) to call protect_from_forgery to make the protection explicit and prevent
accidental bypass in the future.
In `@demos/basic-v16-rspack-tanstack/app/javascript/src/router.ts`:
- Around line 11-29: The client component is creating the router via
React.useState(() => createRouter()) but never passes the component's initialUrl
prop; update the client-side initialization to call createRouter with the
initialUrl (i.e., React.useState(() => createRouter({ initialUrl }))) so the
createRouter function receives and uses opts.initialUrl when building memory
history; locate the client component where React.useState and createRouter are
used and pass the initialUrl prop through.
In `@demos/basic-v16-rspack-tanstack/app/javascript/src/routes/search.tsx`:
- Around line 24-27: The local inputValue state in SearchPage is initialized
from Route.useSearch().q only once and can desync when the URL changes (e.g.,
browser back/forward); add a React.useEffect that watches q and calls
setInputValue(q ?? '') so the text input updates whenever the search param
changes, leaving user typing behavior unchanged; reference SearchPage,
Route.useSearch, inputValue, and setInputValue when making the change.
- Around line 13-18: The page computation currently uses parseInt on string
values but doesn't guard against NaN; update the logic around the page
assignment (the expression handling search.page and parseInt) to detect when
parseInt returns NaN and fall back to 1 (e.g., parse the string then check
Number.isFinite or isNaN and return 1 on invalid result). Ensure you keep the
existing branches (numeric, string, default) but after parsing the string branch
validate the parsed value before assigning it to page.
In
`@demos/basic-v16-rspack-tanstack/app/javascript/src/TanStackApp/ror_components/TanStackApp.server.tsx`:
- Around line 9-17: The component calls router.load() but doesn't await it, so
route loaders may not finish before render; change the code to await
router.load({ sync: true }) before returning JSX by making TanStackApp an async
Server Component (or move router creation/loading to the server entry that calls
renderToString) — specifically, ensure createRouter(...) is followed by await
router.load({ sync: true }) (or perform that load in your wrapper) and only then
return <RouterProvider router={router} /> so the RouterProvider receives a fully
preloaded router.
In `@demos/basic-v16-rspack-tanstack/app/views/layouts/tanstack_app.html.erb`:
- Line 8: The stylesheet_pack_tag call is currently parameterless; change it to
explicitly specify the entry point name to match application.html.erb (use
stylesheet_pack_tag 'application') and likewise ensure any javascript_pack_tag
in this layout uses javascript_pack_tag 'application' so both layouts
consistently reference the same explicit entry entry point names (look for
stylesheet_pack_tag and javascript_pack_tag in this file and
application.html.erb to align them).
In `@demos/basic-v16-rspack-tanstack/bin/dev`:
- Line 27: DEFAULT_ROUTE is stale (set to "hello_world") and must be updated to
match the app's current TanStack Router routes: change the DEFAULT_ROUTE
constant to the actual default path (e.g., "/" ) or remove the constant if the
script no longer needs a default; after editing, verify any usage of
DEFAULT_ROUTE in the script still works and cross-check available routes in the
demo routing config (search for route definitions like root or any route names
in config/routes.rb) to ensure the value matches.
In `@demos/basic-v16-rspack-tanstack/bin/shakapacker-precompile-hook`:
- Around line 23-29: The precompile hook script (shakapacker-precompile-hook)
calls Rainbow (e.g., Rainbow("🔄 Running React on Rails precompile hook..."))
but the rainbow gem is not declared, causing a NameError at runtime; add gem
"rainbow" to the project's Gemfile and run bundle install (or update your
lockfile) so Rainbow is available when the hook runs.
In `@demos/basic-v16-rspack-tanstack/bin/switch-bundler`:
- Around line 47-62: The YAML.load_file usage in update_shakapacker_config is
unsafe; replace it with YAML.safe_load(File.read(`@shakapacker_config`),
permitted_classes: [...], permitted_symbols: [...], aliases: true) (or
appropriate permitted_classes/symbols for your config) to parse the file safely,
then proceed to update config["default"]["assets_bundler"] and
config["default"]["webpack_loader"] as before and write back with YAML.dump;
ensure you still abort if File.exist? is false and preserve the same variables
(`@shakapacker_config`, `@target_bundler`, update_shakapacker_config).
In `@demos/basic-v16-rspack-tanstack/config/webpack/serverWebpackConfig.js`:
- Around line 100-110: The find callback for rule.use that computes cssLoader
can throw because testValue may be undefined when item is an object without a
loader property; update the callback used in rule.use.find (the code computing
testValue) to guard before calling includes by ensuring testValue is a string
(e.g., check typeof testValue === 'string' or coerce to an empty string) and
only call includes on that safe string, so cssLoader resolution never throws on
unexpected loader item shapes.
- Around line 91-99: The filter callback for rule.use can call testValue.match
when testValue may be undefined, causing a TypeError; update the callback in the
rule.use.filter (the anonymous function inside serverWebpackConfig.js) to guard
against undefined before calling match (e.g., check that testValue is a string
or truthy) and only then evaluate testValue.match(/mini-css-extract-plugin/) or
testValue === 'style-loader', so the predicate safely returns false when
testValue is undefined.
In `@demos/basic-v16-rspack-tanstack/ssr-generated/manifest.json`:
- Around line 1-13: manifest.json inside the ssr-generated output is currently
tracked despite a `/ssr-generated` rule in .gitignore; either remove the
`/ssr-generated` entry from .gitignore so the committed manifest.json stays
intentionally, or stop tracking the generated directory (untrack ssr-generated
with git rm --cached and commit) so manifest.json is no longer tracked while
keeping the files locally.
In `@demos/basic-v16-rspack-tanstack/ssr-generated/server-bundle.js`:
- Around line 1-45: The repository currently commits generated SSR assets
(ssr-generated/ including server-bundle.js and manifest.json from
react_on_rails:generate_packs) which should be ignored; add "ssr-generated/" to
.gitignore and remove the tracked files from Git (git rm --cached) so they are
no longer committed, and update the project README or deploy docs to include the
exact build command or npm/yarn script used to regenerate these files (the
project's SSR/webpack/rspack build script that produces ssr-generated) so
maintainers know how to recreate server-bundle.js and manifest.json for
deployments.
🧹 Nitpick comments (21)
demos/basic-v16-rspack-tanstack/config/initializers/react_on_rails.rb (1)
37-51: Minor: Section organization inconsistency.Lines 50-51 (
auto_load_bundleandcomponents_subdirectory) appear after the "Test Configuration" section header but logically belong to component loading configuration. Consider moving them under the "Advanced Configuration" section or adding a dedicated "Component Loading" section for clarity.Additionally, the comment on lines 37-46 states that
build_test_commandandcompile: truein shakapacker.yml are "mutually exclusive," yetbuild_test_commandis set unconditionally. If the recommended approach (compile: true) is being used in shakapacker.yml, this command may be redundant.Suggested reorganization
# ALTERNATIVE APPROACH: Uncomment below AND configure ReactOnRails::TestHelper # - Provides explicit control over test asset compilation timing # - Requires adding ReactOnRails::TestHelper to spec/rails_helper.rb # - See: https://github.com/shakacode/react_on_rails/blob/master/docs/guides/testing-configuration.md # config.build_test_command = "RAILS_ENV=test bin/shakapacker" + ################################################################################ + # Component Loading + ################################################################################ config.auto_load_bundle = true config.components_subdirectory = "ror_components" + ################################################################################ # Advanced Configuration ################################################################################demos/basic-v16-rspack-tanstack/bin/setup (1)
15-19: Consider adding idempotency check for npm install.The Ruby dependency step uses
bundle checkto skip unnecessary installs, butnpm installruns unconditionally every time. For consistency and faster repeated runs, consider a similar pattern:♻️ Optional: Add idempotency check for npm
system("bundle check") || system!("bundle install") # Install JavaScript dependencies - system!("npm install") + system("npm ls --depth=0 > /dev/null 2>&1") || system!("npm install")Alternatively, checking for
node_modulesexistence:system!("npm install") unless Dir.exist?("node_modules")demos/basic-v16-rspack-tanstack/db/seeds.rb (1)
1-9: Standard Rails seeds template – no issues.This is the default Rails seeds.rb template with documentation comments. Since this demo app doesn't appear to require seed data, the file appropriately serves as a placeholder.
Optional: Remove the MovieGenre example
If you'd like to clean up the file, you could remove the generic
MovieGenreexample since it's not relevant to this TanStack Router demo:# This file should ensure the existence of records required to run the application in every environment (production, # development, test). The code here should be idempotent so that it can be executed at any point in every environment. # The data can then be loaded with the bin/rails db:seed command (or created alongside the database with db:setup). -# -# Example: -# -# ["Action", "Comedy", "Drama", "Horror"].each do |genre_name| -# MovieGenre.find_or_create_by!(name: genre_name) -# endHowever, keeping it is also perfectly fine for a demo application.
demos/basic-v16-rspack-tanstack/config/credentials.yml.enc (1)
1-1: LGTM! Standard Rails encrypted credentials file.This encrypted credentials file follows Rails conventions and is safe to commit to version control. The actual secrets remain encrypted and can only be decrypted with the master key.
Optional: Consider adding a trailing newline to follow POSIX standards (most editors add this automatically).
Reminder: Ensure
config/master.keyis in.gitignoreand never committed. For production, use theRAILS_MASTER_KEYenvironment variable.demos/basic-v16-rspack-tanstack/app/assets/stylesheets/application.css (1)
1-10: Consider demonstrating CSS organization or clarifying the CSS strategy.This manifest file contains helpful documentation but no actual CSS imports or rules. For a demo application, consider either:
Adding example CSS organization — Show how to structure and import stylesheets (e.g.,
@import 'base.css';or@import 'components/header.css';) to demonstrate the maintainability advice mentioned in the comment.Clarifying CSS handling strategy — Since the demo uses Rspack for bundling, clarify whether CSS should be managed through Rspack's asset pipeline, the Rails Propshaft pipeline, or a combination of both. This would help users understand the intended approach for styling in this stack.
demos/basic-v16-rspack-tanstack/app/javascript/packs/application.js (1)
1-1: Remove unnecessary ESLint directive.The file contains no console usage, making this directive redundant.
♻️ Proposed fix
-/* eslint no-console:0 */ // This file is automatically compiled by Webpack, along with any other files // present in this directory. You're encouraged to place your actual application logic in // a relevant structure within app/javascript and only use these pack files to referencedemos/basic-v16-rspack-tanstack/README.md (1)
1-24: Consider documenting the demo setup and features.This is the default Rails README template. Given that this demo showcases TanStack Router with SSR, TypeScript, and Rspack, consider adding:
- Prerequisites (Node.js, Ruby versions)
- Setup commands (
bundle install,yarn install, database setup)- How to run the dev server
- Key features demonstrated (file-based routing, SSR, type-safe params)
- How to run Playwright tests
Would you like me to draft a README based on the PR objectives and demo structure?
demos/basic-v16-rspack-tanstack/app/views/pwa/manifest.json.erb (1)
20-21: Consider using hex color codes for consistency.Using named colors like
"red"is valid, but hex codes (e.g.,"#ff0000") are more precise and commonly used in PWA manifests. This is fine for a demo, but worth noting for production use.demos/basic-v16-rspack-tanstack/app/javascript/src/HelloWorld/ror_components/HelloWorld.server.tsx (1)
1-5: Stale comment and potential leftover artifact.The comment on line 3 references "React Router" but this demo uses TanStack Router. Additionally, since the PR objectives mention removing HelloWorld demo artifacts in favor of TanStack Router routes, consider whether this file should be retained or removed as part of the cleanup.
If this file is intentionally kept for reference, update the comment to reflect TanStack Router:
Suggested fix
import HelloWorld from './HelloWorld.client'; -// This could be specialized for server rendering -// For example, if using React Router, we'd have the SSR setup here. +// This could be specialized for server rendering +// For example, if using TanStack Router, we'd have the SSR setup here. export default HelloWorld;demos/basic-v16-rspack-tanstack/config/webpack/clientWebpackConfig.js (1)
30-32: Consider distinguishing between "module not found" and other errors.The current catch block treats all errors the same, which could mask genuine configuration issues (e.g., invalid plugin options) by logging them as "plugin not available."
Suggested improvement
} catch (e) { - console.warn('TanStack Router plugin not available:', e.message); + if (e.code === 'MODULE_NOT_FOUND') { + console.warn('TanStack Router plugin not installed, skipping:', e.message); + } else { + console.error('TanStack Router plugin configuration error:', e); + } }demos/basic-v16-rspack-tanstack/app/javascript/src/routes/search.tsx (1)
4-7: Type mismatch:pageis always defined after validation.The
SearchParamstype declarespageas optional (page?: number), butvalidateSearchalways returns a number (defaulting to1). Consider making the type non-optional to accurately reflect runtime behavior.Suggested fix
type SearchParams = { q?: string; - page?: number; + page: number; };This would also simplify the component code by removing the
(page || 1)fallbacks throughout.demos/basic-v16-rspack-tanstack/config.ru (1)
5-6: Consider removing theload_servercall.The
Rails.application.load_servercall afterrunis non-standard. Typically,load_serveris invoked internally by Rails during server boot (e.g., by Puma) and doesn't need to be called explicitly inconfig.ru. The standard pattern is simply:require_relative "config/environment" run Rails.applicationIf there's a specific reason this is needed (e.g., for a particular middleware setup), it should be called before
run, not after.Suggested fix
require_relative "config/environment" run Rails.application -Rails.application.load_serverdemos/basic-v16-rspack-tanstack/config/webpack/serverWebpackConfig.js (1)
32-38: Redundant mini-css-extract-plugin removal.This filtering logic is duplicated at lines 87-99, which performs the same removal along with additional CSS loader configuration. Consider removing this first pass to avoid redundancy.
♻️ Suggested removal
- // Remove the mini-css-extract-plugin from the style loaders because - // the client build will handle exporting CSS. - // replace file-loader with null-loader - serverWebpackConfig.module.rules.forEach((loader) => { - if (loader.use && loader.use.filter) { - loader.use = loader.use.filter( - (item) => !(typeof item === 'string' && item.match(/mini-css-extract-plugin/)) - ); - } - });demos/basic-v16-rspack-tanstack/babel.config.js (1)
11-18: Remove deprecateduseBuiltInsoption.The
useBuiltInsoption in@babel/preset-reactis deprecated and planned for removal in Babel 8. When usingruntime: 'automatic', the automatic JSX runtime handles transformations without this option.🔧 Suggested fix
[ '@babel/preset-react', { development: !isProductionEnv, - useBuiltIns: true, runtime: 'automatic', }, ],demos/basic-v16-rspack-tanstack/app/views/layouts/tanstack_app.html.erb (1)
2-2: Consider adding alangattribute for accessibility.Adding a language attribute helps screen readers and improves SEO.
Suggested change
-<html> +<html lang="en">demos/basic-v16-rspack-tanstack/app/javascript/src/TanStackApp/ror_components/TanStackApp.client.tsx (1)
5-11: UnusedinitialUrlprop.The
initialUrlprop is defined inTanStackAppPropsbut never used in the component. Perrouter.ts, the client uses browser history (not memory history), so the prop is likely intentionally unused—but leaving it in the interface is misleading.Either remove the unused prop or add a comment explaining why it exists (e.g., for interface consistency with the server component).
Option 1: Remove unused prop
interface TanStackAppProps { - initialUrl?: string; } + +type TanStackAppProps = Record<string, never>;Or simply:
-interface TanStackAppProps { - initialUrl?: string; -} - -const TanStackApp: React.FC<TanStackAppProps> = () => { +const TanStackApp: React.FC = () => {demos/basic-v16-rspack-tanstack/config/webpack/development.js (1)
4-4: Unused imports:devServerandinliningCss.These imports from
shakapackerare not used anywhere in this file. Consider removing them to keep the code clean.Suggested fix
-const { devServer, inliningCss, config } = require('shakapacker'); +const { config } = require('shakapacker');demos/basic-v16-rspack-tanstack/e2e/tanstack_router.spec.ts (2)
45-57: Consider verifying SPA navigation explicitly.The comment states "Should navigate without full page reload" but there's no assertion verifying this. Consider adding a check to ensure client-side navigation occurred rather than a full reload.
Suggested enhancement
test('navigation works after hydration', async ({ page }) => { await page.goto('/'); // Wait for hydration await page.waitForLoadState('networkidle'); + // Track if a navigation event (not a reload) occurs + const navigationPromise = page.waitForURL('/about', { waitUntil: 'domcontentloaded' }); + // Click navigation link await page.click('a[href="/about"]'); + await navigationPromise; + // Should navigate without full page reload await expect(page).toHaveURL('/about'); await expect(page.locator('h1')).toContainText('About'); });Alternatively, you could capture
page.on('load')events and assert none fired during navigation.
97-115: Good hydration consistency check, consider broader coverage.The approach of capturing console warnings/errors and filtering for hydration-related messages is effective. Two suggestions for improvement:
- Consider testing multiple routes (especially parameterized routes like
/users/123) to catch route-specific hydration mismatches.- The string filter is case-sensitive; React's error messages typically use "Hydration" with capital H, which
'hydrat'would still match, but considerlog.toLowerCase().includes(...)for robustness.Suggested enhancement for broader coverage
test('no hydration mismatch warnings on key routes', async ({ page }) => { const routes = ['/', '/about', '/users/123', '/search?q=test']; for (const route of routes) { const consoleLogs: string[] = []; page.on('console', (msg) => { if (msg.type() === 'error' || msg.type() === 'warning') { consoleLogs.push(msg.text()); } }); await page.goto(route); await page.waitForLoadState('networkidle'); const hydrationErrors = consoleLogs.filter( (log) => log.toLowerCase().includes('hydrat') || log.toLowerCase().includes('mismatch') ); expect(hydrationErrors, `Hydration errors on ${route}`).toHaveLength(0); } });demos/basic-v16-rspack-tanstack/bin/switch-bundler (2)
64-87: Consider adding the new bundler's dependencies, not just removing the old ones.The
update_dependenciesmethod removes the old bundler's dependencies frompackage.jsonbut doesn't add the new bundler's dependencies to it. The subsequentinstall_dependenciesmethod installs them via the package manager, but they won't appear inpackage.jsonwith pinned versions sinceyarn add/npm installwith package names (without versions) will add the latest versions.This could lead to version inconsistencies. Consider either:
- Adding the new dependencies with explicit versions to
package.json, or- Documenting that versions will be resolved to latest at install time.
124-129: Consider detecting bun as a package manager.The detection only covers yarn, pnpm, and npm. Bun is increasingly popular and uses
bun.lockbas its lock file. This is optional but would improve compatibility.✨ Optional: Add bun detection
def detect_package_manager + return "bun" if File.exist?("bun.lockb") return "yarn" if File.exist?("yarn.lock") return "pnpm" if File.exist?("pnpm-lock.yaml") "npm" endYou'd also need to add bun cases in
install_dependencies:when "bun" system("bun", "add", *deps[:dependencies])
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (4)
demos/basic-v16-rspack-tanstack/Gemfile.lockis excluded by!**/*.lockdemos/basic-v16-rspack-tanstack/package-lock.jsonis excluded by!**/package-lock.jsondemos/basic-v16-rspack-tanstack/public/icon.pngis excluded by!**/*.pngdemos/basic-v16-rspack-tanstack/public/icon.svgis excluded by!**/*.svg
📒 Files selected for processing (96)
demos/basic-v16-rspack-tanstack/.demo-metadata.ymldemos/basic-v16-rspack-tanstack/.dev-services.yml.exampledemos/basic-v16-rspack-tanstack/.gitignoredemos/basic-v16-rspack-tanstack/.rubocop.ymldemos/basic-v16-rspack-tanstack/Gemfiledemos/basic-v16-rspack-tanstack/Procfile.devdemos/basic-v16-rspack-tanstack/Procfile.dev-prod-assetsdemos/basic-v16-rspack-tanstack/Procfile.dev-static-assetsdemos/basic-v16-rspack-tanstack/README.mddemos/basic-v16-rspack-tanstack/Rakefiledemos/basic-v16-rspack-tanstack/app/assets/stylesheets/application.cssdemos/basic-v16-rspack-tanstack/app/controllers/application_controller.rbdemos/basic-v16-rspack-tanstack/app/controllers/tanstack_app_controller.rbdemos/basic-v16-rspack-tanstack/app/helpers/application_helper.rbdemos/basic-v16-rspack-tanstack/app/javascript/packs/application.jsdemos/basic-v16-rspack-tanstack/app/javascript/packs/server-bundle.jsdemos/basic-v16-rspack-tanstack/app/javascript/src/HelloWorld/ror_components/HelloWorld.client.tsxdemos/basic-v16-rspack-tanstack/app/javascript/src/HelloWorld/ror_components/HelloWorld.module.cssdemos/basic-v16-rspack-tanstack/app/javascript/src/HelloWorld/ror_components/HelloWorld.server.tsxdemos/basic-v16-rspack-tanstack/app/javascript/src/TanStackApp/ror_components/TanStackApp.client.tsxdemos/basic-v16-rspack-tanstack/app/javascript/src/TanStackApp/ror_components/TanStackApp.server.tsxdemos/basic-v16-rspack-tanstack/app/javascript/src/router.tsdemos/basic-v16-rspack-tanstack/app/javascript/src/routes/__root.tsxdemos/basic-v16-rspack-tanstack/app/javascript/src/routes/about.tsxdemos/basic-v16-rspack-tanstack/app/javascript/src/routes/demo/nested.tsxdemos/basic-v16-rspack-tanstack/app/javascript/src/routes/demo/nested/deep.tsxdemos/basic-v16-rspack-tanstack/app/javascript/src/routes/demo/nested/index.tsxdemos/basic-v16-rspack-tanstack/app/javascript/src/routes/index.tsxdemos/basic-v16-rspack-tanstack/app/javascript/src/routes/search.tsxdemos/basic-v16-rspack-tanstack/app/javascript/src/routes/users/$userId.tsxdemos/basic-v16-rspack-tanstack/app/javascript/src/routes/users/index.tsxdemos/basic-v16-rspack-tanstack/app/javascript/types/css-modules.d.tsdemos/basic-v16-rspack-tanstack/app/jobs/application_job.rbdemos/basic-v16-rspack-tanstack/app/mailers/application_mailer.rbdemos/basic-v16-rspack-tanstack/app/models/application_record.rbdemos/basic-v16-rspack-tanstack/app/views/layouts/application.html.erbdemos/basic-v16-rspack-tanstack/app/views/layouts/mailer.html.erbdemos/basic-v16-rspack-tanstack/app/views/layouts/mailer.text.erbdemos/basic-v16-rspack-tanstack/app/views/layouts/tanstack_app.html.erbdemos/basic-v16-rspack-tanstack/app/views/pwa/manifest.json.erbdemos/basic-v16-rspack-tanstack/app/views/pwa/service-worker.jsdemos/basic-v16-rspack-tanstack/app/views/tanstack_app/index.html.erbdemos/basic-v16-rspack-tanstack/babel.config.jsdemos/basic-v16-rspack-tanstack/bin/brakemandemos/basic-v16-rspack-tanstack/bin/bundledemos/basic-v16-rspack-tanstack/bin/devdemos/basic-v16-rspack-tanstack/bin/railsdemos/basic-v16-rspack-tanstack/bin/rakedemos/basic-v16-rspack-tanstack/bin/rubocopdemos/basic-v16-rspack-tanstack/bin/setupdemos/basic-v16-rspack-tanstack/bin/shakapackerdemos/basic-v16-rspack-tanstack/bin/shakapacker-configdemos/basic-v16-rspack-tanstack/bin/shakapacker-dev-serverdemos/basic-v16-rspack-tanstack/bin/shakapacker-precompile-hookdemos/basic-v16-rspack-tanstack/bin/switch-bundlerdemos/basic-v16-rspack-tanstack/bin/thrustdemos/basic-v16-rspack-tanstack/config.rudemos/basic-v16-rspack-tanstack/config/application.rbdemos/basic-v16-rspack-tanstack/config/boot.rbdemos/basic-v16-rspack-tanstack/config/credentials.yml.encdemos/basic-v16-rspack-tanstack/config/database.ymldemos/basic-v16-rspack-tanstack/config/environment.rbdemos/basic-v16-rspack-tanstack/config/environments/development.rbdemos/basic-v16-rspack-tanstack/config/environments/production.rbdemos/basic-v16-rspack-tanstack/config/environments/test.rbdemos/basic-v16-rspack-tanstack/config/initializers/assets.rbdemos/basic-v16-rspack-tanstack/config/initializers/content_security_policy.rbdemos/basic-v16-rspack-tanstack/config/initializers/filter_parameter_logging.rbdemos/basic-v16-rspack-tanstack/config/initializers/inflections.rbdemos/basic-v16-rspack-tanstack/config/initializers/react_on_rails.rbdemos/basic-v16-rspack-tanstack/config/locales/en.ymldemos/basic-v16-rspack-tanstack/config/puma.rbdemos/basic-v16-rspack-tanstack/config/routes.rbdemos/basic-v16-rspack-tanstack/config/shakapacker.ymldemos/basic-v16-rspack-tanstack/config/webpack/clientWebpackConfig.jsdemos/basic-v16-rspack-tanstack/config/webpack/commonWebpackConfig.jsdemos/basic-v16-rspack-tanstack/config/webpack/development.jsdemos/basic-v16-rspack-tanstack/config/webpack/generateWebpackConfigs.jsdemos/basic-v16-rspack-tanstack/config/webpack/production.jsdemos/basic-v16-rspack-tanstack/config/webpack/serverWebpackConfig.jsdemos/basic-v16-rspack-tanstack/config/webpack/test.jsdemos/basic-v16-rspack-tanstack/config/webpack/webpack.config.jsdemos/basic-v16-rspack-tanstack/db/seeds.rbdemos/basic-v16-rspack-tanstack/e2e/tanstack_router.spec.tsdemos/basic-v16-rspack-tanstack/package.jsondemos/basic-v16-rspack-tanstack/playwright.config.tsdemos/basic-v16-rspack-tanstack/public/400.htmldemos/basic-v16-rspack-tanstack/public/404.htmldemos/basic-v16-rspack-tanstack/public/406-unsupported-browser.htmldemos/basic-v16-rspack-tanstack/public/422.htmldemos/basic-v16-rspack-tanstack/public/500.htmldemos/basic-v16-rspack-tanstack/public/robots.txtdemos/basic-v16-rspack-tanstack/ssr-generated/manifest.jsondemos/basic-v16-rspack-tanstack/ssr-generated/server-bundle.jsdemos/basic-v16-rspack-tanstack/test/test_helper.rbdemos/basic-v16-rspack-tanstack/tsconfig.json
🧰 Additional context used
🧬 Code graph analysis (23)
demos/basic-v16-rspack-tanstack/app/javascript/src/routes/demo/nested/index.tsx (2)
demos/basic-v16-rspack-tanstack/app/javascript/src/routes/demo/nested.tsx (1)
Route(3-5)demos/basic-v16-rspack-tanstack/app/javascript/src/routes/demo/nested/deep.tsx (1)
Route(3-5)
demos/basic-v16-rspack-tanstack/app/javascript/src/routes/search.tsx (8)
demos/basic-v16-rspack-tanstack/app/javascript/src/routes/__root.tsx (1)
Route(4-6)demos/basic-v16-rspack-tanstack/app/javascript/src/routes/about.tsx (1)
Route(3-5)demos/basic-v16-rspack-tanstack/app/javascript/src/routes/demo/nested.tsx (1)
Route(3-5)demos/basic-v16-rspack-tanstack/app/javascript/src/routes/demo/nested/deep.tsx (1)
Route(3-5)demos/basic-v16-rspack-tanstack/app/javascript/src/routes/demo/nested/index.tsx (1)
Route(3-5)demos/basic-v16-rspack-tanstack/app/javascript/src/routes/index.tsx (1)
Route(3-5)demos/basic-v16-rspack-tanstack/app/javascript/src/routes/users/$userId.tsx (1)
Route(3-5)demos/basic-v16-rspack-tanstack/app/javascript/src/routes/users/index.tsx (1)
Route(3-5)
demos/basic-v16-rspack-tanstack/app/javascript/src/routes/demo/nested/deep.tsx (3)
demos/basic-v16-rspack-tanstack/app/javascript/src/routes/__root.tsx (1)
Route(4-6)demos/basic-v16-rspack-tanstack/app/javascript/src/routes/demo/nested.tsx (1)
Route(3-5)demos/basic-v16-rspack-tanstack/app/javascript/src/routes/demo/nested/index.tsx (1)
Route(3-5)
demos/basic-v16-rspack-tanstack/app/javascript/src/TanStackApp/ror_components/TanStackApp.client.tsx (1)
demos/basic-v16-rspack-tanstack/app/javascript/src/router.ts (1)
createRouter(11-29)
demos/basic-v16-rspack-tanstack/app/javascript/src/routes/users/$userId.tsx (8)
demos/basic-v16-rspack-tanstack/app/javascript/src/routes/__root.tsx (1)
Route(4-6)demos/basic-v16-rspack-tanstack/app/javascript/src/routes/about.tsx (1)
Route(3-5)demos/basic-v16-rspack-tanstack/app/javascript/src/routes/demo/nested.tsx (1)
Route(3-5)demos/basic-v16-rspack-tanstack/app/javascript/src/routes/demo/nested/deep.tsx (1)
Route(3-5)demos/basic-v16-rspack-tanstack/app/javascript/src/routes/demo/nested/index.tsx (1)
Route(3-5)demos/basic-v16-rspack-tanstack/app/javascript/src/routes/index.tsx (1)
Route(3-5)demos/basic-v16-rspack-tanstack/app/javascript/src/routes/search.tsx (1)
Route(9-22)demos/basic-v16-rspack-tanstack/app/javascript/src/routes/users/index.tsx (1)
Route(3-5)
demos/basic-v16-rspack-tanstack/config/webpack/serverWebpackConfig.js (2)
demos/basic-v16-rspack-tanstack/config/webpack/commonWebpackConfig.js (2)
require(5-5)commonWebpackConfig(16-16)demos/basic-v16-rspack-tanstack/config/webpack/generateWebpackConfigs.js (1)
serverWebpackConfig(5-5)
demos/basic-v16-rspack-tanstack/app/javascript/src/routes/index.tsx (8)
demos/basic-v16-rspack-tanstack/app/javascript/src/routes/__root.tsx (1)
Route(4-6)demos/basic-v16-rspack-tanstack/app/javascript/src/routes/about.tsx (1)
Route(3-5)demos/basic-v16-rspack-tanstack/app/javascript/src/routes/demo/nested.tsx (1)
Route(3-5)demos/basic-v16-rspack-tanstack/app/javascript/src/routes/demo/nested/deep.tsx (1)
Route(3-5)demos/basic-v16-rspack-tanstack/app/javascript/src/routes/demo/nested/index.tsx (1)
Route(3-5)demos/basic-v16-rspack-tanstack/app/javascript/src/routes/search.tsx (1)
Route(9-22)demos/basic-v16-rspack-tanstack/app/javascript/src/routes/users/$userId.tsx (1)
Route(3-5)demos/basic-v16-rspack-tanstack/app/javascript/src/routes/users/index.tsx (1)
Route(3-5)
demos/basic-v16-rspack-tanstack/config/webpack/commonWebpackConfig.js (3)
demos/basic-v16-rspack-tanstack/config/webpack/clientWebpackConfig.js (3)
require(6-6)require(20-20)commonWebpackConfig(5-5)demos/basic-v16-rspack-tanstack/config/webpack/development.js (1)
require(4-4)demos/basic-v16-rspack-tanstack/config/webpack/serverWebpackConfig.js (2)
require(4-4)commonWebpackConfig(5-5)
demos/basic-v16-rspack-tanstack/config/webpack/production.js (4)
demos/basic-v16-rspack-tanstack/config/webpack/development.js (2)
generateWebpackConfigs(6-6)require(4-4)demos/basic-v16-rspack-tanstack/config/webpack/test.js (1)
generateWebpackConfigs(4-4)demos/basic-v16-rspack-tanstack/config/webpack/commonWebpackConfig.js (1)
require(5-5)demos/basic-v16-rspack-tanstack/config/webpack/serverWebpackConfig.js (1)
require(4-4)
demos/basic-v16-rspack-tanstack/config/environments/development.rb (1)
demos/basic-v16-rspack-tanstack/config/application.rb (1)
config(22-41)
demos/basic-v16-rspack-tanstack/config/environments/test.rb (1)
demos/basic-v16-rspack-tanstack/config/application.rb (1)
config(22-41)
demos/basic-v16-rspack-tanstack/app/javascript/src/routes/__root.tsx (8)
demos/basic-v16-rspack-tanstack/app/javascript/src/routes/about.tsx (1)
Route(3-5)demos/basic-v16-rspack-tanstack/app/javascript/src/routes/demo/nested.tsx (1)
Route(3-5)demos/basic-v16-rspack-tanstack/app/javascript/src/routes/demo/nested/deep.tsx (1)
Route(3-5)demos/basic-v16-rspack-tanstack/app/javascript/src/routes/demo/nested/index.tsx (1)
Route(3-5)demos/basic-v16-rspack-tanstack/app/javascript/src/routes/index.tsx (1)
Route(3-5)demos/basic-v16-rspack-tanstack/app/javascript/src/routes/search.tsx (1)
Route(9-22)demos/basic-v16-rspack-tanstack/app/javascript/src/routes/users/$userId.tsx (1)
Route(3-5)demos/basic-v16-rspack-tanstack/app/javascript/src/routes/users/index.tsx (1)
Route(3-5)
demos/basic-v16-rspack-tanstack/app/javascript/src/TanStackApp/ror_components/TanStackApp.server.tsx (1)
demos/basic-v16-rspack-tanstack/app/javascript/src/router.ts (1)
createRouter(11-29)
demos/basic-v16-rspack-tanstack/app/javascript/src/routes/users/index.tsx (3)
demos/basic-v16-rspack-tanstack/app/javascript/src/routes/__root.tsx (1)
Route(4-6)demos/basic-v16-rspack-tanstack/app/javascript/src/routes/index.tsx (1)
Route(3-5)demos/basic-v16-rspack-tanstack/app/javascript/src/routes/users/$userId.tsx (1)
Route(3-5)
demos/basic-v16-rspack-tanstack/config/initializers/filter_parameter_logging.rb (1)
demos/basic-v16-rspack-tanstack/config/application.rb (1)
config(22-41)
demos/basic-v16-rspack-tanstack/config/webpack/clientWebpackConfig.js (6)
demos/basic-v16-rspack-tanstack/config/webpack/webpack.config.js (4)
path(6-6)require(1-1)require(2-2)require(3-3)demos/basic-v16-rspack-tanstack/config/webpack/commonWebpackConfig.js (2)
require(5-5)commonWebpackConfig(16-16)demos/basic-v16-rspack-tanstack/config/webpack/development.js (1)
require(4-4)demos/basic-v16-rspack-tanstack/config/webpack/serverWebpackConfig.js (2)
require(4-4)commonWebpackConfig(5-5)demos/basic-v16-rspack-tanstack/config/webpack/generateWebpackConfigs.js (1)
clientConfig(8-8)demos/basic-v16-rspack-tanstack/config/application.rb (1)
config(22-41)
demos/basic-v16-rspack-tanstack/config/initializers/assets.rb (1)
demos/basic-v16-rspack-tanstack/config/application.rb (1)
config(22-41)
demos/basic-v16-rspack-tanstack/babel.config.js (5)
demos/basic-v16-rspack-tanstack/config/webpack/clientWebpackConfig.js (2)
require(6-6)require(20-20)demos/basic-v16-rspack-tanstack/config/webpack/commonWebpackConfig.js (1)
require(5-5)demos/basic-v16-rspack-tanstack/config/webpack/development.js (1)
require(4-4)demos/basic-v16-rspack-tanstack/config/webpack/serverWebpackConfig.js (1)
require(4-4)demos/basic-v16-rspack-tanstack/config/webpack/webpack.config.js (3)
require(1-1)require(2-2)require(3-3)
demos/basic-v16-rspack-tanstack/config/webpack/generateWebpackConfigs.js (5)
demos/basic-v16-rspack-tanstack/config/webpack/clientWebpackConfig.js (3)
require(6-6)require(20-20)clientConfig(9-9)demos/basic-v16-rspack-tanstack/config/webpack/commonWebpackConfig.js (1)
require(5-5)demos/basic-v16-rspack-tanstack/config/webpack/development.js (1)
require(4-4)demos/basic-v16-rspack-tanstack/config/webpack/serverWebpackConfig.js (2)
require(4-4)serverWebpackConfig(14-14)demos/basic-v16-rspack-tanstack/config/webpack/webpack.config.js (3)
require(1-1)require(2-2)require(3-3)
demos/basic-v16-rspack-tanstack/config/routes.rb (1)
packages/shakacode_demo_common/lib/shakacode_demo_common.rb (1)
root(10-12)
demos/basic-v16-rspack-tanstack/config/environments/production.rb (1)
demos/basic-v16-rspack-tanstack/config/application.rb (1)
config(22-41)
demos/basic-v16-rspack-tanstack/config/webpack/webpack.config.js (4)
demos/basic-v16-rspack-tanstack/config/webpack/clientWebpackConfig.js (2)
require(6-6)require(20-20)demos/basic-v16-rspack-tanstack/config/webpack/commonWebpackConfig.js (1)
require(5-5)demos/basic-v16-rspack-tanstack/config/webpack/development.js (1)
require(4-4)demos/basic-v16-rspack-tanstack/config/webpack/serverWebpackConfig.js (1)
require(4-4)
demos/basic-v16-rspack-tanstack/app/javascript/src/routes/about.tsx (8)
demos/basic-v16-rspack-tanstack/app/javascript/src/routes/__root.tsx (1)
Route(4-6)demos/basic-v16-rspack-tanstack/app/javascript/src/routes/demo/nested.tsx (1)
Route(3-5)demos/basic-v16-rspack-tanstack/app/javascript/src/routes/demo/nested/deep.tsx (1)
Route(3-5)demos/basic-v16-rspack-tanstack/app/javascript/src/routes/demo/nested/index.tsx (1)
Route(3-5)demos/basic-v16-rspack-tanstack/app/javascript/src/routes/index.tsx (1)
Route(3-5)demos/basic-v16-rspack-tanstack/app/javascript/src/routes/search.tsx (1)
Route(9-22)demos/basic-v16-rspack-tanstack/app/javascript/src/routes/users/$userId.tsx (1)
Route(3-5)demos/basic-v16-rspack-tanstack/app/javascript/src/routes/users/index.tsx (1)
Route(3-5)
🪛 Biome (2.1.2)
demos/basic-v16-rspack-tanstack/ssr-generated/server-bundle.js
[error] 3-4: eval() exposes to security risks and performance issues.
See the MDN web docs for more details.
Refactor the code so that it doesn't need to call eval().
(lint/security/noGlobalEval)
🪛 Brakeman (7.1.1)
demos/basic-v16-rspack-tanstack/app/controllers/application_controller.rb
[high] 1-1: protect_from_forgery should be called in ApplicationController
Type: Cross-Site Request Forgery
Confidence: High
More info: https://brakemanscanner.org/docs/warning_types/cross-site_request_forgery/
(Cross-Site Request Forgery)
🪛 Checkov (3.2.334)
demos/basic-v16-rspack-tanstack/config/database.yml
[medium] 68-69: Basic Auth Credentials
(CKV_SECRET_4)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: claude-review
✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.
demos/basic-v16-rspack-tanstack/app/controllers/application_controller.rb
Show resolved
Hide resolved
| const TanStackApp: React.FC<TanStackAppProps> = ({ initialUrl }) => { | ||
| // Create router with memory history for SSR | ||
| const router = createRouter({ initialUrl }); | ||
|
|
||
| // Load the router to ensure route data is ready | ||
| router.load(); | ||
|
|
||
| return <RouterProvider router={router} />; | ||
| }; |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
cat -n demos/basic-v16-rspack-tanstack/app/javascript/src/TanStackApp/ror_components/TanStackApp.server.tsxRepository: shakacode/react_on_rails-demos
Length of output: 706
🌐 Web query:
TanStack Router SSR server-side rendering router.load async await
💡 Result:
Short answer: call router.load() (await it) on the server before rendering. Use the sync option to wait for all loaders to finish (or use router.invalidate() to force reload). Then render with the SSR helpers (defaultRenderHandler / renderRouterToString / RouterServer).
Minimal example:
- create router (shared)
- in server entry:
const router = createRouter()
// make router match the request URL (your router setup will do this)
await router.load({ sync: true }) // waits for route loaders to finish
const html = renderRouterToString(...)
res.end(html)
Notes:
- router.load() respects route.staleTime and will not force reload fresh data; use router.invalidate() to force reload. [1]
- Use the TanStack Router SSR helpers (defaultRenderHandler or renderRouterToString / RouterServer) to serialize/dehydrate loader data for the client. For deferred/streaming data use the deferred/Await pattern and the streaming SSR guide. [2][3]
Sources:
[1] Router API — .load() details.
[2] TanStack Router SSR guide (non-streaming & SSR helpers).
[3] Deferred data / streaming SSR (defer + ).
🏁 Script executed:
fd -e "tsx\|ts" -path "*/server*" demos/basic-v16-rspack-tanstack/app/javascript/srcRepository: shakacode/react_on_rails-demos
Length of output: 242
🏁 Script executed:
rg "RouterServer|renderToString" demos/basic-v16-rspack-tanstack/app/javascript/src --type ts --type tsx -B 2 -A 2Repository: shakacode/react_on_rails-demos
Length of output: 101
🏁 Script executed:
find demos/basic-v16-rspack-tanstack -name "*entry*" -o -name "*server*" | grep -E "\.(tsx?|jsx?)$" | head -20Repository: shakacode/react_on_rails-demos
Length of output: 476
🏁 Script executed:
cat -n demos/basic-v16-rspack-tanstack/app/javascript/packs/server-bundle.jsRepository: shakacode/react_on_rails-demos
Length of output: 184
🏁 Script executed:
rg "TanStackApp\|router\.load" demos/basic-v16-rspack-tanstack --type js --type jsx -B 3 -A 3Repository: shakacode/react_on_rails-demos
Length of output: 101
🏁 Script executed:
rg "TanStackApp" demos/basic-v16-rspack-tanstack --type ts -B 2 -A 2Repository: shakacode/react_on_rails-demos
Length of output: 3086
🏁 Script executed:
rg "TanStackApp" demos/basic-v16-rspack-tanstack -B 2 -A 2Repository: shakacode/react_on_rails-demos
Length of output: 3238
🏁 Script executed:
find demos/basic-v16-rspack-tanstack -name "*.erb" -o -name "*.html" | xargs grep -l "TanStackApp" 2>/dev/null | head -5Repository: shakacode/react_on_rails-demos
Length of output: 143
🏁 Script executed:
cat -n demos/basic-v16-rspack-tanstack/app/javascript/src/router.tsRepository: shakacode/react_on_rails-demos
Length of output: 1173
🏁 Script executed:
rg "async\|Promise" demos/basic-v16-rspack-tanstack/app/javascript/src/TanStackApp --type ts -B 1 -A 1Repository: shakacode/react_on_rails-demos
Length of output: 56
Await router.load() before rendering to ensure route data is available during SSR.
router.load() returns a Promise but the return value is not awaited, which means the component renders before route loaders complete. Per TanStack Router's SSR guidelines, you must await router.load({ sync: true }) before rendering to ensure route data is ready.
Since this is a synchronous function component, you'll need to restructure the component to be async or move the router loading to a wrapper component that can handle the Promise. Consider:
- Convert TanStackApp to an async Server Component that awaits
router.load()before returning JSX - Move router creation and loading to the server entry point that calls
renderToString, then pass the preloaded router to the component
🤖 Prompt for AI Agents
In
`@demos/basic-v16-rspack-tanstack/app/javascript/src/TanStackApp/ror_components/TanStackApp.server.tsx`
around lines 9 - 17, The component calls router.load() but doesn't await it, so
route loaders may not finish before render; change the code to await
router.load({ sync: true }) before returning JSX by making TanStackApp an async
Server Component (or move router creation/loading to the server entry that calls
renderToString) — specifically, ensure createRouter(...) is followed by await
router.load({ sync: true }) (or perform that load in your wrapper) and only then
return <RouterProvider router={router} /> so the RouterProvider receives a fully
preloaded router.
| { | ||
| "server-bundle.js": "/packs/server-bundle.js", | ||
| "entrypoints": { | ||
| "server-bundle": { | ||
| "assets": { | ||
| "js": [ | ||
| "/packs/server-bundle.js" | ||
| ], | ||
| "css": [] | ||
| } | ||
| } | ||
| } | ||
| } No newline at end of file |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Check the gitignore at the demo level
echo "=== Checking demos/basic-v16-rspack-tanstack/.gitignore ==="
if [ -f "demos/basic-v16-rspack-tanstack/.gitignore" ]; then
cat -n "demos/basic-v16-rspack-tanstack/.gitignore"
else
echo "No .gitignore in demo directory"
fi
# Check root level .gitignore
echo -e "\n=== Checking root .gitignore for ssr-generated ==="
rg -n "ssr-generated" .gitignore 2>/dev/null || echo "ssr-generated not found in root .gitignore"
# Check if the file actually exists
echo -e "\n=== Checking if manifest.json exists ==="
ls -la "demos/basic-v16-rspack-tanstack/ssr-generated/" 2>/dev/null || echo "Directory not found"
# Check for README in demo
echo -e "\n=== Checking for README in demo ==="
find "demos/basic-v16-rspack-tanstack" -maxdepth 1 -name "README*" -o -name "readme*" | head -5Repository: shakacode/react_on_rails-demos
Length of output: 1211
🏁 Script executed:
#!/bin/bash
# Check the README for context about ssr-generated
echo "=== Checking demos/basic-v16-rspack-tanstack/README.md ==="
cat "demos/basic-v16-rspack-tanstack/README.md"Repository: shakacode/react_on_rails-demos
Length of output: 506
🏁 Script executed:
#!/bin/bash
# Check git history for the manifest.json
echo "=== Git history for manifest.json ==="
git log --oneline --follow "demos/basic-v16-rspack-tanstack/ssr-generated/manifest.json" | head -10
# Check git history for .gitignore
echo -e "\n=== Git history for .gitignore (recent commits) ==="
git log --oneline -p "demos/basic-v16-rspack-tanstack/.gitignore" | head -40
# Check if manifest.json is currently tracked
echo -e "\n=== Git status of manifest.json ==="
git status "demos/basic-v16-rspack-tanstack/ssr-generated/manifest.json" 2>&1 || echo "File status check failed"
# Check if it's in git index
echo -e "\n=== Check if file is actually tracked ==="
git ls-files "demos/basic-v16-rspack-tanstack/ssr-generated/manifest.json"Repository: shakacode/react_on_rails-demos
Length of output: 1151
Remove /ssr-generated from .gitignore or stop tracking the file with git rm --cached.
manifest.json is currently tracked in git but /ssr-generated is listed in .gitignore. This creates a conflict: the .gitignore rule only prevents new files from being added, not removal of already-tracked files. The directory will continue to be tracked despite the rule.
If the file is intentionally committed for demo purposes (to allow running without a build step), remove the /ssr-generated rule from .gitignore. Otherwise, use git rm --cached demos/basic-v16-rspack-tanstack/ssr-generated/ to stop tracking it while keeping the files locally.
🤖 Prompt for AI Agents
In `@demos/basic-v16-rspack-tanstack/ssr-generated/manifest.json` around lines 1 -
13, manifest.json inside the ssr-generated output is currently tracked despite a
`/ssr-generated` rule in .gitignore; either remove the `/ssr-generated` entry
from .gitignore so the committed manifest.json stays intentionally, or stop
tracking the generated directory (untrack ssr-generated with git rm --cached and
commit) so manifest.json is no longer tracked while keeping the files locally.
| (function() { | ||
| var __webpack_modules__ = ({ | ||
| "./app/javascript/packs/server-bundle.js": (function () { | ||
| eval("{// Placeholder comment - auto-generated imports will be prepended here by react_on_rails:generate_packs\n\n\n//# sourceURL=webpack://app/./app/javascript/packs/server-bundle.js?395a\n}"); | ||
|
|
||
| }), | ||
|
|
||
| }); | ||
| // The module cache | ||
| var __webpack_module_cache__ = {}; | ||
|
|
||
| // The require function | ||
| function __webpack_require__(moduleId) { | ||
|
|
||
| // Check if module is in cache | ||
| var cachedModule = __webpack_module_cache__[moduleId]; | ||
| if (cachedModule !== undefined) { | ||
| return cachedModule.exports; | ||
| } | ||
| // Create a new module (and put it into the cache) | ||
| var module = (__webpack_module_cache__[moduleId] = { | ||
| exports: {} | ||
| }); | ||
| // Execute the module function | ||
| __webpack_modules__[moduleId](module, module.exports, __webpack_require__); | ||
|
|
||
| // Return the exports of the module | ||
| return module.exports; | ||
|
|
||
| } | ||
|
|
||
| // webpack/runtime/rspack_version | ||
| !function() { | ||
| __webpack_require__.rv = function() { return "1.7.2"; } | ||
| }(); | ||
| // webpack/runtime/rspack_unique_id | ||
| !function() { | ||
| __webpack_require__.ruid = "bundler=rspack@1.7.2"; | ||
| }(); | ||
| // startup | ||
| // Load entry module and return exports | ||
| // This entry module can't be inlined because the eval devtool is used. | ||
| var __webpack_exports__ = __webpack_require__("./app/javascript/packs/server-bundle.js"); | ||
| })() | ||
| ; No newline at end of file |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Check if ssr-generated is in .gitignore
echo "=== Checking .gitignore files in repository ==="
fd -t f '.gitignore' --max-depth 3 | head -20
echo ""
# Check content of .gitignore in repo root and demos
if [ -f ".gitignore" ]; then
echo "=== Root .gitignore content ==="
cat .gitignore
echo ""
fi
# Check if ssr-generated is mentioned in any .gitignore
echo "=== Searching for 'ssr-generated' in .gitignore files ==="
rg 'ssr-generated' --type ignore --max-count 10
echo ""
# Check if other demos have ssr-generated directories
echo "=== Checking for ssr-generated directories in demos ==="
fd -t d 'ssr-generated' demos/
echo ""
# List structure of the target demo
echo "=== Structure of target demo directory ==="
fd -t d '' demos/basic-v16-rspack-tanstack --max-depth 2Repository: shakacode/react_on_rails-demos
Length of output: 2273
🏁 Script executed:
#!/bin/bash
# Check if server-bundle.js is tracked by git
echo "=== Checking if server-bundle.js is tracked by git ==="
git ls-files | grep -i 'ssr-generated' || echo "Not found in git tracked files"
echo ""
# Check git status for ssr-generated
echo "=== Git status for ssr-generated paths ==="
git status --porcelain | grep -i 'ssr-generated' || echo "No ssr-generated in git status"
echo ""
# Search .gitignore more carefully with plain grep
echo "=== Searching .gitignore for build/bundle patterns ==="
cat .gitignore | grep -i -E '(public|packs|bundle|generated|build|dist)' || echo "No matching patterns"
echo ""
# Check what files exist in the target directory
echo "=== Checking if ssr-generated directory exists in demo ==="
ls -la demos/basic-v16-rspack-tanstack/ | grep -i generated || echo "No generated directory found via ls"
echo ""
# Try to find any file with 'server-bundle' name
echo "=== Searching for server-bundle files ==="
fd 'server-bundle' demos/basic-v16-rspack-tanstack 2>/dev/null || echo "No server-bundle files found"Repository: shakacode/react_on_rails-demos
Length of output: 776
🏁 Script executed:
#!/bin/bash
# Check for README or documentation in the demo
echo "=== Looking for documentation in demo directory ==="
fd -t f -e md -e txt -e markdown demos/basic-v16-rspack-tanstack | head -20
echo ""
# Check package.json for build scripts
echo "=== Checking package.json for build scripts ==="
if [ -f "demos/basic-v16-rspack-tanstack/package.json" ]; then
cat demos/basic-v16-rspack-tanstack/package.json | grep -A 20 '"scripts"'
fi
echo ""
# Check if .gitignore excludes anything related to builds or generated
echo "=== Full .gitignore content again for context ==="
cat .gitignore | head -40
echo ""
# Check other demos to see if they have similar ssr-generated files
echo "=== Checking other demos for ssr-generated pattern ==="
fd -t d 'ssr-generated' . 2>/dev/null || echo "No other ssr-generated found"
echo ""
# Look for any comments or documentation about generated files
echo "=== Searching for docs about bundle generation ==="
rg -l 'ssr-generated|server-bundle' demos/ --type md -m 3 2>/dev/null || echo "No markdown docs found"Repository: shakacode/react_on_rails-demos
Length of output: 1260
🏁 Script executed:
#!/bin/bash
# Check if package.json exists and show scripts section
echo "=== Package.json scripts section ==="
if [ -f "demos/basic-v16-rspack-tanstack/package.json" ]; then
python3 << 'EOF'
import json
with open("demos/basic-v16-rspack-tanstack/package.json") as f:
data = json.load(f)
if "scripts" in data:
print("Scripts found:")
for key, val in data["scripts"].items():
print(f" {key}: {val}")
else:
print("No scripts section found")
EOF
else
echo "No package.json found in demo directory"
fi
echo ""
# Check the rspack migration doc for context
echo "=== Rspack migration doc (checking for ssr-generated references) ==="
if [ -f "demos/basic-v16-rspack/docs/webpack-to-rspack-migration.md" ]; then
rg 'ssr-generated|server-bundle|build.*artifact' demos/basic-v16-rspack/docs/webpack-to-rspack-migration.md -A 2 -B 2 || echo "No relevant references found"
else
echo "Migration doc not accessible"
fi
echo ""
# Final check: look at git history for when ssr-generated was added
echo "=== Git log for ssr-generated files (last 3 commits) ==="
git log --oneline -n 20 -- "demos/basic-v16-rspack-tanstack/ssr-generated/" 2>/dev/null || echo "Unable to retrieve git history"Repository: shakacode/react_on_rails-demos
Length of output: 480
Committed build artifact — add to .gitignore.
The ssr-generated/ directory and its files (server-bundle.js, manifest.json) are tracked by git but not excluded in .gitignore. This appears unintentional—the rspack migration documentation explicitly treats ssr-generated as a cleanup artifact (listing rm -rf ssr-generated alongside other temporary build outputs), yet it's committed here.
This creates several problems:
- Files may become stale if source files change but the bundle isn't rebuilt
- Unnecessary repository bloat
- Risk of merge conflicts on generated code
Add ssr-generated/ to .gitignore and document the build command needed to regenerate these files for deployment.
🧰 Tools
🪛 Biome (2.1.2)
[error] 3-4: eval() exposes to security risks and performance issues.
See the MDN web docs for more details.
Refactor the code so that it doesn't need to call eval().
(lint/security/noGlobalEval)
🤖 Prompt for AI Agents
In `@demos/basic-v16-rspack-tanstack/ssr-generated/server-bundle.js` around lines
1 - 45, The repository currently commits generated SSR assets (ssr-generated/
including server-bundle.js and manifest.json from react_on_rails:generate_packs)
which should be ignored; add "ssr-generated/" to .gitignore and remove the
tracked files from Git (git rm --cached) so they are no longer committed, and
update the project README or deploy docs to include the exact build command or
npm/yarn script used to regenerate these files (the project's SSR/webpack/rspack
build script that produces ssr-generated) so maintainers know how to recreate
server-bundle.js and manifest.json for deployments.
PR Review: TanStack Router Demo with SSR and TypeScriptSummaryThis PR adds a comprehensive new demo showcasing TanStack Router integration with React on Rails, featuring SSR, TypeScript, and Rspack. The implementation is well-structured and demonstrates best practices for modern React routing with Rails. ✅ Strengths1. Excellent Documentation
2. Solid Architecture
3. Comprehensive Testing
4. TypeScript Quality
5. Build Configuration
🔍 Code Quality ObservationsGood Practices
Security Considerations
Performance
🎯 Suggestions for ImprovementMinor Issues
Documentation Enhancements
🔧 Repository-Level Changesbin/mise-exec
.rubocop.yml
CLAUDE.md Updates
🧪 Test Plan VerificationBased on the PR test plan, here's what's covered:
🚀 Deployment ReadinessProduction Considerations:
📊 Overall AssessmentRating: ⭐⭐⭐⭐⭐ (Excellent) This is a high-quality demo that:
Recommendation: ✅ Approve with minor suggestions The suggestions above are non-blocking and mostly about enhancing an already strong implementation. The core functionality is solid, well-tested, and production-ready as a demo. 🎓 Learning ValueThis demo successfully teaches:
Great work! This will be a valuable reference for the community. 🚀 |
PR Review: TanStack Router Demo with SSR and TypeScriptI've completed a thorough review of this PR. Overall, this is an excellent addition to the demo repository that showcases a modern, well-architected integration of TanStack Router with React on Rails SSR. The implementation is solid, well-documented, and follows best practices. ✅ Strengths1. Excellent Architecture & Code Quality
2. Comprehensive Documentation
3. Strong Test Coverage
4. Webpack/Rspack Configuration
5. Rails Integration
🔍 Observations & Suggestions1. Potential Hydration Issue in
|
PR Review: Add TanStack Router demo with SSR and TypeScriptSummaryThis PR adds a comprehensive new demo ( ✅ Strengths1. Excellent Architecture & Code Quality
2. Outstanding Documentation
3. Robust Testing
4. Security Best Practices
💡 Suggestions for Improvement1. Search Parameter Validation (Minor)File: The page number validation could be more robust: page:
typeof search.page === 'number'
? search.page
: typeof search.page === 'string'
? parseInt(search.page, 10) || 1
: 1,Potential issue: Negative or zero page numbers aren't rejected. Consider: page: (() => {
const parsed = typeof search.page === 'number'
? search.page
: typeof search.page === 'string'
? parseInt(search.page, 10)
: NaN;
return !isNaN(parsed) && parsed > 0 ? parsed : 1;
})(),2. Shell Script Portability (Minor)File: The shebang Suggestion: Either use 3. Error Handling for Router Load (Low Priority)File: The // More explicit about the sync-only constraint
const loadResult = router.load();
if (loadResult instanceof Promise) {
// This is expected - we don't await, but loaders must be sync
void loadResult;
}This makes it clearer to future maintainers that the promise is intentionally ignored. 4. Test Timeout Hardcoded (Minor)File: await page.waitForTimeout(1000);Hardcoded timeouts can be flaky in CI. Consider:
5. RuboCop Exclusion Pattern (Question)File: - 'demos/**/*' # Each demo has its own Gemfile and rubocop configThis excludes ALL demos from root-level linting. Is this intentional? If demos should have their own RuboCop configs, this is fine. Just confirming it aligns with the project's linting strategy. 🔍 Performance ConsiderationsPositive
No concerns identifiedBuild configuration is well-optimized for both development and production. 🛡️ Security Review✅ Good Practices
|
Pull Request Review: TanStack Router DemoOverall AssessmentThis is an excellent addition to the React on Rails demos repository. The implementation is well-structured, thoroughly documented, and demonstrates best practices for integrating TanStack Router with SSR. The code quality is high with comprehensive test coverage. ✅ Strengths1. Excellent Documentation
2. Strong Configuration Management
3. Comprehensive Testing
4. Type Safety
5. SSR Implementation
🔍 Observations & SuggestionsMinor Issues1. Duplicate CSS Loader Logic (serverWebpackConfig.js:32-38 and 84-120)The CSS loader filtering logic appears twice in 2. Search Param Type Coercion (routes/search.tsx:14-17)The search param validation has a minor inconsistency - it checks for both number and string types for page:
typeof search.page === 'number'
? search.page
: typeof search.page === 'string'
? parseInt(search.page, 10) || 1
: 1,URL search params are always strings, so the first check ( 3. Inline Styles Throughout ComponentsThe demo uses inline styles extensively (e.g., 4. Missing .tool-versions FileThe new Positive Observations5. Excellent Error Handling
6. Good .gitignore CoverageProperly ignores generated files:
7. Rails 8 Best Practices
🔒 Security Review✅ No Security Concerns Found
📊 Performance Considerations✅ Good Performance Practices
💡 Potential OptimizationThe 🧪 Test Coverage Assessment✅ Excellent CoverageThe E2E test suite covers:
Suggestion: Consider adding a test for the HelloWorld component to verify the React on Rails auto-bundling feature works alongside TanStack Router. 📝 Documentation Quality✅ Exceptional Documentation
🎯 RecommendationsRequired Before MergeNone - this PR is production-ready as-is. Nice to Have (Optional)
✅ Final VerdictAPPROVED - This is a high-quality demo that:
The minor suggestions above are truly optional improvements. The code is ready to merge as-is. Great work! This will be a valuable resource for developers integrating TanStack Router with React on Rails. 🎉 Reviewed by: Claude Code Assistant |
Code Review: TanStack Router Demo with SSR and TypeScriptI have completed a thorough review of this PR. Overall, this is excellent work with high-quality implementation. The demo effectively showcases TanStack Router integration with React on Rails SSR. ✅ Strengths1. Excellent Documentation
2. Strong Architecture
3. Comprehensive Testing
4. Configuration Quality
5. Security Best Practices
6. Accessibility
💡 Suggestions & Minor Issues1. Route Synchronization PatternConsider adding a comment in routes.rb explaining why each TanStack route needs a matching Rails route, and pointing to the catch-all pattern for production apps with many routes. This makes it clearer to future developers. 2. Error Handling in Webpack ConfigIn clientWebpackConfig.js, the try-catch blocks log warnings but continue. Consider if the build should fail if plugins are missing - currently, a missing plugin would result in a cryptic runtime error rather than a clear build-time error. 3. Client Component Null SafetyIn TanStackApp.client.tsx, consider if initialUrl could be undefined - should there be a fallback to window.location.pathname to ensure hydration consistency? 🎯 Performance Considerations
🛡️ Security Review✅ No security concerns identified
📊 Test Coverage✅ Excellent E2E coverage Suggestion: Consider adding one test for error boundary behavior. 🎓 Adherence to CLAUDE.md Guidelines✅ Fully compliant
🚀 Final RecommendationAPPROVE WITH MINOR SUGGESTIONS This PR is ready to merge. The suggestions above are minor improvements that could be addressed in follow-up PRs. The core implementation is solid, well-tested, and well-documented. Priority of Suggestions:
Excellent work on this demo! 🎉 |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@demos/basic-v16-rspack-tanstack/.env.example`:
- Line 8: Replace the weak example password for RENDERER_PASSWORD with a
non-secret placeholder or add a clear warning so devs don’t reuse it; update the
.env.example line for RENDERER_PASSWORD to either use CHANGE_ME_IN_PRODUCTION
(or similar) or append a comment like “DO NOT USE IN PRODUCTION — set a strong
unique password” so the environment variable RENDERER_PASSWORD is never shown as
a predictable default.
🧹 Nitpick comments (6)
demos/basic-v16-rspack-tanstack/config/webpack/clientWebpackConfig.js (1)
25-42: Warning-only error handling may mask configuration issues.The try-catch blocks silently continue if the TanStack Router plugin fails to load, only logging a warning. While this allows the build to proceed, it could mask issues like missing dependencies or incorrect plugin versions in scenarios where the router is expected to function.
For a demo project this is reasonable, but for production usage consider either:
- Throwing the error to fail fast when the plugin is required, or
- Adding a configuration flag to control whether plugin loading is optional.
demos/basic-v16-rspack-tanstack/e2e/tanstack_router.spec.ts (2)
123-151: Console listener should be attached before navigation to catch all hydration warnings.The
page.on('console')listener is set up afterpageis obtained but the timing relative topage.goto()matters. While this typically works, attaching the listener beforegoto()ensures no early console messages are missed during the initial page load.Additionally, the hydration error filter could be more comprehensive—React 19 uses terms like "Hydration failed" and "There was an error while hydrating".
♻️ Suggested improvement
test('no hydration mismatch warnings', async ({ page }) => { const consoleLogs: string[] = []; + + // Attach listener before navigation to catch all messages page.on('console', (msg) => { if (msg.type() === 'error' || msg.type() === 'warning') { consoleLogs.push(msg.text()); } }); await page.goto('/'); // ... rest of test ... // Check for hydration errors that may have been logged const hydrationErrors = consoleLogs.filter( - (log) => log.includes('hydrat') || log.includes('mismatch') + (log) => + log.toLowerCase().includes('hydrat') || + log.toLowerCase().includes('mismatch') || + log.includes('did not match') ); expect(hydrationErrors).toHaveLength(0); });
76-90: Search params test could benefit from URL encoding verification.The test fills "test query" (with a space) and checks for
/q=test/in the URL. The space in "test query" will be URL-encoded, so the full match would beq=test%20queryorq=test+query. The current regex/q=test/passes but only partially validates the behavior.♻️ More precise URL assertion
// URL should update - await expect(page).toHaveURL(/q=test/); + await expect(page).toHaveURL(/q=test(%20|\+|%2B)?query/);Or use a simpler single-word query to avoid encoding concerns:
// Type in search input and submit - await input.fill('test query'); + await input.fill('testquery'); await page.click('button[type="submit"]'); // URL should update - await expect(page).toHaveURL(/q=test/); + await expect(page).toHaveURL(/q=testquery/);demos/basic-v16-rspack-tanstack/docs/react-on-rails-pro-setup.md (2)
90-94: Add language specifier to fenced code block.The
.npmrcexample code block is missing a language identifier. Adding one improves syntax highlighting and accessibility.📝 Suggested fix
-``` +```ini always-auth=true //npm.pkg.github.com/:_authToken=ghp_your_token_here `@shakacode-tools`:registry=https://npm.pkg.github.com</details> --- `160-165`: **Consider a health check instead of fixed sleep for CI reliability.** The fixed `sleep 5` may be insufficient if the renderer takes longer to start, or wasteful if it starts faster. For improved reliability, consider polling a health endpoint. <details> <summary>📝 Example health check approach</summary> ```yaml - name: Start Node Renderer run: | cd react-on-rails-pro npm run node-renderer & # Wait for renderer to be ready (up to 30 seconds) for i in {1..30}; do curl -s http://localhost:3800/health && break || sleep 1 doneNote: This assumes a
/healthendpoint exists. If not, the current approach is acceptable for a demo.demos/basic-v16-rspack-tanstack/config/webpack/serverWebpackConfig.js (1)
29-38: Redundant filtering logic—consider consolidating.This loop filters out
mini-css-extract-pluginonly whenitemis a string, but lines 88-98 perform a more comprehensive filter that handles both string and object loader items. This duplication may cause confusion during maintenance.Consider removing this block and relying solely on the more complete filtering at lines 88-98, or consolidating both into a single pass.
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (19)
demos/basic-v16-rspack-tanstack/.env.exampledemos/basic-v16-rspack-tanstack/.gitignoredemos/basic-v16-rspack-tanstack/Gemfiledemos/basic-v16-rspack-tanstack/Procfile.devdemos/basic-v16-rspack-tanstack/README.mddemos/basic-v16-rspack-tanstack/app/javascript/packs/server-bundle.jsdemos/basic-v16-rspack-tanstack/app/javascript/src/routes/__root.tsxdemos/basic-v16-rspack-tanstack/app/javascript/src/routes/about.tsxdemos/basic-v16-rspack-tanstack/bin/devdemos/basic-v16-rspack-tanstack/config/initializers/react_on_rails.rbdemos/basic-v16-rspack-tanstack/config/initializers/react_on_rails_pro.rbdemos/basic-v16-rspack-tanstack/config/webpack/clientWebpackConfig.jsdemos/basic-v16-rspack-tanstack/config/webpack/serverWebpackConfig.jsdemos/basic-v16-rspack-tanstack/docs/react-on-rails-pro-setup.mddemos/basic-v16-rspack-tanstack/e2e/tanstack_router.spec.tsdemos/basic-v16-rspack-tanstack/playwright.config.tsdemos/basic-v16-rspack-tanstack/react-on-rails-pro/.npmrc.exampledemos/basic-v16-rspack-tanstack/react-on-rails-pro/node-renderer.jsdemos/basic-v16-rspack-tanstack/react-on-rails-pro/package.json
✅ Files skipped from review due to trivial changes (1)
- demos/basic-v16-rspack-tanstack/react-on-rails-pro/.npmrc.example
🚧 Files skipped from review as they are similar to previous changes (6)
- demos/basic-v16-rspack-tanstack/playwright.config.ts
- demos/basic-v16-rspack-tanstack/app/javascript/src/routes/about.tsx
- demos/basic-v16-rspack-tanstack/app/javascript/packs/server-bundle.js
- demos/basic-v16-rspack-tanstack/config/initializers/react_on_rails.rb
- demos/basic-v16-rspack-tanstack/.gitignore
- demos/basic-v16-rspack-tanstack/Procfile.dev
🧰 Additional context used
📓 Path-based instructions (1)
**/*.js
📄 CodeRabbit inference engine (CLAUDE.md)
When upgrading Shakapacker or React on Rails, identify breaking changes by reading the CHANGELOG for the version you're upgrading to. Apply ONLY the specific code changes mentioned in the changelog (e.g., API changes like
Shakapacker.configtoShakapacker.configuration). Never use install generators to 'fix' breaking changes.
Files:
demos/basic-v16-rspack-tanstack/react-on-rails-pro/node-renderer.jsdemos/basic-v16-rspack-tanstack/config/webpack/serverWebpackConfig.jsdemos/basic-v16-rspack-tanstack/config/webpack/clientWebpackConfig.js
🧠 Learnings (9)
📓 Common learnings
Learnt from: CR
Repo: shakacode/react_on_rails-demos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-14T06:21:07.270Z
Learning: During Shakapacker or React on Rails upgrades, follow a structured workflow: (1) Update version numbers only in Gemfile and package.json, (2) Run bundle install and npm install to update lock files, (3) Read the CHANGELOG for breaking changes, (4) Apply only specific breaking changes mentioned in changelog, (5) Test the application after each change. Never run install generators that regenerate config files.
Learnt from: CR
Repo: shakacode/react_on_rails-demos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-14T06:21:07.270Z
Learning: Applies to **/*.js : When upgrading Shakapacker or React on Rails, identify breaking changes by reading the CHANGELOG for the version you're upgrading to. Apply ONLY the specific code changes mentioned in the changelog (e.g., API changes like `Shakapacker.config` to `Shakapacker.configuration`). Never use install generators to 'fix' breaking changes.
📚 Learning: 2026-01-14T06:21:07.270Z
Learnt from: CR
Repo: shakacode/react_on_rails-demos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-14T06:21:07.270Z
Learning: Applies to **/*.js : When upgrading Shakapacker or React on Rails, identify breaking changes by reading the CHANGELOG for the version you're upgrading to. Apply ONLY the specific code changes mentioned in the changelog (e.g., API changes like `Shakapacker.config` to `Shakapacker.configuration`). Never use install generators to 'fix' breaking changes.
Applied to files:
demos/basic-v16-rspack-tanstack/README.mddemos/basic-v16-rspack-tanstack/.env.exampledemos/basic-v16-rspack-tanstack/docs/react-on-rails-pro-setup.mddemos/basic-v16-rspack-tanstack/react-on-rails-pro/package.jsondemos/basic-v16-rspack-tanstack/bin/devdemos/basic-v16-rspack-tanstack/Gemfile
📚 Learning: 2026-01-14T06:21:07.270Z
Learnt from: CR
Repo: shakacode/react_on_rails-demos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-14T06:21:07.270Z
Learning: During Shakapacker or React on Rails upgrades, follow a structured workflow: (1) Update version numbers only in Gemfile and package.json, (2) Run bundle install and npm install to update lock files, (3) Read the CHANGELOG for breaking changes, (4) Apply only specific breaking changes mentioned in changelog, (5) Test the application after each change. Never run install generators that regenerate config files.
Applied to files:
demos/basic-v16-rspack-tanstack/README.mddemos/basic-v16-rspack-tanstack/.env.exampledemos/basic-v16-rspack-tanstack/docs/react-on-rails-pro-setup.mddemos/basic-v16-rspack-tanstack/react-on-rails-pro/package.jsondemos/basic-v16-rspack-tanstack/bin/devdemos/basic-v16-rspack-tanstack/Gemfile
📚 Learning: 2026-01-14T06:21:07.270Z
Learnt from: CR
Repo: shakacode/react_on_rails-demos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-14T06:21:07.270Z
Learning: Applies to config/initializers/react_on_rails.rb : NEVER overwrite config/initializers/react_on_rails.rb during upgrades. This file contains project-specific React on Rails initialization settings and must be preserved. When upgrading React on Rails, only update version numbers in Gemfile and package.json - never run `rails react_on_rails:install`.
Applied to files:
demos/basic-v16-rspack-tanstack/README.mddemos/basic-v16-rspack-tanstack/.env.exampledemos/basic-v16-rspack-tanstack/react-on-rails-pro/node-renderer.jsdemos/basic-v16-rspack-tanstack/docs/react-on-rails-pro-setup.mddemos/basic-v16-rspack-tanstack/react-on-rails-pro/package.jsondemos/basic-v16-rspack-tanstack/bin/devdemos/basic-v16-rspack-tanstack/config/initializers/react_on_rails_pro.rbdemos/basic-v16-rspack-tanstack/Gemfile
📚 Learning: 2026-01-14T06:21:07.270Z
Learnt from: CR
Repo: shakacode/react_on_rails-demos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-14T06:21:07.270Z
Learning: Applies to Gemfile : When upgrading Shakapacker or React on Rails, ONLY update version numbers in Gemfile - gem version constraints. Do not run install commands like `rails shakapacker:install` or `rails react_on_rails:install` that regenerate config files.
Applied to files:
demos/basic-v16-rspack-tanstack/README.mddemos/basic-v16-rspack-tanstack/.env.exampledemos/basic-v16-rspack-tanstack/docs/react-on-rails-pro-setup.mddemos/basic-v16-rspack-tanstack/bin/devdemos/basic-v16-rspack-tanstack/Gemfile
📚 Learning: 2026-01-14T06:21:07.270Z
Learnt from: CR
Repo: shakacode/react_on_rails-demos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-14T06:21:07.270Z
Learning: Applies to package.json : When upgrading Shakapacker or React on Rails, ONLY update version numbers in package.json - npm package versions. Do not run install commands that regenerate config files.
Applied to files:
demos/basic-v16-rspack-tanstack/README.mddemos/basic-v16-rspack-tanstack/.env.exampledemos/basic-v16-rspack-tanstack/docs/react-on-rails-pro-setup.mddemos/basic-v16-rspack-tanstack/react-on-rails-pro/package.jsondemos/basic-v16-rspack-tanstack/bin/devdemos/basic-v16-rspack-tanstack/Gemfile
📚 Learning: 2026-01-14T06:21:07.270Z
Learnt from: CR
Repo: shakacode/react_on_rails-demos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-14T06:21:07.270Z
Learning: Applies to config/webpack/*.js : Preserve all custom configurations in config/webpack/ directory files. These files contain project-specific webpack settings and should never be overwritten during Shakapacker upgrades.
Applied to files:
demos/basic-v16-rspack-tanstack/config/webpack/serverWebpackConfig.jsdemos/basic-v16-rspack-tanstack/config/webpack/clientWebpackConfig.js
📚 Learning: 2026-01-14T06:21:07.270Z
Learnt from: CR
Repo: shakacode/react_on_rails-demos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-14T06:21:07.270Z
Learning: Applies to config/webpack/webpack.config.js : NEVER replace or overwrite config/webpack/webpack.config.js during upgrades. This file contains custom logic specific to the project and must be preserved. When upgrading Shakapacker, only update version numbers and run bundle install/npm install - never run `rails shakapacker:install`.
Applied to files:
demos/basic-v16-rspack-tanstack/config/webpack/serverWebpackConfig.jsdemos/basic-v16-rspack-tanstack/react-on-rails-pro/package.jsondemos/basic-v16-rspack-tanstack/config/webpack/clientWebpackConfig.jsdemos/basic-v16-rspack-tanstack/Gemfile
📚 Learning: 2026-01-14T06:21:07.270Z
Learnt from: CR
Repo: shakacode/react_on_rails-demos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-14T06:21:07.270Z
Learning: Applies to config/shakapacker.yml : NEVER overwrite or revert config/shakapacker.yml during upgrades. This file contains project-specific settings and must be preserved. When upgrading Shakapacker, only update version numbers in Gemfile and package.json, then run bundle install and npm install - never run `rails shakapacker:install`.
Applied to files:
demos/basic-v16-rspack-tanstack/Gemfile
🧬 Code graph analysis (4)
demos/basic-v16-rspack-tanstack/config/webpack/serverWebpackConfig.js (2)
demos/basic-v16-rspack-tanstack/config/webpack/commonWebpackConfig.js (2)
require(5-5)commonWebpackConfig(16-16)demos/basic-v16-rspack-tanstack/config/webpack/generateWebpackConfigs.js (1)
serverWebpackConfig(5-5)
demos/basic-v16-rspack-tanstack/app/javascript/src/routes/__root.tsx (8)
demos/basic-v16-rspack-tanstack/app/javascript/src/routes/about.tsx (1)
Route(3-5)demos/basic-v16-rspack-tanstack/app/javascript/src/routes/demo/nested/deep.tsx (1)
Route(3-5)demos/basic-v16-rspack-tanstack/app/javascript/src/routes/search.tsx (1)
Route(9-22)demos/basic-v16-rspack-tanstack/app/javascript/src/routes/demo/nested.tsx (1)
Route(3-5)demos/basic-v16-rspack-tanstack/app/javascript/src/routes/demo/nested/index.tsx (1)
Route(3-5)demos/basic-v16-rspack-tanstack/app/javascript/src/routes/users/index.tsx (1)
Route(3-5)demos/basic-v16-rspack-tanstack/app/javascript/src/routes/users/$userId.tsx (1)
Route(3-5)demos/basic-v16-rspack-tanstack/app/javascript/src/routes/index.tsx (1)
Route(3-5)
demos/basic-v16-rspack-tanstack/config/webpack/clientWebpackConfig.js (6)
demos/basic-v16-rspack-tanstack/config/webpack/webpack.config.js (4)
path(6-6)require(1-1)require(2-2)require(3-3)demos/basic-v16-rspack-tanstack/config/webpack/serverWebpackConfig.js (2)
require(4-4)commonWebpackConfig(5-5)demos/basic-v16-rspack-tanstack/config/webpack/commonWebpackConfig.js (2)
require(5-5)commonWebpackConfig(16-16)demos/basic-v16-rspack-tanstack/config/webpack/development.js (1)
require(4-4)demos/basic-v16-rspack-tanstack/config/webpack/generateWebpackConfigs.js (1)
clientConfig(8-8)demos/basic-v16-rspack-tanstack/config/application.rb (1)
config(22-41)
demos/basic-v16-rspack-tanstack/config/initializers/react_on_rails_pro.rb (1)
demos/basic-v16-rspack-tanstack/react-on-rails-pro/node-renderer.js (1)
config(21-39)
🪛 markdownlint-cli2 (0.18.1)
demos/basic-v16-rspack-tanstack/docs/react-on-rails-pro-setup.md
90-90: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: claude-review
🔇 Additional comments (29)
demos/basic-v16-rspack-tanstack/bin/dev (1)
1-26: LGTM!Clean, well-documented development server script. The delegation to
ReactOnRails::Dev::ServerManagerkeeps this file minimal while the documentation clearly explains the available Procfile modes (hmr,static,prod) and customization options. The previous issue regarding the staleDEFAULT_ROUTEconstant has been properly addressed.demos/basic-v16-rspack-tanstack/config/webpack/clientWebpackConfig.js (4)
1-6: LGTM!Imports are consistent with other webpack configuration files in this project, properly using
shakapacker'sconfigexport for bundler detection.
8-15: LGTM!Good defensive coding to remove the server-bundle entry from the client configuration. The comment clearly explains the rationale for this separation.
17-23: LGTM!Plugin configuration is well-structured with appropriate settings for TanStack Router. Path resolution using
path.resolve(__dirname, ...)ensures correct absolute paths regardless of the working directory.
44-47: LGTM!Export pattern correctly exposes the
configureClientfunction, matching the expected usage ingenerateWebpackConfigs.jswhere it's called asclientWebpackConfig().demos/basic-v16-rspack-tanstack/README.md (1)
1-231: Well-structured and comprehensive documentation.The README provides excellent coverage of setup, configuration, SSR requirements, and limitations. The warning about React on Rails Pro requirement is appropriately prominent, and the explanation of why the Node renderer is needed (TanStack Router's use of
setTimeout/clearTimeout) is helpful context.demos/basic-v16-rspack-tanstack/app/javascript/src/routes/__root.tsx (3)
1-8: Root route setup follows TanStack Router conventions correctly.The route configuration properly defines component, errorComponent, and notFoundComponent. JavaScript function hoisting allows the component references to work despite being defined later in the file.
62-68: Good pattern for shared link styles with proper TypeScript typing.The
as constassertion onfontWeightcorrectly narrows the type to the literal'bold'rather thanstring, avoiding TypeScript errors when passing to style props.
74-125: Well-implemented navigation with proper accessibility.Good use of
aria-labelon the nav element andaria-current: 'page'viaactivePropsfor screen reader support. TheactiveOptions: { exact: true }on the Home link correctly prevents it from being marked active on all routes.demos/basic-v16-rspack-tanstack/e2e/tanstack_router.spec.ts (2)
5-14: SSR verification tests look good.The tests appropriately use
waitForLoadState('domcontentloaded')to verify content is present without waiting for JavaScript execution, which correctly validates server-side rendering.
61-74: Client hydration navigation test is well-structured.The test correctly verifies that client-side navigation works after hydration by clicking a link and asserting the URL change without a full page reload. Using
domcontentloadedwith element visibility checks is a reliable pattern for HMR environments.demos/basic-v16-rspack-tanstack/react-on-rails-pro/package.json (1)
1-10: LGTM!The package.json is well-structured with:
private: trueto prevent accidental publishing- Pinned dependency version for reproducibility
- Simple, clear script for starting the renderer
demos/basic-v16-rspack-tanstack/docs/react-on-rails-pro-setup.md (1)
1-47: Well-structured setup documentation.The guide clearly explains why React on Rails Pro is required, provides straightforward license request instructions, and documents the token creation process. This will help developers get started quickly.
demos/basic-v16-rspack-tanstack/Gemfile (1)
27-37: Release candidate version in use - verify stability before wider adoption.The demo uses
react_on_railsversion16.2.0.rc1. This is appropriate for demonstrating new features, but consumers of this demo should be aware it's a pre-release version.The GitHub Packages source block for
react_on_rails_prois correctly configured with clear documentation pointing to setup instructions.demos/basic-v16-rspack-tanstack/config/initializers/react_on_rails_pro.rb (2)
14-27: Excellent developer experience with clear error messaging.The guard clause with detailed setup instructions will help developers understand what's missing and how to resolve it. The multi-line error message is informative without being overwhelming.
29-48: Configuration aligns with Node Renderer - consider documenting the shared password requirement.The configuration correctly matches the Node Renderer defaults:
renderer_urldefault matches port 3800renderer_passworddefault matches"tanstack-demo-renderer"The
renderer_use_fallback_execjs = falseis the right choice since ExecJS cannot handle TanStack Router's timer APIs.One observation: the default password
"tanstack-demo-renderer"appears in both this file andnode-renderer.js. While acceptable for a demo, production deployments should use unique credentials via environment variables. The inline comment could note this.demos/basic-v16-rspack-tanstack/react-on-rails-pro/node-renderer.js (3)
1-14: Clear documentation of configuration options.The JSDoc header effectively documents the renderer's purpose and available environment variables. This makes it easy for developers to customize the setup.
46-50: Good security practice: password excluded from console output.The configuration logging correctly omits the
passwordfield, preventing accidental credential exposure in logs.
21-39: Configuration is well-structured with sensible defaults.The config object uses environment variables with appropriate fallbacks. The defaults align with the Rails initializer (
react_on_rails_pro.rb), ensuring consistency between the Ruby and Node components.demos/basic-v16-rspack-tanstack/.env.example (1)
1-4: LGTM!The React on Rails Pro token configuration is well-documented with clear instructions on how to obtain a license and create the required GitHub PAT.
demos/basic-v16-rspack-tanstack/config/webpack/serverWebpackConfig.js (9)
1-8: LGTM!The dynamic bundler selection based on
config.assets_bundleris a clean approach for supporting both Rspack and Webpack, and the imports follow Shakapacker conventions.
9-27: LGTM!The defensive check for missing
server-bundleentry with an actionable error message is well implemented. The comment explaining the mutable global issue is helpful for maintainability.
40-44: LGTM!Disabling minimization and enforcing a single chunk with
LimitChunkCountPluginis appropriate for server bundles—simplifies debugging and aligns with SSR requirements.
46-72: LGTM!The output configuration with
privateOutputPathfallback and informative warning message provides good guidance for users migrating to Shakapacker 9.0+. Thecommonjs2library target is correct for Node.js server rendering.
74-81: LGTM!Removing
WebpackAssetsManifest,MiniCssExtractPlugin, andForkTsCheckerWebpackPluginis appropriate for server bundles—CSS extraction and manifest generation are client-side concerns, and type checking once is sufficient.
88-120: Good defensive handling in loader callbacks.The filter and find callbacks now initialize
testValue = ''and include null checks (item &&), addressing the potential TypeError issues from previous reviews.
122-133: LGTM!Setting
devtool: 'eval'for fast SSR debugging andtarget: 'node'for Node.js API support is appropriate. The comment explaining the React on Rails Pro Node renderer requirement provides helpful context.
135-135: LGTM!The export pattern is consistent with usage in
generateWebpackConfigs.js.
109-111: > Likely an incorrect or invalid review comment.
✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.
Base demo app created with: - Rails 8.0.3 with PostgreSQL - Shakapacker 9.3.4 with Rspack bundler - React on Rails 16.2.0.rc1 with SSR - TypeScript support - SWC transpiler (20x faster than Babel) - HelloWorld example component Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Install @tanstack/react-router for routing - Install @tanstack/router-plugin for file-based routing - Install @tanstack/react-router-devtools for debugging - Configure TanStack Router plugin in clientWebpackConfig.js - Add .gitignore with routeTree.gen.ts exclusion - Create initial __root.tsx route file Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Routes: - __root.tsx: Root layout with navigation - index.tsx: Home page - about.tsx: About page with SSR explanation - search.tsx: Search params demo with pagination - users/index.tsx: Users list - users/$userId.tsx: URL params demo - demo/nested.tsx: Nested layout with outlet - demo/nested/index.tsx: Nested index page - demo/nested/deep.tsx: Deep nested page Components: - router.ts: Router factory with SSR support - TanStackApp.client.tsx: Client-side React on Rails component - TanStackApp.server.tsx: Server-side React on Rails component Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Controller: - Create TanstackAppController with initialUrl prop for SSR Views: - Create tanstack_app/index.html.erb with react_component helper - Create layouts/tanstack_app.html.erb with pack tags Routes: - Add root route pointing to tanstack_app#index - Add direct routes for SSR: /about, /search, /users, /demo/nested, etc. - Remove old hello_world routes Cleanup: - Remove HelloWorld controller, views, and layout Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Tests: - Server-Side Rendering Verification - Home page is server-rendered - About page is server-rendered at correct route - URL params are server-rendered correctly (/users/123) - Search params are server-rendered correctly (/search?q=hello&page=2) - Nested routes are server-rendered - Client Hydration Verification - Navigation works after hydration - Search params update client-side - URL params navigation works - Nested routes navigation works - SSR + Hydration Consistency - No hydration mismatch warnings Configuration: - Add playwright.config.ts with web server config - Install @playwright/test dependency Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
High priority: - Remove committed generated artifacts (ssr-generated/) from git tracking - Update .gitignore to exclude additional generated directories (app/javascript/generated/, packs/generated/, test-results/) Medium priority: - Document SSR async loader limitations in TanStackApp.server.tsx - Use `void router.load()` to explicitly indicate non-awaited promise - Fix Playwright tests: replace flaky networkidle with domcontentloaded - Add explicit element visibility waits before interactions - Fix client component to pass initialUrl for hydration consistency Low priority: - Update bin/dev DEFAULT_ROUTE from hello_world to / - Add npm scripts for E2E testing (test, test:ui, test:headed) - Expand README with E2E testing and SSR limitations sections Also includes: - Null safety improvements in serverWebpackConfig.js - Minor fixes from rebased changes Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Use bin/mise-exec to ensure correct Ruby version from .tool-versions - Run rubocop from within demo directories for demo files since each demo has its own Gemfile and rubocop config (root excludes demos/) - Add frozen_string_literal to ApplicationHelper for consistency This fixes the pre-commit hook failing with "Your Ruby version is 2.6" when running in non-interactive shells like Conductor. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
RuboCop was only checking files but not auto-fixing them, unlike ESLint (--fix) and Prettier (--write) which auto-correct issues. Added --autocorrect flag to rubocop commands so that auto-correctable offenses are fixed automatically, consistent with the other linters. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The TanStack Router plugin was only configured for Rspack bundler. If someone switched to Webpack using bin/switch-bundler, the route tree wouldn't be auto-generated, breaking the file-based routing. - Extract router plugin config to shared object - Add else branch for Webpack bundler using TanStackRouterWebpack - Both bundlers now have proper route tree generation Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
TanStack Router requires Node.js APIs (setTimeout, clearTimeout, etc.) that are not available in the default ExecJS environment. This commit adds React on Rails Pro with the Node Renderer as a required dependency. Key changes: - Add react_on_rails_pro gem (required, not optional) - Add react-on-rails-pro/ directory with Node Renderer configuration - Add config/initializers/react_on_rails_pro.rb with Node Renderer setup - Add comprehensive setup documentation in docs/react-on-rails-pro-setup.md - Update Procfile.dev to include Node Renderer process - Remove ExecJS polyfills - no fallback, Pro is required - Add .env.example for environment variable configuration Setup instructions: 1. Get a free license: Contact team@shakacode.com 2. Configure bundler for GitHub Packages 3. Run bundle install 4. Set up Node Renderer: cd react-on-rails-pro && npm install 5. Start with bin/dev Related issues: - Documentation: shakacode/react_on_rails#2299 - TanStack Router: shakacode/react_on_rails#2298 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
React on Rails Pro is now available on regular package registries: - Ruby gem from rubygems.org (no longer GitHub Packages) - npm package from npmjs.org (no longer @shakacode-tools scope) Changes: - Update Gemfile to use regular gem source - Update react-on-rails-pro/package.json for regular npm - Remove .npmrc.example (no auth needed) - Simplify documentation to remove GitHub Packages auth setup - Update README with clearer setup instructions Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
f22d23d to
72b4250
Compare
PR Review: TanStack Router Demo with SSR and TypeScriptI've reviewed this PR and it's an excellent addition to the demo suite! The implementation is well-thought-out and demonstrates best practices throughout. Here's my comprehensive feedback: ✅ Strengths1. Architecture & Design
2. Code Quality
3. Documentation
4. Testing
5. Security & Best Practices
🔍 Areas for Consideration1. Node Renderer Dependency ReferenceLocation: The import uses: const { reactOnRailsProNodeRenderer } = require('@shakacode-tools/react-on-rails-pro-node-renderer');However, based on the commit message stating "React on Rails Pro is now available on regular package registries" and the package being named Impact: Low (would fail at startup if incorrect, easy to catch) 2. React on Rails Pro License DocumentationLocation: Various files mention contacting for a "free license" The documentation mentions getting a "free license" but then shows the gem is available on RubyGems. This might be confusing to users. Consider clarifying:
The Recommendation: Clarify the licensing model in the README and potentially remove references to GitHub PAT if no longer needed. 3. Hydration Consistency Edge CaseLocation: The client component receives Current code: const TanStackApp: React.FC<TanStackAppProps> = ({ initialUrl }) => {
const [router] = React.useState(() => createRouter({ initialUrl }));Suggestion: Either make it required in the client interface too, or add a runtime check/default: const [router] = React.useState(() =>
createRouter({ initialUrl: initialUrl || window.location.pathname })
);Impact: Low (appears to work in practice, but could prevent subtle bugs) 4. Test Reliability EnhancementLocation: The hydration mismatch test uses a click interaction to verify hydration completed, which is clever. However, you could make it more explicit: // Alternative: Wait for React DevTools global or a data attribute
await page.waitForFunction(() => {
return document.querySelector('[data-tanstack-router-id]') \!== null;
});Impact: Very low (current approach is fine, this is just an alternative) 5. Bundle Size ConsiderationThe demo includes both webpack and rspack dependencies. For actual projects (not demos), users would only need one. Consider adding a note in the README about removing unused bundler dependencies in production. 🛡️ Security Review✅ No security concerns identified
📊 Test Coverage AssessmentCoverage: Excellent The test suite covers:
Missing tests (Nice to have, not critical for demo):
🎯 Performance Considerations
Suggestion: Consider adding a performance budget or bundle size tracking in future iterations. 📝 Best Practices AdherenceFollows CLAUDE.md Guidelines ✅
React on Rails Best Practices ✅
🚀 Recommendations SummaryHigh PriorityNone - the PR is production-ready as-is for a demo Medium Priority
Low Priority (Polish)
✨ ConclusionRecommendation: APPROVE ✅ This is an excellent demo that showcases TanStack Router integration with React on Rails in a professional, well-documented manner. The code quality is high, security practices are sound, and the documentation is thorough. The few suggestions above are minor improvements rather than critical issues. Outstanding aspects:
Great work! This will be a valuable addition to the demo suite. Review conducted by Claude Code - PR #104 - shakacode/react_on_rails-demos |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Fix all issues with AI agents
In `@demos/basic-v16-rspack-tanstack/bin/switch-bundler`:
- Around line 84-86: When writing package_json_path using File.write and
JSON.pretty_generate, ensure the output ends with a trailing newline by
appending "\n" to the generated JSON string (i.e., write
JSON.pretty_generate(package_json) + "\n"); update the write call where
package_json_path is used so files produced by switch-bundler include the final
newline.
In `@demos/basic-v16-rspack-tanstack/config/webpack/serverWebpackConfig.js`:
- Around line 114-119: The code assumes rule.use.options exists before setting
emitFile; add a null check or initialize options when handling loaders
'url-loader' or 'file-loader' so you don't access undefined. Specifically,
inside the branch that checks rule.use and (rule.use.loader === 'url-loader' ||
rule.use.loader === 'file-loader'), ensure rule.use.options is defined (e.g., if
(!rule.use.options) rule.use.options = {}) before assigning
rule.use.options.emitFile = false to avoid a TypeError.
In `@demos/basic-v16-rspack-tanstack/README.md`:
- Line 16: The README contains an incorrect "Created" date string ("Created:
2025-01-13"); verify whether this is intentional for demo versioning or a
mistake and update the "Created: 2025-01-13" line in
demos/basic-v16-rspack-tanstack/README.md to the correct date (e.g., the PR
creation date in January 2026) or add a clarifying note about versioning if the
older date is intentional.
🧹 Nitpick comments (12)
demos/basic-v16-rspack-tanstack/bin/shakapacker-precompile-hook (1)
23-30: Consider adding a success message for consistency with the documented emoji scheme.The emoji scheme in lines 11-14 documents ✅ for success, but no success message is printed when
generate_packs_if_stalecompletes. Adding one would provide better feedback during builds and maintain consistency with your documented conventions.♻️ Suggested improvement
begin puts Rainbow("🔄 Running React on Rails precompile hook...").cyan ReactOnRails::PacksGenerator.instance.generate_packs_if_stale + puts Rainbow("✅ React on Rails precompile hook completed.").green rescue StandardError => e warn Rainbow("❌ Error in precompile hook: #{e.message}").red warn e.backtrace.first(5).join("\n") exit 1 enddemos/basic-v16-rspack-tanstack/bin/switch-bundler (2)
4-4: Unused require.
fileutilsis required but never used in this script.🧹 Proposed cleanup
-require "fileutils"
124-129: Consider adding Bun support.The current detection covers the major package managers. For future-proofing, you could optionally add Bun detection.
💡 Optional: Add Bun support
def detect_package_manager return "yarn" if File.exist?("yarn.lock") return "pnpm" if File.exist?("pnpm-lock.yaml") + return "bun" if File.exist?("bun.lockb") "npm" endYou would also need to add the corresponding Bun install commands in
install_dependencies:when "bun" system("bun", "add", *deps[:dependencies]) # and when "bun" system("bun", "add", "-d", *deps[:dev_dependencies])demos/basic-v16-rspack-tanstack/config/webpack/clientWebpackConfig.js (1)
31-41: Consider surfacing plugin load failures more prominently in development.Silent
console.warnmay be missed during development. If the TanStack Router plugin fails to load, file-based routing won't work and the app will break at runtime.💡 Optional: throw in development for faster feedback
if (config.assets_bundler === 'rspack') { try { const { TanStackRouterRspack } = require('@tanstack/router-plugin/rspack'); clientConfig.plugins.push(TanStackRouterRspack(routerPluginConfig)); } catch (e) { - console.warn('TanStack Router Rspack plugin not available:', e.message); + console.error('TanStack Router Rspack plugin not available:', e.message); + if (process.env.NODE_ENV === 'development') { + throw e; + } } } else { // Webpack bundler try { const { TanStackRouterWebpack } = require('@tanstack/router-plugin/webpack'); clientConfig.plugins.push(TanStackRouterWebpack(routerPluginConfig)); } catch (e) { - console.warn('TanStack Router Webpack plugin not available:', e.message); + console.error('TanStack Router Webpack plugin not available:', e.message); + if (process.env.NODE_ENV === 'development') { + throw e; + } } }demos/basic-v16-rspack-tanstack/config/webpack/serverWebpackConfig.js (2)
32-38: Duplicate filtering logic—consider removing this block.This filtering logic is superseded by the more comprehensive version at lines 88-98, which handles both string and object loader items. This first pass only handles string items and the filter is applied again later.
♻️ Remove redundant first-pass filter
- // Remove the mini-css-extract-plugin from the style loaders because - // the client build will handle exporting CSS. - // replace file-loader with null-loader - serverWebpackConfig.module.rules.forEach((loader) => { - if (loader.use && loader.use.filter) { - loader.use = loader.use.filter( - (item) => !(typeof item === 'string' && item.match(/mini-css-extract-plugin/)) - ); - } - }); - // No splitting of chunks for a server bundle
65-72: Warning message is misleading—no version check performed.The warning claims "Shakapacker 9.0+ detected" but there's no actual version detection. This warning fires whenever
privateOutputPathis falsy, which could also occur due to configuration omission in any Shakapacker version.📝 Suggested wording fix
if (!config.privateOutputPath) { console.warn( - '⚠️ Shakapacker 9.0+ detected but private_output_path not configured in shakapacker.yml' + '⚠️ private_output_path not configured in shakapacker.yml (required for Shakapacker 9.0+)' );demos/basic-v16-rspack-tanstack/config/shakapacker.yml (1)
1-105: Consider reducing configuration duplication with YAML anchors.The configuration repeats many identical values across environments. While the current explicit form aids readability, you could reduce maintenance burden by anchoring the common
defaultblock and using environment-specific overrides.This is optional since the current format is explicit and follows Shakapacker conventions. Based on learnings, this file contains project-specific settings that should be preserved during upgrades, so either approach works.
demos/basic-v16-rspack-tanstack/config/webpack/development.js (1)
4-4: Unused imports from shakapacker.
devServerandinliningCssare imported but not used in this file. Onlyconfigis actually referenced.🔧 Suggested fix
-const { devServer, inliningCss, config } = require('shakapacker'); +const { config } = require('shakapacker');demos/basic-v16-rspack-tanstack/Gemfile (1)
27-32: Consider adding a version constraint for react_on_rails_pro.While
react_on_railshas a specific version pinned (16.2.0.rc1),react_on_rails_prohas no version constraint. This could lead to unexpected behavior if a breaking change is released.The comment explaining the Node.js API requirement is excellent documentation.
demos/basic-v16-rspack-tanstack/app/javascript/src/routes/users/index.tsx (1)
7-14: Consider adding a TypeScript interface for the user data.For a TypeScript demo, adding explicit types would better showcase type-safety benefits:
🔧 Optional type definition
+interface User { + id: number; + name: string; + email: string; +} + // Mock user data -const users = [ +const users: User[] = [ { id: 1, name: 'Alice Johnson', email: 'alice@example.com' },demos/basic-v16-rspack-tanstack/app/javascript/src/routes/search.tsx (1)
4-7: Type inconsistency:pageis always defined after validation.The
validateSearchfunction always returns apagevalue (defaulting to1), butSearchParamsdeclarespage?: numberas optional. This creates a mismatch between the type and runtime behavior.Suggested fix
type SearchParams = { q?: string; - page?: number; + page: number; };demos/basic-v16-rspack-tanstack/playwright.config.ts (1)
17-22: Consider adding Firefox/WebKit projects for broader coverage.Currently only Chromium is configured. For a demo showcasing SSR, testing across browsers could catch browser-specific hydration issues. This is optional for a demo app.
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (5)
demos/basic-v16-rspack-tanstack/Gemfile.lockis excluded by!**/*.lockdemos/basic-v16-rspack-tanstack/package-lock.jsonis excluded by!**/package-lock.jsondemos/basic-v16-rspack-tanstack/public/icon.pngis excluded by!**/*.pngdemos/basic-v16-rspack-tanstack/public/icon.svgis excluded by!**/*.svgdemos/basic-v16-rspack-tanstack/react-on-rails-pro/package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (100)
demos/basic-v16-rspack-tanstack/.demo-metadata.ymldemos/basic-v16-rspack-tanstack/.dev-services.yml.exampledemos/basic-v16-rspack-tanstack/.env.exampledemos/basic-v16-rspack-tanstack/.gitignoredemos/basic-v16-rspack-tanstack/.rubocop.ymldemos/basic-v16-rspack-tanstack/Gemfiledemos/basic-v16-rspack-tanstack/Procfile.devdemos/basic-v16-rspack-tanstack/Procfile.dev-prod-assetsdemos/basic-v16-rspack-tanstack/Procfile.dev-static-assetsdemos/basic-v16-rspack-tanstack/README.mddemos/basic-v16-rspack-tanstack/Rakefiledemos/basic-v16-rspack-tanstack/app/assets/stylesheets/application.cssdemos/basic-v16-rspack-tanstack/app/controllers/application_controller.rbdemos/basic-v16-rspack-tanstack/app/controllers/tanstack_app_controller.rbdemos/basic-v16-rspack-tanstack/app/helpers/application_helper.rbdemos/basic-v16-rspack-tanstack/app/javascript/packs/application.jsdemos/basic-v16-rspack-tanstack/app/javascript/packs/server-bundle.jsdemos/basic-v16-rspack-tanstack/app/javascript/src/HelloWorld/ror_components/HelloWorld.client.tsxdemos/basic-v16-rspack-tanstack/app/javascript/src/HelloWorld/ror_components/HelloWorld.module.cssdemos/basic-v16-rspack-tanstack/app/javascript/src/HelloWorld/ror_components/HelloWorld.server.tsxdemos/basic-v16-rspack-tanstack/app/javascript/src/TanStackApp/ror_components/TanStackApp.client.tsxdemos/basic-v16-rspack-tanstack/app/javascript/src/TanStackApp/ror_components/TanStackApp.server.tsxdemos/basic-v16-rspack-tanstack/app/javascript/src/router.tsdemos/basic-v16-rspack-tanstack/app/javascript/src/routes/__root.tsxdemos/basic-v16-rspack-tanstack/app/javascript/src/routes/about.tsxdemos/basic-v16-rspack-tanstack/app/javascript/src/routes/demo/nested.tsxdemos/basic-v16-rspack-tanstack/app/javascript/src/routes/demo/nested/deep.tsxdemos/basic-v16-rspack-tanstack/app/javascript/src/routes/demo/nested/index.tsxdemos/basic-v16-rspack-tanstack/app/javascript/src/routes/index.tsxdemos/basic-v16-rspack-tanstack/app/javascript/src/routes/search.tsxdemos/basic-v16-rspack-tanstack/app/javascript/src/routes/users/$userId.tsxdemos/basic-v16-rspack-tanstack/app/javascript/src/routes/users/index.tsxdemos/basic-v16-rspack-tanstack/app/javascript/types/css-modules.d.tsdemos/basic-v16-rspack-tanstack/app/jobs/application_job.rbdemos/basic-v16-rspack-tanstack/app/mailers/application_mailer.rbdemos/basic-v16-rspack-tanstack/app/models/application_record.rbdemos/basic-v16-rspack-tanstack/app/views/layouts/application.html.erbdemos/basic-v16-rspack-tanstack/app/views/layouts/mailer.html.erbdemos/basic-v16-rspack-tanstack/app/views/layouts/mailer.text.erbdemos/basic-v16-rspack-tanstack/app/views/layouts/tanstack_app.html.erbdemos/basic-v16-rspack-tanstack/app/views/pwa/manifest.json.erbdemos/basic-v16-rspack-tanstack/app/views/pwa/service-worker.jsdemos/basic-v16-rspack-tanstack/app/views/tanstack_app/index.html.erbdemos/basic-v16-rspack-tanstack/babel.config.jsdemos/basic-v16-rspack-tanstack/bin/brakemandemos/basic-v16-rspack-tanstack/bin/bundledemos/basic-v16-rspack-tanstack/bin/devdemos/basic-v16-rspack-tanstack/bin/railsdemos/basic-v16-rspack-tanstack/bin/rakedemos/basic-v16-rspack-tanstack/bin/rubocopdemos/basic-v16-rspack-tanstack/bin/setupdemos/basic-v16-rspack-tanstack/bin/shakapackerdemos/basic-v16-rspack-tanstack/bin/shakapacker-configdemos/basic-v16-rspack-tanstack/bin/shakapacker-dev-serverdemos/basic-v16-rspack-tanstack/bin/shakapacker-precompile-hookdemos/basic-v16-rspack-tanstack/bin/switch-bundlerdemos/basic-v16-rspack-tanstack/bin/thrustdemos/basic-v16-rspack-tanstack/config.rudemos/basic-v16-rspack-tanstack/config/application.rbdemos/basic-v16-rspack-tanstack/config/boot.rbdemos/basic-v16-rspack-tanstack/config/credentials.yml.encdemos/basic-v16-rspack-tanstack/config/database.ymldemos/basic-v16-rspack-tanstack/config/environment.rbdemos/basic-v16-rspack-tanstack/config/environments/development.rbdemos/basic-v16-rspack-tanstack/config/environments/production.rbdemos/basic-v16-rspack-tanstack/config/environments/test.rbdemos/basic-v16-rspack-tanstack/config/initializers/assets.rbdemos/basic-v16-rspack-tanstack/config/initializers/content_security_policy.rbdemos/basic-v16-rspack-tanstack/config/initializers/filter_parameter_logging.rbdemos/basic-v16-rspack-tanstack/config/initializers/inflections.rbdemos/basic-v16-rspack-tanstack/config/initializers/react_on_rails.rbdemos/basic-v16-rspack-tanstack/config/initializers/react_on_rails_pro.rbdemos/basic-v16-rspack-tanstack/config/locales/en.ymldemos/basic-v16-rspack-tanstack/config/puma.rbdemos/basic-v16-rspack-tanstack/config/routes.rbdemos/basic-v16-rspack-tanstack/config/shakapacker.ymldemos/basic-v16-rspack-tanstack/config/webpack/clientWebpackConfig.jsdemos/basic-v16-rspack-tanstack/config/webpack/commonWebpackConfig.jsdemos/basic-v16-rspack-tanstack/config/webpack/development.jsdemos/basic-v16-rspack-tanstack/config/webpack/generateWebpackConfigs.jsdemos/basic-v16-rspack-tanstack/config/webpack/production.jsdemos/basic-v16-rspack-tanstack/config/webpack/serverWebpackConfig.jsdemos/basic-v16-rspack-tanstack/config/webpack/test.jsdemos/basic-v16-rspack-tanstack/config/webpack/webpack.config.jsdemos/basic-v16-rspack-tanstack/db/seeds.rbdemos/basic-v16-rspack-tanstack/docs/react-on-rails-pro-setup.mddemos/basic-v16-rspack-tanstack/e2e/tanstack_router.spec.tsdemos/basic-v16-rspack-tanstack/package.jsondemos/basic-v16-rspack-tanstack/playwright.config.tsdemos/basic-v16-rspack-tanstack/public/400.htmldemos/basic-v16-rspack-tanstack/public/404.htmldemos/basic-v16-rspack-tanstack/public/406-unsupported-browser.htmldemos/basic-v16-rspack-tanstack/public/422.htmldemos/basic-v16-rspack-tanstack/public/500.htmldemos/basic-v16-rspack-tanstack/public/robots.txtdemos/basic-v16-rspack-tanstack/react-on-rails-pro/node-renderer.jsdemos/basic-v16-rspack-tanstack/react-on-rails-pro/package.jsondemos/basic-v16-rspack-tanstack/test/test_helper.rbdemos/basic-v16-rspack-tanstack/tsconfig.jsonlefthook.yml
✅ Files skipped from review due to trivial changes (1)
- demos/basic-v16-rspack-tanstack/Procfile.dev
🚧 Files skipped from review as they are similar to previous changes (60)
- demos/basic-v16-rspack-tanstack/app/views/layouts/mailer.html.erb
- demos/basic-v16-rspack-tanstack/Procfile.dev-static-assets
- demos/basic-v16-rspack-tanstack/config/credentials.yml.enc
- demos/basic-v16-rspack-tanstack/app/javascript/packs/application.js
- demos/basic-v16-rspack-tanstack/bin/rake
- demos/basic-v16-rspack-tanstack/config/environment.rb
- demos/basic-v16-rspack-tanstack/public/500.html
- demos/basic-v16-rspack-tanstack/public/406-unsupported-browser.html
- demos/basic-v16-rspack-tanstack/.env.example
- demos/basic-v16-rspack-tanstack/app/javascript/src/routes/index.tsx
- demos/basic-v16-rspack-tanstack/app/javascript/src/router.ts
- demos/basic-v16-rspack-tanstack/app/javascript/src/routes/demo/nested.tsx
- demos/basic-v16-rspack-tanstack/app/javascript/src/HelloWorld/ror_components/HelloWorld.server.tsx
- demos/basic-v16-rspack-tanstack/public/robots.txt
- demos/basic-v16-rspack-tanstack/bin/shakapacker
- demos/basic-v16-rspack-tanstack/public/404.html
- demos/basic-v16-rspack-tanstack/app/javascript/src/TanStackApp/ror_components/TanStackApp.client.tsx
- demos/basic-v16-rspack-tanstack/app/javascript/src/routes/demo/nested/index.tsx
- demos/basic-v16-rspack-tanstack/package.json
- demos/basic-v16-rspack-tanstack/public/422.html
- demos/basic-v16-rspack-tanstack/app/javascript/packs/server-bundle.js
- demos/basic-v16-rspack-tanstack/Rakefile
- demos/basic-v16-rspack-tanstack/bin/shakapacker-dev-server
- demos/basic-v16-rspack-tanstack/config/initializers/react_on_rails_pro.rb
- demos/basic-v16-rspack-tanstack/app/jobs/application_job.rb
- demos/basic-v16-rspack-tanstack/.demo-metadata.yml
- demos/basic-v16-rspack-tanstack/.dev-services.yml.example
- demos/basic-v16-rspack-tanstack/config/webpack/generateWebpackConfigs.js
- demos/basic-v16-rspack-tanstack/app/views/layouts/tanstack_app.html.erb
- demos/basic-v16-rspack-tanstack/app/views/tanstack_app/index.html.erb
- demos/basic-v16-rspack-tanstack/app/javascript/src/HelloWorld/ror_components/HelloWorld.module.css
- demos/basic-v16-rspack-tanstack/app/javascript/src/TanStackApp/ror_components/TanStackApp.server.tsx
- demos/basic-v16-rspack-tanstack/app/controllers/tanstack_app_controller.rb
- demos/basic-v16-rspack-tanstack/config/webpack/test.js
- demos/basic-v16-rspack-tanstack/db/seeds.rb
- demos/basic-v16-rspack-tanstack/react-on-rails-pro/node-renderer.js
- demos/basic-v16-rspack-tanstack/app/views/pwa/service-worker.js
- demos/basic-v16-rspack-tanstack/config/webpack/production.js
- demos/basic-v16-rspack-tanstack/app/views/layouts/application.html.erb
- demos/basic-v16-rspack-tanstack/config/environments/test.rb
- demos/basic-v16-rspack-tanstack/app/javascript/src/HelloWorld/ror_components/HelloWorld.client.tsx
- demos/basic-v16-rspack-tanstack/app/assets/stylesheets/application.css
- demos/basic-v16-rspack-tanstack/config.ru
- demos/basic-v16-rspack-tanstack/app/views/pwa/manifest.json.erb
- demos/basic-v16-rspack-tanstack/bin/rubocop
- demos/basic-v16-rspack-tanstack/config/webpack/webpack.config.js
- demos/basic-v16-rspack-tanstack/config/initializers/inflections.rb
- demos/basic-v16-rspack-tanstack/app/views/layouts/mailer.text.erb
- demos/basic-v16-rspack-tanstack/docs/react-on-rails-pro-setup.md
- demos/basic-v16-rspack-tanstack/public/400.html
- demos/basic-v16-rspack-tanstack/config/environments/development.rb
- demos/basic-v16-rspack-tanstack/app/javascript/src/routes/demo/nested/deep.tsx
- demos/basic-v16-rspack-tanstack/config/boot.rb
- demos/basic-v16-rspack-tanstack/config/locales/en.yml
- demos/basic-v16-rspack-tanstack/bin/shakapacker-config
- demos/basic-v16-rspack-tanstack/tsconfig.json
- demos/basic-v16-rspack-tanstack/bin/bundle
- demos/basic-v16-rspack-tanstack/babel.config.js
- demos/basic-v16-rspack-tanstack/app/models/application_record.rb
- demos/basic-v16-rspack-tanstack/app/javascript/src/routes/users/$userId.tsx
🧰 Additional context used
📓 Path-based instructions (2)
**/*.rb
📄 CodeRabbit inference engine (CLAUDE.md)
When using bin/conductor-exec for Ruby commands (bundle install, bundle exec, etc.), ensure the correct Ruby version from .tool-versions is used
Files:
demos/basic-v16-rspack-tanstack/config/initializers/content_security_policy.rbdemos/basic-v16-rspack-tanstack/config/initializers/assets.rbdemos/basic-v16-rspack-tanstack/config/application.rbdemos/basic-v16-rspack-tanstack/config/initializers/filter_parameter_logging.rbdemos/basic-v16-rspack-tanstack/app/mailers/application_mailer.rbdemos/basic-v16-rspack-tanstack/config/environments/production.rbdemos/basic-v16-rspack-tanstack/config/routes.rbdemos/basic-v16-rspack-tanstack/config/initializers/react_on_rails.rbdemos/basic-v16-rspack-tanstack/config/puma.rbdemos/basic-v16-rspack-tanstack/app/controllers/application_controller.rbdemos/basic-v16-rspack-tanstack/app/helpers/application_helper.rbdemos/basic-v16-rspack-tanstack/test/test_helper.rb
**/*.js
📄 CodeRabbit inference engine (CLAUDE.md)
When using bin/conductor-exec for Node commands (npm install, npm run, etc.), ensure the correct Node version from .tool-versions is used
Files:
demos/basic-v16-rspack-tanstack/config/webpack/clientWebpackConfig.jsdemos/basic-v16-rspack-tanstack/config/webpack/serverWebpackConfig.jsdemos/basic-v16-rspack-tanstack/config/webpack/commonWebpackConfig.jsdemos/basic-v16-rspack-tanstack/config/webpack/development.js
🧠 Learnings (11)
📚 Learning: 2026-01-15T03:21:00.096Z
Learnt from: CR
Repo: shakacode/react_on_rails-demos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-15T03:21:00.096Z
Learning: Applies to config/initializers/react_on_rails.rb : Never overwrite or revert config/initializers/react_on_rails.rb during React on Rails upgrades - this file contains custom settings that must be preserved
Applied to files:
demos/basic-v16-rspack-tanstack/config/initializers/content_security_policy.rbdemos/basic-v16-rspack-tanstack/config/initializers/assets.rbdemos/basic-v16-rspack-tanstack/config/initializers/filter_parameter_logging.rbdemos/basic-v16-rspack-tanstack/react-on-rails-pro/package.jsondemos/basic-v16-rspack-tanstack/config/environments/production.rbdemos/basic-v16-rspack-tanstack/bin/shakapacker-precompile-hookdemos/basic-v16-rspack-tanstack/bin/devdemos/basic-v16-rspack-tanstack/config/initializers/react_on_rails.rbdemos/basic-v16-rspack-tanstack/.gitignoredemos/basic-v16-rspack-tanstack/Gemfiledemos/basic-v16-rspack-tanstack/README.mddemos/basic-v16-rspack-tanstack/.rubocop.yml
📚 Learning: 2026-01-15T03:21:00.096Z
Learnt from: CR
Repo: shakacode/react_on_rails-demos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-15T03:21:00.096Z
Learning: Applies to Gemfile : When upgrading Shakapacker or React on Rails, ONLY update version numbers in Gemfile gem version constraints - never run install generators that regenerate config files
Applied to files:
demos/basic-v16-rspack-tanstack/config/application.rbdemos/basic-v16-rspack-tanstack/bin/switch-bundlerdemos/basic-v16-rspack-tanstack/bin/shakapacker-precompile-hookdemos/basic-v16-rspack-tanstack/bin/devdemos/basic-v16-rspack-tanstack/config/initializers/react_on_rails.rbdemos/basic-v16-rspack-tanstack/bin/brakemandemos/basic-v16-rspack-tanstack/Gemfiledemos/basic-v16-rspack-tanstack/README.md
📚 Learning: 2026-01-15T03:21:00.096Z
Learnt from: CR
Repo: shakacode/react_on_rails-demos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-15T03:21:00.096Z
Learning: Applies to config/webpack/webpack.config.js : Never overwrite or replace config/webpack/webpack.config.js during Shakapacker upgrades - this file contains custom logic that must be preserved
Applied to files:
demos/basic-v16-rspack-tanstack/config/webpack/clientWebpackConfig.jsdemos/basic-v16-rspack-tanstack/bin/switch-bundlerdemos/basic-v16-rspack-tanstack/bin/shakapacker-precompile-hookdemos/basic-v16-rspack-tanstack/config/webpack/serverWebpackConfig.jsdemos/basic-v16-rspack-tanstack/config/shakapacker.ymldemos/basic-v16-rspack-tanstack/config/webpack/commonWebpackConfig.jsdemos/basic-v16-rspack-tanstack/config/initializers/react_on_rails.rbdemos/basic-v16-rspack-tanstack/config/webpack/development.js
📚 Learning: 2026-01-15T03:21:00.096Z
Learnt from: CR
Repo: shakacode/react_on_rails-demos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-15T03:21:00.096Z
Learning: Applies to config/webpack/*.js : Never overwrite or replace config/webpack/*.js custom configuration files during Shakapacker upgrades - preserve all custom configurations
Applied to files:
demos/basic-v16-rspack-tanstack/config/webpack/clientWebpackConfig.jsdemos/basic-v16-rspack-tanstack/bin/switch-bundlerdemos/basic-v16-rspack-tanstack/bin/shakapacker-precompile-hookdemos/basic-v16-rspack-tanstack/config/webpack/serverWebpackConfig.jsdemos/basic-v16-rspack-tanstack/config/shakapacker.ymldemos/basic-v16-rspack-tanstack/config/webpack/commonWebpackConfig.jsdemos/basic-v16-rspack-tanstack/config/webpack/development.js
📚 Learning: 2026-01-15T03:21:00.096Z
Learnt from: CR
Repo: shakacode/react_on_rails-demos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-15T03:21:00.096Z
Learning: When upgrading Shakapacker or React on Rails, read the CHANGELOG for breaking changes and apply only the specific changes mentioned - never use install generators to fix breaking changes
Applied to files:
demos/basic-v16-rspack-tanstack/bin/switch-bundlerdemos/basic-v16-rspack-tanstack/bin/shakapacker-precompile-hookdemos/basic-v16-rspack-tanstack/config/initializers/react_on_rails.rbdemos/basic-v16-rspack-tanstack/Gemfiledemos/basic-v16-rspack-tanstack/README.md
📚 Learning: 2026-01-15T03:21:00.096Z
Learnt from: CR
Repo: shakacode/react_on_rails-demos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-15T03:21:00.096Z
Learning: Applies to package.json : When upgrading Shakapacker or React on Rails, ONLY update version numbers in package.json npm package versions - never run install generators that regenerate config files
Applied to files:
demos/basic-v16-rspack-tanstack/bin/switch-bundlerdemos/basic-v16-rspack-tanstack/react-on-rails-pro/package.jsondemos/basic-v16-rspack-tanstack/bin/shakapacker-precompile-hookdemos/basic-v16-rspack-tanstack/config/shakapacker.ymldemos/basic-v16-rspack-tanstack/config/initializers/react_on_rails.rbdemos/basic-v16-rspack-tanstack/Gemfile
📚 Learning: 2026-01-15T03:21:00.096Z
Learnt from: CR
Repo: shakacode/react_on_rails-demos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-15T03:21:00.096Z
Learning: Applies to config/shakapacker.yml : Never overwrite or revert config/shakapacker.yml during Shakapacker upgrades - this file contains project-specific settings that are sacred
Applied to files:
demos/basic-v16-rspack-tanstack/bin/switch-bundlerdemos/basic-v16-rspack-tanstack/config/shakapacker.yml
📚 Learning: 2026-01-15T03:21:00.096Z
Learnt from: CR
Repo: shakacode/react_on_rails-demos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-15T03:21:00.096Z
Learning: Never run rails shakapacker:install or rails react_on_rails:install commands during upgrades as they overwrite all custom configurations - only use bundle install and npm install
Applied to files:
demos/basic-v16-rspack-tanstack/bin/switch-bundlerdemos/basic-v16-rspack-tanstack/react-on-rails-pro/package.jsondemos/basic-v16-rspack-tanstack/bin/setupdemos/basic-v16-rspack-tanstack/bin/shakapacker-precompile-hookdemos/basic-v16-rspack-tanstack/bin/devdemos/basic-v16-rspack-tanstack/config/initializers/react_on_rails.rbdemos/basic-v16-rspack-tanstack/.gitignoredemos/basic-v16-rspack-tanstack/Gemfiledemos/basic-v16-rspack-tanstack/README.md
📚 Learning: 2026-01-15T03:21:00.096Z
Learnt from: CR
Repo: shakacode/react_on_rails-demos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-15T03:21:00.096Z
Learning: Applies to **/*.rb : When using bin/conductor-exec for Ruby commands (bundle install, bundle exec, etc.), ensure the correct Ruby version from .tool-versions is used
Applied to files:
demos/basic-v16-rspack-tanstack/bin/switch-bundlerlefthook.ymldemos/basic-v16-rspack-tanstack/bin/setupdemos/basic-v16-rspack-tanstack/bin/railsdemos/basic-v16-rspack-tanstack/bin/devdemos/basic-v16-rspack-tanstack/bin/brakeman
📚 Learning: 2026-01-15T03:21:00.096Z
Learnt from: CR
Repo: shakacode/react_on_rails-demos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-15T03:21:00.096Z
Learning: When running pre-commit hooks (lefthook) in Conductor, use bin/conductor-exec wrapper script to ensure correct Ruby and Node versions are available
Applied to files:
lefthook.ymldemos/basic-v16-rspack-tanstack/bin/shakapacker-precompile-hookdemos/basic-v16-rspack-tanstack/bin/brakeman
📚 Learning: 2026-01-15T03:21:00.096Z
Learnt from: CR
Repo: shakacode/react_on_rails-demos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-15T03:21:00.096Z
Learning: Applies to .tool-versions : When running commands in Conductor, use bin/conductor-exec wrapper script to ensure commands respect .tool-versions for correct Ruby/Node version activation
Applied to files:
demos/basic-v16-rspack-tanstack/bin/railsdemos/basic-v16-rspack-tanstack/bin/brakeman
🧬 Code graph analysis (12)
demos/basic-v16-rspack-tanstack/config/initializers/assets.rb (1)
demos/basic-v16-rspack-tanstack/config/application.rb (1)
config(22-41)
demos/basic-v16-rspack-tanstack/config/webpack/clientWebpackConfig.js (3)
demos/basic-v16-rspack-tanstack/config/webpack/serverWebpackConfig.js (2)
require(4-4)commonWebpackConfig(5-5)demos/basic-v16-rspack-tanstack/config/webpack/commonWebpackConfig.js (2)
require(5-5)commonWebpackConfig(16-16)demos/basic-v16-rspack-tanstack/config/webpack/generateWebpackConfigs.js (1)
clientConfig(8-8)
demos/basic-v16-rspack-tanstack/app/javascript/src/routes/about.tsx (8)
demos/basic-v16-rspack-tanstack/app/javascript/src/routes/__root.tsx (1)
Route(4-8)demos/basic-v16-rspack-tanstack/app/javascript/src/routes/search.tsx (1)
Route(9-22)demos/basic-v16-rspack-tanstack/app/javascript/src/routes/demo/nested.tsx (1)
Route(3-5)demos/basic-v16-rspack-tanstack/app/javascript/src/routes/demo/nested/deep.tsx (1)
Route(3-5)demos/basic-v16-rspack-tanstack/app/javascript/src/routes/demo/nested/index.tsx (1)
Route(3-5)demos/basic-v16-rspack-tanstack/app/javascript/src/routes/index.tsx (1)
Route(3-5)demos/basic-v16-rspack-tanstack/app/javascript/src/routes/users/$userId.tsx (1)
Route(3-5)demos/basic-v16-rspack-tanstack/app/javascript/src/routes/users/index.tsx (1)
Route(3-5)
demos/basic-v16-rspack-tanstack/config/initializers/filter_parameter_logging.rb (1)
demos/basic-v16-rspack-tanstack/config/application.rb (1)
config(22-41)
demos/basic-v16-rspack-tanstack/app/javascript/src/routes/__root.tsx (8)
demos/basic-v16-rspack-tanstack/app/javascript/src/routes/about.tsx (1)
Route(3-5)demos/basic-v16-rspack-tanstack/app/javascript/src/routes/search.tsx (1)
Route(9-22)demos/basic-v16-rspack-tanstack/app/javascript/src/routes/demo/nested.tsx (1)
Route(3-5)demos/basic-v16-rspack-tanstack/app/javascript/src/routes/demo/nested/deep.tsx (1)
Route(3-5)demos/basic-v16-rspack-tanstack/app/javascript/src/routes/demo/nested/index.tsx (1)
Route(3-5)demos/basic-v16-rspack-tanstack/app/javascript/src/routes/index.tsx (1)
Route(3-5)demos/basic-v16-rspack-tanstack/app/javascript/src/routes/users/$userId.tsx (1)
Route(3-5)demos/basic-v16-rspack-tanstack/app/javascript/src/routes/users/index.tsx (1)
Route(3-5)
demos/basic-v16-rspack-tanstack/app/javascript/src/routes/search.tsx (8)
demos/basic-v16-rspack-tanstack/app/javascript/src/routes/__root.tsx (1)
Route(4-8)demos/basic-v16-rspack-tanstack/app/javascript/src/routes/about.tsx (1)
Route(3-5)demos/basic-v16-rspack-tanstack/app/javascript/src/routes/demo/nested.tsx (1)
Route(3-5)demos/basic-v16-rspack-tanstack/app/javascript/src/routes/demo/nested/deep.tsx (1)
Route(3-5)demos/basic-v16-rspack-tanstack/app/javascript/src/routes/demo/nested/index.tsx (1)
Route(3-5)demos/basic-v16-rspack-tanstack/app/javascript/src/routes/index.tsx (1)
Route(3-5)demos/basic-v16-rspack-tanstack/app/javascript/src/routes/users/$userId.tsx (1)
Route(3-5)demos/basic-v16-rspack-tanstack/app/javascript/src/routes/users/index.tsx (1)
Route(3-5)
demos/basic-v16-rspack-tanstack/config/environments/production.rb (1)
demos/basic-v16-rspack-tanstack/config/application.rb (1)
config(22-41)
demos/basic-v16-rspack-tanstack/config/webpack/serverWebpackConfig.js (5)
demos/basic-v16-rspack-tanstack/react-on-rails-pro/node-renderer.js (2)
require(17-19)config(21-39)demos/basic-v16-rspack-tanstack/config/webpack/clientWebpackConfig.js (4)
require(6-6)require(29-29)require(37-37)commonWebpackConfig(5-5)demos/basic-v16-rspack-tanstack/config/webpack/commonWebpackConfig.js (2)
require(5-5)commonWebpackConfig(16-16)demos/basic-v16-rspack-tanstack/config/webpack/development.js (1)
require(4-4)demos/basic-v16-rspack-tanstack/config/webpack/generateWebpackConfigs.js (1)
serverWebpackConfig(5-5)
demos/basic-v16-rspack-tanstack/config/routes.rb (1)
packages/shakacode_demo_common/lib/shakacode_demo_common.rb (1)
root(10-12)
demos/basic-v16-rspack-tanstack/app/javascript/src/routes/users/index.tsx (1)
demos/basic-v16-rspack-tanstack/app/javascript/src/routes/users/$userId.tsx (1)
Route(3-5)
demos/basic-v16-rspack-tanstack/config/initializers/react_on_rails.rb (2)
demos/basic-v16-rspack-tanstack/react-on-rails-pro/node-renderer.js (1)
config(21-39)demos/basic-v16-rspack-tanstack/config/application.rb (1)
config(22-41)
demos/basic-v16-rspack-tanstack/config/webpack/development.js (8)
demos/basic-v16-rspack-tanstack/config/webpack/serverWebpackConfig.js (1)
require(4-4)demos/basic-v16-rspack-tanstack/config/webpack/clientWebpackConfig.js (3)
require(6-6)require(29-29)require(37-37)demos/basic-v16-rspack-tanstack/config/webpack/commonWebpackConfig.js (1)
require(5-5)demos/basic-v16-rspack-tanstack/config/webpack/webpack.config.js (3)
require(1-1)require(2-2)require(3-3)demos/basic-v16-rspack-tanstack/config/webpack/production.js (1)
generateWebpackConfigs(4-4)demos/basic-v16-rspack-tanstack/config/webpack/test.js (1)
generateWebpackConfigs(4-4)demos/basic-v16-rspack-tanstack/config/webpack/generateWebpackConfigs.js (1)
clientWebpackConfig(4-4)demos/basic-v16-rspack-tanstack/config/application.rb (1)
config(22-41)
🪛 Checkov (3.2.334)
demos/basic-v16-rspack-tanstack/config/database.yml
[medium] 68-69: Basic Auth Credentials
(CKV_SECRET_4)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: claude-review
🔇 Additional comments (62)
demos/basic-v16-rspack-tanstack/app/helpers/application_helper.rb (1)
1-4: LGTM!Standard Rails helper module boilerplate with the
frozen_string_literalpragma. This is idiomatic Rails scaffolding that provides a placeholder for view helpers to be added as needed.demos/basic-v16-rspack-tanstack/test/test_helper.rb (1)
1-15: LGTM!This is a standard Rails test helper with appropriate configuration. The parallel test setup using
:number_of_processorsand fixture loading follows Rails conventions and is well-suited for the demo application.demos/basic-v16-rspack-tanstack/app/controllers/application_controller.rb (1)
1-5: LGTM!The ApplicationController follows Rails 8 conventions with appropriate browser version restrictions. The explicit CSRF protection with
protect_from_forgery with: :exceptionaddresses the previous security concern and ensures robust defense against cross-site request forgery attacks.demos/basic-v16-rspack-tanstack/app/mailers/application_mailer.rb (1)
1-4: LGTM!Standard Rails ApplicationMailer scaffold code. The placeholder email address is appropriate for a demo application.
demos/basic-v16-rspack-tanstack/app/javascript/types/css-modules.d.ts (1)
1-15: LGTM!This is a standard and correct TypeScript declaration file for CSS modules. The type definitions properly map class names to their generated unique string identifiers, and the coverage of
.css,.scss, and.sassextensions is comprehensive for the project's needs.demos/basic-v16-rspack-tanstack/config/database.yml (1)
15-85: LGTM! Standard Rails database configuration with proper credential handling.The production password is correctly sourced from an environment variable, and development/test configurations appropriately rely on peer authentication.
Regarding the static analysis hint (CKV_SECRET_4) on lines 68-69: this is a false positive — the flagged
postgres://myuser:mypass@localhost/somedatabaseis simply an example URL in documentation comments, not an actual credential.demos/basic-v16-rspack-tanstack/bin/thrust (1)
1-5: LGTM!This is a standard Rails 8 bin stub for thruster (HTTP/2 proxy and asset compression). The pattern correctly uses Bundler setup and delegates to the gem binary via
Gem.bin_path.demos/basic-v16-rspack-tanstack/config/initializers/filter_parameter_logging.rb (1)
6-8: LGTM!This is the standard Rails 8 parameter filtering configuration. The comprehensive list appropriately covers authentication credentials, encryption-related values, and PII/financial data (including
demos/basic-v16-rspack-tanstack/config/initializers/content_security_policy.rb (1)
1-25: LGTM — Standard Rails CSP template appropriate for a demo app.The entirely commented-out CSP initializer is reasonable for a demo project, allowing developers to focus on learning TanStack Router integration without CSP-related friction. The template itself follows best practices (no
unsafe-inline/unsafe-eval) and can be uncommented when needed.demos/basic-v16-rspack-tanstack/config/puma.rb (1)
1-38: LGTM! Standard Rails Puma configuration.This is a well-documented, conventional Puma configuration appropriate for the demo application. The environment-variable-driven settings (threads, port, pidfile) provide good flexibility for different deployment scenarios, and the comments clearly explain the threading model and GVL considerations.
demos/basic-v16-rspack-tanstack/bin/shakapacker-precompile-hook (2)
1-15: LGTM on the script header and documentation.The shebang, frozen_string_literal pragma, and comprehensive documentation block clearly explain the script's purpose and integration with Shakapacker's precompile_hook configuration.
16-21: LGTM on environment setup.Setting
REACT_ON_RAILS_SKIP_VALIDATIONbefore loading the Rails environment is appropriate, and the rationale is well-documented.demos/basic-v16-rspack-tanstack/react-on-rails-pro/package.json (1)
1-10: Package structure is appropriate for the SSR node renderer setup.The minimal package.json is fit for purpose with the RC version intentionally used for showcasing React on Rails 16.2.0 features. No changes needed.
demos/basic-v16-rspack-tanstack/bin/switch-bundler (7)
10-18: LGTM!The dependency constants are well-organized and properly frozen.
20-24: LGTM!Good fail-fast pattern with immediate validation and proper input normalization.
26-37: LGTM!Clear orchestration with helpful user feedback and actionable next steps.
41-45: LGTM!Validation is correct and provides a clear error message.
47-62: Good use ofYAML.safe_load.The security concern from the previous review has been properly addressed. The method now safely parses the YAML file with explicit permitted classes.
89-122: LGTM!Excellent use of the array form of
system()to prevent command injection vulnerabilities. Error handling with explicit return value checks is also well implemented.
132-141: LGTM!Clean CLI entrypoint with helpful usage instructions and proper exit code handling.
demos/basic-v16-rspack-tanstack/bin/rails (1)
1-4: LGTM!Standard Rails
bin/railsentrypoint with correct shebang, APP_PATH configuration, and boot sequence.demos/basic-v16-rspack-tanstack/Procfile.dev-prod-assets (1)
1-8: LGTM!Clear Procfile for testing production assets in development. Port 3001 avoids conflicts with the standard dev server, and commented examples provide useful reference for optional services.
demos/basic-v16-rspack-tanstack/config/initializers/assets.rb (1)
1-7: LGTM!Standard Rails asset pipeline initializer. The version string allows cache busting when needed.
demos/basic-v16-rspack-tanstack/README.md (1)
1-236: Excellent documentation!Comprehensive README with clear setup instructions, thorough SSR configuration explanation (including why Node renderer is required), and honest limitations section. The tables for generated files and scripts are particularly helpful.
demos/basic-v16-rspack-tanstack/.gitignore (1)
1-39: LGTM!Well-organized .gitignore with appropriate patterns for:
- Generated assets (
public/packs,ssr-generated) that should be built during deployment- TanStack Router auto-generated route tree
- Security-sensitive files (credentials, master key,
.npmrcwith auth tokens)- Test artifacts
The
.env.exampleexception is good practice for documenting required environment variables.demos/basic-v16-rspack-tanstack/bin/dev (1)
1-26: LGTM!The development server script is well-structured with clear documentation of the three Procfile modes. The frozen_string_literal pragma and bundler setup are correctly placed before loading the ReactOnRails dev module.
demos/basic-v16-rspack-tanstack/bin/setup (1)
1-37: LGTM!The setup script follows standard Rails conventions with idempotent operations. Good practices observed:
system!wrapper withexception: truefor proper error handlingbundle check || system!("bundle install")avoids unnecessary reinstallsSTDOUT.flushbeforeexecensures output is displayed--skip-serverflag provides flexibility for CI/automation scenariosdemos/basic-v16-rspack-tanstack/config/initializers/react_on_rails.rb (1)
1-76: LGTM!The React on Rails configuration is well-documented with clear explanations of each option. Key highlights:
enforce_private_server_bundles = trueensures server-side code isn't exposed publicly- Comments clearly document the React on Rails Pro dependency for TanStack Router SSR
- Configuration aligns with the node-renderer.js setup (ssr-generated bundle path)
Based on learnings, this file contains custom settings that must be preserved during upgrades—the thorough documentation will help future maintainers understand each setting's purpose.
demos/basic-v16-rspack-tanstack/config/application.rb (1)
1-42: LGTM!Standard Rails 8 application configuration with appropriate selective loading of railties. The decision to disable system test generation (
config.generators.system_tests = nil) aligns well with the PR's use of Playwright for E2E testing.demos/basic-v16-rspack-tanstack/config/environments/production.rb (1)
1-86: LGTM!Solid Rails 8 production configuration with good security and operational practices:
- SSL enforcement with
force_sslandassume_ssl- 12-factor compliant logging to STDOUT with request ID tagging
attributes_for_inspect = [:id]prevents PII leakage in logs- Health check path silencing reduces log noise
The
example.complaceholder on line 57 is acceptable for a demo application.demos/basic-v16-rspack-tanstack/config/routes.rb (1)
3-16: LGTM! Routes correctly support SSR for TanStack Router SPA.The routing pattern is appropriate for a single-page application with server-side rendering—all client routes map to the same controller action which renders the initial HTML. The
:userIdcamelCase parameter on line 11 aligns with TanStack Router's frontend conventions.demos/basic-v16-rspack-tanstack/config/webpack/commonWebpackConfig.js (2)
15-18: Good use of function factory to avoid mutating shared globals.Returning a fresh merged config on each call prevents unintended side effects from modifying the base config. This pattern is essential given the mutable nature of the webpack config objects.
9-13: The extensions array is not problematic — webpack-merge concatenates rather than replaces arrays.Shakapacker's
mergefunction re-exports webpack-merge, which concatenates arrays when merging configs. ThegenerateWebpackConfig()provides webpack's default extensions ([".js", ".json", ".wasm"]), and when merged withcommonOptions, the result includes all extensions:[".js", ".json", ".wasm", ".css", ".ts", ".tsx"]. The.jsfiles in the project (e.g.,application.js,server-bundle.js) will resolve correctly.Likely an incorrect or invalid review comment.
demos/basic-v16-rspack-tanstack/config/webpack/clientWebpackConfig.js (1)
8-45: LGTM! Clean conditional plugin loading with appropriate error handling.The implementation correctly:
- Removes the server-bundle entry to prevent client-side loading issues
- Conditionally loads the appropriate TanStack Router plugin based on the bundler type
- Uses try/catch with warnings for graceful degradation if the plugin isn't available
demos/basic-v16-rspack-tanstack/config/webpack/serverWebpackConfig.js (1)
122-132: LGTM! SSR-specific settings are appropriate.Using
devtool: 'eval'for fast SSR debugging andtarget: 'node'for Node.js APIs are correct choices for a server bundle intended for React on Rails Pro's Node renderer.demos/basic-v16-rspack-tanstack/config/shakapacker.yml (1)
28-63: LGTM! Development configuration is appropriate for the demo setup.The
compile: falsesetting in development is correct since this demo uses a separate webpack dev server (as indicated by thedev_serverconfiguration). HMR and inline CSS settings are properly configured.demos/basic-v16-rspack-tanstack/config/webpack/development.js (1)
8-26: LGTM! React Fast Refresh setup is well-structured.The conditional logic correctly differentiates between rspack and webpack bundlers, loading the appropriate refresh plugin for each. The guard on
WEBPACK_SERVEensures the plugin is only added during dev server operation, which is the correct behavior for HMR.demos/basic-v16-rspack-tanstack/Gemfile (1)
1-54: LGTM! Well-structured Gemfile for the Rails 8 demo.The gem selection is appropriate for the demo's purpose. The use of
react_on_railsrelease candidate (16.2.0.rc1) is acceptable for a demo app showcasing upcoming features.demos/basic-v16-rspack-tanstack/bin/brakeman (1)
1-7: LGTM!Standard Rails bin script pattern for Brakeman. The
--ensure-latestflag is a good practice to encourage keeping security scanning tools up to date.demos/basic-v16-rspack-tanstack/.rubocop.yml (1)
1-8: LGTM!Clean RuboCop configuration inheriting from Rails Omakase. The commented example provides helpful guidance for future customization.
demos/basic-v16-rspack-tanstack/app/javascript/src/routes/users/index.tsx (2)
3-5: LGTM! Route definition follows TanStack Router conventions.The file-based routing setup using
createFileRouteis correctly implemented and consistent with the project's other route files (e.g.,/users/$userId).
33-35: Good use of type-safe route parameters.The Link correctly converts
user.idto a string for the route params, which aligns with TanStack Router's expectation that URL parameters are strings.demos/basic-v16-rspack-tanstack/e2e/tanstack_router.spec.ts (5)
5-14: LGTM!The home page SSR test correctly validates that server-rendered content is visible after
domcontentloaded, which is appropriate for SSR verification.
16-24: LGTM!Clean SSR verification for the about page.
26-57: LGTM!Good coverage of SSR for URL parameters, search params, and nested routes. The specific
h3:text("Deep Nested Page")selector appropriately avoids matching navigation links.
60-120: LGTM!Client hydration tests properly wait for elements to be visible before interaction, avoiding flakiness. The navigation tests verify both URL updates and content changes.
122-151: LGTM!The hydration consistency test uses a smart approach: verifying navigation works confirms React hydration completed, which is more reliable than arbitrary timeouts. The console log filtering for hydration-related messages is appropriate.
demos/basic-v16-rspack-tanstack/app/javascript/src/routes/about.tsx (2)
1-5: LGTM!The route definition follows the established TanStack Router file-based routing pattern used consistently across other routes in this demo.
7-38: LGTM!Clean, informative About page component with appropriate static content describing the demo's technology stack and SSR behavior.
demos/basic-v16-rspack-tanstack/app/javascript/src/routes/search.tsx (3)
9-22: LGTM!The
validateSearchfunction correctly handles various input types with appropriate fallbacks. TheparseInt(search.page, 10) || 1pattern properly handlesNaNfrom non-numeric strings.
24-48: LGTM!The component logic is well-structured. The
useEffectproperly syncs the input value with URL changes (e.g., browser back/forward), and navigation handlers correctly manage search state.
49-119: LGTM!The JSX renders a complete search UI with form, current state display, pagination controls, and helpful example URLs. The pagination buttons correctly disable "Previous" when on page 1.
demos/basic-v16-rspack-tanstack/playwright.config.ts (2)
3-15: LGTM!Sensible Playwright configuration. Serial execution with 1 worker is appropriate for avoiding race conditions with server resources. The CI-aware retry and
forbidOnlysettings are good practices.
24-33: LGTM!The
webServerconfiguration appropriately handles both development (reuseExistingServer: true) and CI (reuseExistingServer: false) scenarios. TheSKIP_WEB_SERVERescape hatch is useful for running tests against an already-running server.lefthook.yml (2)
54-88: LGTM!ESLint and Prettier hooks correctly handle per-demo execution with appropriate manual
git addcalls after fixes. The|| trueaftergrepprevents hook failure when no demo files are staged.
25-51: [Your rewritten review comment text here]
[Exactly ONE classification tag]demos/basic-v16-rspack-tanstack/app/javascript/src/routes/__root.tsx (6)
1-8: LGTM! Clean root route setup.The route configuration properly establishes the TanStack Router root with error handling and 404 components. The function hoisting allows referencing components before their declarations.
14-33: Good error boundary implementation.The error component maintains navigation consistency and properly delegates error rendering to TanStack Router's
ErrorComponent. This ensures users can navigate away from error states.
38-60: Clean 404 implementation.The not-found component provides clear user feedback with consistent navigation and a direct link back to home. The visual distinction (amber theme) appropriately signals a warning state.
62-68: Appropriate use of shared style objects.The
as constassertion onfontWeightcorrectly narrows the type for TypeScript. Style sharing avoids duplication across link components.
74-125: Well-structured navigation with good accessibility.The navigation properly implements:
aria-labelon the nav element for screen readersaria-current="page"viaactivePropsfor active link identificationactiveOptions={{ exact: true }}on Home to prevent it being highlighted on all routesThe parent routes (Users, Nested Routes) will correctly highlight when viewing child routes, which is typically the expected UX for hierarchical navigation.
127-136: LGTM! Standard root layout pattern.The component correctly uses
Outletto render child route content, maintaining a consistent structure with the error and not-found components.
✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.
- Replace weak example password with CHANGE_THIS_TO_A_STRONG_PASSWORD - Remove outdated GitHub PAT reference from .env.example - Add trailing newline to package.json output in switch-bundler - Add null check before accessing rule.use.options in serverWebpackConfig - Fix Created date from 2025 to 2026 in README Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Code Review: TanStack Router Demo with SSR and TypeScriptThis is an excellent addition to the demos repository! The PR demonstrates a well-structured implementation of TanStack Router with React on Rails SSR support. Here's my detailed review: ✅ Strengths1. Excellent Code Quality
2. Security Best Practices ✓
3. Robust Test CoverageThe E2E tests in
4. Configuration Management
5. Documentation Excellence
🎯 Areas for Consideration (Minor Improvements)1. Test RobustnessFile: The hydration mismatch test relies on clicking a link to verify hydration completion. Consider adding an explicit wait for React hydration: // More explicit hydration check
await page.waitForFunction(() => {
const rootElement = document.querySelector('[data-reactroot]');
return rootElement && rootElement._reactRootContainer !== undefined;
});Impact: Low - Current approach works but could be more explicit 2. Configuration WarningsFile: The warning for missing
Impact: Very Low - Defensive programming is good practice 3. CSS Module ConfigurationFile: The CSS loader configuration for SSR has nested conditionals checking for css-loader. Consider extracting this logic to a helper function for clarity: function configureCSSLoaderForSSR(rule) {
if (!Array.isArray(rule.use)) return;
const cssLoader = findCSSLoader(rule.use);
if (cssLoader?.options) {
cssLoader.options.modules = { exportOnlyLocals: true };
}
}Impact: Very Low - Current code works correctly 4. Null SafetyFile: Good null checks on if (rule.use?.options) {
rule.use.options.emitFile = false;
} else if (rule.use) {
rule.use.options = { emitFile: false };
}Impact: Very Low - Unlikely edge case 📊 Test Coverage AssessmentExcellent Coverage:
Potential Additions (Optional):
🔒 Security Review: PASSEDNo security concerns identified. The code follows best practices:
📝 Performance ConsiderationsPositive:
Note:The synchronous SSR approach (
🎓 Adherence to CLAUDE.md Guidelines✅ Excellent compliance with repository conventions:
🏆 Final AssessmentOverall Rating: ⭐⭐⭐⭐⭐ Excellent This PR demonstrates:
Recommendation: APPROVE ✅The minor suggestions above are purely optional refinements. The code is ready to merge as-is and serves as an excellent reference implementation for TanStack Router with React on Rails SSR. 🙏 Additional KudosSpecial appreciation for:
Great work! 🎉 |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@demos/basic-v16-rspack-tanstack/config/webpack/serverWebpackConfig.js`:
- Around line 63-72: The warning text is misleading because the code only checks
config.privateOutputPath rather than detecting Shakapacker's version; update the
logic so the message is version-agnostic (or add actual version detection).
Specifically, change the console.warn block that runs when
config.privateOutputPath is falsy (referencing config.privateOutputPath) to
remove the "Shakapacker 9.0+ detected" claim and instead explain that
private_output_path is not configured and must be added (or, if you prefer to
detect the version, implement a real check for Shakapacker version and
conditionally show the 9.0+ wording).
🧹 Nitpick comments (1)
demos/basic-v16-rspack-tanstack/config/webpack/serverWebpackConfig.js (1)
29-38: Remove duplicate CSS plugin filtering logic.This loop only handles string items and is redundant with the more comprehensive filtering at lines 88-98, which handles both string and object loader items. Consider removing this block to avoid confusion and reduce maintenance burden.
♻️ Suggested removal
- // Remove the mini-css-extract-plugin from the style loaders because - // the client build will handle exporting CSS. - // replace file-loader with null-loader - serverWebpackConfig.module.rules.forEach((loader) => { - if (loader.use && loader.use.filter) { - loader.use = loader.use.filter( - (item) => !(typeof item === 'string' && item.match(/mini-css-extract-plugin/)) - ); - } - }); - // No splitting of chunks for a server bundle
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
demos/basic-v16-rspack-tanstack/.env.exampledemos/basic-v16-rspack-tanstack/README.mddemos/basic-v16-rspack-tanstack/bin/switch-bundlerdemos/basic-v16-rspack-tanstack/config/webpack/serverWebpackConfig.js
🚧 Files skipped from review as they are similar to previous changes (2)
- demos/basic-v16-rspack-tanstack/.env.example
- demos/basic-v16-rspack-tanstack/bin/switch-bundler
🧰 Additional context used
📓 Path-based instructions (1)
**/*.js
📄 CodeRabbit inference engine (CLAUDE.md)
When using bin/conductor-exec for Node commands (npm install, npm run, etc.), ensure the correct Node version from .tool-versions is used
Files:
demos/basic-v16-rspack-tanstack/config/webpack/serverWebpackConfig.js
🧠 Learnings (6)
📚 Learning: 2026-01-15T03:21:00.096Z
Learnt from: CR
Repo: shakacode/react_on_rails-demos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-15T03:21:00.096Z
Learning: Applies to config/webpack/webpack.config.js : Never overwrite or replace config/webpack/webpack.config.js during Shakapacker upgrades - this file contains custom logic that must be preserved
Applied to files:
demos/basic-v16-rspack-tanstack/config/webpack/serverWebpackConfig.js
📚 Learning: 2026-01-15T03:21:00.096Z
Learnt from: CR
Repo: shakacode/react_on_rails-demos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-15T03:21:00.096Z
Learning: Applies to config/webpack/*.js : Never overwrite or replace config/webpack/*.js custom configuration files during Shakapacker upgrades - preserve all custom configurations
Applied to files:
demos/basic-v16-rspack-tanstack/config/webpack/serverWebpackConfig.js
📚 Learning: 2026-01-15T03:21:00.096Z
Learnt from: CR
Repo: shakacode/react_on_rails-demos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-15T03:21:00.096Z
Learning: When upgrading Shakapacker or React on Rails, read the CHANGELOG for breaking changes and apply only the specific changes mentioned - never use install generators to fix breaking changes
Applied to files:
demos/basic-v16-rspack-tanstack/README.md
📚 Learning: 2026-01-15T03:21:00.096Z
Learnt from: CR
Repo: shakacode/react_on_rails-demos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-15T03:21:00.096Z
Learning: Never run rails shakapacker:install or rails react_on_rails:install commands during upgrades as they overwrite all custom configurations - only use bundle install and npm install
Applied to files:
demos/basic-v16-rspack-tanstack/README.md
📚 Learning: 2026-01-15T03:21:00.096Z
Learnt from: CR
Repo: shakacode/react_on_rails-demos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-15T03:21:00.096Z
Learning: Applies to config/initializers/react_on_rails.rb : Never overwrite or revert config/initializers/react_on_rails.rb during React on Rails upgrades - this file contains custom settings that must be preserved
Applied to files:
demos/basic-v16-rspack-tanstack/README.md
📚 Learning: 2026-01-15T03:21:00.096Z
Learnt from: CR
Repo: shakacode/react_on_rails-demos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-15T03:21:00.096Z
Learning: Applies to Gemfile : When upgrading Shakapacker or React on Rails, ONLY update version numbers in Gemfile gem version constraints - never run install generators that regenerate config files
Applied to files:
demos/basic-v16-rspack-tanstack/README.md
🧬 Code graph analysis (1)
demos/basic-v16-rspack-tanstack/config/webpack/serverWebpackConfig.js (4)
demos/basic-v16-rspack-tanstack/config/webpack/clientWebpackConfig.js (4)
require(6-6)require(29-29)require(37-37)commonWebpackConfig(5-5)demos/basic-v16-rspack-tanstack/react-on-rails-pro/node-renderer.js (2)
require(17-19)config(21-39)demos/basic-v16-rspack-tanstack/config/webpack/commonWebpackConfig.js (2)
require(5-5)commonWebpackConfig(16-16)demos/basic-v16-rspack-tanstack/config/webpack/generateWebpackConfigs.js (1)
serverWebpackConfig(5-5)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: claude-review
🔇 Additional comments (7)
demos/basic-v16-rspack-tanstack/README.md (1)
1-236: Excellent comprehensive documentation!This README is exceptionally well-structured and thorough. It clearly documents:
- React on Rails Pro requirements and Node renderer necessity
- Complete setup and build instructions
- SSR configuration details with code examples
- Important limitations (route synchronization, synchronous SSR)
- Deployment considerations
- Comprehensive reference tables for scripts, files, and generated directories
The explanations of why the Node renderer is required (lines 115-125) and the limitations around route synchronization (lines 181-196) are particularly valuable for users. The documentation will help developers understand both the capabilities and constraints of this integration.
demos/basic-v16-rspack-tanstack/config/webpack/serverWebpackConfig.js (6)
1-8: LGTM!Clean imports with good conditional bundler selection pattern supporting both Rspack and Webpack.
9-27: LGTM!Good defensive coding using
mergeto avoid mutating the shared global config, and clear error handling when the server-bundle entry is missing.
40-44: LGTM!Appropriate optimization settings for an SSR bundle—disabling minimization and limiting to a single chunk.
74-81: LGTM!Appropriate plugin filtering for SSR—removing manifest generation, CSS extraction, and TypeScript checking that belong in the client build.
83-121: LGTM!Previously flagged issues have been properly addressed:
testValueinitialized to''to prevent TypeErrors (lines 92, 101)- Null check for
rule.use.optionsadded (line 118)The loader rule configuration correctly handles CSS modules for SSR and disables file emission for asset loaders.
123-136: LGTM!Appropriate
devtoolandtargetsettings for SSR. The documentation clearly explains why Node.js target is required for TanStack Router.
✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.
The warning message incorrectly claimed to detect Shakapacker 9.0+ when it only checks if privateOutputPath is undefined. Updated to be version-agnostic and clarify it's using a fallback path. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Pull Request Review: TanStack Router Demo with SSRExcellent work on this comprehensive demo! This is a well-structured implementation showcasing TanStack Router with React on Rails. Below are my findings organized by category: ✅ StrengthsCode Quality & Architecture
Security
Documentation
🐛 Potential Issues1. Node Renderer Package Reference (Minor)File: The import references const {
reactOnRailsProNodeRenderer,
} = require('@shakacode-tools/react-on-rails-pro-node-renderer');However, commit message (72b4250) indicates migration to regular npm packages. Verify this package name is correct or should be updated to match the new registry structure. 2. Null Safety in serverWebpackConfig.js (Minor)File: The code checks if (cssLoader && cssLoader.options) {
cssLoader.options.modules = { exportOnlyLocals: true };
}While this is likely safe in practice, consider: if (cssLoader && cssLoader.options) {
cssLoader.options.modules = cssLoader.options.modules || {};
cssLoader.options.modules.exportOnlyLocals = true;
}3. Missing Error Handling in TanStack Router Plugin (Low Priority)File: Try-catch blocks warn but don't provide recovery instructions: catch (e) {
console.warn('TanStack Router Rspack plugin not available:', e.message);
}Consider adding installation hints or failing loudly if the plugin is required for this demo to function. 4. Playwright Test Selector Specificity (Minor)File: Using await expect(page.locator('[data-testid="deep-nested-heading"]')).toBeVisible();⚡ Performance ConsiderationsPositive
Suggestions
🔒 Security ReviewCritical Security Checks: ✅ All Passed
Recommendations
📊 Test CoverageExcellent Coverage
Suggestions
🎯 Adherence to CLAUDE.md Guidelines✅ Excellent Compliance
📝 Minor Suggestions
🎉 SummaryThis is production-ready demo code with excellent documentation, comprehensive testing, and thoughtful architecture. The issues identified are minor and mostly suggestions for enhancement rather than bugs. Recommendation: ✅ APPROVEThe code demonstrates:
Priority Fixes (Optional)
Great work on this comprehensive demo! 🚀 Reviewed using repository's CLAUDE.md guidelines |
- Update react_on_rails from 16.2.0.rc1 to 16.2.0 - Update react_on_rails_pro from 16.2.0.rc.1 to 16.2.0 - Update react-on-rails-pro-node-renderer npm package to 16.2.0 - Add react_on_rails_pro_license.key to .gitignore Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Pull Request Review - TanStack Router DemoThank you for this comprehensive TanStack Router demo! This is a well-structured addition to the repository that demonstrates SSR with modern routing. Here's my detailed review: ✅ Strengths1. Excellent Documentation
2. Well-Designed Architecture
3. Comprehensive Testing
4. Best Practices
🔍 Issues & SuggestionsCritical Issues1. React on Rails Pro Configuration Not CommittedLocation: The configuration file mentions requiring React on Rails Pro's Node renderer, but the actual configuration is commented out: # To configure React on Rails Pro Node renderer:
# config.server_render_method = "NodeJS"Issue: Users following the setup won't have SSR working without uncommenting this. Recommendation: Either:
2. Void Expression in Server ComponentLocation: void router.load();Issue: While the comment explains this is intentional, using Recommendation: Either:
Security Concerns3. Default Password in Node RendererLocation: password: process.env.RENDERER_PASSWORD || 'tanstack-demo-renderer',Issue: Hardcoded default password in a production-style configuration file. Recommendation:
Performance Considerations4. No Chunk Splitting Strategy DocumentedLocation: General webpack configuration Observation: The server bundle correctly limits chunks to 1, but there's no documentation about client-side code splitting strategies. Recommendation:
Code Quality Issues5. Missing Error Boundary for Hydration ErrorsLocation: Issue: Client component doesn't have specific error handling for hydration mismatches. Recommendation:
class HydrationErrorBoundary extends React.Component {
componentDidCatch(error: Error) {
if (error.message.includes('hydration')) {
console.error('Hydration mismatch detected:', error);
// Could send to error tracking service
}
}
}6. Routes Configuration DuplicationLocation: Issue: Routes are defined in both Rails and TanStack Router with no validation that they match. Recommendation:
7. TypeScript StrictnessLocation: Multiple TypeScript files Observation: Using Recommendation:
Testing Gaps8. No Tests for Error StatesLocation: Missing Coverage:
Recommendation: test('renders 404 page for unknown routes', async ({ page }) => {
await page.goto('/nonexistent-route');
await expect(page.locator('h1')).toContainText('Page Not Found');
});
test('error boundary catches route errors', async ({ page }) => {
// Navigate to route that throws error
// Verify error boundary displays
});9. No SSR Performance TestsLocation: Testing suite Missing: Tests to ensure SSR performance doesn't degrade. Recommendation:
Documentation Issues10. Missing Migration GuideLocation: README.md Issue: No guidance for users migrating from other routing solutions (React Router, etc.). Recommendation:
11. Incomplete Setup InstructionsLocation: README.md Missing Steps:
Recommendation: ## Prerequisites
- Node.js 18+ (verified with `node --version`)
- Ruby 3.x (specified in .tool-versions)
- PostgreSQL running locally
- React on Rails Pro license (see docs/react-on-rails-pro-setup.md)Minor Issues12. Console Warnings in DevelopmentLocation: Server webpack config The warning about Recommendation:
13. Unused DependenciesLocation: package.json (not shown in diff, would need to check) Recommendation:
14. Hardcoded Port NumbersLocation: Multiple Procfile.dev files Recommendation:
📊 Test Coverage AssessmentWell Covered:
Needs Coverage:
🔒 Security ReviewConcerns Identified:
Recommendations:
🎯 Performance ReviewGood:
Could Improve:
📝 Summary & RecommendationsMust Fix Before Merge:
Should Fix Before Merge:
Nice to Have:
✨ ConclusionThis is a solid, well-documented demo that showcases TanStack Router integration with React on Rails SSR. The architecture is sound, the testing is comprehensive, and the documentation is helpful. The main concerns are:
With the critical issues addressed, this will be an excellent addition to the demo repository! Overall Rating: 8/10 - Great work! Address the critical issues and this is merge-ready. Review generated using repository guidelines from CLAUDE.md |
TanStack Router requires Node.js APIs (URL, setTimeout, etc.) that are not available in the default ExecJS environment. This update: - Switch to react-on-rails-pro npm package (required when using Pro gem) - Fix config typo: renderer_use_fallback_exec_js (underscore) - Update node-renderer.js to use regular npm package name - Add node-polyfills.ts for URL/URLSearchParams globals - Import polyfills first in server-bundle.js Note: SSR with TanStack Router still needs further investigation for the VM sandbox polyfill approach. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
PR Review: TanStack Router Demo with SSR and TypeScriptSummaryThis PR adds a comprehensive demo showcasing TanStack Router integration with React on Rails, Rspack, and SSR. The implementation is well-structured and demonstrates important concepts for building modern React applications with Rails. Overall, this is high-quality work that will serve as an excellent reference for users. ✅ Strengths1. Excellent Documentation
2. Proper SSR Architecture
3. Comprehensive E2E Testing
4. Configuration Best Practices
🔍 Issues & RecommendationsCritical Issues1. Void Operator Misuse (config/webpack/serverWebpackConfig.js:31)void router.load();Issue: Using Recommendation: Either:
2. TypeScript
|
Add createTanStackRouterRenderFunction() to the react-on-rails npm package, providing a render function factory for TanStack Router apps with server-side rendering support. This encapsulates the private API workarounds needed for synchronous SSR (router.__store.setState() and router.ssr flag) inside ShakaCode-maintained code, so consumer apps only use public APIs. Server-side: synchronously injects route matches and renders with renderToString. Client-side: hydrates with browser history and dehydrated router state from the server. Also includes an async path (serverRenderTanStackAppAsync) for use with React on Rails Pro NodeRenderer when rendering_returns_promises is enabled. Related: #2298, #2299 Ref: printivity/printivity#2571, shakacode/react_on_rails-demos#104 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Summary
basic-v16-rspack-tanstackshowcasing TanStack Router with React on RailsFeatures Demonstrated
src/routes//users/:userId/search/demo/nestedTechnical Stack
Test Plan
bin/shakapackercompiles without errorsbundle exec rubocopnpx playwright test(after starting dev server)//about/userswith links to detail pages/users/123/search?q=test&page=2/demo/nested/deep🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Tests
Documentation
✏️ Tip: You can customize this high-level summary in your review settings.