diff --git a/editors/editoria/src/Editoria.js b/editors/editoria/src/Editoria.js
index cf9c690d2b67e40cf1d04fb586d9964b90001ec2..d1ec4b25547a00b440fc75dac04856a8c6e2a6ba 100644
--- a/editors/editoria/src/Editoria.js
+++ b/editors/editoria/src/Editoria.js
@@ -48,7 +48,7 @@ const Editoria = () => (
       autoFocus
       placeholder="Type Something..."
       fileUpload={file => renderImage(file)}
-      value="<p> <span style='font-style:italic;'>test</span>hello <code> this is the code</code></p>"
+      value="<h1> <span style='font-style:italic;'>test</span>hello <code> this is the code</code></p>"
       layout={EditoriaLayout}
       user={user}
     />
diff --git a/editors/editoria/src/config/config.js b/editors/editoria/src/config/config.js
index 1f1e3859de6379d7041663578482dde01fda862f..b31f1704dfe11f6fce63fff51731b7004f1c139a 100644
--- a/editors/editoria/src/config/config.js
+++ b/editors/editoria/src/config/config.js
@@ -17,7 +17,8 @@ import {
   ImageToolGroupService,
   TextBlockLevelService,
   TextToolGroupService,
-  TrackChangeService
+  TrackChangeService,
+  NoteService
 } from "wax-prosemirror-services";
 
 import invisibles, {
@@ -65,6 +66,7 @@ export default {
     new ImageToolGroupService(),
     new TextBlockLevelService(),
     new TextToolGroupService(),
-    new TrackChangeService()
+    new TrackChangeService(),
+    new NoteService()
   ]
 };
diff --git a/wax-prosemirror-core/src/FootnoteView.js b/wax-prosemirror-core/src/FootnoteView.js
new file mode 100644
index 0000000000000000000000000000000000000000..807409849eb3d5d8ac8128577128dc655800b3a8
--- /dev/null
+++ b/wax-prosemirror-core/src/FootnoteView.js
@@ -0,0 +1,119 @@
+import { StepMap } from "prosemirror-transform";
+import { keymap } from "prosemirror-keymap";
+import { undo, redo } from "prosemirror-history";
+import { EditorView } from "prosemirror-view";
+import { EditorState } from "prosemirror-state";
+import { Schema } from "prosemirror-model";
+import { DefaultSchema } from "wax-prosemirror-schema";
+
+class FootnoteView {
+  constructor(node, view, getPos) {
+    console.log(node);
+    // We'll need these later
+    this.node = node;
+
+    this.outerView = view;
+    this.getPos = getPos;
+
+    // The node's representation in the editor (empty, for now)
+    this.dom = document.createElement("footnote");
+    // These are used when the footnote is selected
+    this.innerView = null;
+  }
+  selectNode() {
+    this.dom.classList.add("ProseMirror-selectednode");
+
+    if (!this.innerView) this.open();
+  }
+
+  deselectNode() {
+    this.dom.classList.remove("ProseMirror-selectednode");
+    if (this.innerView) this.close();
+  }
+
+  open() {
+    // Append a tooltip to the outer node
+    let tooltip = this.dom.appendChild(document.createElement("div"));
+    tooltip.className = "footnote-tooltip";
+    // And put a sub-ProseMirror into that
+    this.innerView = new EditorView(tooltip, {
+      // You can use any node as an editor document
+      state: EditorState.create({
+        doc: this.node,
+        plugins: [
+          keymap({
+            "Mod-z": () => undo(this.outerView.state, this.outerView.dispatch),
+            "Mod-y": () => redo(this.outerView.state, this.outerView.dispatch)
+          })
+        ]
+      }),
+      // This is the magic part
+      dispatchTransaction: this.dispatchInner.bind(this),
+      handleDOMEvents: {
+        mousedown: () => {
+          // Kludge to prevent issues due to the fact that the whole
+          // footnote is node-selected (and thus DOM-selected) when
+          // the parent editor is focused.
+          if (this.outerView.hasFocus()) this.innerView.focus();
+        }
+      }
+    });
+  }
+
+  close() {
+    this.innerView.destroy();
+    this.innerView = null;
+    this.dom.textContent = "";
+  }
+  dispatchInner(tr) {
+    let { state, transactions } = this.innerView.state.applyTransaction(tr);
+    this.innerView.updateState(state);
+
+    if (!tr.getMeta("fromOutside")) {
+      let outerTr = this.outerView.state.tr,
+        offsetMap = StepMap.offset(this.getPos() + 1);
+      for (let i = 0; i < transactions.length; i++) {
+        let steps = transactions[i].steps;
+        for (let j = 0; j < steps.length; j++)
+          outerTr.step(steps[j].map(offsetMap));
+      }
+      if (outerTr.docChanged) this.outerView.dispatch(outerTr);
+    }
+  }
+  update(node) {
+    console.log("update");
+    if (!node.sameMarkup(this.node)) return false;
+    this.node = node;
+    if (this.innerView) {
+      let state = this.innerView.state;
+      let start = node.content.findDiffStart(state.doc.content);
+      if (start != null) {
+        let { a: endA, b: endB } = node.content.findDiffEnd(state.doc.content);
+        let overlap = start - Math.min(endA, endB);
+        if (overlap > 0) {
+          endA += overlap;
+          endB += overlap;
+        }
+        this.innerView.dispatch(
+          state.tr
+            .replace(start, endB, node.slice(start, endA))
+            .setMeta("fromOutside", true)
+        );
+      }
+    }
+    return true;
+  }
+  destroy() {
+    if (this.innerView) this.close();
+  }
+
+  stopEvent(event) {
+    return this.innerView && this.innerView.dom.contains(event.target);
+  }
+
+  ignoreMutation() {
+    return true;
+  }
+}
+
+export default FootnoteView;
diff --git a/wax-prosemirror-core/src/WaxView.js b/wax-prosemirror-core/src/WaxView.js
index 03af5111ef506dca908b270d4c661a53fc76a5f6..1dbb4005c354c4baef8772ee2df276591fc07676 100644
--- a/wax-prosemirror-core/src/WaxView.js
+++ b/wax-prosemirror-core/src/WaxView.js
@@ -13,6 +13,7 @@ import "prosemirror-view/style/prosemirror.css";
 
 import trackedTransaction from "./track-changes/trackedTransaction";
 import { WaxContext } from "./ioc-react";
+import FootnoteView from "./FootnoteView";
 
 export default props => {
   const { readonly, onBlur, options, debug, autoFocus } = props;
@@ -45,6 +46,11 @@ export default props => {
               }
             : null
         }
+        // nodeViews: {
+        //   footnote(node, view, getPos) {
+        //     return new FootnoteView(node, view, getPos);
+        //   }
+        // }
       }
     );
     context.updateView(view);
diff --git a/wax-prosemirror-layouts/src/layouts/EditorElements.js b/wax-prosemirror-layouts/src/layouts/EditorElements.js
index 0e771f795ab3ad4cfd99e82b2d46b83fc579db99..2955279069485125598e6bbccc98758b450f0f8e 100644
--- a/wax-prosemirror-layouts/src/layouts/EditorElements.js
+++ b/wax-prosemirror-layouts/src/layouts/EditorElements.js
@@ -2,7 +2,52 @@ import styled, { css } from "styled-components";
 
 /* All styles regarding ProseMirror surface and elements */
 
-export default css`{
+export default css`
+  .ProseMirror footnote {
+    display: inline-block;
+    position: relative;
+    cursor: pointer;
+  }
+
+  .ProseMirror footnote::after {
+    content: counter(footnote);
+    vertical-align: super;
+    font-size: 75%;
+    counter-increment: footnote;
+  }
+
+  .ProseMirror-hideselection .footnote-tooltip *::selection {
+    background-color: transparent;
+  }
+
+  .ProseMirror-hideselection .footnote-tooltip *::-moz-selection {
+    background-color: transparent;
+  }
+
+  .ProseMirror .footnote-tooltip {
+    cursor: auto;
+    position: absolute;
+    left: -30px;
+    top: calc(100% + 10px);
+    background: silver;
+    padding: 3px;
+    border-radius: 2px;
+    width: 500px;
+  }
+
+  .ProseMirror .footnote-tooltip::before {
+    border: 5px solid silver;
+    border-top-width: 0;
+    border-left-color: transparent;
+    border-right-color: transparent;
+    position: absolute;
+    top: -5px;
+    left: 27px;
+    content: " ";
+    height: 0;
+    width: 0;
+  }
+
   .ProseMirror {
     -moz-box-shadow: 0 0 3px #ccc;
     -webkit-box-shadow: 0 0 3px #ccc;
diff --git a/wax-prosemirror-services/index.js b/wax-prosemirror-services/index.js
index 0434a1450d482241eda66ff463708461183f0335..d16ab4d6cb1784c1aac4624b104d98b35d44f434 100644
--- a/wax-prosemirror-services/index.js
+++ b/wax-prosemirror-services/index.js
@@ -1,15 +1,11 @@
 export { default as MenuService } from "./src/MenuService/MenuService";
 export { default as LinkService } from "./src/LinkService/LinkService";
-export {
-  default as PlaceholderService
-} from "./src/PlaceholderService/PlaceholderService";
+export { default as PlaceholderService } from "./src/PlaceholderService/PlaceholderService";
 export { default as ImageService } from "./src/ImageService/ImageService";
 export { default as RulesService } from "./src/RulesService/RulesService";
 export { default as SchemaService } from "./src/SchemaService/SchemaService";
 
-export {
-  default as ShortCutsService
-} from "./src/ShortCutsService/ShortCutsService";
+export { default as ShortCutsService } from "./src/ShortCutsService/ShortCutsService";
 
 export { default as OverlayService } from "./src/OverlayService/OverlayService";
 export { default as Tool } from "./src/lib/Tools";
@@ -21,39 +17,20 @@ export {
 All Elements services
 */
 export { default as BaseService } from "./src/BaseService/BaseService";
-export {
-  default as InlineAnnotationsService
-} from "./src/InlineAnnotations/InlineAnnotationsService";
+export { default as InlineAnnotationsService } from "./src/InlineAnnotations/InlineAnnotationsService";
 export { default as ListsService } from "./src/ListsService/ListsService";
 export { default as TablesService } from "./src/TablesService/TablesService";
-export {
-  default as TextBlockLevelService
-} from "./src/TextBlockLevel/TextBlockLevelService";
-export {
-  default as DisplayBlockLevelService
-} from "./src/DisplayBlockLevel/DisplayBlockLevelService";
+export { default as TextBlockLevelService } from "./src/TextBlockLevel/TextBlockLevelService";
+export { default as DisplayBlockLevelService } from "./src/DisplayBlockLevel/DisplayBlockLevelService";
 
 /*
 ToolGroups
 */
-export {
-  default as BaseToolGroupService
-} from "./src/WaxToolGroups/BaseToolGroupService/BaseToolGroupService";
-export {
-  default as AnnotationToolGroupService
-} from "./src/WaxToolGroups/AnnotationToolGroupService/AnnotationToolGroupService";
-export {
-  default as ListToolGroupService
-} from "./src/WaxToolGroups/ListToolGroupService/ListToolGroupService";
-export {
-  default as ImageToolGroupService
-} from "./src/WaxToolGroups/ImageToolGroupService/ImageToolGroupService";
-export {
-  default as TableToolGroupService
-} from "./src/WaxToolGroups/TableToolGroupService/TableToolGroupService";
-export {
-  default as DisplayToolGroupService
-} from "./src/WaxToolGroups/DisplayToolGroupService/DisplayToolGroupService";
-export {
-  default as TextToolGroupService
-} from "./src/WaxToolGroups/TextToolGroupService/TextToolGroupService";
+export { default as BaseToolGroupService } from "./src/WaxToolGroups/BaseToolGroupService/BaseToolGroupService";
+export { default as AnnotationToolGroupService } from "./src/WaxToolGroups/AnnotationToolGroupService/AnnotationToolGroupService";
+export { default as ListToolGroupService } from "./src/WaxToolGroups/ListToolGroupService/ListToolGroupService";
+export { default as ImageToolGroupService } from "./src/WaxToolGroups/ImageToolGroupService/ImageToolGroupService";
+export { default as TableToolGroupService } from "./src/WaxToolGroups/TableToolGroupService/TableToolGroupService";
+export { default as DisplayToolGroupService } from "./src/WaxToolGroups/DisplayToolGroupService/DisplayToolGroupService";
+export { default as TextToolGroupService } from "./src/WaxToolGroups/TextToolGroupService/TextToolGroupService";
+export { default as NoteService } from "./src/NoteService/NoteService";
diff --git a/wax-prosemirror-services/src/NoteService/Editor.js b/wax-prosemirror-services/src/NoteService/Editor.js
new file mode 100644
index 0000000000000000000000000000000000000000..894e940b1216241be492081d62ae4e88b4eb73d8
--- /dev/null
+++ b/wax-prosemirror-services/src/NoteService/Editor.js
@@ -0,0 +1,93 @@
+import React, { useEffect, useRef } from "react";
+import { EditorView } from "prosemirror-view";
+import { EditorState } from "prosemirror-state";
+import { StepMap } from "prosemirror-transform";
+import { keymap } from "prosemirror-keymap";
+import { undo, redo } from "prosemirror-history";
+import { markActive } from "../lib/Utils";
+
+let noteView = null;
+export default ({ node, view, pos }) => {
+  const editorRef = useRef();
+  useEffect(() => {
+    console.log("test", node);
+    noteView = new EditorView(
+      { mount: editorRef.current },
+      {
+        // You can use any node as an editor document
+        state: EditorState.create({
+          doc: node,
+          plugins: [
+            keymap({
+              "Mod-z": () => undo(view.state, view.dispatch),
+              "Mod-y": () => redo(view.state, view.dispatch),
+              "Mod-u": () =>
+                markActive(noteView.state.config.schema.marks.underline)(
+                  noteView.state
+                )
+            })
+          ]
+        }),
+        // This is the magic part
+        dispatchTransaction: tr => {
+          console.log("in disaptch");
+          let { state, transactions } = noteView.state.applyTransaction(tr);
+          noteView.updateState(state);
+
+          if (!tr.getMeta("fromOutside")) {
+            let outerTr = view.state.tr,
+              offsetMap = StepMap.offset(pos + 1);
+            for (let i = 0; i < transactions.length; i++) {
+              let steps = transactions[i].steps;
+              for (let j = 0; j < steps.length; j++)
+                outerTr.step(steps[j].map(offsetMap));
+            }
+            console.log(noteView.docView.node);
+            // outerTr.setNodeMarkup(pos, view.state.schema.nodes.footnote, {
+            //   title: noteView.docView.node.textContent
+            // });
+
+            if (outerTr.docChanged) {
+              view.dispatch(outerTr);
+            }
+          }
+        },
+        handleDOMEvents: {
+          mousedown: () => {
+            // Kludge to prevent issues due to the fact that the whole
+            // footnote is node-selected (and thus DOM-selected) when
+            // the parent editor is focused.
+            if (noteView.hasFocus()) noteView.focus();
+          }
+        }
+      }
+    );
+  }, []);
+
+  if (noteView) {
+    let state = noteView.state;
+    let start = node.content.findDiffStart(state.doc.content);
+    console.log(start, node);
+    if (start != null) {
+      let { a: endA, b: endB } = node.content.findDiffEnd(state.doc.content);
+      let overlap = start - Math.min(endA, endB);
+      if (overlap > 0) {
+        endA += overlap;
+        endB += overlap;
+      }
+      console.log(endA, endB);
+      noteView.dispatch(
+        state.tr
+          .replace(start, endB, node.slice(start, endA))
+          .setMeta("fromOutside", true)
+      );
+    }
+  }
+
+  return (
+    <div
+      style={{ height: "100px", border: "1px solid black" }}
+      ref={editorRef}
+    ></div>
+  );
+};
diff --git a/wax-prosemirror-services/src/NoteService/Note.js b/wax-prosemirror-services/src/NoteService/Note.js
new file mode 100644
index 0000000000000000000000000000000000000000..c270e7a5bc79e46eb5361787f24b585dd4bd5137
--- /dev/null
+++ b/wax-prosemirror-services/src/NoteService/Note.js
@@ -0,0 +1,18 @@
+import Tools from "../lib/Tools";
+import { injectable } from "inversify";
+import { icons } from "wax-prosemirror-components";
+
+@injectable()
+export default class Note extends Tools {
+  title = "Insert Note";
+  content = icons.footnote;
+
+  get run() {
+    return (state, dispatch) => {
+      const footnote = state.config.schema.nodes.footnote.create();
+      dispatch(state.tr.replaceSelectionWith(footnote));
+    };
+  }
+
+  get enable() {}
+}
diff --git a/wax-prosemirror-services/src/NoteService/NoteComponent.js b/wax-prosemirror-services/src/NoteService/NoteComponent.js
new file mode 100644
index 0000000000000000000000000000000000000000..45801a38dd75527ba12521f0995f427dd2ca5c44
--- /dev/null
+++ b/wax-prosemirror-services/src/NoteService/NoteComponent.js
@@ -0,0 +1,63 @@
+import React, { useContext, useState, useEffect, useMemo } from "react";
+import { WaxContext } from "wax-prosemirror-core/src/ioc-react";
+import { isEqual } from "lodash";
+import NoteEditor from "./NoteEditor";
+
+export default () => {
+  const { view } = useContext(WaxContext);
+  const [notes, setNotes] = useState([]);
+
+  useEffect(() => {
+    setNotes(updateNotes(view));
+  }, [JSON.stringify(updateNotes(view))]);
+
+  const noteComponent = useMemo(
+    () => <NoteEditor notes={notes} view={view} />,
+    [notes]
+  );
+
+  return <div>{noteComponent}</div>;
+};
+
+const updateNotes = view => {
+  if (view) {
+    return findBlockNodes(
+      view.state.doc,
+      view.state.schema.nodes.footnote,
+      true
+    );
+  }
+  return [];
+};
+
+export const flatten = (node, descend = true) => {
+  if (!node) {
+    throw new Error('Invalid "node" parameter');
+  }
+  const result = [];
+  node.descendants((child, pos) => {
+    result.push({ node: child, pos });
+    if (!descend) {
+      return false;
+    }
+  });
+  return result;
+};
+
+export const findChildren = (node, predicate, descend) => {
+  if (!node) {
+    throw new Error('Invalid "node" parameter');
+  } else if (!predicate) {
+    throw new Error('Invalid "predicate" parameter');
+  }
+  return flatten(node, descend).filter(child => {
+    // predicate(child.node)console.log(child.node);
+    // return predicate(child.node);
+    // console.log(child.node.type.name === "footnote", predicate(child.node));
+    return child.node.type.name === "footnote" ? child.node : false;
+  });
+};
+
+export const findBlockNodes = (node, descend) => {
+  return findChildren(node, child => child.isBlock, descend);
+};
diff --git a/wax-prosemirror-services/src/NoteService/NoteEditor.js b/wax-prosemirror-services/src/NoteService/NoteEditor.js
new file mode 100644
index 0000000000000000000000000000000000000000..05094be4cd8ddecef3c182c61c2e2a59dcc83dd9
--- /dev/null
+++ b/wax-prosemirror-services/src/NoteService/NoteEditor.js
@@ -0,0 +1,12 @@
+import React from "react";
+import Editor from "./Editor";
+
+export default ({ notes, view }) => {
+  return (
+    <div>
+      {notes.map(note => (
+        <Editor node={note.node} pos={note.pos} view={view} />
+      ))}
+    </div>
+  );
+};
diff --git a/wax-prosemirror-services/src/NoteService/NoteService.js b/wax-prosemirror-services/src/NoteService/NoteService.js
new file mode 100644
index 0000000000000000000000000000000000000000..57ef932615d4f15a42192950aad26b8ad71a0ead
--- /dev/null
+++ b/wax-prosemirror-services/src/NoteService/NoteService.js
@@ -0,0 +1,18 @@
+import Note from "./Note";
+import Service from "wax-prosemirror-core/src/services/Service";
+import NoteComponent from "./NoteComponent";
+
+class NoteService extends Service {
+  name = "NoteService";
+
+  boot() {
+    const layout = this.container.get("Layout");
+    layout.addComponent("bottomBar", NoteComponent);
+  }
+
+  register() {
+    this.container.bind("Note").to(Note);
+  }
+}
+
+export default NoteService;
diff --git a/wax-prosemirror-services/src/OverlayService/usePosition.js b/wax-prosemirror-services/src/OverlayService/usePosition.js
index 90f7e71d0a227d4e9496175d9df648c7082a5481..ec33f2e6d7e8d683383adfdda8bf492977f7f951 100644
--- a/wax-prosemirror-services/src/OverlayService/usePosition.js
+++ b/wax-prosemirror-services/src/OverlayService/usePosition.js
@@ -12,7 +12,7 @@ const defaultOverlay = {
 };
 
 export default options => {
-  let { view } = useContext(WaxContext);
+  const { view } = useContext(WaxContext);
 
   const [position, setPosition] = useState({
     position: "absolute",
diff --git a/wax-prosemirror-services/src/SchemaService/DefaultSchema.js b/wax-prosemirror-services/src/SchemaService/DefaultSchema.js
index 3bcc0cac0f0121db5e5e79c32fa82d337b74e0c5..73541c6d32767d87ecc45286d7e547d4e8bffb51 100644
--- a/wax-prosemirror-services/src/SchemaService/DefaultSchema.js
+++ b/wax-prosemirror-services/src/SchemaService/DefaultSchema.js
@@ -47,7 +47,31 @@ export default {
         const attrs = blockLevelToDOM(node);
         return ["p", attrs, 0];
       }
+    },
+    footnote: {
+      group: "inline",
+      content: "inline*",
+      inline: true,
+      // This makes the view treat the node as a leaf, even though it
+      // technically has content
+      atom: true,
+      toDOM: () => ["footnote"],
+      parseDOM: [{ tag: "footnote" }]
     }
+    // footnote: {
+    //   group: "inline",
+    //   content: "block+",
+    //   inline: true,
+    //   atom: true,
+    //   toDOM: dom => {
+    //     return ["footnote"];
+    //   },
+    //   parseDOM: [
+    //     {
+    //       tag: "footnote"
+    //     }
+    //   ]
+    // },
   },
   marks: {}
 };
diff --git a/wax-prosemirror-services/src/WaxToolGroups/BaseToolGroupService/Base.js b/wax-prosemirror-services/src/WaxToolGroups/BaseToolGroupService/Base.js
index d9d35019ad83c726d610b45c19c7255c06a7b7fd..1b3e2c89dc170ee0d6ee2f16004910bfadb0a5de 100644
--- a/wax-prosemirror-services/src/WaxToolGroups/BaseToolGroupService/Base.js
+++ b/wax-prosemirror-services/src/WaxToolGroups/BaseToolGroupService/Base.js
@@ -4,9 +4,13 @@ import ToolGroup from "../../lib/ToolGroup";
 @injectable()
 class Base extends ToolGroup {
   tools = [];
-  constructor(@inject("Undo") undo, @inject("Redo") redo) {
+  constructor(
+    @inject("Undo") undo,
+    @inject("Redo") redo,
+    @inject("Note") note
+  ) {
     super();
-    this.tools = [undo, redo];
+    this.tools = [undo, redo, note];
   }
 }