Created
July 4, 2025 17:41
-
-
Save adenta/35d2443957f11fc75b2f0df81005c043 to your computer and use it in GitHub Desktop.
Scaffold React + Turbo Mount + DaisyUI in Ruby on Rails
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import React from "react"; | |
| interface DashboardProps { | |
| app_name: string; | |
| } | |
| const Dashboard: React.FC<DashboardProps> = ({ app_name }) => { | |
| return ( | |
| <React.StrictMode> | |
| <div className="p-6"> | |
| <h1 className="text-4xl font-bold">Hello from {app_name}</h1> | |
| </div> | |
| </React.StrictMode> | |
| ); | |
| }; | |
| export default Dashboard; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <%%= turbo_mount("Dashboard", props: { app_name: Rails.application.class.name.split("::").first }, class: "mb-5") %> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| require_relative 'base_generator' | |
| class ReactGenerator < BaseGenerator | |
| def setup_typescript | |
| say_status_with_color "setup", "TypeScript configuration", :cyan | |
| # Update layout for TypeScript and remove default styling | |
| gsub_file "app/views/layouts/application.html.erb", | |
| "<%= vite_javascript_tag 'application' %>", | |
| "<%= vite_react_refresh_tag %>\n<%= vite_typescript_tag 'application' %>" | |
| gsub_file "app/views/layouts/application.html.erb", | |
| '<main class="container mx-auto mt-28 px-5 flex">', | |
| "<main>" | |
| template "typescript/tsconfig.json.erb", "tsconfig.json" | |
| end | |
| def install_javascript_packages | |
| run_with_status "npm install react react-dom @vitejs/plugin-react @types/react @hotwired/turbo-rails stimulus-vite-helpers turbo-mount", | |
| "React and TypeScript packages" | |
| run_with_status "npm install -D daisyui", "DaisyUI development dependency" | |
| end | |
| def setup_daisyui | |
| say_status_with_color "setup", "DaisyUI configuration", :cyan | |
| append_to_file "app/assets/tailwind/application.css", <<~CSS | |
| @plugin "daisyui"; | |
| CSS | |
| end | |
| def create_turbo_mount_setup | |
| say_status_with_color "create", "Turbo Mount configuration", :cyan | |
| template "javascript/turbo-mount.js.erb", "app/javascript/turbo-mount.js" | |
| template "javascript/Dashboard.tsx.erb", "app/javascript/components/Dashboard.tsx" | |
| # Update application.ts entrypoint | |
| gsub_file "app/javascript/entrypoints/application.ts", /import.*App\.tsx.*/, "" | |
| append_to_file "app/javascript/entrypoints/application.ts", <<~TS | |
| // Import Turbo Rails | |
| import "@hotwired/turbo-rails" | |
| // Import turbo-mount | |
| import "../turbo-mount" | |
| TS | |
| end | |
| def setup_routes_and_controller | |
| say_status_with_color "setup", "Routes and controller", :cyan | |
| route "root to: 'dashboard#index'" | |
| generate(:controller, "dashboard", "index") | |
| remove_file "app/views/dashboard/index.html.erb" | |
| template "views/dashboard/index.html.erb.erb", "app/views/dashboard/index.html.erb" | |
| end | |
| end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import plugin, { TurboMount } from "turbo-mount/react"; | |
| import { registerComponents } from "turbo-mount/registerComponents/vite"; | |
| const controllers = import.meta.glob("./controllers/**/*_controller.js", { eager: true }); | |
| const components = import.meta.glob("./components/**/*.tsx", { eager: true }); | |
| const turboMount = new TurboMount(); | |
| registerComponents({ plugin, turboMount, components, controllers }); | |
| // Debug: Show registered components | |
| console.log("Registered components:", Object.keys(components)); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| { | |
| "compilerOptions": { | |
| "target": "es2020", | |
| "lib": ["dom", "dom.iterable", "es2020"], | |
| "module": "esnext", | |
| "moduleResolution": "bundler", | |
| "allowImportingTsExtensions": true, | |
| "resolveJsonModule": true, | |
| "isolatedModules": true, | |
| "noEmit": true, | |
| "jsx": "react-jsx", | |
| "declaration": false, | |
| "sourceMap": true, | |
| "strict": true, | |
| "noUnusedLocals": true, | |
| "noUnusedParameters": true, | |
| "exactOptionalPropertyTypes": true, | |
| "noUncheckedIndexedAccess": true, | |
| "noImplicitReturns": true, | |
| "noFallthroughCasesInSwitch": true, | |
| "allowSyntheticDefaultImports": true, | |
| "esModuleInterop": true, | |
| "forceConsistentCasingInFileNames": true, | |
| "skipLibCheck": true, | |
| "baseUrl": ".", | |
| "paths": { | |
| "@/*": ["app/javascript/*"], | |
| "~/*": ["app/javascript/*"] | |
| } | |
| }, | |
| "include": [ | |
| "app/javascript/**/*", | |
| "vite.config.ts" | |
| ], | |
| "exclude": [ | |
| "node_modules", | |
| "vendor", | |
| "public", | |
| "**/*.spec.ts", | |
| "**/*.test.ts" | |
| ] | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment