diff --git a/app/controllers/api/v1/favourite_tags_controller.rb b/app/controllers/api/v1/favourite_tags_controller.rb
new file mode 100644
index 0000000000000000000000000000000000000000..6d87efc0600c937b4755cdbcd2d976bd2a210d8d
--- /dev/null
+++ b/app/controllers/api/v1/favourite_tags_controller.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+class Api::V1::FavouriteTagsController < Api::BaseController
+  before_action -> { doorkeeper_authorize! :read, :'read:favourite_tags' }, only: [:index, :show]
+  before_action -> { doorkeeper_authorize! :write, :'write:favourite_tags' }, except: [:index, :show]
+
+  before_action :require_user!
+  before_action :set_favourite_tag, except: [:index, :create]
+
+  def index
+    @favourite_tags = FavouriteTag.where(account: current_account).all
+    render json: @favourite_tags, each_serializer: REST::FavouriteTagSerializer
+  end
+
+  def show
+    render json: @favourite_tag, serializer: REST::FavouriteTagSerializer
+  end
+
+  def create
+    @favourite_tag = FavouriteTag.create!(favourite_tag_params.merge(account: current_account))
+    render json: @favourite_tag, serializer: REST::FavouriteTagSerializer
+  end
+
+  def update
+    @favourite_tag.update!(favourite_tag_params)
+    render json: @favourite_tag, serializer: REST::FavouriteTagSerializer
+  end
+
+  def destroy
+    @favourite_tag.destroy!
+    render_empty
+  end
+
+  private
+
+  def set_favourite_tag
+    @favourite_tag = FavouriteTag.where(account: current_account).find(params[:id])
+  end
+
+  def favourite_tag_params
+    params.permit(:name)
+  end
+end
diff --git a/app/controllers/settings/favourite_tags_controller.rb b/app/controllers/settings/favourite_tags_controller.rb
new file mode 100644
index 0000000000000000000000000000000000000000..dcf07ade56438b3f37f685bcbe57912591b8ba4a
--- /dev/null
+++ b/app/controllers/settings/favourite_tags_controller.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+class Settings::FavouriteTagsController < Settings::BaseController
+  layout 'admin'
+
+  before_action :authenticate_user!
+  before_action :set_favourite_tags, only: :index
+  before_action :set_favourite_tag, except: [:index, :create]
+
+  def index
+    @favourite_tag = FavouriteTag.new
+  end
+
+  def create
+    @favourite_tag = current_account.favourite_tags.new(favourite_tag_params)
+
+    if @favourite_tag.save
+      redirect_to settings_favourite_tags_path
+    else
+      set_favourite_tags
+
+      render :index
+    end
+  end
+
+  def destroy
+    @favourite_tag.destroy!
+    redirect_to settings_favourite_tags_path
+  end
+
+  private
+
+  def set_favourite_tag
+    @favourite_tag = current_account.favourite_tags.find(params[:id])
+  end
+
+  def set_favourite_tags
+    @favourite_tags = current_account.favourite_tags.order(:updated_at).reject(&:new_record?)
+  end
+
+  def favourite_tag_params
+    params.require(:favourite_tag).permit(:name)
+  end
+end
diff --git a/app/javascript/mastodon/actions/favourite_tags.js b/app/javascript/mastodon/actions/favourite_tags.js
new file mode 100644
index 0000000000000000000000000000000000000000..91ffb95eb881b95bea8dd4df9c64c5bbd3258672
--- /dev/null
+++ b/app/javascript/mastodon/actions/favourite_tags.js
@@ -0,0 +1,59 @@
+import api from '../api';
+
+export const FAVOURITE_TAG_FETCH_REQUEST = 'FAVOURITE_TAG_FETCH_REQUEST';
+export const FAVOURITE_TAG_FETCH_SUCCESS = 'FAVOURITE_TAG_FETCH_SUCCESS';
+export const FAVOURITE_TAG_FETCH_FAIL    = 'FAVOURITE_TAG_FETCH_FAIL';
+
+export const FAVOURITE_TAGS_FETCH_REQUEST = 'FAVOURITE_TAGS_FETCH_REQUEST';
+export const FAVOURITE_TAGS_FETCH_SUCCESS = 'FAVOURITE_TAGS_FETCH_SUCCESS';
+export const FAVOURITE_TAGS_FETCH_FAIL    = 'FAVOURITE_TAGS_FETCH_FAIL';
+
+export const fetchFavouriteTag = id => (dispatch, getState) => {
+  if (getState().getIn(['favourite_tags', id])) {
+    return;
+  }
+
+  dispatch(fetchFavouriteTagRequest(id));
+
+  api(getState).get(`/api/v1/favourite_tags/${id}`)
+    .then(({ data }) => dispatch(fetchFavouriteTagSuccess(data)))
+    .catch(err => dispatch(fetchFavouriteTagFail(id, err)));
+};
+
+export const fetchFavouriteTagRequest = id => ({
+  type: FAVOURITE_TAG_FETCH_REQUEST,
+  id,
+});
+
+export const fetchFavouriteTagSuccess = favourite_tag => ({
+  type: FAVOURITE_TAG_FETCH_SUCCESS,
+  favourite_tag,
+});
+
+export const fetchFavouriteTagFail = (id, error) => ({
+  type: FAVOURITE_TAG_FETCH_FAIL,
+  id,
+  error,
+});
+
+export const fetchFavouriteTags = () => (dispatch, getState) => {
+  dispatch(fetchFavouriteTagsRequest());
+
+  api(getState).get('/api/v1/favourite_tags')
+    .then(({ data }) => dispatch(fetchFavouriteTagsSuccess(data)))
+    .catch(err => dispatch(fetchFavouriteTagsFail(err)));
+};
+
+export const fetchFavouriteTagsRequest = () => ({
+  type: FAVOURITE_TAGS_FETCH_REQUEST,
+});
+
+export const fetchFavouriteTagsSuccess = favourite_tags => ({
+  type: FAVOURITE_TAGS_FETCH_SUCCESS,
+  favourite_tags,
+});
+
+export const fetchFavouriteTagsFail = error => ({
+  type: FAVOURITE_TAGS_FETCH_FAIL,
+  error,
+});
diff --git a/app/javascript/mastodon/features/ui/components/favourite_tag_panel.js b/app/javascript/mastodon/features/ui/components/favourite_tag_panel.js
new file mode 100644
index 0000000000000000000000000000000000000000..01193da56956b229e7bfd3cc3efeea74b1c64a6c
--- /dev/null
+++ b/app/javascript/mastodon/features/ui/components/favourite_tag_panel.js
@@ -0,0 +1,55 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import ImmutablePropTypes from 'react-immutable-proptypes';
+import ImmutablePureComponent from 'react-immutable-pure-component';
+import { fetchFavouriteTags } from 'mastodon/actions/favourite_tags';
+import { connect } from 'react-redux';
+import { createSelector } from 'reselect';
+import { NavLink, withRouter } from 'react-router-dom';
+import Icon from 'mastodon/components/icon';
+  
+const getOrderedTags = createSelector([state => state.get('favourite_tags')], favourite_tags => {
+  if (!favourite_tags) {
+    return favourite_tags;
+  }
+
+  return favourite_tags.toList().filter(item => !!item).sort((a, b) => a.get('updated_at').localeCompare(b.get('updated_at'))).take(10);
+});
+
+const mapStateToProps = state => ({
+  favourite_tags: getOrderedTags(state),
+});
+
+export default @withRouter
+@connect(mapStateToProps)
+class FavouriteTagPanel extends ImmutablePureComponent {
+
+  static propTypes = {
+    dispatch: PropTypes.func.isRequired,
+    favourite_tags: ImmutablePropTypes.list,
+  };
+
+  componentDidMount () {
+    const { dispatch } = this.props;
+    dispatch(fetchFavouriteTags());
+  }
+
+  render () {
+    const { favourite_tags } = this.props;
+
+    if (!favourite_tags || favourite_tags.isEmpty()) {
+      return null;
+    }
+
+    return (
+      <div>
+        <hr />
+
+        {favourite_tags.map(favourite_tag => (
+          <NavLink key={favourite_tag.get('id')} className='column-link column-link--transparent' strict to={`/timelines/tag/${favourite_tag.get('name')}`}><Icon className='column-link__icon' id='hashtag' fixedWidth />{favourite_tag.get('name')}</NavLink>
+        ))}
+      </div>
+    );
+  }
+
+}
diff --git a/app/javascript/mastodon/features/ui/components/navigation_panel.js b/app/javascript/mastodon/features/ui/components/navigation_panel.js
index a2cd6b41ab896f17bcce9c3ef7a9a3c794cde5ca..cfb6bc613fb7dbf907033e98beb7858a46fd96da 100644
--- a/app/javascript/mastodon/features/ui/components/navigation_panel.js
+++ b/app/javascript/mastodon/features/ui/components/navigation_panel.js
@@ -6,6 +6,7 @@ import { profile_directory, showTrends } from 'mastodon/initial_state';
 import NotificationsCounterIcon from './notifications_counter_icon';
 import FollowRequestsNavLink from './follow_requests_nav_link';
 import ListPanel from './list_panel';
+import FavouriteTagPanel from './favourite_tag_panel';
 import TrendsContainer from 'mastodon/features/getting_started/containers/trends_container';
 
 const NavigationPanel = () => (
@@ -23,6 +24,7 @@ const NavigationPanel = () => (
     {profile_directory && <NavLink className='column-link column-link--transparent' to='/directory'><Icon className='column-link__icon' id='address-book-o' fixedWidth /><FormattedMessage id='getting_started.directory' defaultMessage='Profile directory' /></NavLink>}
 
     <ListPanel />
+    <FavouriteTagPanel />
 
     <hr />
 
diff --git a/app/javascript/mastodon/reducers/favourite_tags.js b/app/javascript/mastodon/reducers/favourite_tags.js
new file mode 100644
index 0000000000000000000000000000000000000000..ca27107fd0cd6dc0cd4b9e3b90e28aa24c49d4af
--- /dev/null
+++ b/app/javascript/mastodon/reducers/favourite_tags.js
@@ -0,0 +1,31 @@
+import {
+  FAVOURITE_TAG_FETCH_SUCCESS,
+  FAVOURITE_TAG_FETCH_FAIL,
+  FAVOURITE_TAGS_FETCH_SUCCESS,
+} from '../actions/favourite_tags';
+import { Map as ImmutableMap, fromJS } from 'immutable';
+
+const initialState = ImmutableMap();
+
+const normalizeFavouriteTag = (state, favourite_tag) => state.set(favourite_tag.id, fromJS(favourite_tag));
+
+const normalizeFavouriteTags = (state, favourite_tags) => {
+  favourite_tags.forEach(favourite_tag => {
+    state = normalizeFavouriteTag(state, favourite_tag);
+  });
+
+  return state;
+};
+
+export default function favourite_tags(state = initialState, action) {
+  switch(action.type) {
+  case FAVOURITE_TAG_FETCH_SUCCESS:
+    return normalizeFavouriteTag(state, action.favourite_tag);
+  case FAVOURITE_TAGS_FETCH_SUCCESS:
+    return normalizeFavouriteTags(state, action.favourite_tags);
+  case FAVOURITE_TAG_FETCH_FAIL:
+    return state.set(action.id, false);
+  default:
+    return state;
+  }
+};
diff --git a/app/javascript/mastodon/reducers/index.js b/app/javascript/mastodon/reducers/index.js
index b8d60888815471295d95a174bca4212bb2c5e73c..b34d6ebdfb5875ab982a11f1465a69b2e8a0410b 100644
--- a/app/javascript/mastodon/reducers/index.js
+++ b/app/javascript/mastodon/reducers/index.js
@@ -34,6 +34,7 @@ import polls from './polls';
 import identity_proofs from './identity_proofs';
 import trends from './trends';
 import missed_updates from './missed_updates';
+import favourite_tags from './favourite_tags';
 
 const reducers = {
   dropdown_menu,
@@ -71,6 +72,7 @@ const reducers = {
   polls,
   trends,
   missed_updates,
+  favourite_tags,
 };
 
 export default combineReducers(reducers);
diff --git a/app/models/concerns/account_associations.rb b/app/models/concerns/account_associations.rb
index 499edbf4ebb2abf9edf2308204b3a942e129d926..f901c446d1ae46cc898b5a4209a930ca9e1ecdd5 100644
--- a/app/models/concerns/account_associations.rb
+++ b/app/models/concerns/account_associations.rb
@@ -58,6 +58,7 @@ module AccountAssociations
 
     # Hashtags
     has_and_belongs_to_many :tags
+    has_many :favourite_tags, -> { includes(:tag) }, dependent: :destroy, inverse_of: :account
     has_many :featured_tags, -> { includes(:tag) }, dependent: :destroy, inverse_of: :account
   end
 end
diff --git a/app/models/favourite_tag.rb b/app/models/favourite_tag.rb
new file mode 100644
index 0000000000000000000000000000000000000000..c23719d9c0fadd12a4d86fcd7edbd2de3fbf3fb1
--- /dev/null
+++ b/app/models/favourite_tag.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+# == Schema Information
+#
+# Table name: favourite_tags
+#
+#  id         :bigint(8)        not null, primary key
+#  account_id :bigint(8)
+#  tag_id     :bigint(8)
+#  created_at :datetime         not null
+#  updated_at :datetime         not null
+#
+
+class FavouriteTag < ApplicationRecord
+  belongs_to :account, inverse_of: :favourite_tags, required: true
+  belongs_to :tag, inverse_of: :favourite_tags, required: true
+
+  delegate :name, to: :tag, allow_nil: true
+
+  validates_associated :tag, on: :create
+  validates :name, presence: true, on: :create
+  validate :validate_favourite_tags_limit, on: :create
+
+  def name=(str)
+    self.tag = Tag.find_or_create_by_names(str.strip)&.first
+  end
+
+  private
+
+  def validate_favourite_tags_limit
+    errors.add(:base, I18n.t('favourite_tags.errors.limit')) if account.favourite_tags.count >= 10
+  end
+end
diff --git a/app/models/tag.rb b/app/models/tag.rb
index bce76fc1667b43c8d700aa28c2928b21fcf94d64..8e6fc404dbeb779e4fabc7c502f207ea1175b676 100644
--- a/app/models/tag.rb
+++ b/app/models/tag.rb
@@ -22,6 +22,7 @@ class Tag < ApplicationRecord
   has_and_belongs_to_many :accounts
   has_and_belongs_to_many :sample_accounts, -> { local.discoverable.popular.limit(3) }, class_name: 'Account'
 
+  has_many :favourite_tags, dependent: :destroy, inverse_of: :tag
   has_many :featured_tags, dependent: :destroy, inverse_of: :tag
   has_one :account_tag_stat, dependent: :destroy
 
diff --git a/app/serializers/rest/favourite_tag_serializer.rb b/app/serializers/rest/favourite_tag_serializer.rb
new file mode 100644
index 0000000000000000000000000000000000000000..07940434d4c4f8e718c78aae21d9b31357050ea8
--- /dev/null
+++ b/app/serializers/rest/favourite_tag_serializer.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class REST::FavouriteTagSerializer < ActiveModel::Serializer
+  attributes :id, :name, :updated_at
+
+  def id
+    object.id.to_s
+  end
+end
diff --git a/app/views/settings/favourite_tags/index.html.haml b/app/views/settings/favourite_tags/index.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..47044fe8066e0d4a0eda05003a5ef91bec254dda
--- /dev/null
+++ b/app/views/settings/favourite_tags/index.html.haml
@@ -0,0 +1,26 @@
+- content_for :page_title do
+  = t('settings.favourite_tags')
+
+%p= t('favourite_tags.hint_html')
+
+%hr.spacer/
+
+= simple_form_for @favourite_tag, url: settings_favourite_tags_path do |f|
+  = render 'shared/error_messages', object: @favourite_tag
+
+  .fields-group
+    = f.input :name, wrapper: :with_block_label, hint: false
+
+  .actions
+    = f.button :button, t('favourite_tags.add_new'), type: :submit
+
+%hr.spacer/
+
+- @favourite_tags.each do |favourite_tag|
+  .directory__tag{ class: params[:tag] == favourite_tag.name ? 'active' : nil }
+    %div
+      %h4
+        = fa_icon 'hashtag'
+        = favourite_tag.name
+        %small
+          = table_link_to 'trash', t('filters.index.delete'), settings_favourite_tag_path(favourite_tag), method: :delete, data: { confirm: t('admin.accounts.are_you_sure') }
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 5cd05e3c960cf30091bceb2dc8f8154f3dbb5038..172bc51d697e2624dddf8c06e4f477d11fa1f9c3 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -727,6 +727,11 @@ en:
     lists: Lists
     mutes: You mute
     storage: Media storage
+  favourite_tags:
+    add_new: Add new
+    errors:
+      limit: You have already favourite the maximum amount of hashtags
+    hint_html: "<strong>What are favourite hashtags?</strong> They are used only for you, and are tools to help you browse using hashtags. You can quickly switch between timelines."
   featured_tags:
     add_new: Add new
     errors:
@@ -1018,6 +1023,7 @@ en:
     development: Development
     edit_profile: Edit profile
     export: Data export
+    favourite_tags: Favourite hashtags
     featured_tags: Featured hashtags
     identity_proofs: Identity proofs
     import: Import
diff --git a/config/locales/ja.yml b/config/locales/ja.yml
index ee8efec2aca5afb414b54d663a0bb16437951995..5993feb6490fb28987d7ed834a832e0bfff57fed 100644
--- a/config/locales/ja.yml
+++ b/config/locales/ja.yml
@@ -719,6 +719,11 @@ ja:
     lists: リスト
     mutes: ミュート
     storage: メディア
+  favourite_tags:
+    add_new: 追加
+    errors:
+      limit: お気に入りハッシュタグの上限に達しました
+    hint_html: "<strong>お気に入りのハッシュタグとは何ですか?</strong> それらはあなた自身のためにだけ使用される、ハッシュタグを活用したブラウジングを助けるためのツールです。すばやくタイムラインを切り替えることができます。"
   featured_tags:
     add_new: 追加
     errors:
@@ -1004,6 +1009,7 @@ ja:
     development: 開発
     edit_profile: プロフィールを編集
     export: データのエクスポート
+    favourite_tags: お気に入りハッシュタグ
     featured_tags: 注目のハッシュタグ
     identity_proofs: Identity proofs
     import: データのインポート
diff --git a/config/locales/simple_form.ja.yml b/config/locales/simple_form.ja.yml
index 63475167ced229b3f3bed30096a3ff65788d8993..fdccc13448b94f4603eceabfd19934b9b7c2649f 100644
--- a/config/locales/simple_form.ja.yml
+++ b/config/locales/simple_form.ja.yml
@@ -138,6 +138,8 @@ ja:
         username: ユーザー名
         username_or_email: ユーザー名またはメールアドレス
         whole_word: 単語全体にマッチ
+      favourite_tag:
+        name: ハッシュタグ
       featured_tag:
         name: ハッシュタグ
       interactions:
diff --git a/config/navigation.rb b/config/navigation.rb
index eebd4f75e38ba3ba336fbe6ac2d1f93050972a99..f67e6dcc3440c64974b1ad375e28a161b2efa609 100644
--- a/config/navigation.rb
+++ b/config/navigation.rb
@@ -13,6 +13,7 @@ SimpleNavigation::Configuration.run do |navigation|
     n.item :preferences, safe_join([fa_icon('cog fw'), t('settings.preferences')]), settings_preferences_url, if: -> { current_user.functional? } do |s|
       s.item :appearance, safe_join([fa_icon('desktop fw'), t('settings.appearance')]), settings_preferences_appearance_url
       s.item :notifications, safe_join([fa_icon('bell fw'), t('settings.notifications')]), settings_preferences_notifications_url
+      s.item :favourite_tags, safe_join([fa_icon('hashtag fw'), t('settings.favourite_tags')]), settings_favourite_tags_url
       s.item :other, safe_join([fa_icon('cog fw'), t('preferences.other')]), settings_preferences_other_url
     end
 
diff --git a/config/routes.rb b/config/routes.rb
index ff308699d3f565229eb37b6c5859e05ae56d2e95..6b245a1eb7668e09616282f27a3366d6b5b1d9ff 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -146,6 +146,7 @@ Rails.application.routes.draw do
     resources :aliases, only: [:index, :create, :destroy]
     resources :sessions, only: [:destroy]
     resources :featured_tags, only: [:index, :create, :destroy]
+    resources :favourite_tags, only: [:index, :create, :destroy]
   end
 
   resources :media, only: [:show] do
diff --git a/db/migrate/20190821124329_create_favourite_tags.rb b/db/migrate/20190821124329_create_favourite_tags.rb
new file mode 100644
index 0000000000000000000000000000000000000000..da451f84fe8ed2bc3b5cba6b611c7c8369295a4a
--- /dev/null
+++ b/db/migrate/20190821124329_create_favourite_tags.rb
@@ -0,0 +1,10 @@
+class CreateFavouriteTags < ActiveRecord::Migration[5.2]
+  def change
+    create_table :favourite_tags do |t|
+      t.references :account, foreign_key: { on_delete: :cascade }
+      t.references :tag, foreign_key: { on_delete: :cascade }
+
+      t.timestamps
+    end
+  end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 0595f4661843fa6394a50f9651b2f359343a6d4b..65a200371b0aa2d7abf25ce53df8f87ca3c0572d 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -302,6 +302,15 @@ ActiveRecord::Schema.define(version: 2020_01_19_112504) do
     t.index ["domain"], name: "index_email_domain_blocks_on_domain", unique: true
   end
 
+  create_table "favourite_tags", force: :cascade do |t|
+    t.bigint "account_id"
+    t.bigint "tag_id"
+    t.datetime "created_at", null: false
+    t.datetime "updated_at", null: false
+    t.index ["account_id"], name: "index_favourite_tags_on_account_id"
+    t.index ["tag_id"], name: "index_favourite_tags_on_tag_id"
+  end
+
   create_table "favourites", force: :cascade do |t|
     t.datetime "created_at", null: false
     t.datetime "updated_at", null: false
@@ -827,6 +836,8 @@ ActiveRecord::Schema.define(version: 2020_01_19_112504) do
   add_foreign_key "conversation_mutes", "accounts", name: "fk_225b4212bb", on_delete: :cascade
   add_foreign_key "conversation_mutes", "conversations", on_delete: :cascade
   add_foreign_key "custom_filters", "accounts", on_delete: :cascade
+  add_foreign_key "favourite_tags", "accounts", on_delete: :cascade
+  add_foreign_key "favourite_tags", "tags", on_delete: :cascade
   add_foreign_key "favourites", "accounts", name: "fk_5eb6c2b873", on_delete: :cascade
   add_foreign_key "favourites", "statuses", name: "fk_b0e856845e", on_delete: :cascade
   add_foreign_key "featured_tags", "accounts", on_delete: :cascade
diff --git a/spec/fabricators/favourite_tag_fabricator.rb b/spec/fabricators/favourite_tag_fabricator.rb
new file mode 100644
index 0000000000000000000000000000000000000000..7e244043a863ed26ad5a6d051a0d8a351c15b5ea
--- /dev/null
+++ b/spec/fabricators/favourite_tag_fabricator.rb
@@ -0,0 +1,4 @@
+Fabricator(:favourite_tag) do
+  account
+  tag
+end
diff --git a/spec/models/favourite_tag_spec.rb b/spec/models/favourite_tag_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..ff99f96f3ccdb41c73ceeade9070464cba3fb923
--- /dev/null
+++ b/spec/models/favourite_tag_spec.rb
@@ -0,0 +1,4 @@
+require 'rails_helper'
+
+RSpec.describe FavouriteTag, type: :model do
+end