diff --git a/app/controllers/auth/registrations_controller.rb b/app/controllers/auth/registrations_controller.rb
index 8f1909183..63632162e 100644
--- a/app/controllers/auth/registrations_controller.rb
+++ b/app/controllers/auth/registrations_controller.rb
@@ -145,7 +145,13 @@ class Auth::RegistrationsController < Devise::RegistrationsController
end
def determine_layout
- %w(edit update).include?(action_name) ? 'admin' : 'auth'
+ if %w(edit update).include?(action_name)
+ 'admin'
+ elsif action_name == 'new'
+ 'academy-signup'
+ else
+ 'auth'
+ end
end
def set_sessions
diff --git a/app/javascript/images/academy-mascot.webp b/app/javascript/images/academy-mascot.webp
new file mode 100644
index 000000000..17d4e23ef
Binary files /dev/null and b/app/javascript/images/academy-mascot.webp differ
diff --git a/app/javascript/styles/application.scss b/app/javascript/styles/application.scss
index b65bb02d4..a0ba2c11e 100644
--- a/app/javascript/styles/application.scss
+++ b/app/javascript/styles/application.scss
@@ -23,5 +23,6 @@
@import 'mastodon/dashboard';
@import 'mastodon/rtl';
@import 'mastodon/accessibility';
+@import 'mastodon/academy';
@import 'activitypub-visualization';
diff --git a/app/javascript/styles/mastodon/academy.scss b/app/javascript/styles/mastodon/academy.scss
new file mode 100644
index 000000000..a2991e3b6
--- /dev/null
+++ b/app/javascript/styles/mastodon/academy.scss
@@ -0,0 +1,72 @@
+.academy-signup-container {
+ max-width: 1150px;
+ margin: 20px auto;
+ display: flex;
+ align-items: center;
+
+ .title {
+ font-size: 50px;
+ font-weight: 700;
+ margin-bottom: 30px;
+ }
+
+ .subtitle {
+ font-size: 28px;
+ line-height: 32px;
+ color: #d9e1e8;
+ margin-bottom: 20px;
+ }
+
+ p {
+ font-size: 20px;
+ line-height: 26px;
+ color: #d9e1e8;
+ margin: 15px 0;
+ }
+
+ .mascot {
+ width: 500px;
+ max-width: 100%;
+ transform: scaleX(-1);
+ }
+
+ a {
+ color: #8c8dff;
+ text-decoration: underline;
+
+ &:hover {
+ text-decoration: none;
+ }
+ }
+
+ & > * {
+ padding: 15px;
+ }
+}
+
+@media screen and (max-width: 1150px) {
+ .academy-signup-container {
+ max-width: 800px;
+ flex-direction: column;
+
+ .title {
+ font-size: 40px;
+ }
+ }
+}
+
+@media screen and (max-width: 450px) {
+ .academy-signup-container {
+ .title {
+ font-size: 30px;
+ }
+
+ .subtitle {
+ font-size: 24px;
+ }
+
+ p {
+ font-size: 18px;
+ }
+ }
+}
diff --git a/app/views/auth/registrations/new.html.haml b/app/views/auth/registrations/new.html.haml
index 02ebafd58..0e9a7684e 100644
--- a/app/views/auth/registrations/new.html.haml
+++ b/app/views/auth/registrations/new.html.haml
@@ -4,32 +4,32 @@
- content_for :header_tags do
= render partial: 'shared/og', locals: { description: description_for_sign_up }
-= simple_form_for(resource, as: resource_name, url: registration_path(resource_name), html: { novalidate: false }) do |f|
- %h1.title= t('auth.sign_up.title', domain: site_hostname)
- %p.lead= t('auth.sign_up.activity_log_preamble_html')
+.academy-introduction
+ %h1.title ActivityPub.Academy
+ %p.subtitle Explore the ActivityPub protocol interactively
- = render 'shared/error_messages', object: resource
- - if @invite.present? && @invite.autofollow?
- .fields-group.invited-by
- %p.hint= t('invites.invited_by')
- = render 'application/card', account: @invite.user.account
+ %p ActivityPub.Academy is a learning resource for ActivityPub. The protocol is brought to life by showing Activities sent between different instances in real time!
- .fields-group
- = f.input :confirm_password, as: :string, placeholder: t('simple_form.labels.defaults.honeypot', label: t('simple_form.labels.defaults.password')), required: false, input_html: { 'aria-label' => t('simple_form.labels.defaults.honeypot', label: t('simple_form.labels.defaults.password')), :autocomplete => 'off' }, hint: false
- = f.input :website, as: :url, wrapper: :with_label, label: t('simple_form.labels.defaults.honeypot', label: 'Website'), required: false, input_html: { 'aria-label' => t('simple_form.labels.defaults.honeypot', label: 'Website'), :autocomplete => 'off' }
+ %p Sign up for a fully functioning Mastodon account (accounts are deleted after one day, but you can always create a new one). Follow other accounts, create posts, boost & like, and see the effects on the protocol visualized.
+
+ %p Learn more on my blog.
+
+ = simple_form_for(resource, as: resource_name, url: registration_path(resource_name), html: { novalidate: false }) do |f|
+
+ = render 'shared/error_messages', object: resource
- - if approved_registrations? && !@invite.present?
.fields-group
- = f.simple_fields_for :invite_request, resource.invite_request || resource.build_invite_request do |invite_request_fields|
- = invite_request_fields.input :text, as: :text, wrapper: :with_block_label, required: Setting.require_invite_text
+ = f.input :confirm_password, as: :string, placeholder: t('simple_form.labels.defaults.honeypot', label: t('simple_form.labels.defaults.password')), required: false, input_html: { 'aria-label' => t('simple_form.labels.defaults.honeypot', label: t('simple_form.labels.defaults.password')), :autocomplete => 'off' }, hint: false
+ = f.input :website, as: :url, wrapper: :with_label, label: t('simple_form.labels.defaults.honeypot', label: 'Website'), required: false, input_html: { 'aria-label' => t('simple_form.labels.defaults.honeypot', label: 'Website'), :autocomplete => 'off' }
+ = hidden_field_tag :accept, params[:accept]
+ = f.input :invite_code, as: :hidden
- = hidden_field_tag :accept, params[:accept]
- = f.input :invite_code, as: :hidden
+ .fields-group
+ = f.input :agreement, as: :boolean, wrapper: :with_label, label: t('auth.privacy_policy_agreement_html', rules_path: about_more_path, privacy_policy_path: privacy_policy_path), required: true
- .fields-group
- = f.input :agreement, as: :boolean, wrapper: :with_label, label: t('auth.privacy_policy_agreement_html', rules_path: about_more_path, privacy_policy_path: privacy_policy_path), required: true
+ .actions
+ = f.button :button, @invite.present? ? t('auth.register') : sign_up_message, type: :submit
- .actions
- = f.button :button, @invite.present? ? t('auth.register') : sign_up_message, type: :submit
+= image_tag asset_pack_path('media/images/academy-mascot.webp'), alt: 'The Mastodon mascot wearing a university gown', class: 'mascot'
diff --git a/app/views/layouts/academy-signup.html.haml b/app/views/layouts/academy-signup.html.haml
new file mode 100644
index 000000000..0df672eeb
--- /dev/null
+++ b/app/views/layouts/academy-signup.html.haml
@@ -0,0 +1,10 @@
+- content_for :header_tags do
+ = javascript_pack_tag 'public', crossorigin: 'anonymous'
+
+- content_for :content do
+ .academy-signup-container
+ = render 'flashes'
+
+ = yield
+
+= render template: 'layouts/application'
diff --git a/config/webpacker.yml b/config/webpacker.yml
index 4ad78a190..08e920eb0 100644
--- a/config/webpacker.yml
+++ b/config/webpacker.yml
@@ -23,6 +23,7 @@ default: &default
- .jpg
- .jpeg
- .png
+ - .webp
- .tiff
- .ico
- .svg