Ruby framework for conversational voice and text chatbots.
-
-Stealth is inspired by the Model-View-Controller (MVC) pattern. However, instead of calling them _Views,_ Stealth refers to them as _Replies_ to better match the chatbot domain.
-
-* The [Model](models/overview.md) layer represents your data model (such as Account, User, Quote, etc.) and encapsulates the business logic that is specific to your bot. By default, Stealth uses [ActiveRecord](models/activerecord.md), but you can use any library that you prefer.
-* The [Controller](controllers/controller-overview.md) layer is responsible for handling incoming requests from messaging platforms and providing and transmitting the response (reply).
-* The [Reply](replies/reply-overview.md) layer is composed of “templates” that are responsible for constructing the respective reply.
-
-In addition to being inspired by Model-View-Controller (MVC) pattern, Stealth has a few other awesome things built in for you.
-
-* **Plug and play components.** Every service integration in Stealth is a Ruby gem. One bot can support multiple [messaging platforms](platforms/overview.md) (i.e. Facebook Messenger, SMS, Alexa, and more) and multiple NLP/NLU services.
-* **Innovative.** Stealth is constantly improving and evolving. There are many innovations in Stealth such as: [interrupt detection](controllers/interrupt-detection.md), [homophone detection](controllers/handle\_message/homophone-detection.md), [hot-code reloading](dev-environment/hot-code-reloading.md), [multi-level catch-all handling](controllers/catch-alls.md), and more that make your bots perform better.
-* **Advanced tooling.** From web servers to continuous integration testing, Stealth is built to take advantage of all the great work done by the web development community.
-* **Hosting you trust.** Stealth bots are Rack applications. That means your bots can be [deployed](deployment/overview.md) using familiar services like Docker and Heroku.
-* **Ready for production.** Stealth already powers bots for large, well-known brands. You can rest assured your bot will be in good hands with Stealth.
-* **Open source.** Stealth is MIT licensed to ensure you own your bot's source code. More importantly, we welcome contributors to help make Stealth even better for everyone.
-
-## Prerequisites
-
-While it's helpful to have some familiarity with Ruby, we think you can get started with Stealth without yet knowing Ruby or even programming. Building text-based bots or Alexa Skills is a great starting point into the world of programming and we think Ruby is an excellent first programming language.
-
-We welcome contributors and questions from programmers of all experience levels.
diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md
deleted file mode 100644
index 88b42de1..00000000
--- a/docs/SUMMARY.md
+++ /dev/null
@@ -1,99 +0,0 @@
-# Table of contents
-
-* [Intro](README.md)
-* [Getting Started](getting-started.md)
-* [Basics](basics.md)
-* [Dev Environment](dev-environment/README.md)
- * [Booting Up](dev-environment/booting-up.md)
- * [Hot-Code Reloading](dev-environment/hot-code-reloading.md)
- * [Procfile](dev-environment/procfile.md)
- * [Tunnels](dev-environment/tunnels.md)
- * [Environment Variables](dev-environment/environment-variables.md)
- * [Logs](dev-environment/logs.md)
-* [Glossary](glossary.md)
-
-## Flows
-
-* [Flows & States](flows/overview.md)
-* [State Naming](flows/state-naming.md)
-* [FlowMap](flows/flowmap.md)
-* [State Options](flows/state-options.md)
-
-## Controllers
-
-* [Controller Overview](controllers/controller-overview.md)
-* [Sessions](controllers/sessions/README.md)
- * [Session Overview](controllers/sessions/intro.md)
- * [step\_to](controllers/sessions/step\_to.md)
- * [step\_to\_in](controllers/sessions/step\_to\_in.md)
- * [step\_to\_at](controllers/sessions/step\_to\_at.md)
- * [update\_session\_to](controllers/sessions/update\_session\_to.md)
- * [step\_back](controllers/sessions/step\_back.md)
- * [do\_nothing](controllers/sessions/do\_nothing.md)
-* [route](controllers/route.md)
-* [Available Data](controllers/available-data.md)
-* [handle\_message](controllers/handle\_message/README.md)
- * [String Matcher](controllers/handle\_message/string-mather.md)
- * [Alpha Ordinal Matcher](controllers/handle\_message/alpha-ordinal-matcher.md)
- * [Homophone Detection](controllers/handle\_message/homophone-detection.md)
- * [NLP Matcher](controllers/handle\_message/nlp-matcher.md)
- * [Regex Matcher](controllers/handle\_message/regex-matcher.md)
- * [Nil Matcher](controllers/handle\_message/nil-matcher.md)
-* [get\_match](controllers/get\_match/README.md)
- * [Exact Match](controllers/get\_match/exact-match.md)
- * [Alpha Ordinals](controllers/get\_match/alpha-ordinals.md)
- * [Entity Match](controllers/get\_match/entity-match.md)
-* [Catch-Alls](controllers/catch-alls.md)
-* [Dev Jumps](controllers/dev-jumps.md)
-* [Interrupt Detection](controllers/interrupt-detection.md)
-* [Unrecognized Messages](controllers/unrecognized-messages.md)
-* [Platform Errors](controllers/platform-errors.md)
-
-## Replies
-
-* [Reply Overview](replies/reply-overview.md)
-* [YAML Replies](replies/yaml-replies.md)
-* [ERB](replies/erb.md)
-* [Delays](replies/delays.md)
-* [Variants](replies/variants.md)
-* [Inline Replies](replies/inline-replies.md)
-
-## Models
-
-* [Model Overview](models/overview.md)
-* [ActiveRecord](models/activerecord.md)
-* [Mongoid](models/mongoid.md)
-
-## Platforms
-
-* [Platform Overview](platforms/overview.md)
-* [Facebook Messenger](platforms/facebook-messenger.md)
-* [SMS/Whatsapp](platforms/sms-whatsapp.md)
-* [Alexa Skills](platforms/alexa-skills.md)
-* [Voice](platforms/voice.md)
-
-## NLP/NLU
-
-* [NLP Overview](nlp-nlu/overview.md)
-* [Microsoft LUIS](nlp-nlu/microsoft-luis.md)
-* [OpenAI](nlp-nlu/openai.md)
-
-## Config
-
-* [Settings](config/settings.md)
-* [services.yml](config/services.yml.md)
-
-## Testing
-
-* [Specs](testing/untitled.md)
-* [Integration Testing](testing/integration-testing.md)
-
-## Deployment
-
-* [Deployment Overview](deployment/overview.md)
-* [Heroku](deployment/heroku.md)
-
-## Building Components
-
-* [Message Services](building-components/message-services.md)
-* [NLP](building-components/nlp.md)
diff --git a/docs/basics.md b/docs/basics.md
deleted file mode 100644
index a595099f..00000000
--- a/docs/basics.md
+++ /dev/null
@@ -1,77 +0,0 @@
----
-description: A quick primer of the various pieces that comprise Stealth.
----
-
-# Basics
-
-## Anatomy of a Stealth Bot
-
-A Stealth bot has two primary processes: a _web server_, and a _background job processer_. If the messaging platform being used supports it, Stealth will push a message to a queue where a reply will be constructured by a background job. This allows you to easily scale your Stealth bot across many threads and processes.
-
-### Data Store
-
-Stealth requires Redis. Redis is used for [session storage](controllers/sessions/intro.md) as well as the queue for background jobs. You can access the Redis store yourself via the global variable: `$redis`. You can use it as your primary data store if you are building a simple bot, but you'll likely want to use a SQL or NoSQL database for more complex bots.
-
-### Environments
-
-Stealth bots can be booted into three environment types: `development`, `testing`, `production`. By default, if an environment is not specified via the `STEALTH_ENV` environment variable, the `development` environment will be used. The `testing` environment is automatically used when running your specs.
-
-### ActiveSupport
-
-Stealth automatically includes [active\_support](https://guides.rubyonrails.org/active\_support\_core\_extensions.html). So if you're used to using certain core extensions in Ruby on Rails, you can continue to use them in your Stealth bots!
-
-## Lifecycle of a Message
-
-This is just a brief outline of the lifecycle of a message to help you understand how Stealth processes messages. For more detailed information that you can use to build your own message platform components, check out [those docs](building-components/message-services.md).
-
-1. A message is received by the web server.
-2. If the message platform supports it, the message is backgrounded to be processed by a background job. If the message platform does not support it ([Alexa Skill](platforms/alexa-skills.md) or [Voice](platforms/voice.md)), the message is processed inline by the web server process.
-3. Stealth uses the respective message platform component to normalize the message into a standard format.
-4. Stealth calls the [route](controllers/route.md) method in `BotController`. If a session exists for the user, they are routed to their current state. If a session does not exist, by default the `route` method will route the user to the `HellosController#say_hello` method.
-5. The controller action will either do nothing, step to another state, update the session, or generate a reply. In the latter case, the reply will be delivered via the message platform component.
-
-## Directory Structure
-
-When you use the generator `stealth new` to instantiate a new bot, here is the directory structure that will be created:
-
-```
-├── Gemfile
-├── Procfile.dev
-├── README.md
-├── Rakefile
-├── bot
-│ ├── controllers
-│ │ ├── bot_controller.rb
-│ │ ├── catch_alls_controller.rb
-│ │ ├── concerns
-│ │ ├── goodbyes_controller.rb
-│ │ ├── hellos_controller.rb
-│ │ ├── interrupts_controller.rb
-│ │ └── unrecognized_messages_controller.rb
-│ ├── helpers
-│ │ └── bot_helper.rb
-│ ├── models
-│ │ ├── bot_record.rb
-│ │ └── concerns
-│ └── replies
-│ ├── catch_alls
-│ │ └── level1.yml
-│ ├── goodbyes
-│ │ └── say_goodbye.yml
-│ └── hellos
-│ └── say_hello.yml
-├── config
-│ ├── boot.rb
-│ ├── database.yml
-│ ├── environment.rb
-│ ├── flow_map.rb
-│ ├── initializers
-│ │ ├── autoload.rb
-│ │ └── inflections.rb
-│ ├── puma.rb
-│ ├── services.yml
-│ └── sidekiq.yml
-├── config.ru
-└── db
- └── seeds.rb
-```
diff --git a/docs/building-components/message-services.md b/docs/building-components/message-services.md
deleted file mode 100644
index b6a9b2f8..00000000
--- a/docs/building-components/message-services.md
+++ /dev/null
@@ -1,7 +0,0 @@
----
-description: Guide to creating your own message platform component.
----
-
-# Message Services
-
-## Coming Soon...
diff --git a/docs/building-components/nlp.md b/docs/building-components/nlp.md
deleted file mode 100644
index 1ec9f8c0..00000000
--- a/docs/building-components/nlp.md
+++ /dev/null
@@ -1,7 +0,0 @@
----
-description: Guide to creating your own NLP component.
----
-
-# NLP
-
-## Coming Soon...
diff --git a/docs/config/services.yml.md b/docs/config/services.yml.md
deleted file mode 100644
index 53340fd7..00000000
--- a/docs/config/services.yml.md
+++ /dev/null
@@ -1,2 +0,0 @@
-# services.yml
-
diff --git a/docs/config/settings.md b/docs/config/settings.md
deleted file mode 100644
index 29e82f8c..00000000
--- a/docs/config/settings.md
+++ /dev/null
@@ -1,2 +0,0 @@
-# Settings
-
diff --git a/docs/controllers/available-data.md b/docs/controllers/available-data.md
deleted file mode 100644
index da61f2ec..00000000
--- a/docs/controllers/available-data.md
+++ /dev/null
@@ -1,77 +0,0 @@
-# Available Data
-
-Within each controller action, you have access to a few objects containing information about the session and the received message.
-
-{% hint style="info" %}
-Other Stealth components might make additional data available (e.g., sentiment analysis, etc).
-{% endhint %}
-
-## `current_message`
-
-The current message being processed is available via `current_message`. This is a `Stealth::ServiceMessage` object. It has a few important methods:
-
-`sender_id`: The ID of the user sending the message. This will vary based on the message service component. This is also the ID that will be used as the user's session ID.
-
-`target_id`: The ID of the target. This will vary based on the service sending the message, but for Facebook it will be the `page_id` of the Facebook page receiving the message and for SMS will be the number receiving the SMS message. For other services, this may be `nil`.
-
-`timestamp`: Ruby `DateTime` object containing the timestamp of when the message was transmitted. This might differ from the current time.
-
-`service`: String indicating the message service from where the message originated (i.e., `facebook`, or `twilio`).
-
-`message`: String of the message contents.
-
-`payload`: This will vary per message service component.
-
-`nlp_result`: The raw result of the NLP performed on this message. This will vary per NLP component.
-
-`catch_all_reason`: This is a hash that contains two keys: `:err` and `:err_msg`. The `:err` key is a string of the exception class that was raised and the `:err_msg` is the message associated with that exception. See [Catch-All Reasons](catch-alls.md#catch-all-reasons) for more info.
-
-`location`: This will vary per message service component.
-
-`attachments`: This will vary per message service component.
-
-`referral`: This will vary per message service component.
-
-## `current_session`
-
-The user's session is accessible via `current_session`. This is a `Stealth::Session` object. It has a few important methods:
-
-`flow_string`: Returns the name of the flow.
-
-`state_string`: Returns the name of the state.
-
-`to_s`: Returns the session canonical session slug string.
-
-`current_session + 2.states`: Returns a new session object 2 states after the current state. If we've exceeded the last state in flow (as defined in the [FlowMap](../flows/flowmap.md)), the last state is returned.
-
-`current_session - 2.states`: Returns a new session object 2 states before the current state. If we've exceeded the first state in the flow (as defined in the [FlowMap](../flows/flowmap.md)), the first state is returned.
-
-`==`: Compare two sessions and returns `true` if they point to the same flow and state and `false` if they do not.
-
-{% hint style="warning" %}
-Use the session arithmetic operators (`+` and `-`) sparingly. They are primarily designed for use in [Catch](catch-alls.md)[Alls](catch-alls.md) when a `fails_to` state has not been specified.
-{% endhint %}
-
-## `current_service`
-
-Returns a string indicating the message platform from where the message originated (i.e., `facebook`, or `twilio`).
-
-{% hint style="info" %}
-This is an alias of `current_message.service`
-{% endhint %}
-
-## `current_session_id`
-
-Returns the session ID. This will vary by message service, but for Facebook Messenger this will be the user's PSID and for SMS and Whatsapp this will be the user's phone number in [E.164](https://en.m.wikipedia.org/wiki/E.164) format.
-
-{% hint style="info" %}
-This is an alias of `current_message.sender_id`
-{% endhint %}
-
-## `has_location?`
-
-Returns `true` or `false` depending on whether or not the `current_message` contains location data.
-
-## `has_attachments?`
-
-Returns `true` or `false` depending on whether or not the `current_message` contains file or media attachments.
diff --git a/docs/controllers/catch-alls.md b/docs/controllers/catch-alls.md
deleted file mode 100644
index f96ebb00..00000000
--- a/docs/controllers/catch-alls.md
+++ /dev/null
@@ -1,135 +0,0 @@
-# Catch-Alls
-
-Stealth Catch-Alls are designed to handle the error cases within bots. Either the bot doesn't understand what a user typed or an error occurred. If this were a webpage, we'd see the dreaded HTTP 500 error page.
-
-Catch-Alls are designed to move beyond simple "I don't understand" messages and help users get back on track. The better your CatchAlls, the better your bot.
-
-### Triggering
-
-The `catch_all` flow is automatically triggered when either of two things happens within a controller action:
-
-1. The action [fails to progress a user](controller-overview.md#failing-to-progress-a-user).
-2. An Exception is raised.
-
-{% hint style="info" %}
-If an action within `CatchAllsController` raises an exception, it won't fire another Catch-All to prevent loops.
-{% endhint %}
-
-### Multi-Level
-
-Stealth keeps track of how many times a Catch-All is triggered for a given session. This allows you to build experiences in which the user is provided different responses for subsequent failures.
-
-So for example, if in the `hello` flow and `say_hello` state an exception is raised, then Catch-All _Level 1_ will be called. If the user is return to that same flow and state and another exception is raised, Catch-All _Level 2_ will be called. This continues until you either run out of Catch-All states or if the Catch-All counter resets.
-
-{% hint style="info" %}
-The Catch-All counter currently resets after 15 minutes. This is per flow and state. So a user may encounter a Catch-All elsewhere in your bot and it will utilize a separate Catch-All counter.
-{% endhint %}
-
-### Retrying
-
-By default, a Stealth bot comes with Catch-All Level 1 already defined. Here is the default `CatchAllsController` and associated reply:
-
-```ruby
-class CatchAllsController < BotController
-
- def level1
- send_replies
-
- if fail_session.present?
- step_to session: fail_session
- else
- step_to session: previous_session - 2.states
- end
- end
-
-private
-
- def fail_session
- previous_session.flow.current_state.fails_to
- end
-
-end
-```
-
-```yaml
-- reply_type: text
- text: Oops. It looks like something went wrong. Let's try that again
-```
-
-In the controller action, we check if the `previous_session` (the one that failed) specified a `fails_to` state. If so, we send the user there. Otherwise, we send the user back 2 states.
-
-Sending a user back two states is a pretty good generic action. Going back 1 state takes us back to the action that failed. Since the actions most likely to fail are `get` actions, or actions that deal with user responses, going back 2 states usually takes us back to the original "question".
-
-{% hint style="info" %}
-Where possible, it's better to specify a `fails_to` state so Stealth doesn't incorrectly guess where to send your user back.
-{% endhint %}
-
-### Adding More Levels
-
-If you would like to extend the experience, add a `level2` controller action and associated reply (and update the `FlowMap`). You can go as far as you want. CatchAlls have no limit, just make sure you increment using the standardized method names of `level1`, `level2`, `level3`, `level4`, etc.
-
-If a user has encountered the maximum number of CatchAll levels that have been defined, it won't attempt to call any more levels.
-
-{% hint style="warning" %}
-For the last Catch-All state, you'll probably want to prompt the user to contact support or send them to a special menu to choose from.
-{% endhint %}
-
-### Catch-All Reasons
-
-As mentioned in the [Triggering](catch-alls.md#triggering) section above, there are two reasons a Catch-All triggers. Stealth will provide the `CatchAllsController` with that reason so you can customize your messages and take the appropriate action.
-
-So if for example your bot just didn't recognize the message sent by the user, you may ask the user to repeat. If however, your database is down, you might other action.
-
-Here is an example usage:
-
-```ruby
-class CatchAllsController < BotController
-
- before_action :set_catch_all_reason
-
- def level1
- send_catch_all_replies('level1')
-
- if fail_session.present?
- step_to session: fail_session, pos: -1
- else
- step_to session: previous_session - 2.states, pos: -1
- end
- end
-
- def level2
- send_catch_all_replies('level2')
- end
-
- def level3
- send_catch_all_replies('level3')
- end
-
- private
-
- def fail_session
- previous_session.flow.current_state.fails_to
- end
-
- def send_catch_all_replies(level)
- if @reason == :unrecognized_message
- send_replies(custom_reply: "catch_alls/#{level}_unrecognized")
- else
- send_replies(custom_reply: "catch_alls/#{level}")
- end
- end
-
- def set_catch_all_reason
- @reason = case current_message.catch_all_reason[:err].to_s
- when 'Stealth::Errors::UnrecognizedMessage'
- :unrecognized_message
- else
- :system_error
- end
- end
-
-end
-
-```
-
-In `CatchAllsController` we have two sets of Catch-All replies. One for when the message was unrecognized and another for when we've encountered a system error. We dynamically send the appropriate reply based on the `@reason` instance variable that we set with the `before_action` in the controller.
diff --git a/docs/controllers/controller-overview.md b/docs/controllers/controller-overview.md
deleted file mode 100644
index 3c92ebd2..00000000
--- a/docs/controllers/controller-overview.md
+++ /dev/null
@@ -1,130 +0,0 @@
-# Controller Overview
-
-Controllers are responsible for handling incoming requests and getting a response back to the user via replies. They also perform all state transitions.
-
-## Naming Conventions
-
-The controller's methods, also referred to as actions, must be named after the flow's states. So for example, given the flow:
-
-```ruby
-flow :onboard do
- state :say_welcome
- state :ask_for_phone
- state :get_phone, fails_to: :ask_for_phone
-end
-```
-
-The corresponding controller would be:
-
-```ruby
-class OnboardsController < BotController
- def say_welcome
-
- end
-
- def ask_for_phone
-
- end
-
- def get_phone
-
- end
-end
-```
-
-## BotController
-
-Every Stealth bot comes with a default `bot_controller.rb`. You don't have to know what each method does yet, we'll cover each in their respective doc sections.
-
-```ruby
-# frozen_string_literal: true
-
-class BotController < Stealth::Controller
-
- helper :all
-
- def route
- if current_message.payload.present?
- handle_payloads
- # Clear out the payload to prevent duplicate handling
- current_message.payload = nil
- return
- end
-
- # Allow devs to jump around flows and states by typing:
- # /flow_name/state_name or
- # /flow_name (jumps to first state) or
- # //state_name (jumps to state in current flow)
- # (only works for bots in development)
- return if dev_jump_detected?
-
- if current_session.present?
- step_to session: current_session
- else
- step_to flow: 'hello', state: 'say_hello'
- end
- end
-
-private
-
- # Handle payloads globally since payload buttons remain in the chat
- # and we cannot guess in which states they will be tapped.
- def handle_payloads
- case current_message.payload
- when 'developer_restart', 'new_user'
- step_to flow: 'hello', state: 'say_hello'
- when 'goodbye'
- step_to flow: 'goodbye'
- end
- end
-
- # Automatically called when clients receive an opt-out error from
- # the platform. You can write your own steps for handling.
- def handle_opt_out
- do_nothing
- end
-
- # Automatically called when clients receive an invalid session_id error from
- # the platform. For example, attempting to text a landline.
- # You can write your own steps for handling.
- def handle_invalid_session_id
- do_nothing
- end
-
-end
-
-```
-
-All of your controllers will inherit from this `BotController`:
-
-```ruby
-class QuotesController < BotController
-
-end
-```
-
-## Failing to Progress a User
-
-One of the primary responsibilities of a controller is to update a user's session. The other responsibility is sending replies to a user. If you fail to do either of these things, essentially the user at the other end won't have any feedback.
-
-If a controller action fails to update the state or send any replies, Stealth will automatically fire a [CatchAll](catch-alls.md). This is designed to catch errors during development. If you are certain you don't want to send any feedback to the user for a specific action you can call [do\_nothing](sessions/do\_nothing.md) to override Stealth's default behavior.
-
-## Before/After/Around Filters
-
-Like Ruby on Rails controllers, Stealth controllers support `before_action`, `after_action`, and `around_action` filters.
-
-Given a `BotController` that loads a user:
-
-```ruby
-class BotController < Stealth::Controller
-
- before_action :current_user
-
- private def current_user
- @current_user ||= User.find_by_session_id(current_session_id)
- end
-
-end
-```
-
-The `current_user` method will be run on all controllers that inherit from `BotController`. Similarly, if you add a `before_action` to a child controller, only that controller's actions will run that filter.
diff --git a/docs/controllers/dev-jumps.md b/docs/controllers/dev-jumps.md
deleted file mode 100644
index 67445653..00000000
--- a/docs/controllers/dev-jumps.md
+++ /dev/null
@@ -1,47 +0,0 @@
-# Dev Jumps
-
-Dev Jumps are a feature of Stealth that makes you and your team more productive during development. It enables you to jump between flows and states while interacting with your bot. As you develop your bot, you can avoid having to restart the conversation each time.
-
-{% hint style="warning" %}
-Dev Jumps will only work while your bot is in the `development` environment. Dev jumps in other environments will be ignored.
-{% endhint %}
-
-## Usage
-
-You can specify Dev Jumps in one of three ways:
-
-1. Flow and state.
-2. Just a flow name.
-3. Just a state name.
-
-{% hint style="info" %}
-You can text these at any time to your bot.
-{% endhint %}
-
-### Flow and State
-
-```
-/flow_name/state_name
-```
-
-This will immediately step to the `flow_name` and `state_name` that you specified.
-
-### Flow Name
-
-```
-/flow_name
-```
-
-This will jump the the first state declared in the [FlowMap](../flows/flowmap.md) for the flow.
-
-### State Name
-
-```
-//state_name
-```
-
-This will jump to specified `state_name` within the current flow.
-
-{% hint style="info" %}
-Note the double forward slash `//`. This is essentially because the `flow_name` has been explicitly omitted.
-{% endhint %}
diff --git a/docs/controllers/get_match/README.md b/docs/controllers/get_match/README.md
deleted file mode 100644
index a2a213c6..00000000
--- a/docs/controllers/get_match/README.md
+++ /dev/null
@@ -1,2 +0,0 @@
-# get\_match
-
diff --git a/docs/controllers/get_match/alpha-ordinals.md b/docs/controllers/get_match/alpha-ordinals.md
deleted file mode 100644
index 6ca7a04d..00000000
--- a/docs/controllers/get_match/alpha-ordinals.md
+++ /dev/null
@@ -1,2 +0,0 @@
-# Alpha Ordinals
-
diff --git a/docs/controllers/get_match/entity-match.md b/docs/controllers/get_match/entity-match.md
deleted file mode 100644
index ef2f90dd..00000000
--- a/docs/controllers/get_match/entity-match.md
+++ /dev/null
@@ -1,2 +0,0 @@
-# Entity Match
-
diff --git a/docs/controllers/get_match/exact-match.md b/docs/controllers/get_match/exact-match.md
deleted file mode 100644
index 7fd9c932..00000000
--- a/docs/controllers/get_match/exact-match.md
+++ /dev/null
@@ -1,2 +0,0 @@
-# Exact Match
-
diff --git a/docs/controllers/handle_message/README.md b/docs/controllers/handle_message/README.md
deleted file mode 100644
index 99d2c663..00000000
--- a/docs/controllers/handle_message/README.md
+++ /dev/null
@@ -1,54 +0,0 @@
-# handle\_message
-
-The `handle_message` method is one of the most fundamental controller methods in Stealth. It enables you to succinctly handle messages without needing long `if/else` or `case` statements.
-
-## Example
-
-Here's an example of what it looks like:
-
-```ruby
-def get_call_response
- handle_message(
- :yes => proc { step_to state: :say_yes },
- 'Not available' => proc { step_to state: :say_no_problem },
- :no => proc { step_to state: :say_no_problem },
- :call => proc { step_to state: :say_call_later }
- )
-end
-```
-
-In this example, the `handle_message` method has four different "match arms". Each arm is just `key => value` pair since it's all just a hash. The keys are the `match expressions`. The values are `procs` that serve as the action to take if the match expression is matched.
-
-Stealth accepts match expressions in five different ways:
-
-1. [A string](string-mather.md) (like Line 4)
-2. An [alpha ordinal](alpha-ordinal-matcher.md)
-3. A [symbol](nlp-matcher.md) (like Lines 3, 5, and 6)
-4. A [regex](regex-matcher.md)
-5. [nil](nil-matcher.md)
-
-{% hint style="info" %}
-The `procs` can be multi-line and thus perform more than one action. In the docs for the match expressions we'll include some of those examples.
-{% endhint %}
-
-## Proc Scope
-
-If you are new to Ruby, you might be wondering about `procs`. You can think of them as anonymous functions from Javascript or closures.
-
-The code inside of the `proc` is executed if the match expression is matched. That code has access to the same variables as the containing method's scope. So for example:
-
-```ruby
-def get_response
- x = 15
- handle_message(
- 'Buy' => proc {
- x += 1
- },
- 'Refinance' => proc {
- x += 2
- }
- )
-end
-```
-
-In this example if a user sends the message "Buy", the value of `x` will be `16`. Similarly, if the user sends the message "Refinance", the value of `x` will be `17`.
diff --git a/docs/controllers/handle_message/alpha-ordinal-matcher.md b/docs/controllers/handle_message/alpha-ordinal-matcher.md
deleted file mode 100644
index 9283d045..00000000
--- a/docs/controllers/handle_message/alpha-ordinal-matcher.md
+++ /dev/null
@@ -1,40 +0,0 @@
-# Alpha Ordinal Matcher
-
-Alpha ordinals are a way of providing "quick replies" for messaging services that do not support them natively, such as SMS and Whatsapp. With `handle_message`, they are supported directly.
-
-## Example
-
-Imagine you send a user this reply:
-
-```
-What's your favorite color?
-
-Reply with:
-"A" for Red
-"B" for Blue
-"C" for Green
-"D" for Yellow
-```
-
-{% hint style="info" %}
-Stealth's Twilio component can automatically generate these for you. This is covered in depth in the [YAML Replies docs](../../replies/yaml-replies.md).
-{% endhint %}
-
-The corresponding `handle_message` method would look like this:
-
-```ruby
-def get_response
- handle_message(
- 'Red' => proc { current_user.update_attributes!(favorite_color: 'red') },
- 'Blue' => proc { current_user.update_attributes!(favorite_color: 'blue') },
- 'Green' => proc { current_user.update_attributes!(favorite_color: 'green') },
- 'Yellow' => proc { current_user.update_attributes!(favorite_color: 'yellow') }
- )
-end
-```
-
-With alpha ordinals, if a user types "C", then the `Green` match arm is automatically selected since it is the 3rd match expression (Line 5) specified in `handle_message`. Similarly, the user could still reply with "green" directly and that will also match the 3rd match expression (Line 5).
-
-{% hint style="warning" %}
-If a user were to type, "E", then Stealth will still raise a `Stealth::Errors::UnrecognizedMessage` exception.
-{% endhint %}
diff --git a/docs/controllers/handle_message/homophone-detection.md b/docs/controllers/handle_message/homophone-detection.md
deleted file mode 100644
index 9d7917ba..00000000
--- a/docs/controllers/handle_message/homophone-detection.md
+++ /dev/null
@@ -1,36 +0,0 @@
-# Homophone Detection
-
-One of the problems that arises with [alpha ordinals](alpha-ordinal-matcher.md) is that some English letters sound like other words. So for example, pronouncing "C" sounds like "see" or "sea". The letter "B" sounds like "bee" or "be". These are called homophones.
-
-If your user is using a voice assistant to dictate their responses to your bot, it's likely the voice assistant will substitute one of these homophones for the actual letter and your bot would fail to match the user's message.
-
-This is where homophone detection helps.
-
-{% hint style="info" %}
-Homophone detection is currently only supported for the English language.
-{% endhint %}
-
-## Example
-
-Given this code snippet from the [Alpha Ordinal Matcher docs](alpha-ordinal-matcher.md):
-
-```ruby
-def get_response
- handle_message(
- 'Red' => proc { current_user.update_attributes!(favorite_color: 'red') },
- 'Blue' => proc { current_user.update_attributes!(favorite_color: 'blue') },
- 'Green' => proc { current_user.update_attributes!(favorite_color: 'green') },
- 'Yellow' => proc { current_user.update_attributes!(favorite_color: 'yellow') }
- )
-end
-```
-
-If a user enters the letter "b", then the "Blue" match arm will automatically be selected as expected. However, Stealth will also natively accept the input "be" and "bee" from the user and the "Blue" match arm will still be selected. Similarly, "see" and "sea" will select the "Green" match arm.
-
-{% hint style="info" %}
-For a full list of homophones Stealth detects, you can inspect the array constant `Stealth::Controller::Messages::HOMOPHONES`
-{% endhint %}
-
-{% hint style="danger" %}
-If you attempt to use a homophone as your match expression, Stealth will raise a `Stealth::Errors::ReservedHomophoneUsed` exception.
-{% endhint %}
diff --git a/docs/controllers/handle_message/nil-matcher.md b/docs/controllers/handle_message/nil-matcher.md
deleted file mode 100644
index 83d9323a..00000000
--- a/docs/controllers/handle_message/nil-matcher.md
+++ /dev/null
@@ -1,44 +0,0 @@
-# Nil Matcher
-
-When none of the match expressions are matched in a `handle_message` method call, by default Stealth will raise a `Stealth::Errors::UnrecognizedMessage` exception. This is typically the desired behavior because it allows the [UnrecognizedMessagesController](../unrecognized-messages.md) to run.
-
-In the event that you don't want to raise an error, like in the case where you want to just save what the user typed in and move on, you can use the nil matcher.
-
-## Example
-
-Given this reply to a user:
-
-```
-How much is your property worth?
-
-Reply with:
-"A" for $1 - $100
-"B" for $101 - $999
-"C" for $1000 - $9999
-```
-
-```ruby
-def get_response
- handle_message(
- '$1 - $100' => proc {
- current_user.update_attributes!(property_value: '$1 - $100')
- },
- '$101 - $999' => proc {
- current_user.update_attributes!(property_value: '$101 - $999')
- },
- '$1000 - $9999' => proc {
- current_user.update_attributes!(property_value: '$1000 - $9999')
- },
- nil => proc {
- amount = current_user.message
- current_user.update_attributes!(property_value: amount)
- }
- )
-end
-```
-
-In the above example, if a user enters a specific amount instead of choosing one of the ranges provided, we just store that amount and don't raise an error.
-
-{% hint style="warning" %}
-You may likely still want to verify the input they entered is a Numeric. There are also better ways to handle an example like this using [get\_match](../get\_match/).
-{% endhint %}
diff --git a/docs/controllers/handle_message/nlp-matcher.md b/docs/controllers/handle_message/nlp-matcher.md
deleted file mode 100644
index cb91f3cc..00000000
--- a/docs/controllers/handle_message/nlp-matcher.md
+++ /dev/null
@@ -1,51 +0,0 @@
-# NLP Matcher
-
-NLP is a very important part of creating powerful bots. Stealth seamlessly integrates with NLP services to provide NLP matching from within the same `handle_message` method.
-
-{% hint style="info" %}
-Check out the [NLP section](../../nlp-nlu/overview.md) for more information on how to configure your NLP service to work with Stealth's `handle_message`.
-{% endhint %}
-
-## Example
-
-Let's pretend you've trained your NLP service with some examples of "Yes" and some examples of "No". These are two common intents that you'll likely want to train for your bot. Let's also assume that we've named the "Yes" intent as `yes` and the "No" intent as `no`
-
-{% hint style="warning" %}
-Make sure you name your intents using Ruby's `snake_casing` so they easily be used in `handle_message`.
-{% endhint %}
-
-Given this reply to the user:
-
-```
-Are you interested in learning more about Stealth?
-
-Reply with:
-"A" for Yes
-"B" for Remind me later
-"C" for No longer interested
-```
-
-Here is what our controller action that handles this message can look like with NLP matchers:
-
-```ruby
-def get_response
- handle_message(
- :yes => proc {
- step_to state: :say_proceed
- },
- 'Remind me later' => proc { step_to state: :say_no_problem },
- :no => proc { step_to state: :say_goodbye },
- :call => proc {
- step_to state: :ask_when_to_call
- }
- )
-end
-```
-
-Here, we are using NLP matchers on Lines 3, 7, and 8. NLP matchers have specify match expression as a Ruby symbol.
-
-When Stealth encounters an NLP matcher as a match expression, it will perform NLP using your configured NLP service. The result is automatically cached so that subsequent NLP matchers don't trigger another NLP lookup. The raw result of the NLP query will be stored in `current_message.nlp_result`, but `handle_message` will automatically make use of that without you having to parse it yourself.
-
-If the resulting NLP intent is `yes` then the `:yes` match arm will be matched. The same for `:no` and `:call`. So for example, if a user type "Nah, not interested" it's likely or `:no` match arm will be called. Similarly, if a user writes "Sure!!" the `:yes` match arm will be called.
-
-Another interesting thing to note about this example is that we have a 4th option (`:call`) that isn't explicitly mentioned in the reply to the user. With NLP matchers, it's sometimes useful to do this when your data shows that a lot users are manually typing in a custom response for a specific question. So in this case, we've asked the user if they are interested in learning more about Stealth, but some users will ask to jump on a phone call. So we've trained an NLP intent for "calls" and it will match the cases where a user requests a call for this question.
diff --git a/docs/controllers/handle_message/regex-matcher.md b/docs/controllers/handle_message/regex-matcher.md
deleted file mode 100644
index 38622e1c..00000000
--- a/docs/controllers/handle_message/regex-matcher.md
+++ /dev/null
@@ -1,41 +0,0 @@
-# Regex Matcher
-
-When using the [string matcher](string-mather.md), you might have a scenario where the option you present to user for selection is longer or contains more detail than the answer they type. In these cases, it's useful to be able to use a regex to match a just a part of a message.
-
-{% hint style="info" %}
-The regex matcher is not limited to this use case. You can use the full power of Ruby regexes.
-{% endhint %}
-
-## Example
-
-Given this reply to a user:
-
-```
-What would you like to do?
-
-Reply with:
-"A" for I'd like to restart
-"B" for Just stop
-"C" for Repeat
-```
-
-We can take advantage of the regex matcher for options "A" and "B" since it's unlikely a user would type that entire string with the formatting we expect.
-
-```ruby
-def get_response
- handle_message(
- /restart/ => proc { step_to flow: :hello },
- /stop/ => proc {
- current_user.opt_out!
- step_to flow: :opt_out
- },
- 'Repeat' => proc { step_to session: previous_session }
- )
-end
-```
-
-Now if a user types "restart" or "restart plz" it will still match the first match arm. Similarly, if they type "stop" it will match the second match arm. But just as before, typing "just stop" and "B" will also match the second match arm.
-
-{% hint style="info" %}
-Notice how we are able to mix matchers in the same `handle_message` method.
-{% endhint %}
diff --git a/docs/controllers/handle_message/string-mather.md b/docs/controllers/handle_message/string-mather.md
deleted file mode 100644
index 5268407e..00000000
--- a/docs/controllers/handle_message/string-mather.md
+++ /dev/null
@@ -1,23 +0,0 @@
-# String Matcher
-
-The string matcher matches exact string responses. It will however automatically ignore case and also ignore blank padding preceding and trailing a string. These blank spaces occur frequently with texting apps and autocomplete.
-
-## Example
-
-```ruby
-def get_response
- handle_message(
- 'Sure' => proc {
- current_user.update_attributes!(interested: true)
- step_to state: :say_yes
- },
- 'Nope' => proc { step_to state: :say_no_problem }
- )
-end
-```
-
-In this example, if a user types in `SURE` or `SuRE` or `sure`, it will match the first match arm and the corresponding proc will be executed.
-
-{% hint style="warning" %}
-If none of the match expressions are matched, Stealth will raise a `Stealth::Errors::UnrecognizedMessage` exception unless the [nil matcher](nil-matcher.md) is included.
-{% endhint %}
diff --git a/docs/controllers/interrupt-detection.md b/docs/controllers/interrupt-detection.md
deleted file mode 100644
index 8d615000..00000000
--- a/docs/controllers/interrupt-detection.md
+++ /dev/null
@@ -1,2 +0,0 @@
-# Interrupt Detection
-
diff --git a/docs/controllers/platform-errors.md b/docs/controllers/platform-errors.md
deleted file mode 100644
index 10a18bb7..00000000
--- a/docs/controllers/platform-errors.md
+++ /dev/null
@@ -1,2 +0,0 @@
-# Platform Errors
-
diff --git a/docs/controllers/route.md b/docs/controllers/route.md
deleted file mode 100644
index 6fac1924..00000000
--- a/docs/controllers/route.md
+++ /dev/null
@@ -1,70 +0,0 @@
----
-description: Describes the route method in BotController.
----
-
-# route
-
-The `route` method in `BotController` is the primary entry point for messages into your bot. This method is left open for you to edit in order for you to customize that process. Here is the method after having been generated:
-
-```ruby
-def route
- if current_message.payload.present?
- handle_payloads
- # Clear out the payload to prevent duplicate handling
- current_message.payload = nil
- return
- end
-
- # Allow devs to jump around flows and states by typing:
- # /flow_name/state_name or
- # /flow_name (jumps to first state) or
- # //state_name (jumps to state in current flow)
- # (only works for bots in development)
- return if dev_jump_detected?
-
- if current_session.present?
- step_to session: current_session
- else
- step_to flow: 'hello', state: 'say_hello'
- end
-end
-```
-
-The method, by default, performs three tasks:
-
-1. Handles payloads.
-2. Handles [Dev Jumps](dev-jumps.md).
-3. Routes a user to their existing location based on their session or starts a new session if one does not already exist.
-
-We'll cover 1 and 3 in more detail below. You can learn more about Dev Jumps via the [Dev Jumps docs](dev-jumps.md).
-
-### Payloads
-
-Payloads are used to handle things like buttons in Facebook Messenger. On other platforms, like SMS and Whatsapp, payloads might be global keywords your bot is configured to support.
-
-Payloads have to be handled globally because a button may be tapped (or keyword typed in) at any point during a conversation. Your bot, therefore, needs to be able to handle these in any flow and state.
-
-Line 2 in the code sample above checks if the payload field of a message is present, and if so, calls the `handle_payloads` method. Here is that method:
-
-```ruby
-# Handle payloads globally since payload buttons remain in the chat
-# and we cannot guess in which states they will be tapped.
-def handle_payloads
- case current_message.payload
- when 'developer_restart', 'new_user'
- step_to flow: 'hello', state: 'say_hello'
- when 'goodbye'
- step_to flow: 'goodbye'
- end
-end
-```
-
-By setting the payload value of a Facebook Messenger button to `developer_restart`, for example, you can trigger the conversation to restart.
-
-{% hint style="info" %}
-More information for handling global SMS or Whatsapp keywords and button payloads can be found in the respective documentation for each message platform component.
-{% endhint %}
-
-### Routing Based on Session
-
-In the first code sample, Lines 16-20 handle routing a user to their existing session or starting a new one. For users with an existing session, you'll likely want to keep that code the same. For users without session, you may want to customize the starting flow.
diff --git a/docs/controllers/sessions/README.md b/docs/controllers/sessions/README.md
deleted file mode 100644
index fd8b004c..00000000
--- a/docs/controllers/sessions/README.md
+++ /dev/null
@@ -1,2 +0,0 @@
-# Sessions
-
diff --git a/docs/controllers/sessions/do_nothing.md b/docs/controllers/sessions/do_nothing.md
deleted file mode 100644
index 5bded025..00000000
--- a/docs/controllers/sessions/do_nothing.md
+++ /dev/null
@@ -1,17 +0,0 @@
-# do\_nothing
-
-This method is available for overriding the default behavior of Stealth which fires a [CatchAll](../catch-alls.md) in cases where a controller action fails to the update a session or send replies. See the documentation on [failing to progress a user](../controller-overview.md#failing-to-progress-a-user) for more information.
-
-It's primarily used in states that "trap" the user (like your bot's last state or the last level of your `catch_all` flow).
-
-It's usage is straightforward:
-
-```ruby
-def
- do_nothing
-end
-```
-
-{% hint style="info" %}
-You might also use `do_nothing` within an if/else block.
-{% endhint %}
diff --git a/docs/controllers/sessions/intro.md b/docs/controllers/sessions/intro.md
deleted file mode 100644
index 8af3ecb7..00000000
--- a/docs/controllers/sessions/intro.md
+++ /dev/null
@@ -1,37 +0,0 @@
-# Session Overview
-
-Sessions in Stealth allow your bot to maintain a state for each user. If you come from the web development world, they are very similar to HTTP sessions. If you don't come from that world, no worries, we'll explain how sessions work without needing to know. If you haven't yet read the primer on [Flows and States](../../flows/overview.md), we recommend you do that first.
-
-### How are sessions stored?
-
-Sessions in Stealth are backed by Redis. Each user interacting with your bot has a unique ID assigned by the messaging platform that identifies them. With Facebook Messenger, it's a page-scoped ID (PSID). With SMS and Whatsapp it's a phone number. These unique IDs are used as the key in Redis.
-
-Regardless of what it is, it allows Stealth to find and load a user's session each time a message is received.
-
-#### Session Slugs
-
-With the unique messaging platform ID used as the Redis key, the value is the session slug. This is a canonical string that represents a user's current flow and state. A session slug looks like this: `flow->state`. So if a user's session is currently pointing to the `hello` flow and the `say_hola` state, then the slug would be `hello->say_hola`.
-
-{% hint style="info" %}
-If a user has not interacted with your bot before, the key will therefore be `nil` indicating there is no session for the user.
-{% endhint %}
-
-#### Session Expiration
-
-By default, sessions do not expire. This is however configurable as a [setting](../../config/settings.md).
-
-{% hint style="warning" %}
-If your bot sends re-engagements, make sure your session's expiration is set to be _after_ the last re-engagement message is sent.
-{% endhint %}
-
-#### Previous Session
-
-In addition to storing a user's current session, Stealth also automatically maintains a copy of the previous session. This allows you to send a user "back" from a catch-all scenario.
-
-{% hint style="info" %}
-Previous sessions also expire at the same time as primary sessions.
-{% endhint %}
-
-#### State Transitions
-
-State transitions are performed via [step\_to](step\_to.md), [step\_to\_in](step\_to\_in.md), [step\_to\_at](step\_to\_at.md), [step\_back](step\_back.md), and [update\_session\_to](update\_session\_to.md). You can also manually manipulate the key in Redis, but these are currently the only ways to alter a user's session via Stealth.
diff --git a/docs/controllers/sessions/step_back.md b/docs/controllers/sessions/step_back.md
deleted file mode 100644
index c97c57f2..00000000
--- a/docs/controllers/sessions/step_back.md
+++ /dev/null
@@ -1,88 +0,0 @@
-# step\_back
-
-Used in conjunction with `set_back_to`, `step_back` will step the user to the flow and state specified by `set_back_to`. This is a useful feature when you're building shared flows. Like for example, if you ask a user for their name in multiple places throughout your bot. This allows you to keep your flows [DRY](https://en.m.wikipedia.org/wiki/Don't\_repeat\_yourself).
-
-{% hint style="warning" %}
-If a `back_to` session has not been set before `step_back` is called, Stealth will raise a `Stealth::Errors::InvalidStateTransition` exception.
-{% endhint %}
-
-## set\_back\_to
-
-`set_back_to` serves a similar purpose as [previous\_session](intro.md#previous-session), however, instead of being automatically set by Stealth, `set_back_to` is user configurable.
-
-It takes the same parameters as `step_to`:
-
-```ruby
-set_back_to state: 'say_hello'
-set_back_to flow: 'hello', state: 'say_hello'
-set_back_to session: previous_session
-```
-
-All three commands above are valid and will store the `back_to` session.
-
-{% hint style="info" %}
-`back_to` sessions also expire along with the primary session and previous session (if an expiration has been set).
-{% endhint %}
-
-## Example
-
-```ruby
-class DataHelpersController < BotController
-
- def ask_for_email_address
- send_replies
- update_session_to state: :get_email_address
- end
-
- def get_email_address
- unless message_is_a_valid_email?
- step_to state: :say_invalid_email
- return
- end
-
- current_user.store(email: current_message.message)
-
- step_back
- end
-
- def say_invalid_email
- send_replies
- update_session_to state: :get_email_address
- end
-
-end
-
-
-class QuestionsController < BotController
-
- def ask_if_interested
- send_replies
- update_session_to state: :get_interest_response
- end
-
- def get_interest_response
- handle_message(
- :yes => proc {
- set_back_to state: :say_thanks
- step_to flow: :data_helper, state: :ask_for_email_address
- },
- :no => proc {
- step_to state: :say_no_worries
- }
- )
- end
-
- def say_thanks
- send_replies
- end
-
- def say_no_worries
- send_replies
- end
-
-end
-```
-
-In the above example, we have two flows/controllers: `data_helper` and `question`. The `DataHelpersController` contains a few states for asking for an email address for the user and verifying that it looks like a legit email address. Setting it up this way allows any of our other controllers to also ask for an email address without having to duplicate these states.
-
-On Lines 37-38, you see that we set the `back_to` session to be the `say_thanks` state. Then we step to the `data_helper` state directly via `step_to`. From the `DataHelpersController` we can continue to ask questions and update the states as needed like normal. Once we've collected the email address, we send the user "back" to the `back_to` session by calling `step_back` on Line 16.
diff --git a/docs/controllers/sessions/step_to.md b/docs/controllers/sessions/step_to.md
deleted file mode 100644
index c41a5f1b..00000000
--- a/docs/controllers/sessions/step_to.md
+++ /dev/null
@@ -1,47 +0,0 @@
-# step\_to
-
-The `step_to` method is used to update the session and immediately move the user to the specified flow and state. `step_to` can accept a _flow_, a _state_, or both. `step_to` is often used after a `say` action where the next action typically doesn't require user input.
-
-{% hint style="warning" %}
-If the flow and/or action specified in the `step_to` is not declared in the [FlowMap](../../flows/flowmap.md), Stealth will raise an exception.
-{% endhint %}
-
-## Flow Example
-
-```ruby
-step_to flow: 'hello'
-```
-
-Sets the session's flow to `hello` and the state will be set to the **first** state in that flow (as defined by the [FlowMap](../../flows/flowmap.md)). The corresponding controller action in the `HellosController` will also be immediately called.
-
-{% hint style="info" %}
-The flow name can also be specified as a symbol.
-{% endhint %}
-
-## State Example
-
-```ruby
-step_to state: 'say_hello'
-```
-
-Sets the session's state to `say_hello` and keeps the flow the same. The `say_hello` controller action will also be immediately called.
-
-{% hint style="info" %}
-The state name can also be specified as a symbol.
-{% endhint %}
-
-## Flow and State Example
-
-```ruby
-step_to flow: :hello, state: :say_hello
-```
-
-Sets the session's flow to `hello` and the state to `say_hello`. The `say_hello` controller action of the `HellosController` controller will also be immediately called.
-
-## Session Example
-
-```ruby
-step_to session: previous_session
-```
-
-Sets the session to the `previous_session` and immediately calls the respective controller action. This is useful for sending a user "back".
diff --git a/docs/controllers/sessions/step_to_at.md b/docs/controllers/sessions/step_to_at.md
deleted file mode 100644
index 92a5d66a..00000000
--- a/docs/controllers/sessions/step_to_at.md
+++ /dev/null
@@ -1,43 +0,0 @@
-# step\_to\_at
-
-The `step_to_at` method is used to update the session and move the user to the specified flow and state **at the specified date and time**. `step_to_at` can accept a _flow_, a _state_, or both. `step_to_at` is often used as a tool for re-engaging a user at a specific time.
-
-{% hint style="info" %}
-The session will only be updated and the controller action called **at the time specified**.
-{% endhint %}
-
-{% hint style="warning" %}
-If the flow and/or action specified in the `step_to_at` is not declared in the [FlowMap](../../flows/flowmap.md) (at the specified date and time), Stealth will raise an exception.
-{% endhint %}
-
-## Flow Example
-
-```ruby
-step_to_at Time.now.next_week, flow: 'hello'
-```
-
-At the specified time (next week in this case), Stealth will set the session's flow to `hello` and the state will be set to the **first** state in that flow (as defined by the [FlowMap](../../flows/flowmap.md)). The corresponding controller action in the `HellosController` will also be called.
-
-{% hint style="info" %}
-The flow name can also be specified as a symbol.
-{% endhint %}
-
-## State Example
-
-```ruby
-step_to_at Time.now.next_week, state: 'say_hello'
-```
-
-At the specified time (next week in this case), Stealth will set the session's state to `say_hello` and keeps the flow the same. The `say_hello` controller action will also be called.
-
-{% hint style="info" %}
-The state name can also be specified as a symbol.
-{% endhint %}
-
-## Flow and State Example
-
-```ruby
-step_to_at Time.now.next_week, flow: :hello, state: :say_hello
-```
-
-At the specified time (next week in this case), Stealth will set the session's flow to `hello` and the state to `say_hello`. The `say_hello` controller action of the `HellosController` controller will also be called.
diff --git a/docs/controllers/sessions/step_to_in.md b/docs/controllers/sessions/step_to_in.md
deleted file mode 100644
index e07c3d56..00000000
--- a/docs/controllers/sessions/step_to_in.md
+++ /dev/null
@@ -1,43 +0,0 @@
-# step\_to\_in
-
-The `step_to_in` method is used to update the session and move the user to the specified flow and state **after a specified duration**. `step_to_in` can accept a _flow_, a _state_, or both. `step_to_in` is often used as a tool for re-engaging a user after a specified duration.
-
-{% hint style="info" %}
-The session will only be updated and the controller action called **after the specified duration has elapsed**.
-{% endhint %}
-
-{% hint style="warning" %}
-If the flow and/or action specified in the `step_to_in` is not declared in the [FlowMap](../../flows/flowmap.md) (after the specified duration), Stealth will raise an exception.
-{% endhint %}
-
-## Flow Example
-
-```ruby
-step_to_in 8.hours, flow: 'hello'
-```
-
-After the specified duration (8 hours in this case), Stealth will set the session's flow to `hello` and the state will be set to the **first** state in that flow (as defined by the [FlowMap](../../flows/flowmap.md)). The corresponding controller action in the `HellosController` will also be called.
-
-{% hint style="info" %}
-The flow name can also be specified as a symbol.
-{% endhint %}
-
-## State Example
-
-```ruby
-step_to_in 8.hours, state: 'say_hello'
-```
-
-After the specified duration (8 hours in this case), Stealth will set the session's state to `say_hello` and keeps the flow the same. The `say_hello` controller action will also be called.
-
-{% hint style="info" %}
-The state name can also be specified as a symbol.
-{% endhint %}
-
-## Flow and State Example
-
-```ruby
-step_to_in 8.hours, flow: :hello, state: :say_hello
-```
-
-After the specified duration (8 hours in this case), Stealth will set the session's flow to `hello` and the state to `say_hello`. The `say_hello` controller action of the `HellosController` controller will also be called.
diff --git a/docs/controllers/sessions/update_session_to.md b/docs/controllers/sessions/update_session_to.md
deleted file mode 100644
index a8282cc2..00000000
--- a/docs/controllers/sessions/update_session_to.md
+++ /dev/null
@@ -1,47 +0,0 @@
-# update\_session\_to
-
-Similar to [step\_to](step\_to.md), `update_session_to` is used to update the user's session to a flow and state. It also accepts the same arguments. However, `update_session_to` does not immediately call the respective controller action. `update_session_to` is typically used after an `ask` action where the next action is waiting for user input. It allows you to set the state that will be responsible for handling that user input, like a `get` action.
-
-{% hint style="warning" %}
-If the flow and/or action specified in the `update_session_to` is not declared in the [FlowMap](../../flows/flowmap.md), Stealth will raise an exception.
-{% endhint %}
-
-## Flow Example
-
-```ruby
-update_session_to flow: 'hello'
-```
-
-Sets the session's flow to `hello` and the state will be set to the **first** state in that flow (as defined by the [FlowMap](../../flows/flowmap.md)). The corresponding controller action in the `HellosController` will **not** be called.
-
-{% hint style="info" %}
-The flow name can also be specified as a symbol.
-{% endhint %}
-
-## State Example
-
-```ruby
-update_session_to state: 'get_hello_response'
-```
-
-Sets the session's state to `get_hello_response` and keeps the flow the same. The `get_hello_response` controller action will **not** called.
-
-{% hint style="info" %}
-The state name can also be specified as a symbol.
-{% endhint %}
-
-## Flow and State Example
-
-```ruby
-step_to flow: :hello, state: :say_hello
-```
-
-Sets the session's flow to `hello` and the state to `say_hello`. The `say_hello` controller action of the `HellosController` controller will also be immediately called.
-
-## Session Example
-
-```ruby
-update_session_to session: previous_session
-```
-
-Sets the session to the `previous_session` and but does **not** call the respective controller action. This is useful for updating a user's session to the previous value.
diff --git a/docs/controllers/unrecognized-messages.md b/docs/controllers/unrecognized-messages.md
deleted file mode 100644
index 25134419..00000000
--- a/docs/controllers/unrecognized-messages.md
+++ /dev/null
@@ -1,2 +0,0 @@
-# Unrecognized Messages
-
diff --git a/docs/deployment/heroku.md b/docs/deployment/heroku.md
deleted file mode 100644
index 832757ae..00000000
--- a/docs/deployment/heroku.md
+++ /dev/null
@@ -1,2 +0,0 @@
-# Heroku
-
diff --git a/docs/deployment/overview.md b/docs/deployment/overview.md
deleted file mode 100644
index 62a4602b..00000000
--- a/docs/deployment/overview.md
+++ /dev/null
@@ -1,2 +0,0 @@
-# Deployment Overview
-
diff --git a/docs/dev-environment/README.md b/docs/dev-environment/README.md
deleted file mode 100644
index 7dbb16dc..00000000
--- a/docs/dev-environment/README.md
+++ /dev/null
@@ -1,2 +0,0 @@
-# Dev Environment
-
diff --git a/docs/dev-environment/booting-up.md b/docs/dev-environment/booting-up.md
deleted file mode 100644
index 8a3525ca..00000000
--- a/docs/dev-environment/booting-up.md
+++ /dev/null
@@ -1,33 +0,0 @@
----
-description: Steps for booting up your bot.
----
-
-# Booting Up
-
-While you can use Docker or anything else to boot up your bot, there is a built-in command that utilizes [foreman](https://github.com/ddollar/foreman) to ensure your _web server_ and your _background job processor_ both boot up. If you boot only the web server bot the the background job processor, your bot will receive message but will fail to reply.
-
-For more info about the different process types, check out [Anatomy of a Stealth bot](../basics.md#anatomy-of-a-stealth-bot).
-
-### Install Gems
-
-```
-bundle install
-```
-
-### Boot Your Bot
-
-```
-stealth s
-```
-
-Or for the full command:
-
-```
-stealth server
-```
-
-### Tunnels to Localhost
-
-After you boot your server, you'll likely want to use a service to create a tunnel to your localhost. This allows message platform like Facebook Messenger and Whatsapp to deliver messages to your laptop.
-
-Check out the [docs for creating your own tunnel](tunnels.md).
diff --git a/docs/dev-environment/environment-variables.md b/docs/dev-environment/environment-variables.md
deleted file mode 100644
index 936f3bb9..00000000
--- a/docs/dev-environment/environment-variables.md
+++ /dev/null
@@ -1,54 +0,0 @@
----
-description: Tips for streamlining your environment variable management during development.
----
-
-# Environment Variables
-
-Environment variables (ENV Vars) will likely be an important part of your configuration. Each message platform component, NLP component, and others will likely require one or more API keys.
-
-Most production environments will provide a way for you to specify your production keys. But for development, we recommend using the [dotenv](https://github.com/bkeepers/dotenv) gem. This gem will allow you to specify a `.env` file in your bot repo from where you can set all of your environment variables.
-
-{% hint style="info" %}
-Stealth will automatically exclude the `.env` file from git.
-{% endhint %}
-
-### Configuring dotenv in Stealth
-
-Add the [dotenv](https://github.com/bkeepers/dotenv) gem to your `Gemfile`:
-
-```ruby
-group :development do
- gem 'foreman'
- gem 'listen', '~> 3.3'
- gem 'dotenv'
-end
-```
-
-Install the gem:
-
-```ruby
-bundle install
-```
-
-Load dotenv on boot via `boot.rb`:
-
-```ruby
-require 'stealth/base'
-if %w(development test).include?(Stealth.env)
- require 'dotenv/load'
-end
-require_relative './environment'
-```
-
-{% hint style="info" %}
-You'll be adding Lines 2-4 right below Line 1 which will already be there.
-{% endhint %}
-
-That's it! Now you can specify your environment variables via the `.env` file:
-
-```
-FACEBOOK_VERIFY_TOKEN=some_value
-LUIS_APP_ID=1234
-LUIS_ENDPOINT=your_endpoint.cognitiveservices.azure.com
-LUIS_SUBSCRIPTION_KEY=xyz1234
-```
diff --git a/docs/dev-environment/hot-code-reloading.md b/docs/dev-environment/hot-code-reloading.md
deleted file mode 100644
index 5c2d96cf..00000000
--- a/docs/dev-environment/hot-code-reloading.md
+++ /dev/null
@@ -1,52 +0,0 @@
----
-description: ✨✨✨
----
-
-# Hot-Code Reloading
-
-Hot-code reloading is one of the more enjoyable features of using Stealth to create your bots. As you make changes to your bot, your source code is automatically loaded into memory without having to stop and start your bot!
-
-There is nothing you need to turn on to start using this feature. As long as you are in the `development` [environment](../basics.md#environments). You may however wish to customize which files are watched for changes as you add your own custom directories, service objects, etc.
-
-## Customizing Hot-Reload Paths
-
-By default, these are paths and files that Stealth will watch for changes:
-
-```
-bot/controllers/conerns/*.*
-bot/controllers/*.*
-bot/models/concerns/*.*
-bot/models/*.*
-bot/helpers/*.*
-config/*.*
-```
-
-In addition to your Ruby code in these directories, all reply files are automatically included since Stealth reads their contents for each message.
-
-### Adding a File or Path to Watch
-
-As you add your own directories to your bot, you'll want to add them to your `autoload_path` so that they can be hot-reloaded while in `development`.
-
-{% hint style="info" %}
-In `production`Stealth will pre-load all files in the `autoload_paths` array to improve performance.
-{% endhint %}
-
-#### Adding a Single File
-
-To add the file `lib/some_file.rb` to the `autoload_path`, add this line to `config/autoload.rb`:
-
-```ruby
-Stealth.config.autoload_paths << File.join(Stealth.root, 'lib', 'some_file')
-```
-
-{% hint style="warning" %}
-Don't include the `.rb` extension to the filename.
-{% endhint %}
-
-#### Adding a Directory
-
-To add the entire `lib` directory to the `autoload_path`, add this line to `config/autoload.rb`:
-
-```ruby
-Stealth.config.autoload_paths << File.join(Stealth.root, 'lib')
-```
diff --git a/docs/dev-environment/logs.md b/docs/dev-environment/logs.md
deleted file mode 100644
index 9192af86..00000000
--- a/docs/dev-environment/logs.md
+++ /dev/null
@@ -1,74 +0,0 @@
-# Logs
-
-Logs are the primary visibility mechanism into your bot. Stealth logs are designed to help you debug during development and also in production.
-
-Stealth logs all events to `stdout` instead of a log file. This avoids having to routinely clean your log files and also mimics typical production deployments.
-
-### Interpreting Logs
-
-Here are some sample log entries from the [Facebook Messenger](../platforms/facebook-messenger.md) platform:
-
-```
-Dec 28 18:31:33 sidekiq.1 info pid=4 tid=590 class=Stealth::Services::HandleMessageJob jid=b08b6721a327c72aa5baa09f INFO: start
-Dec 28 18:31:33 sidekiq.1 info TID-58w [user] User 3772279279459415 -> Received Message: What is Stealth?
-Dec 28 18:31:33 sidekiq.1 info TID-58w [facebook] Requested user profile for 3772279279459415. Response: 200: {"id":"3772279279459415","name":"Leroy Jenkins","first_name":"Leroy","last_name":"Jenkins","profile_pic":"https:\/\/picsum.photos\/400"}
-Dec 28 18:31:33 sidekiq.1 info TID-58w [primary_session] User 3772279279459415: setting session to hellos->say_hello
-Dec 28 18:31:33 sidekiq.1 info TID-58w [previous_session] User 3772279279459415: setting to
-Dec 28 18:31:33 web.1 info TID-5hs [facebook] Received webhook.
-Dec 28 18:31:34 sidekiq.1 info TID-58w [facebook] Transmitted. Response: 200: {"recipient_id":"3772279279459415"}
-Dec 28 18:31:34 sidekiq.1 info TID-58w [facebook] User 3772279279459415 -> Sending: You may have mistyped the address or the page may have moved.
+If you are the application owner check the logs for more information.
+Maybe you tried to change something you didn't have access to.
+If you are the application owner check the logs for more information.
+If you are the application owner check the logs for more information.
+