diff --git a/README.md b/README.md
index 158bf31..ccf5937 100644
--- a/README.md
+++ b/README.md
@@ -5,13 +5,13 @@ device and provides it to other elimu.ai apps.
 
 ![](https://user-images.githubusercontent.com/15718174/76617075-6c82d200-6560-11ea-867d-e46385017e03.png)
 
-See software architecture diagram at https://github.com/elimu-ai/model/blob/master/README.md
+See software architecture diagram at https://github.com/elimu-ai/model/blob/main/README.md
 
 ## Software Architecture
 
 [
   <img width="320" alt="Software Architecture" src="https://user-images.githubusercontent.com/15718174/83595568-fb6a1e00-a594-11ea-990a-10c0bd62ed11.png">
-](https://github.com/elimu-ai/wiki/blob/master/SOFTWARE_ARCHITECTURE.md)
+](https://github.com/elimu-ai/wiki/blob/main/SOFTWARE_ARCHITECTURE.md)
 
 ## Utils Library 📦
 
@@ -89,6 +89,38 @@ After that, connect your Android device to the same Wi-Fi network as your comput
 ./gradlew wrapper --gradle-version x.x.x --distribution-type all
 ```
 
+### Database Migration 🔀
+
+When adding a new database `@Entity` (or modifying an existing one), you need to prepare a database
+migration (SQL script) in
+[`app/src/main/java/ai/elimu/content_provider/room/db/RoomDb.java`](app/src/main/java/ai/elimu/content_provider/room/db/RoomDb.java).
+
+Follow these steps:
+
+1. Add the new/modified `@Entity` to [`app/src/main/java/ai/elimu/content_provider/room/entity/`](app/src/main/java/ai/elimu/content_provider/room/entity/)
+1. Add the entity's DAO interface to [`app/src/main/java/ai/elimu/content_provider/room/dao/`](app/src/main/java/ai/elimu/content_provider/room/dao/)
+1. Include the DAO interface in [`app/src/main/java/ai/elimu/content_provider/room/db/RoomDb.java`](app/src/main/java/ai/elimu/content_provider/room/db/RoomDb.java)
+1. Include the entity in the `entities` section of the `@Database` in [`app/src/main/java/ai/elimu/content_provider/room/db/RoomDb.java`](app/src/main/java/ai/elimu/content_provider/room/db/RoomDb.java)
+1. Bump the `@Database` version in [`app/src/main/java/ai/elimu/content_provider/room/db/RoomDb.java`](app/src/main/java/ai/elimu/content_provider/room/db/RoomDb.java)
+1. Build the code with `./gradlew clean build`
+1. Open the new database schema generated at `app/schemas/ai.elimu.content_provider.room.db.RoomDb/<version>.json`
+- Under `entities`, find the matching `tableName` and copy its SQL script from the `createSql` property.
+1. Open `RoomDb.java` and add a new method for the latest migration
+- Paste the SQL script from the above JSON schema, and replace `${TABLE_NAME}` with the name of the table you created/modified.
+- Include the migration in the `getDatabase` method in `RoomDb.java`.
+1. To run the database migration, launch the application on your device.
+
+**Tip #1:** To verify that your database migration ran successfully, look at the Logcat output and
+ensure that there are no RoomDb errors:
+```
+2023-11-27 11:46:50.662  6124-13233 ai.elimu.c....RoomDb$18 ai.elimu.content_provider.debug      I  migrate (23 --> 24)
+2023-11-27 11:46:50.663  6124-13233 ai.elimu.c....RoomDb$18 ai.elimu.content_provider.debug      I  sql: CREATE TABLE IF NOT EXISTS `LetterSound` (`revisionNumber` INTEGER NOT NULL, `usageCount` INTEGER, `id` INTEGER, PRIMARY KEY(`id`))
+```
+
+**Tip #2:** You can also use Android Studio's _Database Inspector_ to verify that the database
+migration succeeded:
+
+![](https://github.com/elimu-ai/content-provider/assets/1451036/4c462813-bac0-4d4c-9f62-8c4aa12252d9)
 
 ## Release 📦
 
diff --git a/app/schemas/ai.elimu.content_provider.room.db.RoomDb/24.json b/app/schemas/ai.elimu.content_provider.room.db.RoomDb/24.json
new file mode 100644
index 0000000..42b5964
--- /dev/null
+++ b/app/schemas/ai.elimu.content_provider.room.db.RoomDb/24.json
@@ -0,0 +1,629 @@
+{
+  "formatVersion": 1,
+  "database": {
+    "version": 24,
+    "identityHash": "272858d2cd99837310e007914ec3306b",
+    "entities": [
+      {
+        "tableName": "Letter",
+        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`text` TEXT, `diacritic` INTEGER, `revisionNumber` INTEGER NOT NULL, `usageCount` INTEGER, `id` INTEGER, PRIMARY KEY(`id`))",
+        "fields": [
+          {
+            "fieldPath": "text",
+            "columnName": "text",
+            "affinity": "TEXT",
+            "notNull": false
+          },
+          {
+            "fieldPath": "diacritic",
+            "columnName": "diacritic",
+            "affinity": "INTEGER",
+            "notNull": false
+          },
+          {
+            "fieldPath": "revisionNumber",
+            "columnName": "revisionNumber",
+            "affinity": "INTEGER",
+            "notNull": true
+          },
+          {
+            "fieldPath": "usageCount",
+            "columnName": "usageCount",
+            "affinity": "INTEGER",
+            "notNull": false
+          },
+          {
+            "fieldPath": "id",
+            "columnName": "id",
+            "affinity": "INTEGER",
+            "notNull": false
+          }
+        ],
+        "primaryKey": {
+          "columnNames": [
+            "id"
+          ],
+          "autoGenerate": false
+        },
+        "indices": [],
+        "foreignKeys": []
+      },
+      {
+        "tableName": "Sound",
+        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`valueIpa` TEXT, `diacritic` INTEGER, `revisionNumber` INTEGER NOT NULL, `usageCount` INTEGER, `id` INTEGER, PRIMARY KEY(`id`))",
+        "fields": [
+          {
+            "fieldPath": "valueIpa",
+            "columnName": "valueIpa",
+            "affinity": "TEXT",
+            "notNull": false
+          },
+          {
+            "fieldPath": "diacritic",
+            "columnName": "diacritic",
+            "affinity": "INTEGER",
+            "notNull": false
+          },
+          {
+            "fieldPath": "revisionNumber",
+            "columnName": "revisionNumber",
+            "affinity": "INTEGER",
+            "notNull": true
+          },
+          {
+            "fieldPath": "usageCount",
+            "columnName": "usageCount",
+            "affinity": "INTEGER",
+            "notNull": false
+          },
+          {
+            "fieldPath": "id",
+            "columnName": "id",
+            "affinity": "INTEGER",
+            "notNull": false
+          }
+        ],
+        "primaryKey": {
+          "columnNames": [
+            "id"
+          ],
+          "autoGenerate": false
+        },
+        "indices": [],
+        "foreignKeys": []
+      },
+      {
+        "tableName": "LetterSound",
+        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`revisionNumber` INTEGER NOT NULL, `usageCount` INTEGER, `id` INTEGER, PRIMARY KEY(`id`))",
+        "fields": [
+          {
+            "fieldPath": "revisionNumber",
+            "columnName": "revisionNumber",
+            "affinity": "INTEGER",
+            "notNull": true
+          },
+          {
+            "fieldPath": "usageCount",
+            "columnName": "usageCount",
+            "affinity": "INTEGER",
+            "notNull": false
+          },
+          {
+            "fieldPath": "id",
+            "columnName": "id",
+            "affinity": "INTEGER",
+            "notNull": false
+          }
+        ],
+        "primaryKey": {
+          "columnNames": [
+            "id"
+          ],
+          "autoGenerate": false
+        },
+        "indices": [],
+        "foreignKeys": []
+      },
+      {
+        "tableName": "Word",
+        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`text` TEXT NOT NULL, `wordType` TEXT, `revisionNumber` INTEGER NOT NULL, `usageCount` INTEGER, `id` INTEGER, PRIMARY KEY(`id`))",
+        "fields": [
+          {
+            "fieldPath": "text",
+            "columnName": "text",
+            "affinity": "TEXT",
+            "notNull": true
+          },
+          {
+            "fieldPath": "wordType",
+            "columnName": "wordType",
+            "affinity": "TEXT",
+            "notNull": false
+          },
+          {
+            "fieldPath": "revisionNumber",
+            "columnName": "revisionNumber",
+            "affinity": "INTEGER",
+            "notNull": true
+          },
+          {
+            "fieldPath": "usageCount",
+            "columnName": "usageCount",
+            "affinity": "INTEGER",
+            "notNull": false
+          },
+          {
+            "fieldPath": "id",
+            "columnName": "id",
+            "affinity": "INTEGER",
+            "notNull": false
+          }
+        ],
+        "primaryKey": {
+          "columnNames": [
+            "id"
+          ],
+          "autoGenerate": false
+        },
+        "indices": [],
+        "foreignKeys": []
+      },
+      {
+        "tableName": "Number",
+        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`value` INTEGER NOT NULL, `symbol` TEXT, `revisionNumber` INTEGER NOT NULL, `usageCount` INTEGER, `id` INTEGER, PRIMARY KEY(`id`))",
+        "fields": [
+          {
+            "fieldPath": "value",
+            "columnName": "value",
+            "affinity": "INTEGER",
+            "notNull": true
+          },
+          {
+            "fieldPath": "symbol",
+            "columnName": "symbol",
+            "affinity": "TEXT",
+            "notNull": false
+          },
+          {
+            "fieldPath": "revisionNumber",
+            "columnName": "revisionNumber",
+            "affinity": "INTEGER",
+            "notNull": true
+          },
+          {
+            "fieldPath": "usageCount",
+            "columnName": "usageCount",
+            "affinity": "INTEGER",
+            "notNull": false
+          },
+          {
+            "fieldPath": "id",
+            "columnName": "id",
+            "affinity": "INTEGER",
+            "notNull": false
+          }
+        ],
+        "primaryKey": {
+          "columnNames": [
+            "id"
+          ],
+          "autoGenerate": false
+        },
+        "indices": [],
+        "foreignKeys": []
+      },
+      {
+        "tableName": "Emoji",
+        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`glyph` TEXT NOT NULL, `unicodeVersion` REAL NOT NULL, `unicodeEmojiVersion` REAL NOT NULL, `revisionNumber` INTEGER NOT NULL, `usageCount` INTEGER, `id` INTEGER, PRIMARY KEY(`id`))",
+        "fields": [
+          {
+            "fieldPath": "glyph",
+            "columnName": "glyph",
+            "affinity": "TEXT",
+            "notNull": true
+          },
+          {
+            "fieldPath": "unicodeVersion",
+            "columnName": "unicodeVersion",
+            "affinity": "REAL",
+            "notNull": true
+          },
+          {
+            "fieldPath": "unicodeEmojiVersion",
+            "columnName": "unicodeEmojiVersion",
+            "affinity": "REAL",
+            "notNull": true
+          },
+          {
+            "fieldPath": "revisionNumber",
+            "columnName": "revisionNumber",
+            "affinity": "INTEGER",
+            "notNull": true
+          },
+          {
+            "fieldPath": "usageCount",
+            "columnName": "usageCount",
+            "affinity": "INTEGER",
+            "notNull": false
+          },
+          {
+            "fieldPath": "id",
+            "columnName": "id",
+            "affinity": "INTEGER",
+            "notNull": false
+          }
+        ],
+        "primaryKey": {
+          "columnNames": [
+            "id"
+          ],
+          "autoGenerate": false
+        },
+        "indices": [],
+        "foreignKeys": []
+      },
+      {
+        "tableName": "Emoji_Word",
+        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`Emoji_id` INTEGER NOT NULL, `words_id` INTEGER NOT NULL, PRIMARY KEY(`Emoji_id`, `words_id`))",
+        "fields": [
+          {
+            "fieldPath": "Emoji_id",
+            "columnName": "Emoji_id",
+            "affinity": "INTEGER",
+            "notNull": true
+          },
+          {
+            "fieldPath": "words_id",
+            "columnName": "words_id",
+            "affinity": "INTEGER",
+            "notNull": true
+          }
+        ],
+        "primaryKey": {
+          "columnNames": [
+            "Emoji_id",
+            "words_id"
+          ],
+          "autoGenerate": false
+        },
+        "indices": [],
+        "foreignKeys": []
+      },
+      {
+        "tableName": "Image",
+        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`title` TEXT NOT NULL, `imageFormat` TEXT NOT NULL, `revisionNumber` INTEGER NOT NULL, `usageCount` INTEGER, `id` INTEGER, PRIMARY KEY(`id`))",
+        "fields": [
+          {
+            "fieldPath": "title",
+            "columnName": "title",
+            "affinity": "TEXT",
+            "notNull": true
+          },
+          {
+            "fieldPath": "imageFormat",
+            "columnName": "imageFormat",
+            "affinity": "TEXT",
+            "notNull": true
+          },
+          {
+            "fieldPath": "revisionNumber",
+            "columnName": "revisionNumber",
+            "affinity": "INTEGER",
+            "notNull": true
+          },
+          {
+            "fieldPath": "usageCount",
+            "columnName": "usageCount",
+            "affinity": "INTEGER",
+            "notNull": false
+          },
+          {
+            "fieldPath": "id",
+            "columnName": "id",
+            "affinity": "INTEGER",
+            "notNull": false
+          }
+        ],
+        "primaryKey": {
+          "columnNames": [
+            "id"
+          ],
+          "autoGenerate": false
+        },
+        "indices": [],
+        "foreignKeys": []
+      },
+      {
+        "tableName": "Image_Word",
+        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`Image_id` INTEGER NOT NULL, `words_id` INTEGER NOT NULL, PRIMARY KEY(`Image_id`, `words_id`))",
+        "fields": [
+          {
+            "fieldPath": "Image_id",
+            "columnName": "Image_id",
+            "affinity": "INTEGER",
+            "notNull": true
+          },
+          {
+            "fieldPath": "words_id",
+            "columnName": "words_id",
+            "affinity": "INTEGER",
+            "notNull": true
+          }
+        ],
+        "primaryKey": {
+          "columnNames": [
+            "Image_id",
+            "words_id"
+          ],
+          "autoGenerate": false
+        },
+        "indices": [],
+        "foreignKeys": []
+      },
+      {
+        "tableName": "Audio",
+        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`title` TEXT NOT NULL, `transcription` TEXT NOT NULL, `audioFormat` TEXT NOT NULL, `revisionNumber` INTEGER NOT NULL, `usageCount` INTEGER, `id` INTEGER, PRIMARY KEY(`id`))",
+        "fields": [
+          {
+            "fieldPath": "title",
+            "columnName": "title",
+            "affinity": "TEXT",
+            "notNull": true
+          },
+          {
+            "fieldPath": "transcription",
+            "columnName": "transcription",
+            "affinity": "TEXT",
+            "notNull": true
+          },
+          {
+            "fieldPath": "audioFormat",
+            "columnName": "audioFormat",
+            "affinity": "TEXT",
+            "notNull": true
+          },
+          {
+            "fieldPath": "revisionNumber",
+            "columnName": "revisionNumber",
+            "affinity": "INTEGER",
+            "notNull": true
+          },
+          {
+            "fieldPath": "usageCount",
+            "columnName": "usageCount",
+            "affinity": "INTEGER",
+            "notNull": false
+          },
+          {
+            "fieldPath": "id",
+            "columnName": "id",
+            "affinity": "INTEGER",
+            "notNull": false
+          }
+        ],
+        "primaryKey": {
+          "columnNames": [
+            "id"
+          ],
+          "autoGenerate": false
+        },
+        "indices": [],
+        "foreignKeys": []
+      },
+      {
+        "tableName": "StoryBook",
+        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`title` TEXT NOT NULL, `description` TEXT, `coverImageId` INTEGER NOT NULL, `readingLevel` TEXT, `revisionNumber` INTEGER NOT NULL, `usageCount` INTEGER, `id` INTEGER, PRIMARY KEY(`id`))",
+        "fields": [
+          {
+            "fieldPath": "title",
+            "columnName": "title",
+            "affinity": "TEXT",
+            "notNull": true
+          },
+          {
+            "fieldPath": "description",
+            "columnName": "description",
+            "affinity": "TEXT",
+            "notNull": false
+          },
+          {
+            "fieldPath": "coverImageId",
+            "columnName": "coverImageId",
+            "affinity": "INTEGER",
+            "notNull": true
+          },
+          {
+            "fieldPath": "readingLevel",
+            "columnName": "readingLevel",
+            "affinity": "TEXT",
+            "notNull": false
+          },
+          {
+            "fieldPath": "revisionNumber",
+            "columnName": "revisionNumber",
+            "affinity": "INTEGER",
+            "notNull": true
+          },
+          {
+            "fieldPath": "usageCount",
+            "columnName": "usageCount",
+            "affinity": "INTEGER",
+            "notNull": false
+          },
+          {
+            "fieldPath": "id",
+            "columnName": "id",
+            "affinity": "INTEGER",
+            "notNull": false
+          }
+        ],
+        "primaryKey": {
+          "columnNames": [
+            "id"
+          ],
+          "autoGenerate": false
+        },
+        "indices": [],
+        "foreignKeys": []
+      },
+      {
+        "tableName": "StoryBookChapter",
+        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`storyBookId` INTEGER NOT NULL, `sortOrder` INTEGER NOT NULL, `imageId` INTEGER NOT NULL, `id` INTEGER, PRIMARY KEY(`id`))",
+        "fields": [
+          {
+            "fieldPath": "storyBookId",
+            "columnName": "storyBookId",
+            "affinity": "INTEGER",
+            "notNull": true
+          },
+          {
+            "fieldPath": "sortOrder",
+            "columnName": "sortOrder",
+            "affinity": "INTEGER",
+            "notNull": true
+          },
+          {
+            "fieldPath": "imageId",
+            "columnName": "imageId",
+            "affinity": "INTEGER",
+            "notNull": true
+          },
+          {
+            "fieldPath": "id",
+            "columnName": "id",
+            "affinity": "INTEGER",
+            "notNull": false
+          }
+        ],
+        "primaryKey": {
+          "columnNames": [
+            "id"
+          ],
+          "autoGenerate": false
+        },
+        "indices": [],
+        "foreignKeys": []
+      },
+      {
+        "tableName": "StoryBookParagraph",
+        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`storyBookChapterId` INTEGER NOT NULL, `sortOrder` INTEGER NOT NULL, `originalText` TEXT NOT NULL, `id` INTEGER, PRIMARY KEY(`id`))",
+        "fields": [
+          {
+            "fieldPath": "storyBookChapterId",
+            "columnName": "storyBookChapterId",
+            "affinity": "INTEGER",
+            "notNull": true
+          },
+          {
+            "fieldPath": "sortOrder",
+            "columnName": "sortOrder",
+            "affinity": "INTEGER",
+            "notNull": true
+          },
+          {
+            "fieldPath": "originalText",
+            "columnName": "originalText",
+            "affinity": "TEXT",
+            "notNull": true
+          },
+          {
+            "fieldPath": "id",
+            "columnName": "id",
+            "affinity": "INTEGER",
+            "notNull": false
+          }
+        ],
+        "primaryKey": {
+          "columnNames": [
+            "id"
+          ],
+          "autoGenerate": false
+        },
+        "indices": [],
+        "foreignKeys": []
+      },
+      {
+        "tableName": "StoryBookParagraph_Word",
+        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`StoryBookParagraph_id` INTEGER NOT NULL, `words_id` INTEGER NOT NULL, `words_ORDER` INTEGER NOT NULL, PRIMARY KEY(`StoryBookParagraph_id`, `words_ORDER`))",
+        "fields": [
+          {
+            "fieldPath": "StoryBookParagraph_id",
+            "columnName": "StoryBookParagraph_id",
+            "affinity": "INTEGER",
+            "notNull": true
+          },
+          {
+            "fieldPath": "words_id",
+            "columnName": "words_id",
+            "affinity": "INTEGER",
+            "notNull": true
+          },
+          {
+            "fieldPath": "words_ORDER",
+            "columnName": "words_ORDER",
+            "affinity": "INTEGER",
+            "notNull": true
+          }
+        ],
+        "primaryKey": {
+          "columnNames": [
+            "StoryBookParagraph_id",
+            "words_ORDER"
+          ],
+          "autoGenerate": false
+        },
+        "indices": [],
+        "foreignKeys": []
+      },
+      {
+        "tableName": "Video",
+        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`title` TEXT NOT NULL, `videoFormat` TEXT NOT NULL, `revisionNumber` INTEGER NOT NULL, `usageCount` INTEGER, `id` INTEGER, PRIMARY KEY(`id`))",
+        "fields": [
+          {
+            "fieldPath": "title",
+            "columnName": "title",
+            "affinity": "TEXT",
+            "notNull": true
+          },
+          {
+            "fieldPath": "videoFormat",
+            "columnName": "videoFormat",
+            "affinity": "TEXT",
+            "notNull": true
+          },
+          {
+            "fieldPath": "revisionNumber",
+            "columnName": "revisionNumber",
+            "affinity": "INTEGER",
+            "notNull": true
+          },
+          {
+            "fieldPath": "usageCount",
+            "columnName": "usageCount",
+            "affinity": "INTEGER",
+            "notNull": false
+          },
+          {
+            "fieldPath": "id",
+            "columnName": "id",
+            "affinity": "INTEGER",
+            "notNull": false
+          }
+        ],
+        "primaryKey": {
+          "columnNames": [
+            "id"
+          ],
+          "autoGenerate": false
+        },
+        "indices": [],
+        "foreignKeys": []
+      }
+    ],
+    "views": [],
+    "setupQueries": [
+      "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
+      "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '272858d2cd99837310e007914ec3306b')"
+    ]
+  }
+}
\ No newline at end of file
diff --git a/app/src/main/java/ai/elimu/content_provider/MainActivity.java b/app/src/main/java/ai/elimu/content_provider/MainActivity.java
index c03b7d2..dc94065 100644
--- a/app/src/main/java/ai/elimu/content_provider/MainActivity.java
+++ b/app/src/main/java/ai/elimu/content_provider/MainActivity.java
@@ -53,6 +53,7 @@ protected void onCreate(Bundle savedInstanceState) {
                             R.id.nav_home,
                             R.id.nav_letters,
                             R.id.nav_sounds,
+                            R.id.nav_letter_sounds,
                             R.id.nav_words,
                             R.id.nav_numbers,
                             R.id.nav_emojis,
diff --git a/app/src/main/java/ai/elimu/content_provider/provider/LetterContentProvider.java b/app/src/main/java/ai/elimu/content_provider/provider/LetterContentProvider.java
index d2c8130..4f1ccf2 100644
--- a/app/src/main/java/ai/elimu/content_provider/provider/LetterContentProvider.java
+++ b/app/src/main/java/ai/elimu/content_provider/provider/LetterContentProvider.java
@@ -14,6 +14,7 @@
 import ai.elimu.content_provider.room.dao.LetterDao;
 import ai.elimu.content_provider.room.db.RoomDb;
 
+@Deprecated
 public class LetterContentProvider extends ContentProvider {
 
     private static final String AUTHORITY = BuildConfig.APPLICATION_ID + ".provider.letter_provider";
diff --git a/app/src/main/java/ai/elimu/content_provider/rest/LetterSoundsService.java b/app/src/main/java/ai/elimu/content_provider/rest/LetterSoundsService.java
new file mode 100644
index 0000000..0dfd3f7
--- /dev/null
+++ b/app/src/main/java/ai/elimu/content_provider/rest/LetterSoundsService.java
@@ -0,0 +1,13 @@
+package ai.elimu.content_provider.rest;
+
+import java.util.List;
+
+import ai.elimu.model.v2.gson.content.LetterSoundGson;
+import retrofit2.Call;
+import retrofit2.http.GET;
+
+public interface LetterSoundsService {
+
+    @GET("content/letter-sounds")
+    Call<List<LetterSoundGson>> listLetterSounds();
+}
diff --git a/app/src/main/java/ai/elimu/content_provider/room/GsonToRoomConverter.java b/app/src/main/java/ai/elimu/content_provider/room/GsonToRoomConverter.java
index 99bf374..2bf8edf 100644
--- a/app/src/main/java/ai/elimu/content_provider/room/GsonToRoomConverter.java
+++ b/app/src/main/java/ai/elimu/content_provider/room/GsonToRoomConverter.java
@@ -1,5 +1,6 @@
 package ai.elimu.content_provider.room;
 
+import ai.elimu.content_provider.room.entity.LetterSound;
 import ai.elimu.content_provider.room.entity.Sound;
 import ai.elimu.content_provider.room.entity.Audio;
 import ai.elimu.content_provider.room.entity.Emoji;
@@ -11,6 +12,7 @@
 import ai.elimu.content_provider.room.entity.StoryBookParagraph;
 import ai.elimu.content_provider.room.entity.Video;
 import ai.elimu.content_provider.room.entity.Word;
+import ai.elimu.model.v2.gson.content.LetterSoundGson;
 import ai.elimu.model.v2.gson.content.SoundGson;
 import ai.elimu.model.v2.gson.content.AudioGson;
 import ai.elimu.model.v2.gson.content.EmojiGson;
@@ -67,6 +69,27 @@ public static Sound getSound(SoundGson soundGson) {
         }
     }
 
+    public static LetterSound getLetterSound(LetterSoundGson letterSoundGson) {
+        if (letterSoundGson == null) {
+            return null;
+        } else {
+            LetterSound letterSound = new LetterSound();
+
+            // BaseEntity
+            letterSound.setId(letterSoundGson.getId());
+
+            // Content
+            letterSound.setRevisionNumber(letterSoundGson.getRevisionNumber());
+            letterSound.setUsageCount(letterSoundGson.getUsageCount());
+
+            // LetterSound
+            // TODO: letters
+            // TODO: sounds
+
+            return letterSound;
+        }
+    }
+
     public static Word getWord(WordGson wordGson) {
         if (wordGson == null) {
             return null;
diff --git a/app/src/main/java/ai/elimu/content_provider/room/dao/LetterSoundDao.java b/app/src/main/java/ai/elimu/content_provider/room/dao/LetterSoundDao.java
new file mode 100644
index 0000000..b37c1d0
--- /dev/null
+++ b/app/src/main/java/ai/elimu/content_provider/room/dao/LetterSoundDao.java
@@ -0,0 +1,22 @@
+package ai.elimu.content_provider.room.dao;
+
+import androidx.room.Dao;
+import androidx.room.Insert;
+import androidx.room.Query;
+
+import java.util.List;
+
+import ai.elimu.content_provider.room.entity.LetterSound;
+
+@Dao
+public interface LetterSoundDao {
+
+    @Insert
+    void insert(LetterSound letterSound);
+
+    @Query("SELECT * FROM LetterSound")
+    List<LetterSound> loadAll();
+
+    @Query("DELETE FROM LetterSound")
+    void deleteAll();
+}
diff --git a/app/src/main/java/ai/elimu/content_provider/room/db/RoomDb.java b/app/src/main/java/ai/elimu/content_provider/room/db/RoomDb.java
index 1ae30bc..7562f12 100644
--- a/app/src/main/java/ai/elimu/content_provider/room/db/RoomDb.java
+++ b/app/src/main/java/ai/elimu/content_provider/room/db/RoomDb.java
@@ -13,6 +13,7 @@
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 
+import ai.elimu.content_provider.room.dao.LetterSoundDao;
 import ai.elimu.content_provider.room.dao.SoundDao;
 import ai.elimu.content_provider.room.dao.AudioDao;
 import ai.elimu.content_provider.room.dao.EmojiDao;
@@ -27,6 +28,7 @@
 import ai.elimu.content_provider.room.dao.StoryBookParagraph_WordDao;
 import ai.elimu.content_provider.room.dao.VideoDao;
 import ai.elimu.content_provider.room.dao.WordDao;
+import ai.elimu.content_provider.room.entity.LetterSound;
 import ai.elimu.content_provider.room.entity.Sound;
 import ai.elimu.content_provider.room.entity.Audio;
 import ai.elimu.content_provider.room.entity.Emoji;
@@ -42,7 +44,7 @@
 import ai.elimu.content_provider.room.entity.Video;
 import ai.elimu.content_provider.room.entity.Word;
 
-@Database(version = 23, entities = {Letter.class, Sound.class, Word.class, Number.class, Emoji.class, Emoji_Word.class, Image.class, Image_Word.class, Audio.class, StoryBook.class, StoryBookChapter.class, StoryBookParagraph.class, StoryBookParagraph_Word.class, Video.class})
+@Database(version = 24, entities = {Letter.class, Sound.class, LetterSound.class, Word.class, Number.class, Emoji.class, Emoji_Word.class, Image.class, Image_Word.class, Audio.class, StoryBook.class, StoryBookChapter.class, StoryBookParagraph.class, StoryBookParagraph_Word.class, Video.class})
 @TypeConverters({Converters.class})
 public abstract class RoomDb extends RoomDatabase {
 
@@ -50,6 +52,8 @@ public abstract class RoomDb extends RoomDatabase {
 
     public abstract SoundDao soundDao();
 
+    public abstract LetterSoundDao letterSoundDao();
+
     public abstract WordDao wordDao();
 
     public abstract NumberDao numberDao();
@@ -105,7 +109,8 @@ public static RoomDb getDatabase(final Context context) {
                                     MIGRATION_19_20,
                                     MIGRATION_20_21,
                                     MIGRATION_21_22,
-                                    MIGRATION_22_23
+                                    MIGRATION_22_23,
+                                    MIGRATION_23_24
                             )
                             .build();
                 }
@@ -314,4 +319,15 @@ public void migrate(SupportSQLiteDatabase database) {
             database.execSQL(sql);
         }
     };
+
+    private static final Migration MIGRATION_23_24 = new Migration(23, 24) {
+        @Override
+        public void migrate(SupportSQLiteDatabase database) {
+            Log.i(getClass().getName(), "migrate (23 --> 24)");
+
+            String sql = "CREATE TABLE IF NOT EXISTS `LetterSound` (`revisionNumber` INTEGER NOT NULL, `usageCount` INTEGER, `id` INTEGER, PRIMARY KEY(`id`))";
+            Log.i(getClass().getName(), "sql: " + sql);
+            database.execSQL(sql);
+        }
+    };
 }
diff --git a/app/src/main/java/ai/elimu/content_provider/room/entity/Audio.java b/app/src/main/java/ai/elimu/content_provider/room/entity/Audio.java
index 9a85769..b914172 100644
--- a/app/src/main/java/ai/elimu/content_provider/room/entity/Audio.java
+++ b/app/src/main/java/ai/elimu/content_provider/room/entity/Audio.java
@@ -6,7 +6,7 @@
 import ai.elimu.model.v2.enums.content.AudioFormat;
 
 /**
- * For documentation, see https://github.com/elimu-ai/webapp/tree/master/src/main/java/ai/elimu/model
+ * For documentation, see https://github.com/elimu-ai/webapp/tree/main/src/main/java/ai/elimu/model
  */
 @Entity
 public class Audio extends Content {
diff --git a/app/src/main/java/ai/elimu/content_provider/room/entity/BaseEntity.java b/app/src/main/java/ai/elimu/content_provider/room/entity/BaseEntity.java
index 1e3f364..7d4e97e 100644
--- a/app/src/main/java/ai/elimu/content_provider/room/entity/BaseEntity.java
+++ b/app/src/main/java/ai/elimu/content_provider/room/entity/BaseEntity.java
@@ -3,7 +3,7 @@
 import androidx.room.PrimaryKey;
 
 /**
- * For documentation, see https://github.com/elimu-ai/webapp/tree/master/src/main/java/ai/elimu/model
+ * For documentation, see https://github.com/elimu-ai/webapp/tree/main/src/main/java/ai/elimu/model
  */
 public class BaseEntity {
 
diff --git a/app/src/main/java/ai/elimu/content_provider/room/entity/Content.java b/app/src/main/java/ai/elimu/content_provider/room/entity/Content.java
index cbe4993..c282a1d 100644
--- a/app/src/main/java/ai/elimu/content_provider/room/entity/Content.java
+++ b/app/src/main/java/ai/elimu/content_provider/room/entity/Content.java
@@ -3,7 +3,7 @@
 import androidx.annotation.NonNull;
 
 /**
- * For documentation, see https://github.com/elimu-ai/webapp/tree/master/src/main/java/ai/elimu/model
+ * For documentation, see https://github.com/elimu-ai/webapp/tree/main/src/main/java/ai/elimu/model
  */
 public class Content extends BaseEntity {
 
diff --git a/app/src/main/java/ai/elimu/content_provider/room/entity/Emoji.java b/app/src/main/java/ai/elimu/content_provider/room/entity/Emoji.java
index 94facd2..df44c79 100644
--- a/app/src/main/java/ai/elimu/content_provider/room/entity/Emoji.java
+++ b/app/src/main/java/ai/elimu/content_provider/room/entity/Emoji.java
@@ -4,7 +4,7 @@
 import androidx.room.Entity;
 
 /**
- * For documentation, see https://github.com/elimu-ai/webapp/tree/master/src/main/java/ai/elimu/model
+ * For documentation, see https://github.com/elimu-ai/webapp/tree/main/src/main/java/ai/elimu/model
  */
 @Entity
 public class Emoji extends Content {
diff --git a/app/src/main/java/ai/elimu/content_provider/room/entity/Emoji_Word.java b/app/src/main/java/ai/elimu/content_provider/room/entity/Emoji_Word.java
index ce9cbb7..9238618 100644
--- a/app/src/main/java/ai/elimu/content_provider/room/entity/Emoji_Word.java
+++ b/app/src/main/java/ai/elimu/content_provider/room/entity/Emoji_Word.java
@@ -4,7 +4,7 @@
 import androidx.room.Entity;
 
 /**
- * For documentation, see https://github.com/elimu-ai/webapp/tree/master/src/main/java/ai/elimu/model
+ * For documentation, see https://github.com/elimu-ai/webapp/tree/main/src/main/java/ai/elimu/model
  */
 @Entity(primaryKeys = {"Emoji_id", "words_id"})
 public class Emoji_Word {
diff --git a/app/src/main/java/ai/elimu/content_provider/room/entity/Image.java b/app/src/main/java/ai/elimu/content_provider/room/entity/Image.java
index 17a84b5..38a3f42 100644
--- a/app/src/main/java/ai/elimu/content_provider/room/entity/Image.java
+++ b/app/src/main/java/ai/elimu/content_provider/room/entity/Image.java
@@ -6,7 +6,7 @@
 import ai.elimu.model.v2.enums.content.ImageFormat;
 
 /**
- * For documentation, see https://github.com/elimu-ai/webapp/tree/master/src/main/java/ai/elimu/model
+ * For documentation, see https://github.com/elimu-ai/webapp/tree/main/src/main/java/ai/elimu/model
  */
 @Entity
 public class Image extends Content {
diff --git a/app/src/main/java/ai/elimu/content_provider/room/entity/Image_Word.java b/app/src/main/java/ai/elimu/content_provider/room/entity/Image_Word.java
index 0025caf..40728e3 100644
--- a/app/src/main/java/ai/elimu/content_provider/room/entity/Image_Word.java
+++ b/app/src/main/java/ai/elimu/content_provider/room/entity/Image_Word.java
@@ -4,7 +4,7 @@
 import androidx.room.Entity;
 
 /**
- * For documentation, see https://github.com/elimu-ai/webapp/tree/master/src/main/java/ai/elimu/model
+ * For documentation, see https://github.com/elimu-ai/webapp/tree/main/src/main/java/ai/elimu/model
  */
 @Entity(primaryKeys = {"Image_id", "words_id"})
 public class Image_Word {
diff --git a/app/src/main/java/ai/elimu/content_provider/room/entity/Letter.java b/app/src/main/java/ai/elimu/content_provider/room/entity/Letter.java
index 7cb168b..3c507d1 100644
--- a/app/src/main/java/ai/elimu/content_provider/room/entity/Letter.java
+++ b/app/src/main/java/ai/elimu/content_provider/room/entity/Letter.java
@@ -3,7 +3,7 @@
 import androidx.room.Entity;
 
 /**
- * For documentation, see https://github.com/elimu-ai/webapp/tree/master/src/main/java/ai/elimu/model
+ * For documentation, see https://github.com/elimu-ai/webapp/tree/main/src/main/java/ai/elimu/model
  */
 @Entity
 public class Letter extends Content {
diff --git a/app/src/main/java/ai/elimu/content_provider/room/entity/LetterSound.java b/app/src/main/java/ai/elimu/content_provider/room/entity/LetterSound.java
new file mode 100644
index 0000000..9d292a2
--- /dev/null
+++ b/app/src/main/java/ai/elimu/content_provider/room/entity/LetterSound.java
@@ -0,0 +1,12 @@
+package ai.elimu.content_provider.room.entity;
+
+import androidx.room.Entity;
+
+/**
+ * For documentation, see https://github.com/elimu-ai/webapp/tree/main/src/main/java/ai/elimu/model
+ */
+@Entity
+public class LetterSound extends Content {
+    
+    
+}
diff --git a/app/src/main/java/ai/elimu/content_provider/room/entity/Number.java b/app/src/main/java/ai/elimu/content_provider/room/entity/Number.java
index cbeec33..f47f6eb 100644
--- a/app/src/main/java/ai/elimu/content_provider/room/entity/Number.java
+++ b/app/src/main/java/ai/elimu/content_provider/room/entity/Number.java
@@ -4,7 +4,7 @@
 import androidx.room.Entity;
 
 /**
- * For documentation, see https://github.com/elimu-ai/webapp/tree/master/src/main/java/ai/elimu/model
+ * For documentation, see https://github.com/elimu-ai/webapp/tree/main/src/main/java/ai/elimu/model
  */
 @Entity
 public class Number extends Content {
diff --git a/app/src/main/java/ai/elimu/content_provider/room/entity/Sound.java b/app/src/main/java/ai/elimu/content_provider/room/entity/Sound.java
index bd5bcd0..1b76836 100644
--- a/app/src/main/java/ai/elimu/content_provider/room/entity/Sound.java
+++ b/app/src/main/java/ai/elimu/content_provider/room/entity/Sound.java
@@ -3,7 +3,7 @@
 import androidx.room.Entity;
 
 /**
- * For documentation, see https://github.com/elimu-ai/webapp/tree/master/src/main/java/ai/elimu/model
+ * For documentation, see https://github.com/elimu-ai/webapp/tree/main/src/main/java/ai/elimu/model
  */
 @Entity
 public class Sound extends Content {
diff --git a/app/src/main/java/ai/elimu/content_provider/room/entity/StoryBook.java b/app/src/main/java/ai/elimu/content_provider/room/entity/StoryBook.java
index 4ef1ba3..8ad9369 100644
--- a/app/src/main/java/ai/elimu/content_provider/room/entity/StoryBook.java
+++ b/app/src/main/java/ai/elimu/content_provider/room/entity/StoryBook.java
@@ -6,7 +6,7 @@
 import ai.elimu.model.v2.enums.ReadingLevel;
 
 /**
- * For documentation, see https://github.com/elimu-ai/webapp/tree/master/src/main/java/ai/elimu/model
+ * For documentation, see https://github.com/elimu-ai/webapp/tree/main/src/main/java/ai/elimu/model
  */
 @Entity
 public class StoryBook extends Content {
diff --git a/app/src/main/java/ai/elimu/content_provider/room/entity/StoryBookChapter.java b/app/src/main/java/ai/elimu/content_provider/room/entity/StoryBookChapter.java
index aa5e460..f5147ad 100644
--- a/app/src/main/java/ai/elimu/content_provider/room/entity/StoryBookChapter.java
+++ b/app/src/main/java/ai/elimu/content_provider/room/entity/StoryBookChapter.java
@@ -4,7 +4,7 @@
 import androidx.room.Entity;
 
 /**
- * For documentation, see https://github.com/elimu-ai/webapp/tree/master/src/main/java/ai/elimu/model
+ * For documentation, see https://github.com/elimu-ai/webapp/tree/main/src/main/java/ai/elimu/model
  */
 @Entity
 public class StoryBookChapter extends BaseEntity {
diff --git a/app/src/main/java/ai/elimu/content_provider/room/entity/StoryBookParagraph.java b/app/src/main/java/ai/elimu/content_provider/room/entity/StoryBookParagraph.java
index c6e4465..ef3a617 100644
--- a/app/src/main/java/ai/elimu/content_provider/room/entity/StoryBookParagraph.java
+++ b/app/src/main/java/ai/elimu/content_provider/room/entity/StoryBookParagraph.java
@@ -4,7 +4,7 @@
 import androidx.room.Entity;
 
 /**
- * For documentation, see https://github.com/elimu-ai/webapp/tree/master/src/main/java/ai/elimu/model
+ * For documentation, see https://github.com/elimu-ai/webapp/tree/main/src/main/java/ai/elimu/model
  */
 @Entity
 public class StoryBookParagraph extends BaseEntity {
diff --git a/app/src/main/java/ai/elimu/content_provider/room/entity/StoryBookParagraph_Word.java b/app/src/main/java/ai/elimu/content_provider/room/entity/StoryBookParagraph_Word.java
index e49c2d5..7cfeb6e 100644
--- a/app/src/main/java/ai/elimu/content_provider/room/entity/StoryBookParagraph_Word.java
+++ b/app/src/main/java/ai/elimu/content_provider/room/entity/StoryBookParagraph_Word.java
@@ -4,7 +4,7 @@
 import androidx.room.Entity;
 
 /**
- * For documentation, see https://github.com/elimu-ai/webapp/tree/master/src/main/java/ai/elimu/model
+ * For documentation, see https://github.com/elimu-ai/webapp/tree/main/src/main/java/ai/elimu/model
  */
 @Entity(primaryKeys = {"StoryBookParagraph_id", "words_ORDER"})
 public class StoryBookParagraph_Word {
diff --git a/app/src/main/java/ai/elimu/content_provider/room/entity/Video.java b/app/src/main/java/ai/elimu/content_provider/room/entity/Video.java
index e2b12ef..3e6ac71 100644
--- a/app/src/main/java/ai/elimu/content_provider/room/entity/Video.java
+++ b/app/src/main/java/ai/elimu/content_provider/room/entity/Video.java
@@ -6,7 +6,7 @@
 import ai.elimu.model.v2.enums.content.VideoFormat;
 
 /**
- * For documentation, see https://github.com/elimu-ai/webapp/tree/master/src/main/java/ai/elimu/model
+ * For documentation, see https://github.com/elimu-ai/webapp/tree/main/src/main/java/ai/elimu/model
  */
 @Entity
 public class Video extends Content {
diff --git a/app/src/main/java/ai/elimu/content_provider/room/entity/Word.java b/app/src/main/java/ai/elimu/content_provider/room/entity/Word.java
index 6978c89..8d2a697 100644
--- a/app/src/main/java/ai/elimu/content_provider/room/entity/Word.java
+++ b/app/src/main/java/ai/elimu/content_provider/room/entity/Word.java
@@ -6,7 +6,7 @@
 import ai.elimu.model.v2.enums.content.WordType;
 
 /**
- * For documentation, see https://github.com/elimu-ai/webapp/tree/master/src/main/java/ai/elimu/model
+ * For documentation, see https://github.com/elimu-ai/webapp/tree/main/src/main/java/ai/elimu/model
  */
 @Entity
 public class Word extends Content {
diff --git a/app/src/main/java/ai/elimu/content_provider/ui/letter_sound/LetterSoundsFragment.java b/app/src/main/java/ai/elimu/content_provider/ui/letter_sound/LetterSoundsFragment.java
new file mode 100644
index 0000000..8412b85
--- /dev/null
+++ b/app/src/main/java/ai/elimu/content_provider/ui/letter_sound/LetterSoundsFragment.java
@@ -0,0 +1,145 @@
+package ai.elimu.content_provider.ui.letter_sound;
+
+import android.os.Bundle;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ProgressBar;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.fragment.app.Fragment;
+import androidx.lifecycle.Observer;
+import androidx.lifecycle.ViewModelProvider;
+
+import com.google.android.material.snackbar.Snackbar;
+
+import java.util.List;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+import ai.elimu.content_provider.BaseApplication;
+import ai.elimu.content_provider.R;
+import ai.elimu.content_provider.rest.LetterSoundsService;
+import ai.elimu.content_provider.room.GsonToRoomConverter;
+import ai.elimu.content_provider.room.dao.LetterSoundDao;
+import ai.elimu.content_provider.room.db.RoomDb;
+import ai.elimu.content_provider.room.entity.LetterSound;
+import ai.elimu.model.v2.gson.content.LetterSoundGson;
+import retrofit2.Call;
+import retrofit2.Callback;
+import retrofit2.Response;
+import retrofit2.Retrofit;
+
+public class LetterSoundsFragment extends Fragment {
+
+    private LetterSoundsViewModel letterSoundsViewModel;
+
+    private ProgressBar progressBar;
+
+    private TextView textView;
+
+    public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+        Log.i(getClass().getName(), "onCreateView");
+
+        letterSoundsViewModel = new ViewModelProvider(this).get(LetterSoundsViewModel.class);
+        View root = inflater.inflate(R.layout.fragment_letter_sounds, container, false);
+        progressBar = root.findViewById(R.id.progress_bar_letter_sounds);
+        textView = root.findViewById(R.id.text_letter_sounds);
+        letterSoundsViewModel.getText().observe(getViewLifecycleOwner(), new Observer<String>() {
+            @Override
+            public void onChanged(@Nullable String s) {
+                Log.i(getClass().getName(), "onChanged");
+                textView.setText(s);
+            }
+        });
+        return root;
+    }
+
+    @Override
+    public void onStart() {
+        Log.i(getClass().getName(), "onStart");
+        super.onStart();
+
+        // Download LetterSounds from REST API, and store them in the database
+        BaseApplication baseApplication = (BaseApplication) getActivity().getApplication();
+        Retrofit retrofit = baseApplication.getRetrofit();
+        LetterSoundsService letterSoundsService = retrofit.create(LetterSoundsService.class);
+        Call<List<LetterSoundGson>> letterSoundGsonsCall = letterSoundsService.listLetterSounds();
+        Log.i(getClass().getName(), "letterSoundGsonsCall.request(): " + letterSoundGsonsCall.request());
+        letterSoundGsonsCall.enqueue(new Callback<List<LetterSoundGson>>() {
+
+            @Override
+            public void onResponse(Call<List<LetterSoundGson>> call, Response<List<LetterSoundGson>> response) {
+                Log.i(getClass().getName(), "onResponse");
+
+                Log.i(getClass().getName(), "response: " + response);
+                if (response.isSuccessful()) {
+                    List<LetterSoundGson> letterSoundGsons = response.body();
+                    Log.i(getClass().getName(), "letterSoundGsons.size(): " + letterSoundGsons.size());
+
+                    if (letterSoundGsons.size() > 0) {
+                        processResponseBody(letterSoundGsons);
+                    }
+                } else {
+                    // Handle error
+                    Snackbar.make(textView, response.toString(), Snackbar.LENGTH_LONG)
+                            .setBackgroundTint(getResources().getColor(R.color.deep_orange_darken_4))
+                            .show();
+                    progressBar.setVisibility(View.GONE);
+                }
+            }
+
+            @Override
+            public void onFailure(Call<List<LetterSoundGson>> call, Throwable t) {
+                Log.e(getClass().getName(), "onFailure", t);
+
+                Log.e(getClass().getName(), "t.getCause():", t.getCause());
+
+                // Handle error
+                Snackbar.make(textView, t.getCause().toString(), Snackbar.LENGTH_LONG)
+                        .setBackgroundTint(getResources().getColor(R.color.deep_orange_darken_4))
+                        .show();
+                progressBar.setVisibility(View.GONE);
+            }
+        });
+    }
+
+    private void processResponseBody(List<LetterSoundGson> letterSoundGsons) {
+        Log.i(getClass().getName(), "processResponseBody");
+
+        ExecutorService executorService = Executors.newSingleThreadExecutor();
+        executorService.execute(new Runnable() {
+            @Override
+            public void run() {
+                Log.i(getClass().getName(), "run");
+
+                RoomDb roomDb = RoomDb.getDatabase(getContext());
+                LetterSoundDao letterSoundDao = roomDb.letterSoundDao();
+
+                // Empty the database table before downloading up-to-date content
+                letterSoundDao.deleteAll();
+
+                for (LetterSoundGson letterSoundGson : letterSoundGsons) {
+                    Log.i(getClass().getName(), "letterSoundGson.getId(): " + letterSoundGson.getId());
+
+                    // Store the LetterSound in the database
+                    LetterSound letterSound = GsonToRoomConverter.getLetterSound(letterSoundGson);
+                    letterSoundDao.insert(letterSound);
+                    Log.i(getClass().getName(), "Stored LetterSound in database with ID " + letterSound.getId());
+                }
+
+                // Update the UI
+                List<LetterSound> letterSounds = letterSoundDao.loadAll();
+                Log.i(getClass().getName(), "letterSounds.size(): " + letterSounds.size());
+                getActivity().runOnUiThread(() -> {
+                    textView.setText("letterSounds.size(): " + letterSounds.size());
+                    Snackbar.make(textView, "letterSounds.size(): " + letterSounds.size(), Snackbar.LENGTH_LONG).show();
+                    progressBar.setVisibility(View.GONE);
+                });
+            }
+        });
+    }
+}
diff --git a/app/src/main/java/ai/elimu/content_provider/ui/letter_sound/LetterSoundsViewModel.java b/app/src/main/java/ai/elimu/content_provider/ui/letter_sound/LetterSoundsViewModel.java
new file mode 100644
index 0000000..40e0f9b
--- /dev/null
+++ b/app/src/main/java/ai/elimu/content_provider/ui/letter_sound/LetterSoundsViewModel.java
@@ -0,0 +1,19 @@
+package ai.elimu.content_provider.ui.letter_sound;
+
+import androidx.lifecycle.LiveData;
+import androidx.lifecycle.MutableLiveData;
+import androidx.lifecycle.ViewModel;
+
+public class LetterSoundsViewModel extends ViewModel {
+
+    private MutableLiveData<String> text;
+
+    public LetterSoundsViewModel() {
+        text = new MutableLiveData<>();
+        text.setValue("LetterSoundsViewModel");
+    }
+
+    public LiveData<String> getText() {
+        return text;
+    }
+}
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_menu_emoji_symbols.xml b/app/src/main/res/drawable/ic_menu_emoji_symbols.xml
new file mode 100644
index 0000000..21bc0b7
--- /dev/null
+++ b/app/src/main/res/drawable/ic_menu_emoji_symbols.xml
@@ -0,0 +1,11 @@
+<vector android:height="24dp" android:tint="#000000"
+    android:viewportHeight="24" android:viewportWidth="24"
+    android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="@android:color/white" android:pathData="M3,2h8v2h-8z"/>
+    <path android:fillColor="@android:color/white" android:pathData="M6,11l2,0l0,-4l3,0l0,-2l-8,0l0,2l3,0z"/>
+    <path android:fillColor="@android:color/white" android:pathData="M12.4036,20.1819l7.7781,-7.7781l1.4142,1.4142l-7.7781,7.7781z"/>
+    <path android:fillColor="@android:color/white" android:pathData="M14.5,14.5m-1.5,0a1.5,1.5 0,1 1,3 0a1.5,1.5 0,1 1,-3 0"/>
+    <path android:fillColor="@android:color/white" android:pathData="M19.5,19.5m-1.5,0a1.5,1.5 0,1 1,3 0a1.5,1.5 0,1 1,-3 0"/>
+    <path android:fillColor="@android:color/white" android:pathData="M15.5,11c1.38,0 2.5,-1.12 2.5,-2.5V4h3V2h-4v4.51C16.58,6.19 16.07,6 15.5,6C14.12,6 13,7.12 13,8.5C13,9.88 14.12,11 15.5,11z"/>
+    <path android:fillColor="@android:color/white" android:pathData="M9.74,15.96l-1.41,1.41l-0.71,-0.71l0.35,-0.35c0.98,-0.98 0.98,-2.56 0,-3.54c-0.49,-0.49 -1.13,-0.73 -1.77,-0.73c-0.64,0 -1.28,0.24 -1.77,0.73c-0.98,0.98 -0.98,2.56 0,3.54l0.35,0.35l-1.06,1.06c-0.98,0.98 -0.98,2.56 0,3.54C4.22,21.76 4.86,22 5.5,22s1.28,-0.24 1.77,-0.73l1.06,-1.06l1.41,1.41l1.41,-1.41l-1.41,-1.41l1.41,-1.41L9.74,15.96zM5.85,14.2c0.12,-0.12 0.26,-0.15 0.35,-0.15s0.23,0.03 0.35,0.15c0.19,0.2 0.19,0.51 0,0.71l-0.35,0.35L5.85,14.9C5.66,14.71 5.66,14.39 5.85,14.2zM5.85,19.85C5.73,19.97 5.59,20 5.5,20s-0.23,-0.03 -0.35,-0.15c-0.19,-0.19 -0.19,-0.51 0,-0.71l1.06,-1.06l0.71,0.71L5.85,19.85z"/>
+</vector>
diff --git a/app/src/main/res/layout/fragment_letter_sounds.xml b/app/src/main/res/layout/fragment_letter_sounds.xml
new file mode 100644
index 0000000..65c9187
--- /dev/null
+++ b/app/src/main/res/layout/fragment_letter_sounds.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:paddingTop="@dimen/activity_vertical_margin"
+    android:paddingRight="@dimen/activity_horizontal_margin"
+    android:paddingBottom="@dimen/activity_vertical_margin"
+    android:paddingLeft="@dimen/activity_horizontal_margin">
+
+    <ProgressBar
+        android:id="@+id/progress_bar_letter_sounds"
+        app:layout_constraintTop_toTopOf="parent"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        android:layout_height="wrap_content"
+        android:layout_width="wrap_content" />
+
+    <TextView
+        android:id="@+id/text_letter_sounds"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:textAlignment="center"
+        android:textSize="20sp"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
+</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/app/src/main/res/menu/activity_main_drawer.xml b/app/src/main/res/menu/activity_main_drawer.xml
index 5ce4299..0a429f4 100644
--- a/app/src/main/res/menu/activity_main_drawer.xml
+++ b/app/src/main/res/menu/activity_main_drawer.xml
@@ -21,6 +21,10 @@
                     android:id="@+id/nav_sounds"
                     android:icon="@drawable/ic_menu_music_note"
                     android:title="@string/menu_sounds" />
+                <item
+                    android:id="@+id/nav_letter_sounds"
+                    android:icon="@drawable/ic_menu_emoji_symbols"
+                    android:title="@string/menu_letter_sounds" />
                 <item
                     android:id="@+id/nav_words"
                     android:icon="@drawable/ic_menu_sms"
diff --git a/app/src/main/res/navigation/mobile_navigation.xml b/app/src/main/res/navigation/mobile_navigation.xml
index 4ac4988..2e50674 100644
--- a/app/src/main/res/navigation/mobile_navigation.xml
+++ b/app/src/main/res/navigation/mobile_navigation.xml
@@ -23,6 +23,12 @@
         android:label="@string/menu_sounds"
         tools:layout="@layout/fragment_sounds" />
 
+    <fragment
+        android:id="@+id/nav_letter_sounds"
+        android:name="ai.elimu.content_provider.ui.letter_sound.LetterSoundsFragment"
+        android:label="@string/menu_letter_sounds"
+        tools:layout="@layout/fragment_letter_sounds" />
+
     <fragment
         android:id="@+id/nav_words"
         android:name="ai.elimu.content_provider.ui.word.WordsFragment"
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 845193c..49fd9cf 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -9,6 +9,7 @@
 
     <string name="menu_home">Home</string>
     <string name="menu_letters">Letters</string>
+    <string name="menu_letter_sounds">Letter-Sounds</string>
     <string name="menu_sounds">Sounds</string>
     <string name="menu_words">Words</string>
     <string name="menu_numbers">Numbers</string>