diff --git a/docs/comparing_the_alternatives.md b/docs/comparing_the_alternatives.md
index 51705707b4762472ed193bd82fddc772d6ec281e..ee7d565762680d82c3738d9b068957a4a56c8738 100644
--- a/docs/comparing_the_alternatives.md
+++ b/docs/comparing_the_alternatives.md
@@ -24,127 +24,21 @@ benchmark program and run it for yourself!
 
 ## Feature Breakdown
 
-Despite the superior performance of Ferma it also supports all the features provided by the alternatives out there, not
-to mention several novel features. The following gives a quick breakdown of the features of the various frameworks. We
-also include a bit later in the document some Ferma examples showing the various features in action. All of the examples
-below use the domain model [found here](Ferma:Domain_Example).
-
-|                                                                                                                  | **Ferma**     | **Frames**    | **Totorom**   | **Peapod**    |
-|------------------------------------------------------------------------------------------------------------------|---------------|---------------|---------------|---------------|
-| **[JPA-like Annotations](creating_annotated_domain_models)**                                                     | Supported     | Supported     | Not Supported | Supported     |
-| **[Type information encoded into graph](#type-information-encoded-into-graph)**                                  | Supported     | Supported     | Supported     | Supported     |
-| **[Framing of elements instantiated according to type hierarchy](#framing-instantiated-by-type-hierarchy)**      | Supported     | Supported     | Supported     | Supported     |
-| **[Element queried by type hierarchy](#element-queried-by-type-hierarchy)**                                      | Supported     | Not Supported | Not Supported | Partial \*    |
-| **[Turning off type resolution on a per call basis](#turning-off-type-resolution-per-call)**                     | Supported     | Not Supported | Not Supported | Not Supported |
-| **[Changing the encoded graph type already stored in the database](#changing-type-encoded-in-the-graph)**        | Supported     | Not Supported | Not Supported | Not Supported |
-| **[Customizing the way type information is stored in the graph](#customizing-how-types-are-encoded)**            | Supported     | Not Supported | Not Supported | Not Supported |
-| **Tinkerpop 2 support**                                                                                          | Supported     | Supported     | Supported     | Not Supported |
-| **Tinkerpop 3 support**                                                                                          | Not Supported | Not Supported | Not Supported | Supported     |
+Ferma also supports all the features provided by the alternatives out there, not to mention several novel features. The
+following gives a quick breakdown of the features of the various frameworks. We also link to some Ferma examples showing
+the various features in action.
+
+| Feature                                                                                                                     | **Ferma**     | **Frames**    | **Totorom**   | **Peapod**    |
+|-----------------------------------------------------------------------------------------------------------------------------|---------------|---------------|---------------|---------------|
+| **[JPA-like Annotations](features.md#jpa-like-annotations)**                                                                | Supported     | Supported     | Not Supported | Supported     |
+| **[Type information encoded into graph](features.md#type-information-encoded-into-graph)**                                  | Supported     | Supported     | Supported     | Supported     |
+| **[Framing of elements instantiated according to type hierarchy](features.md#framing-instantiated-by-type-hierarchy)**      | Supported     | Supported     | Supported     | Supported     |
+| **[Element queried by type hierarchy](features.md#element-queried-by-type-hierarchy)**                                      | Supported     | Not Supported | Not Supported | Partial \*    |
+| **[Turning off type resolution on a per call basis](features.md#turning-off-type-resolution-per-call)**                     | Supported     | Not Supported | Not Supported | Not Supported |
+| **[Changing the encoded graph type already stored in the database](features.md#changing-type-encoded-in-the-graph)**        | Supported     | Not Supported | Not Supported | Not Supported |
+| **[Customizing the way type information is stored in the graph](features.md#customizing-how-types-are-encoded)**            | Supported     | Not Supported | Not Supported | Not Supported |
+| **Tinkerpop 2 support**                                                                                                     | Supported     | Supported     | Supported     | Not Supported |
+| **Tinkerpop 3 support**                                                                                                     | Supported     | Not Supported | Not Supported | Supported     |
 
 \* While Peapod does support querying for all instances of a type, and its subtypes, it does not support a mechanism to
 query for a specific type while excluding subtypes.
-
-### Type information encoded into graph
-
-```java
-Set<Class<?>> types = new HashSet<Class<?>>(Arrays.asList(new Class<?>[]{Person.class}));
-Graph g = new TinkerGraph();
-FramedGraph fg = new DelegatingFramedGraph(g, types);
-
-fg.addFramedVertex(Person.class);
-Person person = fg.v().next(Program.class);
-
-String personClassName = Person.class.getName();
-String encodedClassName = person.getProperty(PolymorphicTypeResolver.TYPE_RESOLUTION_KEY)
-assert(personClassName.equals(encodedClassName));
-```
-
-### Framing instantiated by type hierarchy
-
-```java
-Set<Class<?>> types = new HashSet<Class<?>>(Arrays.asList(new Class<?>[]{Person.class,
-                                                                         Programmer.class}));
-TinkerGraph g = new TinkerGraph();
-FramedGraph fg = new DelegatingFramedGraph(g, types);
-
-fg.addFramedVertex(Programmer.class);
-
-//make sure the newly added node is actually a programmer
-Person programmer = fg.v().next(Person.class);
-assert(programmer instanceof Programmer);
-```
-
-### Element queried by type hierarchy
-
-```java
-Set<Class<?>> types = new HashSet<Class<?>>(Arrays.asList(new Class<?>[]{Person.class,
-                                                                         Programmer.class}));
-TinkerGraph g = new TinkerGraph();
-FramedGraph fg = new DelegatingFramedGraph(g, types);
-
-fg.addFramedVertex(Programmer.class);
-fg.addFramedVertex(Person.class);
-
-//counts how many people (or subclasses thereof) in the graph.
-assert(fg.v().has(Person.class).count() == 2);
-//counts how many programmers are in the graph
-assert(fg.v().has(Programmer.class).count() == 1);
-```
-
-### Turning off type resolution per call
-
-```java
-Set<Class<?>> types = new HashSet<Class<?>>(Arrays.asList(new Class<?>[]{Person.class,
-                                                                         Programmer.class}));
-TinkerGraph g = new TinkerGraph();
-FramedGraph fg = new DelegatingFramedGraph(g, types);
-
-fg.addFramedVertex(Programmer.class);
-
-//With type resolution is active it should be a programmer
-assert(fg.v().next(Person.class) instanceof Programmer);
-//With type resolution bypassed it is no longer a programmer
-assert(!(fg.v().nextExplicit(Person.class) instanceof Programmer));
-```
-
-### Changing type encoded in the graph
-
-```java
-Set<Class<?>> types = new HashSet<Class<?>>(Arrays.asList(new Class<?>[]{Person.class,
-                                                                         Programmer.class}));
-TinkerGraph g = new TinkerGraph();
-FramedGraph fg = new DelegatingFramedGraph(g, types);
-
-fg.addFramedVertex(Programmer.class);
-
-//make sure the newly added node is actually a programmer
-Person programmer = fg.v().next(Person.class);
-assert(programmer instanceof Programmer);
-
-//change the type resolution to person
-programmer.setTypeResolution(Person.class);
-
-//make sure the newly added node is actually a programmer
-Person person = fg.v().next(Person.class);
-assert(person instanceof Person);
-assert(!(person instanceof Programmer));
-```
-
-### Customizing how types are encoded
-
-```java
-Set<Class<?>> types = new HashSet<Class<?>>(Arrays.asList(new Class<?>[]{Person.class}));
-final ReflectionCache cache = new ReflectionCache(types);
-FrameFactory factory = new AnnotationFrameFactory(cache);
-TypeResolver resolver = new PolymorphicTypeResolver(cache, "customTypeKey");
-Graph g = new TinkerGraph();
-FramedGraph fg = new DelegatingFramedGraph(g, factory, resolver);
-
-fg.addFramedVertex(Person.class);
-Person person = fg.v().next(Program.class);
-
-String personClassName = Person.class.getName();
-String encodedClassName = person.getProperty("customTypeKey")
-assert(personClassName.equals(encodedClassName));
-```
-
diff --git a/docs/features.md b/docs/features.md
new file mode 100644
index 0000000000000000000000000000000000000000..68628d75fe4ceeee7c7774e0a4e4dad3e00eb73b
--- /dev/null
+++ b/docs/features.md
@@ -0,0 +1,157 @@
+The following gives a quick breakdown of some of the features of the Ferma framework along with examples.
+
+* [JPA-like Annotations](#jpa-like-annotations)
+* [Type information encoded into graph](#type-information-encoded-into-graph)
+* [Framing of elements instantiated according to type hierarchy](#framing-instantiated-by-type-hierarchy)
+* [Element queried by type hierarchy](#element-queried-by-type-hierarchy)
+* [Turning off type resolution on a per call basis](#turning-off-type-resolution-per-call)
+* [Changing the encoded graph type already stored in the database](#changing-type-encoded-in-the-graph)
+* [Customizing the way type information is stored in the graph](#customizing-how-types-are-encoded)
+* Tinkerpop 2 support
+* Tinkerpop 3 support
+
+## JPA-like Annotations
+
+```Java
+public abstract class Person extends AbstractVertexFrame {
+  @Property("name")
+  public abstract String getName();
+
+  @Property("name")
+  public abstract void setName(String name);
+
+  @Adjacency(label = "knows")
+  public abstract List<Person> getKnowsPeople();
+}
+
+public abstract class Programmer extends Person {
+}
+
+public void testAnnotatedTyping() {
+  Set<Class<?>> types = new HashSet<Class<?>>(Arrays.asList(new Class<?>[]{
+                Person.class,
+                Programmer.class,
+                Knows.class}));
+  Graph graph = TinkerGraph.open();
+
+  //implies annotated mode
+  FramedGraph fg = new DelegatingFramedGraph(graph, true, types);
+
+  Person jeff = fg.addFramedVertex(Programmer.class);
+  jeff.setName("Jeff");
+
+  Person julia = fg.addFramedVertex(Person.class);
+  julia.setName("Julia");
+  julia.addKnows(jeff);
+
+  Person juliaAgain = fg.traverse((g) -> g.V().has("name", "Julia")).next(Person.class);
+  Person jeffAgain = juliaAgain.getKnowsPeople().get(0);
+
+  assert jeffAgain instanceof Programmer;
+  assert jeffAgain.getName().equals("Jeff");
+}
+```
+
+## Type information encoded into graph
+
+```java
+Set<Class<?>> types = new HashSet<Class<?>>(Arrays.asList(new Class<?>[]{Person.class}));
+Graph g = new TinkerGraph();
+FramedGraph fg = new DelegatingFramedGraph(g, types);
+
+fg.addFramedVertex(Person.class);
+Person person = fg.traverse(g -> g.V()).next(Program.class);
+
+String personClassName = Person.class.getName();
+String encodedClassName = person.getProperty(PolymorphicTypeResolver.TYPE_RESOLUTION_KEY)
+assert personClassName.equals(encodedClassName);
+```
+
+## Framing instantiated by type hierarchy
+
+```java
+Set<Class<?>> types = new HashSet<Class<?>>(Arrays.asList(new Class<?>[]{Person.class,
+                                                                         Programmer.class}));
+TinkerGraph g = new TinkerGraph();
+FramedGraph fg = new DelegatingFramedGraph(g, types);
+
+fg.addFramedVertex(Programmer.class);
+
+//make sure the newly added node is actually a programmer
+Person programmer = fg.traverse(g -> g.V()).next(Person.class);
+assert programmer instanceof Programmer;
+```
+
+## Element queried by type hierarchy
+
+```java
+Set<Class<?>> types = new HashSet<Class<?>>(Arrays.asList(new Class<?>[]{Person.class,
+                                                                         Programmer.class}));
+TinkerGraph g = new TinkerGraph();
+FramedGraph fg = new DelegatingFramedGraph(g, types);
+
+fg.addFramedVertex(Programmer.class);
+fg.addFramedVertex(Person.class);
+
+//counts how many people (or subclasses thereof) in the graph.
+assert fg.traverse(g -> g.getTypeResolver().hasType(g.V(), Person.class)).toList(Person.class).size() == 2;
+//counts how many programmers are in the graph
+assert fg.traverse(g -> g.getTypeResolver().hasType(g.V(), Programmer.class)).toList(Person.class).size() == 1;
+```
+
+## Turning off type resolution per call
+
+```java
+Set<Class<?>> types = new HashSet<Class<?>>(Arrays.asList(new Class<?>[]{Person.class,
+                                                                         Programmer.class}));
+TinkerGraph g = new TinkerGraph();
+FramedGraph fg = new DelegatingFramedGraph(g, types);
+
+fg.addFramedVertex(Programmer.class);
+
+//With type resolution is active it should be a programmer
+assert fg.traverse(g -> g.V()).next(Person.class) instanceof Programmer;
+//With type resolution bypassed it is no longer a programmer
+assert !(fg.traverse(g -> g.V()).nextExplicit(Person.class) instanceof Programmer);
+```
+
+## Changing type encoded in the graph
+
+```java
+Set<Class<?>> types = new HashSet<Class<?>>(Arrays.asList(new Class<?>[]{Person.class,
+                                                                         Programmer.class}));
+TinkerGraph g = new TinkerGraph();
+FramedGraph fg = new DelegatingFramedGraph(g, types);
+
+fg.addFramedVertex(Programmer.class);
+
+//make sure the newly added node is actually a programmer
+Person programmer = fg.traverse(g -> g.V()).next(Person.class);
+assert programmer instanceof Programmer;
+
+//change the type resolution to person
+programmer.setTypeResolution(Person.class);
+
+//make sure the newly added node is actually a programmer
+Person person = fg.traverse(g -> g.V()).next(Person.class);
+assert !(person instanceof Programmer);
+```
+
+## Customizing how types are encoded
+
+```java
+Set<Class<?>> types = new HashSet<Class<?>>(Arrays.asList(new Class<?>[]{Person.class}));
+final ReflectionCache cache = new ReflectionCache(types);
+FrameFactory factory = new AnnotationFrameFactory(cache);
+TypeResolver resolver = new PolymorphicTypeResolver(cache, "customTypeKey");
+Graph g = new TinkerGraph();
+FramedGraph fg = new DelegatingFramedGraph(g, factory, resolver);
+
+fg.addFramedVertex(Person.class);
+Person person = fg.traverse(g -> g.V()).next(Programmer.class);
+
+String personClassName = Person.class.getName();
+String encodedClassName = person.getProperty("customTypeKey")
+assert personClassName.equals(encodedClassName);
+```
+
diff --git a/mkdocs.yml b/mkdocs.yml
index 861e69fb5a26190a7a5f1f82193e98b2dfc2f966..eacbf0c46b5cc416dbf1c29ed89edc845aed8ee6 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -11,6 +11,7 @@ site_url: 'http://syncleus.com/Ferma'
 pages:
     - Home: index.md
     - Getting Started: getting_started.md
+    - Features: features.md
     - Object Mapping: object_mapping.md
     - Core Annotations:
         - Overview: annotations/overview.md