diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,9 @@
 # Revision history for javelin-frames
 
+## Release 0.1.0.2
+
+* Fixed markup of tutorial
+
 ## Release 0.1.0.1
 
 * Explicit support for `containers-0.8`
diff --git a/javelin-frames.cabal b/javelin-frames.cabal
--- a/javelin-frames.cabal
+++ b/javelin-frames.cabal
@@ -1,6 +1,6 @@
 cabal-version:      3.0
 name:               javelin-frames
-version:            0.1.0.1
+version:            0.1.0.2
 synopsis:           Type-safe data frames based on higher-kinded types.
 -- description:
 license:            MIT
diff --git a/src/Data/Frame/Tutorial.hs b/src/Data/Frame/Tutorial.hs
--- a/src/Data/Frame/Tutorial.hs
+++ b/src/Data/Frame/Tutorial.hs
@@ -14,17 +14,17 @@
 
     -- * Quick start
     -- $quickstart
-    
+
     -- * Defining types
     -- $construction
 
     -- * Advanced indexing
     -- $advindexing
 
-    -- * Merging dataframes    
+    -- * Merging dataframes
     -- ** Zipping
     -- $zipping
-    
+
     -- ** Merging by key
     -- $merging
 
@@ -41,8 +41,8 @@
 
 This is a short user guide on how to get started using @javelin-frames@.
 
-The central data structure at the heart of this package is the dataframe. 
-A dataframe, represented by @`Frame` t@ for some record-type @t@, is a 
+The central data structure at the heart of this package is the dataframe.
+A dataframe, represented by @`Frame` t@ for some record-type @t@, is a
 record whose values are arrays representing columns.
 
 -}
@@ -63,7 +63,7 @@
 
 == Defining dataframes
 
-All dataframes must be defined as record types with a type parameter @f@, 
+All dataframes must be defined as record types with a type parameter @f@,
 where each field involves the `Column` type family, like so:
 
 >>> :{
@@ -80,7 +80,7 @@
 
 >>> deriving instance Frameable Student
 
-Note that the derivation is automatically done for you, through the `Generic` 
+Note that the derivation is automatically done for you, through the `Generic`
 instance for @Student@.
 
 One caveat of this approach is that instances for other typeclasses (e.g. `Show`, `Eq`)
@@ -100,7 +100,7 @@
 Let's now build a dataframe. We use `fromRows` to pack individual students into a dataframe:
 
 >>> :{
-    students = fromRows 
+    students = fromRows
              [ MkStudent "Albert" 12 'C'
              , MkStudent "Beatrice" 13 'B'
              , MkStudent "Clara" 12 'A'
@@ -110,13 +110,13 @@
 Individual students like @MkStudent "Albert" 23 'C'@ are of type @`Row` Student@, but
 the dataframe @students@ has type @`Frame` Student@.
 
-We can render the dataframe @students@ into a nice string using `display` 
+We can render the dataframe @students@ into a nice string using `display`
 (and print that string using using `putStrLn`):
 
 >>> putStrLn (display students)
 studentName | studentAge | studentMathGrade
 ----------- | ---------- | ----------------
-   "Albert" |         12 |              'C' 
+   "Albert" |         12 |              'C'
  "Beatrice" |         13 |              'B'
     "Clara" |         12 |              'A'
 
@@ -145,25 +145,25 @@
 There's `mapRows` to map each row to a new structure:
 
 >>> :{
-    putStrLn 
-        $ display 
-            $ mapRows 
-                (\(MkStudent name age grade) -> MkStudent name (2*age) grade) 
+    putStrLn
+        $ display
+            $ mapRows
+                (\(MkStudent name age grade) -> MkStudent name (2*age) grade)
                 students
 :}
 studentName | studentAge | studentMathGrade
 ----------- | ---------- | ----------------
-   "Albert" |         24 |              'C' 
+   "Albert" |         24 |              'C'
  "Beatrice" |         26 |              'B'
     "Clara" |         24 |              'A'
 
 There's `filterRows` to keep specific rows:
 
 >>> :{
-    putStrLn 
-        $ display 
-            $ filterRows 
-                (\(MkStudent _ _ grade) -> grade < 'C') 
+    putStrLn
+        $ display
+            $ filterRows
+                (\(MkStudent _ _ grade) -> grade < 'C')
                 students
 :}
 studentName | studentAge | studentMathGrade
@@ -175,9 +175,9 @@
 
 >>> import Data.Char (ord)
 >>> :{
-    foldlRows 
-        (\acc (MkStudent _ age grade) -> acc + age + ord grade) 
-        (0 :: Int) 
+    foldlRows
+        (\acc (MkStudent _ age grade) -> acc + age + ord grade)
+        (0 :: Int)
         students
 :}
 235
@@ -190,7 +190,7 @@
 === Querying by integer index
 
 Querying by integer index is supported for all dataframes. Use
-the `ilookup` function to retrive a row:
+the `ilookup` function to retrieve a row:
 
 >>> ilookup 0 students
 Just (MkStudent {studentName = "Albert", studentAge = 12, studentMathGrade = 'C'})
@@ -222,8 +222,8 @@
         index = studentName
 :}
 
-Now, we can use the functions `Frame.lookup` and `at` (similar to `ilookup` 
-and `iat`, respectively) which take key (in our case, student names) 
+Now, we can use the functions `Frame.lookup` and `at` (similar to `ilookup`
+and `iat`, respectively) which take key (in our case, student names)
 instead of integer indices.
 
 >>> Frame.lookup "Beatrice" students
@@ -239,7 +239,7 @@
 and more advanced functionality.
 -}
 
-{- $construction 
+{- $construction
 
 To start using the machinery of this package, one must define the appropriate type.
 Types that can be turned into dataframes are non-empty, higher-kinded, record types.
@@ -259,14 +259,14 @@
         deriving (Generic)
 :}
 
-Here, we define a higher-kinded record type @Store@ with four fields. 
+Here, we define a higher-kinded record type @Store@ with four fields.
 The type parameter @f@ allows the various functions in this package
 to switch between a column-oriented format and single-rows.
 
 In practice the type @f@ can only be `Identity` (for a single row),
 or `Vector` (for a dataframe)
 
-For ergonomics, the type synonym @`Row` t@ is provided to represent a 
+For ergonomics, the type synonym @`Row` t@ is provided to represent a
 single row. The type synonym @`Frame` t@ is provided to represent
 a dataframe.
 
@@ -286,7 +286,7 @@
 record types.
 
 In order to access dataframe functionality, we need to ask our code
-to generate some boilerplate automatically. We do this by deriving an 
+to generate some boilerplate automatically. We do this by deriving an
 instance of `Frameable`:
 
 >>> :set -XDeriveAnyClass
@@ -296,7 +296,7 @@
 a `Generic` instance. This allows @javelin-frames@ to inspect our type @Store@
 and write an implementation of `Frameable` automatically.
 
-** Limitations
+== Limitations
 
 At this time, `Frameable` can only be derived for higher-kinded record types that
 do NOT nest. For example, consider the following hierarchy:
@@ -322,7 +322,7 @@
 deriving instance Frameable Company
 @
 
-Are you an expert in generics who wants to help us figure it out? Feel free to 
+Are you an expert in generics who wants to help us figure it out? Feel free to
 [raise an issue or open a pull request](https://github.com/LaurentRDC/javelin).
 -}
 
@@ -334,12 +334,12 @@
 However, many types can naturally be indexed by a subset of the columns, which becomes a key
 This key is similar to primary keys in databases.
 
-We can derive an instance of `Indexable` to allow us to query data from a 
+We can derive an instance of `Indexable` to allow us to query data from a
 dataframe not by the integer index of the rows, but by some key instead.
 
-** Simple keys
+== Simple keys
 
-The simplest example is that of keys derived from a single column. 
+The simplest example is that of keys derived from a single column.
 
 We start with a data definition:
 
@@ -367,7 +367,7 @@
 As an example, let's build a dataframe of stores:
 
 >>> :{
-    stores = fromRows 
+    stores = fromRows
            [ MkStore "Store A" (Addr "8712 1st Avenue") 787123745
            , MkStore "Store B" (Addr "90 2st Street")   188712313
            , MkStore "Store C" (Addr "109 3rd Street")  910823870
@@ -379,7 +379,7 @@
 >>> Frame.lookup 787123745 stores
 Just (MkStore {storeName = "Store A", storeAddress = Addr "8712 1st Avenue", storeId = 787123745})
 
-** Compound keys
+== Compound keys
 
 Sometimes, it is preferable to identify rows through multiple columns. Again in
 in analogy with databases, the key is a _compound key_.
@@ -396,7 +396,7 @@
     deriving instance Show (Row Actor)
 :}
 
-In this case, we can identify actors by their first and last name, 
+In this case, we can identify actors by their first and last name,
 which creates a compound key:
 
 >>> :{
@@ -409,7 +409,7 @@
 We define some data
 
 >>> :{
-    actors = fromRows 
+    actors = fromRows
            [ MkActor "George" "Clooney" 63
            , MkActor "Brad"   "Pitt"    61
            , MkActor "George" "Takei"   87
@@ -472,7 +472,7 @@
 >>> :{
     putStrLn
         $ display
-            $ zipRowsWith 
+            $ zipRowsWith
                 (\(MkPet name age) (MkPetInfo _ race) -> MkPetSummary name age race)
                 pets
                 petInfos
@@ -486,14 +486,14 @@
 
 
 Hmm this doesn't look right, if you manually inspect the two source dataframes.
-This is because rows are combined in order. You may want to sort rows using 
+This is because rows are combined in order. You may want to sort rows using
 `sortRowsBy` or `sortRowsByUnique`, before applying `zipRowsWith`:
 
 >>> import Data.Function (on)
 >>> :{
     putStrLn
         $ display
-            $ zipRowsWith 
+            $ zipRowsWith
                 (\(MkPet name age) (MkPetInfo _ race) -> MkPetSummary name age race)
                 (sortRowsBy (compare `on` petName) pets)
                 (sortRowsBy (compare `on` petInfoName) petInfos)
@@ -511,9 +511,9 @@
 
 {- $merging
 
-If you want to merge dataframes whose rows have a natural key (i.e. have an instance of `Indexable`), 
-then you should take a look at `mergeWithStrategy`. 
-In this function, for each key present in __either__ dataframe, 
+If you want to merge dataframes whose rows have a natural key (i.e. have an instance of `Indexable`),
+then you should take a look at `mergeWithStrategy`.
+In this function, for each key present in __either__ dataframe,
 a merging strategy is applied. This strategy encodes how the merge should proceed in three cases:
 
 * The key is present in the left dataframe, but not the right;
@@ -555,12 +555,12 @@
                    [ MkContainerDest 1 "Japan"
                    , MkContainerDest 2 "Canada"
                    , MkContainerDest 3 "USA"
-                   -- missing container destination for #4 
+                   -- missing container destination for #4
                    , MkContainerDest 5 "France"
                    ]
 :}
 
-We will first start by merging the dataframes only when we have complete data 
+We will first start by merging the dataframes only when we have complete data
 (i.e. an inner join). We first define the shape of the resulting dataframe:
 
 >>> :{
@@ -580,7 +580,8 @@
 * v`That`: The key is present in the right dataframe, but not the left;
 * v`These`: The key is present in both dataframes (not to be confused with the type constructor t`These`).
 
-In the simplest case, we only care about keys present in both dataframe (v`These`)
+In the simplest case, we only care about keys present in both dataframe (`These`)
+
 >>> :{
     completeDataStrategy :: Int -> These (Row ContainerOrigin) (Row ContainerDest) -> Maybe (Row ContainerJourney)
     completeDataStrategy containerId (These (MkContainerOrigin _ origin) (MkContainerDest _ dest))
@@ -589,14 +590,15 @@
 :}
 
 Sidenote: @completeDataStrategy@ is equivalent to `matchedStrategy`. We re-defined it for illustrative purposes.
+
 >>> :{
     putStrLn
         $ display
-            $ mergeWithStrategy 
+            $ mergeWithStrategy
                 completeDataStrategy
                 containerOrigins
                 containerDests
-:}  
+:}
 containerJourneyId | containerJourneyOrig | containerJourneyDest
 ------------------ | -------------------- | --------------------
                  1 |             "Canada" |              "Japan"
@@ -618,18 +620,18 @@
     completeDataStrategy' :: Int -> These (Row ContainerOrigin) (Row ContainerDest) -> Maybe (Row ContainerJourney)
     completeDataStrategy' containerId (These (MkContainerOrigin _ origin) (MkContainerDest _ dest))
         | validCountry origin && validCountry dest = Just $ MkContainerJourney containerId origin dest
-        | otherwise                                = Nothing 
+        | otherwise                                = Nothing
     completeDataStrategy' _ _ = Nothing -- not enough data
 :}
 
 >>> :{
     putStrLn
         $ display
-            $ mergeWithStrategy 
+            $ mergeWithStrategy
                 completeDataStrategy'
                 containerOrigins
                 containerDests
-:}  
+:}
 containerJourneyId | containerJourneyOrig | containerJourneyDest
 ------------------ | -------------------- | --------------------
                  1 |             "Canada" |              "Japan"
@@ -654,7 +656,7 @@
         | validCountry origin && validCountry dest = Just $ MkPartialContainerJourney containerId (Just origin) dest
         | validCountry dest                        = Just $ MkPartialContainerJourney containerId Nothing       dest
         | otherwise                                = Nothing
-    maybeOriginStrategy containerId (That (MkContainerDest _ dest)) 
+    maybeOriginStrategy containerId (That (MkContainerDest _ dest))
                                                    = Just $ MkPartialContainerJourney containerId Nothing       dest
     maybeOriginStrategy _           (This _)       = Nothing -- we require a destination
 :}
@@ -662,7 +664,7 @@
 >>> :{
     putStrLn
         $ display
-            $ mergeWithStrategy 
+            $ mergeWithStrategy
                 maybeOriginStrategy
                 containerOrigins
                 containerDests
