diff --git a/.gitignore b/.gitignore
new file mode 100644
index 00000000000..0a65d6d4da5
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,13 @@
+.DS_Store
+
+node_modules
+
+lib/core/metadata.js
+lib/core/MetadataBlog.js
+
+website/translated_docs
+website/build/
+website/yarn.lock
+website/node_modules
+website/i18n/*
+!website/i18n/en.json
diff --git a/.gitignore-example-from-docusaurus b/.gitignore-example-from-docusaurus
new file mode 100644
index 00000000000..0a65d6d4da5
--- /dev/null
+++ b/.gitignore-example-from-docusaurus
@@ -0,0 +1,13 @@
+.DS_Store
+
+node_modules
+
+lib/core/metadata.js
+lib/core/MetadataBlog.js
+
+website/translated_docs
+website/build/
+website/yarn.lock
+website/node_modules
+website/i18n/*
+!website/i18n/en.json
diff --git a/.nvmrc b/.nvmrc
new file mode 100644
index 00000000000..45a4fb75db8
--- /dev/null
+++ b/.nvmrc
@@ -0,0 +1 @@
+8
diff --git a/README.md b/README.md
deleted file mode 100644
index 6aecb125568..00000000000
--- a/README.md
+++ /dev/null
@@ -1,4 +0,0 @@
-# Developer documentation
-
-Welcome to the Home Assistant development documentation. This is the place to learn all about how Home Assistant works and how you can extend it with support for your devices and services!
-
diff --git a/SUMMARY.md b/SUMMARY.md
deleted file mode 100644
index 66f0c86366f..00000000000
--- a/SUMMARY.md
+++ /dev/null
@@ -1,52 +0,0 @@
-# Table of contents
-
-* [Hello world!](README.md)
-* [Architecture](/architecture/README.md)
- * [Core](/architecture/core.md)
- * [Components](/architecture/components.md)
- * [Entities](/architecture/entity.md)
- * [Authentication](/architecture/authentication.md)
-
-* [Starting with Development](development/README.md)
- * [Setting up Environment](development/setting_up_environment.md)
- * [Submit your work](development/submit_your_work.md)
- * [Checklist](development/checklist.md)
- * [Style guidelines](development/style_guidelines.md)
- * [Testing](development/testing.md)
- * [Catching up with Reality](development/catching_up_with_reality.md)
- * [Validation](development/validation.md)
-
-* [API Reference](api_reference/README.md)
- * [hass object](api_reference/hass.md)
- * [Events](api_reference/events.md)
- * [States](api_reference/states.md)
- * [Services](api_reference/services.md)
- * [Config](api_reference/config.md)
-
-* [Creating a new platform (to support a new device)](add_new_platform/README.md)
- * [Checklist](add_new_platform/checklist.md)
- * [Example sensor platform](add_new_platform/example_sensor_platform.md)
- * [Example light platform](add_new_platform/example_light_platform.md)
-
-* [Adding a new component](creating_components/README.md)
- * [Checklist creating a component](creating_components/code_review_component.md)
- * [Loading components](creating_components/loading.md)
- * [Requirements & Dependencies](creating_components/deps_and_reqs.md)
- * [Handling events](creating_components/events.md)
- * [States](creating_components/states.md)
- * [Visibility](creating_components/visibility.md)
- * [Loading Platforms](creating_components/generic_discovery.md)
- * [Component Discovery](creating_components/discovery.md)
-
-* [Intents (handling voice responses)](intent/READE.md)
- * [Firing Intents](intent/firing_intents.md)
- * [Handling Intents](intent/handling_intents.md)
- * [Registering Sentences](intent/registering_sentences.md)
-
-
-
-
-
-
-
-
diff --git a/add_new_platform/README.md b/add_new_platform/README.md
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/add_new_platform/checklist.md b/add_new_platform/checklist.md
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/add_new_platform/example_light_platform.md b/add_new_platform/example_light_platform.md
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/add_new_platform/example_sensor_platform.md b/add_new_platform/example_sensor_platform.md
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/api_reference.md/README.md b/api_reference.md/README.md
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/api_reference.md/config.md b/api_reference.md/config.md
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/api_reference.md/events.md b/api_reference.md/events.md
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/api_reference.md/hass.md b/api_reference.md/hass.md
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/api_reference.md/services.md b/api_reference.md/services.md
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/api_reference.md/states.md b/api_reference.md/states.md
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/architecture/README.md b/architecture/README.md
deleted file mode 100644
index 1d59c30efa9..00000000000
--- a/architecture/README.md
+++ /dev/null
@@ -1,12 +0,0 @@
-# Architecture
-
-Before we dive into the Home Assistant architecture, let's get a clear overview of the home automation landscape as a whole. This way, we can show how the different parts of Home Assistant fit into the picture.
-
-For more information about each part in this overview, check out our blog. Here's the tl;dr version of the blog:
-
- * Home Control is responsible for collecting information and controlling devices.
- * Home Automation triggers commands based on user configurations.
- * Smart Home triggers commands based on previous behavior.
-
-
-
diff --git a/architecture/authentication.md b/architecture/authentication.md
deleted file mode 100644
index 42284534e71..00000000000
--- a/architecture/authentication.md
+++ /dev/null
@@ -1,3 +0,0 @@
-# Authentication Architecture
-
-Explain here how our authentication works.
diff --git a/architecture/components.md b/architecture/components.md
deleted file mode 100644
index 58474aa2a33..00000000000
--- a/architecture/components.md
+++ /dev/null
@@ -1 +0,0 @@
-# Components :)
\ No newline at end of file
diff --git a/architecture/core.md b/architecture/core.md
deleted file mode 100644
index db4164d43b6..00000000000
--- a/architecture/core.md
+++ /dev/null
@@ -1,10 +0,0 @@
-# Core Architecture
-
-The Home Assistant core is responsible for Home Control. Home Assistant contains four parts which make this possible:
-
- * **Event Bus**: facilitates the firing and listening of events -- the beating heart of Home Assistant.
- * **State Machine**: keeps track of the states of things and fires a `state_changed` event when a state has been changed.
- * **Service Registry**: listens on the event bus for `call_service` events and allows other code to register services.
- * **Timer**: sends a `time_changed` event every 1 second on the event bus.
-
-
diff --git a/architecture/entity.md b/architecture/entity.md
deleted file mode 100644
index 50093ecc962..00000000000
--- a/architecture/entity.md
+++ /dev/null
@@ -1,12 +0,0 @@
-# Entity Architecture
-
-Entities are an abstraction on top of the Home Assistant core.
-
-Default properties:
-
- - Name
- - Unit of measurement
- - Device class
- - Icon
- - Entity Picture
-
diff --git a/architecture/ha_architecture.svg b/architecture/ha_architecture.svg
deleted file mode 100644
index dbe41b93bc9..00000000000
--- a/architecture/ha_architecture.svg
+++ /dev/null
@@ -1,856 +0,0 @@
-
-
-
-
diff --git a/architecture/home_automation_landscape.svg b/architecture/home_automation_landscape.svg
deleted file mode 100644
index c0fbca28183..00000000000
--- a/architecture/home_automation_landscape.svg
+++ /dev/null
@@ -1,904 +0,0 @@
-
-
-
-
diff --git a/creating_components/README.md b/creating_components/README.md
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/creating_components/code_review_component.md b/creating_components/code_review_component.md
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/creating_components/deps_and_reqs.md b/creating_components/deps_and_reqs.md
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/creating_components/discovery.md b/creating_components/discovery.md
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/creating_components/events.md b/creating_components/events.md
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/creating_components/generic_discovery.md b/creating_components/generic_discovery.md
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/creating_components/loading.md b/creating_components/loading.md
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/creating_components/states.md b/creating_components/states.md
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/creating_components/visibility.md b/creating_components/visibility.md
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/development/README.md b/development/README.md
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/development/catching_up_with_reality.md b/development/catching_up_with_reality.md
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/development/checklist.md b/development/checklist.md
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/development/setting_up_environment.md b/development/setting_up_environment.md
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/development/style_guidelines.md b/development/style_guidelines.md
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/development/submit_your_work.md b/development/submit_your_work.md
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/development/testing.md b/development/testing.md
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/development/validation.md b/development/validation.md
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/docs/add_new_platform.md b/docs/add_new_platform.md
new file mode 100644
index 00000000000..e0882296bfc
--- /dev/null
+++ b/docs/add_new_platform.md
@@ -0,0 +1,35 @@
+---
+layout: page
+title: "Adding support for a new platform"
+description: "Hints and tips for when you're adding a new platform to Home Assistant."
+date: 2014-12-21 13:27
+sidebar: true
+comments: false
+sharing: true
+footer: true
+---
+
+Components that interact with devices are called "[Entity Components](https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/helpers/entity_component.py)." They are structured in core and platform logic, which means different brands can use the same logic to handle a light.
+
+For example, the built-in `switch` component consists of various platforms in [`homeassistant/components/switch/`](https://github.com/home-assistant/home-assistant/tree/master/homeassistant/components/switch). The file `__init__.py` contains the core logic of all platforms and the `vendor_name.py` files contain only the relevant platform code.
+
+If you're planning to add support for a new type of device to an existing component, you can get away with only writing platform logic. Have a look at how the component works with other platforms and create a similar file for the platform that you want to add:
+
+ - [Example sensor platform](/developers/platform_example_sensor): hello world of platforms.
+ - [Example light platform](/developers/platform_example_light): showing best practices.
+
+### {% linkable_title Interfacing with devices %}
+
+One Home Assistant rule is that platform logic should never interface directly with devices. Instead, use a third-party Python 3 library. This way, Home Assistant can share code with the Python community and keep the project maintainable.
+
+To integrate the third-party library, create an [Entity class](https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/helpers/entity.py) for your device. Entities are Home Assistant's representations of lights, switches, sensors, etc. and are derived from the [Entity Abstract Class](https://github.com/home-assistant/home-assistant/blob/master/homeassistant/helpers/entity.py). This abstract class contains logic for integrating most standard features into your entities, such as visibility, entity IDs, updates, and much more.
+
+### {% linkable_title Requirements and dependencies %}
+
+Platforms can specify dependencies and requirements [the same way as components](/developers/component_deps_and_reqs):
+
+```python
+REQUIREMENTS = ['some-package==2.0.0', 'some-other-package==2.5.0']
+DEPENDENCIES = ['mqtt']
+```
+
diff --git a/docs/architecture.md b/docs/architecture.md
new file mode 100644
index 00000000000..191ed65f7b9
--- /dev/null
+++ b/docs/architecture.md
@@ -0,0 +1,41 @@
+---
+layout: page
+title: "Architecture"
+description: "Overview of the Home Assistant architecture."
+date: 2014-12-18 21:49
+sidebar: true
+comments: false
+sharing: true
+footer: true
+og_image: /images/architecture/ha_architecture.svg
+---
+
+Before we dive into the Home Assistant architecture, let's get a clear overview of the home automation landscape as a whole. This way, we can show how the different parts of Home Assistant fit into the picture.
+
+For more information about each part in this overview, check out our blog. Here's the tl;dr version of the blog:
+
+ * Home Control is responsible for collecting information and controlling devices.
+ * Home Automation triggers commands based on user configurations.
+ * Smart Home triggers commands based on previous behavior.
+
+
+
+
+
+ Overview of the home automation landscape
+
+
+The Home Assistant core is responsible for Home Control. Home Assistant contains four parts which make this possible:
+
+ * **Event Bus**: facilitates the firing and listening of events -- the beating heart of Home Assistant.
+ * **State Machine**: keeps track of the states of things and fires a `state_changed` event when a state has been changed.
+ * **Service Registry**: listens on the event bus for `call_service` events and allows other code to register services.
+ * **Timer**: sends a `time_changed` event every 1 second on the event bus.
+
+
+
+
+
+ Overview of the Home Assistant core architecture
+
diff --git a/docs/architecture_components.md b/docs/architecture_components.md
new file mode 100644
index 00000000000..ac05c93ba03
--- /dev/null
+++ b/docs/architecture_components.md
@@ -0,0 +1,67 @@
+---
+layout: page
+title: "Components Architecture"
+description: "Overview of components within the Home Assistant architecture."
+date: 2016-04-16 14:24 -07:00
+sidebar: true
+comments: false
+sharing: true
+footer: true
+og_image: /images/architecture/component_interaction.png
+---
+
+Home Assistant can be extended with **components**. Each component is responsible for a specific domain within Home Assistant. Components can listen for or trigger events, offer services, and maintain states. Components are written in Python and can do all the goodness that Python has to offer. Out of the box, Home Assistant offers a bunch of [built-in components]({{site_root}}/components/).
+
+
+
+Diagram showing interaction between components and the Home Assistant core
+
+
+There are two types of components within Home Assistant: components that interact with an Internet of Things domain, and components that respond to events that happen within Home Assistant. Read on to learn about each type!
+
+#### {% linkable_title Components that interact with an Internet-of-Things domain %}
+
+These components track devices within a specific domain and consist of a core part and platform-specific logic. These components make their information available via the State Machine and the Event Bus. The components also register services in the Service Registry to expose control of the devices.
+
+For example, the built-in [`switch` component](/components/switch/) is responsible for interaction with different types of switches. A platform provides support for a particular kind or brand of device. For example, a switch could use a WeMo or Orvibo platform and a light component might interact with the Hue or LIFX platform.
+
+If you want to add support for a new platform, check out the [add new platform section](/developers/add_new_platform/).
+
+#### {% linkable_title Components that respond to events that happen within Home Assistant %}
+
+These components provide small pieces of home automation logic or involve services that do common tasks within your house.
+
+For example, the [`device_sun_light_trigger` component](/components/device_sun_light_trigger/) tracks the state of devices and the sun to make sure that the lights are turned on when it gets dark and people are home. The component uses logic like this:
+
+```text
+In the event that device 'Paulus Nexus 5' changes to the 'Home' state:
+ If the sun has set and the lights are not on:
+ Turn on the lights
+```
+
+```text
+In the event that the combined state of all tracked devices changes to 'Not Home':
+ If the lights are on:
+ Turn off the lights
+```
+
+```text
+In the event of the sun setting:
+ If the lights are off and the combined state of all tracked device equals 'Home':
+ Turn on the lights
+```
+
+Look [here](/python_component_automation/) for a comprehensive example of a home automation component.
+
+### {% linkable_title The full picture %}
+
+When we put all the different pieces of Home Assistant together, it's a close match for the initial home automation overview sketch. The smart home AI has not been implemented yet, so it's not included in this picture.
+
+
+
+
+
+ Overview of the full Home Assistant architecture with a couple of loaded components and platforms
+
+
+The platform logic for components uses third-party Python libraries to communicate with the devices. Through this, we can leverage some of the best libraries in the Python community.
diff --git a/docs/asyncio.md b/docs/asyncio.md
new file mode 100644
index 00000000000..2a456794d61
--- /dev/null
+++ b/docs/asyncio.md
@@ -0,0 +1,27 @@
+---
+layout: page
+title: "Asynchronous Programming"
+description: "Introduction to the asynchronous core of Home Assistant."
+date: 2016-10-17 21:49
+sidebar: true
+comments: false
+sharing: true
+footer: true
+---
+
+On September 29, 2016 we released [Home Assistant 0.29][0.29] as part of our bi-weekly release schedule. This release introduced a complete overhaul of the core spearheaded by [Ben Bangert][ben].
+
+The old core was set up like a “traditional” threaded application. Each resource that was not thread safe (ie. the state of entities) would be protected by a lock. This caused a lot of waiting and potential inconsistency because a task could now end up waiting halfway through its job until some resource got freed.
+
+Our new core is based on an Python’s built-in asyncio module. Instead of having all threads have access to the core API objects, access is now limited to a special thread called the event loop. All components will now schedule themselves as a task to be executed by the event loop. This gives us the guarantee that only one task is executed at once, meaning we no longer need any locks.
+
+The only problem with running everything inside the event loop is when a task is doing blocking I/O, what most third-party Python libraries are doing. For example while requesting new information from a device, the core will stop running until we get a response from the device. To handle this, a task is able to suspend itself until the response is available after which it will be enqueued for the event loop to process the result.
+
+For a task to be able to suspend itself, all code that it calls has to have this capability added. This means in practice that each device integration will need a full rewrite of the library that offers the integration! As this is not something that can be achieved, ever, a 100% backwards compatible API has been added so that no platform will require updating.
+
+The backwards compatible API works by scheduling a task from a different thread and blocking that thread until the task has been processed by the event loop.
+
+### [Next step: asyncio 101 »](/developers/asyncio_101/)
+
+[0.29]: /blog/2016/09/29/async-sleepiq-emoncms-stocks/
+[ben]: https://github.com/bbangert/
diff --git a/docs/asyncio_101.md b/docs/asyncio_101.md
new file mode 100644
index 00000000000..c88265119fd
--- /dev/null
+++ b/docs/asyncio_101.md
@@ -0,0 +1,20 @@
+---
+layout: page
+title: "Asyncio 101"
+description: "An introduction to asyncio."
+date: 2017-04-08 21:49
+sidebar: true
+comments: false
+sharing: true
+footer: true
+---
+
+If you are not familiar yet with asyncio, please watch the below video. It's a great introduction by [Robert Smallshire][rob] in how and why asyncio works the way it does.
+
+
+
+
+
+### [Next step: Categorizing Functions »](/developers/asyncio_categorizing_functions/)
+
+[rob]: https://github.com/rob-smallshire
\ No newline at end of file
diff --git a/docs/asyncio_categorizing_functions.md b/docs/asyncio_categorizing_functions.md
new file mode 100644
index 00000000000..6fe74ad359d
--- /dev/null
+++ b/docs/asyncio_categorizing_functions.md
@@ -0,0 +1,79 @@
+---
+layout: page
+title: "Categorizing Functions"
+description: "A categorization of functions to work with the asynchronous core of Home Assistant."
+date: 2016-10-17 21:49
+sidebar: true
+comments: false
+sharing: true
+footer: true
+---
+
+A piece of work within Home Assistant is represented by a function that will be invoked. It will either run inside our event loop or inside our thread pool, depending on if it is async safe.
+
+Home Assistant uses the convention that all functions that must be run from within the event loop are prefixed with `async_`.
+
+## {% linkable_title The coroutine function %}
+
+Coroutines are special functions based on Python’s generators syntax which allows them to suspend execution while waiting on a result.
+
+Invoking a coroutine function will return a Generator object back, but will not actually begin execution. This object will execute the task when it is either yielded from (from within another coroutine) or it is scheduled on the event loop.
+
+To declare a function a coroutine, import the coroutine annotation from the asyncio package and annotate your function.
+
+```python
+import asyncio
+
+@asyncio.coroutine
+def async_look_my_coroutine(target):
+ result = yield from entity.async_turn_on()
+ if result:
+ print("hello {}".format(target))
+
+hass.loop.create_task(async_look_my_coroutine("world"))
+```
+
+In this example, we schedule the coroutine by calling `hass.loop.create_task`. This will add the coroutine to the queue of tasks to be run. When the event loop is running `async_look_my_coroutine` it will suspend the task when `yield from entity.async_turn_on()` is called. At that point a new task will be scheduled to execute `entity.async_turn_on()`. When that job has been executed, `async_look_my_coroutine` will resume.
+
+## {% linkable_title The callback function %}
+
+This is a normal function that is considered safe to be run from within the event loop. A callback is unable to suspend itself and thus cannot do any I/O or call a coroutine. A callback is capable of scheduling a new task but it will not be able to wait for the results.
+
+To declare a function as a callback, import the callback annotation from the core package and annotate your function.
+
+A common use case for a callback in Home Assistant is as a listener for an event or a service call. It can process the incoming information and then schedule the right calls to be made. Example from the automation component.
+
+```python
+from homeassistant.core import callback
+
+@callback
+def async_trigger_service_handler(service_call):
+ """Handle automation trigger service calls."""
+ vars = service_call.data.get(ATTR_VARIABLES)
+ for entity in component.async_extract_from_service(service_call):
+ hass.loop.create_task(entity.async_trigger(vars, True))
+```
+
+In this example, `entity.async_trigger` is a coroutine function. Invoking the coroutine function will return a coroutine task. The passed in parameters will be used when the task gets executed.
+
+To execute the task we have to schedule it for execution on the event loop. This is done by calling `hass.loop.create_task`.
+
+### {% linkable_title Why even have callbacks? %}
+
+You might wonder, if a coroutine can do everything a callback can do, why even have a callback. The reason is performance and better state consistency of the core API objects.
+
+When coroutine A waits for coroutine B, it will suspend itself and schedule a new task to run B. This means that the event loop is now running A, B and then A again. If B is a callback, A will never have to suspend itself and thus the event loop is just running A. The consistency implication is that other events queued to run on the event loop continue to wait until callbacks complete, but will be interleaved when yielding to another coroutine.
+
+## {% linkable_title Event loop and thread safe %}
+
+These are functions that are safe to run both in a thread and inside the event loop. These functions are usually performing a computation or transform data in memory. Anything that does I/O does not fall under this category. Many standard library functions fall in this category. For example generating the sum of a set of numbers using sum or merging two dictionaries.
+
+There is no special annotation to mark functions as part of this category and care should be taken when using these functions from inside the event loop. When in doubt, look at their implementation.
+
+## {% linkable_title Other functions %}
+
+These are all the functions that did not fit in the previous categories. These functions are either thread-safe or not considered safe to be run within the event loop. These are functions that use sleep, or perform I/O.
+
+There is no special annotation necessary to be considered part of this category.
+
+### [Next step: Working with Async »](/developers/asyncio_working_with_async/)
diff --git a/docs/asyncio_misc.md b/docs/asyncio_misc.md
new file mode 100644
index 00000000000..3fbc923c6fe
--- /dev/null
+++ b/docs/asyncio_misc.md
@@ -0,0 +1,22 @@
+---
+layout: page
+title: "Miscellaneous Async"
+description: "A collection of miscellaneous topics about async that didn't fit on the other pages."
+date: 2016-10-17 21:49
+sidebar: true
+comments: false
+sharing: true
+footer: true
+---
+
+## {% linkable_title What about ‘async’ and ‘await’ syntax? %}
+Python 3.5 introduced new syntax to formalize the asynchronous pattern. This is however not compatible with Python 3.4. The minimum required Python version for Home Assistant is based on the Python version shipped with Debian stable, which is currently 3.5.3.
+
+For more information, Brett Cannon wrote [an excellent breakdown][brett] on 'async' and 'await' syntax and how asynchronous programming works.
+
+## {% linkable_title Acknowledgements %}
+
+Huge thanks to [Ben Bangert][ben] for starting the conversion of the core to async, guiding other contributors while taking their first steps with async programming and peer reviewing this documentation.
+
+[brett]: http://www.snarky.ca/how-the-heck-does-async-await-work-in-python-3-5
+[ben]: https://github.com/bbangert/
diff --git a/docs/asyncio_working_with_async.md b/docs/asyncio_working_with_async.md
new file mode 100644
index 00000000000..40fd82b2466
--- /dev/null
+++ b/docs/asyncio_working_with_async.md
@@ -0,0 +1,128 @@
+---
+layout: page
+title: "Working with Async"
+description: "A breakdown of all the different ways to work with the asynchronous core of Home Assistant."
+date: 2016-10-17 21:49
+sidebar: true
+comments: false
+sharing: true
+footer: true
+---
+
+Although we have a backwards compatible API, using the async core directly will be a lot faster. Most core components have already been rewritten to leverage the async core. This includes the EntityComponent helper (foundation of light, switch, etc), scripts, groups and automation.
+
+## {% linkable_title Interacting with the core %}
+
+[All methods in the Home Assistant core][dev-docs] are implemented in two flavors: an async version and a version to be called from other threads. The versions for other are merely wrappers that call the async version in a threadsafe manner using [the available async utilities][dev-docs-async].
+
+So if you are making calls to the core (the hass object) from within a callback or coroutine, use the methods that start with async_. If you need to call an async_ function that is a coroutine, your task must also be a coroutine.
+
+## {% linkable_title Implementing an async component %}
+
+To make a component async, implement an async_setup.
+
+```python
+def setup(hass, config):
+ # Setup your component outside of the event loop.
+```
+
+Will turn into:
+
+```python
+import asyncio
+
+@asyncio.coroutine
+def async_setup(hass, config):
+ # Setup your component inside of the event loop.
+```
+
+## {% linkable_title Implementing an async platform %}
+
+For platforms we support async setup. Instead of setup_platform you need to have a coroutine async_setup_platform.
+
+```python
+setup_platform(hass, config, add_entities, discovery_info=None):
+ # Setup your platform outside of the event loop.
+```
+
+Will turn into:
+
+```python
+import asyncio
+
+@asyncio.coroutine
+def async_setup_platform(hass, config, async_add_entities,
+ discovery_info=None):
+ # Setup your platform inside of the event loop
+```
+
+The only difference with the original parameters is that the `add_entities` function has been replaced by the async friendly callback `async_add_entities`.
+
+## {% linkable_title Implementing an async entity %}
+
+You can make your entity async friendly by converting your update method to be async. This requires the dependency of your entities to also be async friendly!
+
+```python
+class MyEntity(Entity):
+ def update(self):
+ """Retrieve latest state."""
+ self._state = fetch_state()
+```
+
+Will turn into:
+
+```python
+import asyncio
+
+class MyEntity(Entity):
+ @asyncio.coroutine
+ def async_update(self):
+ """Retrieve latest state."""
+ self._state = yield from async_fetch_state()
+```
+
+Make sure that all properties defined on your entity do not result in I/O being done. All data has to be fetched inside the update method and cached on the entity. This is because these properties are read from within the event loop and thus doing I/O will result in the core of Home Assistant waiting until your I/O is done.
+
+## {% linkable_title Calling async functions from threads %}
+
+Sometimes it will happen that you’re in a thread and you want to call a function that is only available as async. Home Assistant includes a few async helper utilities to help with this.
+
+In the following example, `say_hello` will schedule `async_say_hello` and block till the function has run and get the result back.
+
+```python
+from homeassistant.util.async import run_callback_threadsafe
+
+def say_hello(hass, target):
+ return run_callback_threadsafe(
+ hass.loop, async_say_hello, target).result()
+
+def async_say_hello(hass, target):
+ return "Hello {}!".format(target)
+```
+
+## {% linkable_title Dealing with passed in functions %}
+
+If your code takes in functions from other code, you will not know which category the function belongs to and how they should be invoked. This usually only occurs if your code supplies an event helper like `mqtt.async_subscribe` or `track_state_change_listener`.
+
+To help with this, there are two helper methods on the hass object that you can call from inside the event loop:
+
+#### {% linkable_title hass.async_run_job %}
+
+Use this method if the function should be called as soon as possible. This will call callbacks immediately, schedule coroutines for execution on the event loop and schedule other functions to be run inside the thread pool.
+
+| Callback | Call immediately.
+| Coroutine | Schedule for execution on the event loop.
+| Other functions | Schedule for execution in the thread pool.
+
+#### {% linkable_title hass.async_add_job %}
+
+Use this method if the function should be called but not get priority over already scheduled calls.
+
+| Callback | Schedule for execution on the event loop.
+| Coroutine | Schedule for execution on the event loop.
+| Other functions | Schedule for execution in the thread pool.
+
+### [Next step: Miscellaneous »](/developers/asyncio_misc/)
+
+[dev-docs]: https://dev-docs.home-assistant.io/en/master/api/core.html
+[dev-docs-async]: https://dev-docs.home-assistant.io/en/dev/api/util.html#module-homeassistant.util.async
diff --git a/docs/code_review_component.md b/docs/code_review_component.md
new file mode 100644
index 00000000000..bebe3dc7847
--- /dev/null
+++ b/docs/code_review_component.md
@@ -0,0 +1,36 @@
+---
+layout: page
+title: "Checklist for creating a component"
+description: "A list of things to pay attention to when code reviewing a component."
+date: 2017-01-15 14:09 -0800
+sidebar: true
+comments: false
+sharing: true
+footer: true
+---
+
+A checklist of things to do when you're adding a new component.
+
+
+Not all existing platforms follow the requirements in this checklist. This cannot be used as a reason to not follow them!
+
+
+### {% linkable_title 1. Requirements %}
+
+ 1. Requirement version pinned: `REQUIREMENTS = ['phue==0.8.1']`
+ 2. We no longer want requirements hosted on GitHub. Please upload to PyPi.
+ 3. Requirements should only be imported inside functions. This is necessary because requirements are installed on the fly.
+
+### {% linkable_title 2. Configuration %}
+
+ 1. Voluptuous schema present for config validation
+ 2. Default parameters specified in voluptuous schema, not in `setup(…)`
+ 3. Schema using as many generic config keys as possible from `homeassistant.const`
+ 4. If your component has platforms, define a `PLATFORM_SCHEMA` instead of a `CONFIG_SCHEMA`.
+ 5. If using a `PLATFORM_SCHEMA` to be used with `EntityComponent`, import base from `homeassistant.helpers.config_validation`
+ 6. Never depend on users adding things to `customize` to configure behavior inside your component.
+
+### {% linkable_title 3. Component/platform communication %}
+
+ 1. If you need to share global data with platforms, use the dictionary `hass.data`. `hass.data[DATA_XY]` while `XY` is the component is preferred over `hass.data[DOMAIN]`.
+ 2. If the component fetches data that causes its related platform entities to update, you can notify them using the dispatcher code in `homeassistant.helpers.dispatcher`.
diff --git a/docs/code_review_platform.md b/docs/code_review_platform.md
new file mode 100644
index 00000000000..00ab599c1b3
--- /dev/null
+++ b/docs/code_review_platform.md
@@ -0,0 +1,78 @@
+---
+layout: page
+title: "Checklist for creating a platform"
+description: "A list of things to pay attention to when code reviewing a platform."
+date: 2017-01-15 14:09 -0800
+sidebar: true
+comments: false
+sharing: true
+footer: true
+---
+
+A checklist of things to do when you're adding a new platform.
+
+
+Not all existing platforms follow the requirements in this checklist. This cannot be used as a reason to not follow them!
+
+
+### {% linkable_title 1. Requirements %}
+
+ 1. Requirement version should be pinned: `REQUIREMENTS = ['phue==0.8.1']`
+ 2. We no longer want requirements hosted on GitHub. Please upload to PyPi.
+ 3. Requirements should only be imported inside functions. This is necessary because requirements are installed on the fly.
+
+### {% linkable_title 2. Dependencies %}
+
+ 1. If you depend on a component for the connection, add it to your dependencies: `DEPENDENCIES = ['nest']`
+
+### {% linkable_title 3. Configuration %}
+
+ 1. Voluptuous schema present for config validation
+ 2. Voluptuous schema extends schema from component (e.g., `light.hue.PLATFORM_SCHEMA` extends `light.PLATFORM_SCHEMA`)
+ 3. Default parameters specified in voluptuous schema, not in `setup_platform(…)`
+ 4. Your `PLATFORM_SCHEMA` should use as many generic config keys as possible from `homeassistant.const`
+ ```python
+ import voluptuous as vol
+
+ from homeassistant.const import CONF_FILENAME, CONF_HOST
+ from homeassistant.components.light import PLATFORM_SCHEMA
+ import homeassistant.helpers.config_validation as cv
+
+ CONF_ALLOW_UNREACHABLE = 'allow_unreachable'
+ DEFAULT_UNREACHABLE = False
+
+ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
+ vol.Required(CONF_HOST): cv.string,
+ vol.Optional(CONF_ALLOW_UNREACHABLE,
+ default=DEFAULT_UNREACHABLE): cv.boolean,
+ vol.Optional(CONF_FILENAME): cv.string,
+ })
+ ```
+ 5. Never depend on users adding things to `customize` to configure behavior inside your platform.
+
+### {% linkable_title 4. Setup Platform %}
+
+ 1. Test if passed in info (user/pass/host etc.) works.
+ 2. Group your calls to `add_devices` if possible.
+ 3. If platform adds extra services, format should be `._`.
+
+### {% linkable_title 5. Entity %}
+
+ 1. Extend entity from component, e.g., `class HueLight(Light)`
+ 2. Do not call `update()` in constructor, use `add_devices(devices, True)` instead.
+ 3. Do not do any I/O inside properties. Cache values inside `update()` instead.
+ 4. The state and/or attributes should not contain relative time since something happened. Instead it should store UTC timestamps.
+
+### {% linkable_title 6. Communication with devices/services %}
+
+ 1. All API specific code has to be part of a third party library hosted on PyPi. Home Assistant should only interact with objects and not make direct calls to the API.
+
+```python
+# bad
+status = requests.get(url('/status'))
+
+# good
+from phue import Bridge
+bridge = Bridge(…)
+status = bridge.status()
+```
diff --git a/docs/component_deps_and_reqs.md b/docs/component_deps_and_reqs.md
new file mode 100644
index 00000000000..2a6ae27d0e1
--- /dev/null
+++ b/docs/component_deps_and_reqs.md
@@ -0,0 +1,43 @@
+---
+layout: page
+title: "Requirements & Dependencies"
+description: "Instructions on how to define requirements and dependencies."
+date: 2016-04-16 13:32
+sidebar: true
+comments: false
+sharing: true
+footer: true
+---
+
+Home Assistant allows components and platforms to specify their dependencies and requirements using the variables `DEPENDENCIES` and `REQUIREMENTS`. Both are lists that contain strings.
+
+## {% linkable_title Dependencies %}
+
+Dependencies are other Home Assistant components that should be setup before the platform is loaded. An example is the MQTT sensor component, which requires an active connection to an MQTT broker. If Home Assistant is unable to load and setup the MQTT component, it will not setup the MQTT sensor component.
+
+```python
+DEPENDENCIES = ['mqtt']
+```
+
+## {% linkable_title Requirements %}
+
+Requirements are Python libraries or modules that you would normally install using `pip` for your component. Home Assistant will try to install the requirements into the `deps` subdirectory of the Home Assistant [configuration directory](/docs/configuration/) if you are not using a `venv` or in something like `path/to/venv/lib/python3.6/site-packages` if you running in a virtual environment. This will make sure that all requirements are present at startup. If steps fails like missing packages for the compilation of a module or other install errors, the component will fail to load.
+
+Requirements is a list of strings. Each entry is a `pip` compatible string. For example, the media player Cast platform depends on the Python package PyChromecast v0.6.12:
+
+```python
+REQUIREMENTS = ['pychromecast==0.6.12']
+```
+
+During development of a component, it can be useful to test against different versions of a requirement. This can be done in two steps, using pychromecast as an example:
+
+* `pip install pychromecast==0.6.13 --target ~/.homeassistant/deps`
+* `hass --skip-pip`
+
+This will use the specified version, and prevent Home Assistant from trying to override it with what is currently in `REQUIREMENTS`.
+
+If you need to make changes to a requirement to support your component, it's also possible to `pip install` from a checkout of the requirement.
+
+* `git clone https://github.com/balloob/pychromecast.git`
+* `pip install ./pychromecast`
+* `hass --skip-pip`
diff --git a/docs/component_discovery.md b/docs/component_discovery.md
new file mode 100644
index 00000000000..2911adaa26d
--- /dev/null
+++ b/docs/component_discovery.md
@@ -0,0 +1,60 @@
+---
+layout: page
+title: "Component Discovery"
+description: "How to make component discovery work."
+date: 2017-11-23 07:27 +02:00
+sidebar: true
+comments: false
+sharing: true
+footer: true
+---
+
+
+This option is only available for built-in components.
+
+
+Home Assistant has a discovery service running in the background to discover new devices. Whenever a new device is discovered, a `SERVICE_DISCOVERED` event will be fired with the found service and the information. The `discovery` component has some knowledge about which components handle which type of services and will ensure those are loaded and listening before firing the `SERVICE_DISCOVERED` event.
+
+### {% linkable_title Add discovery instructions %}
+
+Device discovery for Home Assistant has been extracted into an external library called [NetDisco](https://github.com/home-assistant/netdisco). This library is integrated using [the `discovery` component](https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/components/discovery.py) and scans the network in intervals for uPnP and zeroconf/mDNS services.
+
+To have your device be discovered, you will have to extend the NetDisco library to be able to find your device. This is done by adding a new discoverable. [See the repository for examples of existing discoverable.](https://github.com/home-assistant/netdisco/tree/master/netdisco/discoverables)
+
+### {% linkable_title Listening to `SERVICE_DISCOVERED` events %}
+
+From your component, you will have to set up the listening for specific services. Given below is an example how one would listen for a discovered AwesomeDevice:
+
+```python
+from homeassistant.components.discovery import SERVICE_AWESOMEDEVICE
+from homeassistant.helpers import discovery
+
+DOMAIN = 'awesomedevice'
+
+DEPENDENCIES = ['http']
+
+def setup(hass, config):
+ cfg = config.get(DOMAIN)
+
+ def device_discovered(service, info):
+ """ Called when a Awesome device has been discovered. """
+ print("Discovered a new Awesome device: {}".format(info))
+
+ discovery.listen(
+ hass, SERVICE_AWESOMEDEVICE, device_discovered)
+
+ return True
+```
+
+### {% linkable_title Auto-loading your component upon discovery %}
+
+The `discovery` component is capable of setting up your components before firing the `EVENT_PLATFORM_DISCOVERED` event. To do this you will have to update the [`SERVICE_HANDLERS`](https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/components/discovery.py#L40) constant in [the `discovery` component](https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/components/discovery.py):
+
+```python
+SERVICE_AWESOMEDEVICE = 'awesomedevice'
+
+SERVICE_HANDLERS = {
+ ...
+ SERVICE_AWESOMEDEVICE: ('awesomedevice', None),
+}
+```
diff --git a/docs/component_events.md b/docs/component_events.md
new file mode 100644
index 00000000000..ee2e281b1f3
--- /dev/null
+++ b/docs/component_events.md
@@ -0,0 +1,12 @@
+---
+layout: page
+title: "Handling events"
+description: "Instructions on how to handle events with your component."
+date: 2016-04-16 13:32
+sidebar: true
+comments: false
+sharing: true
+footer: true
+---
+
+Home Assistant has different ways of responding to events that occur in Home Assistant. These have been organized in [helper methods](https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/helpers/event.py). Examples are `track_state_change`, `track_point_in_time`, `track_time_change`.
diff --git a/docs/component_generic_discovery.md b/docs/component_generic_discovery.md
new file mode 100644
index 00000000000..8eacc22ff4a
--- /dev/null
+++ b/docs/component_generic_discovery.md
@@ -0,0 +1,77 @@
+---
+layout: page
+title: "Generic Platform Discovery"
+description: "Using generic platform discovery."
+date: 2016-05-12 22:00 -02:00
+sidebar: true
+comments: false
+sharing: true
+footer: true
+---
+
+New controller or hub components often need to add platforms in sub-components (i.e. Lights & Switches) without additional configuration.
+This can be achieved using the `load_platform` or `async_load_platform` methods from `homeassistant.helpers.discovery`:
+
+```python
+def load_platform(hass, component, platform, discovered=None, hass_config=None)
+```
+
+From more info on how this works, refer to the [load_platform](https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/helpers/discovery.py#L136) method.
+
+### {% linkable_title Example %}
+
+Say you need to implement your new MyFlashyHub that controls both Switches & Lights, you can follow these steps:
+
+Configuration required for your new hub component:
+
+```yaml
+myflashyhub:
+ example: setting
+```
+
+The source for your component can be located in your configuration directory for now:
+
+```bash
+~/.homeassistant/custom_components/myflashyhub.py
+~/.homeassistant/custom_components/light/myflashyhub.py
+~/.homeassistant/custom_components/switch/myflashyhub.py
+```
+
+In the hub component `myflashyhub.py` you can call your light and switch components. To pass any non-serializable information to the platforms in the sub-component, you can use a global variable.
+
+```python
+from homeassistant.helpers.discovery import load_platform
+DOMAIN = 'myflashyhub'
+
+DATA_MFH = 'MFH'
+
+def setup(hass, config):
+ """Your controller/hub specific code."""
+ hass.data[DATA_MFH] = SomeObjectToInitialiseGlobal()
+
+ #--- snip ---
+ load_platform(hass, 'light', DOMAIN)
+ load_platform(hass, 'switch', DOMAIN, {'optional': 'arguments'})
+```
+
+Add your custom device specific code to the `setup_platform` method in `light/myflashyhub.py` and `switch/myflashyhub`.
+
+```python
+import custom_components.myflashyhub as myflashyhub
+
+# 'switch' will receive discovery_info={'optional': 'arguments'}
+# as passed in above. 'light' will receive discovery_info=None
+def setup_platform(hass, config, add_devices, discovery_info=None):
+ """Your switch/light specific code."""
+ # You can now use hass.data[myflashyhub.DATA_MFH]
+```
+
+
+The `load_platform` method allows the platforms to be loaded without the need for any additional platform entries in your `configuration.yaml` file, which normally would have been:
+
+```yaml
+#light:
+# platform: myflashyhub
+#switch:
+# platform: myflashyhub
+```
diff --git a/docs/component_loading.md b/docs/component_loading.md
new file mode 100644
index 00000000000..b817fadf382
--- /dev/null
+++ b/docs/component_loading.md
@@ -0,0 +1,25 @@
+---
+layout: page
+title: "Loading your components"
+description: "Instructions on how to get your component loaded by Home Assistant."
+date: 2016-04-16 13:32
+sidebar: true
+comments: false
+sharing: true
+footer: true
+---
+
+A component will be loaded on start if a section (ie. `light:`) for it exists in the config file. A component can also be loaded if another component is loaded that depends on it. When loading a component Home Assistant will check the following paths:
+
+ * `/custom_components/`
+ * `homeassistant/components/` (built-in components)
+
+Once loaded, a component will only be setup if all dependencies can be loaded and are able to setup. Keep an eye on the logs to see if your component could be loaded and initialized.
+
+
+You can override a built-in component by having a component with the same name in your config/custom_components folder. If the built-in component is inside a subfolder, take care to place your customization in a folder with the same name in config/custom_components/*folder*. Note that overriding built-in components is not recommended and will probably break things!
+
+
+
+Home Assistant will use the directory that contains your config file as the directory that holds your customizations. By default this is the config folder in your current work directory. You can use a different folder by running Home Assistant with the --config argument: python3 homeassistant --config /YOUR/CONFIG/PATH/.
+
diff --git a/docs/component_states.md b/docs/component_states.md
new file mode 100644
index 00000000000..f89803699a9
--- /dev/null
+++ b/docs/component_states.md
@@ -0,0 +1,22 @@
+---
+layout: page
+title: "Handling states"
+description: "Instructions on how to handle states with your component."
+date: 2016-07-01 20:00
+sidebar: true
+comments: false
+sharing: true
+footer: true
+---
+
+It is the responsibility of the component to maintain the states of the devices in your domain. Each device should be a single state and, if possible, a group should be provided that tracks the combined state of the devices.
+
+A state can have several attributes that will help the frontend in displaying your state:
+
+- `friendly_name`: this name will be used as the name of the device
+- `entity_picture`: this picture will be shown instead of the domain icon
+- `unit_of_measurement`: this will be appended to the state in the interface
+- `hidden`: This is a suggestion to the frontend on if the state should be hidden
+
+These attributes are defined in [homeassistant.helpers.entity](https://github.com/home-assistant/home-assistant/blob/master/homeassistant/helpers/entity.py#L180).
+
diff --git a/docs/creating_components.md b/docs/creating_components.md
new file mode 100644
index 00000000000..f52629db8a4
--- /dev/null
+++ b/docs/creating_components.md
@@ -0,0 +1,27 @@
+---
+layout: page
+title: "Creating components"
+description: "Guidelines to get you create your first component for Home Assistant."
+date: 2014-12-21 13:32
+sidebar: true
+comments: false
+sharing: true
+footer: true
+---
+
+Alright, you're ready to make your first component. AWESOME. Don't worry, we've tried hard to keep it as easy as possible.
+
+### {% linkable_title Example component %}
+
+Add `hello_state:` to your `configuration.yaml` file and create a file `/custom_components/hello_state.py` with the below code to test it locally.
+
+```python
+DOMAIN = 'hello_state'
+
+def setup(hass, config):
+ hass.states.set('hello.world', 'Paulus')
+
+ return True
+```
+
+For more examples, see the [Custom Python Component Examples](/cookbook/#custom-python-component-examples) on our examples page.
diff --git a/docs/development.md b/docs/development.md
new file mode 100644
index 00000000000..8bc614295d1
--- /dev/null
+++ b/docs/development.md
@@ -0,0 +1,31 @@
+---
+layout: page
+title: "Starting with Development"
+description: "Everything to get you started developing for Home Assistant."
+date: 2014-12-21 13:32
+sidebar: true
+comments: false
+sharing: true
+footer: true
+---
+
+Home Assistant is built from the ground up to be easily extensible using components. Home Assistant uses [Python 3](https://www.python.org/) for the backend and [Polymer (Web components)](https://www.polymer-project.org/) for the frontend.
+
+Home Assistant is open-source and licensed under [Apache 2.0](http://www.apache.org/licenses/LICENSE-2.0). Here are links to the source:
+
+ - [home-assistant](https://github.com/home-assistant/home-assistant): Python server backend.
+ - [home-assistant-polymer](https://github.com/home-assistant/home-assistant-polymer): Polymer UI.
+
+For those new to contributing to open source software, make sure you are familiar with all of the tools and concepts used in Home Assistant before you start.
+
+When contributing Home Assistant code:
+ - [Github](https://guides.github.com/activities/hello-world/)
+ - [Pip and Virtual Environments](https://www.dabapps.com/blog/introduction-to-pip-and-virtualenv-python/)
+ - [Python 3](https://www.python.org/)
+ - [Pylint](https://www.pylint.org)
+ - [Flake8](http://flake8.pycqa.org/en/latest/)
+ - [Tox](http://tox.readthedocs.org/en/latest/)
+ - [TravisCl](https://travis-ci.org/)
+
+When contributing 3rd Party code to be used by Home Assistant:
+ - [Publishing your own PyPI package](https://jeffknupp.com/blog/2013/08/16/open-sourcing-a-python-project-the-right-way/)
diff --git a/docs/development_101.md b/docs/development_101.md
new file mode 100644
index 00000000000..5db0cdf1287
--- /dev/null
+++ b/docs/development_101.md
@@ -0,0 +1,57 @@
+---
+layout: page
+title: "Development 101"
+description: "Introduction to the basics of Home Assistant."
+date: 2017-05-13 05:40:00 +0000
+sidebar: true
+comments: false
+sharing: true
+footer: true
+---
+
+The goal of development 101 is to get you familiar with the basics of developing for Home Assistant. Before we start, please make sure you familiarize yourself with the [architecture].
+
+To get our code running inside Home Assistant we're going to create a custom component. The first step is to locate your config folder. You can find the path to your config folder by opening the Home Assistant frontend, click on the . It's the path after the text "Path to configuration.yaml".
+
+Inside your configuration directory create a new folder called `custom_components`. It might be that one already exists, that's fine too. This is the folder that Home Assistant will look at when looking for custom code.
+
+
+The Home Assistant API has two variants: a synchronous and an asynchronous version (asyncio). This development course will focus on the synchronous version.
+
+
+To verify that everything is working correctly, let's create a small Hello World component. To do so, create a file called `hello_world.py` in your custom components folder. Copy paste the following content to it:
+
+```python
+# The domain of your component. Equal to the filename of your component.
+DOMAIN = "hello_world"
+
+
+def setup(hass, config):
+ """Setup the hello_world component."""
+ # States are in the format DOMAIN.OBJECT_ID.
+ hass.states.set('hello_world.Hello_World', 'Works!')
+
+ # Return boolean to indicate that initialization was successfully.
+ return True
+```
+
+Last step is to add `hello_world:` entry to your `configuration.yaml` file.
+
+```yaml
+# Hello World component
+hello_world:
+```
+
+After running `hass`, we should see log entries stating that `hello_world` component was loaded. What is more, additional state card shall appear within main panel.
+
+```log
+2018-04-03 21:44:20 INFO (MainThread) [homeassistant.loader] Loaded hello_world from custom_components.hello_world
+2018-04-03 21:44:20 INFO (MainThread) [homeassistant.setup] Setting up hello_world
+```
+
+
+
+State card showing that Hello World component is working as intended.
+
+
+[architecture]: /developers/architecture/
diff --git a/docs/development_catching_up.md b/docs/development_catching_up.md
new file mode 100644
index 00000000000..88f4b73e078
--- /dev/null
+++ b/docs/development_catching_up.md
@@ -0,0 +1,41 @@
+---
+layout: page
+title: "Catching up with Reality"
+description: "Update your fork with the latest commit."
+date: 2016-07-01 20:00
+sidebar: true
+comments: false
+sharing: true
+footer: true
+---
+
+If it's taking a while to develop your feature, and you want to catch up with what's in the current Home Assistant `dev` branch, you can use `git rebase`. This will pull the latest Home Assistant changes locally, rewind your commits, bring in the latest changes from Home Assistant, and replay all of your commits on top.
+
+```bash
+# Run this from your feature branch
+$ git fetch upstream dev # to pull the latest changes into a local dev branch
+$ git rebase upstream/dev # to put those changes into your feature branch before your changes
+```
+
+If rebase detects conflicts, repeat this process until all changes have been resolved:
+
+1. `git status` shows you the file with the conflict; edit the file and resolve the lines between `<<<< | >>>>`
+3. Add the modified file: `git add ` or `git add .`
+4. Continue rebase: `git rebase --continue`
+5. Repeat until you've resolved all conflicts
+
+After rebasing your branch, you will have rewritten history relative to your GitHub fork's branch. When you go to push you will see an error that your history has diverged from the original branch. In order to get your GitHub fork up-to-date with your local branch, you will need to force push, using the following command:
+
+```bash
+# Run this from your feature branch
+$ git push origin --force
+```
+
+Other workflows are covered in detail in the [Github documentation](https://help.github.com/articles/fork-a-repo/). Add an additional `remote` after you clone your fork.
+
+```bash
+$ git remote add upstream https://github.com/home-assistant/home-assistant.git
+```
+
+Then, `git pull --rebase upstream dev`.
+
diff --git a/docs/development_checklist.md b/docs/development_checklist.md
new file mode 100644
index 00000000000..3fe199b8eab
--- /dev/null
+++ b/docs/development_checklist.md
@@ -0,0 +1,20 @@
+---
+layout: page
+title: "Development Checklist"
+description: "Overview of the requirements for an improvement for Home Assistant."
+date: 2016-07-01 20:00
+sidebar: true
+comments: false
+sharing: true
+footer: true
+---
+
+
+Before you commit any changes, check your work against these requirements:
+
+- All dependencies from [pypi](https://pypi.python.org/pypi) are included via the `REQUIREMENTS` variable in your platform or component and only imported inside functions that use them
+- New dependencies are added to `requirements_all.txt` (if applicable), using `script/gen_requirements_all.py`
+- The `.coveragerc` file is updated to exclude your platform if there are no tests available or your new code uses a third-party library for communication with the device, service, or sensor
+- Documentation is developed for [home-assistant.io](/)
+ * It's OK to start with adding a docstring with configuration details (for example, sample entry for `configuration.yaml` file) to the file header. Visit the [website documentation](/developers/documentation/) for more information about contributing to [home-assistant.io](https://github.com/home-assistant/home-assistant.github.io).
+
diff --git a/docs/development_config.md b/docs/development_config.md
new file mode 100644
index 00000000000..56382ecb615
--- /dev/null
+++ b/docs/development_config.md
@@ -0,0 +1,35 @@
+---
+layout: page
+title: "Using Config"
+description: "Introduction to the Config object in Home Assistant."
+date: 2017-05-13 05:40:00 +0000
+sidebar: true
+comments: false
+sharing: true
+footer: true
+---
+
+Based on where you are in the code, `config` can mean various things.
+
+### {% linkable_title On the hass object %}
+
+On the hass object is an instance of the Config class. The Config class contains the users preferred units, the path to the config directory and which components are loaded. [See available methods.](https://dev-docs.home-assistant.io/en/master/api/core.html#homeassistant.core.Config)
+
+### {% linkable_title Config passed into component setup %}
+
+The `config` parameter passed to a component setup is a dictionary containing all of the user supplied configuration. The keys of the dictionary are the component names and the value is another dictionary with the component configuration.
+
+The object will have already been validated using your `CONFIG_SCHEMA` or `PLATFORM_SCHEMA` if available. If you have defined a `PLATFORM_SCHEMA`, all references to your component (ie `light 2:` etc) will have been changed to be accessible as a list under `config[DOMAIN]`.
+
+If your configuration file contains the following lines:
+
+```yaml
+example:
+ host: paulusschoutsen.nl
+```
+
+Then in the setup method of your component you will be able to refer to `config['example']['host']` to get the value `paulusschoutsen.nl`.
+
+### {% linkable_title Passed into platform setup %}
+
+The `config` parameter passed to a platform setup function is only the config for that specific platform.
diff --git a/docs/development_environment.md b/docs/development_environment.md
new file mode 100644
index 00000000000..b198bebbbbd
--- /dev/null
+++ b/docs/development_environment.md
@@ -0,0 +1,110 @@
+---
+layout: page
+title: "Set up Development Environment"
+description: "Set up your environment to start developing for Home Assistant."
+date: 2014-12-21 13:32
+sidebar: true
+comments: false
+sharing: true
+footer: true
+---
+
+You'll need to set up a development environment if you want to develop a new feature or component for Home Assistant. Read on to learn how to set up.
+
+### {% linkable_title Preparing your environment %}
+
+#### {% linkable_title Developing on Linux %}
+
+Install the core dependencies.
+
+```bash
+$ sudo apt-get install python3-pip python3-dev python3-venv
+```
+
+In order to run `script/setup` below you will need some more dependencies.
+
+```bash
+$ sudo apt-get install libssl-dev libxml2-dev libxslt1-dev libjpeg-dev libffi-dev libudev-dev zlib1g-dev
+```
+
+
+Different distributions have different package installation mechanisms and sometimes packages names as well. For example Centos would use: `sudo yum install epel-release && sudo yum install python34 python34-devel mysql-devel`
+
+
+Additional dependencies exist if you plan to perform Frontend Development, please read the [Frontend](/developers/frontend/) section to learn more.
+
+#### {% linkable_title Developing on Windows %}
+
+If you are using Windows as a development platform, make sure that you have the correct Microsoft [Visual C++ build tools](http://landinghub.visualstudio.com/visual-cpp-build-tools) installed. The installation of the most requirements and validation using `tox` will fail if this is not done correctly. Check the [Windows Compilers](https://wiki.python.org/moin/WindowsCompilers) section on the [Python website](https://www.python.org/) for details.
+
+Due to Home Assistant is mainly designed and developed on Linux distributions it is not recommended to develop on Windows machines. However on Windows 10 machines you should decide to set up a [Linux subsystem](https://docs.microsoft.com/de-de/windows/wsl/install-win10).
+
+Setup Linux subsystem.
+
+```bash
+$ apt-get update
+$ apt-get upgrade
+$ echo 'export DISPLAY=:0' >> ~/.bashrc && . ~/.bashrc
+$ sudo apt-get install xubuntu-desktop -y
+```
+
+It is recommended using [PyCharm](https://www.jetbrains.com/pycharm/download/) as debugger. Download and start PyCharm.
+
+```bash
+$ wget https://download.jetbrains.com/python/pycharm-community-20XX.X.tar.gz
+$ tar -xzf pycharm-community-20XX.X
+$ ./pycharm.sh
+```
+
+In order to display the PyCharm GUI on Windows you need to run a X-Server like [VcXserv](https://sourceforge.net/projects/vcxsrv/).
+
+Also, make sure to install or upgrade the `setuptools` Python package. It contains compatibility improvements and adds automatic use of compilers:
+
+```bash
+$ pip install --upgrade setuptools
+```
+
+#### {% linkable_title Developing on OS X %}
+
+Install [Homebrew](https://brew.sh/), then use that to install Python 3:
+
+```bash
+$ brew install python3
+```
+
+### {% linkable_title Setup Local Repository %}
+
+Visit the [Home Assistant repository](https://github.com/home-assistant/home-assistant) and click **Fork**.
+Once forked, setup your local copy of the source using the commands:
+
+```bash
+$ git clone https://github.com/YOUR_GIT_USERNAME/home-assistant.git
+$ cd home-assistant
+$ git remote add upstream https://github.com/home-assistant/home-assistant.git
+```
+
+### {% linkable_title Setting up virtual environment %}
+
+To isolate your environment from the rest of the system, set up a [`venv`](https://docs.python.org/3/library/venv.html). Within the `home-assistant` directory, create and activate your virtual environment.
+
+```bash
+$ python3 -m venv .
+$ source bin/activate
+```
+Install the requirements with a provided script named `setup`.
+
+```bash
+$ script/setup
+```
+
+Invoke your installation.
+
+```bash
+$ hass
+```
+
+### {% linkable_title Logging %}
+
+By default logging in home-assistant is tuned for operating in production (set to INFO by default, with some modules set to even less verbose logging levels).
+
+You can use the [logger](/components/logger/) component to adjust logging to DEBUG to see even more details about what is going on.
diff --git a/docs/development_events.md b/docs/development_events.md
new file mode 100644
index 00000000000..e078396fd05
--- /dev/null
+++ b/docs/development_events.md
@@ -0,0 +1,62 @@
+---
+layout: page
+title: "Using Events"
+description: "Introduction to using events in Home Assistant."
+date: 2017-05-13 05:40:00 +0000
+sidebar: true
+comments: false
+sharing: true
+footer: true
+---
+
+The core of Home Assistant is driven by events. That means that if you want to respond to something happening, you'll have to respond to events. Most of the times you won't interact directly with the event system but use one of the [event listener helpers][helpers].
+
+The event system is very flexible. There are no limitations on the event type, as long as it's a string. Each event can contain data. The data is a dictionary that can contain any data as long as it's JSON serializable. This means that you can use number, string, dictionary and list.
+
+[List of events that Home Assistant fires.][object]
+
+### {% linkable_title Firing events %}
+
+To fire an event, you have to interact with the event bus. The event bus is available on the Home Assistant instance as `hass.bus`.
+
+Example component that will fire an event when loaded.
+
+```python
+DOMAIN = 'hello_event'
+
+def setup(hass, config):
+ """Set up is called when Home Assistant is loading our component."""
+
+ # Fire event my_cool_event with event data answer=42
+ hass.bus.fire('my_cool_event', {
+ 'answer': 42
+ })
+```
+
+### {% linkable_title Listening to events %}
+
+Most of the times you'll not be firing events but instead listen to events. For example, the state change of an entity is broadcasted as an event.
+
+```python
+DOMAIN = 'hello_event'
+
+def setup(hass, config):
+ """Set up is called when Home Assistant is loading our component."""
+ count = 0
+
+ # Listener to handle fired events
+ def handle_event(event):
+ nonlocal count
+ count += 1
+ print('Total events received:', count)
+
+ # Listen for when my_cool_event is fired
+ hass.bus.listen('my_cool_event', handle_event)
+```
+
+#### {% linkable_title Helpers %}
+
+Home Assistant comes with a lot of bundled helpers to listen to specific types of event. There are helpers to track a point in time, to track a time interval, a state change or the sun set. [See available methods.][helpers]
+
+[helpers]: https://dev-docs.home-assistant.io/en/master/api/helpers.html#module-homeassistant.helpers.event
+[object]: /docs/configuration/events/
diff --git a/docs/development_guidelines.md b/docs/development_guidelines.md
new file mode 100644
index 00000000000..7e4088249ce
--- /dev/null
+++ b/docs/development_guidelines.md
@@ -0,0 +1,81 @@
+---
+layout: page
+title: "Style guidelines"
+description: "Details about styling your code."
+date: 2017-04-28 20:00
+sidebar: true
+comments: false
+sharing: true
+footer: true
+---
+
+Home Assistant enforces strict [PEP8 style](https://www.python.org/dev/peps/pep-0008/) and [PEP 257 (Docstring Conventions)](https://www.python.org/dev/peps/pep-0257/) compliance on all code submitted. We automatically test every pull request as part of the linting process with [Coveralls](https://coveralls.io/github/home-assistant/home-assistant) and [Travis CI](https://travis-ci.org/home-assistant/home-assistant).
+
+Summary of the most relevant points:
+
+- Line length is limited to 79 characters (see below).
+- Use 4 spaces per indentation level. We don't use tabs.
+- Comments should be full sentences and end with a period.
+- [Imports](https://www.python.org/dev/peps/pep-0008/#imports) should be ordered.
+- Constants and the content of lists and dictionaries should be in alphabetical order.
+- Avoid trailing whitespace but surround binary operators with a single space.
+- Line separator should be set to `LF`.
+
+The maximum line length comes directly from the [PEP8 style guide](https://www.python.org/dev/peps/pep-0008/#maximum-line-length), and is also used by the Python standard library. All code must pass these linting checks, and no exceptions will be made. There have already been numerous requests to increase the maximum line length, but after evaluating the options, the Home Assistant maintainers have decided to stay at 79 characters. This decision is final.
+
+Those points may require that you adjust your IDE or editor settings.
+
+## {% linkable_title Our recommendations %}
+
+For some cases [PEPs](https://www.python.org/dev/peps/) don't make a statement. This section covers our recommendations about the code style. Those points were collected from the existing code and based on what contributors and developers were using the most. This is basically a majority decision, thus you may not agree with it. But we would like to encourage you follow those recommendations to keep the code unified.
+
+### {% linkable_title Quotes %}
+
+Use single quotes `'` for single word and `"` for multiple words or sentences.
+
+```python
+ATTR_WATERLEVEL = 'level'
+CONF_ATTRIBUTION = "Data provided by the WUnderground weather service"
+SENSOR_TYPES = {
+ 'alerts': ['Alerts', None],
+}
+```
+
+### {% linkable_title File headers %}
+
+The docstring in the file header should contain a link to the documentation to make it easy to find further information, especially about the configuration or details which are not mentioned in the code.
+
+```python
+"""
+Support for MQTT lights.
+
+For more details about this platform, please refer to the documentation at
+https://home-assistant.io/components/light.mqtt/
+"""
+```
+
+### {% linkable_title Requirements %}
+
+Please place [Platform requirements](/developers/code_review_platform/#1-requirements) right after the imports.
+
+```python
+[...]
+from homeassistant.helpers.entity import Entity
+
+REQUIREMENTS = ['xmltodict==0.11.0']
+```
+
+### {% linkable_title Log messages %}
+
+There is no need to add the platform or component name to the log messages. This will be added automatically. Like `syslog` messages there shouldn't be any period at the end. Try to avoid brackets and additional quotes around the output to make it easier for users to parse the log. A widely style is shown below but you are free to compose the messages as you like.
+
+```python
+_LOGGER.error("No route to device: %s", self._resource)
+```
+
+```bash
+2017-05-01 14:28:07 ERROR [homeassistant.components.sensor.arest] No route to device: 192.168.0.18
+```
+
+Don't print out wrong API keys, tokens, usernames, or passwords.
+Also note that `_LOGGER.info` is reserved for the core, use `_LOGGER.debug` in anything else.
diff --git a/docs/development_hass_object.md b/docs/development_hass_object.md
new file mode 100644
index 00000000000..d4a5926d2ec
--- /dev/null
+++ b/docs/development_hass_object.md
@@ -0,0 +1,38 @@
+---
+layout: page
+title: "Hass object"
+description: "Introduction to developing with the hass object."
+date: 2016-04-16 13:32
+sidebar: true
+comments: false
+sharing: true
+footer: true
+redirect_from: /developers/component_initialization/
+---
+
+While developing Home Assistant you will see a variable that is everywhere: `hass`. This is the Home Assistant instance that will give you access to all the various parts of the system.
+
+### {% linkable_title The `hass` object %}
+
+The Home Assistant instance contains four objects to help you interact with the system.
+
+| Object | Description |
+| ------ | ----------- |
+| `hass` | This is the instance of Home Assistant. Allows starting, stopping and enqueing new jobs. [See available methods.](https://dev-docs.home-assistant.io/en/master/api/core.html#homeassistant.core.HomeAssistant)
+| `hass.config` | This is the core configuration of Home Assistant exposing location, temperature preferences and config directory path. [See available methods.](https://dev-docs.home-assistant.io/en/master/api/core.html#homeassistant.core.Config)
+| `hass.states` | This is the StateMachine. It allows you to set states and track when they are changed. [See available methods.](https://dev-docs.home-assistant.io/en/master/api/core.html#homeassistant.core.StateMachine). |
+| `hass.bus` | This is the EventBus. It allows you to trigger and listen for events. [See available methods.](https://dev-docs.home-assistant.io/en/master/api/core.html#homeassistant.core.EventBus). |
+| `hass.services` | This is the ServiceRegistry. It allows you to register services. [See available methods.](https://dev-docs.home-assistant.io/en/master/api/core.html#homeassistant.core.ServiceRegistry). |
+
+### {% linkable_title Where to find `hass` %}
+
+Depending on what you're writing, there are different ways the `hass` object is made available.
+
+**Component**
+Passed into `setup(hass, config)` or `async_setup(hass, config)`.
+
+**Platform**
+Passed into `setup_platform(hass, config, add_devices, discovery_info=None)` or `async_setup_platform(hass, config, async_add_devices, discovery_info=None)`.
+
+**Entity**
+Available as `self.hass` once the entity has been added via the `add_devices` callback inside a platform.
diff --git a/docs/development_services.md b/docs/development_services.md
new file mode 100644
index 00000000000..1aa11397ede
--- /dev/null
+++ b/docs/development_services.md
@@ -0,0 +1,55 @@
+---
+layout: page
+title: "Using Services"
+description: "Introduction to services in Home Assistant."
+date: 2017-05-13 05:40:00 +0000
+sidebar: true
+comments: false
+sharing: true
+footer: true
+---
+
+This is a simple "hello world" example to show the basics of registering a service. To use this example, create the file `/custom_components/hello_service.py` and copy the below example code.
+
+Services can be called from automation and from the service "Developer tools" in the frontend.
+
+```python
+# The domain of your component. Should be equal to the name of your component.
+DOMAIN = 'hello_service'
+
+ATTR_NAME = 'name'
+DEFAULT_NAME = 'World'
+
+
+def setup(hass, config):
+ """Set up is called when Home Assistant is loading our component."""
+
+ def handle_hello(call):
+ name = call.data.get(ATTR_NAME, DEFAULT_NAME)
+
+ hass.states.set('hello_service.hello', name)
+
+ hass.services.register(DOMAIN, 'hello', handle_hello)
+
+ # Return boolean to indicate that initialization was successfully.
+ return True
+```
+
+Load the component by adding the following to your `configuration.yaml`. When your component is loaded, a new service should be available to call.
+
+```yaml
+# configuration.yaml entry
+hello_service:
+```
+
+Open the frontend and in the sidebar, click the first icon in the developer tool section. This will open the Call Service developer tool. On the right, find your service and click on it. This will automatically fill in the correct values.
+
+Pressing "Call Service" will now call your service without any parameters. This will cause your service to create a state with the default name 'World'. If you want to specify the name, you have to specify parameters. Add the following JSON as Service Data and press "Call Service again".
+
+```json
+{
+ "name": "Planet"
+}
+```
+
+The service will now overwrite the previous state with "Planet".
diff --git a/docs/development_states.md b/docs/development_states.md
new file mode 100644
index 00000000000..e1161ffccad
--- /dev/null
+++ b/docs/development_states.md
@@ -0,0 +1,140 @@
+---
+layout: page
+title: "Using States"
+description: "Introduction to states in Home Assistant."
+date: 2017-05-13 05:40:00 +0000
+sidebar: true
+comments: false
+sharing: true
+footer: true
+---
+
+Home Assistant keeps track of the states of entities in a state machine. The state machine has very few requirements:
+
+ - Each state is related to an entity identified by an entity id. This id is made up of a domain and an object id. For example `light.kitchen_ceiling`. You can make up any combination of domain and object id, even overwriting existing states.
+ - Each state has a primary attribute that describes the state of the entity. In the case of a light this could be for example "on" and "off". You can store anything you want in the state, as long as it's a string (will be converted if it's not).
+ - You can store more information about an entity by setting attributes. Attributes is a dictionary that can contain any data that you want. The only requirement is that it's JSON serializable, so you're limited to numbers, strings, dictionaries and lists.
+
+[Description of the state object.](/docs/configuration/state_object/)
+
+### {% linkable_title Using states in your component %}
+
+This is a simple tutorial/example on how to create and set states. We will do our work in a component called "hello_state". The purpose of this component is to display a given text in the frontend.
+
+To get started, create the file `/custom_components/hello_state.py` and copy the below example code.
+
+```python
+"""
+Support for showing text in the frontend.
+
+For more details about this component, please refer to the documentation at
+https://home-assistant.io/cookbook/python_component_basic_state/
+"""
+import logging
+
+_LOGGER = logging.getLogger(__name__)
+
+DOMAIN = 'hello_state'
+DEPENDENCIES = []
+
+def setup(hass, config):
+ """Setup the Hello State component. """
+ _LOGGER.info("The 'hello state' component is ready!")
+
+ return True
+```
+
+1. In the file header we decided to add some details: A short description and the link to the documentation.
+2. We want to do some logging. This means that we import the Python logging module and create an alias.
+3. The component name is equal to the domain name.
+4. At the moment this component has no dependencies. For detail check [dependencies](/developers/component_deps_and_reqs/#dependencies) section.
+5. The `setup` function will take care of the initialization of our component.
+ The component will only write a log message. Keep in mind for later that you have several options for the severity:
+
+ - `_LOGGER.info(msg)`
+ - `_LOGGER.warning(msg)`
+ - `_LOGGER.error(msg)`
+ - `_LOGGER.critical(msg)`
+ - `_LOGGER.exception(msg)`
+
+7. We return `True` if everything is ok.
+
+Add the component to your `configuration.yaml` file.
+
+```yaml
+hello_state:
+```
+
+After a start or a restart of Home Assistant the component will create an entry in the log.
+
+```bash
+16-03-12 14:16:42 INFO (MainThread) [custom_components.hello_state] The 'hello state' component is ready!
+```
+
+The next step is the introduction of configuration options. A user can pass configuration options to our component via `configuration.yaml`. To use them we'll use the passed in `config` variable to our `setup` method.
+
+```python
+import logging
+
+_LOGGER = logging.getLogger(__name__)
+
+DOMAIN = 'hello_state'
+DEPENDENCIES = []
+
+CONF_TEXT = 'text'
+DEFAULT_TEXT = 'No text!'
+
+def setup(hass, config):
+ """Set up the Hello State component. """
+ # Get the text from the configuration. Use DEFAULT_TEXT if no name is provided.
+ text = config[DOMAIN].get(CONF_TEXT, DEFAULT_TEXT)
+
+ # States are in the format DOMAIN.OBJECT_ID
+ hass.states.set('hello_state.Hello_State', text)
+
+ return True
+```
+
+To use the latest feature of our component, update the entry in your `configuration.yaml` file.
+
+```yaml
+hello_state:
+ text: 'Hello, World!'
+```
+
+Thanks to `DEFAULT_TEXT` variable the component will launch even if no `text:` field is used in the `configuration.yaml` file. Quite often there are variables which are required. It's important to check if all mandatory configuration variables are provided. If not, the setup should fail. We will use `voluptuous` as a helper to achieve this. The next listing shows the essential parts.
+
+```python
+import voluptuous as vol
+
+import homeassistant.helpers.config_validation as cv
+
+CONFIG_SCHEMA = vol.Schema({
+ DOMAIN: vol.Schema({
+ vol.Required(CONF_TEXT): cv.string,
+ })
+}, extra=vol.ALLOW_EXTRA)
+```
+
+Now, when `text:` is missing from the config, Home Assistant will alert the user and not setup your component.
+
+After a start or a restart of Home Assistant the component will be visible in the frontend if the `configuration.yaml` file is up-to-date.
+
+
+
+
+
+In order to expose attributes for a platform, you will need to define a property called `device_state_attributes` on the entity class, which will return a dictionary of attributes:
+
+```
+@property
+def device_state_attributes(self):
+ """Return device specific state attributes."""
+ return self._attributes
+```
+
+
+Entities also have a similar property `state_attributes`, which normally doesn't need to be defined by new platforms. This property is used by base components to add standard sets of attributes to a state. Example: The light component uses `state_attributes` to add brightness to the state dictionary. If you are designing a new component, you should define `state_attributes` instead.
+
+
+To get your component included in the Home Assistant releases, follow the steps described in the [Submit your work](/developers/development_submitting/) section. Basically you only need to move your component in the `homeassistant/component/` directory of your fork and create a Pull Request.
diff --git a/docs/development_submitting.md b/docs/development_submitting.md
new file mode 100644
index 00000000000..b1439e4551e
--- /dev/null
+++ b/docs/development_submitting.md
@@ -0,0 +1,47 @@
+---
+layout: page
+title: "Submit your work"
+description: "Submit your work as Pull Request for Home Assistant."
+date: 2016-07-01 20:00
+sidebar: true
+comments: false
+sharing: true
+footer: true
+---
+
+Submit your improvements, fixes, and new features to Home Assistant one at a time, using GitHub [Pull Requests](https://help.github.com/articles/using-pull-requests). Here are the steps:
+
+ 1. From your fork's dev branch, create a new branch to hold your changes:
+
+ `git checkout -b some-feature`
+
+ 2. Make your changes, create a [new platform](/developers/add_new_platform/), develop a [new component](/developers/creating_components/), or fix [issues](https://github.com/home-assistant/home-assistant/issues).
+
+ 3. [Test your changes](/developers/development_testing/) and check for style violations.
+
+ 4. If everything looks good according to these [musts](/developers/development_checklist/), commit your changes:
+
+ `git add .`
+
+ `git commit -m "Added some-feature"`
+
+ * Write a meaningful commit message and not only `Update` or `Fix`.
+ * Use a capital letter to start with your commit message.
+ * Don't prefix your commit message with `[bla.bla]` or `platform:`.
+ * Consider adding tests to ensure that your code works.
+
+ 5. Push your committed changes back to your fork on GitHub:
+
+ `git push origin HEAD`
+
+ 6. Follow [these steps](https://help.github.com/articles/creating-a-pull-request/) to create your pull request.
+
+ * On GitHub, navigate to the main page of the Home Assistant repository.
+ * In the "Branch" menu, choose the branch that contains your commits (from your fork).
+ * To the right of the Branch menu, click **New pull request**.
+ * Use the base branch dropdown menu to select the branch you'd like to merge your changes into, then use the compare branch drop-down menu to choose the topic branch you made your changes in. Make sure the Home Assistant branch matches with your forked branch (`dev`) else you will propose ALL commits between branches.
+ * Type a title and complete the provided description for your pull request.
+ * Click **Create pull request**.
+
+ 7. Check for comments and suggestions on your pull request and keep an eye on the [CI output](https://travis-ci.org/home-assistant/home-assistant/).
+
diff --git a/docs/development_testing.md b/docs/development_testing.md
new file mode 100644
index 00000000000..a4f462690dd
--- /dev/null
+++ b/docs/development_testing.md
@@ -0,0 +1,76 @@
+---
+layout: page
+title: "Testing your code"
+description: "Make sure that your code passes the checks"
+date: 2016-07-01 20:00
+sidebar: true
+comments: false
+sharing: true
+footer: true
+---
+
+As states in the [Style guidelines section](/developers/development_guidelines/) all code is checked to verify all unit tests pass and that the code passes the linting tools. Local testing is done using Tox, which has been installed as part of running `script/setup`. To start the tests, simply run it:
+
+```bash
+$ tox
+```
+**Important:** Run `tox` before you create your pull request to avoid annoying fixes.
+
+Running Tox will run unit tests against the locally available Pythons, as well as validate the code and document style using `pycodestyle`, `pydocstyle` and `pylint`. You can run tests on only one tox target -- just use `-e` to select an environment. For example, `tox -e lint` runs the linters only, and `tox -e py36` runs unit tests only on Python 3.6.
+
+Tox uses virtual environments under the hood to create isolated testing environments. The tox virtual environments will get out-of-date when requirements change, causing test errors. Run `tox -r` to tell Tox to recreate the virtual environments.
+
+If you are working on tests for a component or platform and you need the dependencies available inside the Tox environment, update the list inside `script/gen_requirements_all.py`. Then run the script and then run `tox -r` to recreate the virtual environments.
+
+### {% linkable_title Running single tests using Tox %}
+
+You can pass arguments via Tox to py.test to be able to run single test suites or test files. Replace `py36` with the Python version that you use.
+
+```bash
+# Stop after the first test fails
+$ tox -e py36 -- tests/test_core.py -x
+# Run test with specified name
+$ tox -e py36 -- tests/test_core.py -k test_split_entity_id
+# Fail a test after it runs for 2 seconds
+$ tox -e py36 -- tests/test_core.py --timeout 2
+# Show the 10 slowest tests
+$ tox -e py36 -- tests/test_core.py --duration=10
+```
+
+### {% linkable_title Testing outside of Tox %}
+
+Running tox will invoke the full test suite. Even if you specify which tox target to run, you still run all tests inside that target. That's not very convenient to quickly iterate on your code! To be able to run the specific test suites without Tox, you'll need to install the test dependencies into your Python environment:
+
+```bash
+$ pip3 install -r requirements_test_all.txt
+```
+
+Now that you have all test dependencies installed, you can run tests on individual files:
+
+```bash
+$ flake8 homeassistant/core.py
+$ pylint homeassistant/core.py
+$ pydocstyle homeassistant/core.py
+$ py.test tests/test_core.py
+```
+
+You can also run linting tests against all changed files, as reported by `git diff upstream/dev... --diff-filter=d --name-only`, using the `lint` script:
+
+```bash
+$ script/lint
+```
+
+### {% linkable_title Preventing Linter Errors %}
+
+Save yourself the hassle of extra commits just to fix style errors by enabling the Flake8 git commit hook. Flake8 will check your code when you try to commit to the repository and block the commit if there are any style errors, which gives you a chance to fix them!
+
+```bash
+$ pip3 install flake8 flake8-docstrings
+$ flake8 --install-hook=git
+```
+
+The `flake8-docstrings` extension will check docstrings according to [PEP257](https://www.python.org/dev/peps/pep-0257/) when running Flake8.
+
+### {% linkable_title Notes on PyLint and PEP8 validation %}
+
+If you can't avoid a PyLint warning, add a comment to disable the PyLint check for that line with `# pylint: disable=YOUR-ERROR-NAME`. Example of an unavoidable one is if PyLint incorrectly reports that a certain object doesn't have a certain member.
diff --git a/docs/development_validation.md b/docs/development_validation.md
new file mode 100644
index 00000000000..30b3dc77a86
--- /dev/null
+++ b/docs/development_validation.md
@@ -0,0 +1,87 @@
+---
+layout: page
+title: "Validate the input"
+description: "Validation of entries in configuration.yaml"
+date: 2016-08-11 20:00
+sidebar: true
+comments: false
+sharing: true
+footer: true
+---
+
+The `configuration.yaml` file contains the configuration options for components and platforms. We use [voluptuous](https://pypi.python.org/pypi/voluptuous) to make sure that the configuration provided by the user is valid. Some entries are optional or could be required to set up a platform or a component. Others must be a defined type or from an already-defined list.
+
+We test the configuration to ensure that users have a great experience and minimize notifications if something is wrong with a platform or component setup before Home Assistant runs.
+
+Besides [voluptuous](https://pypi.python.org/pypi/voluptuous) default types, many custom types are available. For an overview, take a look at the [config_validation.py](https://github.com/home-assistant/home-assistant/blob/master/homeassistant/helpers/config_validation.py) helper.
+
+- Types: `string`, `byte`, and `boolean`
+- Entity ID: `entity_id` and `entity_ids`
+- Numbers: `small_float` and `positive_int`
+- Time: `time`, `time_zone`
+- Misc: `template`, `slug`, `temperature_unit`, `latitude`, `longitude`, `isfile`, `sun_event`, `ensure_list`, `port`, `url`, and `icon`
+
+To validate platforms using [MQTT](/components/mqtt/), `valid_subscribe_topic` and `valid_publish_topic` are available.
+
+Some things to keep in mind:
+
+- Use the constants defined in `const.py`
+- Import `PLATFORM_SCHEMA` from the parent component and extend it
+- Preferred order is `required` first and `optional` second
+- Starting with Home Assistant 0.64 `voluptuous` requires default values for optional configuration keys to be valid values. Don't use a default which is `None` like `vol.Optional(CONF_SOMETHING, default=None): cv.string`, set the default to `default=""` if required.
+
+### {% linkable_title Snippets %}
+
+This section contains snippets for the validation we use.
+
+#### {% linkable_title Default name %}
+
+It's common to set a default for a sensor if the user doesn't provide a name to use.
+
+```python
+DEFAULT_NAME = 'Sensor name'
+
+PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
+ ...
+ vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
+```
+
+#### {% linkable_title Limit the values %}
+
+You might want to limit the user's input to a couple of options.
+
+```python
+DEFAULT_METHOD = 'GET'
+
+PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
+ ...
+ vol.Optional(CONF_METHOD, default=DEFAULT_METHOD): vol.In(['POST', 'GET']),
+```
+
+#### {% linkable_title Port %}
+
+All port numbers are from a range of 1 to 65535.
+
+```python
+DEFAULT_PORT = 993
+
+PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
+ ...
+ vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port,
+```
+
+#### {% linkable_title Lists %}
+
+If a sensor has a pre-defined list of available options, test to make sure the configuration entry matches the list.
+
+```python
+SENSOR_TYPES = {
+ 'article_cache': ('Article Cache', 'MB'),
+ 'average_download_rate': ('Average Speed', 'MB/s'),
+}
+
+PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
+ ...
+ vol.Optional(CONF_MONITORED_VARIABLES, default=[]):
+ vol.All(cv.ensure_list, [vol.In(SENSOR_TYPES)]),
+```
diff --git a/docs/documentation_create_page.md b/docs/documentation_create_page.md
new file mode 100644
index 00000000000..cb0c4125198
--- /dev/null
+++ b/docs/documentation_create_page.md
@@ -0,0 +1,127 @@
+---
+layout: page
+title: "Create a new page"
+description: "Create a new page for the documentation"
+date: 2015-06-17 08:00
+sidebar: true
+comments: false
+sharing: true
+footer: true
+---
+
+For a platform or component page, the fastest way is to make a copy of an existing page and edit it. The [Component overview](/components/) and the [Examples section](/cookbook/) are generated automatically, so there is no need to add a link to those pages.
+
+Please honor the [Standards](/developers/documentation/standards/) we have for the documentation.
+
+If you start from scratch with a page, you need to add a header. Different sections of the documentation may need different headers.
+
+```text
+---
+layout: page
+title: "Awesome Sensor"
+description: "home-assistant.io web presence"
+date: 2015-06-17 08:00
+sidebar: true
+comments: false
+sharing: true
+footer: true
+ha_release: "0.38"
+ha_category: Sensor
+---
+
+Content...Written in markdown.
+
+{% raw %}### {% linkable_title Linkable Header %}{% endraw %}
+...
+```
+
+There are [pre-definied variables](https://jekyllrb.com/docs/variables/) available but usually, it's not necessary to use them when writing documentation.
+
+A couple of points to remember:
+
+- Document the needed steps to retrieve API keys or access token for the third party service or device if needed.
+- If you're adding a new component, for the `ha_release` part of the header, just increment of the current release. If the current release is 0.37, make `ha_release` 0.38. If it's 0.30 or 0.40 please quote it with `" "`.
+- `ha_category:` is needed to list the platform or component in the appropriate category on the website.
+
+### {% linkable_title Configuration %}
+
+Every platform page should contain a configuration sample. This sample must contain only the **required** variables to make it easy to copy and paste it for users into their `configuration.yaml` file.
+
+The **Configuration Variables** section must use the {% raw %}`{% configuration %} ... {% endconfiguration %}`{% endraw %} tag.
+
+{% raw %}
+```text
+{% configuration %}
+api_key:
+ description: The API key to access the service.
+ required: true
+ type: string
+name:
+ description: Name to use in the frontend.
+ required: false
+ default: The default name to use in the frontend.
+ type: string
+monitored_conditions:
+ description: Conditions to display in the frontend.
+ required: true
+ type: list
+ keys:
+ weather:
+ description: A human-readable text summary.
+ temperature:
+ description: The current temperature.
+{% endconfiguration %}
+
+```
+{% endraw %}
+
+Available keys:
+
+- **`description:`**: That the variable is about.
+- **`required:`**: If the variable is required.
+```text
+required: true #=> Required
+required: false #=> Optional
+required: inclusive #=> Inclusive
+required: exclusive #=> Exclusive
+required: any string here #=> Any string here
+```
+- **`type:`**: The type of the variable. Allowed entries: `string`, `int`, `time`, `template` or `map`. For multiple possibilities use `[string, int]`. If you use `map` then you need to define `keys:` (see the [`template` sensor](/components/sensor.template/) for an example).
+- **`default:`**: The default value for the variable.
+
+### {% linkable_title Embedding Code %}
+
+You can use the [default markdown syntax](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet#code) to generate syntax highlighted code. For inline code wrap your code in {% raw %}`{% endraw %}.
+
+When you're writing code that is to be executed on the terminal, prefix it with `$`.
+
+### {% linkable_title Templates %}
+
+For the [configuration templating](/topics/templating/) is [Jinja](http://jinja.pocoo.org/) used. Check the [Documentation Standards](/developers/documentation/standards/) for further details.
+
+If you are don't escape templates then they will be rendered and appear blank on the website.
+
+### {% linkable_title HTML %}
+
+The direct usage of HTML is supported but not recommended. The note boxes are an exception.
+
+```html
+
+ You need to enable telnet on your router.
+
+```
+
+### {% linkable_title Images, icons, and logos %}
+
+The images which are displayed on the pages are stored in various directories according to their purpose. If you want to use a logo and placed `logo:` in the file header then this image should be stored in `source/images/supported_brands`. The background must be transparent.
+
+| Type | Location |
+| :----------- |:----------------------------------------------|
+| logos | source/images/supported_brands |
+| blog | source/images/blog |
+| screenshots | source/images/components |
+
+Not everything (product, component, etc.) should have a logo. To show something for internal parts of Home Assistant we are using the [Material Design Icons](https://materialdesignicons.com/).
+
+### {% linkable_title Linking From The Sidebar %}
+If you are adding a new page that requires linking from the sidebar you need to edit the `docs_navigation.html` file in `home-assistant.github.io/source/_includes/asides/docs_navigation.html`.
diff --git a/docs/documentation_index.md b/docs/documentation_index.md
new file mode 100644
index 00000000000..50370c7802a
--- /dev/null
+++ b/docs/documentation_index.md
@@ -0,0 +1,44 @@
+---
+layout: page
+title: "Documentation Home Assistant"
+description: "home-assistant.io web presence for the documentation"
+date: 2015-06-17 08:00
+sidebar: true
+comments: false
+sharing: true
+footer: true
+redirect_from: /developers/website/
+---
+
+The website you are reading now is the home of Home Assistant: [https://www.home-assistant.io](/). This is the place where we provide documentation and additional details about Home Assistant for end users and developers.
+
+home-assistant.io is built using [Jekyll](http://github.com/mojombo/jekyll) and [these available dependencies](https://pages.github.com/versions/). The pages are written in [markdown](http://daringfireball.net/projects/markdown/). To add a page, you don't need to know about HTML.
+
+You can use the "**Edit this page on GitHub**" link to edit pages without creating a fork. Keep in mind that you can't upload images while working this way.
+
+For larger changes, we suggest that you clone the website repository. This way, you can review your changes locally. The process for working on the website is no different from working on Home Assistant itself. You work on your change and propose it via a pull request.
+
+To test your changes locally, you need to install **Ruby** and its dependencies (gems):
+
+- [Install Ruby](https://www.ruby-lang.org/en/documentation/installation/) if you don't have it already. Ruby version 2.3.0 or higher is required.
+- Install `bundler`, a dependency manager for Ruby: `$ gem install bundler`
+- In your home-assistant.github.io root directory, run `$ bundle` to install the gems you need.
+
+Short cut for Fedora: `$ sudo dnf -y install gcc-c++ ruby ruby-devel rubygem-bundler rubygem-json && bundle`
+
+Then you can work on the documentation:
+
+- Fork home-assistant.io [git repository](https://github.com/home-assistant/home-assistant.github.io).
+- Create/edit/update a page in the directory `source/_components/` for your platform/component.
+- Test your changes to home-assistant.io locally: run `rake preview` and navigate to [http://127.0.0.1:4000](http://127.0.0.1:4000)
+- Create a Pull Request (PR) against the **next** branch of home-assistant.github.io if your documentation is a new feature, platform, or component.
+- Create a Pull Request (PR) against the **current** branch of home-assistant.github.io if you fix stuff, create Cookbook entries, or expand existing documentation.
+
+
+It could be necessary that you run `rake generate` prior to `rake preview` for the very first preview.
+
+
+Site generated by `rake` is only available locally. If you are developing on a headless machine use port forwarding:
+`ssh -L 4000:localhost:4000 user_on_headless_machine@ip_of_headless_machine`
+
+
diff --git a/docs/documentation_standards.md b/docs/documentation_standards.md
new file mode 100644
index 00000000000..05b1223cc61
--- /dev/null
+++ b/docs/documentation_standards.md
@@ -0,0 +1,121 @@
+---
+layout: page
+title: "Documentation Standards"
+description: "Standards for the creation and maintenance of documentation for Home Assistant."
+date: 2017-09-16 03:51
+sidebar: true
+comments: false
+sharing: true
+footer: true
+---
+
+To ensure that the documentation for Home Assistant is consistent and easy to follow for both novice and expert users, we ask that you follow a very strict set of standards for developing the documentation.
+
+## {% linkable_title General Documentation %}
+
+* The language of the documentation should be American-English.
+* Don't put two spaces after a period and avoid the "Oxford comma".
+* Be objective and not gender favoring, polarizing, race related or religion inconsiderate.
+* The case of brand names, services, protocols, components, and platforms must match its respective counterpart. e.g., "Z-Wave" **not** "Zwave", "Z-wave", "Z Wave" or "ZWave". Also, "Input Select" **not** "input select" or "Input select".
+* All headings should use the {% raw %}`{% linkable_title %}`{% endraw %} tag.
+
+## {% linkable_title Component and Platform Pages %}
+
+* The **Configuration Variables** section must use the {% raw %}`{% configuration %}`{% endraw %} tag.
+* Configuration variables must document the requirement status.
+* Configuration variables must document the default value, if any.
+* Configuration variables must document the accepted value types.
+ * For configuration variables that accept multiple types, separate the types with a comma (i.e. `string, int`).
+* Use YAML sequence syntax in the sample code if it is supported.
+* All examples should be formatted to be included in `configuration.yaml` unless explicitly stated.
+ * Use capital letters and `_` to indicate that the value needs to be replaced. E.g., `api_key: YOUR_API_KEY` or `api_key: REPLACE_ME`.
+ * If you know that the API key or value contains [control characters](https://en.wikipedia.org/wiki/YAML#Syntax), e.g., `#`, `[`, `?`, etc., wrap it in quotes and add a note.
+* Component and platform names should be a link to their respective documentation pages.
+
+## {% linkable_title Templates %}
+
+* All examples containing Jinja2 templates should be wrapped **outside** of the code markdown with the {% raw %}`{% raw %}`{% endraw %} tag.
+* Do not use `states.switch.source.state` in templates. Instead use `states()` and `is_state()`.
+* Use double quotes (`"`) for ([more information](#single-vs-double-quotation-marks)):
+ * `friendly_name`
+ * Single-line templates:
+ * `value_template`
+ * `level_template`
+ * `icon_template`
+ * Children of `data_template`
+* Use single quotes (`'`) for ([more information](#single-vs-double-quotation-marks):
+ * Strings inside of templates:
+ * States
+ * Entity IDs
+ * `unit_of_measurement`
+* No whitespace around pipe character (`|`) for Jinja2 filters.
+* Single whitespace after Jinja2 opening delimiters ({% raw %}`{{`{% endraw %}).
+* Single whitespace before Jinja2 closing delimiters ({% raw %}`}}`{% endraw %}).
+* Do not quote values for:
+ * `device_class`
+ * `platform`
+ * `condition`
+ * `service`
+
+## {% linkable_title Renaming Pages %}
+
+It can happen that a component or platform is renamed, in this case the documentation needs to be updated as well. If you rename a page, add `redirect_from:` to the file header and let it point to the old location/name of the page. Please consider to add details, like release number or old component/platform name, to the page in a [note](/developers/documentation/create_page/#html).
+
+```text
+---
+...
+redirect_from: /getting-started/android/
+---
+```
+
+Adding a redirect also applies if you move content around in the [documentation](/docs/).
+
+## {% linkable_title Single vs. Double Quotation Marks %}
+
+Use single quotes (`'`) for strings inside of a template. It is more obvious to escape a single quote when necessary (i.e. `name` is a possessive noun), because the single quotes that wrap the string are closer in position to the apostrophe inside the string. Use double quotes (`"`) outside of a template (unless it is a multi-line template, in which case outside quotes are not required).
+
+### {% linkable_title Examples %}
+
+#### {% linkable_title Double Quotes Outside, Single Quotes Inside (Valid) %}
+
+{% raw %}
+```yaml
+automation:
+ ...
+ action:
+ - service: notify.notify
+ data_template:
+ message: "{% if trigger.to_state.name == 'Dale\'s Bedroom' %}Someone's in your base, killing your noobs!{% else %}It's just another door.{% endif %}"
+```
+{% endraw %}
+
+#### {% linkable_title Single Quotes Outside, Double Quotes Inside (Invalid) %}
+
+{% raw %}
+```yaml
+automation:
+ ...
+ action:
+ - service: notify.notify
+ data_template:
+ message: '{% if trigger.to_state.name == "Dale's Bedroom" %}Someone's in your base, killing your noobs!{% else %}It's just another door.{% endif %}'
+```
+{% endraw %}
+
+#### {% linkable_title Multi-Line Template (Valid) %}
+
+{% raw %}
+```yaml
+automation:
+ ...
+ action:
+ - service: notify.notify
+ data_template:
+ message: >-
+ {% if trigger.to_state.name == 'Dale\'s Bedroom' %}
+ Someone's in your base, killing your noobs!
+ {% else %}
+ It's just another door.
+ {% endif %}
+```
+{% endraw %}
diff --git a/docs/external_api_python.md b/docs/external_api_python.md
new file mode 100644
index 00000000000..818bb8d0771
--- /dev/null
+++ b/docs/external_api_python.md
@@ -0,0 +1,236 @@
+---
+layout: page
+title: "Python Remote API"
+description: "Home Assistant Python Remote API documentation"
+date: 2015-05-11 12:00
+sidebar: true
+comments: false
+sharing: true
+footer: true
+---
+
+See the [developer documentation][devdocs] for a full overview of the documentation. The rest of this page will contain examples on how to use it.
+
+[devdocs]: https://dev-docs.home-assistant.io/en/master/api/homeassistant.html#module-homeassistant.remote
+
+In the package [`homeassistant.remote`](https://github.com/home-assistant/home-assistant/blob/master/homeassistant/remote.py) a Python API on top of the [HTTP API](/developers/api/) can be found. If you are not using the [`frontend`](/components/frontend/) in your setup then you need to add the [`api` component](/components/api/) to your `configuration.yaml` file to use the Python Remote API.
+
+A simple way to get all current entities is to visit the "Set State" page in the "Developer Tools". For the examples below just choose one from the available entries. Here the sensor `sensor.office_temperature` and the switch `switch.livingroom_pin_2` are used.
+
+First import the module and setup the basics:
+
+```python
+import homeassistant.remote as remote
+
+api = remote.API('127.0.0.1', 'password')
+print(remote.validate_api(api))
+```
+
+### {% linkable_title Get configuration %}
+
+Get the current configuration of a Home Assistant instance:
+
+```python
+import homeassistant.remote as remote
+
+api = remote.API('127.0.0.1', 'password')
+
+print(remote.get_config(api))
+```
+
+### {% linkable_title Get details about services, events, and entitites %}
+
+The output from this is similar to the output you'd find via the frontend, using the [Developer Tools](/docs/tools/dev-tools/).
+
+```python
+import homeassistant.remote as remote
+
+api = remote.API('127.0.0.1', 'YOUR_PASSWORD')
+
+print('-- Available services:')
+services = remote.get_services(api)
+for service in services:
+ print(service['services'])
+
+print('\n-- Available events:')
+events = remote.get_event_listeners(api)
+for event in events:
+ print(event)
+
+print('\n-- Available entities:')
+entities = remote.get_states(api)
+for entity in entities:
+ print(entity)
+```
+
+### {% linkable_title Get the state of an entity %}
+
+To get the details of a single entity, use `get_state`:
+
+```python
+import homeassistant.remote as remote
+
+api = remote.API('127.0.0.1', 'YOUR_PASSWORD')
+office_temp = remote.get_state(api, 'sensor.office_temperature')
+print('{} is {} {}.'.format(
+ office_temp.name, office_temp.state,
+ office_temp.attributes['unit_of_measurement'])
+)
+```
+
+This outputs the details which are stored for this entity, ie:
+
+```bash
+Office Temperature is 19 °C.
+```
+
+Switches work the same way. The only difference is that both entities have different attributes.
+
+```python
+import homeassistant.remote as remote
+
+api = remote.API('127.0.0.1', 'YOUR_PASSWORD')
+switch_livingroom = remote.get_state(api, 'switch.livingroom_pin_2')
+print('{} is {}.'.format(
+ switch_livingroom.name, switch_livingroom.state)
+)
+```
+
+### {% linkable_title Set the state of an entity %}
+
+Of course, it's possible to set the state as well:
+
+```python
+import homeassistant.remote as remote
+from homeassistant.const import STATE_ON
+
+api = remote.API('127.0.0.1', 'YOUR_PASSWORD')
+remote.set_state(api, 'sensor.office_temperature', new_state=123)
+remote.set_state(api, 'switch.livingroom_pin_2', new_state=STATE_ON)
+```
+
+The state will be set to the new values until the next update occurs.
+
+### {% linkable_title Blinking all entities of a domain %}
+
+If you want to turn on all entities of a domain, retrieve the service via `get_services` and act on that:
+
+
+```python
+import time
+import homeassistant.remote as remote
+
+api = remote.API('127.0.0.1', 'YOUR_PASSWORD')
+domain = 'switch'
+
+remote.call_service(api, domain, 'turn_on')
+time.sleep(10)
+remote.call_service(api, domain, 'turn_off')
+```
+
+### {% linkable_title Control a single entity %}
+
+To turn on or off a single switch, pass the ID of the entity:
+
+```python
+import time
+import homeassistant.remote as remote
+
+api = remote.API('127.0.0.1', 'YOUR_PASSWORD')
+domain = 'switch'
+switch_name = 'switch.livingroom_pin_2'
+
+remote.call_service(api, domain, 'turn_on', {'entity_id': '{}'.format(switch_name)})
+time.sleep(5)
+remote.call_service(api, domain, 'turn_off', {'entity_id': '{}'.format(switch_name)})
+```
+
+### {% linkable_title Specify a timeout %}
+
+The default timeout for an API call with `call_service` is 5 seconds. Services
+taking longer than this to return will raise
+`homeassistant.exceptions.HomeAssistantError: Timeout`, unless provided with a
+longer timeout.
+
+```python
+import homeassistant.remote as remote
+
+api = remote.API('host', 'password')
+domain = 'switch'
+
+# Assuming switch.timeout_switch takes 10 seconds to return
+switch_name = 'switch.timeout_switch'
+
+# Raises homeassistant.exceptions.HomeAssistantError: Timeout when talking to
+remote.call_service(api, domain, 'turn_on', {'entity_id': switch_name})
+
+# Runs withous exception
+remote.call_service(api, domain, 'turn_on', {'entity_id': switch_name},
+ timeout=11)
+```
+
+### {% linkable_title Send a notification %}
+
+The example uses the Jabber notification platform to send a single message to the given recipient in the `configuration.yaml` file:
+
+```python
+import homeassistant.remote as remote
+
+api = remote.API('127.0.0.1', 'YOUR_PASSWORD')
+domain = 'notify'
+data = {"title":"Test", "message":"A simple test message from HA."}
+
+remote.call_service(api, domain, 'jabber', data)
+```
+
+## {% linkable_title Examples %}
+
+This section contains a couple of sample scripts.
+
+### {% linkable_title List all sensors and their value %}
+
+If you want to see, export or list all sensor states then an easy way to do it, is to get all entities and filter for the one you are looking for.
+
+```python
+import homeassistant.remote as remote
+
+api = remote.API('127.0.0.1', 'YOUR_PASSWORD')
+entities = remote.get_states(api)
+for entity in entities:
+ if entity.entity_id.startswith('sensor'):
+ data = remote.get_state(api, entity.entity_id)
+ print('{}: {}'.format(data.attributes['friendly_name'], data.state))
+```
+
+### {% linkable_title Show difference between `last_changed` and `last_updated` %}
+
+The documentation about the [State Objects](/docs/configuration/state_object/) describes the
+`last_changed` and `last_updated` fields. This example shows how it works in practice.
+
+```python
+import time
+
+from prettytable import PrettyTable
+import homeassistant.remote as remote
+
+api = remote.API('127.0.0.1', 'YOUR_PASSWORD')
+
+ACTIONS = {
+ 'Create sensor': [21, 'Test'],
+ 'No new sensor value': [21, 'Test'],
+ 'New sensor value': [22, 'Test'],
+ 'Update attribute': [22, 'Test1'],
+}
+
+output = PrettyTable(['Action', 'Last changed', 'Last updated'])
+
+for key, value in ACTIONS.items():
+ remote.set_state(api, 'sensor.test', new_state=value[0],
+ attributes={'friendly_name': value[1]})
+ data = remote.get_state(api, 'sensor.test')
+ output.add_row([key, data.last_changed, data.last_updated])
+ time.sleep(2)
+
+print(output)
+```
+
diff --git a/docs/external_api_rest.md b/docs/external_api_rest.md
new file mode 100644
index 00000000000..ec232cac97f
--- /dev/null
+++ b/docs/external_api_rest.md
@@ -0,0 +1,530 @@
+---
+layout: page
+title: "RESTful API"
+description: "Home Assistant RESTful API documentation"
+date: 2014-12-21 13:27
+sidebar: true
+comments: false
+sharing: true
+footer: true
+---
+
+Home Assistant runs a web server accessible on port 8123.
+
+* http://IP_ADDRESS:8123/ is an interface to control Home Assistant.
+* http://IP_ADDRESS:8123/api/ is a Rest API.
+
+The API accepts and returns only JSON encoded objects. All API calls have to be accompanied by the header `X-HA-Access: YOUR_PASSWORD` (YOUR_PASSWORD as specified in your `configuration.yaml` file in the [`http:` section](/components/http/)).
+
+If you are not using the [`frontend`](/components/frontend/) in your setup then you need to add the [`api` component](/components/api/) to your `configuration.yaml` file.
+
+There are multiple ways to consume the Home Assistant Rest API. One is with `curl`:
+
+```bash
+curl -X GET \
+ -H "x-ha-access: YOUR_PASSWORD" \
+ -H "Content-Type: application/json" \
+ http://IP_ADDRESS:8123/ENDPOINT
+```
+
+Another option is to use Python and the [Requests](http://docs.python-requests.org/en/latest/) module. =
+
+```python
+from requests import get
+
+url = 'http://localhost:8123/ENDPOINT'
+headers = {'x-ha-access': 'YOUR_PASSWORD',
+ 'content-type': 'application/json'}
+
+response = get(url, headers=headers)
+print(response.text)
+```
+
+
+You can append `?api_password=YOUR_PASSWORD` to any URL to log in automatically.
+
+
+Successful calls will return status code 200 or 201. Other status codes that can return are:
+
+- 400 (Bad Request)
+- 401 (Unauthorized)
+- 404 (Not Found)
+- 405 (Method not allowed)
+
+### {% linkable_title Actions %}
+
+The API supports the following actions:
+
+#### {% linkable_title GET /api/ %}
+
+Returns a message if the API is up and running.
+
+```json
+{
+ "message": "API running."
+}
+```
+
+Sample `curl` command:
+
+```bash
+$ curl -X GET -H "x-ha-access: YOUR_PASSWORD" \
+ -H "Content-Type: application/json" http://localhost:8123/api/
+```
+
+#### {% linkable_title GET /api/config %}
+
+Returns the current configuration as JSON.
+
+```json
+{
+ "components":[
+ "sensor.cpuspeed",
+ "frontend",
+ "config.core",
+ "http",
+ "map",
+ "api",
+ "sun",
+ "config",
+ "discovery",
+ "conversation",
+ "recorder",
+ "group",
+ "sensor",
+ "websocket_api",
+ "automation",
+ "config.automation",
+ "config.customize"
+ ],
+ "config_dir":"/home/ha/.homeassistant",
+ "elevation":510,
+ "latitude":45.8781529,
+ "location_name":"Home",
+ "longitude":8.458853651,
+ "time_zone":"Europe/Zurich",
+ "unit_system":{
+ "length":"km",
+ "mass":"g",
+ "temperature":"\u00b0C",
+ "volume":"L"
+ },
+ "version":"0.56.2",
+ "whitelist_external_dirs":[
+ "/home/ha/.homeassistant/www",
+ "/home/ha/.homeassistant/"
+ ]
+}
+```
+
+Sample `curl` command:
+
+```bash
+$ curl -X GET -H "x-ha-access: YOUR_PASSWORD" \
+ -H "Content-Type: application/json" http://localhost:8123/api/config
+```
+
+#### {% linkable_title GET /api/discovery_info %}
+
+Returns basic information about the Home Assistant instance as JSON.
+
+```json
+{
+ "base_url": "http://192.168.0.2:8123",
+ "location_name": "Home",
+ "requires_api_password": true,
+ "version": "0.56.2"
+}
+```
+
+Sample `curl` command:
+
+```bash
+$ curl -X GET -H "x-ha-access: YOUR_PASSWORD" \
+ -H "Content-Type: application/json" http://localhost:8123/api/discovery_info
+```
+
+#### {% linkable_title GET /api/events %}
+
+Returns an array of event objects. Each event object contains event name and listener count.
+
+```json
+[
+ {
+ "event": "state_changed",
+ "listener_count": 5
+ },
+ {
+ "event": "time_changed",
+ "listener_count": 2
+ }
+]
+```
+
+Sample `curl` command:
+
+```bash
+$ curl -X GET -H "x-ha-access: YOUR_PASSWORD" \
+ -H "Content-Type: application/json" http://localhost:8123/api/events
+```
+
+#### {% linkable_title GET /api/services %}
+
+Returns an array of service objects. Each object contains the domain and which services it contains.
+
+```json
+[
+ {
+ "domain": "browser",
+ "services": [
+ "browse_url"
+ ]
+ },
+ {
+ "domain": "keyboard",
+ "services": [
+ "volume_up",
+ "volume_down"
+ ]
+ }
+]
+```
+
+Sample `curl` command:
+
+```bash
+$ curl -X GET -H "x-ha-access: YOUR_PASSWORD" \
+ -H "Content-Type: application/json" http://localhost:8123/api/services
+```
+
+#### {% linkable_title GET /api/history/period/<timestamp> %}
+
+Returns an array of state changes in the past. Each object contains further details for the entities.
+
+The `` (`YYYY-MM-DDThh:mm:ssTZD`) is optional and defaults to 1 day before the time of the request. It determines the beginning of the period.
+
+You can pass the following optional GET parameters:
+
+- `filter_entity_id=` to filter on a single entity
+- `end_time=` to choose the end of the period in URL encoded format (defaults to 1 day).
+
+```json
+[
+ [
+ {
+ "attributes": {
+ "friendly_name": "Weather Temperature",
+ "unit_of_measurement": "\u00b0C"
+ },
+ "entity_id": "sensor.weather_temperature",
+ "last_changed": "2016-02-06T22:15:00+00:00",
+ "last_updated": "2016-02-06T22:15:00+00:00",
+ "state": "-3.9"
+ },
+ {
+ "attributes": {
+ "friendly_name": "Weather Temperature",
+ "unit_of_measurement": "\u00b0C"
+ },
+ "entity_id": "sensor.weather_temperature",
+ "last_changed": "2016-02-06T22:15:00+00:00",
+ "last_updated": "2016-02-06T22:15:00+00:00",
+ "state": "-1.9"
+ },
+ ]
+]
+```
+
+Sample `curl` commands:
+
+```bash
+$ curl -X GET -H "x-ha-access: YOUR_PASSWORD" \
+ -H "Content-Type: application/json" \
+ http://localhost:8123/api/history/period/2016-12-29T00:00:00+02:00
+```
+
+```bash
+$ curl -X GET -H "x-ha-access: YOUR_PASSWORD" \
+ -H "Content-Type: application/json" \
+ http://localhost:8123/api/history/period/2016-12-29T00:00:00+02:00?filter_entity_id=sensor.temperature
+```
+
+```bash
+$ curl -X GET -H "x-ha-access: YOUR_PASSWORD" \
+ -H "Content-Type: application/json" \
+ http://localhost:8123/api/history/period/2016-12-29T00:00:00+02:00?end_time=2016-12-31T00%3A00%3A00%2B02%3A00
+```
+
+#### {% linkable_title GET /api/states %}
+
+Returns an array of state objects. Each state has the following attributes: entity_id, state, last_changed and attributes.
+
+```json
+[
+ {
+ "attributes": {},
+ "entity_id": "sun.sun",
+ "last_changed": "2016-05-30T21:43:32.418320+00:00",
+ "state": "below_horizon"
+ },
+ {
+ "attributes": {},
+ "entity_id": "process.Dropbox",
+ "last_changed": "22016-05-30T21:43:32.418320+00:00",
+ "state": "on"
+ }
+]
+```
+
+Sample `curl` command:
+
+```bash
+$ curl -X GET -H "x-ha-access: YOUR_PASSWORD" \
+ -H "Content-Type: application/json" http://localhost:8123/api/states
+```
+
+#### {% linkable_title GET /api/states/<entity_id> %}
+
+Returns a state object for specified entity_id. Returns 404 if not found.
+
+```json
+{
+ "attributes":{
+ "azimuth":336.34,
+ "elevation":-17.67,
+ "friendly_name":"Sun",
+ "next_rising":"2016-05-31T03:39:14+00:00",
+ "next_setting":"2016-05-31T19:16:42+00:00"
+ },
+ "entity_id":"sun.sun",
+ "last_changed":"2016-05-30T21:43:29.204838+00:00",
+ "last_updated":"2016-05-30T21:50:30.529465+00:00",
+ "state":"below_horizon"
+}
+```
+
+Sample `curl` command:
+
+```bash
+$ curl -X GET -H "x-ha-access: YOUR_PASSWORD" \
+ -H "Content-Type: application/json" \
+ http://localhost:8123/api/states/sensor.kitchen_temperature
+```
+
+#### {% linkable_title GET /api/error_log %}
+
+Retrieve all errors logged during the current session of Home Assistant as a plaintext response.
+
+```text
+15-12-20 11:02:50 homeassistant.components.recorder: Found unfinished sessions
+15-12-20 11:03:03 netdisco.ssdp: Error fetching description at http://192.168.1.1:8200/rootDesc.xml
+15-12-20 11:04:36 homeassistant.components.alexa: Received unknown intent HelpIntent
+```
+
+Sample `curl` command:
+
+```bash
+$ curl -X GET -H "x-ha-access: YOUR_PASSWORD" \
+ -H "Content-Type: application/json" \
+ http://localhost:8123/api/error_log
+```
+
+#### {% linkable_title GET /api/camera_proxy/camera.<entity_id> %}
+
+Returns the data (image) from the specified camera entity_id.
+
+Sample `curl` command:
+
+```bash
+$ curl -X GET -H "x-ha-access: YOUR_PASSWORD" \
+ -H "Content-Type: application/json" \
+ http://localhost:8123/api/camera_proxy/camera.my_sample_camera?time=1462653861261 -o image.jpg
+```
+
+#### {% linkable_title POST /api/states/<entity_id> %}
+
+Updates or creates the current state of an entity.
+
+Expects a JSON object that has at least a state attribute:
+
+```json
+{
+ "state": "below_horizon",
+ "attributes": {
+ "next_rising":"2016-05-31T03:39:14+00:00",
+ "next_setting":"2016-05-31T19:16:42+00:00"
+ }
+}
+```
+
+The return code is 200 if the entity existed, 201 if the state of a new entity was set. A location header will be returned with the URL of the new resource. The response body will contain a JSON encoded State object.
+
+```json
+{
+ "attributes": {
+ "next_rising":"2016-05-31T03:39:14+00:00",
+ "next_setting":"2016-05-31T19:16:42+00:00"
+ },
+ "entity_id": "sun.sun",
+ "last_changed": "2016-05-30T21:43:29.204838+00:00",
+ "last_updated": "2016-05-30T21:47:30.533530+00:00",
+ "state": "below_horizon"
+}
+```
+
+Sample `curl` command:
+
+```bash
+$ curl -X POST -H "x-ha-access: YOUR_PASSWORD" \
+ -H "Content-Type: application/json" \
+ -d '{"state": "25", "attributes": {"unit_of_measurement": "°C"}}' \
+ http://localhost:8123/api/states/sensor.kitchen_temperature
+```
+
+#### {% linkable_title POST /api/events/<event_type> %}
+
+Fires an event with event_type
+
+You can pass an optional JSON object to be used as `event_data`.
+
+```json
+{
+ "next_rising":"2016-05-31T03:39:14+00:00",
+}
+```
+
+Returns a message if successful.
+
+```json
+{
+ "message": "Event download_file fired."
+}
+```
+
+#### {% linkable_title POST /api/services/<domain>/<service> %}
+
+Calls a service within a specific domain. Will return when the service has been executed or after 10 seconds, whichever comes first.
+
+You can pass an optional JSON object to be used as `service_data`.
+
+```json
+{
+ "entity_id": "light.Ceiling"
+}
+```
+
+Returns a list of states that have changed while the service was being executed.
+
+```json
+[
+ {
+ "attributes": {},
+ "entity_id": "sun.sun",
+ "last_changed": "2016-05-30T21:43:32.418320+00:00",
+ "state": "below_horizon"
+ },
+ {
+ "attributes": {},
+ "entity_id": "process.Dropbox",
+ "last_changed": "22016-05-30T21:43:32.418320+00:00",
+ "state": "on"
+ }
+]
+```
+
+Sample `curl` commands:
+
+Turn the light on:
+
+```bash
+$ curl -X POST -H "x-ha-access: YOUR_PASSWORD" \
+ -H "Content-Type: application/json" \
+ -d '{"entity_id": "switch.christmas_lights"}' \
+ http://localhost:8123/api/services/switch/turn_on
+```
+
+Send a MQTT message:
+
+```bash
+$ curl -X POST \
+ -H "Content-Type: application/json" \
+ -H "x-ha-access:YOUR_PASSWORD" \
+ -d '{"payload": "OFF", "topic": "home/fridge", "retain": "True"}' \
+ http://localhost:8123/api/services/mqtt/publish
+```
+
+
+The result will include any states that changed while the service was being executed, even if their change was the result of something else happening in the system.
+
+
+#### {% linkable_title POST /api/template %}
+
+Render a Home Assistant template. [See template docs for more information.](/topics/templating/)
+
+```json
+{
+ "template": "Paulus is at {% raw %}{{ states('device_tracker.paulus') }}{% endraw %}!"
+}
+```
+
+Returns the rendered template in plain text.
+
+```text
+Paulus is at work!
+```
+
+Sample `curl` command:
+
+```bash
+$ curl -X POST -H "x-ha-access: YOUR_PASSWORD" \
+ -H "Content-Type: application/json" \
+ -d '{"template": "It is {{ now }}!"}' http://localhost:8123/api/template
+```
+
+#### {% linkable_title POST /api/event_forwarding %}
+
+Set up event forwarding to another Home Assistant instance.
+
+Requires a JSON object that represents the API to forward to.
+
+```javascript
+{
+ "host": "machine",
+ "api_password": "my_super_secret_password",
+ "port": 8880 // optional
+}
+```
+
+It will return a message if event forwarding was set up successfully.
+
+```json
+{
+ "message": "Event forwarding setup."
+}
+```
+
+#### {% linkable_title DELETE /api/event_forwarding %}
+
+Cancel event forwarding to another Home Assistant instance.
+
+Requires a JSON object that represents the API to cancel forwarding to.
+
+```javascript
+{
+ "host": "machine",
+ "api_password": "my_super_secret_password",
+ "port": 8880 // optional
+}
+```
+
+It will return a message if event forwarding was canceled successfully.
+
+```json
+{
+ "message": "Event forwarding cancelled."
+}
+```
+
+
+If your client does not support DELETE HTTP requests you can add an optional attribute _METHOD and set its value to DELETE.
+
diff --git a/docs/external_api_server_sent_events.md b/docs/external_api_server_sent_events.md
new file mode 100644
index 00000000000..fc54b168dab
--- /dev/null
+++ b/docs/external_api_server_sent_events.md
@@ -0,0 +1,73 @@
+---
+layout: page
+title: "Server-sent events"
+description: "Home Assistant Server-sent events documentation"
+date: 2016-04-08 07:00
+sidebar: true
+comments: false
+sharing: true
+footer: true
+---
+
+The [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events) feature is a one-way channel from your Home Assistant server to a client which is acting as a consumer. For bi-directional communication check the [RESTful API](/developers/rest_api/) and [Python API](/developers/python_api/).
+
+The URI that is generating the data is `/api/stream`.
+
+A requirement on the client-side is existing support for the [EventSource](https://developer.mozilla.org/en-US/docs/Web/API/EventSource) interface.
+
+There are various ways to access the stream. If you have not set an `api_password` in the [`http`](/components/http/) section of your `configuration.yaml` file then you use your modern browser to read the messages. A command-line option is `curl`:
+
+```bash
+$ curl -X GET -H "x-ha-access: YOUR_PASSWORD" \
+ -H "Content-Type: application/json" http://localhost:8123/api/stream
+```
+
+You can create a convenient view for this by creating an HTML file (`sse.html`) in the `www` folder of your Home Assistant configuration directory (`.homeassistant`). Paste this snippet into the file:
+
+```html
+
+
+
+
Getting Home Assistant server events
+
+
+
+
+```
+
+Visit [http://localhost:8123/local/sse.html](http://localhost:8123/local/sse.html) to see the stream of events.
+
+## {% linkable_title Examples %}
+
+A simple way to consume server-sent events is to use a command-line http client like [httpie](https://httpie.org/). Installation info is on the site (if you use Homebrew, it's `brew install httpie`). Once installed, run this snippet from your terminal:
+
+```bash
+$ http --stream http://localhost:8123/api/stream x-ha-access:YOUR_PASSWORD content-type:application/json
+```
+
+### {% linkable_title Website %}
+
+The [home-assistant-sse](https://github.com/fabaff/home-assistant-sse) repository contains a more advanced example.
+
+### {% linkable_title Python %}
+
+If you want to test the server-sent events without creating a website, the Python module [`sseclient` ](https://pypi.python.org/pypi/sseclient/) can help. To install (assuming Python and pip3 are already installed):
+
+```bash
+$ pip3 install sseclient
+```
+
+A simple script to consume SSE in Python looks like this:
+
+```python
+from sseclient import SSEClient
+
+messages = SSEClient('http://localhost:8123/api/stream?api_password=YOUR_PASSWORD')
+for msg in messages:
+ print(msg)
+```
diff --git a/docs/external_api_websocket.md b/docs/external_api_websocket.md
new file mode 100644
index 00000000000..76f7f0b0c7a
--- /dev/null
+++ b/docs/external_api_websocket.md
@@ -0,0 +1,358 @@
+---
+layout: page
+title: "WebSocket API"
+description: "Home Assistant WebSocket API documentation"
+date: 2016-11-26 13:27
+sidebar: true
+comments: false
+sharing: true
+footer: true
+---
+
+Home Assistant contains a WebSocket API. This API can be used to stream information from a Home Assistant instance to any client that implements WebSocket. Implementations in different languages:
+
+- [JavaScript](https://github.com/home-assistant/home-assistant-js-websocket) - powers the frontend
+- [Python](https://raw.githubusercontent.com/home-assistant/home-assistant-dev-helper/master/ha-websocket-client.py) - CLI client using [`asyncws`](https://async-websockets.readthedocs.io/en/latest/)
+- [JavaScript/HTML](https://raw.githubusercontent.com/home-assistant/home-assistant-dev-helper/master/ha-websocket.html) - WebSocket connection in your browser
+
+Connect your websocket implementation to `ws://localhost:8123/api/websocket`.
+
+If you are not using the [`frontend`](/components/frontend/) in your setup then you need to add the [`websocket_api` component](/components/websocket_api/) to your `configuration.yaml` file to use the WebSocket API.
+
+## {% linkable_title Server states %}
+
+1. Client connects.
+1. Authentication phase starts.
+ - If no further authentication necessary for the user: go to 3.
+ - Server sends `auth_required` message.
+ - Client sends `auth` message.
+ - If `auth` message correct: go to 3.
+ - Server sends `auth_invalid`. Go to 6.
+1. Send `auth_ok` message
+1. Authentication phase ends.
+1. Command phase starts.
+ 1. Client can send commands.
+ 1. Server can send results of previous commands.
+1. Client or server disconnects session.
+
+During the command phase, the client attaches a unique identifier to each message. The server will add this identifier to each message so that the client can link each message to its origin.
+
+## {% linkable_title Message format %}
+
+Each API message is a JSON serialized object containing a `type` key. After the authentication phase messages also must contain an `id`, an integer that contains the number of interactions.
+
+Example of an auth message:
+
+```json
+{
+ "type": "auth",
+ "api_password": "supersecret"
+}
+```
+
+```json
+{
+ "id" 5,
+ "type":"event",
+ "event":{
+ "data":{},
+ "event_type":"test_event",
+ "time_fired":"2016-11-26T01:37:24.265429+00:00",
+ "origin":"LOCAL"
+ }
+}
+```
+
+## {% linkable_title Authentication phase %}
+
+When a client connects to the server, the server will test if the client is authenticated. Authentication will not be necessary if no api_password is set or if the user fulfills one of the other criteria for authentication (trusted network, password in url/header).
+
+If no authentication is needed, the authentication phase will complete and the server will send an `auth_ok` message.
+
+```json
+{
+ "type": "auth_ok"
+}
+```
+
+If authentication is necessary, the server sends out `auth_required`.
+
+```json
+{
+ "type": "auth_required"
+}
+```
+
+This means that the next message from the client should be an auth message:
+
+```json
+{
+ "type": "auth",
+ "api_password": "supersecret"
+}
+```
+
+If the client supplies valid authentication, the authentication phase will complete by the server sending the `auth_ok` message:
+
+```json
+{
+ "type": "auth_ok"
+}
+```
+
+If the data is incorrect, the server will reply with `auth_invalid` message and disconnect the session.
+
+```json
+{
+ "type": "auth_invalid",
+ "message": "Invalid password"
+}
+```
+
+## {% linkable_title Command phase %}
+
+During this phase the client can give commands to the server. The server will respond to each command with a `result` message indicating when the command is done and if it was successful.
+
+```json
+{
+ "id": 6.
+ "type": "result",
+ "success": true,
+ // Can contain extra result info
+ "result": null
+}
+```
+
+## {% linkable_title Subscribe to events %}
+
+The command `subscribe_events` will subscribe your client to the event bus. You can either listen to all events or to a specific event type. If you want to listen to multiple event types, you will have to send multiple `subscribe_events` commands.
+
+```json
+{
+ "id": 18,
+ "type": "subscribe_events",
+ // Optional
+ "event_type": "state_changed"
+}
+```
+
+The server will respond with a result message to indicate that the subscription is active.
+
+```json
+{
+ "id": 18,
+ "type": "result",
+ "success": true,
+ "result": null
+}
+```
+
+For each event that matches, the server will send a message of type `event`. The `id` in the message will point at the original `id` of the `listen_event` command.
+
+```json
+{
+ "id": 18,
+ "type":"event",
+ "event":{
+ "data":{
+ "entity_id":"light.bed_light",
+ "new_state":{
+ "entity_id":"light.bed_light",
+ "last_changed":"2016-11-26T01:37:24.265390+00:00",
+ "state":"on",
+ "attributes":{
+ "rgb_color":[
+ 254,
+ 208,
+ 0
+ ],
+ "color_temp":380,
+ "supported_features":147,
+ "xy_color":[
+ 0.5,
+ 0.5
+ ],
+ "brightness":180,
+ "white_value":200,
+ "friendly_name":"Bed Light"
+ },
+ "last_updated":"2016-11-26T01:37:24.265390+00:00"
+ },
+ "old_state":{
+ "entity_id":"light.bed_light",
+ "last_changed":"2016-11-26T01:37:10.466994+00:00",
+ "state":"off",
+ "attributes":{
+ "supported_features":147,
+ "friendly_name":"Bed Light"
+ },
+ "last_updated":"2016-11-26T01:37:10.466994+00:00"
+ }
+ },
+ "event_type":"state_changed",
+ "time_fired":"2016-11-26T01:37:24.265429+00:00",
+ "origin":"LOCAL"
+ }
+}
+```
+
+### {% linkable_title Unsubscribing from events %}
+
+You can unsubscribe from previously created subscription events. Pass the id of the original subscription command as value to the subscription field.
+
+```json
+{
+ "id": 19,
+ "type": "unsubscribe_events",
+ "subscription": 18
+}
+```
+
+The server will respond with a result message to indicate that unsubscribing was successful.
+
+```json
+{
+ "id": 19,
+ "type": "result",
+ "success": true,
+ "result": null
+}
+```
+
+### {% linkable_title Calling a service %}
+
+This will call a service in Home Assistant. Right now there is no return value. The client can listen to `state_changed` events if it is interested in changed entities as a result of a service call.
+
+```json
+{
+ "id": 24,
+ "type": "call_service",
+ "domain": "light",
+ "service": "turn_on",
+ // Optional
+ "service_data": {
+ "entity_id": "light.kitchen"
+ }
+}
+```
+
+The server will indicate with a message indicating that the service is done executing.
+
+```json
+{
+ "id": 24,
+ "type": "result",
+ "success": true,
+ "result": null
+}
+```
+
+### {% linkable_title Fetching states %}
+
+This will get a dump of all the current states in Home Assistant.
+
+```json
+{
+ "id": 19,
+ "type": "get_states"
+}
+```
+
+The server will respond with a result message containing the states.
+
+```json
+{
+ "id": 19,
+ "type": "result",
+ "success": true,
+ "result": [ ... ]
+}
+```
+
+### {% linkable_title Fetching config %}
+
+This will get a dump of the current config in Home Assistant.
+
+```json
+{
+ "id": 19,
+ "type": "get_config"
+}
+```
+
+The server will respond with a result message containing the config.
+
+```json
+{
+ "id": 19,
+ "type": "result",
+ "success": true,
+ "result": { ... }
+}
+```
+
+### {% linkable_title Fetching services %}
+
+This will get a dump of the current services in Home Assistant.
+
+```json
+{
+ "id": 19,
+ "type": "get_services"
+}
+```
+
+The server will respond with a result message containing the services.
+
+```json
+{
+ "id": 19,
+ "type": "result",
+ "success": true,
+ "result": { ... }
+}
+```
+
+### {% linkable_title Fetching panels %}
+
+This will get a dump of the current registered panels in Home Assistant.
+
+```json
+{
+ "id": 19,
+ "type": "get_panels"
+}
+```
+
+The server will respond with a result message containing the current registered panels.
+
+```json
+{
+ "id": 19,
+ "type": "result",
+ "success": true,
+ "result": [ ... ]
+}
+```
+
+## {% linkable_title Error handling %}
+
+If an error occurs, the `success` key in the `result` message will be set to `false`. It will contain an `error` key containing an object with two keys: `code` and `message`.
+
+| Code | Description |
+| ----- | ------------ |
+| 1 | A non-increasing identifier has been supplied.
+| 2 | Received message is not in expected format (voluptuous validation error).
+| 3 | Requested item cannot be found
+
+```json
+{
+ "id": 12,
+ "type":"result",
+ "success": false,
+ "error": {
+ "code": 2,
+ "message": "Message incorrectly formatted: expected str for dictionary value @ data['event_type']. Got 100"
+ }
+}
+```
diff --git a/docs/frontend.md b/docs/frontend.md
new file mode 100644
index 00000000000..0fb71208d9a
--- /dev/null
+++ b/docs/frontend.md
@@ -0,0 +1,102 @@
+---
+layout: page
+title: "Frontend development"
+description: "Tips and hints if you are starting on Home Assistant frontend development"
+date: 2014-12-21 13:32
+sidebar: true
+comments: false
+sharing: true
+footer: true
+---
+
+Home Assistant is built on top of the [Polymer](https://www.polymer-project.org/) webcomponents framework. Polymer allows building encapsulated custom HTML elements. [Home-Assistant-Polymer source code on GitHub.][hass-polymer]
+
+
+Do not use development mode in production. Home Assistant uses aggressive caching to improve the mobile experience. This is disabled during development so that you do not have to restart the server in between changes.
+
+
+## {% linkable_title Setting up the environment %}
+
+
+All commands below need to be run from inside the home-assistant-polymer repository.
+
+
+Home Assistant will by default serve the compiled version of the frontend from the hass_frontend Python package. For development you want to work with the unbundled source files which are in the home-assistant-polymer repository.
+
+First step is to configure Home Assistant to use the development mode for the frontend. Do this by updating the frontend config in your `configuration.yaml` and set the path to the polymer repo:
+
+```yaml
+frontend:
+ development_repo:
+```
+
+Next step is to git clone the [home-assistant-polymer repository][hass-polymer]. You can place the repository anywhere on your system but to keep these instructions simple we're cloning the home-assistant-polymer repository as a sibling to the Home Assistant repo.
+
+```bash
+$ git clone https://github.com/home-assistant/home-assistant-polymer.git
+$ cd home-assistant-polymer
+```
+
+After cloning, your folder structure should look like this:
+
+```text
+/home-assistant
+/home-assistant-polymer
+```
+
+Node.js is required to build the frontend. The preferred method of installing node.js is with [nvm](https://github.com/creationix/nvm). Install nvm using the instructions in the [README](https://github.com/creationix/nvm#install-script), and install the correct node.js by running the following command:
+
+```bash
+$ nvm install
+```
+
+[Yarn](https://yarnpkg.com/en/) is used as the package manager for node modules. [Install yarn using the instructions here.](https://yarnpkg.com/en/docs/install)
+
+Next, development dependencies need to be installed to bootstrap the frontend development environment. First activate the right Node version and then download all the needed modules and do a first build:
+
+```bash
+$ nvm use
+$ script/bootstrap
+```
+
+This script will use yarn and bower to install all the necessary dependencies necessary for development and do an initial build.
+
+### {% linkable_title Creating pull requests %}
+
+If you're planning on issuing a PR back to the Home Assistant codebase you need to fork the polymer project and add your fork as a remote to the Home Assistant Polymer repo.
+
+```bash
+$ git remote add
+```
+
+When you've made your changes and are ready to push them change to the working directory for the polymer project and then push your changes
+
+``` bash
+$ git add -A
+$ git commit -m "Added new feature X"
+$ git push -u HEAD
+```
+
+## {% linkable_title Development %}
+
+If you are changing `html` files under `/src` or `/panels` - just reload the page in your browser to see changes.
+If you are changing javascript files under `/js` you need to have gulp running to watch the source files for changes and build when necessary.
+
+```bash
+$ yarn run dev-watch
+```
+
+The source code for the frontend can be found in different directories:
+
+ - UI: `/home-assistant-polymer/src/`
+ - Panels: `/home-assistant-polymer/panels/`
+ - Javascript code: `/home-assistant-polymer/js/`
+
+# {% linkable_title Building the Polymer frontend %}
+
+Building a new version of the frontend is as simple as running `script/build_frontend`.
+To use a built version package it: `python setup.py sdist`
+Install it: `pip3 install dist/home-assistant-frontend-xxxxxxxx.0.tar.gz --upgrade`
+Run Home Assistant without trying to reinstall production package: `hass --skip-pip`
+
+[hass-polymer]: https://github.com/home-assistant/home-assistant-polymer
diff --git a/docs/frontend_add_card.md b/docs/frontend_add_card.md
new file mode 100644
index 00000000000..2deba80dbc3
--- /dev/null
+++ b/docs/frontend_add_card.md
@@ -0,0 +1,28 @@
+---
+layout: page
+title: "Adding state card"
+description: "Adding a state card to the frontend"
+date: 2016-04-16 14:40 -07:00
+sidebar: true
+comments: false
+sharing: true
+footer: true
+---
+
+The main interface of Home Assistant is a list of the current entities and their states. For each entity in the system, a state card will be rendered. State cards will show an icon, the name of the entity, when the state has last changed and the current state or a control to interact with it.
+
+
+
+The different card types can be found [here](https://github.com/home-assistant/home-assistant-polymer/tree/master/src/state-summary).
+
+Sensors, when not [grouped](/components/group/), are shown as so-called badges on top of the state cards.
+
+
+
+The different badges are located in the file [`/src/components/entity/ha-state-label-badge.html`](https://github.com/home-assistant/home-assistant-polymer/blob/master/src/components/entity/ha-state-label-badge.html).
+
+Adding a custom card type can be done with a few simple steps. For this example we will add a new state card for the domain `camera`:
+
+ 1. Add `'camera'` to the array `DOMAINS_WITH_CARD` in the file [/util/hass-util.html](https://github.com/home-assistant/home-assistant-polymer/blob/master/src/util/hass-util.html#L11).
+ 2. Create the files `state-card-camera.html` in the folder [/state-summary/](https://github.com/home-assistant/home-assistant-polymer/tree/master/src/state-summary).
+ 4. Add `` to [state-card-content.html](https://github.com/home-assistant/home-assistant-polymer/blob/master/src/state-summary/state-card-content.html).
diff --git a/docs/frontend_add_more_info.md b/docs/frontend_add_more_info.md
new file mode 100644
index 00000000000..2364c5b3129
--- /dev/null
+++ b/docs/frontend_add_more_info.md
@@ -0,0 +1,23 @@
+---
+layout: page
+title: "Adding more info dialogs"
+description: "Adding a more info dialog to the frontend"
+date: 2016-04-16 14:40 -07:00
+sidebar: true
+comments: false
+sharing: true
+footer: true
+---
+
+Whenever the user taps or clicks on one of the cards, a more info dialog will show. The header of this dialog will be the state card, followed by the history of this entity for the last 24 hours. Below this the more info component is rendered for that entity. The more info component can show more information or allow more ways of control.
+
+
+
+ The more info dialog for a light allows the user to control the color and the brightness.
+
+
+The instructions to add a more info dialog are very similar to adding a new card type. This example will add a new more info component for the domain `camera`:
+
+ 1. Add `'camera'` to the array `DOMAINS_WITH_MORE_INFO` in the file [util/hass-util.html](https://github.com/home-assistant/home-assistant-polymer/blob/master/src/util/hass-util.html#L24).
+ 2. Create the files `more-info-camera.html` in the folder [/more-infos](https://github.com/home-assistant/home-assistant-polymer/tree/master/src/more-infos).
+ 4. Add `` to [more-info-content.html](https://github.com/home-assistant/home-assistant-polymer/blob/master/src/more-infos/more-info-content.html)
diff --git a/docs/frontend_creating_custom_panels.md b/docs/frontend_creating_custom_panels.md
new file mode 100644
index 00000000000..4066e6062a6
--- /dev/null
+++ b/docs/frontend_creating_custom_panels.md
@@ -0,0 +1,91 @@
+---
+layout: page
+title: "Creating custom panels"
+description: "Introduction to create custom panels for Home Assistant."
+date: 2016-07-29 13:00
+sidebar: true
+comments: false
+sharing: true
+footer: true
+---
+
+Panels are pages within Home Assistant that show information within Home Assistant and can allow controlling it. Panels are linked from the sidebar and rendered full screen. The have have real-time access to the Home Assistant object via JavaScript. Examples of panels in the app are map, logbook and history.
+
+Besides components registering panels, users can also register panels using the `panel_custom` component. This allows users to quickly build their own custom interfaces for Home Assistant.
+
+### {% linkable_title Before you get started %}
+
+The Home Assistant user interface is currently served to browsers in modern JavaScript and older JavaScript (ES5). The older version has a wider browser support but that comes at a cost of size, performance and more difficult to get started building panels for authors.
+
+We therefore advice to set up the frontend to serve the modern version of the frontend so that you won't need any build tools while developing. If you realize that your audience requires both, you can add a transpilation step in the future. To set up your frontend to always serve the latest version, add this to your config:
+
+```
+frontend:
+ javascript_version: latest
+```
+
+### {% linkable_title Building your first panel %}
+
+Create a file called `hello.html` in your /panels/.
+
+The `hello.html` contains the needed building blocks to create the elements inside the view.
+
+```html
+
+
+
+
Hello {% raw %}{{who}}{% endraw %}. Greetings from Home Assistant.
+
+
+
+
+```
+
+Create an entry for the new panel in your `configuration.yaml` file:
+
+```yaml
+panel_custom:
+ - name: hello
+ sidebar_title: Hello World
+ sidebar_icon: mdi:hand-pointing-right
+ url_path: hello
+```
+
+For more possibilities, see the [Custom panel section](/cookbook/#user-interface) on our Examples page.
diff --git a/docs/frontend_creating_custom_ui.md b/docs/frontend_creating_custom_ui.md
new file mode 100644
index 00000000000..3012f43e60f
--- /dev/null
+++ b/docs/frontend_creating_custom_ui.md
@@ -0,0 +1,99 @@
+---
+layout: page
+title: "Creating custom UI"
+description: "Introduction to create custom ui for Home Assistant."
+date: 2017-02-04 13:00
+sidebar: true
+comments: false
+sharing: true
+footer: true
+ha_release: 0.38
+---
+
+If you would like to use your own [State card](/developers/frontend_add_card/) without merging your code into [home-assistant-polymer](https://github.com/home-assistant/home-assistant-polymer/) you can create your own implementation.
+
+Put the element source file and its dependencies in `www/custom_ui/` directory under your Home Assistant [configuration](/docs/configuration/) directory.
+
+For example if creating a state card for the `light` domain named `state-card-my-custom-light` put `state-card-my-custom-light.html` in `www/custom_ui/`.
+
+That file should implement `` tag with Polymer.
+
+In `state-card-my-custom-light.html` you should use `` to import all the dependencies **not** used by Home Assistant's UI.
+Do not import any dependencies used by the Home Assistant UI.
+Importing those will work in `development: 1` mode, but will fail in production mode.
+
+1. In the `customize:` section of the `configuration.yaml` file put `custom_ui_state_card: state-card-my-custom-light`.
+2. In the `frontend` section use `extra_html_url` to specify the URL to load.
+
+Example:
+
+`configuration.yaml`:
+
+```yaml
+homeassistant:
+ customize:
+ light.bedroom:
+ custom_ui_state_card: state-card-my-custom-light
+
+frontend:
+ extra_html_url:
+ - /local/custom_ui/state-card-my-custom-light.html
+```
+
+`www/custom_ui/state-card-my-custom-light.html`:
+
+```html
+
+
+
+
+
+
+
+
+
+```
+
+Some browsers don't support latest ECMAScript standards, these require a separate ES5 compatible file (`extra_html_url_es5`).
+
+
+For more possibilities, see the [Custom UI section](/cookbook/#user-interface) on our Examples page.
diff --git a/docs/hassio_addon_communication.md b/docs/hassio_addon_communication.md
new file mode 100644
index 00000000000..3a4f57fb8b0
--- /dev/null
+++ b/docs/hassio_addon_communication.md
@@ -0,0 +1,41 @@
+---
+layout: page
+title: "Add-On Communication"
+description: "Description of the internal communication of Hass.io."
+date: 2017-04-30 13:28
+sidebar: true
+comments: false
+sharing: true
+footer: true
+redirect_from: /hassio/addon_config/
+---
+
+There are different ways for communication between add-ons inside Hass.io.
+
+## {% linkable_title Network %}
+
+We use an internal network that allows to communicate with every add-on, even to/from Home Assistant, by using its name or alias. Only the add-ons which run on the host network are a bit limited. These can talk with all internal add-ons by their name but all other add-on can't address these add-on by name - using an alias works for both!
+
+Name/alias are used for communication inside Hass.io.
+The name is generated using the following format: `{REPO}_{SLUG}`, e.g., `local_xy` or `3283fh_myaddon`. In this example, `{SLUG}` is defined in an add-ons `config.json`. You can use this name also as DNS name but you need replace the `_` with `-` to have a valid hostname. If an add-on is installed locally, `{REPO}` will be `local`. If the add-on is installed from a Github repository, `{REPO}` is a hashed identifier generated from the GitHub repository's URL (ex: https://github.com/xy/my_hassio_addons). See [here](https://github.com/home-assistant/hassio/blob/587047f9d648b8491dc8eef17dc6777f81938bfd/hassio/addons/utils.py#L17) to understand how this identifier is generated. Note that this identifier is required in certain service calls that use the [Hass.io add-on API](hassio-addon-api). You can view the repository identifiers for all currently installed add-ons via a GET request to the hassio API `addons` endpoint.
+
+Use `hassio` for communication with the internal API.
+
+## {% linkable_title Home Assistant %}
+
+An add-on can talk to the [Home Assistant API][hass-api] using the internal proxy. That makes it very easy to communicate with the API without knowing the password, port or any other information of the Home Assistant instance. Use this URL: `http://hassio/homeassistant/api` and internal communication is redirected to the right place. The next stept is to add `homeassistant_api: true` to `config.json` and read the environment variable `HASSIO_TOKEN` and use this as Home-Assistant password.
+
+There is also a proxy for the [Home Assistant Websocket API][hass-websocket]. It works like the API proxy above and requires `HASSIO_TOKEN` as password. Use this URL: `http://hassio/homeassistant/websocket`.
+
+It is also possible to talk direct to the Home Assistant instance which is named `homeassistant` over the internal network. But you need to know the configuration that is used by the running instance.
+
+We have severals services for Hass.io inside Home Assistant to run tasks. To send data over STDIN to an add-on use the `hassio.addon_stdin` service.
+
+## {% linkable_title Hass.io API %}
+
+To enables calls to the [Hass.io API][hassio-api], add `hassio_api: true` to `config.json` and read the environment variable `HASSIO_TOKEN`. Now you can use the API over the URL: `http://hassio/`. Use the `HASSIO_TOKEN` with header `X-HASSIO-KEY`.
+
+[hass-api]: /developers/rest_api/
+[hass-websocket]: /developers/websocket_api/
+[hassio-api]: https://github.com/home-assistant/hassio/blob/master/API.md
+[hassio-addon-api]: https://github.com/home-assistant/hassio/blob/dev/API.md#restful-for-api-addons
diff --git a/docs/hassio_addon_config.md b/docs/hassio_addon_config.md
new file mode 100644
index 00000000000..bc4870f8621
--- /dev/null
+++ b/docs/hassio_addon_config.md
@@ -0,0 +1,207 @@
+---
+layout: page
+title: "Add-On Configuration"
+description: "Steps on how-to create an add-on for Hass.io."
+date: 2017-04-30 13:28
+sidebar: true
+comments: false
+sharing: true
+footer: true
+redirect_from: /hassio/addon_config/
+---
+
+Each add-on is stored in a folder. The file structure looks like this:
+
+```text
+addon_name/
+ build.json
+ CHANGELOG.md
+ config.json
+ Dockerfile
+ icon.png
+ logo.png
+ README.md
+ run.sh
+```
+
+## {% linkable_title Add-on script %}
+
+As with every Docker container, you will need a script to run when the container is started. A user might run many add-ons, so it is encouraged to try to stick to Bash scripts if you're doing simple things.
+
+When developing your script:
+
+ - `/data` is a volume for persistent storage.
+ - `/data/options.json` contains the user configuration. You can use `jq` inside your shell script to parse this data. However, you might have to install `jq` as a separate package in your container (see `Dockerfile` below).
+
+```bash
+CONFIG_PATH=/data/options.json
+
+TARGET="$(jq --raw-output '.target' $CONFIG_PATH)"
+```
+
+So if your `options` contain
+```json
+{ "target": "beer" }
+```
+then there will be a variable `TARGET` containing `beer` in the environment of your bash file afterwards.
+
+## {% linkable_title Add-on Docker file %}
+
+All add-ons are based on Alpine Linux 3.6. Hass.io will automatically substitute the right base image based on the machine architecture. Add `tzdata` if you need run in a different timezone. `tzdata` Is is already added to our base images.
+
+```
+ARG BUILD_FROM
+FROM $BUILD_FROM
+
+ENV LANG C.UTF-8
+
+# Install requirements for add-on
+RUN apk add --no-cache jq
+
+# Copy data for add-on
+COPY run.sh /
+RUN chmod a+x /run.sh
+
+CMD [ "/run.sh" ]
+```
+
+If you don't use local build on device or our build script, make sure that the Dockerfile have also a set of labels include:
+```
+LABEL io.hass.version="VERSION" io.hass.type="addon" io.hass.arch="armhf|aarch64|i386|amd64"
+```
+
+It is possible to use own base image with `build.json` or if you do not need support for automatic multi-arch building you can also use a simple docker `FROM`.
+
+### {% linkable_title Build Args %}
+
+We support the following build arguments by default:
+
+| ARG | Description |
+|-----|-------------|
+| BUILD_FROM | Hold image for dynamic builds or buildings over our systems.
+| BUILD_VERSION | Add-on version (read from `config.json`).
+| BUILD_ARCH | Hold current build arch inside.
+
+## {% linkable_title Add-on config %}
+
+The config for an add-on is stored in `config.json`.
+
+```json
+{
+ "name": "xy",
+ "version": "1.2",
+ "slug": "folder",
+ "description": "long description",
+ "arch": ["amd64"],
+ "url": "website with more information about add-on (ie a forum thread for support)",
+ "startup": "application",
+ "boot": "auto",
+ "ports": {
+ "123/tcp": 123
+ },
+ "map": ["config:rw", "ssl"],
+ "options": {},
+ "schema": {},
+ "image": "repo/{arch}-my-custom-addon"
+}
+```
+
+| Key | Type | Required | Description |
+| --- | ---- | -------- | ----------- |
+| name | string | yes | Name of the add-on
+| version | string | yes | Version of the add-on
+| slug | string | yes | Slug of the add-on
+| description | string | yes | Description of the add-on
+| arch | list | no | List of supported arch: `armhf`, `aarch64`, `amd64`, `i386`. Default all.
+| url | url | no | Homepage of the addon. Here you can explain the add-ons and options.
+| startup | bool | yes | `initialize` will start addon on setup of Hass.io. `system` is for things like databases and not dependent on other things. `services` will start before Home Assistant, while `application` is started afterwards. Finally `once` is for applications that don't run as a daemon.
+| webui | string | no | A URL for web interface of this add-on. Like `http://[HOST]:[PORT:2839]/dashboard`, the port needs the internal port, which will be replaced with the effective port. It is also possible to bind the proto part to a config options with: `[PROTO:option_name]://[HOST]:[PORT:2839]/dashboard` and he lookup if they is True and going to `https`.
+| boot | string | yes | `auto` by system and manual or only `manual`
+| ports | dict | no | Network ports to expose from the container. Format is `"container-port/type": host-port`.
+| host_network | bool | no | If that is True, the add-on run on host network.
+| host_ipc | bool | no | Default False. Allow to share the IPC namespace with others.
+| host_dbus | bool | no | Default False. Map Host dbus service into add-on.
+| devices | list | no | Device list to map into the add-on. Format is: `::`. i.e. `/dev/ttyAMA0:/dev/ttyAMA0:rwm`
+| auto_uart | bool | no | Default False. Auto mapping all UART/Serial device from host into add-on.
+| hassio_api | bool | no | This add-on can access to Hass.io REST API. It set the host alias `hassio`.
+| homeassistant_api | bool | no | This add-on can access to Hass.io Home-Assistant REST API proxy. Use `http://hassio/homeassistant/api`.
+| privileged | list | no | Privilege for access to hardware/system. Available access: `NET_ADMIN`, `SYS_ADMIN`, `SYS_RAWIO`, `SYS_TIME`, `SYS_NICE`
+| apparmor | bool | no | Enable or disable AppArmor support. If it is enable, you can also use custom profiles.
+| seccomp | bool | no | Enable or disable Seccomp support. If it is enable, you can also use custom profiles.
+| map | list | no | List of maps for additional Hass.io folders. Possible values: `config`, `ssl`, `addons`, `backup`, `share`. Defaults to `ro`, which you can change by adding `:rw` to the end of the name.
+| environment | dict | no | A dict of environment variable to run add-on.
+| audio | bool | no | Boolean. Mark this add-on to use internal an audio system. The ALSA configuration for this add-on will be mount automatic.
+| gpio | bool | no | Boolean. If this is set to True, `/sys/class/gpio` will map into add-on for access to GPIO interface from kernel. Some library need also `/dev/mem` and `SYS_RAWIO` for read/write access to this device.
+| stdin | bool | no | Boolean. If that is enable, you can use the STDIN with Hass.io API.
+| legacy | bool | no | Boolean. If the docker image have no hass.io labels, you can enable the legacy mode to use the config data.
+| options | dict | yes | Default options value of the add-on
+| schema | dict | yes | Schema for options value of the add-on. It can be `False` to disable schema validation and use custom options.
+| image | string | no | For use with Docker Hub.
+| timeout | integer | no | Default 10 (second). The timeout to wait until the docker is done or will be killed.
+| tmpfs | string | no | Mount a tmpfs file system in `/tmpfs`. Valide format for this option is : `size=XXXu,uid=N,rw`. Size is mandatory, valid units (`u`) are `k`, `m` and `g` and `XXX` has to be replaced by a number. `uid=N` (with `N` the uid number) and `rw` are optional.
+
+### {% linkable_title Options / Schema %}
+
+The `options` dictionary contains all available options and their default value. Set the default value to `null` if the value is required to be given by the user before the add-on can start, and it show it inside default values. Only nested arrays and dictionaries are supported with a deep of two size. If you want make an option optional, put `?` to the end of data type, otherwise it will be a required value.
+
+```json
+{
+ "message": "custom things",
+ "logins": [
+ { "username": "beer", "password": "123456" },
+ { "username": "cheep", "password": "654321" }
+ ],
+ "random": ["haha", "hihi", "huhu", "hghg"],
+ "link": "http://example.com/",
+ "size": 15,
+ "count": 1.2
+}
+```
+
+The `schema` looks like `options` but describes how we should validate the user input. For example:
+
+```json
+{
+ "message": "str",
+ "logins": [
+ { "username": "str", "password": "str" }
+ ],
+ "random": ["match(^\w*$)"],
+ "link": "url",
+ "size": "int(5,20)",
+ "count": "float",
+ "not_need": "str?"
+}
+```
+
+We support:
+- str
+- bool
+- int / int(min,) / int(,max) / int(min,max)
+- float / float(min,) / float(,max) / float(min,max)
+- email
+- url
+- port
+- match(REGEX)
+
+## {% linkable_title Add-on extended build %}
+
+Additional build options for an add-on is stored in `build.json`. This file will be read from our build systems.
+
+```json
+{
+ "build_from": {
+ "armhf": "homeassistant/armhf-base:latest"
+ },
+ "squash": false,
+ "args": {
+ "my_build_arg": "xy"
+ }
+}
+```
+
+| Key | Required | Description |
+| --- | -------- | ----------- |
+| build_from | no | A dictionary with the hardware architecture as the key and the base Docker image as value.
+| squash | no | Default `False`. Be carfully with this option, you can not use the image for caching stuff after that!
+| args | no | Allow to set additional Docker build arguments as a dictionary.
diff --git a/docs/hassio_addon_development.md b/docs/hassio_addon_development.md
new file mode 100644
index 00000000000..ec1f3f96748
--- /dev/null
+++ b/docs/hassio_addon_development.md
@@ -0,0 +1,23 @@
+---
+layout: page
+title: "Developing an add-on"
+description: "Steps on how-to create an add-on for Hass.io."
+date: 2017-04-30 13:28
+sidebar: true
+comments: false
+sharing: true
+footer: true
+redirect_from: /hassio/addon_development/
+---
+
+Add-ons for Hass.io allow the user to extend the functionality around Home Assistant. This can be running an application that Home Assistant can integrate with (like an MQTT broker) or to share the configuration via Samba for easy editing from other computers. Add-ons can be configured via the Hass.io panel in Home Assistant.
+
+Under the hood, add-ons are Docker images published in [Docker Hub](https://hub.docker.com/). Developers can create [GitHub](https://github.com) repositories that contain multiple references to add-ons for easy sharing with the community.
+
+1. [Tutorial: Making your first add-on](/developers/hassio/addon_tutorial/)
+1. [Configuration](/developers/hassio/addon_config/)
+1. [Communication](/developers/hassio/addon_communication/)
+1. [Local Testing](/developers/hassio/addon_testing/)
+1. [Publishing](/developers/hassio/addon_publishing/)
+1. [Presentation](/developers/hassio/addon_presentation/)
+1. [Repositories](/developers/hassio/addon_repository/)
diff --git a/docs/hassio_addon_presentation.md b/docs/hassio_addon_presentation.md
new file mode 100644
index 00000000000..e57270040a0
--- /dev/null
+++ b/docs/hassio_addon_presentation.md
@@ -0,0 +1,53 @@
+---
+layout: page
+title: "Presenting your add-on"
+description: "Details on how to present your Hass.io add-on."
+date: 2018-01-24 22:15
+sidebar: true
+comments: false
+sharing: true
+footer: true
+---
+
+If you decide to share your add-on to the public, paying attention to details is recommended. Of course, your add-on should have a proper name and description, but Hass.io also gives you some other tools to present your add-on even nicer.
+
+## {% linkable_title Adding documentation %}
+
+Good documentation helps the consumer of your add-on to understand its usage, explains configuration options, points users in the right direction in the case they have questions or issues, and contains the license under which the add-on was published.
+
+This file containing the documentation is usually referred to as the "README", which is generally published as the `README.md` file.
+
+Take a look at other projects for inspiration. For example, see the `README.md` of the [Community Hass.io Add-ons: Homebridge](https://github.com/hassio-addons/addon-homebridge/blob/master/README.md) add-on.
+
+In future versions of Hass.io, the `README.md` file will be displayed in the Home Assistant frontend.
+
+## {% linkable_title Add-on icon & logo %}
+
+A picture is worth a thousand words. Therefore, your add-on can be improved by adding a proper image icon and logo. Those images are used when showing your add-on in the Home Assistant Hass.io panel and which will significantly improve the visual representation of your add-on.
+
+Requirements for the logo of your add-on:
+
+- The logo must be in the Portable Network Graphics format (`.png`).
+- The filename must be `logo.png`.
+- It is recommended to keep the logo size around 250x100px. You may choose to use a different size or aspect ratio as you seem fit for your add-on.
+
+Requirements for the icon of your add-on:
+
+- The icon must be in the Portable Network Graphics format (`.png`).
+- The filename must be `icon.png`.
+- The aspect ratio of the icon must be 1x1 (square).
+- It is recommended to use an icon size of 128x128px.
+
+## {% linkable_title Keeping a changelog %}
+
+It is likely you are going to release newer versions of your add-on in the future. In case that happens, the users of your add-on would see an upgrade notice and probably want to know what changes were made in the latest version.
+
+A changelog is a file which contains a curated, chronologically ordered list of notable changes for each version of your add-on and is generally published as the `CHANGELOG.md` file.
+
+If you are in need of a guide on keeping a changelog, we would recommend checking the [keep a changelog](http://keepachangelog.com) website. They have developed a standard that is used by many opensource projects around the world.
+
+In future versions of Hass.io, the `CHANGELOG.md` file will be displayed in the Home Assistant frontend.
+
+## {% linkable_title Extended Security %}
+
+You can use own security profile for you Add-on with Seccomp or AppArmor. Default it is enabled and use the docker default profile. Put `apparmor` or `seccomp.json` file into your Add-on folder and it will load this file as primary profile.
diff --git a/docs/hassio_addon_publishing.md b/docs/hassio_addon_publishing.md
new file mode 100644
index 00000000000..26020a66165
--- /dev/null
+++ b/docs/hassio_addon_publishing.md
@@ -0,0 +1,65 @@
+---
+layout: page
+title: "Publishing your add-on"
+description: "Steps on how-to create an add-on for Hass.io."
+date: 2017-04-30 13:28
+sidebar: true
+comments: false
+sharing: true
+footer: true
+redirect_from: /hassio/addon_publishing/
+---
+
+There are two different ways of publishing add-ons. One is to publish pre-build containers to Docker Hub and the other option is to have users build the containers locally on their Hass.io instance.
+
+#### {% linkable_title Pre-build containers %}
+
+With pre-build containers, the developer is responsible for building the images for each architecture on their machine and push the results out to Docker Hub. This has a lot of advantages for the user. As a user it will only have to download the final container and be up and running once the download finishes. This makes the installation process fast and almost no chance of failure. This is the preferred method.
+
+We have automated the process of building and publishing add-ons. See below for the instructions.
+
+#### {% linkable_title Locally build containers %}
+
+Starting Hass.io 0.26, it is possible to distribute add-ons that will be built on the users machine. The advantage is that as a developer it is easy to test an idea and see if people are interested in your add-ons. This method includes installing and potentially compiling code. This means that installing such an add-on is slow and adds more wear and tear to users SD card/hard drive than the above mentioned pre-build solution. It also has a higher chance of failure if one of the dependencies of the container has changed or is no longer available.
+
+Use this option when you are playing with add-ons and seeing if someone is interested in your work. Once you're an established repository, please migrate to pushing builds to Docker Hub as it greatly improves the user experience. In the future we will mark locally built add-ons in the add-on store to warn users.
+
+## {% linkable_title Build scripts to publish add-ons to Docker Hub %}
+
+All add-ons are simple docker containers. Inside your add-on `config.json` you specify the Docker image that will be installed for your add-on:
+
+```json
+{
+ ...
+
+ "image": "myhub/image-{arch}-addon-name",
+
+ ...
+}
+```
+
+You can use `{arch}` inside the image name to support multiple architectures with 1 configuration file. It will be replaced with the architecture of the user when we load the image. If you use `Buildargs` you can use the `build.json` to overwrite our default args.
+
+Hass.io assumes that the `master` branch of your add-on repository matches the latest tag on Docker Hub. When you're building a new version, it's suggested that you use another branch, ie `build` or do it with a PR on GitHub. After you push the add-on to [Docker Hub](https://hub.docker.com/), you can merge this branch to master.
+
+## {% linkable_title Custom Add-ons %}
+
+You need a Docker Hub account to make your own add-ons. You can build your docker images with docker `build` command or use our script that make it simple. Pull our [builder docker engine][builder] and run one of the following commands.
+
+For a git repository:
+
+```bash
+$ docker run --rm --privileged -v ~/.docker:/root/.docker homeassistant/amd64-builder --all -t addon-folder -r https://github.com/xy/addons -b branchname
+```
+
+For a local repository:
+
+```bash
+$ docker run --rm --privileged -v ~/.docker:/root/.docker -v /my_addon:/data homeassistant/amd64-builder --all -t /data
+```
+
+
+If you are developing on macOS and using Docker for Mac, you may encounter an error message similar to the following: error creating aufs mount to /var/lib/docker/aufs/mnt/-init: invalid argument. A proposed workaround is to add the following to the Advanced Daemon JSON configuration via Docker > Preferences > Daemon > Advanced: "storage-driver" : "aufs".
+
+
+[builder]: https://github.com/home-assistant/hassio-build/tree/master/builder
diff --git a/docs/hassio_addon_repository.md b/docs/hassio_addon_repository.md
new file mode 100644
index 00000000000..9a8373fa514
--- /dev/null
+++ b/docs/hassio_addon_repository.md
@@ -0,0 +1,37 @@
+---
+layout: page
+title: "Create an add-on repository"
+description: "Add-ons repositories."
+date: 2017-04-30 13:28
+sidebar: true
+comments: false
+sharing: true
+footer: true
+redirect_from: /hassio/addon_repository/
+---
+
+An add-on repository can contain one or more add-ons. Each add-on is stored in its own unique folder. To be indentified as a repository, the repository must contain a configuration file.
+
+Check the [Example add-on repository](https://github.com/home-assistant/hassio-addons-example) for further details.
+
+## {% linkable_title Installing a repository %}
+
+A user can add a repository by going to the Hass.io panel in Home Assistant, clicking on the store icon in the top right, copy/paste the URL of your repostory into the repository textarea and click on **Save**.
+
+## {% linkable_title Repository configuration %}
+
+Each repository is required to contain `repository.json` at the root in the git repository.
+
+```json
+{
+ "name": "Name of repository",
+ "url": "http://www.example/addons",
+ "maintainer": "HomeAssistant Team "
+}
+```
+
+| Key | Required | Description |
+| --- | -------- | ----------- |
+| name | yes | Name of the repository
+| url | no | Homepage of the repository. Here you can explain the various add-ons.
+| maintainer | no | Contact info of the maintainer.
diff --git a/docs/hassio_addon_testing.md b/docs/hassio_addon_testing.md
new file mode 100644
index 00000000000..f2f562f4431
--- /dev/null
+++ b/docs/hassio_addon_testing.md
@@ -0,0 +1,37 @@
+---
+layout: page
+title: "Local add-on testing"
+description: "Instructions on how to test your add-on locally."
+date: 2017-04-30 13:28
+sidebar: true
+comments: false
+sharing: true
+footer: true
+redirect_from: /hassio/addon_testing/
+---
+
+The fastest way to develop add-ons is by adding them to your local add-on repository. To access your local add-on repository, install either the [Samba add-on] or [SSH add-on].
+
+Right now add-ons will work with images that are stored on Docker Hub (using `image` from add-on config). Without `image` inside local add-ons repository it to be built on the device.
+
+## {% linkable_title Local build %}
+
+You can build and try the addon on your developer machine also. Move all addon stuff into a temp folder. If you use `FROM $BUILD_FROM` you need set a base image with build args. Normally you can use follow base images:
+
+- armhf: `homeassistant/armhf-base:latest`
+- aarch64: `homeassistant/aarch64-base:latest`
+- amd64: `homeassistant/amd64-base:latest`
+- i386: `homeassistant/i386-base:latest`
+
+Use `docker` to build the test addon: `docker build --build-arg BUILD_FROM="homeassistant/amd64-base:latest" -t local/my-test-addon .`
+
+## {% linkable_title Local run %}
+
+Create a new folder for data and add a test _options.json_ file. After that you can run your add-on with: `docker run --rm -v /tmp/my_test_data:/data -p PORT_STUFF_IF_NEEDED local/my-test-addon`
+
+## {% linkable_title Logs %}
+
+All stdout and stderr are redirected to the Docker logs. The logs can be fetched from the add-on page inside the Hass.io panel in Home Assistant.
+
+[Samba add-on]: /addons/samba/
+[SSH add-on]: /addons/ssh/
diff --git a/docs/hassio_addon_tutorial.md b/docs/hassio_addon_tutorial.md
new file mode 100644
index 00000000000..0a30b2a60d0
--- /dev/null
+++ b/docs/hassio_addon_tutorial.md
@@ -0,0 +1,208 @@
+---
+layout: page
+title: "Tutorial: Making your first add-on"
+description: "Easy tutorial to get started making your first add-on."
+date: 2017-05-12 13:28
+sidebar: true
+comments: false
+sharing: true
+footer: true
+redirect_from: /hassio/addon_tutorial/
+---
+
+So you've got Home Assistant going and you've been enjoying the built-in add-ons but you're missing this one application. Time to make your own add-on! In Hass.io 0.24 we introduced the option to have local add-ons be build on your device. This is great for developing new add-ons locally.
+
+To get started with developing add-ons, we first need access to where Hass.io looks for local add-ons. For this you can use the Samba add-on or the SSH add-on.
+
+For Samba, once you have enabled and started it, your Hass.io instance will show up in your local network tab and share a folder called "addons". This is the folder to store your custom add-ons.
+
+If you are on macOS and the folder is not showing up automatically, go to Finder and press CMD+K then enter 'smb://hassio.local'
+
+
+
+With Samba add-on enabled, you can browse to your Hass.io server over the local network. It will contain an addons folder to store your local add-ons.
+
+
+For SSH, you will have to install it. Before you can start it, you will have to have a private/public key pair and store your public key in the add-on config ([see docs for more info][ssh]). Once started, you can SSH to Hass.io and store your custom add-ons in "/addons".
+
+
+
+Once you SSH into your Hass.io box, you have access to your add-ons in "/addons".
+
+
+Once you have located your add-on directory, it's time to get started!
+
+[ssh]: /addons/ssh/
+
+## {% linkable_title Step 1: The basics %}
+
+ - Create a new directory called `hello_world`
+ - Inside that directory create three files.
+
+`Dockerfile`:
+```
+ARG BUILD_FROM
+FROM $BUILD_FROM
+
+ENV LANG C.UTF-8
+
+# Copy data for add-on
+COPY run.sh /
+RUN chmod a+x /run.sh
+
+CMD [ "/run.sh" ]
+```
+
+`config.json`:
+```json
+{
+ "name": "Hello world",
+ "version": "1",
+ "slug": "hello_world",
+ "description": "My first real add-on!",
+ "startup": "before",
+ "boot": "auto",
+ "options": {},
+ "schema": {}
+}
+```
+
+`run.sh`:
+```bash
+echo Hello world!
+```
+
+## {% linkable_title Step 2: Installing and testing your add-on %}
+
+Now comes the fun part, time to open the Hass.io UI and install and run your add-on.
+
+ - Open the Home Assistant frontend
+ - Go to the Hass.io panel
+ - On the top right click the shopping basket to go to the add-on store.
+
+
+
+From the Hass.io main panel open the add-on store.
+
+
+ - On the top right click the refresh button
+ - You should now see a new card called "Local" that lists your add-on!
+
+
+
+The Hass.io add-on store will list all available local add-ons.
+
+
+ - Click on your add-on to go to the add-on details page.
+ - Install your add-on
+ - Start your add-on
+ - Refresh the logs of your add-on, you should now see "Hello world!" in your logs.
+
+
+
+The add-on will print Hello world to the logs and then quit.
+
+
+### {% linkable_title I don't see my add-on?! %}
+
+Oops! You clicked refresh in the store and your add-on didn't show up. Or maybe you just updated an option, clicked refresh and saw your add-on disappear.
+
+When this happens, it means that your `config.json` is invalid. It's either invalid JSON or one of the specified options is incorrect. To see what went wrong, go to the Hass.io panel and in the supervisor card click on "View logs". This should bring you to a page with the logs of the supervisor. Scroll to the bottom and you should be able to find the validation error.
+
+Once you fixed the error, go to the add-on store and click refresh again.
+
+## {% linkable_title Step 3: Hosting a server %}
+
+Until now we've been able to do some basic stuff, but it's not very useful yet. So let's take it one step further and host a server that we expose on a port. For this we're going to use the built-in HTTP server that comes with Python 3.
+
+To do this, we will need to update our files as follows:
+
+ - `Dockerfile`: Install Python 3
+ - `config.json`: Make the port from the container available on the host
+ - `run.sh`: Run the Python 3 command to start the HTTP server
+
+Add to your `Dockerfile` before `RUN`:
+
+```
+# Install requirements for add-on
+RUN apk add --no-cache python3
+
+# Python 3 HTTP Server serves the current working dir
+# So let's set it to our add-on persistent data directory.
+WORKDIR /data
+```
+
+Add "ports" to `config.json`. This will make TCP on port 8000 inside the container available on the host on port 8000.
+
+```json
+{
+ "name": "Hello world",
+ "version": "0.2",
+ "slug": "hello_world",
+ "description": "My first real add-on!",
+ "startup": "before",
+ "boot": "auto",
+ "options": {},
+ "schema": {},
+ "ports": {
+ "8000/tcp": 8000
+ }
+}
+```
+
+Update `run.sh` to start the Python 3 server:
+
+```
+python3 -m http.server
+```
+
+## {% linkable_title Step 4: Installing the update %}
+
+Since we updated the version number in our `config.json`, Home Assistant will show an update button when looking at the add-on details. You might have to refresh your browser or click the refresh button in the add-on store for it to show up. If you did not update the version number, you can also uninstall and install the add-on again. After installing the add-on again, make sure you start it.
+
+Now navigate to [http://hassio.local:8000](http://hassio.local:8000) to see our server in action!
+
+
+
+The Python 3 server will allow you to browse the /data folder.
+
+
+## {% linkable_title Bonus: Working with add-on options %}
+
+In the screenshot you've probably seen that our server only served up 1 file: `options.json`. This file contains the user configuration for this add-on. Because we specified an empty "config" and "schema" in our `config.json`, the file is currently empty.
+
+Let's see if we can get some data into that file!
+
+To do this, we need to specify the default options and a schema for the user to change the options.
+
+Change the options and schema entries in your `config.json` with the following:
+
+```json
+{
+ …
+
+ "options": {
+ "beer": true,
+ "wine": true,
+ "liquor": false,
+ "name": "world",
+ "year": 2017
+ },
+ "schema": {
+ "beer": "bool",
+ "wine": "bool",
+ "liquor": "bool",
+ "name": "str",
+ "year": "int"
+ },
+
+ …
+}
+```
+
+Refresh the add-on store and re-install your add-on. You will now see the options available in the add-on config screen. When you now go back to our Python 3 server and download `options.json`, you'll see the options you set.
+
+ - [Learn more about the available schema options.](/hassio/addon_config/#options--schema)
+ - [See how options.json can be used inside `run.sh`](https://github.com/home-assistant/hassio-addons/blob/master/mosquitto/run.sh#L4-L6)
+
+### [Next step: Add-on config reference »](/developers/hassio/addon_config/)
diff --git a/docs/hassio_architecture.md b/docs/hassio_architecture.md
new file mode 100644
index 00000000000..173e3657ae3
--- /dev/null
+++ b/docs/hassio_architecture.md
@@ -0,0 +1,39 @@
+---
+layout: page
+title: "Hass.io Architecture"
+description: "The architecture of Hass.io."
+date: 2017-04-30 13:28
+sidebar: true
+comments: false
+sharing: true
+footer: true
+redirect_from: /hassio/architecture/
+---
+
+
+
+ Architecture overview of Hass.io
+
+
+### {% linkable_title Host Control (HC) %}
+
+This is a daemon running on the host machine that allows the supervisor to control certain aspects of the host OS:
+
+ - Power cycle (restart, turn off)
+ - Manage network settings
+ - Local updates
+
+### {% linkable_title Host %}
+
+Our pre-build images are based on [ResinOS]. Any Linux machine can be turned into a Hass.io host by running [the installer][linux].
+
+### {% linkable_title Supervisor %}
+
+The supervisor offers an API to manage the host and running the Docker containers.
+
+### {% linkable_title Configuration panel %}
+
+The configuration panel lives inside the supervisor but is accessible via the Home Assistant user interface. The configuration panel allows the user to manage the installation.
+
+[ResinOS]: https://resinos.io/
+[linux]: /hassio/installation/#alternative-install-on-generic-linux-server
diff --git a/docs/hassio_debugging.md b/docs/hassio_debugging.md
new file mode 100644
index 00000000000..8dde1fbaa83
--- /dev/null
+++ b/docs/hassio_debugging.md
@@ -0,0 +1,55 @@
+---
+layout: page
+title: "Debugging Hass.io"
+description: "Tips and tricks for when things go wrong."
+date: 2017-04-30 13:28
+sidebar: true
+comments: false
+sharing: true
+footer: true
+redirect_from: /hassio/debugging/
+---
+
+
+This section is not for users. Use the [SSH add-on] to SSH into Hass.io. This is for developers of Hass.io. Do not ask for support if you are using these options.
+
+
+[SSH add-on]: /addons/ssh/
+
+The following debug tips and tricks are for people who are running the Hass.io image and are working on the base image. If you use the generic Linux installer script, you should be able to access your host and logs as per your host.
+
+## {% linkable_title SSH access to the host %}
+
+Create an `authorized_keys` file containing your public key, and place it in the root of the boot partition of your SD card. Once the device is booted, you can access your device as root over SSH on port 22222.
+
+Windows instructions how to generate and use private/public keys with Putty are [here][windows-keys]. Instead of the droplet instructions, add the public key as per above instructions.
+
+Alternative instructions, for Mac, Windows and Linux can be found [here](https://help.github.com/articles/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent/#platform-mac).
+
+Follow steps 1-4 under 'Generating a new SSH key' (The other sections are not applicable to Hass.io and can be ignored.)
+
+Step 3 in the link above, shows the path to the private key file `id_rsa` for your chosen operating system. Your public key, `id_rsa.pub`, is saved in the same folder. Next, select all text from text box "Public key for pasting into OpenSSH authorized_keys file" and save it to the root of your SD card as `authorized_keys`.
+
+
+Make sure when you are copying the public key to the root of the /resin-boot partition of the SD card that you rename the file correctly to `authorized_keys` with no `.pub` file extension.
+
+
+You should then be able to SSH into your Hass.io device. On mac/linux, use:
+```
+ssh root@hassio.local -p 22222
+```
+
+## {% linkable_title Checking the logs %}
+
+```bash
+# Logs from the supervisor service on the Host OS
+journalctl -f -u resin-supervisor.service
+
+# Hass.io supervisor logs
+docker logs resin_supervisor
+
+# Home Assistant logs
+docker logs homeassistant
+```
+
+[windows-keys]: https://www.digitalocean.com/community/tutorials/how-to-use-ssh-keys-with-putty-on-digitalocean-droplets-windows-users
diff --git a/docs/index.md b/docs/index.md
new file mode 100644
index 00000000000..c801866e6aa
--- /dev/null
+++ b/docs/index.md
@@ -0,0 +1,26 @@
+---
+layout: page
+title: "Developers"
+description: "Everything you need to know to get started with Home Assistant development."
+date: 2016-04-16 10:28 +07:00
+sidebar: true
+comments: false
+sharing: true
+footer: true
+og_image: /images/architecture/component_interaction.png
+---
+
+Welcome to the Home Assistant development documentation. This is the place to learn all about how Home Assistant works and how you can extend it with support for your devices and services!
+
+
+
+Diagram showing interaction between components and the Home Assistant core.
+
+
+The best way to familiarize yourself with Home Assistant is to watch the PyCon 2016 talk about Home Assistant and read through the [Python API docs].
+
+
+
+
+
+[Python API docs]: https://dev-docs.home-assistant.io
diff --git a/docs/intent_conversation.md b/docs/intent_conversation.md
new file mode 100644
index 00000000000..38d02fe337a
--- /dev/null
+++ b/docs/intent_conversation.md
@@ -0,0 +1,27 @@
+---
+layout: page
+title: "Registering sentences"
+description: "Register sentences with the conversation component."
+date: 2017-07-23 20:00
+sidebar: true
+comments: false
+sharing: true
+footer: true
+---
+
+The conversation component handles incoming commands from the frontend and converts them to intents. It does this based on registered sentences.
+
+As a component, you can register sentences with the conversation component to allow it to be remote controlled. Refer to named slots by putting the slot name between curly braces: `{item}`.
+
+Example code:
+
+```python
+@asyncio.coroutine
+def async_setup(hass, config):
+ hass.components.conversation.async_register('MyCoolIntent', [
+ 'I think that {object} is very cool',
+ 'Nothing is cooler than {object}'
+ ])
+```
+
+If a sentence like "I think that beer is very cool" comes in, the conversation component will generate an intent of type `MyCoolIntent` and with 1 slot, named `object` and value `beer`.
diff --git a/docs/intent_firing.md b/docs/intent_firing.md
new file mode 100644
index 00000000000..17e80678b4b
--- /dev/null
+++ b/docs/intent_firing.md
@@ -0,0 +1,59 @@
+---
+layout: page
+title: "Firing intents"
+description: "How to fire intents to be handled by Home Assistant."
+date: 2017-07-23 20:00
+sidebar: true
+comments: false
+sharing: true
+footer: true
+---
+
+When you fire an intent, you will get a response back or an error will be raised. It is up to the component to return the result to the user.
+
+Example code to handle an intent in Home Assistant.
+
+```python
+from homeassistant.helpers import intent
+
+intent_type = 'TurnLightOn'
+slots = {
+ 'entity': { 'value': 'Kitchen' }
+}
+
+try:
+ intent_response = yield from intent.async_handle(
+ hass, 'example_component', intent_type, slots
+ )
+
+except intent.UnknownIntent as err:
+ _LOGGER.warning('Received unknown intent %s', intent_type)
+
+except intent.InvalidSlotInfo as err:
+ _LOGGER.error('Received invalid slot data: %s', err)
+
+except intent.IntentError:
+ _LOGGER.exception('Error handling request for %s', intent_type)
+```
+
+The intent response is an instance of `homeassistant.helpers.intent.IntentResponse`.
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| `intent` | Intent | Instance of intent that triggered response. |
+| `speech` | Dictionary | Speech responses. Each key is a type. Allowed types are `plain` and `ssml`. |
+| `card` | Dictionary | Card responses. Each key is a type. |
+
+Speech dictionary values:
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| `speech` | String | The text to say
+| `extra_data` | Any | Extra information related to this speech.
+
+Card dictionary values:
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| `title` | String | The title of the card
+| `content` | Any | The content of the card
diff --git a/docs/intent_handling.md b/docs/intent_handling.md
new file mode 100644
index 00000000000..c341f6ef178
--- /dev/null
+++ b/docs/intent_handling.md
@@ -0,0 +1,49 @@
+---
+layout: page
+title: "Handling intents"
+description: "How to handle intents that are fired in Home Assistant."
+date: 2017-07-23 20:00
+sidebar: true
+comments: false
+sharing: true
+footer: true
+---
+
+Any component can register to handle intents. This allows a single component to handle intents fired from multiple voice assistants.
+
+A component has to register an intent handler for each type that it wants to handle. Intent handlers have to extend `homeassistant.helpers.intent.IntentHandler`
+
+```python
+import asyncio
+from homeassistant.helpers import intent
+
+DATA_KEY = 'example_key'
+
+@asyncio.coroutine
+def async_setup(hass, config):
+ hass.data[DATA_KEY] = 0
+ intent.async_register(hass, CountInvocationIntent())
+
+
+class CountInvocationIntent(intent.IntentHandler):
+ """Handle CountInvocationIntent intents."""
+
+ # Type of intent to handle
+ intent_type = 'CountInvocationIntent'
+
+ # Optional. A validation schema for slots
+ # slot_schema = {
+ # 'item': cv.string
+ # }
+
+ @asyncio.coroutine
+ def async_handle(self, intent_obj):
+ """Handle the intent."""
+ intent_obj.hass.data[DATA_KEY] += 1
+
+ response = intent_obj.create_response()
+ response.async_set_speech(
+ "This intent has been invoked {} times".format(
+ intent_obj.hass.data[DATA_KEY]))
+ return response
+```
diff --git a/docs/intent_index.md b/docs/intent_index.md
new file mode 100644
index 00000000000..a454deecbcc
--- /dev/null
+++ b/docs/intent_index.md
@@ -0,0 +1,37 @@
+---
+layout: page
+title: "Intents"
+description: "Intents are helping Home Assistant to gather "
+date: 2017-07-23 20:00
+sidebar: true
+comments: false
+sharing: true
+footer: true
+---
+
+An intent is a description of a user's intention. Intents are generated by user actions, like asking Amazon Echo to turn on a light.
+
+
+
+Architectural overview of intents in Home Assistant
+
+
+Intents are fired by components that receive them from external sources/services. Conversation, Alexa, API.ai and Snips are currently sourcing intents.
+
+Any component can handle intents. This makes it very easy for developers to integrate with all voice assistants at once.
+
+Intents are implemented using the `homeassistant.helpers.intent.Intent` class. It contains the following properties:
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| `hass` | Home Assistant | The Home Assistant instance that fired the intent.
+| `platform` | string | The platform that fired the intent
+| `intent_type` | string | The type (name) of the intent
+| `slots` | dictionary | Contains the slot values keyed by slot name.
+| `text_input` | string | Optional. The raw text input that initiated the intent.
+
+Description of the slots dictionary values.
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| Value | anything | Value of the slot.
diff --git a/docs/internationalization_backend_localization.md b/docs/internationalization_backend_localization.md
new file mode 100644
index 00000000000..f50d797045a
--- /dev/null
+++ b/docs/internationalization_backend_localization.md
@@ -0,0 +1,51 @@
+---
+layout: page
+title: "Backend Localization"
+description: "Translating platforms in Home Assistant"
+date: 2018-03-01 18:00
+sidebar: true
+comments: false
+sharing: true
+footer: true
+ha_release: 0.64
+---
+
+## {% linkable_title Translation Strings %}
+Platform translation strings are stored as JSON in the [home-assistant](https://github.com/home-assistant/home-assistant) repository. These files must be located adjacent to the component/platform they belong to. Components must have their own directory, and the file is simply named `strings.json` in that directory. For platforms, they are named `strings..json` in the platform directory. This file will contain the different strings that will be translatable.
+
+In order to test changes to translation files, the translation strings must be compiled into Home Assistant’s translation directories by running the following script:
+
+```bash
+$ script/translations_develop
+```
+
+After the pull request with the strings file is merged into the `dev` branch, the strings will be automatically uploaded to Lokalise, where contributors can submit translations. The translated strings in Lokalise will be periodically pulled in to the home-assistant repository.
+
+## {% linkable_title States Localization %}
+The first step when localizing platform states is to ensure that the states defined in the actual platform code are defined in `snake_case`. The states should not contain capital letters or spaces. Next, the strings file needs to be created. The states should exist under the `state` key, and map the backend state keys to their English translations. [The season sensor localization](https://github.com/home-assistant/home-assistant/pull/12453/commits/bb2f328ce10c3867990e34a88da64e2f8dc7a5c4) is a good example.
+
+## {% linkable_title Configuration Flow Localization %}
+The translation strings for the configuration flow handler are defined under the `config` key. An example strings file below describes the different supported keys:
+
+```json
+{
+ "config": {
+ "title": "This title is shown in the integrations list",
+ "step": {
+ "init": {
+ "title": "The user visible title of the `init` step.",
+ "description": "Markdown that is shown with the step.",
+ "data": {
+ "api_key": "The label for the `api_key` input field"
+ }
+ }
+ },
+ "error": {
+ "invalid_api_key": "This message will be displayed if `invalid_api_key` is returned as a flow error."
+ },
+ "abort": {
+ "stale_api_key": "This message will be displayed if `stale_api_key` is returned as the abort reason."
+ }
+ }
+}
+```
diff --git a/docs/internationalization_custom_component_localization.md b/docs/internationalization_custom_component_localization.md
new file mode 100644
index 00000000000..b7d12664d4d
--- /dev/null
+++ b/docs/internationalization_custom_component_localization.md
@@ -0,0 +1,20 @@
+---
+layout: page
+title: "Custom Component Localization"
+description: "Translating custom components in Home Assistant"
+date: 2018-03-01 18:00
+sidebar: true
+comments: false
+sharing: true
+footer: true
+ha_release: 0.64
+---
+
+## {% linkable_title Translation Strings %}
+Unlike localized strings merged in the home-assistant repository, custom components cannot take advantage of Lokalise for user submitted translations. However, custom component authors can still include translation with their components. These will be read from the `.translations` directory, adjacent to the component source file. They are named `..json`, unless the custom component exists in its own directory, in which case the file is simply named `.json` in the `.translations` directory.
+
+These files follow the same formatting as [backend translation string files](/developers/internationalization/backend_localization/), but a copy will exist for each translated language.
+
+The language codes follow the [BCP47](https://tools.ietf.org/html/bcp47) format. The [frontend translation files](https://github.com/home-assistant/home-assistant-polymer/tree/master/translations) can also be referred to if you are unsure of the correct language code to use.
+
+The frontend will serve these files after Home Assistant is restarted.
diff --git a/docs/internationalization_index.md b/docs/internationalization_index.md
new file mode 100644
index 00000000000..109502fe458
--- /dev/null
+++ b/docs/internationalization_index.md
@@ -0,0 +1,19 @@
+---
+layout: page
+title: "Internationalization"
+description: "Home Assistant internationalization summary"
+date: 2018-03-01 18:00
+sidebar: true
+comments: false
+sharing: true
+footer: true
+ha_release: 0.64
+---
+
+The Home Assistant internationalization project includes preparing platforms and the frontend for localization, as well as the actual translation of localized strings.
+
+Some compmonents and platforms will have strings that need to be localized specifically for that platform. These strings are managed in the core [home-assistant](https://github.com/home-assistant/home-assistant) repository. The Home Assistant backend will serve strings to the clients based on the loaded components in the running instance.
+
+There are also localizable strings that exist only on the frontend. These strings are managed in the [home-assistant-polymer](https://github.com/home-assistant/home-assistant-polymer) repository. These strings are stored with the frontend and don’t depend on the backend configuration.
+
+Our strings are translated by the community using the online translation tool [Lokalise](https://lokalise.co/).
diff --git a/docs/internationalization_translation.md b/docs/internationalization_translation.md
new file mode 100644
index 00000000000..334a68e6aa3
--- /dev/null
+++ b/docs/internationalization_translation.md
@@ -0,0 +1,53 @@
+---
+layout: page
+title: "Translation"
+description: "How to translate Home Assistant."
+date: 2017-10-27 13:00
+sidebar: true
+comments: false
+sharing: true
+footer: true
+ha_release: 0.57
+redirect_from: /developers/frontend_translation/
+---
+
+## {% linkable_title How to start %}
+Translations for Home Assistant are managed through Lokalise, an online translation management tool. Our translations are split between two projects, a backend project for platform-specific translations, and a frontend project for UI translations. Click the links below to join both projects! Even if your language is completely translated, extra proofreading is a big help! Please feel free to review the existing translations, and vote for alternatives that might be more appropriate.
+
+- [Join the frontend translation team](https://lokalise.co/signup/3420425759f6d6d241f598.13594006/all/)
+- [Join the backend translation team](https://lokalise.co/signup/130246255a974bd3b5e8a1.51616605/all/)
+
+For more information about the translation workflow, please see the [Lokalise translation workflow documents](https://docs.lokalise.co/category/iOzEuQPS53-for-team-leads-and-translators).
+
+
+The translation of the Home Assistant frontend is still a work in progress. More phrases will be available for translation soon.
+
+
+## {% linkable_title Translation placeholders %}
+
+Some translation strings will contain special placeholders that will be replaced later. Placeholders shown in square brackets `[]` are [Lokalise key references](https://docs.lokalise.co/article/KO5SZWLLsy-key-referencing). These are primarily used to link translation strings that will be duplicated. Different languages may not have the same duplicates as English, and are welcome to link duplicate translations that are not linked in English. Placeholders shown in curly brackets `{}` are [translation arguments](https://formatjs.io/guides/message-syntax/) that will be replaced with a live value when Home Assistant is running. Any translation argument placeholders present in the original string must be included in the translated string. These may include special syntax for defining plurals or other replacement rules. The linked format.js guide explains the syntax for adding plural definitions and other rules.
+
+## {% linkable_title Rules %}
+1. Only native speakers should submit translations.
+2. Stick to [Material Design guidelines](https://material.io/guidelines/style/writing.html).
+3. Don't translate or change proper nouns like `Home Assistant`, `Hass.io` or `Hue`.
+4. For a region specific translation, keys that will be the same as the base translation should be filled with `[VOID]`. These will be replaced during our translation build process.
+5. Translations under the `state_badge` keys will be used for the notification badge display. These translations should be short enough to fit in the badge label without overflowing. This can be tested in the Home Assistant UI either by editing the label text with your browsers development tools, or by using the States developer tool in the Home Assistant UI. In the UI, enter a new entity ID (`device_tracker.test`), and enter the text you want to test in state.
+6. If text will be duplicated across different translation keys, make use of the Lokalise key reference feature where possible. The base translation provides examples of this underneath the `states` translations. Please see the [Lokalise key referencing](https://docs.lokalise.co/article/KO5SZWLLsy-key-referencing) documentation for more details.
+
+## {% linkable_title Adding a new language %}
+If your language is not listed you can request it at [GitHub](https://github.com/home-assistant/home-assistant-polymer/issues/new). Please provide both the English name and the native name for your language. For example:
+```
+English Name: German
+Native Name: Deutsch
+```
+
+
+Region specific translations (`en-US`, `fr-CA`) will only be included if translations for that region need to differ from the base language translation.
+
+
+### {% linkable_title Maintainer steps to add a new language %}
+1. Language tags have to follow [BCP 47](https://tools.ietf.org/html/bcp47). A list of most language tags can be found here: [IANA sutbtag registry](http://www.iana.org/assignments/language-subtag-registry/language-subtag-registry). Examples: `fr`, `fr-CA`, `zh-Hans`. Only include the country code if country specific overrides are being included, and the base language is already translated.
+2. Add the language tag and native name in `src/translations/translationMetadata.json`. Examples: "Français", "Français (CA)"
+3. Add the new language in Lokalize.
+Note: Sometimes you have to change the tag in Lokalise (Language -> Language settings -> custom ISO code).
diff --git a/docs/maintenance.md b/docs/maintenance.md
new file mode 100644
index 00000000000..4995e7de51c
--- /dev/null
+++ b/docs/maintenance.md
@@ -0,0 +1,52 @@
+---
+layout: page
+title: "Maintenance"
+description: "Steps involved to maintain the current state of Home Assistant."
+date: 2016-09-13 17:00
+sidebar: true
+comments: false
+sharing: true
+footer: true
+---
+
+This page documents a couple of points for maintaining the Home Assistant code. Most of the tasks don't need to be performed on a regular base thus the steps, used tools, or details are preserved here.
+
+## {% linkable_title Source code %}
+
+### {% linkable_title Line separator %}
+
+People are using various operating systems to develop components and platforms for Home Assistant. This could lead to different line endings on file. We prefer `LN`. Especially Microsoft Windows tools tend to use `CRLF`.
+
+```bash
+$ find homeassistant -name "*.py" -exec file {} \; | grep BOM
+$ find homeassistant -name "*.py" -exec file {} \; | grep CRLF
+```
+
+To fix the line separator, use `dos2unix` or `sed`.
+
+```bash
+$ dos2unix homeassistant/components/notify/kodi.py
+```
+
+### {% linkable_title File permissions %}
+
+Most files don't need to the be executable. `0644` is fine.
+
+### {% linkable_title Dependencies %}
+
+A lot of components and platforms depends on third-party Python modules. The dependencies which are stored in the `requirements_*.txt` files are tracked by [gemnasium](https://gemnasium.com/github.com/home-assistant/home-assistant) and [Requires.io](https://requires.io/github/home-assistant/home-assistant/requirements/?branch=dev).
+
+If you update the requirements of a component/platform through the `REQUIREMENTS = ['modules-xyz==0.3']` entry, run the provided script to update the `requirements_*.txt` file(s).
+
+```bash
+$ script/gen_requirements_all.py
+```
+
+Start a test run of Home Assistant. If that was successful, include all files in a Pull Request. Add a short summary of the changes, a sample configuration entry, details about the tests you performed to ensure the update works, and other useful information to the description.
+
+
+## {% linkable_title Documentation %}
+
+- Merge `current` into `next` on a regular base.
+- Optimize the images.
+
diff --git a/docs/platform_example_light.md b/docs/platform_example_light.md
new file mode 100644
index 00000000000..8a11eec73f5
--- /dev/null
+++ b/docs/platform_example_light.md
@@ -0,0 +1,124 @@
+---
+layout: page
+title: "Example light platform"
+description: "Minimum implementation of a Home Assistant platform."
+date: 2016-04-16 14:24 -07:00
+sidebar: true
+comments: false
+sharing: true
+footer: true
+---
+
+This example is for adding support for the imaginary Awesome Lights. It shows the different best practices for developing a platform.
+
+Similar to Example Sensor Platform, copy the code below, and create it as a file in `/custom_components/light/awesomelights.py`.
+
+Add the following to your configuration.yaml:
+
+```yaml
+light:
+ - platform: awesomelights
+ host: HOST_HERE
+ username: USERNAME_HERE
+ password: PASSWORD_HERE_OR_secrets.yaml
+```
+
+Note the `platform` name matches the filename for the source code.
+
+```python
+import logging
+
+import voluptuous as vol
+
+# Import the device class from the component that you want to support
+from homeassistant.components.light import ATTR_BRIGHTNESS, Light, PLATFORM_SCHEMA
+from homeassistant.const import CONF_HOST, CONF_USERNAME, CONF_PASSWORD
+import homeassistant.helpers.config_validation as cv
+
+# Home Assistant depends on 3rd party packages for API specific code.
+REQUIREMENTS = ['awesome_lights==1.2.3']
+
+_LOGGER = logging.getLogger(__name__)
+
+# Validation of the user's configuration
+PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
+ vol.Required(CONF_HOST): cv.string,
+ vol.Optional(CONF_USERNAME, default='admin'): cv.string,
+ vol.Optional(CONF_PASSWORD): cv.string,
+})
+
+
+def setup_platform(hass, config, add_devices, discovery_info=None):
+ """Setup the Awesome Light platform."""
+ import awesomelights
+
+ # Assign configuration variables. The configuration check takes care they are
+ # present.
+ host = config.get(CONF_HOST)
+ username = config.get(CONF_USERNAME)
+ password = config.get(CONF_PASSWORD)
+
+ # Setup connection with devices/cloud
+ hub = awesomelights.Hub(host, username, password)
+
+ # Verify that passed in configuration works
+ if not hub.is_valid_login():
+ _LOGGER.error("Could not connect to AwesomeLight hub")
+ return False
+
+ # Add devices
+ add_devices(AwesomeLight(light) for light in hub.lights())
+
+
+
+class AwesomeLight(Light):
+ """Representation of an Awesome Light."""
+
+ def __init__(self, light):
+ """Initialize an AwesomeLight."""
+ self._light = light
+ self._name = light.name
+ self._state = None
+ self._brightness = None
+
+ @property
+ def name(self):
+ """Return the display name of this light."""
+ return self._name
+
+ @property
+ def brightness(self):
+ """Return the brightness of the light.
+
+ This method is optional. Removing it indicates to Home Assistant
+ that brightness is not supported for this light.
+ """
+ return self._brightness
+
+ @property
+ def is_on(self):
+ """Return true if light is on."""
+ return self._state
+
+ def turn_on(self, **kwargs):
+ """Instruct the light to turn on.
+
+ You can skip the brightness part if your light does not support
+ brightness control.
+ """
+ self._light.brightness = kwargs.get(ATTR_BRIGHTNESS, 255)
+ self._light.turn_on()
+
+ def turn_off(self, **kwargs):
+ """Instruct the light to turn off."""
+ self._light.turn_off()
+
+ def update(self):
+ """Fetch new state data for this light.
+
+ This is the only method that should fetch new data for Home Assistant.
+ """
+ self._light.update()
+ self._state = self._light.is_on()
+ self._brightness = self._light.brightness
+```
diff --git a/docs/platform_example_sensor.md b/docs/platform_example_sensor.md
new file mode 100644
index 00000000000..166b3071178
--- /dev/null
+++ b/docs/platform_example_sensor.md
@@ -0,0 +1,66 @@
+---
+layout: page
+title: "Example sensor platform"
+description: "Minimum implementation of a Home Assistant platform."
+date: 2016-04-16 14:24 -07:00
+sidebar: true
+comments: false
+sharing: true
+footer: true
+---
+
+This is a minimum implementation of a platform for the sensor component.
+
+### {% linkable_title Installation %}
+
+Copy the code below and create it as a file in `/custom_components/sensor/example.py`.
+
+Add the following to your `configuration.yaml` file:
+
+```yaml
+# Example configuration.yaml entry
+sensor:
+ platform: example
+```
+
+### {% linkable_title Code %}
+
+```python
+from homeassistant.const import TEMP_CELSIUS
+from homeassistant.helpers.entity import Entity
+
+
+def setup_platform(hass, config, add_devices, discovery_info=None):
+ """Setup the sensor platform."""
+ add_devices([ExampleSensor()])
+
+
+class ExampleSensor(Entity):
+ """Representation of a Sensor."""
+
+ def __init__(self):
+ """Initialize the sensor."""
+ self._state = None
+
+ @property
+ def name(self):
+ """Return the name of the sensor."""
+ return 'Example Temperature'
+
+ @property
+ def state(self):
+ """Return the state of the sensor."""
+ return self._state
+
+ @property
+ def unit_of_measurement(self):
+ """Return the unit of measurement."""
+ return TEMP_CELSIUS
+
+ def update(self):
+ """Fetch new state data for the sensor.
+
+ This is the only method that should fetch new data for Home Assistant.
+ """
+ self._state = 23
+```
diff --git a/docs/releasing.md b/docs/releasing.md
new file mode 100644
index 00000000000..5ddce854181
--- /dev/null
+++ b/docs/releasing.md
@@ -0,0 +1,74 @@
+---
+layout: page
+title: "Releasing"
+description: "Steps involved publishing a new Home Assistant release."
+date: 2016-07-13 17:00
+sidebar: true
+comments: false
+sharing: true
+footer: true
+---
+
+This page describes the steps for publishing a new Home Assistant release. Those steps requires that you don't use forks but work with the repositories themself. The [hass-release](https://github.com/home-assistant/hass-release) script is a helper to do a release.
+
+### {% linkable_title Release preparation (3 days before release) %}
+
+### {% linkable_title GitHub %}
+
+1. Merge `master` into `dev` to make the PR mergeable.
+1. Cut a release branch from `dev`. Example name `release-0-57`.
+1. Create a pull request from the release branch to `master` with the upcoming release number as the title.
+1. Update `homeassistant/const.py` with the correct version number (remove the `dev` tag) and push that commit to release branch.
+
+### {% linkable_title Website %}
+
+1. Merge `current` into `next`
+1. Cut release branch of `next`. For example `release-0-57`.
+1. Open a PR from release branch to `current` with the upcoming release number as the title.
+
+## {% linkable_title Release day %}
+
+From creating the release branch till it has been merged, we tag bugfixes with the milestone for the release (create if doesn't exist).
+
+### {% linkable_title GitHub %}
+
+1. Cherry-pick the milestoned PRs that need to get into the release `python3 -m hassrelease milestone_cherry_pick 0.57`
+1. Run `python3 -m hassrelease release_notes 0.56` for the release notes.
+1. Once the release notes has been generated, issue `python3 -m hassrelease milestone_close 0.56`
+1. Merge pull request (DO NOT SQUASH!). Use `Merge pull request`.
+1. Go to [releases](https://github.com/home-assistant/home-assistant/releases), click `Draft a new release` and tag a new release on the `master` branch. "Tag version" and "Release title" are the version number (`O.x` for major version, `0.x.y` for minor and bug fix releases). Release description is the text from PR. Press "Publish release" to finish the process.
+1. Merge `master` into `dev`.
+1. Update `homeassistant/const.py` with the upcoming version number (including the `dev` tag) and push that commit to the `dev` branch.
+
+### {% linkable_title Website %}
+
+1. Create a blog post in the release branch and base it on the text of the PR in the main repository. Add images, additional text, links, etc. if it adds value. Tag each platform/component in a message to documentation.
+1. Create missing documentation as stubs.
+1. Run `credits_generator`.
+1. Update `_config.yml` with a link to the new release blog post and version number (at the bottom of the file).
+1. Merge `current` into release branch (`$ git checkout release-0-40 && git merge current`) to make the PR mergeable.
+1. Merge pull request (blog post, updated frontpage, and all new documentation) to `current`. DO NOT SQUASH!
+1. Merge `current` into `next`.
+
+### {% linkable_title Docker Hub %}
+
+Tags on Docker hub are automatically created when a release has been created on GitHub.
+
+### {% linkable_title Python Package Index %}
+
+Checkout the `master` branch and run `script/release` to publish the new release on [Python Package Index](https://pypi.python.org).
+
+### {% linkable_title Social media %}
+
+1. Use [hootsuite](https://hootsuite.com/dashboard) to publish a link to the release post on social media.
+
+## {% linkable_title Bugfix Release %}
+
+1. Checkout `master` and update it. `git checkout master && git pull --rebase`
+1. Create a new release branch from `master`. `git checkout -b release-0-56-2`
+1. Cherry-pick the PRs which were milestoned.
+1. Update `homeassistant/const.py` with the correct version number (increment `PATCH_VERSION`) and push that commit to release branch.
+1. Create a pull request from the release branch to `master` with the upcoming release number as the title.
+1. Merge pull request (DO NOT SQUASH!). Use `Merge pull request`.
+1. Go to [releases](https://github.com/home-assistant/home-assistant/releases), click `Draft a new release` and tag a new release on the `master` branch. "Tag version" and "Release title" are the version number (`O.x` for major version, `0.x.y` for minor and bug fix releases). Release description is the text from PR. Press "Publish release" to finish the process.
+1. [Publish](/developers/releasing/#python-package-index) the new release on PyPI.
diff --git a/intent/README.md b/intent/README.md
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/intent/firing_intents.md b/intent/firing_intents.md
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/intent/handling_intents.md b/intent/handling_intents.md
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/intent/registering_sentences.md b/intent/registering_sentences.md
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/website/blog-examples-from-docusaurus/2016-03-11-blog-post.md b/website/blog-examples-from-docusaurus/2016-03-11-blog-post.md
new file mode 100755
index 00000000000..cf2ba296067
--- /dev/null
+++ b/website/blog-examples-from-docusaurus/2016-03-11-blog-post.md
@@ -0,0 +1,18 @@
+---
+title: Blog Title
+author: Blog Author
+authorURL: http://twitter.com/
+authorFBID: 100002976521003
+---
+
+Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus elementum massa eget nulla aliquet sagittis. Proin odio tortor, vulputate ut odio in, ultrices ultricies augue. Cras ornare ultrices lorem malesuada iaculis. Etiam sit amet libero tempor, pulvinar mauris sed, sollicitudin sapien.
+
+
+
+Mauris vestibulum ullamcorper nibh, ut semper purus pulvinar ut. Donec volutpat orci sit amet mauris malesuada, non pulvinar augue aliquam. Vestibulum ultricies at urna ut suscipit. Morbi iaculis, erat at imperdiet semper, ipsum nulla sodales erat, eget tincidunt justo dui quis justo. Pellentesque dictum bibendum diam at aliquet. Sed pulvinar, dolor quis finibus ornare, eros odio facilisis erat, eu rhoncus nunc dui sed ex. Nunc gravida dui massa, sed ornare arcu tincidunt sit amet. Maecenas efficitur sapien neque, a laoreet libero feugiat ut.
+
+Nulla facilisi. Maecenas sodales nec purus eget posuere. Sed sapien quam, pretium a risus in, porttitor dapibus erat. Sed sit amet fringilla ipsum, eget iaculis augue. Integer sollicitudin tortor quis ultricies aliquam. Suspendisse fringilla nunc in tellus cursus, at placerat tellus scelerisque. Sed tempus elit a sollicitudin rhoncus. Nulla facilisi. Morbi nec dolor dolor. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Cras et aliquet lectus. Pellentesque sit amet eros nisi. Quisque ac sapien in sapien congue accumsan. Nullam in posuere ante. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Proin lacinia leo a nibh fringilla pharetra.
+
+Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Proin venenatis lectus dui, vel ultrices ante bibendum hendrerit. Aenean egestas feugiat dui id hendrerit. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Curabitur in tellus laoreet, eleifend nunc id, viverra leo. Proin vulputate non dolor vel vulputate. Curabitur pretium lobortis felis, sit amet finibus lorem suscipit ut. Sed non mollis risus. Duis sagittis, mi in euismod tincidunt, nunc mauris vestibulum urna, at euismod est elit quis erat. Phasellus accumsan vitae neque eu placerat. In elementum arcu nec tellus imperdiet, eget maximus nulla sodales. Curabitur eu sapien eget nisl sodales fermentum.
+
+Phasellus pulvinar ex id commodo imperdiet. Praesent odio nibh, sollicitudin sit amet faucibus id, placerat at metus. Donec vitae eros vitae tortor hendrerit finibus. Interdum et malesuada fames ac ante ipsum primis in faucibus. Quisque vitae purus dolor. Duis suscipit ac nulla et finibus. Phasellus ac sem sed dui dictum gravida. Phasellus eleifend vestibulum facilisis. Integer pharetra nec enim vitae mattis. Duis auctor, lectus quis condimentum bibendum, nunc dolor aliquam massa, id bibendum orci velit quis magna. Ut volutpat nulla nunc, sed interdum magna condimentum non. Sed urna metus, scelerisque vitae consectetur a, feugiat quis magna. Donec dignissim ornare nisl, eget tempor risus malesuada quis.
diff --git a/website/blog-examples-from-docusaurus/2017-04-10-blog-post-two.md b/website/blog-examples-from-docusaurus/2017-04-10-blog-post-two.md
new file mode 100644
index 00000000000..3ab4637bd5b
--- /dev/null
+++ b/website/blog-examples-from-docusaurus/2017-04-10-blog-post-two.md
@@ -0,0 +1,18 @@
+---
+title: New Blog Post
+author: Blog Author
+authorURL: http://twitter.com/
+authorFBID: 100002976521003
+---
+
+Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus elementum massa eget nulla aliquet sagittis. Proin odio tortor, vulputate ut odio in, ultrices ultricies augue. Cras ornare ultrices lorem malesuada iaculis. Etiam sit amet libero tempor, pulvinar mauris sed, sollicitudin sapien.
+
+
+
+Mauris vestibulum ullamcorper nibh, ut semper purus pulvinar ut. Donec volutpat orci sit amet mauris malesuada, non pulvinar augue aliquam. Vestibulum ultricies at urna ut suscipit. Morbi iaculis, erat at imperdiet semper, ipsum nulla sodales erat, eget tincidunt justo dui quis justo. Pellentesque dictum bibendum diam at aliquet. Sed pulvinar, dolor quis finibus ornare, eros odio facilisis erat, eu rhoncus nunc dui sed ex. Nunc gravida dui massa, sed ornare arcu tincidunt sit amet. Maecenas efficitur sapien neque, a laoreet libero feugiat ut.
+
+Nulla facilisi. Maecenas sodales nec purus eget posuere. Sed sapien quam, pretium a risus in, porttitor dapibus erat. Sed sit amet fringilla ipsum, eget iaculis augue. Integer sollicitudin tortor quis ultricies aliquam. Suspendisse fringilla nunc in tellus cursus, at placerat tellus scelerisque. Sed tempus elit a sollicitudin rhoncus. Nulla facilisi. Morbi nec dolor dolor. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Cras et aliquet lectus. Pellentesque sit amet eros nisi. Quisque ac sapien in sapien congue accumsan. Nullam in posuere ante. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Proin lacinia leo a nibh fringilla pharetra.
+
+Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Proin venenatis lectus dui, vel ultrices ante bibendum hendrerit. Aenean egestas feugiat dui id hendrerit. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Curabitur in tellus laoreet, eleifend nunc id, viverra leo. Proin vulputate non dolor vel vulputate. Curabitur pretium lobortis felis, sit amet finibus lorem suscipit ut. Sed non mollis risus. Duis sagittis, mi in euismod tincidunt, nunc mauris vestibulum urna, at euismod est elit quis erat. Phasellus accumsan vitae neque eu placerat. In elementum arcu nec tellus imperdiet, eget maximus nulla sodales. Curabitur eu sapien eget nisl sodales fermentum.
+
+Phasellus pulvinar ex id commodo imperdiet. Praesent odio nibh, sollicitudin sit amet faucibus id, placerat at metus. Donec vitae eros vitae tortor hendrerit finibus. Interdum et malesuada fames ac ante ipsum primis in faucibus. Quisque vitae purus dolor. Duis suscipit ac nulla et finibus. Phasellus ac sem sed dui dictum gravida. Phasellus eleifend vestibulum facilisis. Integer pharetra nec enim vitae mattis. Duis auctor, lectus quis condimentum bibendum, nunc dolor aliquam massa, id bibendum orci velit quis magna. Ut volutpat nulla nunc, sed interdum magna condimentum non. Sed urna metus, scelerisque vitae consectetur a, feugiat quis magna. Donec dignissim ornare nisl, eget tempor risus malesuada quis.
diff --git a/website/blog-examples-from-docusaurus/2017-09-25-testing-rss.md b/website/blog-examples-from-docusaurus/2017-09-25-testing-rss.md
new file mode 100644
index 00000000000..b7ff8129ceb
--- /dev/null
+++ b/website/blog-examples-from-docusaurus/2017-09-25-testing-rss.md
@@ -0,0 +1,11 @@
+---
+title: Adding RSS Support - RSS Truncation Test
+author: Eric Nakagawa
+authorURL: http://twitter.com/ericnakagawa
+authorFBID: 661277173
+---
+1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+
+This should be truncated.
+
+This line should never render in XML.
diff --git a/website/blog-examples-from-docusaurus/2017-09-26-adding-rss.md b/website/blog-examples-from-docusaurus/2017-09-26-adding-rss.md
new file mode 100644
index 00000000000..eeb4f0477e5
--- /dev/null
+++ b/website/blog-examples-from-docusaurus/2017-09-26-adding-rss.md
@@ -0,0 +1,10 @@
+---
+title: Adding RSS Support
+author: Eric Nakagawa
+authorURL: http://twitter.com/ericnakagawa
+authorFBID: 661277173
+---
+
+This is a test post.
+
+A whole bunch of other information.
diff --git a/website/blog-examples-from-docusaurus/2017-10-24-new-version-1.0.0.md b/website/blog-examples-from-docusaurus/2017-10-24-new-version-1.0.0.md
new file mode 100644
index 00000000000..60761c02dc6
--- /dev/null
+++ b/website/blog-examples-from-docusaurus/2017-10-24-new-version-1.0.0.md
@@ -0,0 +1,8 @@
+---
+title: New Version 1.0.0
+author: Eric Nakagawa
+authorURL: http://twitter.com/ericnakagawa
+authorFBID: 661277173
+---
+
+This blog post will test file name parsing issues when periods are present.
diff --git a/website/core/Footer.js b/website/core/Footer.js
new file mode 100644
index 00000000000..b43f1d6adff
--- /dev/null
+++ b/website/core/Footer.js
@@ -0,0 +1,102 @@
+/**
+ * Copyright (c) 2017-present, Facebook, Inc.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+const React = require('react');
+
+class Footer extends React.Component {
+ docUrl(doc, language) {
+ const baseUrl = this.props.config.baseUrl;
+ return baseUrl + 'docs/' + (language ? language + '/' : '') + doc;
+ }
+
+ pageUrl(doc, language) {
+ const baseUrl = this.props.config.baseUrl;
+ return baseUrl + (language ? language + '/' : '') + doc;
+ }
+
+ render() {
+ const currentYear = new Date().getFullYear();
+ return (
+
+ );
+ }
+}
+
+module.exports = Footer;
diff --git a/website/i18n/en.json b/website/i18n/en.json
new file mode 100644
index 00000000000..41417cf5d2a
--- /dev/null
+++ b/website/i18n/en.json
@@ -0,0 +1,92 @@
+{
+ "_comment": "This file is auto-generated by write-translations.js",
+ "localized-strings": {
+ "next": "Next",
+ "previous": "Previous",
+ "tagline": "A website for testing",
+ "add_new_platform": "Adding support for a new platform",
+ "architecture_components": "Components Architecture",
+ "architecture": "Architecture",
+ "asyncio_101": "Asyncio 101",
+ "asyncio_categorizing_functions": "Categorizing Functions",
+ "asyncio_misc": "Miscellaneous Async",
+ "asyncio_working_with_async": "Working with Async",
+ "asyncio": "asyncio",
+ "code_review_component": "Checklist for creating a component",
+ "code_review_platform": "Checklist for creating a platform",
+ "component_deps_and_reqs": "Requirements & Dependencies",
+ "component_discovery": "Component Discovery",
+ "component_events": "Handling events",
+ "component_generic_discovery": "Generic Platform Discovery",
+ "component_loading": "Loading your components",
+ "component_states": "Handling states",
+ "creating_components": "Creating components",
+ "development_101": "Development 101",
+ "development_catching_up": "Catching up with Reality",
+ "development_checklist": "Development Checklist",
+ "development_config": "Using Config",
+ "development_environment": "Set up Development Environment",
+ "development_events": "Using Events",
+ "development_guidelines": "Style guidelines",
+ "development_hass_object": "Hass object",
+ "development_services": "Using Services",
+ "development_states": "Using States",
+ "development_submitting": "Submit your work",
+ "development_testing": "Testing your code",
+ "development_validation": "Validate the input",
+ "development": "Starting with Development",
+ "documentation_create_page": "Create a new page",
+ "documentation_index": "Documentation Home Assistant",
+ "documentation_standards": "Documentation Standards",
+ "external_api_python": "Python Remote API",
+ "external_api_rest": "RESTful API",
+ "external_api_server_sent_events": "Server-sent events",
+ "external_api_websocket": "WebSocket API",
+ "frontend_add_card": "Adding state card",
+ "frontend_add_more_info": "Adding more info dialogs",
+ "frontend_creating_custom_panels": "Creating custom panels",
+ "frontend_creating_custom_ui": "Creating custom UI",
+ "frontend": "Frontend development",
+ "hassio_addon_communication": "Add-On Communication",
+ "hassio_addon_config": "Add-On Configuration",
+ "hassio_addon_development": "Developing an add-on",
+ "hassio_addon_presentation": "Presenting your add-on",
+ "hassio_addon_publishing": "Publishing your add-on",
+ "hassio_addon_repository": "Create an add-on repository",
+ "hassio_addon_testing": "Local add-on testing",
+ "hassio_addon_tutorial": "Tutorial: Making your first add-on",
+ "hassio_architecture": "Hass.io Architecture",
+ "hassio_debugging": "Debugging Hass.io",
+ "index": "Developers",
+ "intent_conversation": "Registering sentences",
+ "intent_firing": "Firing intents",
+ "intent_handling": "Handling intents",
+ "intent_index": "Intents",
+ "internationalization_backend_localization": "Backend Localization",
+ "internationalization_custom_component_localization": "Custom Component Localization",
+ "internationalization_index": "Internationalization",
+ "internationalization_translation": "Translation",
+ "maintenance": "Maintenance",
+ "platform_example_light": "Example light platform",
+ "platform_example_sensor": "Example sensor platform",
+ "releasing": "Releasing",
+ "Developers": "Developers",
+ "Catch all category": "Catch all category",
+ "Creating Platforms": "Creating Platforms",
+ "Creating Components": "Creating Components",
+ "Documentation": "Documentation",
+ "Frontend": "Frontend",
+ "Intents": "Intents",
+ "External API": "External API",
+ "Architecture": "Architecture",
+ "Development": "Development",
+ "Internationalization": "Internationalization",
+ "Hass.io": "Hass.io",
+ "Introduction": "Introduction"
+ },
+ "pages-strings": {
+ "Help Translate|recruit community translators for your project": "Help Translate",
+ "Edit this Doc|recruitment message asking to edit the doc source": "Edit",
+ "Translate this Doc|recruitment message asking to translate the docs": "Translate"
+ }
+}
diff --git a/website/package.json b/website/package.json
new file mode 100644
index 00000000000..9af0d076c5d
--- /dev/null
+++ b/website/package.json
@@ -0,0 +1,14 @@
+{
+ "scripts": {
+ "examples": "docusaurus-examples",
+ "start": "docusaurus-start",
+ "build": "docusaurus-build",
+ "publish-gh-pages": "docusaurus-publish",
+ "write-translations": "docusaurus-write-translations",
+ "version": "docusaurus-version",
+ "rename-version": "docusaurus-rename-version"
+ },
+ "devDependencies": {
+ "docusaurus": "^1.0.14"
+ }
+}
diff --git a/website/pages/en/help.js b/website/pages/en/help.js
new file mode 100755
index 00000000000..baff8e747e5
--- /dev/null
+++ b/website/pages/en/help.js
@@ -0,0 +1,57 @@
+/**
+ * Copyright (c) 2017-present, Facebook, Inc.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+const React = require('react');
+
+const CompLibrary = require('../../core/CompLibrary.js');
+const Container = CompLibrary.Container;
+const GridBlock = CompLibrary.GridBlock;
+
+const siteConfig = require(process.cwd() + '/siteConfig.js');
+
+function docUrl(doc, language) {
+ return siteConfig.baseUrl + 'docs/' + (language ? language + '/' : '') + doc;
+}
+
+class Help extends React.Component {
+ render() {
+ let language = this.props.language || '';
+ const supportLinks = [
+ {
+ content: `Learn more using the [documentation on this site.](${docUrl(
+ 'doc1.html',
+ language
+ )})`,
+ title: 'Browse Docs',
+ },
+ {
+ content: 'Ask questions about the documentation and project',
+ title: 'Join the community',
+ },
+ {
+ content: "Find out what's new with this project",
+ title: 'Stay up to date',
+ },
+ ];
+
+ return (
+
+
+
+
+
Need help?
+
+
This project is maintained by a dedicated group of people.
+
+
+
+
+ );
+ }
+}
+
+module.exports = Help;
diff --git a/website/pages/en/index.js b/website/pages/en/index.js
new file mode 100755
index 00000000000..d6db81ee8f6
--- /dev/null
+++ b/website/pages/en/index.js
@@ -0,0 +1,219 @@
+/**
+ * Copyright (c) 2017-present, Facebook, Inc.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+const React = require('react');
+
+const CompLibrary = require('../../core/CompLibrary.js');
+const MarkdownBlock = CompLibrary.MarkdownBlock; /* Used to read markdown */
+const Container = CompLibrary.Container;
+const GridBlock = CompLibrary.GridBlock;
+
+const siteConfig = require(process.cwd() + '/siteConfig.js');
+
+function imgUrl(img) {
+ return siteConfig.baseUrl + 'img/' + img;
+}
+
+function docUrl(doc, language) {
+ return siteConfig.baseUrl + 'docs/' + (language ? language + '/' : '') + doc;
+}
+
+function pageUrl(page, language) {
+ return siteConfig.baseUrl + (language ? language + '/' : '') + page;
+}
+
+class Button extends React.Component {
+ render() {
+ return (
+