{"id":13514428,"url":"https://github.com/hopsoft/turbo_boost-streams","last_synced_at":"2026-04-02T11:37:53.491Z","repository":{"id":57913401,"uuid":"529029423","full_name":"hopsoft/turbo_boost-streams","owner":"hopsoft","description":"Take full control of the DOM with Turbo Streams","archived":false,"fork":false,"pushed_at":"2024-03-01T05:28:09.000Z","size":2859,"stargazers_count":272,"open_issues_count":1,"forks_count":13,"subscribers_count":7,"default_branch":"main","last_synced_at":"2026-01-21T20:14:47.268Z","etag":null,"topics":["hotwire","rails","reactive","ruby","ruby-on-rails","turbo","turbo-streams"],"latest_commit_sha":null,"homepage":"https://hopsoft.io/@turbo-boost/streams","language":"HTML","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/hopsoft.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"MIT-LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","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},"funding":{"github":"hopsoft"}},"created_at":"2022-08-25T21:53:55.000Z","updated_at":"2025-12-28T06:16:29.000Z","dependencies_parsed_at":"2024-02-15T13:52:40.492Z","dependency_job_id":"c6d9f395-0f05-499f-8777-a9194a6f8187","html_url":"https://github.com/hopsoft/turbo_boost-streams","commit_stats":{"total_commits":178,"total_committers":7,"mean_commits":"25.428571428571427","dds":0.0337078651685393,"last_synced_commit":"7559483b61c629f1e1f64972a4106ec656ddec9b"},"previous_names":["hopsoft/turbo_ready"],"tags_count":21,"template":false,"template_full_name":null,"purl":"pkg:github/hopsoft/turbo_boost-streams","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hopsoft%2Fturbo_boost-streams","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hopsoft%2Fturbo_boost-streams/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hopsoft%2Fturbo_boost-streams/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hopsoft%2Fturbo_boost-streams/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hopsoft","download_url":"https://codeload.github.com/hopsoft/turbo_boost-streams/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hopsoft%2Fturbo_boost-streams/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31305704,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-02T09:48:21.550Z","status":"ssl_error","status_checked_at":"2026-04-02T09:48:19.196Z","response_time":89,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["hotwire","rails","reactive","ruby","ruby-on-rails","turbo","turbo-streams"],"created_at":"2024-08-01T05:00:56.102Z","updated_at":"2026-04-02T11:37:53.470Z","avatar_url":"https://github.com/hopsoft.png","language":"HTML","funding_links":["https://github.com/sponsors/hopsoft"],"categories":["HTML","**Awesome Hotwire** [![Awesome](https://cdn.rawgit.com/sindresorhus/awesome/d7305f38d29fed78fa85652e3a63e154dd8e8829/media/badge.svg)](https://github.com/sindresorhus/awesome)"],"sub_categories":["Turbo"],"readme":"\u003cp align=\"center\"\u003e\n  \u003cpicture\u003e\n    \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"https://ik.imagekit.io/hopsoft/turbo-boost-logo-dark-bg_o_f0bVskz.webp?ik-sdk-version=javascript-1.4.3\u0026updatedAt=1671722004391\"\u003e\n    \u003cimg height=\"60\" src=\"https://ik.imagekit.io/hopsoft/turbo-boost-logo_zHiiimlvT.webp?ik-sdk-version=javascript-1.4.3\u0026updatedAt=1671722004342\" /\u003e\n  \u003c/picture\u003e\n  \u003ch1 align=\"center\"\u003e\n    Welcome to TurboBoost Streams 👋\n  \u003c/h1\u003e\n  \u003cp align=\"center\"\u003e\n    \u003ca href=\"http://blog.codinghorror.com/the-best-code-is-no-code-at-all/\"\u003e\n      \u003cimg alt=\"Lines of Code\" src=\"https://img.shields.io/badge/loc-295-47d299.svg\" /\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://codeclimate.com/github/hopsoft/turbo_boost-streams/maintainability\"\u003e\n      \u003cimg src=\"https://api.codeclimate.com/v1/badges/a6671f4294ec0f21f732/maintainability\" /\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://rubygems.org/gems/turbo_boost-streams\"\u003e\n      \u003cimg alt=\"GEM Version\" src=\"https://img.shields.io/gem/v/turbo_boost-streams?color=168AFE\u0026include_prereleases\u0026logo=ruby\u0026logoColor=FE1616\"\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://rubygems.org/gems/turbo_boost-streams\"\u003e\n      \u003cimg alt=\"GEM Downloads\" src=\"https://img.shields.io/gem/dt/turbo_boost-streams?color=168AFE\u0026logo=ruby\u0026logoColor=FE1616\"\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://github.com/testdouble/standard\"\u003e\n      \u003cimg alt=\"Ruby Style\" src=\"https://img.shields.io/badge/style-standard-168AFE?logo=ruby\u0026logoColor=FE1616\" /\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://www.npmjs.com/package/@turbo-boost/streams\"\u003e\n      \u003cimg alt=\"NPM Version\" src=\"https://img.shields.io/npm/v/@turbo-boost/streams?color=168AFE\u0026logo=npm\"\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://www.npmjs.com/package/@turbo-boost/streams\"\u003e\n      \u003cimg alt=\"NPM Downloads\" src=\"https://img.shields.io/npm/dm/@turbo-boost/streams?color=168AFE\u0026logo=npm\"\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://bundlephobia.com/package/@turbo-boost/streams@\"\u003e\n      \u003cimg alt=\"NPM Bundle Size\" src=\"https://img.shields.io/bundlephobia/minzip/@turbo-boost/streams?label=bundle%20size\u0026logo=npm\u0026color=47d299\"\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://github.com/sheerun/prettier-standard\"\u003e\n      \u003cimg alt=\"JavaScript Style\" src=\"https://img.shields.io/badge/style-prettier--standard-168AFE?logo=javascript\u0026logoColor=f4e137\" /\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://github.com/hopsoft/turbo_boost-streams/actions/workflows/tests.yml\"\u003e\n      \u003cimg alt=\"Tests\" src=\"https://github.com/hopsoft/turbo_boost-streams/actions/workflows/tests.yml/badge.svg\" /\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://github.com/hopsoft/turbo_boost-streams/discussions\" target=\"_blank\"\u003e\n      \u003cimg alt=\"GitHub Discussions\" src=\"https://img.shields.io/github/discussions/hopsoft/turbo_boost-streams?color=168AFE\u0026logo=github\"\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://discord.gg/stimulus-reflex\"\u003e\n      \u003cimg alt=\"Discord Community\" src=\"https://img.shields.io/discord/629472241427415060?color=8892F6\u0026label=discord\u0026logo=discord\u0026logoColor=8892F6\"\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://github.com/sponsors/hopsoft\"\u003e\n      \u003cimg alt=\"Sponsors\" src=\"https://img.shields.io/github/sponsors/hopsoft?color=eb4aaa\u0026logo=GitHub%20Sponsors\" /\u003e\n    \u003c/a\u003e\n    \u003cbr\u003e\n    \u003ca href=\"https://ruby.social/@hopsoft\"\u003e\n      \u003cimg alt=\"Ruby.Social Follow\" src=\"https://img.shields.io/mastodon/follow/000008274?domain=https%3A%2F%2Fruby.social\u0026label=%40hopsoft\u0026style=social\"\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://twitter.com/hopsoft\"\u003e\n      \u003cimg alt=\"Twitter Follow\" src=\"https://img.shields.io/twitter/url?label=%40hopsoft\u0026style=social\u0026url=https%3A%2F%2Ftwitter.com%2Fhopsoft\"\u003e\n    \u003c/a\u003e\n  \u003c/p\u003e\n\u003c/p\u003e\n\n**TurboBoost Streams extends [Turbo Streams](https://turbo.hotwired.dev/reference/streams) to give you full control of the\nbrowser's [Document Object Model (DOM).](https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model)**\n\n```ruby\nturbo_stream.invoke \"console.log\", args: [\"Hello World!\"]\n```\n\n**That's right!**\nYou can `invoke` any DOM method on the client with Turbo Streams.\n\n\u003c!-- Tocer[start]: Auto-generated, don't remove. --\u003e\n\n## Table of Contents\n\n  - [Why boosted Streams?](#why-boosted-streams)\n  - [Sponsors](#sponsors)\n  - [Community](#community)\n  - [Dependencies](#dependencies)\n  - [Installation](#installation)\n  - [Setup](#setup)\n  - [Usage](#usage)\n    - [Method Chaining](#method-chaining)\n    - [Event Dispatch](#event-dispatch)\n    - [Morph](#morph)\n    - [Morph Method](#morph-method)\n    - [Syntax Styles](#syntax-styles)\n    - [Extending Behavior](#extending-behavior)\n    - [Implementation Details](#implementation-details)\n    - [Broadcasting](#broadcasting)\n      - [Background Job Queues](#background-job-queues)\n  - [FAQ](#faq)\n  - [A Word of Warning](#a-word-of-warning)\n  - [Developing](#developing)\n      - [Notable Files](#notable-files)\n  - [Deploying](#deploying)\n      - [Notable Files](#notable-files-1)\n      - [How to Deploy](#how-to-deploy)\n  - [Releasing](#releasing)\n  - [About TurboBoost](#about-turboboost)\n  - [License](#license)\n\n\u003c!-- Tocer[finish]: Auto-generated, don't remove. --\u003e\n\n## Why boosted Streams?\n\nTurbo Streams [intentionally restrict](https://turbo.hotwired.dev/handbook/streams#but-what-about-running-javascript%3F)\nofficial actions to CRUD-related activity.\nThese [official actions](https://turbo.hotwired.dev/reference/streams#the-seven-actions) work well for a considerable number of use cases.\n*We recommend that you push Turbo Streams as far as possible before reaching for __boosted streams__.*\n\nIf you find that CRUD isn't enough, boosted streams are there to handle pretty much everything else.\n\n## Sponsors\n\n\u003cp align=\"center\"\u003e\n  \u003cem\u003eProudly sponsored by\u003c/em\u003e\n\u003c/p\u003e\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://www.clickfunnels.com?utm_source=hopsoft\u0026utm_medium=open-source\u0026utm_campaign=turbo_boost-streams\"\u003e\n    \u003cimg src=\"https://images.clickfunnel.com/uploads/digital_asset/file/176632/clickfunnels-dark-logo.svg\" width=\"575\" /\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\n## Community\n\nCome join the party with over 2200+ like-minded friendly Rails/Hotwire enthusiasts on our [Discord server](https://discord.gg/stimulus-reflex).\n\n## Dependencies\n\n- [rails](https://rubygems.org/gems/rails) `\u003e= 6.1`\n- [turbo-rails](https://rubygems.org/gems/turbo-rails) `\u003e= 1.1`\n- [@hotwired/turbo-rails](https://www.npmjs.com/package/@hotwired/turbo-rails) `\u003e= 7.2`\n\n## Installation\n\nBe sure to install the same version for each library.\n\n```sh\nbundle add \"turbo_boost-streams --version VERSION\"\nnpm install \"@turbo-boost/streams@VERSION\"\n```\n\n## Setup\n\nImport and initialize Turbo Boost Streams in your application.\n\n```diff\n# Gemfile\ngem \"turbo-rails\", \"\u003e= 1.1\", \"\u003c 2\"\n+gem \"turbo_boost-streams\", \"~\u003e VERSION\"\n```\n\n```diff\n# package.json\n\"dependencies\": {\n  \"@hotwired/turbo-rails\": \"\u003e=7.2\",\n+  \"@turbo-boost/streams\": \"^VERSION\"\n```\n\n```diff\n# app/javascript/application.js\nimport '@hotwired/turbo-rails'\n+import '@turbo-boost/streams'\n```\n\n## Usage\n\nManipulate the DOM from anywhere you use official [Turbo Streams](https://turbo.hotwired.dev/handbook/streams#integration-with-server-side-frameworks).\nThe possibilities are endless.\n[Learn more about the DOM at MDN.](https://developer.mozilla.org/en-US/docs/Web/API.)\n\n```ruby\nturbo_stream.invoke \"console.log\", args: [\"Hello World!\"]\n```\n\n### Method Chaining\n\nYou can use [dot notation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Property_accessors#dot_notation)\nor [selectors](https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelectorAll) and even combine them!\n\n```ruby\nturbo_stream\n  .invoke(\"document.body.insertAdjacentHTML\", args: [\"afterbegin\", \"\u003ch1\u003eHello World!\u003c/h1\u003e\"]) # dot notation\n  .invoke(\"setAttribute\", args: [\"data-turbo-ready\", true], selector: \".button\") # selector\n  .invoke(\"classList.add\", args: [\"turbo-ready\"], selector: \"a\") # dot notation + selector\n```\n\n### Event Dispatch\n\nIt's possible to fire events on `window`, `document`, and element(s).\n\n```ruby\nturbo_stream\n  .invoke(:dispatch_event, args: [\"turbo-ready:demo\"]) # fires on window\n  .invoke(\"document.dispatchEvent\", args: [\"turbo-ready:demo\"]) # fires on document\n  .invoke(:dispatch_event, args: [\"turbo-ready:demo\"], selector: \"#my-element\") # fires on matching element(s)\n  .invoke(:dispatch_event, args: [\"turbo-ready:demo\", {bubbles: true, detail: {...}}]) # set event options\n```\n\n### Morph\n\nYou can morph elements with the `morph` method.\n\n```ruby\nturbo_stream.invoke(:morph, args: [render(\"path/to/partial\")], selector: \"#my-element\")\n```\n\n\u003e [!NOTE]\n\u003e TurboBoost Streams uses [Idiomorph](https://github.com/bigskysoftware/idiomorph) for morphing.\n\nThe following options are used to morph elements.\n\n```js\n{\n  morphStyle: 'outerHTML',\n  ignoreActiveValue: true,\n  head: { style: 'merge' },\n  callbacks: { beforeNodeMorphed: (oldNode, _) =\u003e ... }\n}\n```\n\n\u003e [!TIP]\n\u003e The callbacks honor the `data-turbo-permanent` attribute and is aware of the [Trix](https://trix-editor.org/) editor.\n\n### Morph Method\n\nThe morph method is also exported to the `TurboBoost.Streams` global and is available for client side morphing.\n\n```js\nTurboBoost.Streams.morph.method // → function(targetNode, htmlString, options = {})\n```\n\nYou can also override the `morph` method if desired.\n\n```js\nTurboBoost.Streams.morph.method = (targetNode, htmlString, options = {}) =\u003e {\n  // your custom implementation\n}\n```\n\nIt also support adding a delay before morphing is performed.\n\n```js\nTurboBoost.Streams.morph.delay = 50 // → 50ms\n```\n\n\u003e [!TIP]\n\u003e Complex test suites may require a delay to ensure the DOM is ready before morphing.\n\n### Syntax Styles\n\nYou can use [`snake_case`](https://en.wikipedia.org/wiki/Snake_case) when invoking DOM functionality.\nIt will implicitly convert to [`camelCase`](https://en.wikipedia.org/wiki/Camel_case).\n\n```ruby\nturbo_stream.invoke :event,\n  args: [\"turbo-ready:demo\", {detail: {converts_to_camel_case: true}}]\n```\n\nNeed to opt-out? No problem... just disable it.\n\n```ruby\nturbo_stream.invoke :contrived_demo, camelize: false\n```\n\n### Extending Behavior\n\nIf you add new capabilities to the browser, you can control them from the server.\n\n```js\n// JavaScript on the client\nimport morphdom from 'morphdom'\n\nwindow.MyNamespace = { coolStuff: (arg) =\u003e { ... } }\n```\n\n```ruby\n# Ruby on the server\nturbo_stream.invoke \"MyNamespace.coolStuff\", args: [\"Hello World!\"]\n```\n\n### Implementation Details\n\nThere's basically one method to learn... `invoke`\n\n```ruby\n# Ruby\nturbo_stream\n  .invoke(method, args: [], selector: nil, camelize: true, id: nil)\n#         |       |         |              |               |\n#         |       |         |              |               |- Identifies this invocation (optional)\n#         |       |         |              |\n#         |       |         |              |- Should we camelize the JavaScript stuff? (optional)\n#         |       |         |                 (allows us to write snake_case in Ruby)\n#         |       |         |\n#         |       |         |- A CSS selector for the element(s) to target (optional)\n#         |       |\n#         |       |- The arguments to pass to the JavaScript method (optional)\n#         |\n#         |- The JavaScript method to invoke (can use dot notation)\n```\n\n\u003e 📘 **NOTE:** The method will be invoked on all matching elements if a `selector` is present.\n\nThe following Ruby code,\n\n```ruby\nturbo_stream.invoke \"console.log\", args: [\"Hello World!\"], id: \"123ABC\"\n```\n\nemits this HTML markup.\n\n```html\n\u003cturbo-stream action=\"invoke\" target=\"DOM\"\u003e\n  \u003ctemplate\u003e{\"id\":\"123ABC\",\"receiver\":\"console\",\"method\":\"log\",\"args\":[\"Hello World!\"]}\u003c/template\u003e\n\u003c/turbo-stream\u003e\n```\n\nWhen this element enters the DOM,\nTurbo Streams automatically executes `invoke` on the client with the template's JSON payload and then removes the element from the DOM.\n\n### Broadcasting\n\nYou can also broadcast DOM invocations to subscribed users.\n\n1. First, setup the stream subscription.\n\n    ```erb\n    \u003c!-- app/views/posts/show.html.erb --\u003e\n    \u003c%= turbo_stream_from @post %\u003e\n    \u003c!--                  |\n                          |- *streamables - model(s), string(s), etc...\n    --\u003e\n    ```\n\n2. Then, broadcast to the subscription.\n\n    ```ruby\n    # app/models/post.rb\n    class Post \u003c ApplicationRecord\n      after_save do\n        # emit a message in the browser console for anyone subscribed to this post\n        broadcast_invoke \"console.log\", args: [\"Post was saved! #{to_gid}\"]\n\n        # broadcast with a background job\n        broadcast_invoke_later \"console.log\", args: [\"Post was saved! #{to_gid}\"]\n      end\n    end\n    ```\n\n    ```ruby\n    # app/controllers/posts_controller.rb\n    class PostsController \u003c ApplicationController\n      def create\n        @post = Post.find params[:id]\n\n        if @post.update post_params\n          # emit a message in the browser console for anyone subscribed to this post\n          @post.broadcast_invoke \"console.log\", args: [\"Post was saved! #{@post.to_gid}\"]\n\n          # broadcast with a background job\n          @post.broadcast_invoke_later \"console.log\", args: [\"Post was saved! #{@postto_gid}\"]\n\n          # you can also broadcast directly from the channel\n          Turbo::StreamsChannel.broadcast_invoke_to @post, \"console.log\",\n            args: [\"Post was saved! #{@post.to_gid}\"]\n\n          # broadcast with a background job\n          Turbo::StreamsChannel.broadcast_invoke_later_to @post, \"console.log\",\n            args: [\"Post was saved! #{@post.to_gid}\"]\n        end\n      end\n    end\n    ```\n\n\u003e 📘 **NOTE:** [Method Chaining](#method-chaining) is not currently supported when broadcasting.\n\n#### Background Job Queues\n\nYou may want to change the queue name for Turbo Stream background jobs in order to isolate, prioritize, and scale the workers independently.\n\n```ruby\n# config/initializers/turbo_streams.rb\nTurbo::Streams::BroadcastJob.queue_name = :turbo_streams\nTurboBoost::Streams::BroadcastInvokeJob.queue_name = :turbo_streams\n```\n\n## FAQ\n\n- Isn't this just RJS?\n\n  \u003e No. But, perhaps it could be considered RJS's \"modern\" spiritual successor. 🤷‍♂️\n  \u003e Though it embraces JavaScript instead of trying to avoid it.\n\n- Does it use `eval`?\n\n  \u003e **No.** The `invoke` stream can only execute existing functions on the client.\n  \u003e It's not a carte blanche invitation to emit free-form JavaScript to be evaluated on the client.\n\n## A Word of Warning\n\nTurboBoost Streams is a foundational tool designed to help you build modern, maintainable, and scalable reactive web apps with Hotwire.\nIt allows you to break free from the strict CRUD/REST conventions that Rails and Hotwire wisely encourage.\nYou should consider boosted streams a substrate for building additional libraries and abstractions.\n\n*Please don't use TurboBoost Streams to manually orchestrate micro DOM updates (from the server).\nSuch techniques are what gave rise to Full Stack Frontend and sent the industry on a decade-long journey of complexity and frustration.*\n\n## Developing\n\nThis project supports a fully Dockerized development experience.\n\n1. Simply run the following commands to get started.\n\n    ```sh\n    git clone -o github https://github.com/hopsoft/turbo_boost-streams.git\n    cd turbo_boost-streams\n    ```\n\n    ```sh\n    docker compose up -d # start the environment (will take a few minutes on 1st run)\n    docker exec -it turbo_boost-streams-web rake # run the test suite\n    open http://localhost:3000 # open the `test/dummy` app in a browser\n    ```\n\n    And, if you're using the [containers gem (WIP)](https://github.com/hopsoft/containers).\n\n    ```sh\n    containers up # start the environment (will take a few minutes on 1st run)\n    containers rake # run the test suite\n    open http://localhost:3000 # open the `test/dummy` app in a browser\n    ```\n\n1. Edit files using your preferred tools on the host machine.\n\n1. That's it!\n\n####  Notable Files\n\n- [Dockerfile](https://github.com/hopsoft/turbo_boost-streams/blob/main/Dockerfile)\n- [docker-compose.yml](https://github.com/hopsoft/turbo_boost-streams/blob/main/docker-compose.yml)\n- [bin/docker/run/local](https://github.com/hopsoft/turbo_boost-streams/blob/main/bin/docker/run/local)\n\n## Deploying\n\nThis project supports Dockerized deployment via the same configuration used for development,\nand... it actually runs the [`test/dummy`](https://github.com/hopsoft/turbo_boost-streams/tree/main/test/dummy) application in \"production\". 🤯\n\nThe `test/dummy` app serves the following purposes.\n\n- Test app for the Rails engine\n- Documentation and marketing site with interactive demos\n\nYou can [__see it in action__ here.](https://hopsoft.io/@turbo-boost/streams)\n_How's that for innovative simplicity?_\n\n####  Notable Files\n\n- [Dockerfile](https://github.com/hopsoft/turbo_boost-streams/blob/main/Dockerfile)\n- [fly.toml](https://github.com/hopsoft/turbo_boost-streams/blob/main/fly.toml)\n- [bin/docker/run/remote](https://github.com/hopsoft/turbo_boost-streams/blob/main/bin/docker/run/remote)\n\n#### How to Deploy\n\n```sh\nfly deploy\n```\n\n## Releasing\n\n\u003e [!TIP]\n\u003e Run these commands on the host machine _(i.e. not inside the dev container)_\n\n1. Run `npm update` and `bundle update` to pick up the latest dependencies\n1. Update the version number consistently in the following files:\n   * `lib/turbo_boost/streams/version.rb` - pre-release versions should use `.preN`\n   * `app/javascript/version.js` - pre-release versions use `-preN`\n   * `package.json` - pre-release versions use `-preN`\n1. Run `bin/standardize`\n1. Run `rake build`\n1. Run `npm run build`\n1. Commit and push any changes to GitHub\n1. Run `rake release`\n1. Run `npm publish --access public`\n1. Create a new release on GitHub ([here](https://github.com/hopsoft/turbo_boost-streams/releases)) and generate the changelog for the stable release for it\n\n## About TurboBoost\n\nTurboBoost is a suite of libraries that enhance Rails, Hotwire, and Turbo... making them even more powerful and boosting your productivity.\nBe sure to check out all of the various libraries.\n\n- [Streams](https://github.com/hopsoft/turbo_boost-streams)\n- [Commands](https://github.com/hopsoft/turbo_boost-commands)\n- [Elements](https://github.com/hopsoft/turbo_boost-elements)\n- [Devtools](https://github.com/hopsoft/turbo_boost-devtools)\n- Coming soon...\n\n## License\n\nThese libraries are 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%2Fhopsoft%2Fturbo_boost-streams","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhopsoft%2Fturbo_boost-streams","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhopsoft%2Fturbo_boost-streams/lists"}