diff --git a/docs/_markbind/layouts/devGuide.md b/docs/_markbind/layouts/devGuide.md
index 6412945cdf..33c9dc6abd 100644
--- a/docs/_markbind/layouts/devGuide.md
+++ b/docs/_markbind/layouts/devGuide.md
@@ -14,6 +14,7 @@
* [Project Structure]({{baseUrl}}/devGuide/design/projectStructure.html)
* [Architecture]({{baseUrl}}/devGuide/design/architecture.html)
* [Server Side Rendering]({{baseUrl}}/devGuide/design/serverSideRendering.html)
+* [Writing Components]({{baseUrl}}/devGuide/writingComponents.html)
* [Writing Plugins]({{baseUrl}}/devGuide/writingPlugins.html)
* [Project management]({{baseUrl}}/devGuide/projectManagement.html)
* Appendices :expanded:
diff --git a/docs/devGuide/writingComponents.md b/docs/devGuide/writingComponents.md
new file mode 100644
index 0000000000..2763460a58
--- /dev/null
+++ b/docs/devGuide/writingComponents.md
@@ -0,0 +1,154 @@
+{% set title = "Writing Components" %}
+{{ title }}
+
+
+ title: "{{ title }}"
+ layout: devGuide.md
+ pageNav: default
+
+
+# {{ title }}
+
+
+
+This page explains how MarkBind components work, focused on implementation and testing.
+
+
+MarkBind provides a number of components (e.g. expandable panels, tooltips) to dynamically express content.
+In order to serve content on the browser, MarkBind syntax is converted to valid HTML.
+
+
+
+The main logic of the node processing flow can be found in [`packages/core/src/html/NodeProcessor.js`](https://github.com/MarkBind/markbind/blob/master/packages/core/src/html/NodeProcessor.js).
+
+A MarkBind source file is first parsed into a series of
+nodes.
+In general, each component will be parsed as a node, which may contain other child nodes (components or otherwise).
+
+Each node is then processed to implement MarkBind functionalities, such as checking for invalid intrasite links and rendering markdown.
+Components may undergo further processing (in `processNode`) and/or post-processing (in `postProcessNode`) to further transform the node to the desired HTML.
+MarkBind identifies each component by the node's _name_ (e.g. `panel`, `question`).
+
+`cheerio` is then used to convert all nodes back into HTML, and this HTML is served to the browser as a MarkBind page.
+
+
+
+
+
+## Implementing Components
+
+There are multiple ways to implement MarkBind components.
+
+### Transforming the Node Directly
+
+One way to implement a MarkBind component is to transform the node itself.
+This is a more low-level implementation that can be useful when a node only needs to be modified slightly.
+
+When a node is processed, MarkBind syntax is converted to HTML, and any remaining attributes will also be converted to HTML attributes.
+This can be useful if you just need to add a HTML attribute to the node, or modify the value of an existing attribute.
+
+These transformations may take place at various stages of node processing: before (`preProcessNode`), during (`processNode`), or after (`postProcessNode`).
+
+{{ icon_examples }}
+* Adding a class to a node (setting line numbers for code blocks)
+* Modifying attributes and adding a directive to a node ([former implementation](https://github.com/MarkBind/markbind/blob/502df135e07baebd9d4eea8ccc0654c990047792/packages/core/src/html/bootstrapVueProcessor.js#L73) of popovers)
+
+
+
+### Vue Components
+
+Many MarkBind components are implemented as Vue components, either by creating a component in the `vue-components` package, or by importing a component from an external library.
+This can be useful when a more complicated set of features is needed, where a Vue component can provide an interface for us to manage these functionalities.
+
+Vue components are registered in `vue-components/src/index.js`, which allows them to be used in the template section of any Vue instance without needing to be imported first.
+
+
+
+##### Attributes
+
+MarkBind attributes are passed to the Vue component as **props**. The type of the prop will be a `String`.
+
+##### Slots
+
+MarkBind slots are passed as **named slots** to the Vue component. The name of the MarkBind slot will be the same as the name of the Vue slot.
+Hence, MarkBind slots can be accessed in a Vue component either through the [named slots](https://v2.vuejs.org/v2/guide/components-slots.html#Named-Slots) or through the [`$slots` API](https://v2.vuejs.org/v2/api/#vm-slots).
+
+
+
+
+{{ icon_examples }}
+* As a wrapper for an external library ([Modal component](https://github.com/MarkBind/markbind/blob/master/packages/vue-components/src/Modal.vue))
+* To implement a set of customised behaviours ([Quiz component](https://github.com/MarkBind/markbind/blob/master/packages/vue-components/src/questions/Quiz.vue))
+
+### As a Plugin
+
+MarkBind components can be implemented as a plugin as well.
+This is suitable for more lightweight components where the implementation is largely in processing the node, making it fitting to use MarkBind plugins' `processNode` or `postRender` interfaces.
+These interfaces provide additional entry points for modifying the page generated, and do not replace MarkBind's usual node processing.
+
+The [Writing Plugins]({{baseUrl}}/devGuide/writingPlugins.html) page is a good guide to get started on plugins.
+
+{{ icon_examples }}
+* The [`tree` component](https://github.com/MarkBind/markbind/blob/master/packages/core/src/plugins/default/markbind-plugin-tree.js) is implemented as a default plugin
+
+## Testing Components
+
+Automated tests that are relevant to the components include:
+
+* [Functional tests]({{baseUrl}}/devGuide/workflow.html#adding-test-site-content)
+* [Snapshot tests]({{baseUrl}}/devGuide/workflow.html#adding-snapshot-tests-for-components)
+
+The API for Snapshot tests can be found at [Vue Test Utils](https://v1.test-utils.vuejs.org/).
+
+Additionally, it's a good idea to check the deployed PR preview in addition to serving the app locally, to ensure that there are no differences.
+
+## Additional Considerations
+
+Some things you may need to consider when implementing a MarkBind component:
+
+#### Reactivity
+
+_Reactivity_ refers to the ability of a web framework to update your view whenever the application state has changed.
+It is important to consider reactivity when implementing a component that may have dynamic contents that readers can interact with (e.g. opening a panel, triggering a tooltip to show).
+
+#### SSR
+
+Components should be compatible with SSR (Server-Side Rendering).
+Minimally, there should be no SSR issues (viewable from the browser console), though a lack of warnings does **not** mean that there are no SSR problems.
+A guide on SSR for MarkBind can be found [here]({{baseUrl}}/devGuide/design/serverSideRendering.html).
+
+Vue-specific tips for resolving SSR issues:
+* The `mount` and `beforeMount` lifecycle hooks will only be executed on the client, not the server
+* When using `v-if`, ensure that it will evaluate to the same value on both the client and server
+* Take note of how the Vue component will be compiled, ensuring that the HTML is correct and aligns on both client- and server- side
+* Conditionally render data when it has been fully loaded
+
+#### Bundle size
+
+When creating a new component, you may need to import a package or library to support some functionality.
+Ideally, this should not increase MarkBind's bundle size too much.
+[Bundlephobia](https://bundlephobia.com/) may be useful to quickly look up the size of a package!
+
+#### Dependencies
+
+When choosing to use a third-party library or package, it should ideally be well-maintained and not have too many dependencies.
+While dependencies may be inevitable, a package with dependencies on large libraries may lag behind the most recent releases of these libraries, which may become a blocker for MarkBind to migrate to these recent releases as well.
+
+For instance, if `bootstrap-vue` depends on Bootstrap and Vue, we will need to wait for `bootstrap-vue` to migrate to the newest versions of both Bootstrap and Vue before MarkBind can migrate to these versions of Bootstrap and Vue as well.
+
+
+
+Feel free to raise any concerns during the initial discussion phase for other devs to weigh in on the tradeoffs!
+
+
+#### Attributes and Slots
+
+MarkBind components may support attributes, slots or both.
+Some components allow users to supply the same content as either a slot or an attribute.
+If an author provides the same content as both a slot and an attribute, in most cases, the slot should override the attribute.
+
+
+
+MarkBind should also **log a warning** to inform the author of this conflict!
+
+