diff --git a/README.md b/README.md
index 335eae2a..4b5c6f80 100644
--- a/README.md
+++ b/README.md
@@ -6,19 +6,19 @@ Written in Elixir & Phoenix LiveView, with Bootstrap v5.
 
 ## TODO
 
-- [ ] Ability to edit shifts?
-- [ ] Proper modal to delete shifts?
-- [ ] Allow all-day items for notes, or require hours even for sick days?
-- [ ] Implement proper shift/template/assign tests (views etc)
+- [X] ~~*Proper modal to delete shifts?*~~ [2022-08-14]
+- [ ] Update tests, which are probably all way out of date. But I also don't care that much for this project...
 
 ## Deploying
 
+The below notes are old; I'm using a docker build to deploy this now. Will document when I have time.
+
 ### New versions
 
 When improvements are made, we can update the deployed version like so:
 
 ```shell
-cd /opt/shift73k
+cd ${SHIFT73K_BASE_DIR}
 # update from master
 /usr/bin/git pull 73k master
 # fetch prod deps & compile
@@ -27,10 +27,10 @@ MIX_ENV=prod /usr/bin/mix compile
 # perform any migrations
 MIX_ENV=prod /usr/bin/mix ecto.migrate
 # update node packages via package-lock.json
-/usr/bin/npm --prefix /opt/shift73k/assets/ ci
+/usr/bin/npm --prefix ./assets/ ci
 # rebuild static assets:
-rm -rf /opt/shift73k/priv/static/*
-/usr/bin/npm --prefix /opt/shift73k/assets/ run deploy
+rm -rf ./priv/static/*
+/usr/bin/npm --prefix ./assets/ run build
 MIX_ENV=prod /usr/bin/mix phx.digest
 # rebuild release
 MIX_ENV=prod /usr/bin/mix release --overwrite
diff --git a/assets/package-lock.json b/assets/package-lock.json
index 66947817..0bd90fcf 100644
--- a/assets/package-lock.json
+++ b/assets/package-lock.json
@@ -57,9 +57,9 @@
       }
     },
     "node_modules/@types/node": {
-      "version": "18.7.2",
-      "resolved": "https://registry.npmjs.org/@types/node/-/node-18.7.2.tgz",
-      "integrity": "sha512-ce7MIiaYWCFv6A83oEultwhBXb22fxwNOQf5DIxWA4WXvDQ7K+L0fbWl/YOfCzlR5B/uFkSnVBhPcOfOECcWvA==",
+      "version": "18.7.3",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-18.7.3.tgz",
+      "integrity": "sha512-LJgzOEwWuMTBxHzgBR/fhhBOWrvBjvO+zPteUgbbuQi80rYIZHrk1mNbRUqPZqSLP2H7Rwt1EFLL/tNLD1Xx/w==",
       "dev": true
     },
     "node_modules/@types/phoenix": {
@@ -1070,9 +1070,9 @@
       "peer": true
     },
     "@types/node": {
-      "version": "18.7.2",
-      "resolved": "https://registry.npmjs.org/@types/node/-/node-18.7.2.tgz",
-      "integrity": "sha512-ce7MIiaYWCFv6A83oEultwhBXb22fxwNOQf5DIxWA4WXvDQ7K+L0fbWl/YOfCzlR5B/uFkSnVBhPcOfOECcWvA==",
+      "version": "18.7.3",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-18.7.3.tgz",
+      "integrity": "sha512-LJgzOEwWuMTBxHzgBR/fhhBOWrvBjvO+zPteUgbbuQi80rYIZHrk1mNbRUqPZqSLP2H7Rwt1EFLL/tNLD1Xx/w==",
       "dev": true
     },
     "@types/phoenix": {
diff --git a/config/runtime.exs b/config/runtime.exs
deleted file mode 100644
index 029407bf..00000000
--- a/config/runtime.exs
+++ /dev/null
@@ -1,83 +0,0 @@
-import Config
-
-# config/runtime.exs is executed for all environments, including
-# during releases. It is executed after compilation and before the
-# system starts, so it is typically used to load production configuration
-# and secrets from environment variables or elsewhere. Do not define
-# any compile-time configuration in here, as it won't be applied.
-# The block below contains prod specific runtime configuration.
-
-# ## Using releases
-#
-# If you use `mix release`, you need to explicitly enable the server
-# by passing the PHX_SERVER=true when you start it:
-#
-#     PHX_SERVER=true bin/shift73k start
-#
-# Alternatively, you can use `mix phx.gen.release` to generate a `bin/server`
-# script that automatically sets the env var above.
-if System.get_env("PHX_SERVER") do
-  config :shift73k, Shift73kWeb.Endpoint, server: true
-end
-
-if config_env() == :prod do
-  database_url =
-    System.get_env("DATABASE_URL") ||
-      raise """
-      environment variable DATABASE_URL is missing.
-      For example: ecto://USER:PASS@HOST/DATABASE
-      """
-
-  maybe_ipv6 = if System.get_env("ECTO_IPV6"), do: [:inet6], else: []
-
-  config :shift73k, Shift73k.Repo,
-    # ssl: true,
-    url: database_url,
-    pool_size: String.to_integer(System.get_env("POOL_SIZE") || "10"),
-    socket_options: maybe_ipv6
-
-  # The secret key base is used to sign/encrypt cookies and other secrets.
-  # A default value is used in config/dev.exs and config/test.exs but you
-  # want to use a different value for prod and you most likely don't want
-  # to check this value into version control, so we use an environment
-  # variable instead.
-  secret_key_base =
-    System.get_env("SECRET_KEY_BASE") ||
-      raise """
-      environment variable SECRET_KEY_BASE is missing.
-      You can generate one by calling: mix phx.gen.secret
-      """
-
-  host = System.get_env("PHX_HOST") || "example.com"
-  port = String.to_integer(System.get_env("PORT") || "4000")
-
-  config :shift73k, Shift73kWeb.Endpoint,
-    url: [host: host, port: 443, scheme: "https"],
-    http: [
-      # Enable IPv6 and bind on all interfaces.
-      # Set it to  {0, 0, 0, 0, 0, 0, 0, 1} for local network only access.
-      # See the documentation on https://hexdocs.pm/plug_cowboy/Plug.Cowboy.html
-      # for details about using IPv6 vs IPv4 and loopback vs public addresses.
-      ip: {0, 0, 0, 0, 0, 0, 0, 0},
-      port: port
-    ],
-    secret_key_base: secret_key_base
-
-  # ## Configuring the mailer
-  #
-  # In production you need to configure the mailer to use a different adapter.
-  # Also, you may need to configure the Swoosh API client of your choice if you
-  # are not using SMTP. Here is an example of the configuration:
-  #
-  #     config :shift73k, Shift73k.Mailer,
-  #       adapter: Swoosh.Adapters.Mailgun,
-  #       api_key: System.get_env("MAILGUN_API_KEY"),
-  #       domain: System.get_env("MAILGUN_DOMAIN")
-  #
-  # For this example you need include a HTTP client required by Swoosh API client.
-  # Swoosh supports Hackney and Finch out of the box:
-  #
-  #     config :swoosh, :api_client, Swoosh.ApiClient.Hackney
-  #
-  # See https://hexdocs.pm/swoosh/Swoosh.html#module-installation for details.
-end
diff --git a/lib/shift73k_web.ex b/lib/shift73k_web.ex
index 5a03df6a..0eaba35a 100644
--- a/lib/shift73k_web.ex
+++ b/lib/shift73k_web.ex
@@ -105,9 +105,6 @@ defmodule Shift73kWeb do
       # Import basic rendering functionality (render, render_layout, etc)
       import Phoenix.View
 
-      # Import SVG Icon helper
-      import Shift73kWeb.IconHelpers
-
       import Shift73kWeb.ErrorHelpers
       import Shift73kWeb.Gettext
       alias Shift73kWeb.Router.Helpers, as: Routes
diff --git a/lib/shift73k_web/live/live_helpers.ex b/lib/shift73k_web/live/live_helpers.ex
index ff98ac8d..36c33170 100644
--- a/lib/shift73k_web/live/live_helpers.ex
+++ b/lib/shift73k_web/live/live_helpers.ex
@@ -1,6 +1,5 @@
 defmodule Shift73kWeb.LiveHelpers do
   import Phoenix.LiveView
-  import Phoenix.LiveView.Helpers
 
   alias Shift73k.Accounts
   alias Shift73k.Accounts.User
@@ -19,27 +18,6 @@ defmodule Shift73kWeb.LiveHelpers do
   """
   def live_okreply(socket), do: {:ok, socket}
 
-  @doc """
-  Renders a component inside the `Shift73kWeb.ModalComponent` component.
-
-  The rendered modal receives a `:return_to` option to properly update
-  the URL when the modal is closed.
-
-  ## Examples
-
-      <%= live_modal @socket, Shift73kWeb.PropertyLive.FormComponent,
-        id: @property.id || :new,
-        action: @live_action,
-        property: @property,
-        return_to: Routes.property_index_path(@socket, :index) %>
-  """
-  def live_modal(socket, component, opts) do
-    modal_opts = [id: :modal, component: component, opts: opts]
-    # dirty little workaround for elixir complaining about socket being unused
-    _socket = socket
-    live_component(socket, Shift73kWeb.ModalComponent, modal_opts)
-  end
-
   @doc """
   Loads default assigns for liveviews
   """
diff --git a/lib/shift73k_web/live/shift_assign_live/index.html.heex b/lib/shift73k_web/live/shift_assign_live/index.html.heex
index ce1d37a4..ce656afe 100644
--- a/lib/shift73k_web/live/shift_assign_live/index.html.heex
+++ b/lib/shift73k_web/live/shift_assign_live/index.html.heex
@@ -1,10 +1,15 @@
 <%= if @delete_days_shifts do %>
-  <%= live_modal @socket, Shift73kWeb.ShiftAssignLive.DeleteComponent,
+  <.live_component
+    module={Shift73kWeb.ModalComponent}
+    id="modal"
+    component={Shift73kWeb.ShiftAssignLive.DeleteComponent}
+    opts={[
       id: "delete-days-shifts-#{@current_user.id}",
       title: "Delete Shifts From Selected Days",
       delete_days_shifts: @delete_days_shifts,
       current_user: @current_user
-      %>
+    ]}
+    />
 <% end %>
 
 
diff --git a/lib/shift73k_web/live/shift_live/index.html.heex b/lib/shift73k_web/live/shift_live/index.html.heex
index bc9cdf08..b599bd8e 100644
--- a/lib/shift73k_web/live/shift_live/index.html.heex
+++ b/lib/shift73k_web/live/shift_live/index.html.heex
@@ -1,8 +1,14 @@
 <%= if @delete_shift do %>
-  <%= live_modal @socket, Shift73kWeb.ShiftLive.DeleteComponent,
+  <.live_component
+    module={Shift73kWeb.ModalComponent}
+    id="modal"
+    component={Shift73kWeb.ShiftLive.DeleteComponent}
+    opts={[
       id: @delete_shift.id,
       title: "Delete Shift Template",
-      delete_shift: @delete_shift %>
+      delete_shift: @delete_shift
+    ]}
+    />
 <% end %>
 
 
diff --git a/lib/shift73k_web/live/shift_template_live/index.html.heex b/lib/shift73k_web/live/shift_template_live/index.html.heex
index 45faa445..62abcdec 100644
--- a/lib/shift73k_web/live/shift_template_live/index.html.heex
+++ b/lib/shift73k_web/live/shift_template_live/index.html.heex
@@ -1,17 +1,29 @@
 <%= if @live_action in [:new, :edit, :clone] do %>
-  <%= live_modal @socket, Shift73kWeb.ShiftTemplateLive.FormComponent,
-    id: @shift_template.id || :new,
-    title: @page_title,
-    action: @live_action,
-    shift_template: @shift_template,
-    current_user: @current_user %>
+  <.live_component
+    module={Shift73kWeb.ModalComponent}
+    id="modal"
+    component={Shift73kWeb.ShiftTemplateLive.FormComponent}
+    opts={[
+      id: @shift_template.id || :new,
+      title: @page_title,
+      action: @live_action,
+      shift_template: @shift_template,
+      current_user: @current_user
+    ]}
+    />
 <% end %>
 
 <%= if @delete_shift_template do %>
-  <%= live_modal @socket, Shift73kWeb.ShiftTemplateLive.DeleteComponent,
+  <.live_component
+    module={Shift73kWeb.ModalComponent}
+    id="modal"
+    component={Shift73kWeb.ShiftTemplateLive.DeleteComponent}
+    opts={[
       id: @delete_shift_template.id,
       title: "Delete Shift Template",
-      delete_shift_template: @delete_shift_template %>
+      delete_shift_template: @delete_shift_template
+    ]}
+    />
 <% end %>
 
 
diff --git a/lib/shift73k_web/live/user/settings.html.heex b/lib/shift73k_web/live/user/settings.html.heex
index e45e8cee..e769ec43 100644
--- a/lib/shift73k_web/live/user/settings.html.heex
+++ b/lib/shift73k_web/live/user/settings.html.heex
@@ -6,10 +6,10 @@
     </h2>
 
     <div class="row justify-content-center justify-content-md-start">
-      <%= live_component @socket, Shift73kWeb.UserLive.Settings.Email, id: "email-#{@current_user.id}", current_user: @current_user %>
-      <%= live_component @socket, Shift73kWeb.UserLive.Settings.Password, id: "password-#{@current_user.id}", current_user: @current_user %>
-      <%= live_component @socket, Shift73kWeb.UserLive.Settings.WeekStart, id: "week_start-#{@current_user.id}", current_user: @current_user %>
-      <%= live_component @socket, Shift73kWeb.UserLive.Settings.CalendarUrl, id: "calendar_url-#{@current_user.id}", current_user: @current_user %>
+      <.live_component module={Shift73kWeb.UserLive.Settings.Email} id={"email-#{@current_user.id}"} current_user={@current_user} />
+      <.live_component module={Shift73kWeb.UserLive.Settings.Password} id={"password-#{@current_user.id}"} current_user={@current_user} />
+      <.live_component module={Shift73kWeb.UserLive.Settings.WeekStart} id={"week_start-#{@current_user.id}"} current_user={@current_user} />
+      <.live_component module={Shift73kWeb.UserLive.Settings.CalendarUrl} id={"calendar_url-#{@current_user.id}"} current_user={@current_user} />
     </div>
 
   </div>
diff --git a/lib/shift73k_web/live/user_management/delete_component.ex b/lib/shift73k_web/live/user_management/delete_component.ex
index b1c48aae..ee73804f 100644
--- a/lib/shift73k_web/live/user_management/delete_component.ex
+++ b/lib/shift73k_web/live/user_management/delete_component.ex
@@ -9,9 +9,13 @@ defmodule Shift73kWeb.UserManagement.DeleteComponent do
   end
 
   @impl true
-  def handle_event("confirm", %{"id" => id, "email" => email}, socket) do
-    id
-    |> Accounts.get_user()
+  def handle_event("confirm", %{"id" => id, "email" => email} = params, socket) do
+    IO.inspect(params)
+
+    user = Accounts.get_user(id)
+    IO.inspect(user)
+
+    user
     |> Accounts.delete_user()
     |> case do
       {:ok, _} ->
diff --git a/lib/shift73k_web/live/user_management/index.html.heex b/lib/shift73k_web/live/user_management/index.html.heex
index 912bb88b..110cd7de 100644
--- a/lib/shift73k_web/live/user_management/index.html.heex
+++ b/lib/shift73k_web/live/user_management/index.html.heex
@@ -1,18 +1,29 @@
 <%= if @live_action in [:new, :edit] do %>
-  <%= live_modal @socket, Shift73kWeb.UserManagement.FormComponent,
+  <.live_component
+    module={Shift73kWeb.ModalComponent}
+    id="modal"
+    component={Shift73kWeb.UserManagement.FormComponent}
+    opts={[
       id: @user.id || :new,
       title: @page_title,
       action: @live_action,
       user: @user,
-      current_user: @current_user %>
+      current_user: @current_user
+    ]}
+    />
 <% end %>
 
 <%= if @delete_user do %>
-  <%= live_modal @socket, Shift73kWeb.UserManagement.DeleteComponent,
+  <.live_component
+    module={Shift73kWeb.ModalComponent}
+    id="modal"
+    component={Shift73kWeb.UserManagement.DeleteComponent}
+    opts={[
       id: @delete_user.id,
       title: "Delete User",
       delete_user: @delete_user
-    %>
+    ]}
+    />
 <% end %>
 
 
diff --git a/lib/shift73k_web/templates/layout/_navbar.html.heex b/lib/shift73k_web/templates/layout/_navbar.html.heex
index 4c81942d..c8ac8310 100644
--- a/lib/shift73k_web/templates/layout/_navbar.html.heex
+++ b/lib/shift73k_web/templates/layout/_navbar.html.heex
@@ -52,7 +52,7 @@
         AND:
           There are no users -- [REGISTER]
           OR no registration allowed -- [LOG IN] %>
-    <%= else %>
+    <% else %>
 
       <%= if !Repo.exists?(User) || allow_registration() do %>
         <%= link nav_link_opts(@conn, to: Routes.user_registration_path(@conn, :new), class: "btn btn-outline-light") do %>
diff --git a/lib/shift73k_web/views/icon_helpers.ex b/lib/shift73k_web/views/icon_helpers.ex
deleted file mode 100644
index 048373f8..00000000
--- a/lib/shift73k_web/views/icon_helpers.ex
+++ /dev/null
@@ -1,38 +0,0 @@
-defmodule Shift73kWeb.IconHelpers do
-  @moduledoc """
-  Generate SVG sprite use tags for SVG icons
-  """
-
-  use Phoenix.HTML
-  alias Shift73kWeb.Router.Helpers, as: Routes
-
-  def icon_div(conn, name, div_opts \\ [], svg_opts \\ []) do
-    content_tag(:div, tag_opts(name, div_opts)) do
-      icon_svg(conn, name, svg_opts)
-    end
-  end
-
-  def icon_svg(conn, name, opts \\ []) do
-    opts = aria_hidden?(opts)
-
-    content_tag(:svg, tag_opts(name, opts)) do
-      ~E"""
-      <%= if title = Keyword.get(opts, :aria_label), do: content_tag(:title, title) %>
-      <%= tag(:use, "xlink:href": Routes.static_path(conn, "/images/icons.svg##{name}")) %>
-      """
-    end
-  end
-
-  defp tag_opts(name, opts) do
-    Keyword.update(opts, :class, name, fn c -> "#{c} #{name}" end)
-  end
-
-  defp aria_hidden?(opts) do
-    case Keyword.get(opts, :aria_hidden) do
-      "false" -> Keyword.drop(opts, [:aria_hidden])
-      false -> Keyword.drop(opts, [:aria_hidden])
-      "true" -> opts
-      _ -> Keyword.put(opts, :aria_hidden, "true")
-    end
-  end
-end
diff --git a/priv/repo/migrations/20220814161100_fix_shifts_user_id_reference.exs b/priv/repo/migrations/20220814161100_fix_shifts_user_id_reference.exs
new file mode 100644
index 00000000..c4222e3a
--- /dev/null
+++ b/priv/repo/migrations/20220814161100_fix_shifts_user_id_reference.exs
@@ -0,0 +1,19 @@
+defmodule Shift73k.Repo.Migrations.FixShiftsUserIdReference do
+  use Ecto.Migration
+
+  def up do
+    execute("ALTER TABLE shifts DROP CONSTRAINT shifts_user_id_fkey")
+
+    alter table(:shifts) do
+      modify :user_id, references(:users, on_delete: :delete_all, type: :binary_id)
+    end
+  end
+
+  def down do
+    execute("ALTER TABLE shifts DROP CONSTRAINT shifts_user_id_fkey")
+
+    alter table(:shifts) do
+      modify :user_id, references(:users, on_delete: :nothing, type: :binary_id)
+    end
+  end
+end