about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Gemfile1
-rw-r--r--Gemfile.lock9
-rw-r--r--app/controllers/api/v1/accounts/credentials_controller.rb4
-rw-r--r--app/controllers/api/v1/accounts/follower_accounts_controller.rb2
-rw-r--r--app/controllers/api/v1/accounts/following_accounts_controller.rb2
-rw-r--r--app/controllers/api/v1/accounts/relationships_controller.rb11
-rw-r--r--app/controllers/api/v1/accounts/search_controller.rb3
-rw-r--r--app/controllers/api/v1/accounts/statuses_controller.rb5
-rw-r--r--app/controllers/api/v1/accounts_controller.rb38
-rw-r--r--app/controllers/api/v1/apps_controller.rb1
-rw-r--r--app/controllers/api/v1/blocks_controller.rb1
-rw-r--r--app/controllers/api/v1/favourites_controller.rb5
-rw-r--r--app/controllers/api/v1/follow_requests_controller.rb1
-rw-r--r--app/controllers/api/v1/follows_controller.rb2
-rw-r--r--app/controllers/api/v1/instances_controller.rb4
-rw-r--r--app/controllers/api/v1/media_controller.rb1
-rw-r--r--app/controllers/api/v1/mutes_controller.rb1
-rw-r--r--app/controllers/api/v1/notifications_controller.rb7
-rw-r--r--app/controllers/api/v1/reports_controller.rb3
-rw-r--r--app/controllers/api/v1/search_controller.rb3
-rw-r--r--app/controllers/api/v1/statuses/favourited_by_accounts_controller.rb2
-rw-r--r--app/controllers/api/v1/statuses/favourites_controller.rb4
-rw-r--r--app/controllers/api/v1/statuses/mutes_controller.rb4
-rw-r--r--app/controllers/api/v1/statuses/reblogged_by_accounts_controller.rb2
-rw-r--r--app/controllers/api/v1/statuses/reblogs_controller.rb4
-rw-r--r--app/controllers/api/v1/statuses_controller.rb16
-rw-r--r--app/controllers/api/v1/timelines/home_controller.rb6
-rw-r--r--app/controllers/api/v1/timelines/public_controller.rb6
-rw-r--r--app/controllers/api/v1/timelines/tag_controller.rb6
-rw-r--r--app/lib/inline_rabl_scope.rb17
-rw-r--r--app/lib/inline_renderer.rb36
-rw-r--r--app/models/context.rb5
-rw-r--r--app/models/search.rb5
-rw-r--r--app/presenters/account_relationships_presenter.rb15
-rw-r--r--app/presenters/status_relationships_presenter.rb19
-rw-r--r--app/serializers/rest/account_serializer.rb33
-rw-r--r--app/serializers/rest/application_serializer.rb14
-rw-r--r--app/serializers/rest/context_serializer.rb6
-rw-r--r--app/serializers/rest/instance_serializer.rb30
-rw-r--r--app/serializers/rest/media_attachment_serializer.rb24
-rw-r--r--app/serializers/rest/notification_serializer.rb12
-rw-r--r--app/serializers/rest/preview_card_serializer.rb14
-rw-r--r--app/serializers/rest/relationship_serializer.rb30
-rw-r--r--app/serializers/rest/report_serializer.rb5
-rw-r--r--app/serializers/rest/search_serializer.rb12
-rw-r--r--app/serializers/rest/status_serializer.rb93
-rw-r--r--app/services/fan_out_on_write_service.rb2
-rw-r--r--app/services/notify_service.rb2
-rw-r--r--app/views/api/v1/accounts/index.rabl2
-rw-r--r--app/views/api/v1/accounts/relationship.rabl9
-rw-r--r--app/views/api/v1/accounts/relationships/index.rabl2
-rw-r--r--app/views/api/v1/accounts/show.rabl12
-rw-r--r--app/views/api/v1/accounts/statuses/index.rabl2
-rw-r--r--app/views/api/v1/apps/create.rabl4
-rw-r--r--app/views/api/v1/apps/show.rabl3
-rw-r--r--app/views/api/v1/blocks/index.rabl2
-rw-r--r--app/views/api/v1/favourites/index.rabl2
-rw-r--r--app/views/api/v1/follow_requests/index.rabl2
-rw-r--r--app/views/api/v1/follows/show.rabl2
-rw-r--r--app/views/api/v1/instances/show.rabl10
-rw-r--r--app/views/api/v1/media/create.rabl7
-rw-r--r--app/views/api/v1/mutes/index.rabl2
-rw-r--r--app/views/api/v1/notifications/index.rabl2
-rw-r--r--app/views/api/v1/notifications/show.rabl11
-rw-r--r--app/views/api/v1/reports/index.rabl2
-rw-r--r--app/views/api/v1/reports/show.rabl2
-rw-r--r--app/views/api/v1/search/index.rabl13
-rw-r--r--app/views/api/v1/statuses/_media.rabl6
-rw-r--r--app/views/api/v1/statuses/_mention.rabl4
-rw-r--r--app/views/api/v1/statuses/_show.rabl29
-rw-r--r--app/views/api/v1/statuses/_tags.rabl2
-rw-r--r--app/views/api/v1/statuses/accounts.rabl2
-rw-r--r--app/views/api/v1/statuses/card.rabl7
-rw-r--r--app/views/api/v1/statuses/context.rabl9
-rw-r--r--app/views/api/v1/statuses/index.rabl2
-rw-r--r--app/views/api/v1/statuses/show.rabl15
-rw-r--r--app/views/api/v1/timelines/show.rabl2
-rw-r--r--app/views/home/initial_state.json.rabl4
-rw-r--r--app/workers/push_update_worker.rb2
-rw-r--r--spec/lib/inline_rabl_scope_spec.rb23
80 files changed, 425 insertions, 301 deletions
diff --git a/Gemfile b/Gemfile
index 6ee884a17..95c74eef9 100644
--- a/Gemfile
+++ b/Gemfile
@@ -18,6 +18,7 @@ gem 'aws-sdk', '~> 2.9'
 gem 'paperclip', '~> 5.1'
 gem 'paperclip-av-transcoder', '~> 0.6'
 
+gem 'active_model_serializers', '~> 0.10'
 gem 'addressable', '~> 2.5'
 gem 'bootsnap'
 gem 'browser'
diff --git a/Gemfile.lock b/Gemfile.lock
index f0156529c..71f83f736 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -24,6 +24,11 @@ GEM
       erubi (~> 1.4)
       rails-dom-testing (~> 2.0)
       rails-html-sanitizer (~> 1.0, >= 1.0.3)
+    active_model_serializers (0.10.6)
+      actionpack (>= 4.1, < 6)
+      activemodel (>= 4.1, < 6)
+      case_transform (>= 0.2)
+      jsonapi-renderer (>= 0.1.1.beta1, < 0.2)
     active_record_query_trace (1.5.4)
     activejob (5.1.2)
       activesupport (= 5.1.2)
@@ -101,6 +106,8 @@ GEM
       rack (>= 1.0.0)
       rack-test (>= 0.5.4)
       xpath (~> 2.0)
+    case_transform (0.2)
+      activesupport
     chunky_png (1.3.8)
     cld3 (3.1.3)
       ffi (>= 1.1.0, < 1.10.0)
@@ -200,6 +207,7 @@ GEM
       terminal-table (>= 1.5.1)
     jmespath (1.3.1)
     json (2.1.0)
+    jsonapi-renderer (0.1.2)
     kaminari (1.0.1)
       activesupport (>= 4.1.0)
       kaminari-actionview (= 1.0.1)
@@ -476,6 +484,7 @@ PLATFORMS
   ruby
 
 DEPENDENCIES
+  active_model_serializers (~> 0.10)
   active_record_query_trace (~> 1.5)
   addressable (~> 2.5)
   annotate (~> 2.7)
diff --git a/app/controllers/api/v1/accounts/credentials_controller.rb b/app/controllers/api/v1/accounts/credentials_controller.rb
index 1cf52ff10..8ee9a2416 100644
--- a/app/controllers/api/v1/accounts/credentials_controller.rb
+++ b/app/controllers/api/v1/accounts/credentials_controller.rb
@@ -6,13 +6,13 @@ class Api::V1::Accounts::CredentialsController < Api::BaseController
 
   def show
     @account = current_account
-    render 'api/v1/accounts/show'
+    render json: @account, serializer: REST::AccountSerializer
   end
 
   def update
     current_account.update!(account_params)
     @account = current_account
-    render 'api/v1/accounts/show'
+    render json: @account, serializer: REST::AccountSerializer
   end
 
   private
diff --git a/app/controllers/api/v1/accounts/follower_accounts_controller.rb b/app/controllers/api/v1/accounts/follower_accounts_controller.rb
index 81aae56d3..80b0bef40 100644
--- a/app/controllers/api/v1/accounts/follower_accounts_controller.rb
+++ b/app/controllers/api/v1/accounts/follower_accounts_controller.rb
@@ -9,7 +9,7 @@ class Api::V1::Accounts::FollowerAccountsController < Api::BaseController
 
   def index
     @accounts = load_accounts
-    render 'api/v1/accounts/index'
+    render json: @accounts, each_serializer: REST::AccountSerializer
   end
 
   private
diff --git a/app/controllers/api/v1/accounts/following_accounts_controller.rb b/app/controllers/api/v1/accounts/following_accounts_controller.rb
index 63c6d54b2..55cffdf37 100644
--- a/app/controllers/api/v1/accounts/following_accounts_controller.rb
+++ b/app/controllers/api/v1/accounts/following_accounts_controller.rb
@@ -9,7 +9,7 @@ class Api::V1::Accounts::FollowingAccountsController < Api::BaseController
 
   def index
     @accounts = load_accounts
-    render 'api/v1/accounts/index'
+    render json: @accounts, each_serializer: REST::AccountSerializer
   end
 
   private
diff --git a/app/controllers/api/v1/accounts/relationships_controller.rb b/app/controllers/api/v1/accounts/relationships_controller.rb
index cb923ab91..a88cf2021 100644
--- a/app/controllers/api/v1/accounts/relationships_controller.rb
+++ b/app/controllers/api/v1/accounts/relationships_controller.rb
@@ -8,16 +8,15 @@ class Api::V1::Accounts::RelationshipsController < Api::BaseController
 
   def index
     @accounts = Account.where(id: account_ids).select('id')
-    @following = Account.following_map(account_ids, current_user.account_id)
-    @followed_by = Account.followed_by_map(account_ids, current_user.account_id)
-    @blocking = Account.blocking_map(account_ids, current_user.account_id)
-    @muting = Account.muting_map(account_ids, current_user.account_id)
-    @requested = Account.requested_map(account_ids, current_user.account_id)
-    @domain_blocking = Account.domain_blocking_map(account_ids, current_user.account_id)
+    render json: @accounts, each_serializer: REST::RelationshipSerializer, relationships: relationships
   end
 
   private
 
+  def relationships
+    AccountRelationshipsPresenter.new(@accounts, current_user.account_id)
+  end
+
   def account_ids
     @_account_ids ||= Array(params[:id]).map(&:to_i)
   end
diff --git a/app/controllers/api/v1/accounts/search_controller.rb b/app/controllers/api/v1/accounts/search_controller.rb
index c4a8f97f2..2a5cac547 100644
--- a/app/controllers/api/v1/accounts/search_controller.rb
+++ b/app/controllers/api/v1/accounts/search_controller.rb
@@ -8,8 +8,7 @@ class Api::V1::Accounts::SearchController < Api::BaseController
 
   def show
     @accounts = account_search
-
-    render 'api/v1/accounts/index'
+    render json: @accounts, each_serializer: REST::AccountSerializer
   end
 
   private
diff --git a/app/controllers/api/v1/accounts/statuses_controller.rb b/app/controllers/api/v1/accounts/statuses_controller.rb
index 504ed8c07..d9ae5c089 100644
--- a/app/controllers/api/v1/accounts/statuses_controller.rb
+++ b/app/controllers/api/v1/accounts/statuses_controller.rb
@@ -9,6 +9,7 @@ class Api::V1::Accounts::StatusesController < Api::BaseController
 
   def index
     @statuses = load_statuses
+    render json: @statuses, each_serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id)
   end
 
   private
@@ -18,9 +19,7 @@ class Api::V1::Accounts::StatusesController < Api::BaseController
   end
 
   def load_statuses
-    cached_account_statuses.tap do |statuses|
-      set_maps(statuses)
-    end
+    cached_account_statuses
   end
 
   def cached_account_statuses
diff --git a/app/controllers/api/v1/accounts_controller.rb b/app/controllers/api/v1/accounts_controller.rb
index 8fc0dd36f..f621aa245 100644
--- a/app/controllers/api/v1/accounts_controller.rb
+++ b/app/controllers/api/v1/accounts_controller.rb
@@ -8,49 +8,38 @@ class Api::V1::AccountsController < Api::BaseController
 
   respond_to :json
 
-  def show; end
+  def show
+    render json: @account, serializer: REST::AccountSerializer
+  end
 
   def follow
     FollowService.new.call(current_user.account, @account.acct)
-    set_relationship
-    render :relationship
+    render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships
   end
 
   def block
     BlockService.new.call(current_user.account, @account)
-
-    @following       = { @account.id => false }
-    @followed_by     = { @account.id => false }
-    @blocking        = { @account.id => true }
-    @requested       = { @account.id => false }
-    @muting          = { @account.id => current_account.muting?(@account.id) }
-    @domain_blocking = { @account.id => current_account.domain_blocking?(@account.domain) }
-
-    render :relationship
+    render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships
   end
 
   def mute
     MuteService.new.call(current_user.account, @account)
-    set_relationship
-    render :relationship
+    render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships
   end
 
   def unfollow
     UnfollowService.new.call(current_user.account, @account)
-    set_relationship
-    render :relationship
+    render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships
   end
 
   def unblock
     UnblockService.new.call(current_user.account, @account)
-    set_relationship
-    render :relationship
+    render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships
   end
 
   def unmute
     UnmuteService.new.call(current_user.account, @account)
-    set_relationship
-    render :relationship
+    render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships
   end
 
   private
@@ -59,12 +48,7 @@ class Api::V1::AccountsController < Api::BaseController
     @account = Account.find(params[:id])
   end
 
-  def set_relationship
-    @following       = Account.following_map([@account.id], current_user.account_id)
-    @followed_by     = Account.followed_by_map([@account.id], current_user.account_id)
-    @blocking        = Account.blocking_map([@account.id], current_user.account_id)
-    @muting          = Account.muting_map([@account.id], current_user.account_id)
-    @requested       = Account.requested_map([@account.id], current_user.account_id)
-    @domain_blocking = Account.domain_blocking_map([@account.id], current_user.account_id)
+  def relationships
+    AccountRelationshipsPresenter.new([@account.id], current_user.account_id)
   end
 end
diff --git a/app/controllers/api/v1/apps_controller.rb b/app/controllers/api/v1/apps_controller.rb
index 98e908948..44a27b20a 100644
--- a/app/controllers/api/v1/apps_controller.rb
+++ b/app/controllers/api/v1/apps_controller.rb
@@ -5,6 +5,7 @@ class Api::V1::AppsController < Api::BaseController
 
   def create
     @app = Doorkeeper::Application.create!(application_options)
+    render json: @app, serializer: REST::ApplicationSerializer
   end
 
   private
diff --git a/app/controllers/api/v1/blocks_controller.rb b/app/controllers/api/v1/blocks_controller.rb
index 1702953cf..a412e4341 100644
--- a/app/controllers/api/v1/blocks_controller.rb
+++ b/app/controllers/api/v1/blocks_controller.rb
@@ -9,6 +9,7 @@ class Api::V1::BlocksController < Api::BaseController
 
   def index
     @accounts = load_accounts
+    render json: @accounts, each_serializer: REST::AccountSerializer
   end
 
   private
diff --git a/app/controllers/api/v1/favourites_controller.rb b/app/controllers/api/v1/favourites_controller.rb
index fe0819a3f..92c0a62a9 100644
--- a/app/controllers/api/v1/favourites_controller.rb
+++ b/app/controllers/api/v1/favourites_controller.rb
@@ -9,14 +9,13 @@ class Api::V1::FavouritesController < Api::BaseController
 
   def index
     @statuses = load_statuses
+    render json: @statuses, each_serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id)
   end
 
   private
 
   def load_statuses
-    cached_favourites.tap do |statuses|
-      set_maps(statuses)
-    end
+    cached_favourites
   end
 
   def cached_favourites
diff --git a/app/controllers/api/v1/follow_requests_controller.rb b/app/controllers/api/v1/follow_requests_controller.rb
index eed22ef4f..b9f50d784 100644
--- a/app/controllers/api/v1/follow_requests_controller.rb
+++ b/app/controllers/api/v1/follow_requests_controller.rb
@@ -7,6 +7,7 @@ class Api::V1::FollowRequestsController < Api::BaseController
 
   def index
     @accounts = load_accounts
+    render json: @accounts, each_serializer: REST::AccountSerializer
   end
 
   def authorize
diff --git a/app/controllers/api/v1/follows_controller.rb b/app/controllers/api/v1/follows_controller.rb
index bcdb4e177..e01ae5c01 100644
--- a/app/controllers/api/v1/follows_controller.rb
+++ b/app/controllers/api/v1/follows_controller.rb
@@ -10,7 +10,7 @@ class Api::V1::FollowsController < Api::BaseController
     raise ActiveRecord::RecordNotFound if follow_params[:uri].blank?
 
     @account = FollowService.new.call(current_user.account, target_uri).try(:target_account)
-    render :show
+    render json: @account, serializer: REST::AccountSerializer
   end
 
   private
diff --git a/app/controllers/api/v1/instances_controller.rb b/app/controllers/api/v1/instances_controller.rb
index ce2181879..1c6971c18 100644
--- a/app/controllers/api/v1/instances_controller.rb
+++ b/app/controllers/api/v1/instances_controller.rb
@@ -3,5 +3,7 @@
 class Api::V1::InstancesController < Api::BaseController
   respond_to :json
 
-  def show; end
+  def show
+    render json: {}, serializer: REST::InstanceSerializer
+  end
 end
diff --git a/app/controllers/api/v1/media_controller.rb b/app/controllers/api/v1/media_controller.rb
index 25a331319..8a1992fca 100644
--- a/app/controllers/api/v1/media_controller.rb
+++ b/app/controllers/api/v1/media_controller.rb
@@ -11,6 +11,7 @@ class Api::V1::MediaController < Api::BaseController
 
   def create
     @media = current_account.media_attachments.create!(file: media_params[:file])
+    render json: @media, serializer: REST::MediaAttachmentSerializer
   rescue Paperclip::Errors::NotIdentifiedByImageMagickError
     render json: file_type_error, status: 422
   rescue Paperclip::Error
diff --git a/app/controllers/api/v1/mutes_controller.rb b/app/controllers/api/v1/mutes_controller.rb
index 2a353df03..0c43cb943 100644
--- a/app/controllers/api/v1/mutes_controller.rb
+++ b/app/controllers/api/v1/mutes_controller.rb
@@ -9,6 +9,7 @@ class Api::V1::MutesController < Api::BaseController
 
   def index
     @accounts = load_accounts
+    render json: @accounts, each_serializer: REST::AccountSerializer
   end
 
   private
diff --git a/app/controllers/api/v1/notifications_controller.rb b/app/controllers/api/v1/notifications_controller.rb
index a28e99f2f..8910b77e9 100644
--- a/app/controllers/api/v1/notifications_controller.rb
+++ b/app/controllers/api/v1/notifications_controller.rb
@@ -11,11 +11,12 @@ class Api::V1::NotificationsController < Api::BaseController
 
   def index
     @notifications = load_notifications
-    set_maps_for_notification_target_statuses
+    render json: @notifications, each_serializer: REST::NotificationSerializer, relationships: StatusRelationshipsPresenter.new(target_statuses_from_notifications, current_user&.account_id)
   end
 
   def show
     @notification = current_account.notifications.find(params[:id])
+    render json: @notification, serializer: REST::NotificationSerializer
   end
 
   def clear
@@ -46,10 +47,6 @@ class Api::V1::NotificationsController < Api::BaseController
     current_account.notifications.browserable(exclude_types)
   end
 
-  def set_maps_for_notification_target_statuses
-    set_maps target_statuses_from_notifications
-  end
-
   def target_statuses_from_notifications
     @notifications.reject { |notification| notification.target_status.nil? }.map(&:target_status)
   end
diff --git a/app/controllers/api/v1/reports_controller.rb b/app/controllers/api/v1/reports_controller.rb
index 8e7070d07..9592cd4bd 100644
--- a/app/controllers/api/v1/reports_controller.rb
+++ b/app/controllers/api/v1/reports_controller.rb
@@ -9,6 +9,7 @@ class Api::V1::ReportsController < Api::BaseController
 
   def index
     @reports = current_account.reports
+    render json: @reports, each_serializer: REST::ReportSerializer
   end
 
   def create
@@ -20,7 +21,7 @@ class Api::V1::ReportsController < Api::BaseController
 
     User.admins.includes(:account).each { |u| AdminMailer.new_report(u.account, @report).deliver_later }
 
-    render :show
+    render json: @report, serializer: REST::ReportSerializer
   end
 
   private
diff --git a/app/controllers/api/v1/search_controller.rb b/app/controllers/api/v1/search_controller.rb
index 8b832148c..1353682ea 100644
--- a/app/controllers/api/v1/search_controller.rb
+++ b/app/controllers/api/v1/search_controller.rb
@@ -6,7 +6,8 @@ class Api::V1::SearchController < Api::BaseController
   respond_to :json
 
   def index
-    @search = OpenStruct.new(search_results)
+    @search = Search.new(search_results)
+    render json: @search, serializer: REST::SearchSerializer
   end
 
   private
diff --git a/app/controllers/api/v1/statuses/favourited_by_accounts_controller.rb b/app/controllers/api/v1/statuses/favourited_by_accounts_controller.rb
index e58184939..f95cf9457 100644
--- a/app/controllers/api/v1/statuses/favourited_by_accounts_controller.rb
+++ b/app/controllers/api/v1/statuses/favourited_by_accounts_controller.rb
@@ -11,7 +11,7 @@ class Api::V1::Statuses::FavouritedByAccountsController < Api::BaseController
 
   def index
     @accounts = load_accounts
-    render 'api/v1/statuses/accounts'
+    render json: @accounts, each_serializer: REST::AccountSerializer
   end
 
   private
diff --git a/app/controllers/api/v1/statuses/favourites_controller.rb b/app/controllers/api/v1/statuses/favourites_controller.rb
index b6fb13cc0..4c4b0c160 100644
--- a/app/controllers/api/v1/statuses/favourites_controller.rb
+++ b/app/controllers/api/v1/statuses/favourites_controller.rb
@@ -10,7 +10,7 @@ class Api::V1::Statuses::FavouritesController < Api::BaseController
 
   def create
     @status = favourited_status
-    render 'api/v1/statuses/show'
+    render json: @status, serializer: REST::StatusSerializer
   end
 
   def destroy
@@ -19,7 +19,7 @@ class Api::V1::Statuses::FavouritesController < Api::BaseController
 
     UnfavouriteWorker.perform_async(current_user.account_id, @status.id)
 
-    render 'api/v1/statuses/show'
+    render json: @status, serializer: REST::StatusSerializer
   end
 
   private
diff --git a/app/controllers/api/v1/statuses/mutes_controller.rb b/app/controllers/api/v1/statuses/mutes_controller.rb
index eab88f2ef..a4bf0acdd 100644
--- a/app/controllers/api/v1/statuses/mutes_controller.rb
+++ b/app/controllers/api/v1/statuses/mutes_controller.rb
@@ -14,14 +14,14 @@ class Api::V1::Statuses::MutesController < Api::BaseController
     current_account.mute_conversation!(@conversation)
     @mutes_map = { @conversation.id => true }
 
-    render 'api/v1/statuses/show'
+    render json: @status, serializer: REST::StatusSerializer
   end
 
   def destroy
     current_account.unmute_conversation!(@conversation)
     @mutes_map = { @conversation.id => false }
 
-    render 'api/v1/statuses/show'
+    render json: @status, serializer: REST::StatusSerializer
   end
 
   private
diff --git a/app/controllers/api/v1/statuses/reblogged_by_accounts_controller.rb b/app/controllers/api/v1/statuses/reblogged_by_accounts_controller.rb
index 43593d3c5..175217e6e 100644
--- a/app/controllers/api/v1/statuses/reblogged_by_accounts_controller.rb
+++ b/app/controllers/api/v1/statuses/reblogged_by_accounts_controller.rb
@@ -11,7 +11,7 @@ class Api::V1::Statuses::RebloggedByAccountsController < Api::BaseController
 
   def index
     @accounts = load_accounts
-    render 'api/v1/statuses/accounts'
+    render json: @accounts, each_serializer: REST::AccountSerializer
   end
 
   private
diff --git a/app/controllers/api/v1/statuses/reblogs_controller.rb b/app/controllers/api/v1/statuses/reblogs_controller.rb
index ee9c5b3a6..f7f4b5a5c 100644
--- a/app/controllers/api/v1/statuses/reblogs_controller.rb
+++ b/app/controllers/api/v1/statuses/reblogs_controller.rb
@@ -10,7 +10,7 @@ class Api::V1::Statuses::ReblogsController < Api::BaseController
 
   def create
     @status = ReblogService.new.call(current_user.account, status_for_reblog)
-    render 'api/v1/statuses/show'
+    render json: @status, serializer: REST::StatusSerializer
   end
 
   def destroy
@@ -20,7 +20,7 @@ class Api::V1::Statuses::ReblogsController < Api::BaseController
     authorize status_for_destroy, :unreblog?
     RemovalWorker.perform_async(status_for_destroy.id)
 
-    render 'api/v1/statuses/show'
+    render json: @status, serializer: REST::StatusSerializer
   end
 
   private
diff --git a/app/controllers/api/v1/statuses_controller.rb b/app/controllers/api/v1/statuses_controller.rb
index 9aa1cbc4d..9c7124d0f 100644
--- a/app/controllers/api/v1/statuses_controller.rb
+++ b/app/controllers/api/v1/statuses_controller.rb
@@ -13,6 +13,7 @@ class Api::V1::StatusesController < Api::BaseController
   def show
     cached  = Rails.cache.read(@status.cache_key)
     @status = cached unless cached.nil?
+    render json: @status, serializer: REST::StatusSerializer
   end
 
   def context
@@ -21,15 +22,20 @@ class Api::V1::StatusesController < Api::BaseController
     loaded_ancestors    = cache_collection(ancestors_results, Status)
     loaded_descendants  = cache_collection(descendants_results, Status)
 
-    @context = OpenStruct.new(ancestors: loaded_ancestors, descendants: loaded_descendants)
-    statuses = [@status] + @context[:ancestors] + @context[:descendants]
+    @context = Context.new(ancestors: loaded_ancestors, descendants: loaded_descendants)
+    statuses = [@status] + @context.ancestors + @context.descendants
 
-    set_maps(statuses)
+    render json: @context, serializer: REST::ContextSerializer, relationships: StatusRelationshipsPresenter.new(statuses, current_user&.account_id)
   end
 
   def card
     @card = PreviewCard.find_by(status: @status)
-    render_empty if @card.nil?
+
+    if @card.nil?
+      render_empty
+    else
+      render json: @card, serializer: REST::PreviewCardSerializer
+    end
   end
 
   def create
@@ -43,7 +49,7 @@ class Api::V1::StatusesController < Api::BaseController
                                          application: doorkeeper_token.application,
                                          idempotency: request.headers['Idempotency-Key'])
 
-    render :show
+    render json: @status, serializer: REST::StatusSerializer
   end
 
   def destroy
diff --git a/app/controllers/api/v1/timelines/home_controller.rb b/app/controllers/api/v1/timelines/home_controller.rb
index 511d2f65d..3dd27710c 100644
--- a/app/controllers/api/v1/timelines/home_controller.rb
+++ b/app/controllers/api/v1/timelines/home_controller.rb
@@ -9,15 +9,13 @@ class Api::V1::Timelines::HomeController < Api::BaseController
 
   def show
     @statuses = load_statuses
-    render 'api/v1/timelines/show'
+    render json: @statuses, each_serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id)
   end
 
   private
 
   def load_statuses
-    cached_home_statuses.tap do |statuses|
-      set_maps(statuses)
-    end
+    cached_home_statuses
   end
 
   def cached_home_statuses
diff --git a/app/controllers/api/v1/timelines/public_controller.rb b/app/controllers/api/v1/timelines/public_controller.rb
index 305451cc7..49887778e 100644
--- a/app/controllers/api/v1/timelines/public_controller.rb
+++ b/app/controllers/api/v1/timelines/public_controller.rb
@@ -7,15 +7,13 @@ class Api::V1::Timelines::PublicController < Api::BaseController
 
   def show
     @statuses = load_statuses
-    render 'api/v1/timelines/show'
+    render json: @statuses, each_serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id)
   end
 
   private
 
   def load_statuses
-    cached_public_statuses.tap do |statuses|
-      set_maps(statuses)
-    end
+    cached_public_statuses
   end
 
   def cached_public_statuses
diff --git a/app/controllers/api/v1/timelines/tag_controller.rb b/app/controllers/api/v1/timelines/tag_controller.rb
index 50afca7c7..08db04a39 100644
--- a/app/controllers/api/v1/timelines/tag_controller.rb
+++ b/app/controllers/api/v1/timelines/tag_controller.rb
@@ -8,7 +8,7 @@ class Api::V1::Timelines::TagController < Api::BaseController
 
   def show
     @statuses = load_statuses
-    render 'api/v1/timelines/show'
+    render json: @statuses, each_serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id)
   end
 
   private
@@ -18,9 +18,7 @@ class Api::V1::Timelines::TagController < Api::BaseController
   end
 
   def load_statuses
-    cached_tagged_statuses.tap do |statuses|
-      set_maps(statuses)
-    end
+    cached_tagged_statuses
   end
 
   def cached_tagged_statuses
diff --git a/app/lib/inline_rabl_scope.rb b/app/lib/inline_rabl_scope.rb
deleted file mode 100644
index 26adcb03a..000000000
--- a/app/lib/inline_rabl_scope.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class InlineRablScope
-  include RoutingHelper
-
-  def initialize(account)
-    @account = account
-  end
-
-  def current_user
-    @account.try(:user)
-  end
-
-  def current_account
-    @account
-  end
-end
diff --git a/app/lib/inline_renderer.rb b/app/lib/inline_renderer.rb
index 8e04ad1d5..7cd9758ec 100644
--- a/app/lib/inline_renderer.rb
+++ b/app/lib/inline_renderer.rb
@@ -1,13 +1,33 @@
 # frozen_string_literal: true
 
 class InlineRenderer
-  def self.render(status, current_account, template)
-    Rabl::Renderer.new(
-      template,
-      status,
-      view_path: 'app/views',
-      format: :json,
-      scope: InlineRablScope.new(current_account)
-    ).render
+  def initialize(object, current_account, template)
+    @object          = object
+    @current_account = current_account
+    @template        = template
+  end
+
+  def render
+    case @template
+    when :status
+      serializer = REST::StatusSerializer
+    when :notification
+      serializer = REST::NotificationSerializer
+    else
+      return
+    end
+
+    serializable_resource = ActiveModelSerializers::SerializableResource.new(@object, serializer: serializer, scope: current_user, scope_name: :current_user)
+    serializable_resource.as_json
+  end
+
+  def self.render(object, current_account, template)
+    new(object, current_account, template).render
+  end
+
+  private
+
+  def current_user
+    @current_account&.user
   end
 end
diff --git a/app/models/context.rb b/app/models/context.rb
new file mode 100644
index 000000000..cc667999e
--- /dev/null
+++ b/app/models/context.rb
@@ -0,0 +1,5 @@
+# frozen_string_literal: true
+
+class Context < ActiveModelSerializers::Model
+  attributes :ancestors, :descendants
+end
diff --git a/app/models/search.rb b/app/models/search.rb
new file mode 100644
index 000000000..676c2a7f8
--- /dev/null
+++ b/app/models/search.rb
@@ -0,0 +1,5 @@
+# frozen_string_literal: true
+
+class Search < ActiveModelSerializers::Model
+  attributes :accounts, :statuses, :hashtags
+end
diff --git a/app/presenters/account_relationships_presenter.rb b/app/presenters/account_relationships_presenter.rb
new file mode 100644
index 000000000..657807863
--- /dev/null
+++ b/app/presenters/account_relationships_presenter.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class AccountRelationshipsPresenter
+  attr_reader :following, :followed_by, :blocking,
+              :muting, :requested, :domain_blocking
+
+  def initialize(account_ids, current_account_id)
+    @following       = Account.following_map(account_ids, current_account_id)
+    @followed_by     = Account.followed_by_map(account_ids, current_account_id)
+    @blocking        = Account.blocking_map(account_ids, current_account_id)
+    @muting          = Account.muting_map(account_ids, current_account_id)
+    @requested       = Account.requested_map(account_ids, current_account_id)
+    @domain_blocking = Account.domain_blocking_map(account_ids, current_account_id)
+  end
+end
diff --git a/app/presenters/status_relationships_presenter.rb b/app/presenters/status_relationships_presenter.rb
new file mode 100644
index 000000000..caf00791a
--- /dev/null
+++ b/app/presenters/status_relationships_presenter.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class StatusRelationshipsPresenter
+  attr_reader :reblogs_map, :favourites_map, :mutes_map
+
+  def initialize(statuses, current_account_id = nil)
+    if current_account_id.nil?
+      @reblogs_map    = {}
+      @favourites_map = {}
+      @mutes_map      = {}
+    else
+      status_ids       = statuses.compact.flat_map { |s| [s.id, s.reblog_of_id] }.uniq
+      conversation_ids = statuses.compact.map(&:conversation_id).compact.uniq
+      @reblogs_map     = Status.reblogs_map(status_ids, current_account_id)
+      @favourites_map  = Status.favourites_map(status_ids, current_account_id)
+      @mutes_map       = Status.mutes_map(conversation_ids, current_account_id)
+    end
+  end
+end
diff --git a/app/serializers/rest/account_serializer.rb b/app/serializers/rest/account_serializer.rb
new file mode 100644
index 000000000..012a4fd18
--- /dev/null
+++ b/app/serializers/rest/account_serializer.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+class REST::AccountSerializer < ActiveModel::Serializer
+  include RoutingHelper
+
+  attributes :id, :username, :acct, :display_name, :locked, :created_at,
+             :note, :url, :avatar, :avatar_static, :header, :header_static,
+             :followers_count, :following_count, :statuses_count
+
+  def note
+    Formatter.instance.simplified_format(object)
+  end
+
+  def url
+    TagManager.instance.url_for(object)
+  end
+
+  def avatar
+    full_asset_url(object.avatar_original_url)
+  end
+
+  def avatar_static
+    full_asset_url(object.avatar_static_url)
+  end
+
+  def header
+    full_asset_url(object.header_original_url)
+  end
+
+  def header_static
+    full_asset_url(object.header_static_url)
+  end
+end
diff --git a/app/serializers/rest/application_serializer.rb b/app/serializers/rest/application_serializer.rb
new file mode 100644
index 000000000..868a62f1e
--- /dev/null
+++ b/app/serializers/rest/application_serializer.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+class REST::ApplicationSerializer < ActiveModel::Serializer
+  attributes :id, :name, :website, :redirect_uri,
+             :client_id, :client_secret
+
+  def client_id
+    object.uid
+  end
+
+  def client_secret
+    object.secret
+  end
+end
diff --git a/app/serializers/rest/context_serializer.rb b/app/serializers/rest/context_serializer.rb
new file mode 100644
index 000000000..44515c85d
--- /dev/null
+++ b/app/serializers/rest/context_serializer.rb
@@ -0,0 +1,6 @@
+# frozen_string_literal: true
+
+class REST::ContextSerializer < ActiveModel::Serializer
+  has_many :ancestors,   serializer: REST::StatusSerializer
+  has_many :descendants, serializer: REST::StatusSerializer
+end
diff --git a/app/serializers/rest/instance_serializer.rb b/app/serializers/rest/instance_serializer.rb
new file mode 100644
index 000000000..8e32f9cb3
--- /dev/null
+++ b/app/serializers/rest/instance_serializer.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+class REST::InstanceSerializer < ActiveModel::Serializer
+  attributes :uri, :title, :description, :email,
+             :version, :urls
+
+  def uri
+    Rails.configuration.x.local_domain
+  end
+
+  def title
+    Setting.site_title
+  end
+
+  def description
+    Setting.site_description
+  end
+
+  def email
+    Setting.site_contact_email
+  end
+
+  def version
+    Mastodon::Version.to_s
+  end
+
+  def urls
+    { streaming_api: Rails.configuration.x.streaming_api_base_url }
+  end
+end
diff --git a/app/serializers/rest/media_attachment_serializer.rb b/app/serializers/rest/media_attachment_serializer.rb
new file mode 100644
index 000000000..9b07a686e
--- /dev/null
+++ b/app/serializers/rest/media_attachment_serializer.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+class REST::MediaAttachmentSerializer < ActiveModel::Serializer
+  include RoutingHelper
+
+  attributes :id, :type, :url, :preview_url,
+             :remote_url, :text_url, :meta
+
+  def url
+    full_asset_url(object.file.url(:original))
+  end
+
+  def preview_url
+    full_asset_url(object.file.url(:small))
+  end
+
+  def text_url
+    medium_url(object.id)
+  end
+
+  def meta
+    object.file.meta
+  end
+end
diff --git a/app/serializers/rest/notification_serializer.rb b/app/serializers/rest/notification_serializer.rb
new file mode 100644
index 000000000..97fadf32e
--- /dev/null
+++ b/app/serializers/rest/notification_serializer.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+class REST::NotificationSerializer < ActiveModel::Serializer
+  attributes :id, :type, :created_at
+
+  belongs_to :from_account, key: :account, serializer: REST::AccountSerializer
+  belongs_to :status, if: :status_type?,   serializer: REST::StatusSerializer
+
+  def status_type?
+    [:favourite, :reblog, :mention].include?(object.type)
+  end
+end
diff --git a/app/serializers/rest/preview_card_serializer.rb b/app/serializers/rest/preview_card_serializer.rb
new file mode 100644
index 000000000..9c460332c
--- /dev/null
+++ b/app/serializers/rest/preview_card_serializer.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+class REST::PreviewCardSerializer < ActiveModel::Serializer
+  include RoutingHelper
+
+  attributes :url, :title, :description, :type,
+             :author_name, :author_url, :provider_name,
+             :provider_url, :html, :width, :height,
+             :image
+
+  def image
+    object.image? ? full_asset_url(object.image.url(:original)) : nil
+  end
+end
diff --git a/app/serializers/rest/relationship_serializer.rb b/app/serializers/rest/relationship_serializer.rb
new file mode 100644
index 000000000..1d431aa1b
--- /dev/null
+++ b/app/serializers/rest/relationship_serializer.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+class REST::RelationshipSerializer < ActiveModel::Serializer
+  attributes :id, :following, :followed_by, :blocking,
+             :muting, :requested, :domain_blocking
+
+  def following
+    instance_options[:relationships].following[object.id] || false
+  end
+
+  def followed_by
+    instance_options[:relationships].followed_by[object.id] || false
+  end
+
+  def blocking
+    instance_options[:relationships].blocking[object.id] || false
+  end
+
+  def muting
+    instance_options[:relationships].muting[object.id] || false
+  end
+
+  def requested
+    instance_options[:relationships].requested[object.id] || false
+  end
+
+  def domain_blocking
+    instance_options[:relationships].domain_blocking[object.id] || false
+  end
+end
diff --git a/app/serializers/rest/report_serializer.rb b/app/serializers/rest/report_serializer.rb
new file mode 100644
index 000000000..0c6bd6556
--- /dev/null
+++ b/app/serializers/rest/report_serializer.rb
@@ -0,0 +1,5 @@
+# frozen_string_literal: true
+
+class REST::ReportSerializer < ActiveModel::Serializer
+  attributes :id, :action_taken
+end
diff --git a/app/serializers/rest/search_serializer.rb b/app/serializers/rest/search_serializer.rb
new file mode 100644
index 000000000..157f543ae
--- /dev/null
+++ b/app/serializers/rest/search_serializer.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+class REST::SearchSerializer < ActiveModel::Serializer
+  attributes :hashtags
+
+  has_many :accounts, serializer: REST::AccountSerializer
+  has_many :statuses, serializer: REST::StatusSerializer
+
+  def hashtags
+    object.hashtags.map(&:name)
+  end
+end
diff --git a/app/serializers/rest/status_serializer.rb b/app/serializers/rest/status_serializer.rb
new file mode 100644
index 000000000..246b12a90
--- /dev/null
+++ b/app/serializers/rest/status_serializer.rb
@@ -0,0 +1,93 @@
+# frozen_string_literal: true
+
+class REST::StatusSerializer < ActiveModel::Serializer
+  attributes :id, :created_at, :in_reply_to_id, :in_reply_to_account_id,
+             :sensitive, :spoiler_text, :visibility, :language,
+             :uri, :content, :url, :reblogs_count, :favourites_count
+
+  attribute :favourited, if: :current_user?
+  attribute :reblogged, if: :current_user?
+  attribute :muted, if: :current_user?
+
+  belongs_to :reblog, serializer: REST::StatusSerializer
+  belongs_to :application
+  belongs_to :account, serializer: REST::AccountSerializer
+
+  has_many :media_attachments, serializer: REST::MediaAttachmentSerializer
+  has_many :mentions
+  has_many :tags
+
+  def current_user?
+    !current_user.nil?
+  end
+
+  def uri
+    TagManager.instance.uri_for(object)
+  end
+
+  def content
+    Formatter.instance.format(object)
+  end
+
+  def url
+    TagManager.instance.url_for(object)
+  end
+
+  def favourited
+    if instance_options && instance_options[:relationships]
+      instance_options[:relationships].favourites_map[object.id] || false
+    else
+      current_user.account.favourited?(object)
+    end
+  end
+
+  def reblogged
+    if instance_options && instance_options[:relationships]
+      instance_options[:relationships].reblogs_map[object.id] || false
+    else
+      current_user.account.reblogged?(object)
+    end
+  end
+
+  def muted
+    if instance_options && instance_options[:relationships]
+      instance_options[:relationships].mutes_map[object.conversation_id] || false
+    else
+      current_user.account.muting_conversation?(object.conversation)
+    end
+  end
+
+  class ApplicationSerializer < ActiveModel::Serializer
+    attributes :name, :website
+  end
+
+  class MentionSerializer < ActiveModel::Serializer
+    attributes :id, :username, :url, :acct
+
+    def id
+      object.account_id
+    end
+
+    def username
+      object.account_username
+    end
+
+    def url
+      TagManager.instance.url_for(object.account)
+    end
+
+    def acct
+      object.account_acct
+    end
+  end
+
+  class TagSerializer < ActiveModel::Serializer
+    include RoutingHelper
+
+    attributes :name, :url
+
+    def url
+      tag_url(object)
+    end
+  end
+end
diff --git a/app/services/fan_out_on_write_service.rb b/app/services/fan_out_on_write_service.rb
index 3b74696d5..47a47a735 100644
--- a/app/services/fan_out_on_write_service.rb
+++ b/app/services/fan_out_on_write_service.rb
@@ -54,7 +54,7 @@ class FanOutOnWriteService < BaseService
   end
 
   def render_anonymous_payload(status)
-    @payload = InlineRenderer.render(status, nil, 'api/v1/statuses/show')
+    @payload = InlineRenderer.render(status, nil, :status)
     @payload = Oj.dump(event: :update, payload: @payload)
   end
 
diff --git a/app/services/notify_service.rb b/app/services/notify_service.rb
index 422d5f97e..407d385ea 100644
--- a/app/services/notify_service.rb
+++ b/app/services/notify_service.rb
@@ -60,7 +60,7 @@ class NotifyService < BaseService
   def create_notification
     @notification.save!
     return unless @notification.browserable?
-    Redis.current.publish("timeline:#{@recipient.id}", Oj.dump(event: :notification, payload: InlineRenderer.render(@notification, @recipient, 'api/v1/notifications/show')))
+    Redis.current.publish("timeline:#{@recipient.id}", Oj.dump(event: :notification, payload: InlineRenderer.render(@notification, @recipient, :notification)))
   end
 
   def send_email
diff --git a/app/views/api/v1/accounts/index.rabl b/app/views/api/v1/accounts/index.rabl
deleted file mode 100644
index 9f3b13a53..000000000
--- a/app/views/api/v1/accounts/index.rabl
+++ /dev/null
@@ -1,2 +0,0 @@
-collection @accounts
-extends 'api/v1/accounts/show'
diff --git a/app/views/api/v1/accounts/relationship.rabl b/app/views/api/v1/accounts/relationship.rabl
deleted file mode 100644
index 4f7763d9d..000000000
--- a/app/views/api/v1/accounts/relationship.rabl
+++ /dev/null
@@ -1,9 +0,0 @@
-object @account
-
-attribute :id
-node(:following)       { |account| @following[account.id]       || false }
-node(:followed_by)     { |account| @followed_by[account.id]     || false }
-node(:blocking)        { |account| @blocking[account.id]        || false }
-node(:muting)          { |account| @muting[account.id]          || false }
-node(:requested)       { |account| @requested[account.id]       || false }
-node(:domain_blocking) { |account| @domain_blocking[account.id] || false }
diff --git a/app/views/api/v1/accounts/relationships/index.rabl b/app/views/api/v1/accounts/relationships/index.rabl
deleted file mode 100644
index 022ea2ac4..000000000
--- a/app/views/api/v1/accounts/relationships/index.rabl
+++ /dev/null
@@ -1,2 +0,0 @@
-collection @accounts
-extends 'api/v1/accounts/relationship'
diff --git a/app/views/api/v1/accounts/show.rabl b/app/views/api/v1/accounts/show.rabl
deleted file mode 100644
index 8826aa22d..000000000
--- a/app/views/api/v1/accounts/show.rabl
+++ /dev/null
@@ -1,12 +0,0 @@
-object @account
-
-attributes :id, :username, :acct, :display_name, :locked, :created_at
-
-node(:note)            { |account| Formatter.instance.simplified_format(account) }
-node(:url)             { |account| TagManager.instance.url_for(account) }
-node(:avatar)          { |account| full_asset_url(account.avatar_original_url) }
-node(:avatar_static)   { |account| full_asset_url(account.avatar_static_url) }
-node(:header)          { |account| full_asset_url(account.header_original_url) }
-node(:header_static)   { |account| full_asset_url(account.header_static_url) }
-
-attributes :followers_count, :following_count, :statuses_count
diff --git a/app/views/api/v1/accounts/statuses/index.rabl b/app/views/api/v1/accounts/statuses/index.rabl
deleted file mode 100644
index 44d29d91b..000000000
--- a/app/views/api/v1/accounts/statuses/index.rabl
+++ /dev/null
@@ -1,2 +0,0 @@
-collection @statuses
-extends 'api/v1/statuses/show'
diff --git a/app/views/api/v1/apps/create.rabl b/app/views/api/v1/apps/create.rabl
deleted file mode 100644
index 1ff6469a4..000000000
--- a/app/views/api/v1/apps/create.rabl
+++ /dev/null
@@ -1,4 +0,0 @@
-object @app
-attributes :id, :redirect_uri
-node(:client_id) { |app| app.uid }
-node(:client_secret) { |app| app.secret }
diff --git a/app/views/api/v1/apps/show.rabl b/app/views/api/v1/apps/show.rabl
deleted file mode 100644
index 6d9e607db..000000000
--- a/app/views/api/v1/apps/show.rabl
+++ /dev/null
@@ -1,3 +0,0 @@
-object @application
-
-attributes :name, :website
diff --git a/app/views/api/v1/blocks/index.rabl b/app/views/api/v1/blocks/index.rabl
deleted file mode 100644
index 9f3b13a53..000000000
--- a/app/views/api/v1/blocks/index.rabl
+++ /dev/null
@@ -1,2 +0,0 @@
-collection @accounts
-extends 'api/v1/accounts/show'
diff --git a/app/views/api/v1/favourites/index.rabl b/app/views/api/v1/favourites/index.rabl
deleted file mode 100644
index 44d29d91b..000000000
--- a/app/views/api/v1/favourites/index.rabl
+++ /dev/null
@@ -1,2 +0,0 @@
-collection @statuses
-extends 'api/v1/statuses/show'
diff --git a/app/views/api/v1/follow_requests/index.rabl b/app/views/api/v1/follow_requests/index.rabl
deleted file mode 100644
index 9f3b13a53..000000000
--- a/app/views/api/v1/follow_requests/index.rabl
+++ /dev/null
@@ -1,2 +0,0 @@
-collection @accounts
-extends 'api/v1/accounts/show'
diff --git a/app/views/api/v1/follows/show.rabl b/app/views/api/v1/follows/show.rabl
deleted file mode 100644
index e07106164..000000000
--- a/app/views/api/v1/follows/show.rabl
+++ /dev/null
@@ -1,2 +0,0 @@
-object @account
-extends('api/v1/accounts/show')
diff --git a/app/views/api/v1/instances/show.rabl b/app/views/api/v1/instances/show.rabl
deleted file mode 100644
index 05fb65031..000000000
--- a/app/views/api/v1/instances/show.rabl
+++ /dev/null
@@ -1,10 +0,0 @@
-object false
-
-node(:uri)         { site_hostname }
-node(:title)       { Setting.site_title }
-node(:description) { Setting.site_description }
-node(:email)       { Setting.site_contact_email }
-node(:version)     { Mastodon::Version.to_s }
-node :urls do
-    { :streaming_api => Rails.configuration.x.streaming_api_base_url }
-end
diff --git a/app/views/api/v1/media/create.rabl b/app/views/api/v1/media/create.rabl
deleted file mode 100644
index 53c13bbda..000000000
--- a/app/views/api/v1/media/create.rabl
+++ /dev/null
@@ -1,7 +0,0 @@
-object @media
-attribute :id, :type
-
-node(:url)         { |media| full_asset_url(media.file.url(:original)) }
-node(:preview_url) { |media| full_asset_url(media.file.url(:small)) }
-node(:text_url)    { |media| medium_url(media) }
-node(:meta)        { |media| media.file.meta }
diff --git a/app/views/api/v1/mutes/index.rabl b/app/views/api/v1/mutes/index.rabl
deleted file mode 100644
index 9f3b13a53..000000000
--- a/app/views/api/v1/mutes/index.rabl
+++ /dev/null
@@ -1,2 +0,0 @@
-collection @accounts
-extends 'api/v1/accounts/show'
diff --git a/app/views/api/v1/notifications/index.rabl b/app/views/api/v1/notifications/index.rabl
deleted file mode 100644
index 6abc3da36..000000000
--- a/app/views/api/v1/notifications/index.rabl
+++ /dev/null
@@ -1,2 +0,0 @@
-collection @notifications
-extends 'api/v1/notifications/show'
diff --git a/app/views/api/v1/notifications/show.rabl b/app/views/api/v1/notifications/show.rabl
deleted file mode 100644
index ca34f2d5d..000000000
--- a/app/views/api/v1/notifications/show.rabl
+++ /dev/null
@@ -1,11 +0,0 @@
-object @notification
-
-attributes :id, :type, :created_at
-
-child from_account: :account do
-  extends 'api/v1/accounts/show'
-end
-
-node(:status, if: lambda { |n| [:favourite, :reblog, :mention].include?(n.type) }) do |n|
-  partial 'api/v1/statuses/show', object: n.target_status
-end
diff --git a/app/views/api/v1/reports/index.rabl b/app/views/api/v1/reports/index.rabl
deleted file mode 100644
index 4f0794027..000000000
--- a/app/views/api/v1/reports/index.rabl
+++ /dev/null
@@ -1,2 +0,0 @@
-collection @reports
-extends 'api/v1/reports/show'
diff --git a/app/views/api/v1/reports/show.rabl b/app/views/api/v1/reports/show.rabl
deleted file mode 100644
index 006db51e3..000000000
--- a/app/views/api/v1/reports/show.rabl
+++ /dev/null
@@ -1,2 +0,0 @@
-object @report
-attributes :id, :action_taken
diff --git a/app/views/api/v1/search/index.rabl b/app/views/api/v1/search/index.rabl
deleted file mode 100644
index 8d1640f2d..000000000
--- a/app/views/api/v1/search/index.rabl
+++ /dev/null
@@ -1,13 +0,0 @@
-object @search
-
-child :accounts, object_root: false do
-  extends 'api/v1/accounts/show'
-end
-
-node(:hashtags) do |search|
-  search.hashtags.map(&:name)
-end
-
-child :statuses, object_root: false do
-  extends 'api/v1/statuses/show'
-end
diff --git a/app/views/api/v1/statuses/_media.rabl b/app/views/api/v1/statuses/_media.rabl
deleted file mode 100644
index 07ac31888..000000000
--- a/app/views/api/v1/statuses/_media.rabl
+++ /dev/null
@@ -1,6 +0,0 @@
-attributes :id, :remote_url, :type
-
-node(:url)         { |media| full_asset_url(media.file.url(:original)) }
-node(:preview_url) { |media| full_asset_url(media.file.url(:small)) }
-node(:text_url)    { |media| media.local? ? medium_url(media) : nil }
-node(:meta)        { |media| media.file.meta }
diff --git a/app/views/api/v1/statuses/_mention.rabl b/app/views/api/v1/statuses/_mention.rabl
deleted file mode 100644
index 8c95fc9bd..000000000
--- a/app/views/api/v1/statuses/_mention.rabl
+++ /dev/null
@@ -1,4 +0,0 @@
-node(:url)      { |mention| TagManager.instance.url_for(mention.account) }
-node(:acct)     { |mention| mention.account_acct }
-node(:id)       { |mention| mention.account_id }
-node(:username) { |mention| mention.account_username }
diff --git a/app/views/api/v1/statuses/_show.rabl b/app/views/api/v1/statuses/_show.rabl
deleted file mode 100644
index fe3ec89ab..000000000
--- a/app/views/api/v1/statuses/_show.rabl
+++ /dev/null
@@ -1,29 +0,0 @@
-attributes :id, :created_at, :in_reply_to_id,
-           :in_reply_to_account_id, :sensitive,
-           :spoiler_text, :visibility, :language
-
-node(:uri)              { |status| TagManager.instance.uri_for(status) }
-node(:content)          { |status| Formatter.instance.format(status) }
-node(:url)              { |status| TagManager.instance.url_for(status) }
-node(:reblogs_count)    { |status| defined?(@reblogs_counts_map)    ? (@reblogs_counts_map[status.id]    || 0) : status.reblogs_count }
-node(:favourites_count) { |status| defined?(@favourites_counts_map) ? (@favourites_counts_map[status.id] || 0) : status.favourites_count }
-
-child :application do
-  extends 'api/v1/apps/show'
-end
-
-child :account do
-  extends 'api/v1/accounts/show'
-end
-
-child :media_attachments, object_root: false do
-  extends 'api/v1/statuses/_media'
-end
-
-child :mentions, object_root: false do
-  extends 'api/v1/statuses/_mention'
-end
-
-child :tags, object_root: false do
-  extends 'api/v1/statuses/_tags'
-end
diff --git a/app/views/api/v1/statuses/_tags.rabl b/app/views/api/v1/statuses/_tags.rabl
deleted file mode 100644
index 25e7b0fac..000000000
--- a/app/views/api/v1/statuses/_tags.rabl
+++ /dev/null
@@ -1,2 +0,0 @@
-attribute :name
-node(:url) { |tag| tag_url(tag) }
diff --git a/app/views/api/v1/statuses/accounts.rabl b/app/views/api/v1/statuses/accounts.rabl
deleted file mode 100644
index 9f3b13a53..000000000
--- a/app/views/api/v1/statuses/accounts.rabl
+++ /dev/null
@@ -1,2 +0,0 @@
-collection @accounts
-extends 'api/v1/accounts/show'
diff --git a/app/views/api/v1/statuses/card.rabl b/app/views/api/v1/statuses/card.rabl
deleted file mode 100644
index 5d8d7af3b..000000000
--- a/app/views/api/v1/statuses/card.rabl
+++ /dev/null
@@ -1,7 +0,0 @@
-object @card
-
-attributes :url, :title, :description, :type,
-           :author_name, :author_url, :provider_name,
-           :provider_url, :html, :width, :height
-
-node(:image) { |card| card.image? ? full_asset_url(card.image.url(:original)) : nil }
diff --git a/app/views/api/v1/statuses/context.rabl b/app/views/api/v1/statuses/context.rabl
deleted file mode 100644
index 0b62f26d5..000000000
--- a/app/views/api/v1/statuses/context.rabl
+++ /dev/null
@@ -1,9 +0,0 @@
-object @context
-
-node :ancestors do |context|
-  partial 'api/v1/statuses/index', object: context.ancestors
-end
-
-node :descendants do |context|
-  partial 'api/v1/statuses/index', object: context.descendants
-end
diff --git a/app/views/api/v1/statuses/index.rabl b/app/views/api/v1/statuses/index.rabl
deleted file mode 100644
index 0a0ed13c5..000000000
--- a/app/views/api/v1/statuses/index.rabl
+++ /dev/null
@@ -1,2 +0,0 @@
-collection @statuses
-extends('api/v1/statuses/show')
diff --git a/app/views/api/v1/statuses/show.rabl b/app/views/api/v1/statuses/show.rabl
deleted file mode 100644
index 4b33fb2c3..000000000
--- a/app/views/api/v1/statuses/show.rabl
+++ /dev/null
@@ -1,15 +0,0 @@
-object @status
-
-extends 'api/v1/statuses/_show'
-
-node(:favourited, if: proc { !current_account.nil? }) { |status| defined?(@favourites_map) ? @favourites_map[status.id]         : current_account.favourited?(status) }
-node(:reblogged,  if: proc { !current_account.nil? }) { |status| defined?(@reblogs_map)    ? @reblogs_map[status.id]            : current_account.reblogged?(status) }
-node(:muted,      if: proc { !current_account.nil? }) { |status| defined?(@mutes_map)      ? @mutes_map[status.conversation_id] : current_account.muting_conversation?(status.conversation) }
-
-child reblog: :reblog do
-  extends 'api/v1/statuses/_show'
-
-  node(:favourited, if: proc { !current_account.nil? }) { |status| defined?(@favourites_map) ? @favourites_map[status.id] : current_account.favourited?(status) }
-  node(:reblogged,  if: proc { !current_account.nil? }) { |status| defined?(@reblogs_map)    ? @reblogs_map[status.id]    : current_account.reblogged?(status) }
-  node(:muted,      if: proc { !current_account.nil? }) { false }
-end
diff --git a/app/views/api/v1/timelines/show.rabl b/app/views/api/v1/timelines/show.rabl
deleted file mode 100644
index 0a0ed13c5..000000000
--- a/app/views/api/v1/timelines/show.rabl
+++ /dev/null
@@ -1,2 +0,0 @@
-collection @statuses
-extends('api/v1/statuses/show')
diff --git a/app/views/home/initial_state.json.rabl b/app/views/home/initial_state.json.rabl
index 291ff806b..c428a5a1f 100644
--- a/app/views/home/initial_state.json.rabl
+++ b/app/views/home/initial_state.json.rabl
@@ -24,8 +24,8 @@ end
 
 node(:accounts) do
   store = {}
-  store[current_account.id] = partial('api/v1/accounts/show', object: current_account)
-  store[@admin.id] = partial('api/v1/accounts/show', object: @admin) unless @admin.nil?
+  store[current_account.id] = ActiveModelSerializers::SerializableResource.new(current_account, serializer: REST::AccountSerializer)
+  store[@admin.id] = ActiveModelSerializers::SerializableResource.new(@admin, serializer: REST::AccountSerializer) unless @admin.nil?
   store
 end
 
diff --git a/app/workers/push_update_worker.rb b/app/workers/push_update_worker.rb
index fbcdcf634..697cbd6a6 100644
--- a/app/workers/push_update_worker.rb
+++ b/app/workers/push_update_worker.rb
@@ -6,7 +6,7 @@ class PushUpdateWorker
   def perform(account_id, status_id)
     account = Account.find(account_id)
     status  = Status.find(status_id)
-    message = InlineRenderer.render(status, account, 'api/v1/statuses/show')
+    message = InlineRenderer.render(status, account, :status)
 
     Redis.current.publish("timeline:#{account.id}", Oj.dump(event: :update, payload: message, queued_at: (Time.now.to_f * 1000.0).to_i))
   rescue ActiveRecord::RecordNotFound
diff --git a/spec/lib/inline_rabl_scope_spec.rb b/spec/lib/inline_rabl_scope_spec.rb
deleted file mode 100644
index 3fff176e4..000000000
--- a/spec/lib/inline_rabl_scope_spec.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe InlineRablScope do
-  describe '#current_account' do
-    it 'returns the given account' do
-      account = Fabricate(:account)
-      expect(InlineRablScope.new(account).current_account).to eq account
-    end
-  end
-
-  describe '#current_user' do
-    it 'returns nil if the given account is nil' do
-      expect(InlineRablScope.new(nil).current_user).to eq nil
-    end
-
-    it 'returns user of account if the given account is not nil' do
-      user = Fabricate(:user)
-      expect(InlineRablScope.new(user.account).current_user).to eq user
-    end
-  end
-end