diff --git a/src/main/preload.ts b/src/main/preload.ts
index 7ab343a82b3f6a7d704d35181657fdfdf5f139ed..47ff3204b5e10e2c161f8f3f25e3974e064e1d94 100644
--- a/src/main/preload.ts
+++ b/src/main/preload.ts
@@ -81,11 +81,13 @@ contextBridge.exposeInMainWorld('storage', {
 });
 
 contextBridge.exposeInMainWorld('sshClient', {
-  connect: (data) => ipcRenderer.invoke('ssh:connect', data),
-  data: (data) => ipcRenderer.send('ssh:data', data),
+  connect: (data: string) => ipcRenderer.invoke('ssh:connect', data),
+  data: (data: string) => ipcRenderer.send('ssh:data', data),
 
-  onData: (data) => ipcRenderer.on('ssh:data', data),
-  onSSHConnected: (callback) => ipcRenderer.on('ssh:connected', callback),
+  onData: (data: any) => ipcRenderer.on('ssh:data', data),
+  onSSHConnected: (callback: {
+    (event: IpcRendererEvent, data: string): void;
+  }) => ipcRenderer.on('ssh:connected', callback),
 
   removeAllListeners: () => {
     ipcRenderer.removeAllListeners('ssh:data');
@@ -94,5 +96,5 @@ contextBridge.exposeInMainWorld('sshClient', {
 });
 
 contextBridge.exposeInMainWorld('autoUpdater', {
-  onMessage: (data) => ipcRenderer.on('autoUpdater', data),
+  onMessage: (data: any) => ipcRenderer.on('autoUpdater', data),
 });
diff --git a/src/main/ssh-client.js b/src/main/ssh-client.js
index 70a9b2d3f8ad613be0f6fcac61f9e1f55cbbc0da..c752860b9529489596dc61ae87354622c49a28f4 100644
--- a/src/main/ssh-client.js
+++ b/src/main/ssh-client.js
@@ -8,7 +8,7 @@ const HOME_DIR = app.getPath('home');
 const default_private_key = '';
 const default_private_key_location = HOME_DIR + '/.ssh/id_rsa';
 
-var mainWindow = null;
+let mainWindow = null;
 
 function sendToRenderer(channel, data) {
   if (mainWindow === null) {
@@ -119,6 +119,6 @@ ipcMain.handle('ssh:connect', (event, key) => {
 
 export default function setupSSHClient(browserWindow) {
   console.log('setting up ssh client');
-  console.log(browserWindow);
+  // console.log(browserWindow);
   mainWindow = browserWindow;
 }
diff --git a/src/main/util.ts b/src/main/util.ts
index 1abafac94260e4f68fbdd075f39c597bffe96067..18bcd55a73af533d0aa3786c84a6cb05f82a8a53 100644
--- a/src/main/util.ts
+++ b/src/main/util.ts
@@ -1,6 +1,7 @@
 /* eslint import/prefer-default-export: off */
 import { URL } from 'url';
 import path from 'path';
+import { ExecException } from 'child_process';
 const fs = require('fs');
 const os = require('os');
 const { spawn, exec, ChildProcess } = require('child_process');
@@ -132,21 +133,21 @@ export async function startLocalServer() {
   console.log('Local server started with pid', localServer.pid);
 
   return new Promise((resolve) => {
-    let err_msg;
+    let err_msg: string;
 
     // if there was an error spawning then stderr will be null
     if (localServer.stderr) {
-      localServer.stderr.on('data', (data) => {
+      localServer.stderr.on('data', (data: string) => {
         console.error(`stderr: ${data}`);
       });
     }
 
-    localServer.on('error', (error_msg) => {
-      console.log(`child process failed: ${error_msg}`);
-      err_msg = error_msg;
+    localServer.on('error', (err: string) => {
+      console.log(`child process failed: ${err}`);
+      err_msg = err;
     });
 
-    localServer.on('close', (code) => {
+    localServer.on('close', (code: number) => {
       console.log(`child process exited with code ${code}`);
 
       if (code === 0) {
@@ -170,7 +171,7 @@ export function killLocalServer() {
         `Killing local server with pid ${localServer.pid} and all it children`
       );
       var kill = require('tree-kill');
-      kill(localServer.pid, 'SIGTERM', function (err) {
+      kill(localServer.pid, 'SIGTERM', function (err: string) {
         console.log('Finished killing local server');
         console.log(err);
         resolve(err);
@@ -201,10 +202,10 @@ export async function installLocalServer() {
     ? {}
     : { shell: '/bin/bash', cwd: root_dir };
   try {
-    const child = exec(
+    exec(
       installScriptCommand,
       options,
-      (error, stdout, stderr) => {
+      (error: ExecException | null, stdout: string, stderr: string) => {
         if (error) {
           console.error(`exec error: ${error}`);
           return;
@@ -235,7 +236,7 @@ export async function checkDependencies() {
   let response = {
     status: '',
     message: '',
-    data: [],
+    data: {},
   };
 
   // check if we've done an install/update of dependencies with this build
@@ -276,7 +277,7 @@ export async function checkDependencies() {
     return response;
   }
 
-  const pipListNames = pipList.map((x) => x.name);
+  const pipListNames = pipList.map((x: { name: string }) => x.name);
   const keyDependencies = [
     'fastapi',
     'pydantic',
@@ -299,9 +300,9 @@ export async function checkDependencies() {
 
   response.data = missingDependencies;
   console.log('missingDependencies', missingDependencies);
-  if (missingDependencies.legnth > 0) {
+  if (missingDependencies.length > 0) {
     response.status = 'error';
-    const missingList = missingDependencies.data?.join(', ');
+    const missingList = missingDependencies.join(', ');
     response.message = `Missing dependencies including: ${missingList}...`;
   } else {
     response.status = 'success';
@@ -319,7 +320,7 @@ export async function checkIfCondaEnvironmentExists() {
   let response = {
     status: '',
     message: '',
-    data: [],
+    data: {},
   };
 
   console.log(JSON.stringify({ error, stdout, stderr }));
@@ -352,18 +353,29 @@ export async function checkIfCondaEnvironmentExists() {
   }
 }
 
+interface ExecError extends Error {
+  code?: number;     // Exit code of the shell command if the process exited on its own.
+  stdout?: string;   // Standard output from the command.
+  stderr?: string;   // Standard error output from the command.
+}
+
 /**
  *
  * @param argument parameter to pass to install.sh
  * @returns the stdout of the process or false on failure.
  */
-export async function executeInstallStep(argument: string) {
+export async function executeInstallStep(argument: string): Promise<{
+  error: ExecException | null;
+  stdout: string;
+  stderr: string;
+}> {
   const server_dir = await getTransformerLabCodeDir();
   if (!fs.existsSync(server_dir)) {
-    console.log(
-      'Install step failed. TransformerLab directory has not been setup.'
-    );
-    return false;
+    return {
+      error: new Error('TransformerLab directory has not been setup.'),
+      stdout: 'TransformerLab directory has not been setup.',
+      stderr: 'TransformerLab directory has not been setup.',
+    };
   }
 
   const installScriptFilename = 'install.sh';
@@ -383,14 +395,19 @@ export async function executeInstallStep(argument: string) {
   try {
     ({ error, stdout, stderr } = await awaitExec(exec_cmd, options));
   } catch (err) {
+
     console.log('Failed to execute install step', err);
     console.log(JSON.stringify(err));
-    return {
-      error: err?.code,
-      stdout: err?.stdout?.toString(),
-      stderr: err?.stderr?.toString(),
-    };
+    if (err instanceof Error) {
+      const execError = err as ExecError;
+      return {
+        error: new Error(String(execError.code)),
+        stdout: execError.stdout?.toString() ?? '',
+        stderr: execError.stderr?.toString() ?? '',
+      };
+    }
   }
+
   if (stdout) console.log(`${installScriptFilename} stdout:`, stdout);
   if (stderr) console.error(`${installScriptFilename} stderr:`, stderr);
   return { error, stdout, stderr };
diff --git a/src/renderer/components/AutoUpdateModal.tsx b/src/renderer/components/AutoUpdateModal.tsx
index 4843b175e45135b20caf46a1cd487e5a23e8f0c1..bf21d5a307f5bd1f7ccc1d7d3ccf9d6f0318ddb2 100644
--- a/src/renderer/components/AutoUpdateModal.tsx
+++ b/src/renderer/components/AutoUpdateModal.tsx
@@ -1,13 +1,14 @@
 import React from 'react';
-
 import { Modal, ModalClose, Sheet, Typography } from '@mui/joy';
-window.autoUpdater.onMessage((message) => {
-  console.log('autoupdate message', message);
-  var container = document.getElementById('messages');
-  var m = document.createElement('div');
-  m.innerHTML = text;
+
+window.autoUpdater.onMessage((message: Node) => {
+  // console.log('autoupdate message', message);
+  const container = document.getElementById('messages') as HTMLDivElement;
+  // const m = document.createElement('div');
+  // m.innerHTML = text;
   container?.appendChild(message);
 });
+
 export default function AutoUpdateModal({}) {
   const [open, setOpen] = React.useState<boolean>(true);
 
diff --git a/src/renderer/components/Computer.tsx b/src/renderer/components/Computer.tsx
index 90274d0f46923197d7f29075b2d4fa02ad2faff1..81b66bc5de66f893be1e687b1bb66b4141c5dcef 100644
--- a/src/renderer/components/Computer.tsx
+++ b/src/renderer/components/Computer.tsx
@@ -24,11 +24,25 @@ import { formatBytes } from 'renderer/lib/utils';
 import { useServerStats } from 'renderer/lib/transformerlab-api-sdk';
 
 function getSystemProperties() {
-  const information = document.getElementById('info');
+  const information = document.getElementById('info') as HTMLPreElement;
   information.innerText = `This app is using Chrome (v${window.platform.chrome()}), Node.js (v${window.platform.node()}), and Electron (v${window.platform.electron()})`;
 }
 
-function ComputerCard({ children, title, description = '', chip = '', icon }) {
+interface ComputerCardProps {
+  title: string;
+  description?: string;
+  chip?: string;
+  icon: React.ReactNode;
+  children: React.ReactNode;
+}
+
+function ComputerCard({
+  children,
+  title,
+  description = '',
+  chip = '',
+  icon,
+}: ComputerCardProps) {
   return (
     <Card variant="outlined">
       <CardContent>
@@ -99,7 +113,7 @@ export default function Computer() {
                 title="GPU Specs"
                 image={undefined}
               >
-                {server.gpu?.map((g) => {
+                {server.gpu?.map((g: Record<string, any>) => {
                   return (
                     <>
                       🔥 {g.name}
diff --git a/src/renderer/components/Connect/LocalConnection.tsx b/src/renderer/components/Connect/LocalConnection.tsx
index 8f4cbeb559ccc0d0792ceb0ab00c5784da5c202f..7412a0b5d0f82bf52bfa0fb597a97c4268710d5e 100644
--- a/src/renderer/components/Connect/LocalConnection.tsx
+++ b/src/renderer/components/Connect/LocalConnection.tsx
@@ -13,43 +13,24 @@ import {
 import { CheckCircle2, PlayIcon, RotateCcwIcon } from 'lucide-react';
 import { useEffect, useState } from 'react';
 import { useCheckLocalConnection } from 'renderer/lib/transformerlab-api-sdk';
-
 import { FaApple } from 'react-icons/fa6';
+import {
+  LocalConnectionProvider,
+  useLocalConnectionContext,
+} from './context/localConnectionContext';
+import { setIntervalXTimes, isStep, Steps } from './utils';
+import { Message } from './types/Message';
 
-// Runs a callback every delay milliseconds, up to repetitions times.
-// If the callback returns true, the interval is cleared.
-// If the callback returns false, and the interval has run repetitions times, the notSuccessful callback is run.
-function setIntervalXTimes(callback, notSuccessful, delay, repetitions) {
-  var x = 0;
-  var intervalID = window.setInterval(async function () {
-    console.log(`trying ${x} times`);
-    const response = await callback();
-
-    if (response) {
-      window.clearInterval(intervalID);
-    } else if (++x === repetitions) {
-      notSuccessful();
-      window.clearInterval(intervalID);
-    }
-  }, delay);
-}
+function CheckIfInstalled() {
+  const { activeStep, setActiveStep } = useLocalConnectionContext();
 
-const Steps = [
-  'CHECK_IF_INSTALLED',
-  'CHECK_VERSION',
-  'CHECK_IF_CONDA_INSTALLED',
-  'CHECK_IF_CONDA_ENVIRONMENT_EXISTS',
-  'CHECK_IF_PYTHON_DEPENDENCIES_INSTALLED',
-  'CHECK_IF_SERVER_RUNNING_ON_PORT_8000',
-  'CHECK_FOR_IMPORTANT_PLUGINS',
-];
-
-function CheckIfInstalled({ activeStep, setActiveStep }) {
   const [installStatus, setInstallStatus] = useState('notstarted'); // notstarted, pending, success, error
-  const [installErrorMessage, setInstallErrorMessage] = useState(null);
+  const [installErrorMessage, setInstallErrorMessage] = useState<string | null>(
+    null
+  );
 
   useEffect(() => {
-    if (activeStep !== Steps.indexOf('CHECK_IF_INSTALLED')) return;
+    if (!isStep(activeStep)) return;
     (async () => {
       // First check if there are any system requirement issues
       // If not, then check if installed locally
@@ -142,7 +123,9 @@ function CheckIfInstalled({ activeStep, setActiveStep }) {
   );
 }
 
-function CheckCurrentVersion({ activeStep, setActiveStep }) {
+function CheckCurrentVersion() {
+  const { activeStep = 0, setActiveStep } = useLocalConnectionContext();
+
   const [version, setVersion] = useState('pending'); // pending, or #.#.#
   const [release, setRelease] = useState('');
   const [installStatus, setInstallStatus] = useState('notstarted'); // notstarted, pending, success, error
@@ -238,7 +221,9 @@ function CheckCurrentVersion({ activeStep, setActiveStep }) {
   );
 }
 
-function RunServer({ activeStep, setActiveStep }) {
+function RunServer() {
+  const { activeStep, setActiveStep } = useLocalConnectionContext();
+
   const [thinking, setThinking] = useState(false);
   const {
     server,
@@ -271,72 +256,70 @@ function RunServer({ activeStep, setActiveStep }) {
   }, [activeStep, server]);
 
   return (
-    <>
-      <Stack spacing={1}>
-        {activeStep >= Steps.indexOf('CHECK_IF_SERVER_RUNNING_ON_PORT_8000') &&
-          server &&
-          !serverError && <Chip color="success">Success!</Chip>}
-        {activeStep >= Steps.indexOf('CHECK_IF_SERVER_RUNNING_ON_PORT_8000') &&
-          (!server || serverError) && <Chip color="danger">Not Running</Chip>}
-        <ButtonGroup variant="plain" spacing={1}>
-          {activeStep ==
-            Steps.indexOf('CHECK_IF_SERVER_RUNNING_ON_PORT_8000') &&
-            (!server || serverError ? (
-              thinking ? (
-                <CircularProgress color="primary" />
-              ) : (
-                <>
-                  <Button
-                    variant="solid"
-                    onClick={async () => {
-                      setThinking(true);
-                      const start_process =
-                        await window.electron.ipcRenderer.invoke(
-                          'server:startLocalServer'
-                        );
+    <Stack spacing={1}>
+      {activeStep >= Steps.indexOf('CHECK_IF_SERVER_RUNNING_ON_PORT_8000') &&
+        server &&
+        !serverError && <Chip color="success">Success!</Chip>}
+      {activeStep >= Steps.indexOf('CHECK_IF_SERVER_RUNNING_ON_PORT_8000') &&
+        (!server || serverError) && <Chip color="danger">Not Running</Chip>}
+      <ButtonGroup variant="plain" spacing={1}>
+        {activeStep == Steps.indexOf('CHECK_IF_SERVER_RUNNING_ON_PORT_8000') &&
+          (!server || serverError ? (
+            thinking ? (
+              <CircularProgress color="primary" />
+            ) : (
+              <>
+                <Button
+                  variant="solid"
+                  onClick={async () => {
+                    setThinking(true);
+                    const start_process =
+                      await window.electron.ipcRenderer.invoke(
+                        'server:startLocalServer'
+                      );
 
-                      if (start_process?.status == 'error') {
-                        const response_text =
-                          'Failed to start server: \n' + start_process?.message;
-                        alert(response_text);
+                    if (start_process?.status == 'error') {
+                      const response_text =
+                        'Failed to start server: \n' + start_process?.message;
+                      alert(response_text);
+                      setThinking(false);
+                      return;
+                    }
+                    //set interval to check if server is running every 2 seconds, 15 times:
+                    setIntervalXTimes(
+                      async () => {
+                        if (!server || serverError) return false;
                         setThinking(false);
-                        return;
-                      }
-                      //set interval to check if server is running every 2 seconds, 15 times:
-                      setIntervalXTimes(
-                        async () => {
-                          if (!server || serverError) return false;
-                          setThinking(false);
-                          setActiveStep(
-                            Steps.indexOf(
-                              'CHECK_IF_SERVER_RUNNING_ON_PORT_8000'
-                            ) + 1
-                          );
-                          return true;
-                        },
-                        () => {
-                          setThinking(false);
-                        },
-                        2000,
-                        15
-                      );
-                    }}
-                  >
-                    Start
-                  </Button>
-                </>
-              )
-            ) : (
-              ''
-            ))}
-        </ButtonGroup>
-      </Stack>
-    </>
+                        setActiveStep(
+                          Steps.indexOf(
+                            'CHECK_IF_SERVER_RUNNING_ON_PORT_8000'
+                          ) + 1
+                        );
+                        return true;
+                      },
+                      () => {
+                        setThinking(false);
+                      },
+                      2000,
+                      15
+                    );
+                  }}
+                >
+                  Start
+                </Button>
+              </>
+            )
+          ) : (
+            ''
+          ))}
+      </ButtonGroup>
+    </Stack>
   );
 }
 
-function CheckForPlugins({ activeStep, setActiveStep }) {
-  const [missingPlugins, setMissingPlugins] = useState(null);
+function CheckForPlugins() {
+  const { activeStep, setActiveStep } = useLocalConnectionContext();
+  const [missingPlugins, setMissingPlugins] = useState([]);
   const [installing, setInstalling] = useState(false);
 
   useEffect(() => {
@@ -365,7 +348,7 @@ function CheckForPlugins({ activeStep, setActiveStep }) {
         )}
 
         <Typography level="body-sm">
-          {platform.isMac() && platform.arch() == 'arm64' && (
+          {window.platform.isMac() && window.platform.arch() == 'arm64' && (
             <>
               You are running on a <FaApple /> Mac with <b>Apple Silicon</b>
               .&nbsp;
@@ -437,7 +420,8 @@ function CheckForPlugins({ activeStep, setActiveStep }) {
   );
 }
 
-function CheckIfCondaInstalled({ activeStep, setActiveStep }) {
+function CheckIfCondaInstalled() {
+  const { activeStep, setActiveStep } = useLocalConnectionContext();
   const [installStatus, setInstallStatus] = useState(''); // notstarted, pending, success, error
 
   useEffect(() => {
@@ -519,9 +503,15 @@ function CheckIfCondaInstalled({ activeStep, setActiveStep }) {
   );
 }
 
-function CheckIfCondaEnvironmentExists({ activeStep, setActiveStep }) {
-  const [installStatus, setInstallStatus] = useState(''); // notstarted, pending, success, error
-  const [errorMessage, setErrorMessage] = useState(null);
+function CheckIfCondaEnvironmentExists() {
+  const { activeStep, setActiveStep } = useLocalConnectionContext();
+  const [installStatus, setInstallStatus] = useState<
+    'success' | 'notstarted' | 'pending' | 'error' | ''
+  >(''); // notstarted, pending, success, error
+  const [errorMessage, setErrorMessage] = useState<{
+    message: string;
+    data: any;
+  } | null>(null);
 
   useEffect(() => {
     if (activeStep !== Steps.indexOf('CHECK_IF_CONDA_ENVIRONMENT_EXISTS'))
@@ -628,9 +618,10 @@ function CheckIfCondaEnvironmentExists({ activeStep, setActiveStep }) {
   );
 }
 
-function CheckDependencies({ activeStep, setActiveStep }) {
+function CheckDependencies() {
+  const { activeStep, setActiveStep } = useLocalConnectionContext();
   const [installStatus, setInstallStatus] = useState(''); // notstarted, pending, success, error
-  const [errorMessage, setErrorMessage] = useState(null);
+  const [errorMessage, setErrorMessage] = useState<Message>(null);
 
   useEffect(() => {
     if (activeStep !== Steps.indexOf('CHECK_IF_PYTHON_DEPENDENCIES_INSTALLED'))
@@ -641,10 +632,7 @@ function CheckDependencies({ activeStep, setActiveStep }) {
         'server:checkDependencies'
       );
 
-      if (
-        ipcResponse?.status == 'success' &&
-        ipcResponse?.data?.length == 0
-      ) {
+      if (ipcResponse?.status == 'success' && ipcResponse?.data?.length == 0) {
         setInstallStatus('success');
         setActiveStep(
           Steps.indexOf('CHECK_IF_PYTHON_DEPENDENCIES_INSTALLED') + 1
@@ -665,76 +653,78 @@ function CheckDependencies({ activeStep, setActiveStep }) {
   }, [activeStep]);
 
   return (
-    <>
-      <Stack spacing={1}>
-        {installStatus == 'success' && <Chip color="success">Success!</Chip>}
-        {installStatus == 'pending' && (
-          <>
-            <CircularProgress color="primary" />
-            <Typography level="body-sm" color="warning">
-              Installing. This can take a long while.
-            </Typography>
-          </>
-        )}
-        {activeStep ==
-          Steps.indexOf('CHECK_IF_PYTHON_DEPENDENCIES_INSTALLED') &&
-          installStatus == 'notstarted' && (
-            <ButtonGroup variant="plain" spacing={1}>
-              <Button
-                variant="solid"
-                size="sm"
-                startDecorator={<RotateCcwIcon size="16px" />}
-                onClick={async () => {
-                  setInstallStatus('pending');
-                  setErrorMessage(null);
-                  await window.electron.ipcRenderer.invoke(
-                    'server:install_install-dependencies'
-                  );
-
-                  const ipcResponse =
-                    await window.electron.ipcRenderer.invoke(
-                      'server:checkDependencies'
-                    );
+    <Stack spacing={1}>
+      {installStatus == 'success' && <Chip color="success">Success!</Chip>}
+      {installStatus == 'pending' && (
+        <>
+          <CircularProgress color="primary" />
+          <Typography level="body-sm" color="warning">
+            Installing. This can take a long while.
+          </Typography>
+        </>
+      )}
+      {activeStep == Steps.indexOf('CHECK_IF_PYTHON_DEPENDENCIES_INSTALLED') &&
+        installStatus == 'notstarted' && (
+          <ButtonGroup variant="plain" spacing={1}>
+            <Button
+              variant="solid"
+              size="sm"
+              startDecorator={<RotateCcwIcon size="16px" />}
+              onClick={async () => {
+                setInstallStatus('pending');
+                setErrorMessage(null);
+                await window.electron.ipcRenderer.invoke(
+                  'server:install_install-dependencies'
+                );
 
-                  if (
-                    ipcResponse?.status == 'success' &&
-                    ipcResponse?.data?.length == 0
-                  ) {
-                    setInstallStatus('success');
-                    setActiveStep(
-                      Steps.indexOf('CHECK_IF_PYTHON_DEPENDENCIES_INSTALLED') +
-                        1
-                    );
-                    return;
-                  }
+                const ipcResponse = await window.electron.ipcRenderer.invoke(
+                  'server:checkDependencies'
+                );
 
-                  if (ipcResponse?.status == 'error') {
-                    setErrorMessage({
-                      message: ipcResponse?.message,
-                      data: ipcResponse?.data,
-                    });
-                  } else {
-                    setErrorMessage(null);
-                  }
-                }}
-              >
-                Install Dependencies
-              </Button>
-            </ButtonGroup>
-          )}
+                if (
+                  ipcResponse?.status == 'success' &&
+                  ipcResponse?.data?.length == 0
+                ) {
+                  setInstallStatus('success');
+                  setActiveStep(
+                    Steps.indexOf('CHECK_IF_PYTHON_DEPENDENCIES_INSTALLED') + 1
+                  );
+                  return;
+                }
+
+                if (ipcResponse?.status == 'error') {
+                  setErrorMessage({
+                    message: ipcResponse?.message,
+                    data: ipcResponse?.data,
+                  });
+                } else {
+                  setErrorMessage(null);
+                }
+              }}
+            >
+              Install Dependencies
+            </Button>
+          </ButtonGroup>
+        )}
 
-        <Typography level="body-sm" color="warning">
-          {errorMessage?.message}
-        </Typography>
-        <Typography level="body-sm" color="neutral">
-          {errorMessage?.data?.stdout} {errorMessage?.data?.stderr}
-        </Typography>
-      </Stack>
-    </>
+      <Typography level="body-sm" color="warning">
+        {errorMessage?.message}
+      </Typography>
+      <Typography level="body-sm" color="neutral">
+        {errorMessage?.data?.stdout} {errorMessage?.data?.stderr}
+      </Typography>
+    </Stack>
   );
 }
 
-function InstallStep({ children, thisStep, title, activeStep, setActiveStep }) {
+interface InstallStepProps {
+  children: React.ReactNode;
+  title: string;
+  thisStep: number;
+}
+
+function InstallStep({ children, thisStep, title }: InstallStepProps) {
+  const { activeStep, setActiveStep } = useLocalConnectionContext();
   return (
     <Step
       indicator={
@@ -754,108 +744,84 @@ function InstallStep({ children, thisStep, title, activeStep, setActiveStep }) {
   );
 }
 
-function InstallStepper({ setServer }) {
+interface InstallStepperProps {
+  setServer: (server: string) => void;
+}
+
+function InstallStepper({ setServer }: InstallStepperProps) {
   const [activeStep, setActiveStep] = useState(
     Steps.indexOf('CHECK_IF_INSTALLED')
-  ); // 0, 1, 2
+  );
 
   function tryToConnect() {
     const fullServer = 'http://' + 'localhost' + ':' + '8000' + '/';
-    window.TransformerLab = {};
-    window.TransformerLab.API_URL = fullServer;
+    window.TransformerLab = {
+      API_URL: fullServer,
+    };
+
     setActiveStep(Steps.indexOf('CHECK_IF_INSTALLED'));
     setServer(fullServer);
   }
+
   return (
-    <Sheet
-      sx={{
-        display: 'flex',
-        flexDirection: 'column',
-        overflow: 'hidden',
-        height: '100%',
-      }}
-    >
-      <Stepper
-        orientation="vertical"
-        sx={{ display: 'flex', overflow: 'auto' }}
+    <LocalConnectionProvider>
+      <Sheet
+        sx={{
+          display: 'flex',
+          flexDirection: 'column',
+          overflow: 'hidden',
+          height: '100%',
+        }}
       >
-        {/* Active Step: {activeStep} */}
-        <InstallStep
-          thisStep={Steps.indexOf('CHECK_IF_INSTALLED')}
-          title="Check if Server is Installed at ~/.transformerlab/"
-          activeStep={activeStep}
-          setActiveStep={setActiveStep}
-        >
-          <CheckIfInstalled
-            activeStep={activeStep}
-            setActiveStep={setActiveStep}
-          />
-        </InstallStep>
-        <InstallStep
-          thisStep={Steps.indexOf('CHECK_VERSION')}
-          title="Check Current Version"
-          activeStep={activeStep}
-          setActiveStep={setActiveStep}
-        >
-          <CheckCurrentVersion
-            activeStep={activeStep}
-            setActiveStep={setActiveStep}
-          />
-        </InstallStep>
-        <InstallStep
-          thisStep={Steps.indexOf('CHECK_IF_CONDA_INSTALLED')}
-          title="Check if Conda is Installed at ~/.transformerlab/miniconda3/"
-          activeStep={activeStep}
-          setActiveStep={setActiveStep}
-        >
-          <CheckIfCondaInstalled
-            activeStep={activeStep}
-            setActiveStep={setActiveStep}
-          />
-        </InstallStep>
-        <InstallStep
-          thisStep={Steps.indexOf('CHECK_IF_CONDA_ENVIRONMENT_EXISTS')}
-          title="Check if Conda Environment 'transformerlab' Exists"
-          activeStep={activeStep}
-          setActiveStep={setActiveStep}
-        >
-          <CheckIfCondaEnvironmentExists
-            activeStep={activeStep}
-            setActiveStep={setActiveStep}
-          />
-        </InstallStep>
-        <InstallStep
-          thisStep={Steps.indexOf('CHECK_IF_PYTHON_DEPENDENCIES_INSTALLED')}
-          title="Check if Python Dependencies are Installed"
-          activeStep={activeStep}
-          setActiveStep={setActiveStep}
-        >
-          <CheckDependencies
-            activeStep={activeStep}
-            setActiveStep={setActiveStep}
-          />
-        </InstallStep>
-        <InstallStep
-          thisStep={Steps.indexOf('CHECK_IF_SERVER_RUNNING_ON_PORT_8000')}
-          title="Check if Server is Running Locally on Port 8000"
-          activeStep={activeStep}
-          setActiveStep={setActiveStep}
+        <Stepper
+          orientation="vertical"
+          sx={{ display: 'flex', overflow: 'auto' }}
         >
-          <RunServer activeStep={activeStep} setActiveStep={setActiveStep} />
-        </InstallStep>
-        <InstallStep
-          thisStep={Steps.indexOf('CHECK_FOR_IMPORTANT_PLUGINS')}
-          title="Check for Important Plugins"
-          activeStep={activeStep}
-          setActiveStep={setActiveStep}
-        >
-          <CheckForPlugins
-            activeStep={activeStep}
-            setActiveStep={setActiveStep}
-          />
-        </InstallStep>
-      </Stepper>
-      {
+          {/* Active Step: {activeStep} */}
+          <InstallStep
+            thisStep={Steps.indexOf('CHECK_IF_INSTALLED')}
+            title="Check if Server is Installed at ~/.transformerlab/"
+          >
+            <CheckIfInstalled />
+          </InstallStep>
+          <InstallStep
+            thisStep={Steps.indexOf('CHECK_VERSION')}
+            title="Check Current Version"
+          >
+            <CheckCurrentVersion />
+          </InstallStep>
+          <InstallStep
+            thisStep={Steps.indexOf('CHECK_IF_CONDA_INSTALLED')}
+            title="Check if Conda is Installed at ~/.transformerlab/miniconda3/"
+          >
+            <CheckIfCondaInstalled />
+          </InstallStep>
+          <InstallStep
+            thisStep={Steps.indexOf('CHECK_IF_CONDA_ENVIRONMENT_EXISTS')}
+            title="Check if Conda Environment 'transformerlab' Exists"
+          >
+            <CheckIfCondaEnvironmentExists />
+          </InstallStep>
+          <InstallStep
+            thisStep={Steps.indexOf('CHECK_IF_PYTHON_DEPENDENCIES_INSTALLED')}
+            title="Check if Python Dependencies are Installed"
+          >
+            <CheckDependencies />
+          </InstallStep>
+          <InstallStep
+            thisStep={Steps.indexOf('CHECK_IF_SERVER_RUNNING_ON_PORT_8000')}
+            title="Check if Server is Running Locally on Port 8000"
+          >
+            <RunServer />
+          </InstallStep>
+          <InstallStep
+            thisStep={Steps.indexOf('CHECK_FOR_IMPORTANT_PLUGINS')}
+            title="Check for Important Plugins"
+          >
+            <CheckForPlugins />
+          </InstallStep>
+        </Stepper>
+
         <Button
           size="lg"
           variant="solid"
@@ -867,13 +833,9 @@ function InstallStepper({ setServer }) {
         >
           Connect
         </Button>
-      }
-    </Sheet>
+      </Sheet>
+    </LocalConnectionProvider>
   );
 }
 
-function LocalConnection({ setServer }) {
-  return <InstallStepper setServer={setServer} />;
-}
-
-export default LocalConnection;
+export default InstallStepper;
diff --git a/src/renderer/components/Connect/context/index.ts b/src/renderer/components/Connect/context/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..65db0994f24a7eb181da75e296925f441d695987
--- /dev/null
+++ b/src/renderer/components/Connect/context/index.ts
@@ -0,0 +1 @@
+export * from './localConnectionContext'
diff --git a/src/renderer/components/Connect/context/localConnectionContext.tsx b/src/renderer/components/Connect/context/localConnectionContext.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..f8eea5ea1c3f35d4363bc5cd528cef6800b7fccf
--- /dev/null
+++ b/src/renderer/components/Connect/context/localConnectionContext.tsx
@@ -0,0 +1,35 @@
+import { createContext, useContext, useState } from 'react';
+
+interface LocalConnectionContext {
+  children?: React.ReactNode;
+  activeStep: number;
+  setActiveStep: React.Dispatch<React.SetStateAction<number>>;
+}
+
+const LocalConnectionContext = createContext<LocalConnectionContext>({
+  activeStep: 0,
+  setActiveStep: (_val) => {},
+});
+
+const LocalConnectionProvider: React.FC<{
+  children: React.ReactNode;
+}> = ({ children }) => {
+  const [activeStep, setActiveStep] = useState<number>(0);
+  return (
+    <LocalConnectionContext.Provider value={{ activeStep, setActiveStep }}>
+      {children}
+    </LocalConnectionContext.Provider>
+  );
+};
+
+const useLocalConnectionContext = () => {
+  const context = useContext(LocalConnectionContext);
+  if (!context) {
+    throw new Error(
+      'useLocalConnectionContext must be used within a LocalConnectionProvider'
+    );
+  }
+  return context;
+};
+
+export { LocalConnectionProvider, useLocalConnectionContext };
diff --git a/src/renderer/components/Connect/types/Message.ts b/src/renderer/components/Connect/types/Message.ts
new file mode 100644
index 0000000000000000000000000000000000000000..cd385c70c9fbc7a49af236686570e79bed23fdba
--- /dev/null
+++ b/src/renderer/components/Connect/types/Message.ts
@@ -0,0 +1,4 @@
+export type Message = {
+  message: string;
+  data: any
+} | null;
diff --git a/src/renderer/components/Connect/utils/index.ts b/src/renderer/components/Connect/utils/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..45cb61e4f0e26a53b4091d0a5119577430006343
--- /dev/null
+++ b/src/renderer/components/Connect/utils/index.ts
@@ -0,0 +1,2 @@
+export * from './isStep'
+export * from './setIntervalXTimes'
diff --git a/src/renderer/components/Connect/utils/isStep.ts b/src/renderer/components/Connect/utils/isStep.ts
new file mode 100644
index 0000000000000000000000000000000000000000..ae4662ef9dc50c22f99a3fee65f28db25ce4dfe3
--- /dev/null
+++ b/src/renderer/components/Connect/utils/isStep.ts
@@ -0,0 +1,14 @@
+export const Steps = [
+  'CHECK_IF_INSTALLED',
+  'CHECK_VERSION',
+  'CHECK_IF_CONDA_INSTALLED',
+  'CHECK_IF_CONDA_ENVIRONMENT_EXISTS',
+  'CHECK_IF_PYTHON_DEPENDENCIES_INSTALLED',
+  'CHECK_IF_SERVER_RUNNING_ON_PORT_8000',
+  'CHECK_FOR_IMPORTANT_PLUGINS',
+] as const;
+export type Step = (typeof Steps)[number];
+
+export function isStep(value: any): value is Step {
+  return Steps.includes(value as Step);
+}
diff --git a/src/renderer/components/Connect/utils/setIntervalXTimes.ts b/src/renderer/components/Connect/utils/setIntervalXTimes.ts
new file mode 100644
index 0000000000000000000000000000000000000000..0cbabf2b21d0db3c00ace2d69d90169a8a281e78
--- /dev/null
+++ b/src/renderer/components/Connect/utils/setIntervalXTimes.ts
@@ -0,0 +1,24 @@
+// Runs a callback every delay milliseconds, up to repetitions times.
+// If the callback returns true, the interval is cleared.
+// If the callback returns false, and the interval has run repetitions times, the notSuccessful callback is run.
+export function setIntervalXTimes(
+  callback: () => any,
+  notSuccessful: () => void,
+  delay: number,
+  repetitions: number
+) {
+  let x = 0;
+  const intervalID = window.setInterval(async function () {
+    console.log(`trying ${x} times`);
+    const response = await callback();
+
+    if (response) {
+      window.clearInterval(intervalID);
+    } else if (++x === repetitions) {
+      notSuccessful();
+      window.clearInterval(intervalID);
+    }
+  }, delay);
+
+  return intervalID;
+}
diff --git a/src/renderer/components/Logs.tsx b/src/renderer/components/Logs.tsx
index 748e15be5561c754b8a54f4c1eca94a45da295a3..92d8924c01a932f1848994a6dfd738b4a633aa65 100644
--- a/src/renderer/components/Logs.tsx
+++ b/src/renderer/components/Logs.tsx
@@ -14,14 +14,16 @@ import * as chatAPI from 'renderer/lib/transformerlab-api-sdk';
 
 import useSWR from 'swr';
 
-const fetcher = (url) => fetch(url).then((res) => res.text());
+const fetcher = (url: string) => fetch(url).then((res) => res.text());
 
-function objectMinusPrompt(obj) {
-  const { prompt, ...rest } = obj;
+function objectMinusPrompt({
+  prompt,
+  ...rest
+}: Record<string, any>): Record<string, any> {
   return rest;
 }
 
-function renderJSONLinesLog(logs) {
+function renderJSONLinesLog(logs: string) {
   return logs?.split('\n').map((line, i) => {
     try {
       const line_object = JSON.parse(line);
@@ -67,7 +69,7 @@ export default function Logs({}) {
           flexDirection: 'column',
         }}
       >
-        <AccordionGroup>{renderJSONLinesLog(data)}</AccordionGroup>
+        <AccordionGroup>{renderJSONLinesLog(data ?? '')}</AccordionGroup>
       </Box>
     </Sheet>
   );
diff --git a/src/renderer/components/MainAppPanel.tsx b/src/renderer/components/MainAppPanel.tsx
index 019f1c3595bffed026f270523f73baa47d8f4cdb..3f8c93ef2adfbcd2e7157e0df18993b2683dd403 100644
--- a/src/renderer/components/MainAppPanel.tsx
+++ b/src/renderer/components/MainAppPanel.tsx
@@ -86,7 +86,7 @@ export default function MainAppPanel({
     updateConfigs();
   }
 
-  function setAdaptor(name) {
+  function setAdaptor(name: string) {
     fetch(
       chatAPI.GET_EXPERIMENT_UPDATE_CONFIG_URL(
         experimentInfo?.id,
diff --git a/src/renderer/components/ModelCurrentlyPlayingBar.tsx b/src/renderer/components/ModelCurrentlyPlayingBar.tsx
index 9ffb032abd71e1242c705c74ab23acb335939379..0b27f3a2218680d11d347b970eb7c87e30e2bd9e 100644
--- a/src/renderer/components/ModelCurrentlyPlayingBar.tsx
+++ b/src/renderer/components/ModelCurrentlyPlayingBar.tsx
@@ -6,7 +6,13 @@ import {
 import { Box, Button, CircularProgress, Typography } from '@mui/joy';
 import TinyCircle from './Shared/TinyCircle';
 
-export default function ModelCurrentlyPlaying({ experimentInfo }) {
+interface ModelCurrentlyPlayingProps {
+  experimentInfo: Record<string, any>;
+}
+
+export default function ModelCurrentlyPlaying({
+  experimentInfo,
+}: ModelCurrentlyPlayingProps) {
   const { models, isError, isLoading } = useModelStatus();
 
   const inferenceParams = experimentInfo?.config?.inferenceParams
@@ -50,7 +56,7 @@ export default function ModelCurrentlyPlaying({ experimentInfo }) {
         variant="plain"
         sx={{ display: models?.length > 0 ? 'flex' : 'none' }}
       >
-        {models?.length == 0 ? (
+        {models?.length === 0 ? (
           <CircularProgress color="warning" />
         ) : (
           <StopCircleIcon />
diff --git a/src/renderer/components/TransformerLabSettings.tsx b/src/renderer/components/TransformerLabSettings.tsx
index 4134fa3f1d02d04ccca0935b51773204f680f854..aa72337b900ede7e1b2ebb41fcdb6c0b3fbb26a5 100644
--- a/src/renderer/components/TransformerLabSettings.tsx
+++ b/src/renderer/components/TransformerLabSettings.tsx
@@ -17,7 +17,7 @@ import * as chatAPI from 'renderer/lib/transformerlab-api-sdk';
 import useSWR from 'swr';
 import { EyeIcon, EyeOffIcon } from 'lucide-react';
 
-const fetcher = (url) => fetch(url).then((res) => res.json());
+const fetcher = (url: string) => fetch(url).then((res) => res.json());
 
 export default function TransformerLabSettings({}) {
   const [showPassword, setShowPassword] = React.useState(false);
@@ -52,12 +52,16 @@ export default function TransformerLabSettings({}) {
               endDecorator={
                 <IconButton
                   onClick={() => {
-                    var x = document.getElementsByName('hftoken')[0];
-                    if (x.type === 'text') {
-                      x.type = 'password';
+                    const hfToken = document.getElementsByName(
+                      'hftoken'
+                    )[0] as HTMLInputElement;
+
+                    if (hfToken.type === 'text') {
+                      hfToken.type = 'password';
                     } else {
-                      x.type = 'text';
+                      hfToken.type = 'text';
                     }
+
                     setShowPassword(!showPassword);
                   }}
                 >
@@ -68,7 +72,10 @@ export default function TransformerLabSettings({}) {
           )}
           <Button
             onClick={async () => {
-              const token = document.getElementsByName('hftoken')[0].value;
+              const tokenElement = document.getElementsByName(
+                'hftoken'
+              )[0] as HTMLInputElement;
+              const token = tokenElement.value;
               await fetch(
                 chatAPI.Endpoints.Config.Set(
                   'HuggingfaceUserAccessToken',
diff --git a/src/renderer/components/Welcome.tsx b/src/renderer/components/Welcome.tsx
index fded8eceb3c7b127b7cb147a129c3235f7e90967..a16faec4497a5d08ed1e50c0fb878aa7e4d9ee7d 100644
--- a/src/renderer/components/Welcome.tsx
+++ b/src/renderer/components/Welcome.tsx
@@ -1,12 +1,8 @@
 /* eslint-disable jsx-a11y/anchor-is-valid */
 
-import { Button, Sheet, Stack, Typography } from '@mui/joy';
-import { ArrowRightCircleIcon, FlaskConicalIcon } from 'lucide-react';
-
-async function testStore() {}
+import { Sheet, Stack, Typography } from '@mui/joy';
 
 import labImage from '../img/lab.jpg';
-
 import flaskLogo from '../img/flask.png';
 
 function LogoComponent() {
@@ -14,13 +10,15 @@ function LogoComponent() {
     <img
       src={flaskLogo}
       width="38"
-      style={{ verticalAlign: 'middle', marginBottom: '10px' }}
+      style={{
+        verticalAlign: 'middle',
+        marginBottom: '10px',
+        display: 'inline-block',
+      }}
     />
   );
 }
 
-testStore();
-
 export default function Welcome() {
   return (
     <Sheet
diff --git a/src/renderer/preload.d.ts b/src/renderer/preload.d.ts
index 3ff48d7b91ae443f317367c9f4ef75e7d41615f9..08ccd4489b3f9218f9d1f6246a0390e6c7a33891 100644
--- a/src/renderer/preload.d.ts
+++ b/src/renderer/preload.d.ts
@@ -1,10 +1,26 @@
 import { ElectronHandler } from 'main/preload';
 
+interface Platform {
+  node: () => string,
+  chrome: () => string,
+  electron: () => string,
+  isMac: () => string,
+  isWindows: () => string,
+  isLinux: () => string,
+  platform: () => string,
+  arch: () => string,
+}
+
 declare global {
   // eslint-disable-next-line no-unused-vars
   interface Window {
     electron: ElectronHandler;
+    TransformerLab: {
+      API_URL: string;
+    }
+    platform: Platform
   }
+
 }
 
 export {};