{"id":13880641,"url":"https://github.com/skryukov/turbo-mount","last_synced_at":"2025-12-25T14:46:42.742Z","repository":{"id":238728046,"uuid":"797395423","full_name":"skryukov/turbo-mount","owner":"skryukov","description":"Use React, Vue, Svelte, and other components with Hotwire","archived":false,"fork":false,"pushed_at":"2024-11-26T09:39:21.000Z","size":96,"stargazers_count":375,"open_issues_count":5,"forks_count":5,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-04-21T03:05:47.542Z","etag":null,"topics":["hacktoberfest","hotwire","rails","react","stimulusjs","svelte","turbo","vue"],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/skryukov.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-05-07T18:40:32.000Z","updated_at":"2025-04-16T00:17:00.000Z","dependencies_parsed_at":"2024-11-26T10:35:34.077Z","dependency_job_id":"397c1d62-df5b-4fa8-b287-50d6a174c470","html_url":"https://github.com/skryukov/turbo-mount","commit_stats":null,"previous_names":["skryukov/turbo-mount"],"tags_count":10,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skryukov%2Fturbo-mount","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skryukov%2Fturbo-mount/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skryukov%2Fturbo-mount/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skryukov%2Fturbo-mount/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/skryukov","download_url":"https://codeload.github.com/skryukov/turbo-mount/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254259384,"owners_count":22040820,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["hacktoberfest","hotwire","rails","react","stimulusjs","svelte","turbo","vue"],"created_at":"2024-08-06T08:03:20.669Z","updated_at":"2025-12-25T14:46:42.736Z","avatar_url":"https://github.com/skryukov.png","language":"Ruby","funding_links":[],"categories":["Ruby"],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cpicture\u003e\n    \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"assets/logo-dark.svg\"\u003e\n    \u003cimg src=\"assets/logo.svg\" title=\"Turbo Mount logo\" width=\"220\" height=\"45\"\u003e\n  \u003c/picture\u003e\n\u003c/p\u003e\n\n\u003ch1 align=\"center\"\u003eTurbo Mount\u003c/h1\u003e\n\n[![Gem Version](https://badge.fury.io/rb/turbo-mount.svg)](https://rubygems.org/gems/turbo-mount)\n\n`TurboMount` is a simple library that allows you to add highly interactive components from React, Vue, Svelte, and other frameworks to your Hotwire application.\n\n### Learn more\n\n- [The art of Turbo Mount: Hotwire meets modern JS frameworks](https://evilmartians.com/chronicles/the-art-of-turbo-mount-hotwire-meets-modern-js-frameworks)\n- [Excel-lent palettes: a demo application for the Turbo Mount gem](https://github.com/skryukov/excellent-palettes)\n\n## Table of Contents\n- [Installation](#installation)\n  - [Importmaps](#importmaps)\n- [Usage](#usage)\n  - [Initialization](#initialization)\n    - [Standard Initialization](#standard-initialization)\n    - [Simplified Initialization](#simplified-initialization)\n    - [Plugin-Specific Initialization](#plugin-specific-initialization)\n  - [View Helpers](#view-helpers)\n  - [Supported Frameworks](#supported-frameworks)\n  - [Custom Controllers](#custom-controllers)\n  - [Auto-Loading Components](#auto-loading-components)\n    - [Components in Nested Directories](#components-in-nested-directories)\n    - [Vite Integration](#vite-integration)\n    - [ESBuild Integration](#esbuild-integration)\n  - [Mount Target](#mount-target)\n- [License](#license)\n\n\u003ca href=\"https://evilmartians.com/?utm_source=turbo-mount\u0026utm_campaign=project_page\"\u003e\n\u003cimg src=\"https://evilmartians.com/badges/sponsored-by-evil-martians.svg\" alt=\"Built by Evil Martians\" width=\"236\" height=\"54\"\u003e\n\u003c/a\u003e\n\n## Installation\n\nTo install Turbo Mount, add the following line to your `Gemfile` and run `bundle install`:\n\n```ruby\ngem \"turbo-mount\"\n```\n\n### Automatic Installation\n\nRun the following command to install the necessary files:\n\n```bash\nbin/rails generate turbo_mount:install\n```\n\nThis will add `turbo-mount` package and framework dependencies to your `package.json` or `importmap.rb`, and create the Turbo Mount initialization file.\n\n### Manual Installation\n\nYou can also install the necessary JavaScript files manually.\n\nIf your project utilizes build tools such as [Vite](http://vite-ruby.netlify.app), also install the `turbo-mount` package:\n\n```bash\nnpm install turbo-mount\n# or with yarn\nyarn add turbo-mount\n\n# and the desired framework\nnpm install react react-dom\n# or\nnpm install vue\n# or\nnpm install svelte\n```\n\nIf you're using Vite, don't forget to add [framework-specific plugins](https://vitejs.dev/plugins) to your `vite.config.js`.\n\n### Importmaps\nTo use `TurboMount` with importmaps, you need to pin the necessary JavaScript files in your `config/importmap.rb`:\n\n```ruby\npin \"turbo-mount\", to: \"turbo-mount.min.js\"\npin \"turbo-mount/react\", to: \"turbo-mount/react.min.js\"\n```\n\nThis ensures that `turbo-mount` and its plugins are available in your application.\n\nAlso pin the desired framework:\n\n```bash\nbin/importmap pin react react-dom react-dom/client\n# or\nbin/importmap pin vue\n# or\nbin/importmap pin svelte\n```\n\nNote: Importmap-only mode is quite limited in terms of JavaScript dependencies. If you're using a more complex setup, consider using a bundler like Vite.\n\n## Usage\n\n### Initialization\n\nTo begin using `TurboMount`, start by initializing the library and registering the components you intend to use. Here's how to set it up with a React plugin:\n\n```js\n// app/javascript/turbo-mount.js\n\nimport { TurboMount } from \"turbo-mount\";\nimport { registerComponent } from \"turbo-mount/react\";\nimport { HexColorPicker } from 'react-colorful';\n\nconst turboMount = new TurboMount(); // or new TurboMount({ application })\n\nregisterComponent(turboMount, \"HexColorPicker\", HexColorPicker);\n```\n\nIf you prefer not to specify the `application` explicitly, `TurboMount` can automatically detect or initialize it. Turbo Mount uses the `window.Stimulus` if available; otherwise, it initializes a new Stimulus application.  \n\nMake sure your `application.js` is importing `turbo-mount.js`:\n```js\nimport \"@hotwired/turbo-rails\"\nimport \"./controllers\"\nimport \"./turbo-mount\"  // \u003c------\n```\n\n### View Helpers\n\nUse the following helpers to mount components in your views:\n\n```erb\n\u003c%= turbo_mount(\"HexColorPicker\", props: {color: \"#034\"}, class: \"mb-5\") %\u003e\n```\n\nThis will generate the following HTML:\n\n```html\n\u003cdiv data-controller=\"turbo-mount-hex-color-picker\"\n     data-turbo-mount-hex-color-picker-component-value=\"HexColorPicker\"\n     data-turbo-mount-hex-color-picker-props-value=\"{\u0026quot;color\u0026quot;:\u0026quot;#034\u0026quot;}\"\n     class=\"mb-5\"\u003e\n\u003c/div\u003e\n```\n\n### Supported Frameworks\n\n`TurboMount` supports the following frameworks:\n\n- React: `\"turbo-mount/react\"`\n- Vue: `\"turbo-mount/vue\"`\n- Svelte 4: `\"turbo-mount/svelte4\"`\n- Svelte 5: `\"turbo-mount/svelte\"`\n\nTo add support for other frameworks, create a custom plugin. See included plugins for examples.\n\n### Custom Controllers\n\nTo customize component behavior or pass functions as props, create a custom controller:\n\n```js\nimport { TurboMountController } from \"turbo-mount\";\n\nexport default class extends TurboMountController {\n  get componentProps() {\n    return {\n      ...this.propsValue,\n      onChange: this.onChange.bind(this),\n    };\n  }\n\n  onChange = (color) =\u003e {\n    // same as this.propsValue = { ...this.propsValue, color };\n    // but skips the rerendering of the component:\n    this.setComponentProps({ ...this.propsValue, color });\n  };\n}\n```\n\nThen pass this controller to the `registerComponent` method:\n\n```js\nimport HexColorPickerController from \"controllers/turbo_mount/hex_color_picker_controller\";\n\nregisterComponent(turboMount, \"HexColorPicker\", HexColorPicker, HexColorPickerController);\n```\n\n### Auto-Loading Components\n\n`TurboMount` includes a `registerComponents` functions that automates the loading of components. `registerComponents` also accepts an optional `controllers` property to autoload customized controllers.\n\nThe `registerComponents` helpers search for controllers in the following paths:\n- `controllers/turbo-mount/${controllerName}`\n- `controllers/turbo-mount-${controllerName}`\n\n#### Components in Nested Directories\n\nTurbo Mount supports components located in nested directories. For example, if you have a component structure like:\n\n```\ncomponents/\n├── Dashboard/\n│ └── WeatherWidget.tsx\n└── ...\n```\n\nYou can use the following helper to mount the component:\n\n```erb\n\u003c%= turbo_mount(\"Dashboard/WeatherWidget\") %\u003e\n```\n\nFor nested components, controllers are searched in these paths:\n\n- `controllers/turbo_mount/dashboard/weather_widget_controller.js`\n- `controllers/turbo_mount_dashboard__weather_widget_controller.js`\n\n#### Vite Integration\n\nVite helper requires the `stimulus-vite-helpers` package to load components and controllers. Here's how to set it up:\n\n```bash\nnpm install stimulus-vite-helpers\n```\n\nThen use the `registerComponents` helper to autoload components and controllers:\n\n```js\nimport plugin, { TurboMount } from \"turbo-mount/react\";\nimport { registerComponents } from \"turbo-mount/registerComponents/vite\";\n\nconst controllers = import.meta.glob(\"./**/*_controller.js\", { eager: true });\nconst components = import.meta.glob(\"/components/**/*.jsx\", { eager: true });\n\nconst turboMount = new TurboMount();\nregisterComponents({ plugin, turboMount, components, controllers });\n```\n\n#### ESBuild Integration\n\nESBuild helper requires the `esbuild-rails` package to load components and controllers. Read the [ESBuild Rails README](https://github.com/excid3/esbuild-rails) for more information on how to set it up.\n\n```js\nimport plugin, { TurboMount } from \"turbo-mount/react\";\nimport { registerComponents } from \"turbo-mount/registerComponents/esbuild\";\n\nconst turboMount = new TurboMount();\n\nimport controllers from \"./controllers/**/*_controller.js\";\nimport components from \"./components/**/*.jsx\";\n\nregisterComponents({ plugin, turboMount, components, controllers });\n```\n\n### Mount Target\n\nTo specify a non-root mount target, use the `data-\u003c%= controller_name %\u003e-target=\"mount\"` attribute:\n\n```erb\n\u003c%= turbo_mount(\"HexColorPicker\", props: {color: \"#430\"}) do |controller_name| %\u003e\n  \u003ch3\u003eColor picker\u003c/h3\u003e\n  \u003cdiv data-\u003c%= controller_name %\u003e-target=\"mount\"\u003e\u003c/div\u003e\n\u003c% end %\u003e\n```\n\n## License\n\nThe gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fskryukov%2Fturbo-mount","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fskryukov%2Fturbo-mount","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fskryukov%2Fturbo-mount/lists"}