diff --git a/__mocks__/api.ts b/__mocks__/api.ts
index 7cddfdc..22c9b4c 100644
--- a/__mocks__/api.ts
+++ b/__mocks__/api.ts
@@ -14,6 +14,9 @@ class LanguageServer {
       "es": { code: "es", name: "Spanish", targets: ['fr', 'en'] },
     }
   }
+  static getDefault() {
+    return new LanguageServer("http://localhost:5002");
+  }
 }
 
 class Translator {
@@ -21,6 +24,9 @@ class Translator {
   translate(message : string, target : string) {
     return message;
   }
+  static getDefault(code : string) {
+    return new Translator(code);
+  }
 }
 
 class CachedTranslator extends Translator{
diff --git a/__mocks__/db.ts b/__mocks__/db.ts
new file mode 100644
index 0000000..54d8c12
--- /dev/null
+++ b/__mocks__/db.ts
@@ -0,0 +1,10 @@
+export default {
+  getDb: jest.fn(() => {
+    return {
+      runAsync: jest.fn((statement: string, value: string) => {}),
+      getFirstAsync: jest.fn((statement: string, value: string) => {
+        return [];
+      }),
+    };
+  }),
+};
diff --git a/__mocks__/settings.ts b/__mocks__/settings.ts
new file mode 100644
index 0000000..1720a8f
--- /dev/null
+++ b/__mocks__/settings.ts
@@ -0,0 +1,16 @@
+const originalModule = jest.requireActual("@/app/lib/settings");
+class MockSettings {
+  public constructor(public db = {}) {}
+  public setHostLanguage = jest.fn((val: string) => {});
+  public setLibretranslateBaseUrl(val: string) {}
+  getHostLanguage = jest.fn(() => {
+    return "en";
+  });
+  getLibretranslateBaseUrl = jest.fn(() => {
+    return "http://localhost:5004";
+  });
+}
+export default {
+  ...originalModule,
+  Settings: MockSettings,
+};
diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index 8b00f62..f3fb253 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -1,8 +1,10 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android">
   <uses-permission android:name="android.permission.INTERNET"/>
   <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
+  <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
   <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
   <uses-permission android:name="android.permission.VIBRATE"/>
+  <uses-permission android:name="android.permission.WAKE_LOCK"/>
   <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
   <queries>
     <intent>
diff --git a/app.json b/app.json
index a2740ca..6737023 100644
--- a/app.json
+++ b/app.json
@@ -3,7 +3,7 @@
     "name": "translation-terrace",
     "slug": "translation-terrace",
     "version": "1.0.0",
-    "orientation": "portrait",
+    "orientation": "landscape",
     "icon": "./assets/images/icon.png",
     "scheme": "myapp",
     "userInterfaceStyle": "automatic",
@@ -30,7 +30,7 @@
       [
         "expo-screen-orientation",
         {
-          "initialOrientation": "LANDSCAPE"
+          "orientation": "landscape"
         }
       ],
       [
@@ -48,12 +48,10 @@
           "enableFTS": true,
           "useSQLCipher": true,
           "android": {
-            // Override the shared configuration for Android
             "enableFTS": false,
             "useSQLCipher": false
           },
           "ios": {
-            // You can also override the shared configurations for iOS
             "customBuildFlags": [
               "-DSQLITE_ENABLE_DBSTAT_VTAB=1 -DSQLITE_ENABLE_SNAPSHOT=1"
             ]
diff --git a/app/_layout.tsx b/app/_layout.tsx
index 41f32ad..a148ebb 100644
--- a/app/_layout.tsx
+++ b/app/_layout.tsx
@@ -1,11 +1,21 @@
 import * as React from "react";
-import { NavigationContainer } from "@react-navigation/native";
 import TTNavStack from "@/components/TTNavStack";
+import * as ScreenOrientation from "expo-screen-orientation";
+import { NavigationContainer } from "@react-navigation/native";
+import { migrateDb } from "./lib/db";
+import { Text } from "react-native";
 
 export default function Layout() {
-  return (
-    <NavigationContainer>
-      <TTNavStack />
-    </NavigationContainer>
-  );
+  const [loaded, setLoaded] = React.useState<boolean>(true);
+  React.useEffect(() => {
+    (async function () {
+      await migrateDb();
+      await ScreenOrientation.unlockAsync();
+      await ScreenOrientation.lockAsync(
+        ScreenOrientation.OrientationLock.LANDSCAPE_LEFT
+      );
+      setLoaded(true);
+    })();
+  });
+  return loaded ? <TTNavStack /> : <Text>Loading...</Text>;
 }
diff --git a/app/i18n/api.ts b/app/i18n/api.ts
index c81a3a7..e2ab4ec 100644
--- a/app/i18n/api.ts
+++ b/app/i18n/api.ts
@@ -24,16 +24,23 @@ export type language_matrix = {
     [key:string] : language_matrix_entry
 }
 
+export async function fetchWithTimeout(url : string, options : RequestInit, timeout = 5000) : Promise<Response> {
+    return Promise.race([
+        fetch(url, options),
+        new Promise((_, reject) => setTimeout(() => reject(new Error('timeout')), timeout))
+    ]);
+}
+
 export class LanguageServer {
     constructor(public baseUrl : string) {}
 
-    async fetchLanguages() : Promise<language_matrix> {
+    async fetchLanguages(timeout = 500) : Promise<language_matrix> {
         let data  = {};
-        const res = await fetch(this.baseUrl + "/languages", {
+        const res = await fetchWithTimeout(this.baseUrl + "/languages", {
             headers: {
                 "Content-Type": "application/json"
             }
-        });
+        }, timeout);
         try {
             data = await res.json();
         } catch (e) {
@@ -55,16 +62,20 @@ export class LanguageServer {
 
     static async getDefault() {
         const settings = await Settings.getDefault();
-        return new LanguageServer(await settings.getLibretranslateBaseUrl());
+        return new LanguageServer(await settings.getLibretranslateBaseUrl() || LIBRETRANSLATE_BASE_URL);
     }
 }
 
 export class Translator {
-    constructor(public source : language_t, public defaultTarget : string = "en", private languageServer : LanguageServer) {
+    constructor(public source : language_t, public defaultTarget : string = "en", private _languageServer : LanguageServer) {
+    }
+
+    get languageServer() {
+        return this._languageServer;
     }
 
     async translate(text : string, target : string|undefined = undefined) {
-        const url = this.languageServer.baseUrl + `/translate`;
+        const url = this._languageServer.baseUrl + `/translate`;
         const res = await fetch(url, {
             method: "POST",
             body: JSON.stringify({
@@ -103,4 +114,10 @@ export class CachedTranslator extends Translator {
         await cache.set(key2, tr2);
         return tr2;
     }
+
+    static async getDefault(defaultTarget: string | undefined = undefined) {
+        const settings = await Settings.getDefault();
+        const source = await settings.getHostLanguage();
+        return new CachedTranslator(source, defaultTarget, await LanguageServer.getDefault())
+    }
 }
\ No newline at end of file
diff --git a/app/i18n/countries.ts b/app/i18n/countries.ts
index dee5d9b..02e57f7 100644
--- a/app/i18n/countries.ts
+++ b/app/i18n/countries.ts
@@ -12,7 +12,7 @@ export function chooseCountry(lang_a2 : string) {
         c => c.languages.includes(lang_a3.alpha3)
     );
 
-    console.log("cc = %x, ", cs.map(c => c.alpha2))
+    // console.log("cc = %x, ", cs.map(c => c.alpha2))
 
     return cs.filter(cc => Object.keys(LANG_FLAGS).includes(cc.alpha2.toLowerCase())).map(c => c.alpha2.toLowerCase());
 }
diff --git a/app/i18n/lang.ts b/app/i18n/lang.ts
index 9a43f7f..e556684 100644
--- a/app/i18n/lang.ts
+++ b/app/i18n/lang.ts
@@ -4,7 +4,9 @@ import _LANGUAGES from "@/assets/languages.min.json"
 export const LANG_FLAGS = _LANG_FLAGS
 
 export function longLang(shortLang : string) {
-    return ((LANG_FLAGS as any)[shortLang] as any)["name"] as string
+    const obj = LANG_FLAGS[shortLang];
+    if (!obj) return undefined;
+    return obj["name"] as string;
 }
 
 export function lang_a3_a2(a3 : string) {
diff --git a/app/index.tsx b/app/index.tsx
index 96f6119..180851e 100644
--- a/app/index.tsx
+++ b/app/index.tsx
@@ -43,6 +43,9 @@ export default function Home() {
 
   return (
     <View style={styles.container}>
+    <Pressable onPress={() => navigation.navigate("Settings")}>
+      <Text>Settings</Text>
+    </Pressable>
       <LanguageSelection onLangSelected={onLangSelected} />
     </View>
   );
diff --git a/app/lib/__tests__/settings.spec.tsx b/app/lib/__tests__/settings.spec.tsx
index b057eee..2de95bf 100644
--- a/app/lib/__tests__/settings.spec.tsx
+++ b/app/lib/__tests__/settings.spec.tsx
@@ -1,12 +1,13 @@
 import {describe, expect, beforeEach} from '@jest/globals';
 import {Settings} from '@/app/lib/settings';
-import { getDb } from '@/app/lib/db';
+import { getDb, migrateDb } from '@/app/lib/db';
 
 describe('Settings', () => {
     let settings: Settings;
 
     beforeEach(async () => {
         // Initialize your Settings class here with a fresh database instance
+        await migrateDb();
         const db = await getDb();
         if (!db) throw new Error("Could not get db");
         settings = new Settings(db);
diff --git a/app/lib/conversation.ts b/app/lib/conversation.ts
index 87502c4..2cc921d 100644
--- a/app/lib/conversation.ts
+++ b/app/lib/conversation.ts
@@ -31,11 +31,15 @@ export class Message {
     }
 }
 
+type conversation_event_t = "add_message" | "translation_done"
+type conversation_callback_t = (conversation : Conversation) => any;
+
 export class Conversation extends Array<Message> {
 
     public onAddMessage? : (conversation : Conversation) => any;
     public onTranslationDone? : (conversation : Conversation) => any;
 
+
     constructor (
         public translator : Translator,
         public host : Speaker,
@@ -44,6 +48,15 @@ export class Conversation extends Array<Message> {
         super();
     }
 
+    public on(event : conversation_event_t, callback : conversation_callback_t) {
+        if (event === "add_message") {
+            this.onAddMessage = callback;
+        }
+        if (event === "translation_done") {
+            this.onTranslationDone = callback;
+        }
+    }
+
     public addMessage(speaker : Speaker, text? : string) {
         this.push(new Message(this, speaker, text));
     }
diff --git a/app/lib/db.ts b/app/lib/db.ts
index fae9f8b..57f8776 100644
--- a/app/lib/db.ts
+++ b/app/lib/db.ts
@@ -1,40 +1,26 @@
-import * as SQLite from 'expo-sqlite';
+import * as SQLite from "expo-sqlite";
+import { MIGRATE_UP, MIGRATE_DOWN } from "./migrations";
 
-export const MIGRATE_UP = {
-    1: [
-        `CREATE TABLE IF NOT EXISTS settings (
-            host_language TEXT,
-            libretranslate_base_url TEXT,
-            ui_direction INTEGER
-        )`,
-    ],
-    2: [
-        `CREATE TABLE IF NOT EXISTS whisper_models (
-            model TEXT PRIMARY KEY,
-            bytes_done INTEGER,
-            bytes_total INTEGER,
-        )`,
-    ]
+export async function getDb() {
+  return await SQLite.openDatabaseAsync("translation_terrace");
 }
 
-export const MIGRATE_DOWN = {
-    1: [
-        `DROP TABLE IF EXISTS settings`
-    ],
-    2: [
-        `DROP TABLE IF EXISTS whisper_models`
-    ]
-}
 
-export async function getDb(migrationDirection : "up" | "down" = "up") {
-    const db = await SQLite.openDatabaseAsync('translation_terrace');
+export async function migrateDb(direction: "up" | "down" = "up") {
 
-    for (let [migration, statements] of Object.entries(MIGRATE_UP)) {
-        for (let statement of statements) {
-            console.log(statement)
-            await db.runAsync(statement);
-        }
+  const db = await getDb();
+
+  const m = direction === "up" ? MIGRATE_UP : MIGRATE_DOWN;
+
+  for (let [migration, statements] of Object.entries(m)) {
+    for (let statement of statements) {
+      console.log(statement);
+      try {
+        const result = await db.runAsync(statement);
+        console.log(result);
+      } catch (err) {
+        console.error(err);
+      }
     }
-
-    return db;
+  }
 }
\ No newline at end of file
diff --git a/app/lib/migrations.ts b/app/lib/migrations.ts
new file mode 100644
index 0000000..9da55d8
--- /dev/null
+++ b/app/lib/migrations.ts
@@ -0,0 +1,23 @@
+
+export const MIGRATE_UP = {
+    1: [
+      `CREATE TABLE IF NOT EXISTS settings (
+              host_language TEXT,
+              libretranslate_base_url TEXT,
+              ui_direction INTEGER,
+              whisper_model TEXT
+          )`,
+    ],
+    2: [
+      `CREATE TABLE IF NOT EXISTS whisper_models (
+              model TEXT PRIMARY KEY,
+              bytes_done INTEGER,
+              bytes_total INTEGER
+          )`,
+    ],
+  };
+  
+  export const MIGRATE_DOWN = {
+    1: [`DROP TABLE IF EXISTS settings`],
+    2: [`DROP TABLE IF EXISTS whisper_models`],
+  };
\ No newline at end of file
diff --git a/app/lib/settings.ts b/app/lib/settings.ts
index 5e1a2b9..3911eaa 100644
--- a/app/lib/settings.ts
+++ b/app/lib/settings.ts
@@ -8,7 +8,7 @@ export class Settings {
         "host_language",
         "libretranslate_base_url",
         'ui_direction',
-        "wisper_model",
+        "whisper_model",
     ]
 
     constructor(public db: SQLiteDatabase) {
diff --git a/app/lib/whisper.ts b/app/lib/whisper.ts
index e50a9fb..e3937c7 100644
--- a/app/lib/whisper.ts
+++ b/app/lib/whisper.ts
@@ -1,5 +1,5 @@
 import { Platform } from "react-native";
-import FileSystem from "expo-file-system";
+import * as FileSystem from "expo-file-system";
 import { File, Paths } from 'expo-file-system/next';
 import { getDb } from "./db";
 
@@ -145,10 +145,13 @@ export async function downloadWhisperModel(
   }
 ) {
 
+  console.debug("Starting download of %s", whisper_model);
+
   if (!WHISPER_MODEL_DIR.exists) {
     await FileSystem.makeDirectoryAsync(WHISPER_MODEL_PATH, {
       intermediates: true,
-    })
+    });
+    console.debug("Created %s", WHISPER_MODEL_DIR);
   }
 
   const whisperTarget = getWhisperTarget(whisper_model);
@@ -179,6 +182,7 @@ export async function downloadWhisperModel(
         data.totalBytesWritten,
         data.totalBytesExpectedToWrite,
       ];
+      console.log("%s, %s of %s", whisper_model, data.totalBytesWritten, data.totalBytesExpectedToWrite);
       await db.runAsync(
         `INSERT OR REPLACE INTO whisper_models (model, bytes_done, bytes_remaining) VALUES (?, ?, ?)`,
         args
@@ -187,4 +191,4 @@ export async function downloadWhisperModel(
   );
 
   await resumable.downloadAsync();
-}
+}
\ No newline at end of file
diff --git a/components/ConversationThread.tsx b/components/ConversationThread.tsx
index 6972f58..c7d873a 100644
--- a/components/ConversationThread.tsx
+++ b/components/ConversationThread.tsx
@@ -1,13 +1,9 @@
 import React, { useState, useEffect } from "react";
-import { ScrollView, Text, TouchableHighlight, View } from "react-native";
+import { ScrollView, StyleSheet, Text, TouchableHighlight, View } from "react-native";
 import { useNavigation, Route } from "@react-navigation/native";
 import { Conversation, Message } from "@/app/lib/conversation";
 import MessageBubble from "@/components/ui/MessageBubble";
-import { WhisperContext } from "whisper.rn";
-import { NavigationProp, ParamListBase } from "@react-navigation/native";
-import { CachedTranslator, LanguageServer } from "@/app/i18n/api";
-import { getDb } from "@/app/lib/db";
-import LiveAudioStream from "react-native-live-audio-stream";
+import { CachedTranslator, LanguageServer, language_matrix_entry } from "@/app/i18n/api";
 
 const lasOptions = {
   sampleRate: 32000, // default is 44100 but 32000 is adequate for accurate voice recognition
@@ -35,18 +31,45 @@ const ConversationThread = ({ route } : {route?: Route<"Conversation", {conversa
     undefined | CachedTranslator
   >();
 
+  const [languageLabels, setLanguageLabels] = useState<undefined | {
+    hostNative: {
+      host: string,
+      guest: string,
+    },
+    guestNative: {
+      host: string,
+      guest: string,
+    }
+  }>()
+
   useEffect(() => {
     (async () => {
-      setCachedTranslator(
-        new CachedTranslator(
-          "en",
-          conversation.guest.language,
-          await LanguageServer.getDefault()
-        )
-      );
-      if (!cachedTranslator) throw new Error("cachedTranslator is undefined");
-      setGuestSpeak(await cachedTranslator.translate("Speak"));
+
+      const languageServer = await LanguageServer.getDefault();
+      const languages = await languageServer.fetchLanguages();
+      const cc = new CachedTranslator(
+        "en",
+        conversation.guest.language,
+        languageServer,
+      )
+      setCachedTranslator(cc);
+      setGuestSpeak(await cc.translate("Speak"));
+      const hostLang1 = languages[conversation.host.language].name;
+      const guestLang1 = languages[conversation.host.language].name;
+      const hostLang2 = await cc.translate(languages[conversation.host.language].name);
+      const guestLang2 = await cc.translate(languages[conversation.host.language].name);
+      setLanguageLabels({
+        hostNative: {
+          host: hostLang1,
+          guest: guestLang1,
+        },
+        guestNative: {
+          host: hostLang2,
+          guest: guestLang2,
+        }
+      })
     })();
+    
     const updateMessages = (c: Conversation) => {
       setMessages([...c]);
     };
@@ -67,7 +90,11 @@ const ConversationThread = ({ route } : {route?: Route<"Conversation", {conversa
 
   return cachedTranslator ? (
     <View style={{ flex: 1, flexDirection: "column" }}>
-      <Text>Conversation Thread</Text>
+      {languageLabels && (<View style={styles.languageLabels}>
+        <Text style={styles.nativeHostLabel}>{ languageLabels.hostNative.host } / { languageLabels.hostNative.guest }</Text>
+        <Text style={styles.nativeGuestLabel}>{ languageLabels.guestNative.host } / { languageLabels.guestNative.guest }</Text>
+      </View>)
+      }
       <ScrollView
         style={{
           borderColor: "black",
@@ -106,4 +133,16 @@ const ConversationThread = ({ route } : {route?: Route<"Conversation", {conversa
   );
 };
 
+const styles = StyleSheet.create({
+  languageLabels: {
+
+  },
+  nativeHostLabel: {
+
+  },
+  nativeGuestLabel: {
+
+  },
+})
+
 export default ConversationThread;
diff --git a/components/LanguageSelection.tsx b/components/LanguageSelection.tsx
index 4026885..0771cd0 100644
--- a/components/LanguageSelection.tsx
+++ b/components/LanguageSelection.tsx
@@ -3,11 +3,11 @@ import { LIBRETRANSLATE_BASE_URL } from "@/constants/api";
 import { useEffect, useState } from "react";
 import ISpeakButton from "./ui/ISpeakButton";
 import { LANG_FLAGS } from "@/app/i18n/lang";
-import { ScrollView, StyleSheet, Text, View } from "react-native";
+import { Pressable, ScrollView, StyleSheet, Text, View } from "react-native";
 import { SafeAreaProvider, SafeAreaView } from "react-native-safe-area-context";
 import { Conversation, Speaker } from "@/app/lib/conversation";
 import { NavigationProp, ParamListBase } from "@react-navigation/native";
-import { Link } from "expo-router";
+import { Link, useNavigation } from "expo-router";
 
 
 export function LanguageSelection(props: {
@@ -17,9 +17,11 @@ export function LanguageSelection(props: {
 }) {
   const [languages, setLanguages] = useState<language_matrix | undefined>();
   const [languagesLoaded, setLanguagesLoaded] = useState<boolean>(false);
+  const [translator, setTranslator] = useState<Translator|undefined>();
+
+  const nav = useNavigation();
 
   const languageServer = new LanguageServer(LIBRETRANSLATE_BASE_URL);
-  const translator = props.translator || new CachedTranslator("en", undefined, languageServer);
 
   function onLangSelected(language: language_matrix_entry) {
     props.onLangSelected && props.onLangSelected(language)
@@ -27,33 +29,32 @@ export function LanguageSelection(props: {
 
 
   useEffect(() => {
-    const fetchData = async () => {
+    (async () => {
       try {
         // Replace with your actual async data fetching logic
-        const languages = await languageServer.fetchLanguages();
+        setTranslator(await CachedTranslator.getDefault());
+        const languageServer = await LanguageServer.getDefault();
+        const languages = await languageServer.fetchLanguages(5000);
         setLanguages(languages);
         setLanguagesLoaded(true);
       } catch (error) {
-        error = error as Response;
-        console.error('Error fetching data (%d %s): %s', (error as Response).status, (error as Response).statusText, (error as Response).body);
+        console.error('Error fetching languages from %s: %s', languageServer.baseUrl, error);
       }
-    };
-
-    fetchData();
+    })();
   }, []);
 
   return (
     <View>
-      <Link href={"/settings"}>
+      <Pressable onPress={() => nav.navigate('Settings')}>
         <Text>Settings</Text>
-      </Link>
+      </Pressable>
       <ScrollView >
         <SafeAreaProvider >
           <SafeAreaView>
             {(languages && languagesLoaded) ? Object.entries(languages).filter((l) => (LANG_FLAGS as any)[l[0]] !== undefined).map(
               ([lang, lang_entry]) => {
                 return (
-                  <ISpeakButton language={lang_entry} key={lang_entry.code} onLangSelected={onLangSelected} />
+                  <ISpeakButton language={lang_entry} key={lang_entry.code} onLangSelected={onLangSelected} translator={translator} />
                 );
               }
             ) : <Text>Waiting...</Text>
diff --git a/components/Settings.tsx b/components/Settings.tsx
index 6095684..2f04949 100644
--- a/components/Settings.tsx
+++ b/components/Settings.tsx
@@ -3,164 +3,280 @@ import React, { useState, useEffect } from "react";
 import { View, Text, TextInput, StyleSheet, Pressable } from "react-native"; // Add Picker import
 import { getDb } from "@/app/lib/db";
 import { Settings } from "@/app/lib/settings";
-import { LanguageServer } from "@/app/i18n/api";
-import {Picker} from "@react-native-picker/picker"
+import { LanguageServer, fetchWithTimeout } from "@/app/i18n/api";
+import { Picker } from "@react-native-picker/picker";
 import { longLang } from "@/app/i18n/lang";
 import { LIBRETRANSLATE_BASE_URL } from "@/constants/api";
-import { WHISPER_MODELS, downloadWhisperModel, download_status, getWhisperDownloadStatus, whisper_model_tag_t } from "@/app/lib/whisper";
+import {
+  WHISPER_MODELS,
+  WHISPER_MODEL_DIR,
+  downloadWhisperModel,
+  download_status,
+  getWhisperDownloadStatus,
+  getWhisperTarget,
+  whisper_model_tag_t,
+} from "@/app/lib/whisper";
+import { Paths } from "expo-file-system/next";
 
 type Language = {
-    code: string;
-    name: string;
+  code: string;
+  name: string;
 };
 
 type LanguageMatrix = {
-    [key: string]: Language;
+  [key: string]: Language;
 };
 
+type connection_test_t =
+  | {
+      success: true;
+    }
+  | {
+      success: false;
+      error: string;
+    };
+
 const SettingsComponent: React.FC = () => {
-    const [hostLanguage, setHostLanguage] = useState<string | null>(null);
-    const [libretranslateBaseUrl, setLibretranslateBaseUrl] = useState<string | null>(null);
-    const [languages, setLanguages] = useState<undefined|LanguageMatrix>();
-    const [isLoaded, setIsLoaded] = useState<boolean>(false);
-    const [whisperModel, setWhisperModel] = useState<undefined|whisper_model_tag_t>()
-    const [downloadStatus, setDownloadStatus] = useState<undefined|download_status>();
+  const [hostLanguage, setHostLanguage] = useState<string | null>(null);
+  const [libretranslateBaseUrl, setLibretranslateBaseUrl] = useState<
+    string | null
+  >(null);
+  const [languages, setLanguages] = useState<undefined | LanguageMatrix>();
+  const [isLoaded, setIsLoaded] = useState<boolean>(false);
+  const [whisperModel, setWhisperModel] = useState<
+    undefined | whisper_model_tag_t
+  >();
+  const [downloadStatus, setDownloadStatus] = useState<
+    undefined | download_status
+  >();
 
-    useEffect(() => {
-        (async () => {
-            // Fetch the database connection
-            const db = await getDb();
-            const settings = new Settings(db);
-            
-            // Get the current settings values
-            const hostLang = await settings.getHostLanguage();
-            const libretranslateUrl = await settings.getLibretranslateBaseUrl();
-            const langServer = new LanguageServer(libretranslateBaseUrl || LIBRETRANSLATE_BASE_URL);
-            const wModel = await settings.getWhisperModel()
+  const [langServerConn, setLangServerConn] = useState<
+    undefined | connection_test_t
+  >();
 
-            // Fetch languages from API
-            const langData = await langServer.fetchLanguages();
-            setLanguages(langData);
-            setHostLanguage(hostLang || "en");
-            setLibretranslateBaseUrl(libretranslateUrl);
-            setWhisperModel(wModel);
-            setIsLoaded(true);
-        })();
-        
-        // Check for whether a model is currently downloading and set the status.
-        setInterval(async () => {
-            if (!whisperModel) return null;
-            const dlStatus = await getWhisperDownloadStatus(whisperModel);
-            setDownloadStatus(dlStatus)
-        }, 200);
-    }, []);
-
-    const doReadownload = async () => {
-        if (!whisperModel) return;
-        await downloadWhisperModel(whisperModel, {force_redownload: true});
-    }
-    
-    const doDownload = async () => {
-        if (!whisperModel) return;
-        await downloadWhisperModel(whisperModel)
-    }
-
-    const handleHostLanguageChange = async (value: string) => {
-        setHostLanguage(value);
-
-        // Fetch the database connection
-        const db = await getDb();
-        const settings = new Settings(db);
-
-        // Save the updated setting value
-        await settings.setHostLanguage(value);
-    };
-
-    const handleLibretranslateBaseUrlChange = async (value: string) => {
-        setLibretranslateBaseUrl(value);
-
-        // Fetch the database connection
-        const db = await getDb();
-        const settings = new Settings(db);
-
-        // Save the updated setting value
-        await settings.setLibretranslateBaseUrl(value);
-    };
-
-    return (
-        isLoaded ? <View style={styles.container}>
-            <Text style={styles.label}>Host Language:</Text>
-            <Picker
-                selectedValue={hostLanguage || ""}
-                style={{ height: 50, width: "100%" }}
-                onValueChange={handleHostLanguageChange}
-                accessibilityHint="language"
-            >
-                {languages && Object.keys(languages).map((langCode) => (
-                    <Picker.Item key={langCode} label={longLang(langCode)} value={langCode} />
-                ))}
-            </Picker>
-
-            <Text style={styles.label}>LibreTranslate Base URL:</Text>
-            <TextInput
-                style={styles.input}
-                value={libretranslateBaseUrl || ""}
-                onChangeText={handleLibretranslateBaseUrlChange}
-                accessibilityHint="libretranslate base url"
-            />
-            <Picker
-                selectedValue={whisperModel || ""}
-                style={{ height: 50, width: "100%" }}
-                onValueChange={setWhisperModel}
-                accessibilityHint="language"
-            >
-                {Object.entries(WHISPER_MODELS).map(([key, {label}]) => (
-                    <Picker.Item key={key} label={label} value={key} />
-                ))}
-            </Picker>
-            {whisperModel && (
-                <View>
-                    {
-                        downloadStatus?.status === "complete" ? (
-                            <Pressable onPress={doReadownload}>
-                                Re-Download
-                            </Pressable>
-                        ) : (
-                            downloadStatus?.status === "in_progress" ? (
-                                <Text>
-                                    {downloadStatus.bytes.done / downloadStatus.bytes.total * 100.0} % complete
-                                    { downloadStatus.bytes.done } bytes of { downloadStatus.bytes.total }
-                                </Text>
-                            ) : (
-                                <Pressable onPress={doDownload}>
-                                    Download
-                                </Pressable>
-                            )
-                        )
-                    }
-                </View>
-            )}
-        </View> : <View><Text>Loading ...</Text></View>
+  const fillHostLanguageOptions = async () => {
+    const settings = await Settings.getDefault();
+    const hostLang = await settings.getHostLanguage();
+    setHostLanguage(hostLang || "en");
+    const langServer = new LanguageServer(
+      libretranslateBaseUrl || LIBRETRANSLATE_BASE_URL
     );
+    // Fetch languages from API
+    try {
+      const langData = await langServer.fetchLanguages();
+      setLanguages(langData);
+      setLangServerConn({ success: true });
+    } catch (err) {
+      console.warn("Got an error fetching: %s", err);
+      setLangServerConn({
+        success: false,
+        error: `Could not connect to ${libretranslateBaseUrl}: ${err}`,
+      });
+    }
+  }
+
+  useEffect(() => {
+    (async () => {
+      // Fetch the database connection
+      // const db = await getDb("down");
+      const settings = await Settings.getDefault();
+
+      await fillHostLanguageOptions();
+
+      console.log("Fetched settings");
+
+      // Get the current settings values
+      const libretranslateUrl =
+        (await settings.getLibretranslateBaseUrl()) || LIBRETRANSLATE_BASE_URL;
+      setLibretranslateBaseUrl(libretranslateUrl);
+      console.log("libretranslate url = %s", libretranslateUrl);
+      try {
+        const wModel = await settings.getWhisperModel();
+        setWhisperModel(wModel || "small");
+      } catch (err) {
+        console.warn(err);
+      }
+
+      // setWhisperModel(wModel);
+      setIsLoaded(true);
+      //   console.log("Set is loaded: %s", isLoaded);
+    })();
+
+    // Check for whether a model is currently downloading and set the status.
+    setInterval(async () => {
+      if (!whisperModel) return null;
+      const dlStatus = await getWhisperDownloadStatus(whisperModel);
+      setDownloadStatus(dlStatus);
+    }, 200);
+
+    setInterval(async () => {
+      if (!libretranslateBaseUrl) return;
+      try {
+        const resp = await fetchWithTimeout(
+          libretranslateBaseUrl + "/languages",
+          {
+            method: "HEAD",
+            headers: {
+              Accept: "application/json",
+              "Content-Type": "application/json",
+            },
+          },
+          5000
+        );
+        if (resp.status !== 200) {
+          throw new Error(resp.statusText);
+        }
+        setLangServerConn({ success: true });
+      } catch (err) {
+        setLangServerConn({
+          success: false,
+          error: `Could not connect to ${libretranslateBaseUrl}: ${err}`,
+        });
+      }
+    }, 1000);
+
+    setInterval(async () => {
+      const settings = await Settings.getDefault();
+      await settings.setHostLanguage(hostLanguage || "en");
+      await settings.setLibretranslateBaseUrl(
+        libretranslateBaseUrl || LIBRETRANSLATE_BASE_URL
+      );
+      await settings.setWhisperModel(whisperModel || "small");
+    }, 1000);
+  }, []);
+
+  const doReadownload = async () => {
+    if (!whisperModel) return;
+    await downloadWhisperModel(whisperModel, { force_redownload: true });
+  };
+
+  const doDownload = async () => {
+    if (!whisperModel) return;
+    await downloadWhisperModel(whisperModel);
+  };
+
+  const handleHostLanguageChange = async (value: string) => {
+    setHostLanguage(value);
+
+    // Fetch the database connection
+    const db = await getDb();
+    const settings = new Settings(db);
+
+    // Save the updated setting value
+    await settings.setHostLanguage(value);
+  };
+
+  const handleLibretranslateBaseUrlChange = async (value: string) => {
+    setLibretranslateBaseUrl(value);
+
+    const settings = await Settings.getDefault();
+
+    // Save the updated setting value
+    await settings.setLibretranslateBaseUrl(value);
+
+    await fillHostLanguageOptions();
+  };
+
+  return isLoaded ? (
+    <View style={styles.container}>
+      <Text style={styles.label}>Host Language:</Text>
+      <Picker
+        selectedValue={hostLanguage || ""}
+        style={{ height: 50, width: "100%" }}
+        onValueChange={handleHostLanguageChange}
+        accessibilityHint="hostLanguage"
+      >
+        {languages &&
+          Object.entries(languages).map((lang) => (
+            <Picker.Item key={lang[0]} label={lang[1].name} value={lang[0]} />
+          ))}
+      </Picker>
+
+      <Text style={styles.label}>LibreTranslate Base URL:</Text>
+      <TextInput
+        style={styles.input}
+        value={libretranslateBaseUrl || LIBRETRANSLATE_BASE_URL}
+        onChangeText={handleLibretranslateBaseUrlChange}
+        accessibilityHint="libretranslate base url"
+      />
+      {langServerConn &&
+        (langServerConn.success ? (
+          <Text>Success connecting to {libretranslateBaseUrl}</Text>
+        ) : (
+          <Text>
+            Error connecting to {libretranslateBaseUrl}: {langServerConn.error}
+          </Text>
+        ))}
+      <Picker
+        selectedValue={whisperModel || ""}
+        style={{ height: 50, width: "100%" }}
+        onValueChange={setWhisperModel}
+        accessibilityHint="language"
+      >
+        {Object.entries(WHISPER_MODELS).map(([key, { label }]) => (
+          <Picker.Item key={key} label={label} value={key} />
+        ))}
+      </Picker>
+      {whisperModel && (
+        <View>
+          {downloadStatus?.status === "complete" ? (
+            <Pressable onPress={doReadownload}>Re-Download</Pressable>
+          ) : downloadStatus?.status === "in_progress" ? (
+            <Text>
+              {(downloadStatus.bytes.done / downloadStatus.bytes.total) * 100.0}{" "}
+              % complete
+              {downloadStatus.bytes.done} bytes of {downloadStatus.bytes.total}
+            </Text>
+          ) : (
+            <View>
+              <Pressable onPress={doDownload} style={styles.button}>
+                <Text style={styles.buttonText}>Download</Text>
+              </Pressable>
+              <Text>
+                This will download to {Paths.join(WHISPER_MODEL_DIR, WHISPER_MODELS[whisperModel].target)}
+              </Text>
+            </View>
+          )}
+        </View>
+      )}
+    </View>
+  ) : (
+    <View>
+      <Text>Loading ...</Text>
+    </View>
+  );
 };
 
 // Create styles for the component
 const styles = StyleSheet.create({
-    container: {
-        flex: 1,
-        padding: 20,
-    },
-    label: {
-        fontSize: 16,
-        marginBottom: 8,
-    },
-    input: {
-        height: 40,
-        borderColor: "gray",
-        borderWidth: 1,
-        marginBottom: 20,
-        paddingHorizontal: 8,
-    },
+  button: {
+    backgroundColor: "blue",
+    flexDirection: "row",
+    display: "flex",
+    flexShrink: 1,
+    padding: 20,
+    alignItems: "center",
+    alignContent: "center",
+  },
+  buttonText: {
+    color: "white",
+    alignSelf: "center",
+  },
+  container: {
+    flex: 1,
+    padding: 20,
+  },
+  label: {
+    fontSize: 16,
+    marginBottom: 8,
+  },
+  input: {
+    height: 40,
+    borderColor: "gray",
+    borderWidth: 1,
+    marginBottom: 20,
+    paddingHorizontal: 8,
+  },
 });
 
-export default SettingsComponent;
\ No newline at end of file
+export default SettingsComponent;
diff --git a/components/TTNavStack.tsx b/components/TTNavStack.tsx
index 59eb538..3fb0c71 100644
--- a/components/TTNavStack.tsx
+++ b/components/TTNavStack.tsx
@@ -1,42 +1,42 @@
-import * as React from 'react';
-import { NavigationContainer } from '@react-navigation/native';
-import SettingsComponent from '@/components/Settings';
-import { LanguageSelection } from '@/components/LanguageSelection';
-import { createNativeStackNavigator, NativeStackNavigationProp } from '@react-navigation/native-stack';
+import * as React from "react";
+import SettingsComponent from "@/components/Settings";
+import { LanguageSelection } from "@/components/LanguageSelection";
 import {
-  useNavigation,
-} from '@react-navigation/native'
-import ConversationThread from '@/components/ConversationThread';
-import { language_matrix_entry, Translator } from '@/app/i18n/api';
-import { useRouter } from 'expo-router';
-import { Conversation } from '@/app/lib/conversation';
-import { Settings } from '@/app/lib/settings';
-import { RootStackParamList } from '@/navigation.types';
+  createNativeStackNavigator,
+  NativeStackNavigationProp,
+} from "@react-navigation/native-stack";
+import { useNavigation } from "@react-navigation/native";
+import ConversationThread from "@/components/ConversationThread";
+import { language_matrix_entry, Translator } from "@/app/i18n/api";
+import { Conversation } from "@/app/lib/conversation";
+import { Settings } from "@/app/lib/settings";
+import { RootStackParamList } from "@/navigation.types";
 
 const Stack = createNativeStackNavigator();
 
 export default function TTNavStack() {
-
-  const nav = useNavigation<NativeStackNavigationProp<RootStackParamList, 'ConversationThread'>>();
-
+  const nav = useNavigation<NativeStackNavigationProp<RootStackParamList, "Conversation">>()
+  
   async function onLangSelected(lang: language_matrix_entry) {
     const settings = await Settings.getDefault();
     const hostLanguage = await settings.getHostLanguage();
     const conversation = new Conversation(
-      (await Translator.getDefault(lang.code)),
+      await Translator.getDefault(lang.code),
       { id: "host", language: hostLanguage },
-      { "id": "guest", language: lang.code, }
-    )
-    nav.navigate("Conversation", { conversation, })
+      { id: "guest", language: lang.code }
+    );
+    nav.navigate("ConversationThread", { conversation });
   }
 
   return (
-      <Stack.Navigator initialRouteName='LanguageSelection'>
-        <Stack.Screen name="LanguageSelection" >
-          { props => <LanguageSelection {...props} onLangSelected={(l) => onLangSelected(l)}  />}
-        </Stack.Screen>
-        <Stack.Screen name="ConversationThread" component={ConversationThread} />
-        <Stack.Screen name="Settings" component={SettingsComponent} />
-      </Stack.Navigator>
+    <Stack.Navigator initialRouteName="LanguageSelection">
+      <Stack.Screen name="LanguageSelection">
+        {(props) => (
+          <LanguageSelection {...props} onLangSelected={onLangSelected} />
+        )}
+      </Stack.Screen>
+      <Stack.Screen name="ConversationThread" component={ConversationThread} />
+      <Stack.Screen name="Settings" component={SettingsComponent} />
+    </Stack.Navigator>
   );
-}
\ No newline at end of file
+}
diff --git a/components/__tests__/index.spec.tsx b/components/__tests__/index.spec.tsx
index b576561..b4ea7a0 100644
--- a/components/__tests__/index.spec.tsx
+++ b/components/__tests__/index.spec.tsx
@@ -1,35 +1,61 @@
-import {dirname, resolve} from 'path'
-import React from 'react';
-import { act, fireEvent, render, screen } from '@testing-library/react-native';
-import { createStackNavigator } from '@react-navigation/stack';
-
 jest.mock("@/app/i18n/api", () => require("../../__mocks__/api.ts"));
+import { renderRouter} from 'expo-router/testing-library';
+import React from "react";
+import {
+  act,
+  fireEvent,
+  render,
+  screen,
+  waitFor,
+} from "@testing-library/react-native";
+import {
+  NavigationContainer,
+  createNavigationContainerRef,
+} from "@react-navigation/native";
+import TTNavStack from "../TTNavStack";
 
-import TTNavStack from '../TTNavStack';
-
-const Stack = createStackNavigator();
-
-describe('Navigation', () => {
+describe("Navigation", () => {
   beforeEach(() => {
     // Reset the navigation state before each test
     jest.clearAllMocks();
+    jest.useFakeTimers();
   });
 
-  it('Navigates to ConversationThread on language selection', async () => {
-    render(<TTNavStack />);
-    const languageSelectionText = await screen.findByText(/I Speak French\./i);
+  it("Navigates to ConversationThread on language selection", async () => {
+    const MockComponent = jest.fn(() => <TTNavStack />);
+    renderRouter(
+      {
+        index: MockComponent,
+      },
+      {
+        initialUrl: '/',
+      }
+    );
+    const languageSelectionText = await waitFor(() =>
+      screen.getByText(/.*I Speak French.*/i)
+    );
     act(() => {
       fireEvent.press(languageSelectionText);
-    })
+    });
     expect(await screen.findByText("Conversation Thread")).toBeOnTheScreen();
   });
 
-  it('Navigates to Settings on settings selection', async () => {
-    render(<TTNavStack />);
-    const settingsButton = await screen.findByText("Settings");
-    act(() => {
-      fireEvent.press(settingsButton)
-    })
-    expect(await screen.findByText("Settings")).toBeOnTheScreen();
+  it("Navigates to Settings on settings selection", async () => {
+    const MockComponent = jest.fn(() => <TTNavStack />);
+    renderRouter(
+      {
+        index: MockComponent,
+      },
+      {
+        initialUrl: '/',
+      }
+    );
+    const settingsButton = await waitFor(() =>
+      screen.getByText(/.*Settings.*/i)
+    );
+    fireEvent.press(settingsButton);
+    expect(await waitFor(() => screen.getByText(/Settings/i))).toBeOnTheScreen();
+    // expect(waitFor(() => screen.getByText(/Settings/i))).toBeTruthy()
+    expect(screen.getByText("Settings")).toBeOnTheScreen();
   });
-});
\ No newline at end of file
+});
diff --git a/components/ui/ISpeakButton.tsx b/components/ui/ISpeakButton.tsx
index 7d5e463..ec6a754 100644
--- a/components/ui/ISpeakButton.tsx
+++ b/components/ui/ISpeakButton.tsx
@@ -1,121 +1,142 @@
 // import AsyncStorage from '@react-native-async-storage/async-storage';
-import { CachedTranslator, Translator, language_matrix_entry } from "@/app/i18n/api"
-import { longLang } from "@/app/i18n/lang"
-import React, { useEffect, useRef, useState } from "react"
-import { Button, Image, ImageBackground, Pressable, StyleSheet, TouchableOpacity, View } from "react-native"
-import { Text } from 'react-native';
+import {
+  CachedTranslator,
+  Translator,
+  language_matrix_entry,
+} from "@/app/i18n/api";
+import { longLang } from "@/app/i18n/lang";
+import React, { useEffect, useRef, useState } from "react";
+import {
+  Button,
+  Image,
+  ImageBackground,
+  Pressable,
+  StyleSheet,
+  TouchableOpacity,
+  View,
+} from "react-native";
+import { Text } from "react-native";
 import CountryFlag from "react-native-country-flag";
-import { chooseCountry } from '@/app/i18n/countries';
+import { chooseCountry } from "@/app/i18n/countries";
 
 type ISpeakButtonProps = {
-    language: language_matrix_entry,
-    translator?: Translator,
-    onLangSelected?: (lang : language_matrix_entry) => any | Promise<any>,
+  language: language_matrix_entry;
+  translator?: Translator;
+  onLangSelected?: (lang: language_matrix_entry) => any | Promise<any>;
+};
+
+function iSpeak(language: language_matrix_entry) {
+  return `I speak ${language.name}.`;
 }
 
-function iSpeak(language : language_matrix_entry) {
-    return `I speak ${language.name}.`
-}
-
-async function iSpeakTr(translator : CachedTranslator, targetLang : language_matrix_entry) {
-    const sourceStr = iSpeak(targetLang)
-    return await translator.translate(sourceStr, targetLang.code);
+async function iSpeakTr(
+  translator: CachedTranslator,
+  targetLang: language_matrix_entry
+) {
+  const sourceStr = iSpeak(targetLang);
+  return await translator.translate(sourceStr, targetLang.code);
 }
 
 const DEFAULT_FLAGS = {
-    "en": ["us", "gb"],
-    // "sq": ["al"],
-    "ar": ["ae"],
-    "es": ["es"],
-    "pt": ["pt"],
-    "ru": ["ru"],
-    "it": ["it"],
-    "ir": ["ie"],
-    "sk": ["sk"],
-    "ro": ["ro"],
-    "ja": ["jp"],
-    "ko": ["kp", "kr"],
-    "el": ["gr"],
-    "fr": ["fr"],
-    "de": ["de"],
-    "nl": ["nl"],
-    "cz": ["cz"],
-    "uk": ["ua"],
-    "he": ["il"],
-    "hi": ["in"],
-    "gl": ["es"],
-    "fa": ["ir"],
-    "ur": ["pk"],
-    "ga": ["ie"],
-    "eo": ["es"]
-}
+  en: ["us", "gb"],
+  // "sq": ["al"],
+  ar: ["ae"],
+  es: ["es"],
+  pt: ["pt"],
+  ru: ["ru"],
+  it: ["it"],
+  ir: ["ie"],
+  sk: ["sk"],
+  ro: ["ro"],
+  ja: ["jp"],
+  ko: ["kp", "kr"],
+  el: ["gr"],
+  fr: ["fr"],
+  de: ["de"],
+  nl: ["nl"],
+  cz: ["cz"],
+  uk: ["ua"],
+  he: ["il"],
+  hi: ["in"],
+  gl: ["es"],
+  fa: ["ir"],
+  ur: ["pk"],
+  ga: ["ie"],
+  eo: ["es"],
+};
 
-const ISpeakButton = (props : ISpeakButtonProps) => {
+const ISpeakButton = (props: ISpeakButtonProps) => {
+  const [title, setTitle] = useState<string | undefined>();
+  const [titleLoaded, setTitleLoaded] = useState<boolean>(false);
+  const [translator, setTranslator] = useState<Translator | undefined>(
+    undefined
+  );
 
-    const [title, setTitle] = useState<string | undefined>();
-    const [titleLoaded, setTitleLoaded] = useState<boolean>(false);
-    const translator = props.translator || new CachedTranslator("en");
+  useEffect(() => {
+    (async function () {
+      const tr = props.translator || (await CachedTranslator.getDefault());
+      if (!tr) {
+        console.error("Failed to construct cachedTranslator");
+      }
+      setTranslator(tr);
+      try {
+        // Replace with your actual async data fetching logic
+        const title2 = await iSpeakTr(tr, props.language);
+        setTitle(title2);
+      } catch (error) {
+        console.error("Error fetching data from %s: %s", tr.languageServer.baseUrl, error);
+      } finally {
+        setTitleLoaded(true);
+      }
+    })();
+  }, []);
 
-    useEffect(() => {
-        const fetchData = async () => {
-          try {
-            // Replace with your actual async data fetching logic
-            const title = await iSpeakTr(translator, props.language);
-            setTitle(title);
-        } catch (error) {
-            console.error('Error fetching data:', error);
-        } finally {
-            setTitleLoaded(true);
-          }
-        };
-    
-        fetchData();
-      }, []);
-    
-    const countries = DEFAULT_FLAGS[props.language.code] || chooseCountry(props.language.code);
-    
-    return (
-        title ? (
-            <TouchableOpacity style={styles.button} onPress={() => props.onLangSelected && props.onLangSelected(props.language)}>
-                <View>
-                    <View style={styles.flag}>
-                    {countries &&
-                        countries.map( c => {
-                            return <CountryFlag isoCode={c} size={25} key={c}/> }
-                        )
-                    }
-                    </View>
-                    <View style={styles.iSpeak}>
-                        <Text style={styles.iSpeakText}>{ title }</Text>
-                    </View>
-                </View>
-            </TouchableOpacity>
-        ) : (
-            <Text>Loading...</Text>
-        )
-    )
+  const countries =
+  // @ts-ignore
+    DEFAULT_FLAGS[props.language.code] || chooseCountry(props.language.code);
 
-}
+  return title ? (
+    <TouchableOpacity
+      style={styles.button}
+      onPress={() =>
+        props.onLangSelected && props.onLangSelected(props.language)
+      }
+    >
+      <View>
+        <View style={styles.flag}>
+          {countries &&
+            countries.map((c) => {
+              return <CountryFlag isoCode={c} size={25} key={c} />;
+            })}
+        </View>
+        <View>
+          <Text style={styles.iSpeakText}>{title}</Text>
+        </View>
+      </View>
+    </TouchableOpacity>
+  ) : (
+    <Text>Loading...</Text>
+  );
+};
 
 const styles = StyleSheet.create({
-    button: {
-        width: "20%",
-        borderRadius: 10,
-        borderColor: "white",
-        borderWidth: 1,
-        borderStyle: "solid",
-        height: 110,
-        alignSelf: "flex-start",
-        margin: 8,
-    },
-    flag: {
-    },
-    iSpeak: {
-        textAlign: "center",
-    },
-    iSpeakText: {
-        textAlign: "center"
-    }
-})
+  button: {
+    width: "20%",
+    borderRadius: 10,
+    borderColor: "white",
+    borderWidth: 1,
+    borderStyle: "solid",
+    height: 110,
+    alignSelf: "flex-start",
+    margin: 8,
+  },
+  flag: {},
+  iSpeak: {
+    textAlign: "center",
+  },
+  iSpeakText: {
+    textAlign: "center",
+  },
+});
 
-export default ISpeakButton;
\ No newline at end of file
+export default ISpeakButton;
diff --git a/components/ui/__tests__/Settings.spec.tsx b/components/ui/__tests__/Settings.spec.tsx
index bf381f5..da39c6e 100644
--- a/components/ui/__tests__/Settings.spec.tsx
+++ b/components/ui/__tests__/Settings.spec.tsx
@@ -1,9 +1,9 @@
 import React, { Dispatch } from "react";
 import { render, screen, fireEvent, act } from "@testing-library/react-native";
 import SettingsComponent from "@/components/Settings";
-import { Settings } from "@/app/lib/settings";
-import { getDb } from "@/app/lib/db";
 import { language_matrix } from "@/app/i18n/api";
+import { Settings } from "@/app/lib/settings";
+import { getDb, migrateDb } from "@/app/lib/db";
 
 const RENDER_TIME = 1000;
 
@@ -49,45 +49,10 @@ jest.mock("@/app/i18n/api", () => {
     }
 })
 
-jest.mock("@/app/lib/db", () => {
-    return {
-        getDb: jest.fn(() => {
-            return {
-                runAsync: jest.fn((statement : string, value : string) => {}),
-                getFirstAsync: jest.fn((statement : string, value : string) => {
-                    return []
-                }),
-            }
-        })
-    }
-})
-
-jest.mock("@/app/lib/settings", () => {
-    const originalModule = jest.requireActual('@/app/lib/settings');
-    class MockSettings {
-        public constructor(public db = {}) {}
-        public setHostLanguage = jest.fn((val : string) => {
-
-        })
-        public setLibretranslateBaseUrl(val : string) {
-
-        }
-        getHostLanguage = jest.fn(() => {
-            return "en"
-        })
-        getLibretranslateBaseUrl = jest.fn(() => {
-            return "http://localhost:5004"
-        });
-    }
-    return {
-        ...originalModule,
-        Settings: MockSettings
-    }
-})
-
 describe("SettingsComponent", () => {
     beforeEach(async() => {
-        const settings = new Settings(await getDb());
+        await migrateDb();
+        const settings = await Settings.getDefault();
         await settings.setHostLanguage("en");
         await settings.setLibretranslateBaseUrl("https://example.com");
     })
@@ -116,13 +81,12 @@ describe("SettingsComponent", () => {
     test("updates host language setting when input changes", async () => {
         render(<SettingsComponent />);
 
-
         // Wait for the component to fetch and display the initial settings
         await screen.findByText(/Host Language:/i);
         await screen.findByText(/LibreTranslate Base URL:/i);
 
         // Change the host language input value
-        const picker = screen.getByAccessibilityHint("language");
+        const picker = screen.getByAccessibilityHint("hostLanguage");
         fireEvent(picker, "onvalueChange", "es");
         expect(picker.props.selectedIndex).toStrictEqual(0); 
     });
diff --git a/jestSetup.ts b/jestSetup.ts
index c97a007..749b5f2 100644
--- a/jestSetup.ts
+++ b/jestSetup.ts
@@ -1,29 +1,71 @@
 // jestSetup.ts
 
-jest.mock('expo-sqlite', () => {
-    return {
-        openDatabaseAsync: async (name: string) => {
-            const {DatabaseSync} = require("node:sqlite")
-            const db = new DatabaseSync(':memory:');
+// include this line for mocking react-native-gesture-handler
+import 'react-native-gesture-handler/jestSetup';
 
-            return {
-                closeAsync: jest.fn(() => db.close()),
-                executeSql: jest.fn((sql: string) => db.exec(sql)),
-                runAsync: jest.fn(async (sql: string, params = []) => {
-                    const stmt = db.prepare(sql);
-                    // console.log("Running %s with %s", sql, params);
-                    try {
-                        stmt.run(params);
-                    } catch (e) {
-                        throw new Error(`running ${sql} with params ${JSON.stringify(params)}: ${e}`);
-                    }
-                }),
-                getFirstAsync: jest.fn(async (sql : string, params = []) => {
-                    const stmt = db.prepare(sql)
-                    // const result = stmt.run(...params);
-                    return stmt.get(params)
-                })
-            };
-        },
+jest.mock("expo-sqlite", () => {
+  const { DatabaseSync } = require("node:sqlite");
+  const db = new DatabaseSync(":memory:");
+
+  const { MIGRATE_UP } = jest.requireActual("./app/lib/migrations");
+
+  const openDatabaseAsync = async (name: string) => {
+    return {
+      closeAsync: jest.fn(() => db.close()),
+      executeSql: jest.fn((sql: string) => db.exec(sql)),
+      runAsync: jest.fn(async (sql: string, params = []) => {
+        for (let m of Object.values(MIGRATE_UP)) {
+          for (let stmt of m) {
+            const s = db.prepare(stmt);
+            s.run();
+          }
+        }
+        const stmt = db.prepare(sql);
+        // console.log("Running %s with %s", sql, params);
+        try {
+          stmt.run(params);
+        } catch (e) {
+          throw new Error(
+            `running ${sql} with params ${JSON.stringify(params)}: ${e}`
+          );
+        }
+      }),
+      getFirstAsync: jest.fn(async (sql: string, params = []) => {
+        for (let m of Object.values(MIGRATE_UP)) {
+          for (let stmt of m) {
+            const s = db.prepare(stmt);
+            s.run();
+          }
+        }
+        const stmt = db.prepare(sql);
+        // const result = stmt.run(...params);
+        return stmt.get(params);
+      }),
     };
-});
\ No newline at end of file
+  };
+  return {
+    migrateDb: async (direction: "up" | "down" = "up") => {
+      const db = await openDatabaseAsync("translation_terrace");
+      for (let m of Object.values(MIGRATE_UP)) {
+        for (let stmt of m) {
+          await db.executeSql(stmt);
+        }
+      }
+    },
+    openDatabaseAsync,
+  };
+});
+
+// include this section and the NativeAnimatedHelper section for mocking react-native-reanimated
+jest.mock('react-native-reanimated', () => {
+  const Reanimated = require('react-native-reanimated/mock');
+
+  // The mock for `call` immediately calls the callback which is incorrect
+  // So we override it with a no-op
+  Reanimated.default.call = () => {};
+
+  return Reanimated;
+});
+
+// Silence the warning: Animated: `useNativeDriver` is not supported because the native animated module is missing
+// jest.mock('react-native/Libraries/Animated/NativeAnimatedHelper');
\ No newline at end of file