diff --git a/README.md b/README.md
index 3d44df97bbd5ddf6faaa6487782d6abd43245470..7b3ef26669073c9a0b60e381b23c8cc178c5bb52 100644
--- a/README.md
+++ b/README.md
@@ -30,8 +30,8 @@ src
     + java                        Test runners and supporting code
     + resources
       + features                  Feature files
-        + search                  Feature file subdirectories
-            search_by_keyword.feature
+        + veterinarian                  Feature file subdirectories
+            manage_specialties.feature
 ```
 
 Serenity 2.2.13 introduced integration with [WebDriverManager](https://bonigarcia.dev/webdrivermanager/) to download webdriver binaries.
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 0000000000000000000000000000000000000000..2aefcdec70a96556b8cba4ce0874c593b608ad02
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,10 @@
+---
+services:
+  api:
+    image: docker.io/springcommunity/spring-petclinic-rest:3.0.2
+    ports:
+      - "127.0.0.1:9966:9966"
+  app:
+    image: docker.io/addianto/spring-petclinic-angular:latest
+    ports:
+      - "127.0.0.1:80:8080"
diff --git a/src/test/java/starter/CucumberTestSuite.java b/src/test/java/starter/CucumberTestSuite.java
index cdac1f7e5e03839df695b1e74c7ed9205b0058f2..da9bb37ab9ef690f2fe5ee6c962487babf322e50 100644
--- a/src/test/java/starter/CucumberTestSuite.java
+++ b/src/test/java/starter/CucumberTestSuite.java
@@ -12,4 +12,4 @@ import static io.cucumber.junit.platform.engine.Constants.PLUGIN_PROPERTY_NAME;
 @SelectClasspathResource("/features")
 @ConfigurationParameter(key = PLUGIN_PROPERTY_NAME, value = "io.cucumber.core.plugin.SerenityReporterParallel,pretty,timeline:build/test-results/timeline")
 public class CucumberTestSuite {
-}
+}
\ No newline at end of file
diff --git a/src/test/java/starter/navigation/DuckDuckGoHomePage.java b/src/test/java/starter/navigation/DuckDuckGoHomePage.java
deleted file mode 100644
index d54895b9348c2ae3e78c7292932ee4d6a2a5b63e..0000000000000000000000000000000000000000
--- a/src/test/java/starter/navigation/DuckDuckGoHomePage.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package starter.navigation;
-
-import net.serenitybdd.annotations.DefaultUrl;
-import net.thucydides.core.pages.PageObject;
-
-@DefaultUrl("https://duckduckgo.com")
-public class DuckDuckGoHomePage extends PageObject {
-}
diff --git a/src/test/java/starter/navigation/NavigateTo.java b/src/test/java/starter/navigation/NavigateTo.java
index 7292a40e7acaacfbd25b698b740143c0247fbb3c..ed2172bb8875d4064ffe850b98a4283cd5cae2a6 100644
--- a/src/test/java/starter/navigation/NavigateTo.java
+++ b/src/test/java/starter/navigation/NavigateTo.java
@@ -5,8 +5,9 @@ import net.serenitybdd.screenplay.Task;
 import net.serenitybdd.screenplay.actions.Open;
 
 public class NavigateTo {
-    public static Performable theSearchHomePage() {
-        return Task.where("{0} opens the DuckDuckGo home page",
-                Open.browserOn().the(DuckDuckGoHomePage.class));
+
+    public static Performable theSpringPetclinicHomePage() {
+        return Task.where("{0} opens the Spring Petclinic home page",
+                Open.browserOn().the(SpringPetclinicHomePage.class));
     }
 }
diff --git a/src/test/java/starter/navigation/SpringPetclinicHomePage.java b/src/test/java/starter/navigation/SpringPetclinicHomePage.java
new file mode 100644
index 0000000000000000000000000000000000000000..de53d1793582714bf6e510851c6a1a12517a238e
--- /dev/null
+++ b/src/test/java/starter/navigation/SpringPetclinicHomePage.java
@@ -0,0 +1,8 @@
+package starter.navigation;
+
+import net.serenitybdd.annotations.DefaultUrl;
+import net.serenitybdd.core.pages.PageObject;
+
+@DefaultUrl("http://127.0.0.1")
+public class SpringPetclinicHomePage extends PageObject {
+}
diff --git a/src/test/java/starter/search/LookForInformation.java b/src/test/java/starter/search/LookForInformation.java
deleted file mode 100644
index d17fa05983af41c0f976b3b78cf89111269c7ebc..0000000000000000000000000000000000000000
--- a/src/test/java/starter/search/LookForInformation.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package starter.search;
-
-import net.serenitybdd.screenplay.Performable;
-import net.serenitybdd.screenplay.Task;
-import net.serenitybdd.screenplay.actions.Enter;
-import org.openqa.selenium.Keys;
-
-public class LookForInformation {
-    public static Performable about(String searchTerm) {
-        return Task.where("{0} searches for '" + searchTerm + "'",
-                Enter.theValue(searchTerm)
-                        .into(SearchForm.SEARCH_FIELD)
-                        .thenHit(Keys.ENTER)
-        );
-    }
-}
diff --git a/src/test/java/starter/search/SearchArticle.java b/src/test/java/starter/search/SearchArticle.java
deleted file mode 100644
index e510ffc01edb78978be7fb83d9caddde65f36716..0000000000000000000000000000000000000000
--- a/src/test/java/starter/search/SearchArticle.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package starter.search;
-
-import net.serenitybdd.screenplay.targets.Target;
-
-public class SearchArticle {
-    public static final Target BODY =  Target.the("article identifier").locatedBy("//article");
-}
diff --git a/src/test/java/starter/search/SearchForm.java b/src/test/java/starter/search/SearchForm.java
deleted file mode 100644
index 404636cd7c55eeff1fdad5c49810d34bfb095715..0000000000000000000000000000000000000000
--- a/src/test/java/starter/search/SearchForm.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package starter.search;
-
-import net.serenitybdd.screenplay.targets.Target;
-
-class SearchForm {
-    static Target SEARCH_FIELD = Target.the("search field").locatedBy("#searchbox_input");
-
-}
diff --git a/src/test/java/starter/stepdefinitions/PetTypeStepDefinitions.java b/src/test/java/starter/stepdefinitions/PetTypeStepDefinitions.java
new file mode 100644
index 0000000000000000000000000000000000000000..1fee08f823e9872bcb26898e9f15709fcc1baad5
--- /dev/null
+++ b/src/test/java/starter/stepdefinitions/PetTypeStepDefinitions.java
@@ -0,0 +1,69 @@
+package starter.stepdefinitions;
+
+import io.cucumber.datatable.DataTable;
+import io.cucumber.java.en.And;
+import io.cucumber.java.en.Given;
+import io.cucumber.java.en.Then;
+import io.cucumber.java.en.When;
+import net.serenitybdd.core.pages.WebElementFacade;
+import net.serenitybdd.screenplay.Actor;
+import net.serenitybdd.screenplay.actions.Click;
+import net.serenitybdd.screenplay.actions.Enter;
+import net.serenitybdd.screenplay.actions.HoverOverBy;
+import net.serenitybdd.screenplay.actions.Open;
+import net.serenitybdd.screenplay.ensure.Ensure;
+import net.serenitybdd.screenplay.ui.Button;
+import net.serenitybdd.screenplay.ui.InputField;
+import net.serenitybdd.screenplay.ui.Link;
+import org.openqa.selenium.Keys;
+import starter.navigation.SpringPetclinicHomePage;
+
+import java.util.List;
+
+public class PetTypeStepDefinitions {
+    @Given("a system operator named {actor} is looking at the pet types page")
+    public void lookingAtPetTypesPage(Actor actor) {
+        actor.wasAbleTo(
+                Open.browserOn()
+                    .the(SpringPetclinicHomePage.class),
+                // TODO: Refactor the two actions below into a new Performable class
+                HoverOverBy.over(Link.withText("Pet Types")),
+                Click.on(Link.withText("Pet Types"))
+        );
+    }
+
+    @And("{actor} found the following pet types exist:")
+    public void verifyingExistingPetTypes(Actor actor, DataTable table) {
+        List<String> existingPetTypes = InputField
+                .withNameOrId("pettype_name")
+                .resolveAllFor(actor)
+                .map(WebElementFacade::getValue);
+
+        actor.wasAbleTo(
+                Ensure.that(existingPetTypes)
+                      .containsElementsFrom(table.asList())
+        );
+    }
+
+    @When("{actor} adds a new pet type named {string}")
+    public void addsNewPetType(Actor actor, String name) {
+        actor.attemptsTo(
+                // TODO: Refactor the click action below into a new Performable class
+                Click.on(Button.withText("Add")),
+                Enter.theValue(name)
+                     .into(InputField.withNameOrId("name"))
+                     .thenHit(Keys.ENTER)
+        );
+    }
+
+    @Then("{actor} should see the pet type {string} on the list of pet types")
+    public void shouldSeeThePetType(Actor actor, String name) {
+        actor.attemptsTo(
+                Ensure.thatAmongst(InputField.withNameOrId("pettype_name"))
+                      .anyMatch(name + " should be on the list",
+                              (field) -> field.getValue()
+                                              .equals(name)
+                      )
+        );
+    }
+}
diff --git a/src/test/java/starter/stepdefinitions/SearchStepDefinitions.java b/src/test/java/starter/stepdefinitions/SearchStepDefinitions.java
deleted file mode 100644
index cf2d19ee130809006dc34d0dc1a9d8fd10268331..0000000000000000000000000000000000000000
--- a/src/test/java/starter/stepdefinitions/SearchStepDefinitions.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package starter.stepdefinitions;
-
-import io.cucumber.java.en.Given;
-import io.cucumber.java.en.Then;
-import io.cucumber.java.en.When;
-import net.serenitybdd.screenplay.Actor;
-import net.serenitybdd.screenplay.ensure.Ensure;
-import net.serenitybdd.screenplay.questions.page.TheWebPage;
-import starter.navigation.NavigateTo;
-import starter.search.LookForInformation;
-
-public class SearchStepDefinitions {
-
-    @Given("{actor} is researching things on the internet")
-    public void researchingThings(Actor actor) {
-        actor.wasAbleTo(NavigateTo.theSearchHomePage());
-    }
-
-    @When("{actor} looks up {string}")
-    public void searchesFor(Actor actor, String term) {
-        actor.attemptsTo(
-                LookForInformation.about(term)
-        );
-    }
-
-    @Then("{actor} should see information about {string}")
-    public void should_see_information_about(Actor actor, String term) {
-        actor.attemptsTo(
-                Ensure.that(TheWebPage.title()).containsIgnoringCase(term)
-        );
-    }
-}
diff --git a/src/test/java/starter/stepdefinitions/SpecialtyStepDefinitions.java b/src/test/java/starter/stepdefinitions/SpecialtyStepDefinitions.java
new file mode 100644
index 0000000000000000000000000000000000000000..cd54eb5ac01d9af55180156b9585fac931cf212d
--- /dev/null
+++ b/src/test/java/starter/stepdefinitions/SpecialtyStepDefinitions.java
@@ -0,0 +1,61 @@
+package starter.stepdefinitions;
+
+import io.cucumber.java.en.Given;
+import io.cucumber.java.en.Then;
+import io.cucumber.java.en.When;
+import net.serenitybdd.screenplay.Actor;
+import net.serenitybdd.screenplay.actions.*;
+import net.serenitybdd.screenplay.ensure.Ensure;
+import net.serenitybdd.screenplay.ui.Button;
+import net.serenitybdd.screenplay.ui.InputField;
+import net.serenitybdd.screenplay.ui.Link;
+import org.openqa.selenium.By;
+import org.openqa.selenium.Keys;
+import starter.navigation.SpringPetclinicHomePage;
+
+public class SpecialtyStepDefinitions {
+
+    @Given("a system operator named {actor} is looking at the specialties page")
+    public void lookingAtSpecialtiesPage(Actor actor) {
+        actor.wasAbleTo(
+                Open.browserOn()
+                    .the(SpringPetclinicHomePage.class),
+                // TODO: Refactor the two actions below into a new Performable class
+                HoverOverBy.over(Link.withText("Specialties")),
+                Click.on(Link.withText("Specialties"))
+        );
+    }
+
+    @When("{actor} adds a new specialty called {string}")
+    public void addsNewSpecialty(Actor actor, String name) {
+        actor.attemptsTo(
+                // TODO: Refactor the Click action into a new Performable class
+                Click.on(Button.withText("Add")),
+                Enter.theValue(name)
+                     .into(InputField.withNameOrId("name"))
+                     .thenHit(Keys.ENTER)
+        );
+    }
+
+    @When("{actor} edits the first specialty to {string}")
+    public void editsFirstSpecialty(Actor actor, String name) {
+        actor.attemptsTo(
+                Click.on(Button.located(By.xpath("//table[@id='specialties']/tbody/tr[1]/td[2]/button[1]"))),
+                Clear.field(InputField.withNameOrId("name")),
+                Enter.theValue(name)
+                     .into(InputField.withNameOrId("name")),
+                Click.on(Button.withText("Update"))
+        );
+    }
+
+    @Then("{actor} should see the specialty {string} on the list of specialties")
+    public void shouldSeeTheSpecialty(Actor actor, String name) {
+        actor.attemptsTo(
+                Ensure.thatAmongst(InputField.withNameOrId("spec_name"))
+                      .anyMatch(name + " should be on the list",
+                              (field) -> field.getValue()
+                                              .equals(name)
+                      )
+        );
+    }
+}
diff --git a/src/test/resources/features/search/search_by_keyword.feature b/src/test/resources/features/search/search_by_keyword.feature
deleted file mode 100644
index e6475dee301ffa5542f03fd4a8a81027e51ecdfb..0000000000000000000000000000000000000000
--- a/src/test/resources/features/search/search_by_keyword.feature
+++ /dev/null
@@ -1,13 +0,0 @@
-Feature: Search by keyword
-
-  @green
-  Scenario: Searching for 'green'
-    Given Sergey is researching things on the internet
-    When he looks up "green"
-    Then he should see information about "green"
-
-  @red
-  Scenario: Searching for 'red'
-    Given Sergey is researching things on the internet
-    When he looks up "red"
-    Then he should see information about "red"
diff --git a/src/test/resources/features/veterinarian/manage_pet_types.feature b/src/test/resources/features/veterinarian/manage_pet_types.feature
new file mode 100644
index 0000000000000000000000000000000000000000..1b87c497b5c7d5ceb760b44e779646a8fecb0ede
--- /dev/null
+++ b/src/test/resources/features/veterinarian/manage_pet_types.feature
@@ -0,0 +1,16 @@
+Feature: Manage pet types
+  The veterinarian wants to be able to add, edit, and delete pet types.
+
+  Scenario: Add new pet type
+    Given a system operator named "Jane" is looking at the pet types page
+    And she found the following pet types exist:
+      | cat     |
+      | dog     |
+      | lizard  |
+      | snake   |
+      | bird    |
+      | hamster |
+    When she adds a new pet type named "turtle"
+    Then she should see the pet type "turtle" on the list of pet types
+
+  # TODO: Add a scenario to "Edit the last pet type"
\ No newline at end of file
diff --git a/src/test/resources/features/veterinarian/manage_specialties.feature b/src/test/resources/features/veterinarian/manage_specialties.feature
new file mode 100644
index 0000000000000000000000000000000000000000..a5692d412025689114309bc0b705607e1909d21e
--- /dev/null
+++ b/src/test/resources/features/veterinarian/manage_specialties.feature
@@ -0,0 +1,14 @@
+Feature: Manage specialties
+  The veterinarian wants to be able to add, edit, and delete specialties.
+
+  Scenario: Add new specialty
+    Given a system operator named "John" is looking at the specialties page
+    When he adds a new specialty called "cardiology"
+    Then he should see the specialty "cardiology" on the list of specialties
+
+  Scenario: Edit the first specialty
+    Given a system operator named "John" is looking at the specialties page
+    When he edits the first specialty to "snake oil"
+    Then he should see the specialty "snake oil" on the list of specialties
+
+  # TODO: Add a scenario to "Add new specialty and remove it immediately"
\ No newline at end of file
diff --git a/src/test/resources/junit-platform.properties b/src/test/resources/junit-platform.properties
index c36f2bb1ffd064820140c8540a9966ff96ac9f62..3105dc4b5e70c8ce5c3b9d0f46dc9f9c8311ae95 100644
--- a/src/test/resources/junit-platform.properties
+++ b/src/test/resources/junit-platform.properties
@@ -1,4 +1,4 @@
-cucumber.execution.parallel.enabled=true
+cucumber.execution.parallel.enabled=false
 cucumber.execution.parallel.config.strategy=fixed
 cucumber.execution.parallel.config.fixed.parallelism=4
 cucumber.execution.parallel.config.fixed.max-pool-size=4