Skip to content

Instantly share code, notes, and snippets.

@adenta
Created July 4, 2025 17:41
Show Gist options
  • Save adenta/35d2443957f11fc75b2f0df81005c043 to your computer and use it in GitHub Desktop.
Save adenta/35d2443957f11fc75b2f0df81005c043 to your computer and use it in GitHub Desktop.
Scaffold React + Turbo Mount + DaisyUI in Ruby on Rails
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;
<%%= turbo_mount("Dashboard", props: { app_name: Rails.application.class.name.split("::").first }, class: "mb-5") %>
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
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));
{
"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