diff --git a/Rakefile b/Rakefile
new file mode 100644
index 0000000000000000000000000000000000000000..b8b42c4ba8491b3a22abfa0086c473bc3ef7b88c
--- /dev/null
+++ b/Rakefile
@@ -0,0 +1 @@
+Dir.glob('lib/tasks/*.rake').each {|r| import r}
diff --git a/_config.yml b/_config.yml
index 054d9266ffccd98bbac7c95d4278791561f7a0bb..273679436ad66d62a45157b9de4214e08971d155 100644
--- a/_config.yml
+++ b/_config.yml
@@ -19,7 +19,7 @@ baseurl: "/just-the-docs" # the subpath of your site, e.g. /blog
 url: "https://pmarsceill.github.io" # the base hostname & protocol for your site, e.g. http://example.com
 
 permalink: pretty
-exclude: ["node_modules/", "*.gemspec", "*.gem", "Gemfile", "Gemfile.lock", "package.json", "package-lock.json", "script/", "LICENSE.txt", "README.md"]
+exclude: ["node_modules/", "*.gemspec", "*.gem", "Gemfile", "Gemfile.lock", "package.json", "package-lock.json",  "script/", "LICENSE.txt", "lib/", "bin/", "README.md", "Rakefile"]
 
 # Set a path/url to a logo that will be displayed instead of the title
 #logo: "/assets/images/just-the-docs.png"
diff --git a/assets/js/zzzz-search-data.json b/assets/js/zzzz-search-data.json
index 225a764083b495ea61c8dca9ba4bd8b71a22cb4d..0a6c3e5c89046ea68923a53cec7d7f5e7b2794fe 100644
--- a/assets/js/zzzz-search-data.json
+++ b/assets/js/zzzz-search-data.json
@@ -55,4 +55,4 @@ permalink: /assets/js/search-data.json
       {%- endunless -%}
     {%- endif -%}
   {% endfor %}
-}
\ No newline at end of file
+}
diff --git a/bin/just-the-docs b/bin/just-the-docs
new file mode 100644
index 0000000000000000000000000000000000000000..5a622903058b7f1e332e5a34ae639ed9ab9c2f43
--- /dev/null
+++ b/bin/just-the-docs
@@ -0,0 +1,16 @@
+#!/usr/bin/env ruby
+
+gem_dir = File.expand_path("..",File.dirname(__FILE__))
+$LOAD_PATH.unshift gem_dir # Look in gem directory for resources first.
+exec_type = ARGV[0]
+
+if exec_type == 'rake' then
+    require 'rake'
+    require 'pp'
+    pwd=Dir.pwd
+    Dir.chdir(gem_dir) # We'll load rakefile from the gem's dir.
+    Rake.application.init
+    Rake.application.load_rakefile
+    Dir.chdir(pwd) # Revert to original pwd for any path args passed to task.
+    Rake.application.invoke_task(ARGV[1])
+end
diff --git a/docs/search.md b/docs/search.md
index 32732b2ca0f436c25a4da9cb5446ae78fa8c907c..dbc03d6c459ce2c28577aab62baea205f7434e1f 100644
--- a/docs/search.md
+++ b/docs/search.md
@@ -109,3 +109,17 @@ nav_exclude: true
 search_exclude: true
 ---
 ```
+
+
+## Generate search index when used as a gem
+
+If you use Just the Docs as a remote theme, you do not need the following steps.
+
+If you use the theme as a gem, you must initialize the search by running this `rake` command that comes with `just-the-docs`:
+
+```bash
+$ bundle exec just-the-docs rake search:init
+```
+
+This command creates the `assets/js/zzzz-search-data.json` file that Jekyll uses to create your search index.
+Alternatively, you can create the file manually with [this content]({{ site.github.repository_url }}/blob/master/assets/js/zzzz-search-data.json).
diff --git a/lib/tasks/search.rake b/lib/tasks/search.rake
new file mode 100644
index 0000000000000000000000000000000000000000..8e6305a6115a4f4f642ec859222b722b12dd5ef3
--- /dev/null
+++ b/lib/tasks/search.rake
@@ -0,0 +1,72 @@
+namespace :search do
+  desc 'Generate the files needed for search functionality'
+  task :init do
+    puts 'Creating search data json file...'
+    mkdir_p 'assets/js'
+    touch 'assets/js/zzzz-search-data.json'
+    puts 'Done.'
+    puts 'Generating content...'
+
+    File.open('assets/js/zzzz-search-data.json', 'w') do |f|
+      f.puts '---
+permalink: /assets/js/search-data.json
+---
+{
+  {%- assign i = 0 -%}
+  {% for page in site.html_pages %}
+    {%- if page.title and page.search_exclude != true -%}
+      {%- assign page_content = page.content -%}
+      {%- assign heading_level = site.search.heading_level | default: 2 -%}
+      {%- for j in (2..heading_level) -%}
+        {%- assign tag = \'<h\' | append: j -%}
+        {%- assign closing_tag = \'</h\' | append: j -%}
+        {%- assign page_content = page_content | replace: tag, \'<h1\' | replace: closing_tag, \'</h1\' -%}
+      {%- endfor -%}
+      {%- assign parts = page_content | split: \'<h1\' -%}
+      {%- assign title_found = false -%}
+      {% for part in parts offset: 1 %}
+        {%- assign titleAndContent = part | split: \'</h1>\' -%}
+        {%- assign title = titleAndContent[0] | replace_first: \'>\', \'<h1>\' | split: \'<h1>\' -%}
+        {%- assign title = title[1] | strip_html -%}
+        {%- assign content = titleAndContent[1] -%}
+        {%- assign url = page.url -%}
+        {%- if title == page.title and parts[0] == \'\' -%}
+          {%- assign title_found = true -%}
+        {%- else -%}
+          {%- assign id = titleAndContent[0] -%}
+          {%- assign id = id | split: \'id="\' -%}
+          {%- if id.size == 2 -%}
+            {%- assign id = id[1] -%}
+            {%- assign id = id | split: \'"\' -%}
+            {%- assign id = id[0] -%}
+            {%- capture url -%}{{ url | append: \'#\' | append: id }}{%- endcapture -%}
+          {%- endif -%}
+        {%- endif -%}
+  {%- unless i == 0 -%},{%- endunless -%}
+  "{{ i }}": {
+    "doc": {{ page.title | jsonify }},
+    "title": {{ title | jsonify }},
+    "content": {{ content | replace: \'</h\', \' . </h\' | replace: \'<hr\', \' . <hr\' | replace: \'</p\', \' . </p\' | replace: \'<ul\', \' . <ul\' | replace: \'</ul\', \' . </ul\' | replace: \'<ol\', \' . <ol\' | replace: \'</ol\', \' . </ol\' | replace: \'</tr\', \' . </tr\' | replace: \'<li\', \' | <li\' | replace: \'</li\', \' | </li\' | replace: \'</td\', \' | </td\' | replace: \'<td\', \' | <td\' | replace: \'</th\', \' | </th\' | replace: \'<th\', \' | <th\' | strip_html | remove: \'Table of contents\' | normalize_whitespace | replace: \'. . .\', \'.\' | replace: \'. .\', \'.\' | replace: \'| |\', \'|\' | append: \' \' | jsonify }},
+    "url": "{{ url | absolute_url }}",
+    "relUrl": "{{ url }}"
+  }
+        {%- assign i = i | plus: 1 -%}
+      {%- endfor -%}
+      {%- unless title_found -%}
+  {%- unless i == 0 -%},{%- endunless -%}
+  "{{ i }}": {
+    "doc": {{ page.title | jsonify }},
+    "title": {{ page.title | jsonify }},
+    "content": {{ parts[0] | replace: \'</h\', \' . </h\' | replace: \'<hr\', \' . <hr\' | replace: \'</p\', \' . </p\' | replace: \'<ul\', \' . <ul\' | replace: \'</ul\', \' . </ul\' | replace: \'<ol\', \' . <ol\' | replace: \'</ol\', \' . </ol\' | replace: \'</tr\', \' . </tr\' | replace: \'<li\', \' | <li\' | replace: \'</li\', \' | </li\' | replace: \'</td\', \' | </td\' | replace: \'<td\', \' | <td\' | replace: \'</th\', \' | </th\' | replace: \'<th\', \' | <th\' | strip_html | remove: \'Table of contents\' | normalize_whitespace | replace: \'. . .\', \'.\' | replace: \'. .\', \'.\' | replace: \'| |\', \'|\' | append: \' \' | jsonify }},
+    "url": "{{ page.url | absolute_url }}",
+    "relUrl": "{{ page.url }}"
+  }
+        {%- assign i = i | plus: 1 -%}
+      {%- endunless -%}
+    {%- endif -%}
+  {% endfor %}
+}'
+    end
+    puts 'Done.'
+  end
+end