diff --git a/.circleci/config.yml b/.circleci/config.yml
index 9f7a25b6..a10030c2 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -71,7 +71,7 @@ jobs:
   rspec:
     executor:
       name: test_executor
-    
+
     environment:
       PHOENIX_URI: http://localhost:4000
 
@@ -123,6 +123,9 @@ jobs:
     executor:
       name: test_executor
 
+    environment:
+      - CC_TEST_REPORTER_ID: "a561562e78b6f0b3e346d4811eef2b020f977cd089bf459f102f6229dd100703"
+
     steps:
       - restore_cache:
           key: repo-{{ .Environment.CIRCLE_SHA1 }}
diff --git a/.env_login b/.env_login
index 42d5b0d4..56b421dd 100644
--- a/.env_login
+++ b/.env_login
@@ -6,5 +6,3 @@ export LOGOUT_REDIRECT_EVAL_URL=http://localhost:3000/
 export PHOENIX_URI="http://localhost:4000"
 export LOGIN_SECRET="f4d3c40a00a8e6ed72fae5204d9ddacd40f087865d40803a6fcfb935591a271838533f06081067dac24c0085c74123e7e1c8b3e0ab562c6645b17eb769854d0d"
 export JWT_SECRET="fc28c5738ca45162f61126e770a8fbdbd938d0fedcfe8fbb9f851b855b0264866364a9130e96aca8b1977e9f58edf064f1aa435ceccf415ff22fd3c24adba320"
-
-export APP_DOMAIN="localhost"
diff --git a/.envrc b/.envrc
index 4fbb075a..dd85f90b 100644
--- a/.envrc
+++ b/.envrc
@@ -5,5 +5,8 @@ use nix
 mkdir -p .nix-bundler
 export BUNDLE_PATH=./.nix-bundler
 
+# hook for rbenv locally
+which rbenv &> /dev/null && eval "$(rbenv init - -zsh)"
+
 # Login Env Vars
 source .env_login
diff --git a/Gemfile b/Gemfile
index e4893ae2..1bedb549 100644
--- a/Gemfile
+++ b/Gemfile
@@ -5,13 +5,13 @@ source "https://rubygems.org"
 ruby "3.2.4"
 
 # Bundle edge Rails instead: gem "rails", github: "rails/rails", branch: "main"
-gem "rails", "~> 7.2.0"
+gem "rails", "~> 7.2.1", ">= 7.2.1.1"
 
 # Use postgresql as the database for Active Record
 gem "pg"
 
 # Use the Puma web server [https://github.com/puma/puma]
-gem "puma", ">= 5.0"
+gem "puma", ">= 6.4.3"
 
 # Use the popular Faraday HTTP library
 gem "faraday"
@@ -20,7 +20,7 @@ gem "faraday"
 gem "jwt"
 
 # Use simple asset pipeline
-gem "propshaft", "~> 0.9.1"
+gem "propshaft", "~> 1.1.0"
 gem "cssbundling-rails", "~> 1.4"
 gem "jsbundling-rails", "~> 1.3"
 
@@ -59,9 +59,6 @@ group :development, :test do
 
   gem 'pry'
 
-  # add the Ruby LSP package so it's bundled with the rest of the gems and available to VS Code
-  gem "ruby-lsp"
-
   # rubocop and specific extensions used by VS Code
   gem "rubocop", ">= 1.66.0"
   gem "rubocop-performance", require: false
diff --git a/Gemfile.lock b/Gemfile.lock
index 0a442425..d7b75653 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -1,29 +1,29 @@
 GEM
   remote: https://rubygems.org/
   specs:
-    actioncable (7.2.1)
-      actionpack (= 7.2.1)
-      activesupport (= 7.2.1)
+    actioncable (7.2.1.2)
+      actionpack (= 7.2.1.2)
+      activesupport (= 7.2.1.2)
       nio4r (~> 2.0)
       websocket-driver (>= 0.6.1)
       zeitwerk (~> 2.6)
-    actionmailbox (7.2.1)
-      actionpack (= 7.2.1)
-      activejob (= 7.2.1)
-      activerecord (= 7.2.1)
-      activestorage (= 7.2.1)
-      activesupport (= 7.2.1)
+    actionmailbox (7.2.1.2)
+      actionpack (= 7.2.1.2)
+      activejob (= 7.2.1.2)
+      activerecord (= 7.2.1.2)
+      activestorage (= 7.2.1.2)
+      activesupport (= 7.2.1.2)
       mail (>= 2.8.0)
-    actionmailer (7.2.1)
-      actionpack (= 7.2.1)
-      actionview (= 7.2.1)
-      activejob (= 7.2.1)
-      activesupport (= 7.2.1)
+    actionmailer (7.2.1.2)
+      actionpack (= 7.2.1.2)
+      actionview (= 7.2.1.2)
+      activejob (= 7.2.1.2)
+      activesupport (= 7.2.1.2)
       mail (>= 2.8.0)
       rails-dom-testing (~> 2.2)
-    actionpack (7.2.1)
-      actionview (= 7.2.1)
-      activesupport (= 7.2.1)
+    actionpack (7.2.1.2)
+      actionview (= 7.2.1.2)
+      activesupport (= 7.2.1.2)
       nokogiri (>= 1.8.5)
       racc
       rack (>= 2.2.4, < 3.2)
@@ -32,35 +32,35 @@ GEM
       rails-dom-testing (~> 2.2)
       rails-html-sanitizer (~> 1.6)
       useragent (~> 0.16)
-    actiontext (7.2.1)
-      actionpack (= 7.2.1)
-      activerecord (= 7.2.1)
-      activestorage (= 7.2.1)
-      activesupport (= 7.2.1)
+    actiontext (7.2.1.2)
+      actionpack (= 7.2.1.2)
+      activerecord (= 7.2.1.2)
+      activestorage (= 7.2.1.2)
+      activesupport (= 7.2.1.2)
       globalid (>= 0.6.0)
       nokogiri (>= 1.8.5)
-    actionview (7.2.1)
-      activesupport (= 7.2.1)
+    actionview (7.2.1.2)
+      activesupport (= 7.2.1.2)
       builder (~> 3.1)
       erubi (~> 1.11)
       rails-dom-testing (~> 2.2)
       rails-html-sanitizer (~> 1.6)
-    activejob (7.2.1)
-      activesupport (= 7.2.1)
+    activejob (7.2.1.2)
+      activesupport (= 7.2.1.2)
       globalid (>= 0.3.6)
-    activemodel (7.2.1)
-      activesupport (= 7.2.1)
-    activerecord (7.2.1)
-      activemodel (= 7.2.1)
-      activesupport (= 7.2.1)
+    activemodel (7.2.1.2)
+      activesupport (= 7.2.1.2)
+    activerecord (7.2.1.2)
+      activemodel (= 7.2.1.2)
+      activesupport (= 7.2.1.2)
       timeout (>= 0.4.0)
-    activestorage (7.2.1)
-      actionpack (= 7.2.1)
-      activejob (= 7.2.1)
-      activerecord (= 7.2.1)
-      activesupport (= 7.2.1)
+    activestorage (7.2.1.2)
+      actionpack (= 7.2.1.2)
+      activejob (= 7.2.1.2)
+      activerecord (= 7.2.1.2)
+      activesupport (= 7.2.1.2)
       marcel (~> 1.0)
-    activesupport (7.2.1)
+    activesupport (7.2.1.2)
       base64
       bigdecimal
       concurrent-ruby (~> 1.0, >= 1.3.1)
@@ -77,12 +77,14 @@ GEM
       activerecord (>= 3.2, < 8.0)
       rake (>= 10.4, < 14.0)
     ast (2.4.2)
-    axe-core-api (4.10.0)
+    axe-core-api (4.10.1)
       dumb_delegator
+      ostruct
       virtus
-    axe-core-rspec (4.10.0)
-      axe-core-api (= 4.10.0)
+    axe-core-rspec (4.10.1)
+      axe-core-api (= 4.10.1)
       dumb_delegator
+      ostruct
       virtus
     axiom-types (0.1.1)
       descendants_tracker (~> 0.0.4)
@@ -129,7 +131,7 @@ GEM
     erubi (1.13.0)
     factory_bot (6.5.0)
       activesupport (>= 5.0.0)
-    faker (3.4.2)
+    faker (3.5.1)
       i18n (>= 1.8.11, < 2)
     faraday (2.12.0)
       faraday-net_http (>= 2.0, < 3.4)
@@ -153,12 +155,12 @@ GEM
       activesupport (>= 5.0.0)
     jsbundling-rails (1.3.1)
       railties (>= 6.0.0)
-    json (2.7.2)
+    json (2.7.4)
     jwt (2.9.3)
       base64
     language_server-protocol (3.17.0.3)
     logger (1.6.1)
-    loofah (2.22.0)
+    loofah (2.23.1)
       crass (~> 1.0.2)
       nokogiri (>= 1.12.0)
     mail (2.8.1)
@@ -174,7 +176,7 @@ GEM
     msgpack (1.7.3)
     net-http (0.4.1)
       uri
-    net-imap (0.4.17)
+    net-imap (0.5.0)
       date
       net-protocol
     net-pop (0.1.2)
@@ -196,13 +198,13 @@ GEM
       racc (~> 1.4)
     nokogiri (1.16.7-x86_64-linux)
       racc (~> 1.4)
+    ostruct (0.6.0)
     parallel (1.26.3)
     parser (3.3.5.0)
       ast (~> 2.4.1)
       racc
-    pg (1.5.8)
-    prism (1.2.0)
-    propshaft (0.9.1)
+    pg (1.5.9)
+    propshaft (1.1.0)
       actionpack (>= 7.0.0)
       activesupport (>= 7.0.0)
       rack
@@ -224,20 +226,20 @@ GEM
     rackup (2.1.0)
       rack (>= 3)
       webrick (~> 1.8)
-    rails (7.2.1)
-      actioncable (= 7.2.1)
-      actionmailbox (= 7.2.1)
-      actionmailer (= 7.2.1)
-      actionpack (= 7.2.1)
-      actiontext (= 7.2.1)
-      actionview (= 7.2.1)
-      activejob (= 7.2.1)
-      activemodel (= 7.2.1)
-      activerecord (= 7.2.1)
-      activestorage (= 7.2.1)
-      activesupport (= 7.2.1)
+    rails (7.2.1.2)
+      actioncable (= 7.2.1.2)
+      actionmailbox (= 7.2.1.2)
+      actionmailer (= 7.2.1.2)
+      actionpack (= 7.2.1.2)
+      actiontext (= 7.2.1.2)
+      actionview (= 7.2.1.2)
+      activejob (= 7.2.1.2)
+      activemodel (= 7.2.1.2)
+      activerecord (= 7.2.1.2)
+      activestorage (= 7.2.1.2)
+      activesupport (= 7.2.1.2)
       bundler (>= 1.15.0)
-      railties (= 7.2.1)
+      railties (= 7.2.1.2)
     rails-controller-testing (1.0.5)
       actionpack (>= 5.0.1.rc1)
       actionview (>= 5.0.1.rc1)
@@ -249,9 +251,9 @@ GEM
     rails-html-sanitizer (1.6.0)
       loofah (~> 2.21)
       nokogiri (~> 1.14)
-    railties (7.2.1)
-      actionpack (= 7.2.1)
-      activesupport (= 7.2.1)
+    railties (7.2.1.2)
+      actionpack (= 7.2.1.2)
+      activesupport (= 7.2.1.2)
       irb (~> 1.13)
       rackup (>= 1.0.0)
       rake (>= 12.2)
@@ -259,15 +261,13 @@ GEM
       zeitwerk (~> 2.6)
     rainbow (3.1.1)
     rake (13.2.1)
-    rbs (3.6.1)
-      logger
     rdoc (6.7.0)
       psych (>= 4.0.0)
     regexp_parser (2.9.2)
     reline (0.5.10)
       io-console (~> 0.5)
-    rexml (3.3.8)
-    rspec-core (3.13.1)
+    rexml (3.3.9)
+    rspec-core (3.13.2)
       rspec-support (~> 3.13.0)
     rspec-expectations (3.13.3)
       diff-lcs (>= 1.2.0, < 2.0)
@@ -286,7 +286,7 @@ GEM
     rspec-support (3.13.1)
     rspec_junit_formatter (0.6.0)
       rspec-core (>= 2, < 4, != 2.12.0)
-    rubocop (1.66.1)
+    rubocop (1.67.0)
       json (~> 2.3)
       language_server-protocol (>= 3.17.0)
       parallel (~> 1.10)
@@ -303,20 +303,15 @@ GEM
     rubocop-performance (1.22.1)
       rubocop (>= 1.48.1, < 2.0)
       rubocop-ast (>= 1.31.1, < 2.0)
-    rubocop-rails (2.26.2)
+    rubocop-rails (2.27.0)
       activesupport (>= 4.2.0)
       rack (>= 1.1)
       rubocop (>= 1.52.0, < 2.0)
       rubocop-ast (>= 1.31.1, < 2.0)
     rubocop-rake (0.6.0)
       rubocop (~> 1.0)
-    rubocop-rspec (3.1.0)
+    rubocop-rspec (3.2.0)
       rubocop (~> 1.61)
-    ruby-lsp (0.20.0)
-      language_server-protocol (~> 3.17.0)
-      prism (>= 1.2, < 2.0)
-      rbs (>= 3, < 4)
-      sorbet-runtime (>= 0.5.10782)
     ruby-progressbar (1.13.0)
     rubyzip (2.3.2)
     securerandom (0.3.1)
@@ -331,14 +326,13 @@ GEM
       json (>= 1.8, < 3)
       simplecov-html (~> 0.10.0)
     simplecov-html (0.10.2)
-    sorbet-runtime (0.5.11602)
     stimulus-rails (1.3.4)
       railties (>= 6.0.0)
     stringio (3.1.1)
     thor (1.3.2)
     thread_safe (0.3.6)
     timeout (0.4.1)
-    turbo-rails (2.0.10)
+    turbo-rails (2.0.11)
       actionpack (>= 6.0.0)
       railties (>= 6.0.0)
     tzinfo (2.0.6)
@@ -366,7 +360,7 @@ GEM
     websocket-extensions (0.1.5)
     xpath (3.2.0)
       nokogiri (~> 1.8)
-    zeitwerk (2.7.0)
+    zeitwerk (2.7.1)
 
 PLATFORMS
   aarch64-linux
@@ -392,10 +386,10 @@ DEPENDENCIES
   jsbundling-rails (~> 1.3)
   jwt
   pg
-  propshaft (~> 0.9.1)
+  propshaft (~> 1.1.0)
   pry
-  puma (>= 5.0)
-  rails (~> 7.2.0)
+  puma (>= 6.4.3)
+  rails (~> 7.2.1, >= 7.2.1.1)
   rails-controller-testing
   rspec-rails
   rspec_junit_formatter
@@ -405,7 +399,6 @@ DEPENDENCIES
   rubocop-rails (>= 2.26.0)
   rubocop-rake
   rubocop-rspec
-  ruby-lsp
   selenium-webdriver (>= 4.24.0)
   simplecov (~> 0.17.0)
   stimulus-rails
diff --git a/app/controllers/evaluation_forms_controller.rb b/app/controllers/evaluation_forms_controller.rb
index 0827796d..e0cd999c 100644
--- a/app/controllers/evaluation_forms_controller.rb
+++ b/app/controllers/evaluation_forms_controller.rb
@@ -41,7 +41,7 @@ def update
     respond_to do |format|
       if @evaluation_form.update(evaluation_form_params)
         format.html do
-          redirect_to evaluation_form_url(@evaluation_form), notice: I18n.t("evaluation_form_saved")
+          redirect_to evaluation_forms_url, notice: I18n.t("evaluation_form_saved")
         end
         format.json { render :show, status: :ok, location: @evaluation_form }
       else
diff --git a/app/controllers/manage_submissions_controller.rb b/app/controllers/manage_submissions_controller.rb
index e684cb41..318a1911 100644
--- a/app/controllers/manage_submissions_controller.rb
+++ b/app/controllers/manage_submissions_controller.rb
@@ -2,5 +2,7 @@
 
 class ManageSubmissionsController < ApplicationController
   before_action -> { authorize_user('challenge_manager') }
-  def index; end
+  def index
+    @challenges = current_user.challenge_manager_challenges
+  end
 end
diff --git a/app/helpers/dashboard_helper.rb b/app/helpers/dashboard_helper.rb
index d3e201ca..515b190c 100644
--- a/app/helpers/dashboard_helper.rb
+++ b/app/helpers/dashboard_helper.rb
@@ -7,7 +7,8 @@ def dashboard_cards_by_role
         { image_path: 'emoji_events', href: Rails.configuration.phx_interop[:phx_uri],
           alt: 'challenges', title: 'Challenges', subtitle: 'Create and manage challenges.' },
         { image_path: 'star_half', href: 'manage_submissions',
-          alt: 'submissions', title: 'Submissions', subtitle: 'Manage submissions, evaluations, and evaluators.' },
+          alt: 'submissions and evaluations', title: 'Submissions & Evaluations', subtitle:
+           'Manage submissions, evaluations, and evaluators.' },
         { image_path: 'check_circle_outline', href: 'evaluation_forms',
           alt: 'evaluation forms', title: 'Evaluation Forms', subtitle: 'Create and manage evaluation forms.' },
         { image_path: 'mail', href: "#{Rails.configuration.phx_interop[:phx_uri]}/messages",
@@ -19,7 +20,7 @@ def dashboard_cards_by_role
       ],
       evaluator: [
         { image_path: 'star_half', href: 'evaluations',
-          alt: 'submissions', title: 'Submissions',
+          alt: 'submissions and evaluations', title: 'Submissions & Evaluations',
           subtitle: 'View submissions assigned to me and provide evaluations.' },
         { image_path: 'support', href: 'https://www.challenge.gov/cm-user-guide/',
           alt: 'resources', title: 'Resources', subtitle: 'Learn how to make the most of the platform.' }
diff --git a/app/helpers/evaluation_forms_helper.rb b/app/helpers/evaluation_forms_helper.rb
index 94420370..ed34b279 100644
--- a/app/helpers/evaluation_forms_helper.rb
+++ b/app/helpers/evaluation_forms_helper.rb
@@ -33,4 +33,8 @@ def criteria_field_name(form, attribute, is_template)
       "#{prefix}[#{form.options[:child_index]}][#{attribute}]"
     end
   end
+
+  def eval_form_disabled?(evaluation_form)
+    evaluation_form.valid? && evaluation_form.phase.end_date < Time.zone.today
+  end
 end
diff --git a/app/helpers/navigation_helper.rb b/app/helpers/navigation_helper.rb
index 7d0a6687..d1d21798 100644
--- a/app/helpers/navigation_helper.rb
+++ b/app/helpers/navigation_helper.rb
@@ -1,14 +1,15 @@
 # frozen_string_literal: true
 
 module NavigationHelper
-  def utility_menu_link(image_path, href, alt, button_label)
+  def utility_menu_link(image_path, href, _alt, button_label)
     link_to(href,
             class: "display-flex flex-align-center flex-column desktop:flex-row " \
-                   "margin-x-1 desktop:margin-x-3 text-white text-no-wrap") do
+                   "margin-x-1 desktop:margin-x-3 text-white
+                    width-9 tablet:width-auto tablet:text-no-wrap text-center") do
       image_tag(
         "images/usa-icons/#{image_path}.svg",
         class: "usa-icon--size-4 desktop:usa-icon--size-3 icon-white desktop:margin-right-1",
-        alt:
+        alt: ""
       ) +
         tag.span(button_label, class: "display-none desktop:display-block") +
         tag.span(button_label, class: "desktop:display-none", style: "font-size: 0.7rem")
diff --git a/app/models/challenge.rb b/app/models/challenge.rb
index 030552b7..5472be04 100644
--- a/app/models/challenge.rb
+++ b/app/models/challenge.rb
@@ -99,6 +99,9 @@ class Challenge < ApplicationRecord
   has_many :phases, -> { order(:start_date) }, inverse_of: :challenge, dependent: :destroy
   has_many :submissions, dependent: :destroy
   has_many :submission_exports, dependent: :destroy
+  has_many :evaluator_invitations, dependent: :destroy
+  has_many :challenge_phases_evaluators, dependent: :destroy
+  has_many :evaluators, through: :challenge_phases_evaluators, source: :user
 
   # JSON fields
   attribute :types, :jsonb
diff --git a/app/models/challenge_phases_evaluator.rb b/app/models/challenge_phases_evaluator.rb
new file mode 100644
index 00000000..d2389a27
--- /dev/null
+++ b/app/models/challenge_phases_evaluator.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+# == Schema Information
+#
+# Table name: challenge_phases_evaluators
+#
+#  id           :bigint           not null, primary key
+#  challenge_id :bigint           not null
+#  phase_id     :bigint           not null
+#  user_id      :bigint           not null
+#  created_at   :datetime         not null
+#  updated_at   :datetime         not null
+#
+class ChallengePhasesEvaluator < ApplicationRecord
+  belongs_to :challenge
+  belongs_to :phase
+  belongs_to :user
+end
diff --git a/app/models/evaluator_invitation.rb b/app/models/evaluator_invitation.rb
new file mode 100644
index 00000000..42ffa177
--- /dev/null
+++ b/app/models/evaluator_invitation.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+# == Schema Information
+#
+# Table name: evaluator_invitations
+#
+#  id               :bigint           not null, primary key
+#  challenge_id     :bigint           not null
+#  phase_id         :bigint           not null
+#  first_name       :string           not null
+#  last_name        :string           not null
+#  email            :string           not null
+#  last_invite_sent :datetime         not null
+#  created_at       :datetime         not null
+#  updated_at       :datetime         not null
+#
+class EvaluatorInvitation < ApplicationRecord
+  belongs_to :challenge
+  belongs_to :phase
+
+  validates :first_name, presence: true
+  validates :last_name, presence: true
+  validates :email, presence: true, format: { with: URI::MailTo::EMAIL_REGEXP }
+  validates :last_invite_sent, presence: true
+
+  validates :email, uniqueness: { scope: [:challenge_id, :phase_id] }
+end
diff --git a/app/models/phase.rb b/app/models/phase.rb
index 2d773320..bb4193be 100644
--- a/app/models/phase.rb
+++ b/app/models/phase.rb
@@ -24,8 +24,12 @@
 class Phase < ApplicationRecord
   belongs_to :challenge
   # More relations from phoenix app
-  # has_many :submissions
+  has_many :submissions, dependent: :destroy
+  has_one :evaluation_form, dependent: :destroy
   # has_one :winner, class_name: 'PhaseWinner'
+  has_many :evaluator_invitations, dependent: :destroy
+  has_many :challenge_phases_evaluators, dependent: :destroy
+  has_many :evaluators, through: :challenge_phases_evaluators, source: :user
 
   # Attributes
   attribute :uuid, :uuid
diff --git a/app/models/submission.rb b/app/models/submission.rb
new file mode 100644
index 00000000..36b2ec41
--- /dev/null
+++ b/app/models/submission.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+class Submission < ApplicationRecord
+  enum :status, { draft: "draft", submitted: "submitted" }
+  enum :judging_status, { not_selected: "not_selected", selected: "selected", qualified: "qualified", winner: "winner" }
+
+  # Associations
+  belongs_to :submitter, class_name: 'User'
+  belongs_to :challenge
+  belongs_to :phase
+  belongs_to :manager, class_name: 'User'
+
+  # Fields
+  attribute :title, :string
+  attribute :brief_description, :string
+  attribute :description, :string
+  attribute :external_url, :string
+  attribute :terms_accepted, :boolean, default: nil
+  attribute :review_verified, :boolean, default: nil
+
+  # Validations
+  validates :title, presence: true
+end
diff --git a/app/models/user.rb b/app/models/user.rb
index 5f90cd1c..7b182c39 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -48,6 +48,8 @@ class User < ApplicationRecord
            dependent: :destroy
   has_many :submission_documents, class_name: 'Submissions::Document', dependent: :destroy
   has_many :message_context_statuses, dependent: :destroy
+  has_many :challenge_phases_evaluators, dependent: :destroy
+  has_many :evaluated_phases, through: :challenge_phases_evaluators, source: :phase
 
   attribute :role, :string
   attribute :status, :string, default: 'pending'
diff --git a/app/views/dashboard/_dashboard_card.html.erb b/app/views/dashboard/_dashboard_card.html.erb
index 8bc4bf15..1c53778f 100644
--- a/app/views/dashboard/_dashboard_card.html.erb
+++ b/app/views/dashboard/_dashboard_card.html.erb
@@ -5,7 +5,7 @@
         <%= image_tag(
             "images/usa-icons/#{card[:image_path]}.svg",
             class: "usa-icon--size-7 icon-white margin-x-2",
-            alt: card[:alt]
+            alt: ""
         )%>
         <div class="margin-right-2" >
             <h2><%= card[:title] %></h2>
diff --git a/app/views/evaluation_forms/_form.html.erb b/app/views/evaluation_forms/_form.html.erb
index 3cacf9fd..ac43659f 100644
--- a/app/views/evaluation_forms/_form.html.erb
+++ b/app/views/evaluation_forms/_form.html.erb
@@ -15,6 +15,7 @@
       challenge = evaluation_form.challenge
       phase = evaluation_form.phase
       combo_box_default_value = "#{challenge.id}.#{phase.id}.#{phase.end_date.strftime("%m/%d/%Y")}"
+      disabled = eval_form_disabled?(evaluation_form)
     end
   %>
   <ol class="usa-process-list">
@@ -26,7 +27,7 @@
       </p>
       <div>
         <%= form.label :title, class: "usa-label" %>
-        <%= form.text_field :title, maxlength: 150, class: "usa-input", data: {"action": "evaluation-form#validatePresence focusout->evaluation-form#validatePresence"} %>
+        <%= form.text_field :title, maxlength: 150, class: "usa-input", data: {"action": "evaluation-form#validatePresence focusout->evaluation-form#validatePresence"}, disabled: disabled %>
       </div>
 
       <%= inline_error(evaluation_form, :title) %>
@@ -34,7 +35,7 @@
       <label class="usa-label" for="challenge-combo">Select a challenge</label>
       <div class="usa-hint">Choose the challenge this form will evaluate.</div>
       <div class="usa-combo-box" data-default-value="<%= combo_box_default_value %>">
-        <select id="challenge-combo" class="usa-select" name="challenge-combo" data-action="evaluation-form#handleChallengeSelect">
+        <select class="usa-select" <%= if disabled then "disabled" end %> id="challenge-combo" title="challenge-combo" data-action="evaluation-form#handleChallengeSelect">
           <% current_user.challenge_manager_challenges.each do |challenge| %>
             <% challenge.phases.each do |phase| %>
               <option value="<%= "#{challenge.id}.#{phase.id}.#{phase.end_date.strftime("%m/%d/%Y")}" %>"><%= challenge_phase_title(challenge, phase) %></option>
@@ -52,7 +53,7 @@
       <div class="usa-character-count">
         <div class="usa-form-group">
           <%= form.label :instructions, class: "usa-label" %>
-          <%= form.text_area :instructions, class: "usa-textarea usa-character-count__field", maxlength: 3000, rows: "7", data: {"action": "evaluation-form#validatePresence focusout->evaluation-form#validatePresence"} %>
+          <%= form.text_area :instructions, class: "usa-textarea usa-character-count__field", maxlength: 3000, rows: "7", data: {"action": "evaluation-form#validatePresence focusout->evaluation-form#validatePresence"}, disabled: disabled%>
         </div>
         <span id="with-hint-textarea-info" class="usa-character-count__message">You can enter up to 3000 characters</span>
       </div>
@@ -65,7 +66,7 @@
         Build your evaluation criteria and scoring options.
       </p>
       <div class="usa-checkbox">
-        <%= form.check_box :comments_required, class: "usa-checkbox__input", id: "evaluation_form_comments_required" %>
+        <%= form.check_box :comments_required, class: "usa-checkbox__input", id: "evaluation_form_comments_required", disabled: disabled %>
         <label class="usa-checkbox__label" for="evaluation_form_comments_required">
           Require evaluators to provide comments on their scores. (optional)
           <%= image_tag 'images/usa-icons/help_outline.svg', width: 16, height: 16, alt: 'Help for comments required' %>
@@ -80,11 +81,11 @@
           </legend>
           <div class="display-flex flex-row">
             <div class="usa-radio margin-right-205">
-              <input class="usa-radio__input" id="point_scale" type="radio" name="evaluation_form[weighted_scoring]" value="false" <%= 'checked' unless evaluation_form.weighted_scoring %>>
+              <input class="usa-radio__input" id="point_scale" type="radio" name="evaluation_form[weighted_scoring]" value="false" <%= 'checked' unless evaluation_form.weighted_scoring %> <%= 'disabled' unless !disabled %>>
               <label class="usa-radio__label font-sans-xs" for="point_scale">Point Scale</label>
             </div>
             <div class="usa-radio">
-              <input class="usa-radio__input" id="weighted_scale" type="radio" name="evaluation_form[weighted_scoring]" value="true" <%= 'checked' if evaluation_form.weighted_scoring %>>
+              <input class="usa-radio__input" id="weighted_scale" type="radio" name="evaluation_form[weighted_scoring]" value="true" <%= 'checked' if evaluation_form.weighted_scoring %> <%= 'disabled' unless !disabled %>>
               <label class="usa-radio__label font-sans-xs" for="weighted_scale">Weighted Scale (%)</label>
             </div>
           </div>
diff --git a/app/views/evaluation_forms/_table.html.erb b/app/views/evaluation_forms/_table.html.erb
index 27e71b32..f2151c6d 100644
--- a/app/views/evaluation_forms/_table.html.erb
+++ b/app/views/evaluation_forms/_table.html.erb
@@ -10,7 +10,7 @@
       <% @evaluation_forms.each do |evaluation_form| %>
         <tr>
           <th data-label="Form Title" scope="row">
-            <%= link_to evaluation_form do %>
+            <%= link_to edit_evaluation_form_path(evaluation_form) do %>
                 <%= evaluation_form.title %>
             <% end %>    
             </th>
diff --git a/app/views/evaluation_forms/edit.html.erb b/app/views/evaluation_forms/edit.html.erb
index 03d62c26..27efdc86 100644
--- a/app/views/evaluation_forms/edit.html.erb
+++ b/app/views/evaluation_forms/edit.html.erb
@@ -1,5 +1,5 @@
 <% content_for :title, "Editing evaluation form" %>
 
-<h1>Editing evaluation form</h1>
+<h1><%= if eval_form_disabled?(@evaluation_form) then "View" else "Editing" end %> evaluation form</h1>
 
 <%= render "form", evaluation_form: @evaluation_form %>
diff --git a/app/views/layouts/_header.html.erb b/app/views/layouts/_header.html.erb
index e9f70579..b6db8a9f 100644
--- a/app/views/layouts/_header.html.erb
+++ b/app/views/layouts/_header.html.erb
@@ -99,7 +99,7 @@ aria-label="Official website of the United States government"
         <em class="usa-logo__text"
           ><a href="/" title="challenge.gov">
           <span class="site-title--long">
-            <img width="300" class="usa-header__logo-img margin-left-4 desktop:margin-left-2 desktop:margin-bottom-2" src="<%= image_path("challenge-logo.svg") %>" alt="challenge logo" />
+            <img width="300" class="usa-header__logo-img desktop:margin-bottom-2" src="<%= image_path("challenge-logo.svg") %>" alt="challenge logo" />
           </span>  
           </a></em
         >
diff --git a/app/views/layouts/_utility_menu.erb b/app/views/layouts/_utility_menu.erb
index cb25a84b..0a770e20 100644
--- a/app/views/layouts/_utility_menu.erb
+++ b/app/views/layouts/_utility_menu.erb
@@ -3,11 +3,11 @@
     <%= utility_menu_link('grid_view', dashboard_path, 'dashboard', 'Dashboard') %>
     <% if current_user.role == "challenge_manager" %>
       <%= utility_menu_link('emoji_events', Rails.configuration.phx_interop[:phx_uri], 'challenges', 'Challenges') %>
-      <%= utility_menu_link('star_half', manage_submissions_path, 'Manage Submissions', 'Submissions') %>
+      <%= utility_menu_link('star_half', manage_submissions_path, 'Manage Submissions and Evaluations', 'Submissions & Evaluations') %>
       <%= utility_menu_link('check_circle_outline', evaluation_forms_path, 'Evaluation Forms', 'Evaluation Forms') %>
     <% end %>
     <% if current_user.role == "evaluator" %>
-      <%= utility_menu_link('star_half', evaluations_path, 'Evaluate Submissions', 'Submissions') %>
+      <%= utility_menu_link('star_half', evaluations_path, 'Evaluate Submissions', 'Submissions & Evaluations') %>
     <% end %>  
     <%= utility_menu_link('support', 'https://www.challenge.gov/cm-user-guide/', 'Resources', 'Resources') %>
     <div class="display-none desktop:display-flex flex-align-center margin-x-1 margin-top-1">
diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb
index c7908dc6..82cc5812 100644
--- a/app/views/layouts/application.html.erb
+++ b/app/views/layouts/application.html.erb
@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <html lang="en">
   <head>
-    <title>RailsNew</title>
+    <title>Challenge.gov</title>
     <meta name="viewport" content="width=device-width,initial-scale=1">
     <%= csrf_meta_tags %>
     <%= csp_meta_tag %>
diff --git a/app/views/manage_submissions/_table.html.erb b/app/views/manage_submissions/_table.html.erb
new file mode 100644
index 00000000..674aa9f7
--- /dev/null
+++ b/app/views/manage_submissions/_table.html.erb
@@ -0,0 +1,52 @@
+<table class="usa-table usa-table--stacked-header usa-table--borderless width-full">
+    <thead>
+      <tr>
+        <th scope="col">Challenge</th>
+        <th scope="col">Number of Submissions</th>
+        <th scope="col">Evaluation Form</th>
+        <th scope="col">Evaluations are due by</th>
+      </tr>
+    </thead>
+    <tbody>
+      <% @challenges.each do |challenge| %>
+        <% challenge.phases.each do |phase| %>
+          <tr>
+            <th data-label="Form Title" scope="row">
+              <%= challenge_phase_title(challenge, phase) %>
+              </th>
+            <td data-label="Number of Submissions">
+              <%= phase.submissions.length %>
+            </td>
+            <td data-label="Evaluation Form">
+              <% if phase.evaluation_form %>
+                <%= link_to edit_evaluation_form_path(phase.evaluation_form) do %>
+                  <%= phase.evaluation_form.title %>
+              <% end %>    
+              <% else %>
+                N/A  
+              <% end %>  
+            </td>
+            <td data-label="Evaluations are due by">
+              <% if phase.evaluation_form %>
+                <%= phase.evaluation_form.closing_date %>
+              <% else %>
+                N/A  
+              <% end %>  
+            </td>
+            <td>
+              <div class="display-flex flex-no-wrap grid-row grid-gap-1">
+                <button class="usa-button font-body-2xs text-no-wrap">
+                  Manage Evaluators
+                </button>
+                <% unless phase.submissions.empty? %>
+                  <button class="usa-button font-body-2xs text-no-wrap">
+                    View Submissions
+                  </button>
+                <% end %>  
+              </div>  
+            </td>  
+          </tr>
+        <% end %>  
+      <% end %>  
+    </tbody>
+  </table>
\ No newline at end of file
diff --git a/app/views/manage_submissions/index.html.erb b/app/views/manage_submissions/index.html.erb
index d3797af9..bbf6ceae 100644
--- a/app/views/manage_submissions/index.html.erb
+++ b/app/views/manage_submissions/index.html.erb
@@ -1,7 +1,10 @@
-<div class="usa-card__container col-md-6">
-  <div class="usa-card__body">
-    <h1>Manage Submissions</h1>
+<h1>Submissions & Evaluations</h1>
+<p class="text-normal">View challenge submissions and manage your list of evaluators for each challenge.</p>
 
-    <p>Placeholder text for Manage Submissions.</p>
+<% if @challenges.empty? %>
+  <div class="text-normal">
+    <p>You currently do not have any challenges.</p>
   </div>
-</div>
\ No newline at end of file
+<% else %>
+  <%= render partial: "table", locals: { challenges: @challenges } %>
+<% end %>  
\ No newline at end of file
diff --git a/config/application.rb b/config/application.rb
index 342165ce..5aeb8cb4 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -8,7 +8,7 @@
 # you've limited to :test, :development, or :production.
 Bundler.require(*Rails.groups)
 
-module RailsNew
+module ChallengePlatform
   class Application < Rails::Application
     # Initialize configuration defaults for originally generated Rails version.
     config.load_defaults 7.1
diff --git a/db/migrate/20241001143033_change_null_values_on_evaluation_forms.rb b/db/migrate/20241001143033_change_null_values_on_evaluation_forms.rb
index e0b1be3b..e3fc8f30 100644
--- a/db/migrate/20241001143033_change_null_values_on_evaluation_forms.rb
+++ b/db/migrate/20241001143033_change_null_values_on_evaluation_forms.rb
@@ -1,5 +1,8 @@
 class ChangeNullValuesOnEvaluationForms < ActiveRecord::Migration[7.2]
   def change
+    # reset both tables due to foreign_key constraint
+    execute('DELETE FROM evaluation_criteria;')
+    execute('DELETE FROM evaluation_forms;')
     change_column_null :evaluation_forms, :title, false
     change_column_null :evaluation_forms, :instructions, false
     change_column_null :evaluation_forms, :challenge_phase, false
diff --git a/db/migrate/20241014214843_create_challenge_phases_evaluators.rb b/db/migrate/20241014214843_create_challenge_phases_evaluators.rb
new file mode 100644
index 00000000..50e365fa
--- /dev/null
+++ b/db/migrate/20241014214843_create_challenge_phases_evaluators.rb
@@ -0,0 +1,11 @@
+class CreateChallengePhasesEvaluators < ActiveRecord::Migration[7.2]
+  def change
+    create_table :challenge_phases_evaluators do |t|
+      t.references :challenge, null: false, foreign_key: true
+      t.references :phase, null: false, foreign_key: true
+      t.references :user, null: false, foreign_key: true
+
+      t.timestamps
+    end
+  end
+end
diff --git a/db/migrate/20241018150049_create_evaluator_invitations.rb b/db/migrate/20241018150049_create_evaluator_invitations.rb
new file mode 100644
index 00000000..865db7fa
--- /dev/null
+++ b/db/migrate/20241018150049_create_evaluator_invitations.rb
@@ -0,0 +1,16 @@
+class CreateEvaluatorInvitations < ActiveRecord::Migration[7.2]
+  def change
+    create_table :evaluator_invitations do |t|
+      t.references :challenge, null: false, foreign_key: true
+      t.references :phase, null: false, foreign_key: true
+      t.string :first_name, null: false
+      t.string :last_name, null: false
+      t.string :email, null: false
+      t.datetime :last_invite_sent
+
+      t.timestamps
+    end
+
+    add_index :evaluator_invitations, [:challenge_id, :phase_id, :email], unique: true
+  end
+end
diff --git a/db/structure.sql b/db/structure.sql
index 668ac499..11f62eb6 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -183,6 +183,39 @@ CREATE SEQUENCE public.challenge_owners_id_seq
 ALTER SEQUENCE public.challenge_owners_id_seq OWNED BY public.challenge_managers.id;
 
 
+--
+-- Name: challenge_phases_evaluators; Type: TABLE; Schema: public; Owner: -
+--
+
+CREATE TABLE public.challenge_phases_evaluators (
+    id bigint NOT NULL,
+    challenge_id bigint NOT NULL,
+    phase_id bigint NOT NULL,
+    user_id bigint NOT NULL,
+    created_at timestamp(6) without time zone NOT NULL,
+    updated_at timestamp(6) without time zone NOT NULL
+);
+
+
+--
+-- Name: challenge_phases_evaluators_id_seq; Type: SEQUENCE; Schema: public; Owner: -
+--
+
+CREATE SEQUENCE public.challenge_phases_evaluators_id_seq
+    START WITH 1
+    INCREMENT BY 1
+    NO MINVALUE
+    NO MAXVALUE
+    CACHE 1;
+
+
+--
+-- Name: challenge_phases_evaluators_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
+--
+
+ALTER SEQUENCE public.challenge_phases_evaluators_id_seq OWNED BY public.challenge_phases_evaluators.id;
+
+
 --
 -- Name: challenges; Type: TABLE; Schema: public; Owner: -
 --
@@ -397,6 +430,42 @@ CREATE SEQUENCE public.evaluation_forms_id_seq
 ALTER SEQUENCE public.evaluation_forms_id_seq OWNED BY public.evaluation_forms.id;
 
 
+--
+-- Name: evaluator_invitations; Type: TABLE; Schema: public; Owner: -
+--
+
+CREATE TABLE public.evaluator_invitations (
+    id bigint NOT NULL,
+    challenge_id bigint NOT NULL,
+    phase_id bigint NOT NULL,
+    first_name character varying NOT NULL,
+    last_name character varying NOT NULL,
+    email character varying NOT NULL,
+    last_invite_sent timestamp(6) without time zone,
+    created_at timestamp(6) without time zone NOT NULL,
+    updated_at timestamp(6) without time zone NOT NULL
+);
+
+
+--
+-- Name: evaluator_invitations_id_seq; Type: SEQUENCE; Schema: public; Owner: -
+--
+
+CREATE SEQUENCE public.evaluator_invitations_id_seq
+    START WITH 1
+    INCREMENT BY 1
+    NO MINVALUE
+    NO MAXVALUE
+    CACHE 1;
+
+
+--
+-- Name: evaluator_invitations_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
+--
+
+ALTER SEQUENCE public.evaluator_invitations_id_seq OWNED BY public.evaluator_invitations.id;
+
+
 --
 -- Name: federal_partners; Type: TABLE; Schema: public; Owner: -
 --
@@ -1161,6 +1230,13 @@ ALTER TABLE ONLY public.certification_log ALTER COLUMN id SET DEFAULT nextval('p
 ALTER TABLE ONLY public.challenge_managers ALTER COLUMN id SET DEFAULT nextval('public.challenge_owners_id_seq'::regclass);
 
 
+--
+-- Name: challenge_phases_evaluators id; Type: DEFAULT; Schema: public; Owner: -
+--
+
+ALTER TABLE ONLY public.challenge_phases_evaluators ALTER COLUMN id SET DEFAULT nextval('public.challenge_phases_evaluators_id_seq'::regclass);
+
+
 --
 -- Name: challenges id; Type: DEFAULT; Schema: public; Owner: -
 --
@@ -1189,6 +1265,13 @@ ALTER TABLE ONLY public.evaluation_criteria ALTER COLUMN id SET DEFAULT nextval(
 ALTER TABLE ONLY public.evaluation_forms ALTER COLUMN id SET DEFAULT nextval('public.evaluation_forms_id_seq'::regclass);
 
 
+--
+-- Name: evaluator_invitations id; Type: DEFAULT; Schema: public; Owner: -
+--
+
+ALTER TABLE ONLY public.evaluator_invitations ALTER COLUMN id SET DEFAULT nextval('public.evaluator_invitations_id_seq'::regclass);
+
+
 --
 -- Name: federal_partners id; Type: DEFAULT; Schema: public; Owner: -
 --
@@ -1362,6 +1445,14 @@ ALTER TABLE ONLY public.challenge_managers
     ADD CONSTRAINT challenge_owners_pkey PRIMARY KEY (id);
 
 
+--
+-- Name: challenge_phases_evaluators challenge_phases_evaluators_pkey; Type: CONSTRAINT; Schema: public; Owner: -
+--
+
+ALTER TABLE ONLY public.challenge_phases_evaluators
+    ADD CONSTRAINT challenge_phases_evaluators_pkey PRIMARY KEY (id);
+
+
 --
 -- Name: challenges challenges_pkey; Type: CONSTRAINT; Schema: public; Owner: -
 --
@@ -1394,6 +1485,14 @@ ALTER TABLE ONLY public.evaluation_forms
     ADD CONSTRAINT evaluation_forms_pkey PRIMARY KEY (id);
 
 
+--
+-- Name: evaluator_invitations evaluator_invitations_pkey; Type: CONSTRAINT; Schema: public; Owner: -
+--
+
+ALTER TABLE ONLY public.evaluator_invitations
+    ADD CONSTRAINT evaluator_invitations_pkey PRIMARY KEY (id);
+
+
 --
 -- Name: federal_partners federal_partners_pkey; Type: CONSTRAINT; Schema: public; Owner: -
 --
@@ -1584,6 +1683,34 @@ CREATE UNIQUE INDEX agency_members_user_id_index ON public.agency_members USING
 CREATE UNIQUE INDEX challenges_custom_url_index ON public.challenges USING btree (custom_url);
 
 
+--
+-- Name: idx_on_challenge_id_phase_id_email_b0ae3723d2; Type: INDEX; Schema: public; Owner: -
+--
+
+CREATE UNIQUE INDEX idx_on_challenge_id_phase_id_email_b0ae3723d2 ON public.evaluator_invitations USING btree (challenge_id, phase_id, email);
+
+
+--
+-- Name: index_challenge_phases_evaluators_on_challenge_id; Type: INDEX; Schema: public; Owner: -
+--
+
+CREATE INDEX index_challenge_phases_evaluators_on_challenge_id ON public.challenge_phases_evaluators USING btree (challenge_id);
+
+
+--
+-- Name: index_challenge_phases_evaluators_on_phase_id; Type: INDEX; Schema: public; Owner: -
+--
+
+CREATE INDEX index_challenge_phases_evaluators_on_phase_id ON public.challenge_phases_evaluators USING btree (phase_id);
+
+
+--
+-- Name: index_challenge_phases_evaluators_on_user_id; Type: INDEX; Schema: public; Owner: -
+--
+
+CREATE INDEX index_challenge_phases_evaluators_on_user_id ON public.challenge_phases_evaluators USING btree (user_id);
+
+
 --
 -- Name: index_evaluation_criteria_on_evaluation_form_id; Type: INDEX; Schema: public; Owner: -
 --
@@ -1605,6 +1732,20 @@ CREATE INDEX index_evaluation_forms_on_challenge_id ON public.evaluation_forms U
 CREATE INDEX index_evaluation_forms_on_phase_id ON public.evaluation_forms USING btree (phase_id);
 
 
+--
+-- Name: index_evaluator_invitations_on_challenge_id; Type: INDEX; Schema: public; Owner: -
+--
+
+CREATE INDEX index_evaluator_invitations_on_challenge_id ON public.evaluator_invitations USING btree (challenge_id);
+
+
+--
+-- Name: index_evaluator_invitations_on_phase_id; Type: INDEX; Schema: public; Owner: -
+--
+
+CREATE INDEX index_evaluator_invitations_on_phase_id ON public.evaluator_invitations USING btree (phase_id);
+
+
 --
 -- Name: message_contexts_context_context_id_audience_parent_id_index; Type: INDEX; Schema: public; Owner: -
 --
@@ -1773,6 +1914,14 @@ ALTER TABLE ONLY public.evaluation_forms
     ADD CONSTRAINT fk_rails_1c5ee6cafd FOREIGN KEY (phase_id) REFERENCES public.phases(id);
 
 
+--
+-- Name: challenge_phases_evaluators fk_rails_252b3aeac2; Type: FK CONSTRAINT; Schema: public; Owner: -
+--
+
+ALTER TABLE ONLY public.challenge_phases_evaluators
+    ADD CONSTRAINT fk_rails_252b3aeac2 FOREIGN KEY (user_id) REFERENCES public.users(id);
+
+
 --
 -- Name: evaluation_forms fk_rails_28ad57fb81; Type: FK CONSTRAINT; Schema: public; Owner: -
 --
@@ -1789,6 +1938,38 @@ ALTER TABLE ONLY public.evaluation_criteria
     ADD CONSTRAINT fk_rails_a39b8fa483 FOREIGN KEY (evaluation_form_id) REFERENCES public.evaluation_forms(id);
 
 
+--
+-- Name: challenge_phases_evaluators fk_rails_ba136003c3; Type: FK CONSTRAINT; Schema: public; Owner: -
+--
+
+ALTER TABLE ONLY public.challenge_phases_evaluators
+    ADD CONSTRAINT fk_rails_ba136003c3 FOREIGN KEY (phase_id) REFERENCES public.phases(id);
+
+
+--
+-- Name: evaluator_invitations fk_rails_c4f5e767a9; Type: FK CONSTRAINT; Schema: public; Owner: -
+--
+
+ALTER TABLE ONLY public.evaluator_invitations
+    ADD CONSTRAINT fk_rails_c4f5e767a9 FOREIGN KEY (phase_id) REFERENCES public.phases(id);
+
+
+--
+-- Name: evaluator_invitations fk_rails_d623dba270; Type: FK CONSTRAINT; Schema: public; Owner: -
+--
+
+ALTER TABLE ONLY public.evaluator_invitations
+    ADD CONSTRAINT fk_rails_d623dba270 FOREIGN KEY (challenge_id) REFERENCES public.challenges(id);
+
+
+--
+-- Name: challenge_phases_evaluators fk_rails_e27fcb2d4d; Type: FK CONSTRAINT; Schema: public; Owner: -
+--
+
+ALTER TABLE ONLY public.challenge_phases_evaluators
+    ADD CONSTRAINT fk_rails_e27fcb2d4d FOREIGN KEY (challenge_id) REFERENCES public.challenges(id);
+
+
 --
 -- Name: message_context_statuses message_context_statuses_message_context_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
 --
@@ -1996,8 +2177,10 @@ ALTER TABLE ONLY public.winners
 SET search_path TO "$user", public;
 
 INSERT INTO "schema_migrations" (version) VALUES
+(20241018150049),
 (20241017172408),
 (20241015140056),
+(20241014214843),
 (20241001143033),
 (20240927010020),
 (20240917010803),
diff --git a/spec/factories/challenge.rb b/spec/factories/challenge.rb
index 30ebd428..53b873d5 100644
--- a/spec/factories/challenge.rb
+++ b/spec/factories/challenge.rb
@@ -22,7 +22,7 @@
     end_date { 3.months.from_now }
     auto_publish_date { 1.week.from_now }
     published_on { 2.weeks.from_now }
-    custom_url { Faker::Internet.url(host: "example.com", path: "/custom") }
+    custom_url { Faker::Internet.url(host: "example.com", path: "/custom/#{SecureRandom.hex(8)}") }
     external_url { Faker::Internet.url(host: "example.com", path: "/external") }
     agency_name { Faker::Company.name }
     fiscal_year { "2024" }
diff --git a/spec/factories/challenge_phases_evaluator.rb b/spec/factories/challenge_phases_evaluator.rb
new file mode 100644
index 00000000..73eb8d95
--- /dev/null
+++ b/spec/factories/challenge_phases_evaluator.rb
@@ -0,0 +1,8 @@
+FactoryBot.define do
+  factory :challenge_phases_evaluator do
+    # Associations
+    association :challenge
+    association :phase
+    association :user
+  end
+end
diff --git a/spec/factories/evaluator_invitation.rb b/spec/factories/evaluator_invitation.rb
new file mode 100644
index 00000000..3a08477a
--- /dev/null
+++ b/spec/factories/evaluator_invitation.rb
@@ -0,0 +1,13 @@
+FactoryBot.define do
+  factory :evaluator_invitation do
+    # Associations
+    association :challenge
+    association :phase
+
+    # Fields
+    first_name { Faker::Name.first_name }
+    last_name { Faker::Name.last_name }
+    email { Faker::Internet.email }
+    last_invite_sent { Time.current }
+  end
+end
diff --git a/spec/models/challenge_phases_evaluator_spec.rb b/spec/models/challenge_phases_evaluator_spec.rb
new file mode 100644
index 00000000..b4c720c8
--- /dev/null
+++ b/spec/models/challenge_phases_evaluator_spec.rb
@@ -0,0 +1,54 @@
+require 'rails_helper'
+
+RSpec.describe ChallengePhasesEvaluator, type: :model do
+  let(:challenge) { create(:challenge) }
+  let(:phase) { create(:phase, challenge:) }
+  let(:user) { create(:user, role: :evaluator) }
+
+  it "can be created with valid attributes" do
+    evaluator = build(:challenge_phases_evaluator, challenge:, phase:, user:)
+    expect(evaluator).to be_valid
+    expect { evaluator.save! }.to change { described_class.count }.by(1)
+  end
+
+  it "can be destroyed" do
+    evaluator = create(:challenge_phases_evaluator, challenge:, phase:, user:)
+    expect { evaluator.destroy }.to change { described_class.count }.by(-1)
+  end
+
+  it "associates the user as an evaluator for the challenge" do
+    create(:challenge_phases_evaluator, challenge:, phase:, user:)
+    expect(challenge.evaluators).to include(user)
+  end
+
+  it "requires a challenge" do
+    evaluator = build(:challenge_phases_evaluator, challenge: nil)
+    expect(evaluator).not_to be_valid
+    expect(evaluator.errors[:challenge]).to include("must exist")
+  end
+
+  it "requires a phase" do
+    evaluator = build(:challenge_phases_evaluator, phase: nil)
+    expect(evaluator).not_to be_valid
+    expect(evaluator.errors[:phase]).to include("must exist")
+  end
+
+  it "requires a user" do
+    evaluator = build(:challenge_phases_evaluator, user: nil)
+    expect(evaluator).not_to be_valid
+    expect(evaluator.errors[:user]).to include("must exist")
+  end
+
+  it "allows multiple evaluators for the same challenge and phase" do
+    challenge = create(:challenge)
+    phase = create(:phase, challenge:)
+    user1 = create(:user, role: :evaluator)
+    user2 = create(:user, role: :evaluator)
+
+    create(:challenge_phases_evaluator, challenge:, phase:, user: user1)
+    evaluator2 = build(:challenge_phases_evaluator, challenge:, phase:, user: user2)
+
+    expect(evaluator2).to be_valid
+    expect { evaluator2.save! }.not_to raise_error
+  end
+end
diff --git a/spec/models/evaluator_invitation_spec.rb b/spec/models/evaluator_invitation_spec.rb
new file mode 100644
index 00000000..68e0b82b
--- /dev/null
+++ b/spec/models/evaluator_invitation_spec.rb
@@ -0,0 +1,56 @@
+require 'rails_helper'
+
+RSpec.describe EvaluatorInvitation, type: :model do
+  let(:challenge) { create(:challenge) }
+  let(:phase) { create(:phase, challenge:) }
+
+  it "can be created with valid attributes" do
+    invitation = build(:evaluator_invitation, challenge:, phase:)
+    expect(invitation).to be_valid
+    expect { invitation.save! }.to change { described_class.count }.by(1)
+  end
+
+  it "can be destroyed" do
+    invitation = create(:evaluator_invitation, challenge:, phase:)
+    expect { invitation.destroy }.to change { described_class.count }.by(-1)
+  end
+
+  it "validates uniqueness of email within challenge and phase" do
+    create(:evaluator_invitation, challenge:, phase:, email: "test@example.com")
+    duplicate_invitation = build(:evaluator_invitation, challenge:, phase:, email: "test@example.com")
+    expect(duplicate_invitation).not_to be_valid
+    expect(duplicate_invitation.errors[:email]).to include("has already been taken")
+  end
+
+  it "allows the same email for different challenges or phases" do
+    create(:evaluator_invitation, challenge:, phase:, email: "test@example.com")
+    different_challenge = create(:challenge)
+    different_phase = create(:phase, challenge: different_challenge)
+
+    invitation_different_challenge = build(:evaluator_invitation, challenge: different_challenge, phase:,
+                                                                  email: "test@example.com")
+    expect(invitation_different_challenge).to be_valid
+
+    invitation_different_phase = build(:evaluator_invitation, challenge:, phase: different_phase,
+                                                              email: "test@example.com")
+    expect(invitation_different_phase).to be_valid
+  end
+
+  it "requires a first name" do
+    invitation = build(:evaluator_invitation, first_name: nil)
+    expect(invitation).not_to be_valid
+    expect(invitation.errors[:first_name]).to include("can't be blank")
+  end
+
+  it "requires a last name" do
+    invitation = build(:evaluator_invitation, last_name: nil)
+    expect(invitation).not_to be_valid
+    expect(invitation.errors[:last_name]).to include("can't be blank")
+  end
+
+  it "requires a valid email" do
+    invitation = build(:evaluator_invitation, email: "invalid_email")
+    expect(invitation).not_to be_valid
+    expect(invitation.errors[:email]).to include("is invalid")
+  end
+end
diff --git a/spec/requests/manage_submissions_spec.rb b/spec/requests/manage_submissions_spec.rb
index fe833df5..063fb1a9 100644
--- a/spec/requests/manage_submissions_spec.rb
+++ b/spec/requests/manage_submissions_spec.rb
@@ -27,15 +27,34 @@
     end
 
     context "when logged in as a challenge manager" do
-      before do
-        create_and_log_in_user(role: "challenge_manager")
-      end
+      let(:challenge_user) { create_user(role: "challenge_manager") }
+
+      before { log_in_user(challenge_user) }
 
       it "renders the index view with the correct header" do
         get manage_submissions_path
 
         expect(response).to have_http_status(:success)
-        expect(response.body).to include("Manage Submissions")
+        expect(response.body).to include("Submissions & Evaluations")
+        expect(response.body).to include("View challenge submissions")
+      end
+
+      it "renders an empty list" do
+        get manage_submissions_path
+
+        expect(response.body).to include("You currently do not have any challenges.")
+      end
+
+      it "renders a list of challenges" do
+        agency = Agency.create!(name: "Gandalf and Sons", acronym: "GAD")
+        challenge = Challenge.create!(user: challenge_user, agency:, title: "Turning monster energy into pepto bismol")
+        phase = create_phase(challenge_id: challenge.id)
+        ChallengeManager.create(user: challenge_user, challenge:)
+        create_evaluation_form(title: "Frodo", challenge_id: challenge.id, phase_id: phase.id)
+
+        get manage_submissions_path
+        expect(response.body).to include("Turning monster energy into pepto bismol")
+        expect(response.body).to include("Frodo")
       end
     end