Created by: pixelastic
Hello Bootstrap team,
I've always wanted to be able to easily search inside the Bootstrap documentation, so I've added the feature.
You can see it live and test it here: https://bootstrap.algolia.com/ (it of course includes smaller screen versions as well).
This pull request uses Algolia API to index and search the documentation. It includes both the indexing code (using our Jekyll plugin) as well as the front-end code to display the results.
Benefits for the end user
- Search in the whole documentation (CSS, JavaScript, Components), with typo-tolerance
- Fast results (your search index is replicated in 13 regions worldwide, it is fast no matter where the user is)
- Instant access to the documentation at the first keystroke, in a few milliseconds
- Directly scroll to the relevant part of the page
- Responsive integration, available on all viewports
How it works
We've created a free account for you that hosts the documentation. When a user does a search, it uses the Algolia API to retrieve the most relevant results from the documentation and display them in a dropdown.
This uses Typeahead v0.10.15 for the dropdown, Hogan v3.0.2 for the templates and the Algolia Client v3.7.5 for the calls to the API. The indexing is done using the Algolia Jekyll plugin v0.4 (more on this later).
Testing the pull request locally
If you want to test the PR locally, you can do the following:
$ git clone -b feature/algolia-search git@github.com:algolia/bootstrap.git
$ cd ./bootstrap
$ bundle install
$ npm install
$ grunt docs
$ jekyll serve
Note that we've added a Gemfile
to avoid any dependency version issue.
Updating the index
The Jekyll plugins adds a new command to jekyll: jekyll algolia push
. This will read the generated HTML files from a jekyll build
, extract each <p>
paragraph and <h1> - <h6>
header and index them in Algolia. You'll basically have to re-run this command everytime you push a new version to gh-pages
.
This will need your admin API key as the ALGOLIA_API_KEY
environment variable. I'll give you full and unlimited access to your dashboard so you can find it there.
ALGOLIA_API_KEY=[YOUR_ALGOLIA_ADMIN_KEY] jekyll algolia push
Tweaking
The Jekyll plugin default settings are configured for indexing a blog. We had to tweak it a bit for the Bootstrap documentation. The algolia.settings
key in _config.yml
are the Algolia settings we think provides the most relevant results. What every option does is explained in our documentation but I'm also available to give more context if any of them is not clear enough.
Records
Here is an example of what a record looks like:
{
"objectID": "components_145",
"type": "page",
"url": "/components/#navbar-forms",
"title": "Components",
"slug": "components",
"h2": "Forms",
"h1": "Navbar",
"tag_name": "p",
"raw_html": "<p>As a heads up, <code>.navbar-form</code> shares much of its code with <code>.form-inline</code> via mixin. <strong class=\"text-danger\">Some form controls, like input groups, may require fixed widths to be show up properly within a navbar.</strong></p>",
"text": "As a heads up, <code>.navbar-form</code> shares much of its code with <code>.form-inline</code> via mixin. Some form controls, like input groups, may require fixed widths to be show up properly within a navbar.",
"unique_hierarchy": "Components > Navbar > Forms",
"css_selector": "div:nth-of-type(7) > p:nth-of-type(5)",
"css_selector_parent": "#navbar-forms",
"weight": {
"page": 2,
"tag_name": 0,
"number_of_words": 1
},
"codes": [
"navbar-form",
"form-inline"
]
}
Most of the keys are self-explanatory. Some of them are used to calculate the relevance of a record, others are used for the display in the dropdown templates.
Each record contains its raw_html
version as well as a sanitized text
version. As we are indexing both <p>
and <h1-6>
, the tag_name
key tells us what kind of node each record is. The h1
, h2
, ..., h6
keys are the parent headings of the records. The unique_hierarchy
field is a concatenation of those fields, symbolising where the record is in the TOC.
css_selector
and css_selector_parent
are two unique CSS selector that target respectively the record itself, and its closest parent heading. We actually do not use css_selector
in this PR, because the generated doc adds <div>
markup (for copy-pasting snippets) that breaks them. Instead, we use the css_selector_parent
to scroll the page to the closest parent heading.
weight
and codes
are custom attributes that are not part of the plugin, but that we could add using the custom_hook_each
hook for this specific implementation. weight
is an attribute used in our custom ranking to break ties between several records. codes
contains all the class and method found in <code>
examples of the records, giving us better results when searching for navbar btn
, for example.
About Algolia
At Algolia we provide a hosted search API and support community websites like Hackernews search, CDNJS, GrowthHackers, Product Hunt or the Laravel documentation with free plans. We only ask for a "powered by Algolia". This pull request adds it to the search results.
If you want to move forward with this implementation, I'll send you the free and unlimited credentials to your Algolia dashboard as mentionned above.
I'm available for any questions you may have or any more information you would need.