diff --git a/src/utils/parse.ts b/src/utils/parse.ts
index 7c4fb04..c6e1a07 100644
--- a/src/utils/parse.ts
+++ b/src/utils/parse.ts
@@ -7,6 +7,15 @@ type TutorialFrame = {
   levels: T.Level[];
 };
 
+const R = {
+  summary: /^#\s(?<tutorialTitle>.*)[\n\r]+(?<tutorialDescription>[^]*)/,
+  level: /^(#{2}\s(?<levelId>L?\d+\.?)\s(?<levelTitle>.*)[\n\r]*(>\s(?<levelSummary>.*))?[\n\r]+(?<levelContent>[^]*))/,
+  step: /^(#{3}\s(?<stepTitle>.*)[\n\r]+(?<stepContent>[^]*))/,
+  hints: /^(#{4}\sHINTS[\n\r]+([\*|\-]\s(?<hintContent>[^]*))[\n\r]+)+/,
+  subtasks: /^(#{4}\sSUBTASKS[\n\r]+([\*|\-]\s(?<subtaskContent>[^]*))[\n\r]+)+/,
+  listItem: /[\n\r]+[\*|\-]\s/,
+};
+
 export function parseMdContent(md: string): TutorialFrame | never {
   let start: number = -1;
   const parts: any[] = [];
@@ -34,9 +43,7 @@ export function parseMdContent(md: string): TutorialFrame | never {
   };
 
   // Capture summary
-  const summaryMatch = parts
-    .shift()
-    .match(/^#\s(?<tutorialTitle>.*)[\n\r]+(?<tutorialDescription>[^]*)/);
+  const summaryMatch = parts.shift().match(R.summary);
   if (summaryMatch.groups.tutorialTitle) {
     mdContent.summary.title = summaryMatch.groups.tutorialTitle.trim();
   }
@@ -49,8 +56,7 @@ export function parseMdContent(md: string): TutorialFrame | never {
   // Identify each part of the content
   parts.forEach((section: string) => {
     // match level
-    const levelRegex = /^(#{2}\s(?<levelId>L?\d+\.?)\s(?<levelTitle>.*)[\n\r]*(>\s(?<levelSummary>.*))?[\n\r]+(?<levelContent>[^]*))/;
-    const levelMatch: RegExpMatchArray | null = section.match(levelRegex);
+    const levelMatch: RegExpMatchArray | null = section.match(R.level);
 
     if (levelMatch && levelMatch.groups) {
       const levelId = levelMatch.groups.levelId.replace(".", "");
@@ -77,8 +83,7 @@ export function parseMdContent(md: string): TutorialFrame | never {
       };
     } else {
       // match step
-      const stepRegex = /^(#{3}\s(?<stepTitle>.*)[\n\r]+(?<stepContent>[^]*))/;
-      const stepMatch: RegExpMatchArray | null = section.match(stepRegex);
+      const stepMatch: RegExpMatchArray | null = section.match(R.step);
       if (stepMatch && stepMatch.groups) {
         current = {
           levelId: current.levelId,
@@ -91,20 +96,36 @@ export function parseMdContent(md: string): TutorialFrame | never {
           content: stepContent.trim(),
         };
       } else {
-        // parse hints from stepContent
-        const hintDetectRegex = /^(#{4}\sHINTS[\n\r]+([\*|\-]\s(?<hintContent>[^]*))[\n\r]+)+/;
-        const hintMatch = section.match(hintDetectRegex);
-        if (!!hintMatch) {
-          const hintItemRegex = /[\n\r]+[\*|\-]\s/;
-          const hints = section
-            .split(hintItemRegex)
-            .slice(1) // remove #### HINTS
-            .map((h) => h.trim());
-          if (hints.length) {
-            mdContent.levels[current.levelIndex].steps[
-              current.stepIndex
-            ].hints = hints;
-          }
+        const hintMatch = section.match(R.hints);
+        const subtaskMatch = section.match(R.subtasks);
+
+        switch (true) {
+          // parse hints from stepContent
+          case !!hintMatch:
+            const hints = section
+              .split(R.listItem)
+              .slice(1) // remove #### HINTS
+              .map((h) => h.trim());
+            if (hints.length) {
+              mdContent.levels[current.levelIndex].steps[
+                current.stepIndex
+              ].hints = hints;
+            }
+            return;
+          // parse subtasks from stepContent
+          case !!subtaskMatch:
+            const subtasks = section
+              .split(R.listItem)
+              .slice(1) // remove #### SUBTASKS
+              .map((h) => h.trim());
+            if (subtasks.length) {
+              mdContent.levels[current.levelIndex].steps[
+                current.stepIndex
+              ].subtasks = subtasks;
+            }
+            return;
+          default:
+            console.warn(`No build parser match found for:\n${section}\n`);
         }
       }
     }
diff --git a/tests/parse.test.ts b/tests/parse.test.ts
index 28746af..478918b 100644
--- a/tests/parse.test.ts
+++ b/tests/parse.test.ts
@@ -541,7 +541,6 @@ The first step
                   files: ["someFile.js"],
                   watchers: ["someFile.js"],
                   filter: "someFilter",
-                  subtasks: true,
                 },
                 solution: {
                   commands: ["npm install"],
@@ -579,7 +578,6 @@ The first step
                   files: ["someFile.js"],
                   watchers: ["someFile.js"],
                   filter: "someFilter",
-                  subtasks: true,
                 },
                 solution: {
                   commits: ["1gfedcba", "987654321"],
@@ -631,7 +629,6 @@ The third step
                   files: ["someFile.js"],
                   watchers: ["someFile.js"],
                   filter: "someFilter",
-                  subtasks: true,
                 },
                 solution: {
                   commands: ["npm install"],
@@ -645,7 +642,6 @@ The third step
                   files: ["someFile.js"],
                   watchers: ["someFile.js"],
                   filter: "someFilter",
-                  subtasks: true,
                 },
                 solution: {
                   commands: ["npm install"],
@@ -666,7 +662,6 @@ The third step
                   files: ["someFile.js"],
                   watchers: ["someFile.js"],
                   filter: "someFilter",
-                  subtasks: true,
                 },
                 solution: {
                   commands: ["npm install"],
@@ -709,7 +704,6 @@ The third step
                   files: ["someFile.js"],
                   watchers: ["someFile.js"],
                   filter: "someFilter",
-                  subtasks: true,
                 },
                 solution: {
                   commits: ["1fedcba", "987654321"],
@@ -726,7 +720,6 @@ The third step
                   files: ["someFile.js"],
                   watchers: ["someFile.js"],
                   filter: "someFilter",
-                  subtasks: true,
                 },
                 solution: {
                   commits: ["3abcdef"],
@@ -751,7 +744,6 @@ The third step
                   files: ["someFile.js"],
                   watchers: ["someFile.js"],
                   filter: "someFilter",
-                  subtasks: true,
                 },
                 solution: {
                   commits: ["5abcdef"],
@@ -1419,4 +1411,75 @@ The second uninterrupted step
       expect(result.levels[0]).toEqual(expected.levels[0]);
     });
   });
+  describe("subtasks", () => {
+    it("should parse subtasks", () => {
+      const md = `# Subtask Demo
+
+A demo demonstrating how to use subtasks
+
+## 1. Subtask Example
+
+A subtask example
+
+### 1.1
+
+Create a function \`add\` that can take a variety of params.
+
+#### SUBTASKS
+
+- Add one number
+- Add two numbers
+- Add three numbers
+`;
+      const skeleton = {
+        levels: [
+          {
+            id: "1",
+            steps: [
+              {
+                id: "1.1",
+              },
+            ],
+          },
+        ],
+      };
+      const expected = {
+        levels: [
+          {
+            id: "1",
+            title: "Subtask Example",
+            summary: "A subtask example",
+            content: "A subtask example",
+            steps: [
+              {
+                id: "1.1",
+                setup: {
+                  commits: ["abcdef1"],
+                },
+                content:
+                  "Create a function `add` that can take a variety of params.",
+                solution: {
+                  commits: ["abcdef2"],
+                },
+                subtasks: [
+                  "Add one number",
+                  "Add two numbers",
+                  "Add three numbers",
+                ],
+              },
+            ],
+          },
+        ],
+      };
+      const result = parse({
+        text: md,
+        skeleton,
+        commits: {
+          "1.1:T": ["abcdef1"],
+          "1.1:S": ["abcdef2"],
+        },
+      });
+      expect(result.levels[0]).toEqual(expected.levels[0]);
+    });
+  });
 });
diff --git a/typings/tutorial.d.ts b/typings/tutorial.d.ts
index 2b7769c..f19830b 100644
--- a/typings/tutorial.d.ts
+++ b/typings/tutorial.d.ts
@@ -27,7 +27,7 @@ export type Step = {
   content: string;
   setup?: StepActions;
   solution?: Maybe<StepActions>;
-  subtasks?: { [testName: string]: boolean };
+  subtasks?: string[];
   hints?: string[];
 };
 
@@ -52,7 +52,7 @@ export type StepActions = {
   files?: string[];
   watchers?: string[];
   filter?: string;
-  subtasks?: boolean;
+  subtasks?: string[];
 };
 
 export interface TestRunnerArgs {