diff --git a/Dockerfile b/Dockerfile
index 932d8b13..a5a8f855 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -50,7 +50,7 @@ ENV OPENSSL_CONF=/app/openssl_legacy.cnf
 
 WORKDIR /app
 
-RUN echo '@edge https://dl-cdn.alpinelinux.org/alpine/edge/community' >> /etc/apk/repositories && apk add --no-cache sqlite-dev libpq-dev mariadb-dev vips-dev@edge redis libheif@edge vips-heif gcompat ttf-freefont && mkdir /fonts && rm /usr/share/fonts/freefont/FreeSans.otf
+RUN echo '@edge https://dl-cdn.alpinelinux.org/alpine/edge/community' >> /etc/apk/repositories && apk add --no-cache sqlite-dev libpq-dev mariadb-dev vips-dev@edge redis libheif@edge vips-heif@edge gcompat ttf-freefont && mkdir /fonts && rm /usr/share/fonts/freefont/FreeSans.otf
 
 RUN echo $'.include = /etc/ssl/openssl.cnf\n\
 \n\
diff --git a/app/controllers/api/templates_controller.rb b/app/controllers/api/templates_controller.rb
index 5e8da098..25c0c537 100644
--- a/app/controllers/api/templates_controller.rb
+++ b/app/controllers/api/templates_controller.rb
@@ -100,6 +100,7 @@ module Api
       permitted_params = [
         :name,
         :external_id,
+        :shared_link,
         {
           submitters: [%i[name uuid is_requester invite_by_uuid optional_invite_by_uuid linked_to_uuid email]],
           fields: [[:uuid, :submitter_uuid, :name, :type,
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index a3cb0242..7500acdb 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -55,6 +55,14 @@ class ApplicationController < ActionController::Base
     request.session[:impersonated_user_id] = user.uuid
   end
 
+  def pagy_auto(collection, **keyword_args)
+    if current_ability.can?(:manage, :countless)
+      pagy_countless(collection, **keyword_args)
+    else
+      pagy(collection, **keyword_args)
+    end
+  end
+
   private
 
   def with_locale(&)
diff --git a/app/controllers/email_smtp_settings_controller.rb b/app/controllers/email_smtp_settings_controller.rb
index d41ca570..766a9545 100644
--- a/app/controllers/email_smtp_settings_controller.rb
+++ b/app/controllers/email_smtp_settings_controller.rb
@@ -9,7 +9,9 @@ class EmailSmtpSettingsController < ApplicationController
 
   def create
     if @encrypted_config.update(email_configs)
-      SettingsMailer.smtp_successful_setup(@encrypted_config.value['from_email'] || current_user.email).deliver_now!
+      unless Docuseal.multitenant?
+        SettingsMailer.smtp_successful_setup(@encrypted_config.value['from_email'] || current_user.email).deliver_now!
+      end
 
       redirect_to settings_email_index_path, notice: I18n.t('changes_have_been_saved')
     else
diff --git a/app/controllers/send_submission_email_controller.rb b/app/controllers/send_submission_email_controller.rb
index 6d1f34c3..ef6ff62b 100644
--- a/app/controllers/send_submission_email_controller.rb
+++ b/app/controllers/send_submission_email_controller.rb
@@ -11,15 +11,15 @@ class SendSubmissionEmailController < ApplicationController
 
   def create
     if params[:template_slug]
-      @submitter = Submitter.joins(submission: :template).find_by!(email: params[:email].to_s.downcase,
-                                                                   template: { slug: params[:template_slug] })
+      @submitter = Submitter.completed.joins(submission: :template).find_by!(email: params[:email].to_s.downcase,
+                                                                             template: { slug: params[:template_slug] })
     elsif params[:submission_slug]
-      @submitter = Submitter.joins(:submission).find_by(email: params[:email].to_s.downcase,
-                                                        submission: { slug: params[:submission_slug] })
+      @submitter = Submitter.completed.joins(:submission).find_by(email: params[:email].to_s.downcase,
+                                                                  submission: { slug: params[:submission_slug] })
 
       return redirect_to submissions_preview_completed_path(params[:submission_slug], status: :error) unless @submitter
     else
-      @submitter = Submitter.find_by!(slug: params[:submitter_slug])
+      @submitter = Submitter.completed.find_by!(slug: params[:submitter_slug])
     end
 
     RateLimit.call("send-email-#{@submitter.id}", limit: 2, ttl: 5.minutes)
diff --git a/app/controllers/start_form_controller.rb b/app/controllers/start_form_controller.rb
index c79535ec..415adab4 100644
--- a/app/controllers/start_form_controller.rb
+++ b/app/controllers/start_form_controller.rb
@@ -8,20 +8,28 @@ class StartFormController < ApplicationController
 
   around_action :with_browser_locale, only: %i[show completed]
   before_action :maybe_redirect_com, only: %i[show completed]
+  before_action :load_resubmit_submitter, only: :update
   before_action :load_template
+  before_action :authorize_start!, only: :update
 
   def show
-    raise ActionController::RoutingError, I18n.t('not_found') if @template.preferences['require_phone_2fa'] == true
+    raise ActionController::RoutingError, I18n.t('not_found') if @template.preferences['require_phone_2fa']
 
-    @submitter = @template.submissions.new(account_id: @template.account_id)
-                          .submitters.new(account_id: @template.account_id,
-                                          uuid: (filter_undefined_submitters(@template).first ||
-                                                 @template.submitters.first)['uuid'])
+    if @template.shared_link?
+      @submitter = @template.submissions.new(account_id: @template.account_id)
+                            .submitters.new(account_id: @template.account_id,
+                                            uuid: (filter_undefined_submitters(@template).first ||
+                                                  @template.submitters.first)['uuid'])
+    else
+      Rollbar.warning("Not shared template: #{@template.id}") if defined?(Rollbar)
+
+      return render :private if current_user && current_ability.can?(:read, @template)
+
+      raise ActionController::RoutingError, I18n.t('not_found')
+    end
   end
 
   def update
-    return redirect_to start_form_path(@template.slug) if @template.archived_at?
-
     @submitter = find_or_initialize_submitter(@template, submitter_params)
 
     if @submitter.completed_at?
@@ -59,6 +67,8 @@ class StartFormController < ApplicationController
   end
 
   def completed
+    return redirect_to start_form_path(@template.slug) if !@template.shared_link? || @template.archived_at?
+
     @submitter = Submitter.where(submission: @template.submissions)
                           .where.not(completed_at: nil)
                           .find_by!(email: params[:email])
@@ -66,6 +76,24 @@ class StartFormController < ApplicationController
 
   private
 
+  def load_resubmit_submitter
+    @resubmit_submitter =
+      if params[:resubmit].present? && !params[:resubmit].in?([true, 'true'])
+        Submitter.find_by(slug: params[:resubmit])
+      end
+  end
+
+  def authorize_start!
+    return redirect_to start_form_path(@template.slug) if @template.archived_at?
+
+    return if @resubmit_submitter
+    return if @template.shared_link? || (current_user && current_ability.can?(:read, @template))
+
+    Rollbar.warning("Not shared template: #{@template.id}") if defined?(Rollbar)
+
+    redirect_to start_form_path(@template.slug)
+  end
+
   def enqueue_submission_create_webhooks(submitter)
     WebhookUrls.for_account_id(submitter.account_id, 'submission.created').each do |webhook_url|
       SendSubmissionCreatedWebhookRequestJob.perform_async('submission_id' => submitter.submission_id,
@@ -74,31 +102,29 @@ class StartFormController < ApplicationController
   end
 
   def find_or_initialize_submitter(template, submitter_params)
-    Submitter.where(submission: template.submissions.where(expire_at: Time.current..)
-                                        .or(template.submissions.where(expire_at: nil)).where(archived_at: nil))
-             .order(id: :desc)
-             .where(declined_at: nil)
-             .where(external_id: nil)
-             .where(ip: [nil, request.remote_ip])
-             .then { |rel| params[:resubmit].present? ? rel.where(completed_at: nil) : rel }
-             .find_or_initialize_by(email: submitter_params[:email], **submitter_params.compact_blank)
+    Submitter
+      .where(submission: template.submissions.where(expire_at: Time.current..)
+                                 .or(template.submissions.where(expire_at: nil)).where(archived_at: nil))
+      .order(id: :desc)
+      .where(declined_at: nil)
+      .where(external_id: nil)
+      .where(ip: [nil, request.remote_ip])
+      .then { |rel| params[:resubmit].present? || params[:selfsign].present? ? rel.where(completed_at: nil) : rel }
+      .find_or_initialize_by(email: submitter_params[:email], **submitter_params.compact_blank)
   end
 
   def assign_submission_attributes(submitter, template)
-    resubmit_submitter =
-      (Submitter.where(submission: template.submissions).find_by(slug: params[:resubmit]) if params[:resubmit].present?)
-
     submitter.assign_attributes(
       uuid: (filter_undefined_submitters(template).first || @template.submitters.first)['uuid'],
       ip: request.remote_ip,
       ua: request.user_agent,
-      values: resubmit_submitter&.preferences&.fetch('default_values', nil) || {},
-      preferences: resubmit_submitter&.preferences.presence || { 'send_email' => true },
-      metadata: resubmit_submitter&.metadata.presence || {}
+      values: @resubmit_submitter&.preferences&.fetch('default_values', nil) || {},
+      preferences: @resubmit_submitter&.preferences.presence || { 'send_email' => true },
+      metadata: @resubmit_submitter&.metadata.presence || {}
     )
 
     if submitter.values.present?
-      resubmit_submitter.attachments.each do |attachment|
+      @resubmit_submitter.attachments.each do |attachment|
         submitter.attachments << attachment.dup if submitter.values.value?(attachment.uuid)
       end
     end
@@ -120,15 +146,21 @@ class StartFormController < ApplicationController
   end
 
   def submitter_params
+    return current_user.slice(:email) if params[:selfsign]
+    return @resubmit_submitter.slice(:name, :phone, :email) if @resubmit_submitter.present?
+
     params.require(:submitter).permit(:email, :phone, :name).tap do |attrs|
       attrs[:email] = Submissions.normalize_email(attrs[:email])
     end
   end
 
   def load_template
-    slug = params[:slug] || params[:start_form_slug]
-
-    @template = Template.find_by!(slug:)
+    @template =
+      if @resubmit_submitter
+        @resubmit_submitter.template
+      else
+        Template.find_by!(slug: params[:slug] || params[:start_form_slug])
+      end
   end
 
   def multiple_submitters_error_message
diff --git a/app/controllers/submissions_archived_controller.rb b/app/controllers/submissions_archived_controller.rb
index f71638c7..3ad5d936 100644
--- a/app/controllers/submissions_archived_controller.rb
+++ b/app/controllers/submissions_archived_controller.rb
@@ -18,6 +18,6 @@ class SubmissionsArchivedController < ApplicationController
                      @submissions.order(id: :desc)
                    end
 
-    @pagy, @submissions = pagy(@submissions.preload(submitters: :start_form_submission_events))
+    @pagy, @submissions = pagy_auto(@submissions.preload(submitters: :start_form_submission_events))
   end
 end
diff --git a/app/controllers/submissions_dashboard_controller.rb b/app/controllers/submissions_dashboard_controller.rb
index 3386edd8..55fb6ae0 100644
--- a/app/controllers/submissions_dashboard_controller.rb
+++ b/app/controllers/submissions_dashboard_controller.rb
@@ -19,6 +19,6 @@ class SubmissionsDashboardController < ApplicationController
                      @submissions.order(id: :desc)
                    end
 
-    @pagy, @submissions = pagy(@submissions.preload(submitters: :start_form_submission_events))
+    @pagy, @submissions = pagy_auto(@submissions.preload(submitters: :start_form_submission_events))
   end
 end
diff --git a/app/controllers/template_folders_controller.rb b/app/controllers/template_folders_controller.rb
index e5cb2bbf..c22f2fed 100644
--- a/app/controllers/template_folders_controller.rb
+++ b/app/controllers/template_folders_controller.rb
@@ -9,7 +9,7 @@ class TemplateFoldersController < ApplicationController
     @templates = Templates.search(@templates, params[:q])
     @templates = Templates::Order.call(@templates, current_user, cookies.permanent[:dashboard_templates_order])
 
-    @pagy, @templates = pagy(@templates, limit: 12)
+    @pagy, @templates = pagy_auto(@templates, limit: 12)
   end
 
   def edit; end
diff --git a/app/controllers/templates_archived_controller.rb b/app/controllers/templates_archived_controller.rb
index f75e83a1..f52e5af7 100644
--- a/app/controllers/templates_archived_controller.rb
+++ b/app/controllers/templates_archived_controller.rb
@@ -7,6 +7,6 @@ class TemplatesArchivedController < ApplicationController
     @templates = @templates.where.not(archived_at: nil).preload(:author, :folder, :template_accesses).order(id: :desc)
     @templates = Templates.search(@templates, params[:q])
 
-    @pagy, @templates = pagy(@templates, limit: 12)
+    @pagy, @templates = pagy_auto(@templates, limit: 12)
   end
 end
diff --git a/app/controllers/templates_archived_submissions_controller.rb b/app/controllers/templates_archived_submissions_controller.rb
index bf023677..9c9da083 100644
--- a/app/controllers/templates_archived_submissions_controller.rb
+++ b/app/controllers/templates_archived_submissions_controller.rb
@@ -15,7 +15,7 @@ class TemplatesArchivedSubmissionsController < ApplicationController
                      @submissions.order(id: :desc)
                    end
 
-    @pagy, @submissions = pagy(@submissions.preload(submitters: :start_form_submission_events))
+    @pagy, @submissions = pagy_auto(@submissions.preload(submitters: :start_form_submission_events))
   rescue ActiveRecord::RecordNotFound
     redirect_to root_path
   end
diff --git a/app/controllers/templates_controller.rb b/app/controllers/templates_controller.rb
index 6eb91ed8..b3d0ccec 100644
--- a/app/controllers/templates_controller.rb
+++ b/app/controllers/templates_controller.rb
@@ -21,7 +21,7 @@ class TemplatesController < ApplicationController
                     submissions.order(id: :desc)
                   end
 
-    @pagy, @submissions = pagy(submissions.preload(:template_accesses, submitters: :start_form_submission_events))
+    @pagy, @submissions = pagy_auto(submissions.preload(:template_accesses, submitters: :start_form_submission_events))
   rescue ActiveRecord::RecordNotFound
     redirect_to root_path
   end
diff --git a/app/controllers/templates_dashboard_controller.rb b/app/controllers/templates_dashboard_controller.rb
index 319b0297..b4806fbc 100644
--- a/app/controllers/templates_dashboard_controller.rb
+++ b/app/controllers/templates_dashboard_controller.rb
@@ -17,7 +17,7 @@ class TemplatesDashboardController < ApplicationController
 
     @pagy, @template_folders = pagy(
       @template_folders,
-      items: FOLDERS_PER_PAGE,
+      limit: FOLDERS_PER_PAGE,
       page: @template_folders.count > SHOW_TEMPLATES_FOLDERS_THRESHOLD ? params[:page] : 1
     )
 
@@ -35,7 +35,7 @@ class TemplatesDashboardController < ApplicationController
           (@template_folders.size < 7 ? 9 : 6)
         end
 
-      @pagy, @templates = pagy(@templates, limit:)
+      @pagy, @templates = pagy_auto(@templates, limit:)
     end
   end
 
diff --git a/app/controllers/templates_share_link_controller.rb b/app/controllers/templates_share_link_controller.rb
new file mode 100644
index 00000000..5b84f6ca
--- /dev/null
+++ b/app/controllers/templates_share_link_controller.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+class TemplatesShareLinkController < ApplicationController
+  load_and_authorize_resource :template
+
+  def show; end
+
+  def create
+    authorize!(:update, @template)
+
+    @template.update!(template_params)
+
+    head :ok
+  end
+
+  private
+
+  def template_params
+    params.require(:template).permit(:shared_link)
+  end
+end
diff --git a/app/javascript/application.js b/app/javascript/application.js
index c2e12079..f951b8fe 100644
--- a/app/javascript/application.js
+++ b/app/javascript/application.js
@@ -24,6 +24,7 @@ import SubmitForm from './elements/submit_form'
 import PromptPassword from './elements/prompt_password'
 import EmailsTextarea from './elements/emails_textarea'
 import ToggleOnSubmit from './elements/toggle_on_submit'
+import CheckOnClick from './elements/check_on_click'
 import PasswordInput from './elements/password_input'
 import SearchInput from './elements/search_input'
 import ToggleAttribute from './elements/toggle_attribute'
@@ -103,6 +104,7 @@ safeRegisterElement('set-date-button', SetDateButton)
 safeRegisterElement('indeterminate-checkbox', IndeterminateCheckbox)
 safeRegisterElement('app-tour', AppTour)
 safeRegisterElement('dashboard-dropzone', DashboardDropzone)
+safeRegisterElement('check-on-click', CheckOnClick)
 
 safeRegisterElement('template-builder', class extends HTMLElement {
   connectedCallback () {
diff --git a/app/javascript/elements/check_on_click.js b/app/javascript/elements/check_on_click.js
new file mode 100644
index 00000000..8b3b9ab8
--- /dev/null
+++ b/app/javascript/elements/check_on_click.js
@@ -0,0 +1,14 @@
+export default class extends HTMLElement {
+  connectedCallback () {
+    this.addEventListener('click', () => {
+      if (!this.element.checked) {
+        this.element.checked = true
+        this.element.dispatchEvent(new Event('change', { bubbles: true }))
+      }
+    })
+  }
+
+  get element () {
+    return document.getElementById(this.dataset.elementId)
+  }
+}
diff --git a/app/javascript/elements/clipboard_copy.js b/app/javascript/elements/clipboard_copy.js
index 777727d1..4118b9e2 100644
--- a/app/javascript/elements/clipboard_copy.js
+++ b/app/javascript/elements/clipboard_copy.js
@@ -3,8 +3,6 @@ export default class extends HTMLElement {
     this.clearChecked()
 
     this.addEventListener('click', (e) => {
-      e.stopPropagation()
-
       const text = this.dataset.text || this.innerText.trim()
 
       if (navigator.clipboard) {
diff --git a/app/javascript/submission_form/area.vue b/app/javascript/submission_form/area.vue
index 01819533..5aed2a7a 100644
--- a/app/javascript/submission_form/area.vue
+++ b/app/javascript/submission_form/area.vue
@@ -23,7 +23,7 @@
     
     
       <%= render partial: 'templates/template', collection: @templates %>
     
     <% templates_order_select_html = capture do %>
       <% if params[:q].blank? && @pagy.pages > 1 %>
-        <%= render('shared/templates_order_select', with_recently_used: @pagy.count < 10_000) %>
+        <%= render('shared/templates_order_select', with_recently_used: @pagy.count.present? && @pagy.count < 10_000) %>
       <% end %>
     <% end %>
     <%= render 'shared/pagination', pagy: @pagy, items_name: 'templates', right_additional_html: templates_order_select_html %>
diff --git a/app/views/templates/_title.html.erb b/app/views/templates/_title.html.erb
index c33a8298..28d2e037 100644
--- a/app/views/templates/_title.html.erb
+++ b/app/views/templates/_title.html.erb
@@ -49,7 +49,12 @@
             <% end %>
           
         <% end %>
-        <%= render 'shared/clipboard_copy', text: start_form_url(slug: @template.slug), id: 'share_link_clipboard', class: 'absolute md:relative bottom-0 right-0 btn btn-xs md:btn-sm whitespace-nowrap btn-neutral text-white mt-1 px-2', icon_class: 'w-4 h-4 md:w-6 md:h-6 text-white', copy_title: t('link'), copied_title: t('copied'), copy_title_md: t('link'), copied_title_md: t('copied') %>
+        <%= link_to template_share_link_path(template), class: 'absolute md:relative bottom-0 right-0 btn btn-xs md:btn-sm whitespace-nowrap btn-neutral text-white mt-1 px-2', data: { turbo_frame: :modal } do %>
+          
     <%= render partial: 'templates/submission', collection: @submissions, locals: { template: @template, archived: true } %>
   
diff --git a/app/views/templates_dashboard/index.html.erb b/app/views/templates_dashboard/index.html.erb
index bcd85b01..99f4d80e 100644
--- a/app/views/templates_dashboard/index.html.erb
+++ b/app/views/templates_dashboard/index.html.erb
@@ -12,7 +12,7 @@
       <%= render 'templates/dashboard_dropzone', style: 'height: 114px' %>
     <% end %>
     
-      <% if has_archived || @pagy.count > 0 || @template_folders.present? %>
+      <% if has_archived || @pagy.count.nil? || @pagy.count > 0 || @template_folders.present? %>
         
           <%= render 'dashboard/toggle_view', selected: 'templates' %>
         
@@ -45,7 +45,7 @@
   <% end %>
   <% templates_order_select_html = capture do %>
     <% if params[:q].blank? && @pagy.pages > 1 %>
-      <%= render('shared/templates_order_select', with_recently_used: @pagy.count < 10_000) %>
+      <%= render('shared/templates_order_select', with_recently_used: @pagy.count.present? && @pagy.count < 10_000) %>
     <% end %>
   <% end %>
   <% if @template_folders.present? %>
@@ -84,9 +84,9 @@
 <% if show_dropzone %>
   <%= render 'templates/dropzone' %>
 <% end %>
-<% if @templates.present? || params[:q].blank? %>
+<% if @templates.present? || @template_folders.present? || params[:q].blank? %>
   <% if @pagy.pages > 1 %>
-    <%= render 'shared/pagination', pagy: @pagy, items_name: 'templates', left_additional_html: view_archived_html, right_additional_html: templates_order_select_html %>
+    <%= render 'shared/pagination', pagy: @pagy, items_name: @templates.present? ? 'templates' : 'template_folders', left_additional_html: view_archived_html, right_additional_html: templates_order_select_html %>
   <% else %>
     
       <%= view_archived_html %>
diff --git a/app/views/templates_preferences/show.html.erb b/app/views/templates_preferences/show.html.erb
index b59fac43..47b342c7 100644
--- a/app/views/templates_preferences/show.html.erb
+++ b/app/views/templates_preferences/show.html.erb
@@ -380,8 +380,18 @@
           <%= t('embedding_url') %>
         
         
-          
-          <%= render 'shared/clipboard_copy', icon: 'copy', text: start_form_url(slug: @template.slug), class: 'base-button', icon_class: 'w-6 h-6 text-white', copy_title: t('copy'), copied_title: t('copied') %>
+          <%= form_for @template, url: template_share_link_path(@template), method: :post, html: { id: 'shared_link_form', autocomplete: 'off', class: 'w-full mt-1' }, data: { close_on_submit: false } do |f| %>
+            
+              
+              
+                <%= render 'shared/clipboard_copy', icon: 'copy', text: start_form_url(slug: @template.slug), class: 'base-button', icon_class: 'w-6 h-6 text-white', copy_title: t('copy'), copied_title: t('copied') %>
+              
+            
+            
+              <%= t('enable_shared_link') %>
+              <%= f.check_box :shared_link, { class: 'toggle', onchange: 'this.form.requestSubmit()' }, 'true', 'false' %>
+            
+          <% end %>
         
       <%= render 'templates_code_modal/placeholder' %>
diff --git a/app/views/templates_share_link/show.html.erb b/app/views/templates_share_link/show.html.erb
new file mode 100644
index 00000000..eb2d74e0
--- /dev/null
+++ b/app/views/templates_share_link/show.html.erb
@@ -0,0 +1,16 @@
+<%= render 'shared/turbo_modal_large', title: t('share_link') do %>
+  
+    <%= form_for @template, url: template_share_link_path(@template), method: :post, html: { id: 'shared_link_form', autocomplete: 'off', class: 'mt-3' }, data: { close_on_submit: false } do |f| %>
+      
+        <%= t('enable_shared_link') %>
+        <%= f.check_box :shared_link, { disabled: !can?(:update, @template), class: 'toggle', onchange: 'this.form.requestSubmit()' }, 'true', 'false' %>
+      
+      
+        
+        
+          <%= render 'shared/clipboard_copy', icon: 'copy', text: start_form_url(slug: @template.slug), class: 'base-button', icon_class: 'w-6 h-6 text-white', copy_title: t('copy'), copied_title: t('copied') %>
+        
+      
+    <% end %>
+  
+<% end %>
diff --git a/config/initializers/pagy.rb b/config/initializers/pagy.rb
index dc79235a..45c364e8 100644
--- a/config/initializers/pagy.rb
+++ b/config/initializers/pagy.rb
@@ -1,5 +1,7 @@
 # frozen_string_literal: true
 
+require 'pagy/extras/countless'
+
 Pagy::DEFAULT[:limit] = 10
 Pagy::DEFAULT.freeze
 
diff --git a/config/locales/i18n.yml b/config/locales/i18n.yml
index d807d374..378a6f5e 100644
--- a/config/locales/i18n.yml
+++ b/config/locales/i18n.yml
@@ -745,6 +745,10 @@ en: &en
   three_months: 3 months
   eu_data_residency: EU data residency
   please_enter_your_email_address_associated_with_the_completed_submission: Please enter your email address associated with the completed submission.
+  esignature_disclosure: eSignature Disclosure
+  share_link: Share link
+  enable_shared_link: Enable shared link
+  share_link_is_currently_disabled: Share link is currently disabled
   submission_sources:
     api: API
     bulk: Bulk Send
@@ -829,6 +833,22 @@ en: &en
     scopes:
       write: Update your data
       read: Read your data
+  pagination:
+    submissions:
+      range_with_total: "%{from}-%{to} of %{count} submissions"
+      range_without_total: "%{from}-%{to} submissions"
+    templates:
+      range_with_total: "%{from}-%{to} of %{count} templates"
+      range_without_total: "%{from}-%{to} templates"
+    template_folders:
+      range_with_total: "%{from}-%{to} of %{count} folders"
+      range_without_total: "%{from}-%{to} folders"
+    users:
+      range_with_total: "%{from}-%{to} of %{count} users"
+      range_without_total: "%{from}-%{to} users"
+    items:
+      range_with_total: "%{from}-%{to} of %{count} items"
+      range_without_total: "%{from}-%{to} items"
 
 es: &es
   stripe_integration: Integración con Stripe
@@ -1557,6 +1577,10 @@ es: &es
   three_months: 3 meses
   eu_data_residency: Datos alojados UE
   please_enter_your_email_address_associated_with_the_completed_submission: Por favor, introduce tu dirección de correo electrónico asociada con el envío completado.
+  esignature_disclosure: Uso de firma electrónica
+  share_link: Enlace para compartir
+  enable_shared_link: Habilitar enlace compartido
+  share_link_is_currently_disabled: El enlace compartido está deshabilitado actualmente
   submission_sources:
     api: API
     bulk: Envío masivo
@@ -1641,6 +1665,22 @@ es: &es
     scopes:
       write: Actualizar tus datos
       read: Leer tus datos
+  pagination:
+    submissions:
+      range_with_total: "%{from}-%{to} de %{count} envíos"
+      range_without_total: "%{from}-%{to} envíos"
+    templates:
+      range_with_total: "%{from}-%{to} de %{count} plantillas"
+      range_without_total: "%{from}-%{to} plantillas"
+    template_folders:
+      range_with_total: "%{from}-%{to} de %{count} carpetas"
+      range_without_total: "%{from}-%{to} carpetas"
+    users:
+      range_with_total: "%{from}-%{to} de %{count} usuarios"
+      range_without_total: "%{from}-%{to} usuarios"
+    items:
+      range_with_total: "%{from}-%{to} de %{count} elementos"
+      range_without_total: "%{from}-%{to} elementos"
 
 it: &it
   stripe_integration: Integrazione Stripe
@@ -2367,6 +2407,10 @@ it: &it
   three_months: 3 mesi
   eu_data_residency: "Dati nell'UE"
   please_enter_your_email_address_associated_with_the_completed_submission: "Inserisci il tuo indirizzo email associato all'invio completato."
+  esignature_disclosure: Uso della firma elettronica
+  share_link: Link di condivisione
+  enable_shared_link: Abilita link condiviso
+  share_link_is_currently_disabled: Il link condiviso è attualmente disabilitato
   submission_sources:
     api: API
     bulk: Invio massivo
@@ -2451,6 +2495,22 @@ it: &it
     scopes:
       write: Aggiorna i tuoi dati
       read: Leggi i tuoi dati
+  pagination:
+    submissions:
+      range_with_total: "%{from}-%{to} di %{count} invii"
+      range_without_total: "%{from}-%{to} invii"
+    templates:
+      range_with_total: "%{from}-%{to} di %{count} modelli"
+      range_without_total: "%{from}-%{to} modelli"
+    template_folders:
+      range_with_total: "%{from}-%{to} di %{count} cartelle"
+      range_without_total: "%{from}-%{to} cartelle"
+    users:
+      range_with_total: "%{from}-%{to} di %{count} utenti"
+      range_without_total: "%{from}-%{to} utenti"
+    items:
+      range_with_total: "%{from}-%{to} di %{count} elementi"
+      range_without_total: "%{from}-%{to} elementi"
 
 fr: &fr
   stripe_integration: Intégration Stripe
@@ -3180,6 +3240,10 @@ fr: &fr
   three_months: 3 mois
   eu_data_residency: "Données dans l'UE"
   please_enter_your_email_address_associated_with_the_completed_submission: "Veuillez saisir l'adresse e-mail associée à l'envoi complété."
+  esignature_disclosure: Divulgation de Signature Électronique
+  share_link: Lien de partage
+  enable_shared_link: Activer le lien de partage
+  share_link_is_currently_disabled: Le lien de partage est actuellement désactivé
   submission_sources:
     api: API
     bulk: Envoi en masse
@@ -3264,6 +3328,22 @@ fr: &fr
     scopes:
       write: Mettre à jour vos données
       read: Lire vos données
+  pagination:
+    submissions:
+      range_with_total: "%{from} à %{to} sur %{count} soumissions"
+      range_without_total: "%{from} à %{to} soumissions"
+    templates:
+      range_with_total: "%{from} à %{to} sur %{count} modèles"
+      range_without_total: "%{from} à %{to} modèles"
+    template_folders:
+      range_with_total: "%{from} à %{to} sur %{count} dossiers"
+      range_without_total: "%{from} à %{to} dossiers"
+    users:
+      range_with_total: "%{from} à %{to} sur %{count} utilisateurs"
+      range_without_total: "%{from} à %{to} utilisateurs"
+    items:
+      range_with_total: "%{from} à %{to} sur %{count} éléments"
+      range_without_total: "%{from} à %{to} éléments"
 
 pt: &pt
   stripe_integration: Integração com Stripe
@@ -3992,6 +4072,10 @@ pt: &pt
   three_months: 3 meses
   eu_data_residency: Dados na UE
   please_enter_your_email_address_associated_with_the_completed_submission: Por favor, insira seu e-mail associado ao envio concluído.
+  esignature_disclosure: Uso de assinatura eletrônica
+  share_link: Link de compartilhamento
+  enable_shared_link: Ativar link compartilhado
+  share_link_is_currently_disabled: O link compartilhado está desativado no momento
   submission_sources:
     api: API
     bulk: Envio em massa
@@ -4036,8 +4120,8 @@ pt: &pt
     start: Iniciar
     previous: Anterior
     next: Próximo
-    template_and_submissions: 'Modelos e Envios'
-    template_and_submissions_description: "Você pode selecionar a visualização que melhor se adapta ao seu fluxo de trabalho. Escolha a visualização 'Modelos' para criar modelos reutilizáveis de documentos ou 'Envios' para assinar documentos individuais ou verificar o status de cada solicitação de assinatura."
+    template_and_submissions: 'Modelos e Submissões'
+    template_and_submissions_description: "Você pode selecionar a visualização que melhor se adapta ao seu fluxo de trabalho. Escolha a visualização 'Modelos' para criar modelos reutilizáveis de documentos ou 'Submissões' para assinar documentos individuais ou verificar o status de cada solicitação de assinatura."
     upload_a_pdf_file: 'Enviar um arquivo PDF'
     upload_a_pdf_file_description: 'Envie um documento PDF para criar um modelo de formulário de assinatura.'
     select_a_signer_party: 'Selecionar parte assinante'
@@ -4077,6 +4161,22 @@ pt: &pt
     scopes:
       write: Atualizar seus dados
       read: Ler seus dados
+  pagination:
+    submissions:
+      range_with_total: "%{from}-%{to} de %{count} submissões"
+      range_without_total: "%{from}-%{to} submissões"
+    templates:
+      range_with_total: "%{from}-%{to} de %{count} modelos"
+      range_without_total: "%{from}-%{to} modelos"
+    template_folders:
+      range_with_total: "%{from}-%{to} de %{count} pastas"
+      range_without_total: "%{from}-%{to} pastas"
+    users:
+      range_with_total: "%{from}-%{to} de %{count} usuários"
+      range_without_total: "%{from}-%{to} usuários"
+    items:
+      range_with_total: "%{from}-%{to} de %{count} itens"
+      range_without_total: "%{from}-%{to} itens"
 
 de: &de
   stripe_integration: Stripe-Integration
@@ -4805,6 +4905,10 @@ de: &de
   three_months: 3 Monate
   eu_data_residency: EU-Datenspeicher
   please_enter_your_email_address_associated_with_the_completed_submission: Bitte gib deine E-Mail-Adresse ein, die mit der abgeschlossenen Übermittlung verknüpft ist.
+  esignature_disclosure: Nutzung der E-Signatur
+  share_link: Freigabelink
+  enable_shared_link: 'Freigabelink aktivieren'
+  share_link_is_currently_disabled: 'Freigabelink ist derzeit deaktiviert'
   submission_sources:
     api: API
     bulk: Massenversand
@@ -4889,6 +4993,22 @@ de: &de
     scopes:
       write: Aktualisiere deine Daten
       read: Lese deine Daten
+  pagination:
+    submissions:
+      range_with_total: "%{from}-%{to} von %{count} Einreichungen"
+      range_without_total: "%{from}-%{to} Einreichungen"
+    templates:
+      range_with_total: "%{from}-%{to} von %{count} Vorlagen"
+      range_without_total: "%{from}-%{to} Vorlagen"
+    template_folders:
+      range_with_total: "%{from}-%{to} von %{count} Ordnern"
+      range_without_total: "%{from}-%{to} Ordner"
+    users:
+      range_with_total: "%{from}-%{to} von %{count} Benutzern"
+      range_without_total: "%{from}-%{to} Benutzer"
+    items:
+      range_with_total: "%{from}-%{to} von %{count} Elementen"
+      range_without_total: "%{from}-%{to} Elemente"
 
 pl:
   require_phone_2fa_to_open: Wymagaj uwierzytelniania telefonicznego 2FA do otwarcia
@@ -4958,6 +5078,8 @@ pl:
   open_source_documents_software: 'oprogramowanie do dokumentów open source'
   eu_data_residency: Dane w UE
   please_enter_your_email_address_associated_with_the_completed_submission: Wprowadź adres e-mail powiązany z ukończonym zgłoszeniem.
+  privacy_policy: Polityka Prywatności
+  esignature_disclosure: Użycie e-podpisu
 
 uk:
   require_phone_2fa_to_open: Вимагати двофакторну автентифікацію через телефон для відкриття
@@ -5027,6 +5149,8 @@ uk:
   open_source_documents_software: 'відкрите програмне забезпечення для документів'
   eu_data_residency: 'Зберігання даних в ЄС'
   please_enter_your_email_address_associated_with_the_completed_submission: "Введіть адресу електронної пошти, пов'язану із завершеним поданням."
+  privacy_policy: Політика конфіденційності
+  esignature_disclosure: Використання e-підпису
 
 cs:
   require_phone_2fa_to_open: Vyžadovat otevření pomocí telefonního 2FA
@@ -5096,6 +5220,8 @@ cs:
   open_source_documents_software: 'open source software pro dokumenty'
   eu_data_residency: 'Uložení dat v EU'
   please_enter_your_email_address_associated_with_the_completed_submission: Zadejte e-mailovou adresu spojenou s dokončeným odesláním.
+  privacy_policy: Zásady Ochrany Osobních Údajů
+  esignature_disclosure: Použití e-podpisu
 
 he:
   require_phone_2fa_to_open: דרוש אימות דו-שלבי באמצעות טלפון לפתיחה
@@ -5165,6 +5291,8 @@ he:
   open_source_documents_software: 'תוכנה בקוד פתוח למסמכים'
   eu_data_residency: 'נתונים באיחוד האירופי	'
   please_enter_your_email_address_associated_with_the_completed_submission: 'אנא הזן את כתובת הדוא"ל המשויכת למשלוח שהושלם.'
+  privacy_policy: 'מדיניות פרטיות'
+  esignature_disclosure: 'גילוי חתימה אלקטרונית'
 
 nl:
   require_phone_2fa_to_open: Vereis telefoon 2FA om te openen
@@ -5234,6 +5362,8 @@ nl:
   open_source_documents_software: 'open source documenten software'
   eu_data_residency: Gegevens EU
   please_enter_your_email_address_associated_with_the_completed_submission: Voer het e-mailadres in dat is gekoppeld aan de voltooide indiening.
+  privacy_policy: Privacybeleid
+  esignature_disclosure: Gebruik van e-handtekening
 
 ar:
   require_phone_2fa_to_open: "تطلب فتح عبر تحقق الهاتف ذو العاملين"
@@ -5303,6 +5433,8 @@ ar:
   open_source_documents_software: 'برنامج مستندات مفتوح المصدر'
   eu_data_residency: 'بيانات في الاتحاد الأوروبي'
   please_enter_your_email_address_associated_with_the_completed_submission: 'يرجى إدخال عنوان البريد الإلكتروني المرتبط بالإرسال المكتمل.'
+  privacy_policy: 'سياسة الخصوصية'
+  esignature_disclosure: 'إفصاح التوقيع الإلكتروني'
 
 ko:
   require_phone_2fa_to_open: 휴대폰 2FA를 열 때 요구함
@@ -5372,6 +5504,8 @@ ko:
   open_source_documents_software: '오픈소스 문서 소프트웨어'
   eu_data_residency: 'EU 데이터 보관'
   please_enter_your_email_address_associated_with_the_completed_submission: '완료된 제출과 연결된 이메일 주소를 입력하세요.'
+  privacy_policy: 개인정보 처리방침
+  esignature_disclosure: 전자서명 공개
 
 ja:
   require_phone_2fa_to_open: 電話による2段階認証が必要です
@@ -5441,6 +5575,8 @@ ja:
   open_source_documents_software: 'オープンソースのドキュメントソフトウェア'
   eu_data_residency: 'EU データ居住'
   please_enter_your_email_address_associated_with_the_completed_submission: '完了した提出に関連付けられたメールアドレスを入力してください。'
+  privacy_policy: プライバシーポリシー
+  esignature_disclosure: 電子署名に関する開示
 
 en-US:
   <<: *en
diff --git a/config/routes.rb b/config/routes.rb
index 331ca82d..aed50953 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -106,6 +106,7 @@ Rails.application.routes.draw do
     resource :form, only: %i[show], controller: 'templates_form_preview'
     resource :code_modal, only: %i[show], controller: 'templates_code_modal'
     resource :preferences, only: %i[show create], controller: 'templates_preferences'
+    resource :share_link, only: %i[show create], controller: 'templates_share_link'
     resources :recipients, only: %i[create], controller: 'templates_recipients'
     resources :submissions_export, only: %i[index new]
   end
@@ -131,6 +132,8 @@ Rails.application.routes.draw do
     get :completed
   end
 
+  resource :resubmit_form, controller: 'start_form', only: :update
+
   resources :submit_form, only: %i[], path: '' do
     get :success, on: :collection
   end
diff --git a/db/migrate/20250523121121_add_shared_link_to_templates.rb b/db/migrate/20250523121121_add_shared_link_to_templates.rb
new file mode 100644
index 00000000..6fe962eb
--- /dev/null
+++ b/db/migrate/20250523121121_add_shared_link_to_templates.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+class AddSharedLinkToTemplates < ActiveRecord::Migration[8.0]
+  disable_ddl_transaction
+
+  class MigrationTemplate < ActiveRecord::Base
+    self.table_name = 'templates'
+  end
+
+  def up
+    add_column :templates, :shared_link, :boolean, if_not_exists: true
+
+    MigrationTemplate.where(shared_link: nil).in_batches.update_all(shared_link: true)
+
+    change_column_default :templates, :shared_link, from: nil, to: false
+    change_column_null :templates, :shared_link, false
+  end
+
+  def down
+    remove_column :templates, :shared_link
+  end
+end
diff --git a/db/migrate/20250530080846_add_email_events_date_index.rb b/db/migrate/20250530080846_add_email_events_date_index.rb
new file mode 100644
index 00000000..25a0d643
--- /dev/null
+++ b/db/migrate/20250530080846_add_email_events_date_index.rb
@@ -0,0 +1,8 @@
+# frozen_string_literal: true
+
+class AddEmailEventsDateIndex < ActiveRecord::Migration[8.0]
+  def change
+    remove_index :email_events, :account_id
+    add_index :email_events, %i[account_id event_datetime]
+  end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 887938d0..b024ff66 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
 #
 # It's strongly recommended that you check this file into your version control system.
 
-ActiveRecord::Schema[8.0].define(version: 2025_05_18_070555) do
+ActiveRecord::Schema[8.0].define(version: 2025_05_30_080846) do
   # These are extensions that must be enabled in order to support this database
   enable_extension "plpgsql"
 
@@ -174,7 +174,7 @@ ActiveRecord::Schema[8.0].define(version: 2025_05_18_070555) do
     t.text "data", null: false
     t.datetime "event_datetime", null: false
     t.datetime "created_at", null: false
-    t.index ["account_id"], name: "index_email_events_on_account_id"
+    t.index ["account_id", "event_datetime"], name: "index_email_events_on_account_id_and_event_datetime"
     t.index ["email"], name: "index_email_events_on_email"
     t.index ["emailable_type", "emailable_id"], name: "index_email_events_on_emailable"
     t.index ["message_id"], name: "index_email_events_on_message_id"
@@ -361,6 +361,7 @@ ActiveRecord::Schema[8.0].define(version: 2025_05_18_070555) do
     t.bigint "folder_id", null: false
     t.string "external_id"
     t.text "preferences", null: false
+    t.boolean "shared_link", default: false, null: false
     t.index ["account_id"], name: "index_templates_on_account_id"
     t.index ["author_id"], name: "index_templates_on_author_id"
     t.index ["external_id"], name: "index_templates_on_external_id"
diff --git a/lib/submissions/generate_audit_trail.rb b/lib/submissions/generate_audit_trail.rb
index 32622049..cdd5945a 100644
--- a/lib/submissions/generate_audit_trail.rb
+++ b/lib/submissions/generate_audit_trail.rb
@@ -31,7 +31,9 @@ module Submissions
     def call(submission)
       account = submission.account
 
-      I18n.with_locale(account.locale) do
+      last_submitter = submission.submitters.select(&:completed_at).max_by(&:completed_at)
+
+      I18n.with_locale(last_submitter.metadata.fetch('lang', account.locale)) do
         document = build_audit_trail(submission)
 
         pkcs = Accounts.load_signing_pkcs(account)
@@ -41,8 +43,6 @@ module Submissions
 
         document.trailer.info[:Creator] = "#{Docuseal.product_name} (#{Docuseal::PRODUCT_URL})"
 
-        last_submitter = submission.submitters.select(&:completed_at).max_by(&:completed_at)
-
         if pkcs
           sign_params = {
             reason: sign_reason,
@@ -322,7 +322,7 @@ module Submissions
               resized_image = image.resize([scale, 1].min)
               io = StringIO.new(resized_image.write_to_buffer('.png'))
 
-              width = field['type'] == 'initials' ? 100 : 200
+              width = field['type'] == 'initials' ? 50 : 200
               height = resized_image.height * (width.to_f / resized_image.width)
 
               if height > MAX_IMAGE_HEIGHT
diff --git a/lib/submissions/generate_result_attachments.rb b/lib/submissions/generate_result_attachments.rb
index e260192d..7dfdb6d9 100644
--- a/lib/submissions/generate_result_attachments.rb
+++ b/lib/submissions/generate_result_attachments.rb
@@ -152,7 +152,8 @@ module Submissions
                   TESTING_FOOTER
                 end
               else
-                "#{I18n.t('document_id', locale: submitter.account.locale)}: #{document_id}"
+                "#{I18n.t('document_id',
+                          locale: submitter.metadata.fetch('lang', submitter.account.locale))}: #{document_id}"
               end
 
             text = HexaPDF::Layout::TextFragment.create(
@@ -182,6 +183,8 @@ module Submissions
 
       with_headings = find_last_submitter(submitter.submission, submitter:).blank? if with_headings.nil?
 
+      locale = submitter.metadata.fetch('lang', account.locale)
+
       submitter.submission.template_fields.each do |field|
         next if field['type'] == 'heading' && !with_headings
         next if field['submitter_uuid'] != submitter.uuid && field['type'] != 'heading'
@@ -258,7 +261,7 @@ module Submissions
             reason_value = submitter.values[field.dig('preferences', 'reason_field_uuid')].presence
 
             reason_string =
-              I18n.with_locale(submitter.account.locale) do
+              I18n.with_locale(locale) do
                 "#{reason_value ? "#{I18n.t('reason')}: " : ''}#{reason_value || I18n.t('digitally_signed_by')} " \
                   "#{submitter.name}#{submitter.email.present? ? " <#{submitter.email}>" : ''}\n" \
                   "#{I18n.l(attachment.created_at.in_time_zone(submitter.account.timezone), format: :long)} " \
@@ -442,7 +445,7 @@ module Submissions
               option = field['options']&.find { |o| o['uuid'] == area['option_uuid'] }
 
               option_name = option['value'].presence
-              option_name ||= "#{I18n.t('option', locale: account.locale)} #{field['options'].index(option) + 1}"
+              option_name ||= "#{I18n.t('option', locale: locale)} #{field['options'].index(option) + 1}"
 
               value = Array.wrap(value).include?(option_name)
             end
@@ -509,7 +512,7 @@ module Submissions
             end
           else
             if field['type'] == 'date'
-              value = TimeUtils.format_date_string(value, field.dig('preferences', 'format'), account.locale)
+              value = TimeUtils.format_date_string(value, field.dig('preferences', 'format'), locale)
             end
 
             value = NumberUtils.format_number(value, field.dig('preferences', 'format')) if field['type'] == 'number'
diff --git a/lib/templates/clone.rb b/lib/templates/clone.rb
index 0fe3b91b..e4b5fc60 100644
--- a/lib/templates/clone.rb
+++ b/lib/templates/clone.rb
@@ -9,6 +9,7 @@ module Templates
       template = original_template.account.templates.new
 
       template.external_id = external_id
+      template.shared_link = original_template.shared_link
       template.author = author
       template.name = name.presence || "#{original_template.name} (#{I18n.t('clone')})"
 
diff --git a/lib/templates/process_document.rb b/lib/templates/process_document.rb
index 8ee1dff5..1a5e5ae1 100644
--- a/lib/templates/process_document.rb
+++ b/lib/templates/process_document.rb
@@ -118,10 +118,10 @@ module Templates
 
       page = page.copy(interpretation: :srgb)
 
-      bitdepth = 2**page.stats.to_a[1..3].pluck(2).uniq.size
-
       data =
         if format == FORMAT
+          bitdepth = 2**page.stats.to_a[1..3].pluck(2).uniq.size
+
           page.write_to_buffer(format, compression: 7, filter: 0, bitdepth:,
                                        palette: true, Q: bitdepth == 8 ? Q : 5, dither: 0)
         else
@@ -138,6 +138,8 @@ module Templates
       blob
     rescue Vips::Error, Pdfium::PdfiumError => e
       Rollbar.warning(e) if defined?(Rollbar)
+
+      nil
     ensure
       doc_page&.close
     end
diff --git a/lib/templates/serialize_for_api.rb b/lib/templates/serialize_for_api.rb
index f5f03ebe..b60f9023 100644
--- a/lib/templates/serialize_for_api.rb
+++ b/lib/templates/serialize_for_api.rb
@@ -6,7 +6,7 @@ module Templates
       only: %w[
         id archived_at fields name preferences schema
         slug source submitters created_at updated_at
-        author_id external_id folder_id
+        author_id external_id folder_id shared_link
       ],
       methods: %i[application_key folder_name],
       include: { author: { only: %i[id email first_name last_name] } }
diff --git a/spec/fixtures/fieldtags.docx b/spec/fixtures/fieldtags.docx
new file mode 100644
index 00000000..50655a04
Binary files /dev/null and b/spec/fixtures/fieldtags.docx differ
diff --git a/spec/requests/templates_spec.rb b/spec/requests/templates_spec.rb
index fa2a362a..7763d8cd 100644
--- a/spec/requests/templates_spec.rb
+++ b/spec/requests/templates_spec.rb
@@ -83,13 +83,15 @@ describe 'Templates API' do
   end
 
   describe 'PUT /api/templates' do
-    it 'update a template' do
-      template = create(:template, account:,
-                                   author:,
-                                   folder:,
-                                   external_id: SecureRandom.base58(10),
-                                   preferences: template_preferences)
+    let(:template) do
+      create(:template, account:,
+                        author:,
+                        folder:,
+                        external_id: SecureRandom.base58(10),
+                        preferences: template_preferences)
+    end
 
+    it 'updates a template' do
       put "/api/templates/#{template.id}", headers: { 'x-auth-token': author.access_token.token }, params: {
         name: 'Updated Template Name',
         external_id: '123456'
@@ -106,6 +108,24 @@ describe 'Templates API' do
         updated_at: template.updated_at
       }.to_json))
     end
+
+    it "enables the template's shared link" do
+      expect do
+        put "/api/templates/#{template.id}", headers: { 'x-auth-token': author.access_token.token }, params: {
+          shared_link: true
+        }.to_json
+      end.to change { template.reload.shared_link }.from(false).to(true)
+    end
+
+    it "disables the template's shared link" do
+      template.update(shared_link: true)
+
+      expect do
+        put "/api/templates/#{template.id}", headers: { 'x-auth-token': author.access_token.token }, params: {
+          shared_link: false
+        }.to_json
+      end.to change { template.reload.shared_link }.from(true).to(false)
+    end
   end
 
   describe 'DELETE /api/templates/:id' do
@@ -206,6 +226,7 @@ describe 'Templates API' do
           name: 'sample-document'
         }
       ],
+      shared_link: template.shared_link,
       author_id: author.id,
       archived_at: nil,
       created_at: template.created_at,
diff --git a/spec/system/profile_settings_spec.rb b/spec/system/profile_settings_spec.rb
index 7b977d2d..3c05a664 100644
--- a/spec/system/profile_settings_spec.rb
+++ b/spec/system/profile_settings_spec.rb
@@ -33,6 +33,14 @@ RSpec.describe 'Profile Settings' do
       expect(user.last_name).to eq('Beckham')
       expect(user.email).to eq('david.beckham@example.com')
     end
+
+    it 'does not update if email is invalid' do
+      fill_in 'Email', with: 'devid+test@example'
+
+      all(:button, 'Update')[0].click
+
+      expect(page).to have_content('Email is invalid')
+    end
   end
 
   context 'when changes password' do
diff --git a/spec/system/setup_spec.rb b/spec/system/setup_spec.rb
index 5235c9b5..da4a37da 100644
--- a/spec/system/setup_spec.rb
+++ b/spec/system/setup_spec.rb
@@ -51,6 +51,16 @@ RSpec.describe 'App Setup' do
   end
 
   context 'when invalid information' do
+    it 'does not setup the app if the email is invalid' do
+      fill_setup_form(form_data.merge(email: 'bob@example-com'))
+
+      expect do
+        click_button 'Submit'
+      end.not_to(change(User, :count))
+
+      expect(page).to have_content('Email is invalid')
+    end
+
     it 'does not setup the app if the password is too short' do
       fill_setup_form(form_data.merge(password: 'pass'))
 
diff --git a/spec/system/signing_form_spec.rb b/spec/system/signing_form_spec.rb
index 8bfa3e5e..83c1b30b 100644
--- a/spec/system/signing_form_spec.rb
+++ b/spec/system/signing_form_spec.rb
@@ -5,7 +5,9 @@ RSpec.describe 'Signing Form' do
   let(:author) { create(:user, account:) }
 
   context 'when the template form link is opened' do
-    let(:template) { create(:template, account:, author:, except_field_types: %w[phone payment stamp]) }
+    let(:template) do
+      create(:template, shared_link: true, account:, author:, except_field_types: %w[phone payment stamp])
+    end
 
     before do
       visit start_form_path(slug: template.slug)
@@ -811,7 +813,9 @@ RSpec.describe 'Signing Form' do
   end
 
   context 'when the template requires multiple submitters' do
-    let(:template) { create(:template, submitter_count: 2, account:, author:, only_field_types: %w[text]) }
+    let(:template) do
+      create(:template, shared_link: true, submitter_count: 2, account:, author:, only_field_types: %w[text])
+    end
 
     context 'when default signer details are not defined' do
       it 'shows an explanation error message if a logged-in user associated with the template account opens the link' do
diff --git a/spec/system/team_settings_spec.rb b/spec/system/team_settings_spec.rb
index 0286267f..01ce568f 100644
--- a/spec/system/team_settings_spec.rb
+++ b/spec/system/team_settings_spec.rb
@@ -92,6 +92,23 @@ RSpec.describe 'Team Settings' do
       end
     end
 
+    it 'does not allow to create a new user with an invalid email' do
+      click_link 'New User'
+
+      within '#modal' do
+        fill_in 'First name', with: 'Joseph'
+        fill_in 'Last name', with: 'Smith'
+        fill_in 'Email', with: 'joseph.smith@gmail'
+        fill_in 'Password', with: 'password'
+
+        expect do
+          click_button 'Submit'
+        end.not_to change(User, :count)
+
+        expect(page).to have_content('Email is invalid')
+      end
+    end
+
     it 'updates a user' do
       first(:link, 'Edit').click
 
diff --git a/spec/system/template_share_link_spec.rb b/spec/system/template_share_link_spec.rb
new file mode 100644
index 00000000..23499434
--- /dev/null
+++ b/spec/system/template_share_link_spec.rb
@@ -0,0 +1,54 @@
+# frozen_string_literal: true
+
+RSpec.describe 'Template Share Link' do
+  let!(:account) { create(:account) }
+  let!(:author) { create(:user, account:) }
+  let!(:template) { create(:template, account:, author:) }
+
+  before do
+    sign_in(author)
+  end
+
+  context 'when the template is not shareable' do
+    before do
+      visit template_path(template)
+    end
+
+    it 'makes the template shareable' do
+      click_on 'Link'
+
+      expect do
+        within '#modal' do
+          check 'template_shared_link'
+        end
+      end.to change { template.reload.shared_link }.from(false).to(true)
+    end
+
+    it 'makes the template shareable on toggle' do
+      click_on 'Link'
+
+      expect do
+        within '#modal' do
+          find('#template_shared_link').click
+        end
+      end.to change { template.reload.shared_link }.from(false).to(true)
+    end
+  end
+
+  context 'when the template is already shareable' do
+    before do
+      template.update(shared_link: true)
+      visit template_path(template)
+    end
+
+    it 'makes the template unshareable' do
+      click_on 'Link'
+
+      expect do
+        within '#modal' do
+          uncheck 'template_shared_link'
+        end
+      end.to change { template.reload.shared_link }.from(true).to(false)
+    end
+  end
+end
diff --git a/spec/system/template_spec.rb b/spec/system/template_spec.rb
index a0ffe4e5..d343283e 100644
--- a/spec/system/template_spec.rb
+++ b/spec/system/template_spec.rb
@@ -16,7 +16,7 @@ RSpec.describe 'Template' do
       expect(page).to have_content(template.name)
       expect(page).to have_content('There are no Submissions')
       expect(page).to have_content('Send an invitation to fill and complete the form')
-      expect(page).to have_link('Sign it Yourself')
+      expect(page).to have_button('Sign it Yourself')
     end
   end