diff --git a/app/controllers/api/oembed_controller.rb b/app/controllers/api/oembed_controller.rb
index f8c87dd16ee1e818beb969f8842e6e7021d5a284..37a163cd333d32ae0e672efc37e2d8243057b856 100644
--- a/app/controllers/api/oembed_controller.rb
+++ b/app/controllers/api/oembed_controller.rb
@@ -4,14 +4,14 @@ class Api::OEmbedController < Api::BaseController
   respond_to :json
 
   def show
-    @stream_entry = find_stream_entry.stream_entry
-    render json: @stream_entry, serializer: OEmbedSerializer, width: maxwidth_or_default, height: maxheight_or_default
+    @status = status_finder.status
+    render json: @status, serializer: OEmbedSerializer, width: maxwidth_or_default, height: maxheight_or_default
   end
 
   private
 
-  def find_stream_entry
-    StreamEntryFinder.new(params[:url])
+  def status_finder
+    StatusFinder.new(params[:url])
   end
 
   def maxwidth_or_default
diff --git a/app/controllers/statuses_controller.rb b/app/controllers/statuses_controller.rb
index a9768d09298604d89abaacb51771c2342f98ae68..65206ea969e54923aeb4e66902c5d4fab05d554b 100644
--- a/app/controllers/statuses_controller.rb
+++ b/app/controllers/statuses_controller.rb
@@ -30,6 +30,11 @@ class StatusesController < ApplicationController
     render json: @status, serializer: ActivityPub::ActivitySerializer, adapter: ActivityPub::Adapter, content_type: 'application/activity+json'
   end
 
+  def embed
+    response.headers['X-Frame-Options'] = 'ALLOWALL'
+    render 'stream_entries/embed', layout: 'embedded'
+  end
+
   private
 
   def set_account
diff --git a/app/controllers/stream_entries_controller.rb b/app/controllers/stream_entries_controller.rb
index ccb15495e4252af697cdb98227c6ac23eebcd8f2..cc579dbc8898b1c85ac41b19a5a83eaa33f76503 100644
--- a/app/controllers/stream_entries_controller.rb
+++ b/app/controllers/stream_entries_controller.rb
@@ -25,10 +25,7 @@ class StreamEntriesController < ApplicationController
   end
 
   def embed
-    response.headers['X-Frame-Options'] = 'ALLOWALL'
-    return gone if @stream_entry.activity.nil?
-
-    render layout: 'embedded'
+    redirect_to embed_short_account_status_url(@account, @stream_entry.activity), status: 301
   end
 
   private
diff --git a/app/helpers/stream_entries_helper.rb b/app/helpers/stream_entries_helper.rb
index 4ef7cffb07f40e897fdac6099b84c97425066710..44511498577e90c1a8e1fe3b72d31963075c8f35 100644
--- a/app/helpers/stream_entries_helper.rb
+++ b/app/helpers/stream_entries_helper.rb
@@ -1,7 +1,7 @@
 # frozen_string_literal: true
 
 module StreamEntriesHelper
-  EMBEDDED_CONTROLLER = 'stream_entries'
+  EMBEDDED_CONTROLLER = 'statuses'
   EMBEDDED_ACTION = 'embed'
 
   def display_name(account)
diff --git a/app/javascript/packs/public.js b/app/javascript/packs/public.js
index d8a0f4eeeb1528cf523813735db137f4171890af..ce12041e66e90b4b1950d3e81f7484324032122f 100644
--- a/app/javascript/packs/public.js
+++ b/app/javascript/packs/public.js
@@ -38,6 +38,13 @@ function main() {
       content.title = dateTimeFormat.format(datetime);
       content.textContent = relativeFormat.format(datetime);
     });
+
+    [].forEach.call(document.querySelectorAll('.logo-button'), (content) => {
+      content.addEventListener('click', (e) => {
+        e.preventDefault();
+        window.open(e.target.href, 'mastodon-intent', 'width=400,height=400,resizable=no,menubar=no,status=no,scrollbars=yes');
+      });
+    });
   });
 
   delegate(document, '.video-player video', 'click', ({ target }) => {
diff --git a/app/javascript/styles/stream_entries.scss b/app/javascript/styles/stream_entries.scss
index 1192e2a806ebcb6d0eda22a070c9e826c7055aaa..7048ab110c3051d58d9aa7888d980b79556fe6af 100644
--- a/app/javascript/styles/stream_entries.scss
+++ b/app/javascript/styles/stream_entries.scss
@@ -421,3 +421,33 @@
     }
   }
 }
+
+.button.button-secondary.logo-button {
+  position: absolute;
+  right: 14px;
+  top: 14px;
+  font-size: 14px;
+
+  svg {
+    width: 20px;
+    height: auto;
+    vertical-align: middle;
+    margin-right: 5px;
+
+    path:first-child {
+      fill: $ui-primary-color;
+    }
+
+    path:last-child {
+      fill: $simple-background-color;
+    }
+  }
+
+  &:active,
+  &:focus,
+  &:hover {
+    svg path:first-child {
+      fill: lighten($ui-primary-color, 4%);
+    }
+  }
+}
diff --git a/app/lib/stream_entry_finder.rb b/app/lib/status_finder.rb
similarity index 76%
rename from app/lib/stream_entry_finder.rb
rename to app/lib/status_finder.rb
index 0ea33229ce9d22a3faf7cfc2618725a97ca71486..bd910f12bb2a51e12d9fafb622d3a45455c1e13b 100644
--- a/app/lib/stream_entry_finder.rb
+++ b/app/lib/status_finder.rb
@@ -1,20 +1,20 @@
 # frozen_string_literal: true
 
-class StreamEntryFinder
+class StatusFinder
   attr_reader :url
 
   def initialize(url)
     @url = url
   end
 
-  def stream_entry
+  def status
     verify_action!
 
     case recognized_params[:controller]
     when 'stream_entries'
-      StreamEntry.find(recognized_params[:id])
+      StreamEntry.find(recognized_params[:id]).status
     when 'statuses'
-      Status.find(recognized_params[:id]).stream_entry
+      Status.find(recognized_params[:id])
     else
       raise ActiveRecord::RecordNotFound
     end
diff --git a/app/serializers/oembed_serializer.rb b/app/serializers/oembed_serializer.rb
index 78376d253eeadaf1ac8d3bce3d4e0eff148aae3c..0c2ced859e27026cb4bbdc810c0fe9608a26aee2 100644
--- a/app/serializers/oembed_serializer.rb
+++ b/app/serializers/oembed_serializer.rb
@@ -21,7 +21,7 @@ class OEmbedSerializer < ActiveModel::Serializer
   end
 
   def author_url
-    account_url(object.account)
+    short_account_url(object.account)
   end
 
   def provider_name
@@ -38,7 +38,7 @@ class OEmbedSerializer < ActiveModel::Serializer
 
   def html
     tag :iframe,
-        src: embed_account_stream_entry_url(object.account, object),
+        src: embed_short_account_status_url(object.account, object),
         style: 'width: 100%; overflow: hidden',
         frameborder: '0',
         scrolling: 'no',
diff --git a/app/views/stream_entries/_detailed_status.html.haml b/app/views/stream_entries/_detailed_status.html.haml
index 193cc64702eeece4401bf698bdaaebca09408348..107202b7594bf8a1e75d0e6f3a65e2b69c26acad 100644
--- a/app/views/stream_entries/_detailed_status.html.haml
+++ b/app/views/stream_entries/_detailed_status.html.haml
@@ -1,4 +1,9 @@
 .detailed-status.light
+  - if embedded_view?
+    = link_to "web+mastodon://follow?uri=#{status.account.local_username_and_domain}", class: 'button button-secondary logo-button', target: '_new' do
+      = render file: Rails.root.join('app', 'javascript', 'images', 'logo.svg')
+      = t('accounts.follow')
+
   = link_to TagManager.instance.url_for(status.account), class: 'detailed-status__display-name p-author h-card', target: stream_link_target, rel: 'noopener' do
     %div
       .avatar
diff --git a/app/views/stream_entries/embed.html.haml b/app/views/stream_entries/embed.html.haml
index 5df82528bdf239067635bdf02ed8a59f60c98149..b703c15d2f022665078520060c7babdea9e01801 100644
--- a/app/views/stream_entries/embed.html.haml
+++ b/app/views/stream_entries/embed.html.haml
@@ -1,2 +1,3 @@
-.activity-stream.activity-stream-headless
-  = render @type, @type.to_sym => @stream_entry.activity, centered: true
+- cache @stream_entry.activity do
+  .activity-stream.activity-stream-headless
+    = render "stream_entries/#{@type}", @type.to_sym => @stream_entry.activity, centered: true
diff --git a/config/brakeman.ignore b/config/brakeman.ignore
index f9bc77069082ca8faf69ef5170420d5febcc4aec..dbb59dd0796c7bd477784bbc995f29f03d843a80 100644
--- a/config/brakeman.ignore
+++ b/config/brakeman.ignore
@@ -1,5 +1,24 @@
 {
   "ignored_warnings": [
+    {
+      "warning_type": "Dynamic Render Path",
+      "warning_code": 15,
+      "fingerprint": "44d3f14e05d8fbb5b23e13ac02f15aa38b2a2f0f03b9ba76bab7f98e155a4a4e",
+      "check_name": "Render",
+      "message": "Render path contains parameter value",
+      "file": "app/views/stream_entries/embed.html.haml",
+      "line": 3,
+      "link": "http://brakemanscanner.org/docs/warning_types/dynamic_render_path/",
+      "code": "render(action => \"stream_entries/#{Account.find_local!(params[:account_username]).statuses.find(params[:id]).stream_entry.activity_type.downcase}\", { Account.find_local!(params[:account_username]).statuses.find(params[:id]).stream_entry.activity_type.downcase.to_sym => Account.find_local!(params[:account_username]).statuses.find(params[:id]).stream_entry.activity, :centered => true })",
+      "render_path": [{"type":"controller","class":"StatusesController","method":"embed","line":35,"file":"app/controllers/statuses_controller.rb"}],
+      "location": {
+        "type": "template",
+        "template": "stream_entries/embed"
+      },
+      "user_input": "params[:id]",
+      "confidence": "Weak",
+      "note": ""
+    },
     {
       "warning_type": "Dynamic Render Path",
       "warning_code": 15,
@@ -7,10 +26,10 @@
       "check_name": "Render",
       "message": "Render path contains parameter value",
       "file": "app/views/admin/accounts/index.html.haml",
-      "line": 32,
+      "line": 63,
       "link": "http://brakemanscanner.org/docs/warning_types/dynamic_render_path/",
       "code": "render(action => filtered_accounts.page(params[:page]), {})",
-      "render_path": [{"type":"controller","class":"Admin::AccountsController","method":"index","line":7,"file":"app/controllers/admin/accounts_controller.rb"}],
+      "render_path": [{"type":"controller","class":"Admin::AccountsController","method":"index","line":10,"file":"app/controllers/admin/accounts_controller.rb"}],
       "location": {
         "type": "template",
         "template": "admin/accounts/index"
@@ -39,25 +58,6 @@
       "confidence": "High",
       "note": ""
     },
-    {
-      "warning_type": "Dynamic Render Path",
-      "warning_code": 15,
-      "fingerprint": "c417f9d44ab05dd9cf3d5ec9df2324a5036774c151181787b32c4c940623191b",
-      "check_name": "Render",
-      "message": "Render path contains parameter value",
-      "file": "app/views/stream_entries/embed.html.haml",
-      "line": 2,
-      "link": "http://brakemanscanner.org/docs/warning_types/dynamic_render_path/",
-      "code": "render(action => Account.find_local!(params[:account_username]).stream_entries.where(:activity_type => \"Status\").find(params[:id]).activity_type.downcase, { Account.find_local!(params[:account_username]).stream_entries.where(:activity_type => \"Status\").find(params[:id]).activity_type.downcase.to_sym => Account.find_local!(params[:account_username]).stream_entries.where(:activity_type => \"Status\").find(params[:id]).activity, :centered => true })",
-      "render_path": [{"type":"controller","class":"StreamEntriesController","method":"embed","line":32,"file":"app/controllers/stream_entries_controller.rb"}],
-      "location": {
-        "type": "template",
-        "template": "stream_entries/embed"
-      },
-      "user_input": "params[:id]",
-      "confidence": "Weak",
-      "note": ""
-    },
     {
       "warning_type": "Dynamic Render Path",
       "warning_code": 15,
@@ -84,10 +84,10 @@
       "check_name": "Render",
       "message": "Render path contains parameter value",
       "file": "app/views/stream_entries/show.html.haml",
-      "line": 19,
+      "line": 23,
       "link": "http://brakemanscanner.org/docs/warning_types/dynamic_render_path/",
       "code": "render(partial => \"stream_entries/#{Account.find_local!(params[:account_username]).statuses.find(params[:id]).stream_entry.activity_type.downcase}\", { :locals => ({ Account.find_local!(params[:account_username]).statuses.find(params[:id]).stream_entry.activity_type.downcase.to_sym => Account.find_local!(params[:account_username]).statuses.find(params[:id]).stream_entry.activity, :include_threads => true }) })",
-      "render_path": [{"type":"controller","class":"StatusesController","method":"show","line":15,"file":"app/controllers/statuses_controller.rb"}],
+      "render_path": [{"type":"controller","class":"StatusesController","method":"show","line":20,"file":"app/controllers/statuses_controller.rb"}],
       "location": {
         "type": "template",
         "template": "stream_entries/show"
@@ -97,6 +97,6 @@
       "note": ""
     }
   ],
-  "updated": "2017-05-07 08:26:06 +0900",
-  "brakeman_version": "3.6.1"
+  "updated": "2017-08-30 05:14:04 +0200",
+  "brakeman_version": "3.7.2"
 }
diff --git a/config/environments/development.rb b/config/environments/development.rb
index 4c60965c89601cfe5cd6c7049bd55ad8ff6683b6..59bc2c3e257469e30212b9cb8853db9d3cb9f05f 100644
--- a/config/environments/development.rb
+++ b/config/environments/development.rb
@@ -16,9 +16,10 @@ Rails.application.configure do
   if Rails.root.join('tmp/caching-dev.txt').exist?
     config.action_controller.perform_caching = true
 
-    config.cache_store = :memory_store
+    config.cache_store = :redis_store, ENV['REDIS_URL'], REDIS_CACHE_PARAMS
+
     config.public_file_server.headers = {
-      'Cache-Control' => "public, max-age=#{2.days.seconds.to_i}"
+      'Cache-Control' => "public, max-age=#{2.days.seconds.to_i}",
     }
   else
     config.action_controller.perform_caching = false
diff --git a/config/routes.rb b/config/routes.rb
index 7588805c0d174276456ba41251108c7c8a1ff9ed..f8f145e1dddd892c19cfa4368bb2244b4b6b1345 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -44,6 +44,7 @@ Rails.application.routes.draw do
     resources :statuses, only: [:show] do
       member do
         get :activity
+        get :embed
       end
     end
 
@@ -59,6 +60,7 @@ Rails.application.routes.draw do
   get '/@:username/with_replies', to: 'accounts#show', as: :short_account_with_replies
   get '/@:username/media', to: 'accounts#show', as: :short_account_media
   get '/@:account_username/:id', to: 'statuses#show', as: :short_account_status
+  get '/@:account_username/:id/embed', to: 'statuses#embed', as: :embed_short_account_status
 
   namespace :settings do
     resource :profile, only: [:show, :update]
diff --git a/spec/controllers/stream_entries_controller_spec.rb b/spec/controllers/stream_entries_controller_spec.rb
index 808cf667c8314748d2e999f359940bf40edcbfa1..f81e2be7b4753eeb374a677ea61e876c7abbc8cf 100644
--- a/spec/controllers/stream_entries_controller_spec.rb
+++ b/spec/controllers/stream_entries_controller_spec.rb
@@ -88,14 +88,12 @@ RSpec.describe StreamEntriesController, type: :controller do
   describe 'GET #embed' do
     include_examples 'before_action', :embed
 
-    it 'returns embedded view of status' do
+    it 'redirects to new embed page' do
       status = Fabricate(:status)
 
       get :embed, params: { account_username: status.account.username, id: status.stream_entry.id }
 
-      expect(response).to have_http_status(:success)
-      expect(response.headers['X-Frame-Options']).to eq 'ALLOWALL'
-      expect(response).to render_template(layout: 'embedded')
+      expect(response).to redirect_to(embed_short_account_status_url(status.account, status))
     end
   end
 end
diff --git a/spec/lib/stream_entry_finder_spec.rb b/spec/lib/status_finder_spec.rb
similarity index 75%
rename from spec/lib/stream_entry_finder_spec.rb
rename to spec/lib/status_finder_spec.rb
index 64e03c36af79d589c278f77d8da6bc69cc884465..5c2f2dbe87114c4ef6a5b8b3fc1cba1582e399f5 100644
--- a/spec/lib/stream_entry_finder_spec.rb
+++ b/spec/lib/status_finder_spec.rb
@@ -2,17 +2,17 @@
 
 require 'rails_helper'
 
-describe StreamEntryFinder do
+describe StatusFinder do
   include RoutingHelper
 
-  describe '#stream_entry' do
+  describe '#status' do
     context 'with a status url' do
       let(:status) { Fabricate(:status) }
       let(:url) { short_account_status_url(account_username: status.account.username, id: status.id) }
       subject { described_class.new(url) }
 
       it 'finds the stream entry' do
-        expect(subject.stream_entry).to eq(status.stream_entry)
+        expect(subject.status).to eq(status)
       end
 
       it 'raises an error if action is not :show' do
@@ -20,7 +20,7 @@ describe StreamEntryFinder do
         expect(recognized).to receive(:[]).with(:action).and_return(:create)
         expect(Rails.application.routes).to receive(:recognize_path).with(url).and_return(recognized)
 
-        expect { subject.stream_entry }.to raise_error(ActiveRecord::RecordNotFound)
+        expect { subject.status }.to raise_error(ActiveRecord::RecordNotFound)
       end
     end
 
@@ -30,7 +30,7 @@ describe StreamEntryFinder do
       subject { described_class.new(url) }
 
       it 'finds the stream entry' do
-        expect(subject.stream_entry).to eq(stream_entry)
+        expect(subject.status).to eq(stream_entry.status)
       end
     end
 
@@ -39,7 +39,7 @@ describe StreamEntryFinder do
       subject { described_class.new(url) }
 
       it 'raises an error' do
-        expect { subject.stream_entry }.to raise_error(ActiveRecord::RecordNotFound)
+        expect { subject.status }.to raise_error(ActiveRecord::RecordNotFound)
       end
     end
 
@@ -48,7 +48,7 @@ describe StreamEntryFinder do
       subject { described_class.new(url) }
 
       it 'raises an error' do
-        expect { subject.stream_entry }.to raise_error(ActiveRecord::RecordNotFound)
+        expect { subject.status }.to raise_error(ActiveRecord::RecordNotFound)
       end
     end
   end