turbo Documentation

The speed of a single-page web application without having to write any JavaScript

7,401 stars JavaScript JavaScript 1 file Β· ~3,115 tokens
RAW Doc

File: README.md

Turbo

Turbo uses complementary techniques to dramatically reduce the amount of custom JavaScript that most web applications will need to write:

  • Turbo Drive accelerates links and form submissions by negating the need for full page reloads.
  • Turbo Frames decompose pages into independent contexts, which scope navigation and can be lazily loaded.
  • Turbo Streams deliver page changes over WebSocket or in response to form submissions using just HTML and a set of CRUD-like actions.
  • Turbo Native lets your majestic monolith form the center of your native iOS and Android apps, with seamless transitions between web and native sections.

It's all done by sending HTML over the wire. And for those instances when that's not enough, you can reach for the other side of Hotwire, and finish the job with Stimulus.

Read more on turbo.hotwired.dev.

Contributing

Please read CONTRIBUTING.md.

Β© 2026 37signals LLC.


File: CHANGELOG.md

Changelog

Please see our GitHub "Releases" page.


File: CODE_OF_CONDUCT.md

Contributor Covenant Code of Conduct

Our Pledge

In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, gender identity and expression, level of experience,
nationality, personal appearance, race, religion, or sexual identity and
orientation.

Our Standards

Examples of behavior that contributes to creating a positive environment
include:

  • Using welcoming and inclusive language
  • Being respectful of differing viewpoints and experiences
  • Gracefully accepting constructive criticism
  • Focusing on what is best for the community
  • Showing empathy towards other community members

Examples of unacceptable behavior by participants include:

  • The use of sexualized language or imagery and unwelcome sexual attention or
    advances
  • Trolling, insulting/derogatory comments, and personal or political attacks
  • Public or private harassment
  • Publishing others' private information, such as a physical or electronic
    address, without explicit permission
  • Other conduct which could reasonably be considered inappropriate in a
    professional setting

Our Responsibilities

Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.

Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.

Scope

This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.

Enforcement

Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting one of the project maintainers listed below. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.

Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.

Project Maintainers

Attribution

This Code of Conduct is adapted from the Contributor Covenant, version 1.4,
available at http://contributor-covenant.org/version/1/4


File: CONTRIBUTING.md


Contributing

Note that we have a code of conduct. Please follow it in your interactions with this project.

Sending a Pull Request

The core team is monitoring for pull requests. We will review your pull request and either merge it, request changes to it, or close it with an explanation.

Before submitting a pull request, please:

  1. Fork the repository and create your branch.
  2. Follow the setup instructions in this file.
  3. If you’re fixing a bug or adding code that should be tested, add tests!
  4. Ensure the test suite passes.

Developing locally

First, clone the hotwired/turbo repository and install dependencies:

bash
git clone https://github.com/hotwired/turbo.git
bash
cd turbo
yarn install

Then create a branch for your changes:

bash
git checkout -b <your_branch_name>

Testing

Tests are run through yarn using Web Test Runner with Playwright for browser testing. Browser and runtime configuration can be found in web-test-runner.config.mjs and playwright.config.js.

To begin testing, install the browser drivers:

bash
yarn playwright install --with-deps

Then build the source. Because tests are run against the compiled source (and are themselves compiled) be sure to run yarn build prior to testing. Alternatively, you can run yarn watch to build and watch for changes.

bash
yarn build

Running the test suite

The test suite can be run with yarn, using the test commands defined in package.json. To run all tests in all configured browsers:

bash
yarn test

To run just the unit or browser tests:

bash
yarn test:unit
yarn test:browser

By default, tests are run in "headless" mode against all configured browsers (currently chrome and firefox). Use the --headed flag to run in normal mode. Use the --project flag to run against a particular browser.

bash
yarn test:browser --project=firefox
yarn test:browser --project=chrome
yarn test:browser --project=chrome --headed

Running a single test

To run a single test file, pass its path as an argument. To run a particular test case, append its starting line number after a colon.

bash
yarn test:browser src/tests/functional/drive_tests.js
yarn test:browser src/tests/functional/drive_tests.js:11
yarn test:browser src/tests/functional/drive_tests.js:11 --project=chrome

Running the local web server

Because tests are running headless in browsers, debugging can be difficult. Sometimes the simplest thing to do is load the test fixtures into the browser and navigate manually. To make this easier, a local web server is included.

To run the web server, ensure the source is built and start the server with yarn:

bash
yarn build
yarn start

The web server is available on port 9000, serving from the project root. Fixture files are accessible by path. For example, the file at src/tests/fixtures/rendering.html will be accessible at http://localhost:9000/src/tests/fixtures/rendering.html.


File: package.json

{
"name": "@hotwired/turbo",
"version": "8.0.23",
"description": "The speed of a single-page web application without having to write any JavaScript",
"module": "dist/turbo.es2017-esm.js",
"main": "dist/turbo.es2017-umd.js",
"files": [
"dist/.js",
"dist/
.js.map"
],
"repository": {
"type": "git",
"url": "git+https://github.com/hotwired/turbo.git"
},
"keywords": [
"hotwire",
"turbo",
"browser",
"pushstate"
],
"author": "37signals LLC",
"contributors": [
"Jeffrey Hardy [email protected]",
"Javan Makhmali [email protected]",
"Sam Stephenson [email protected]"
],
"license": "MIT",
"bugs": {
"url": "https://github.com/hotwired/turbo/issues"
},
"homepage": "https://turbo.hotwired.dev",
"publishConfig": {
"access": "public"
},
"devDependencies": {
"@open-wc/testing": "^3.1.7",
"@playwright/test": "~1.51.1",
"@rollup/plugin-node-resolve": "13.1.3",
"@web/dev-server-esbuild": "^0.3.3",
"@web/test-runner": "^0.15.0",
"@web/test-runner-playwright": "^0.9.0",
"arg": "^5.0.1",
"body-parser": "^1.20.1",
"eslint": "^8.13.0",
"express": "^4.18.2",
"idiomorph": "~0.7.4",
"multer": "^2.0.2",
"rollup": "^2.35.1"
},
"scripts": {
"clean": "rm -fr dist",
"clean:win": "rmdir /s /q dist",
"build": "yarn install && rollup -c",
"build:win": "yarn install && rollup -c",
"watch": "rollup -wc",
"start": "node src/tests/server.mjs",
"test": "yarn test:unit && yarn test:browser",
"test:browser": "playwright test",
"test:unit": "NODE_OPTIONS=--inspect web-test-runner",
"test:unit:win": "SET NODE_OPTIONS=--inspect & web-test-runner",
"release": "yarn build && yarn publish",
"lint": "eslint . --ext .js"
},
"engines": {
"node": ">= 18"
}
}


File: .prettierrc.json

{
"singleQuote": false,
"printWidth": 120,
"semi": false,
"trailingComma" : "none"
}


File: .devcontainer/devcontainer.json

// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:
// https://github.com/microsoft/vscode-dev-containers/tree/v0.191.1/containers/typescript-node
{
"name": "Node.js & Playwright",
"build": {
"dockerfile": "Dockerfile",
// Change to pick a different tag, see https://mcr.microsoft.com/en-us/product/playwright/tags
//
// IMPORTANT: The playwright image version must match @playwright/test version from package.json.
// Otherwise it will not work, the test version will look for the browser versions which it won't
// find on the image.
"args": {
"PLAYWRIGHT_TAG": "v1.51.1-jammy"
}
},
// Add the IDs of extensions you want installed when the container is created.
"customizations": {
"vscode": {
"extensions": ["dbaeumer.vscode-eslint"]
}
},
// Use 'forwardPorts' to make a list of ports inside the container available locally.
"forwardPorts": [9000],
// Use 'postCreateCommand' to run commands after the container is created.
"postCreateCommand": "yarn install && yarn build"
}


File: .github/workflows/ci.yml

name: CI

on: [push, pull_request]

jobs:
build:

text
runs-on: ubuntu-22.04

steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
  with:
    node-version: '22'
    cache: 'yarn'
- run: yarn install --frozen-lockfile
- run: yarn run playwright install --with-deps
- run: yarn build

- name: Set Chrome Version
  run: |
    CHROMEVER="$(chromedriver --version | cut -d' ' -f2)"
    echo "Actions ChromeDriver is $CHROMEVER"
    echo "CHROMEVER=${CHROMEVER}" >> $GITHUB_ENV

- name: Lint
  run: yarn lint

- name: Unit Test
  run: yarn test:unit

- name: Chrome Test
  run: yarn test:browser --project=chrome

- name: Firefox Test
  run: yarn test:browser --project=firefox

- uses: actions/upload-artifact@v4
  with:
    name: turbo-dist
    path: dist/*

File: .github/workflows/dev-builds.yml

name: dev-builds

on:
workflow_dispatch:
push:
branches:
- main
- 'builds/**'

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '22'
cache: 'yarn'

text
- run: yarn install --frozen-lockfile
  - run: yarn build

  - name: Publish dev build
    run: .github/scripts/publish-dev-build '${{ secrets.DEV_BUILD_GITHUB_TOKEN }}'