diff --git a/Gemfile b/Gemfile
index d24dc5f5c43cc9b1854ba58a5a8282747977d7cc..247070d5fa631bcab023c2d430d984bc4288d763 100644
--- a/Gemfile
+++ b/Gemfile
@@ -91,6 +91,7 @@ gem 'simple-navigation', '~> 4.1'
 gem 'simple_form', '~> 5.0'
 gem 'sprockets-rails', '~> 3.2', require: 'sprockets/railtie'
 gem 'stoplight', '~> 2.2.0'
+gem 'stoplight-admin', '~> 0.3.5'
 gem 'strong_migrations', '~> 0.5'
 gem 'tty-command', '~> 0.9', require: false
 gem 'tty-prompt', '~> 0.20', require: false
diff --git a/Gemfile.lock b/Gemfile.lock
index f6857f090272bff51af990eb4f3bcc5352ea6ae6..52c9564d8be8c2ceec252d6499a1d967ccdaeeee 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -118,6 +118,7 @@ GEM
       aws-sigv4 (~> 1.1)
     aws-sigv4 (1.1.0)
       aws-eventstream (~> 1.0, >= 1.0.2)
+    backports (3.15.0)
     bcrypt (3.1.12)
     better_errors (2.5.1)
       coderay (>= 1.0.0)
@@ -261,6 +262,9 @@ GEM
       http (~> 4.0)
       nokogiri (~> 1.8)
       oj (~> 3.0)
+    haml (5.0.4)
+      temple (>= 0.8.0)
+      tilt
     hamlit (2.11.0)
       temple (>= 0.8.2)
       thor
@@ -376,6 +380,7 @@ GEM
     msgpack (1.3.1)
     multi_json (1.14.1)
     multipart-post (2.1.1)
+    mustermann (1.0.3)
     necromancer (0.5.1)
     net-ldap (0.16.2)
     net-scp (2.0.0)
@@ -596,6 +601,18 @@ GEM
       json (>= 1.8, < 3)
       simplecov-html (~> 0.10.0)
     simplecov-html (0.10.2)
+    sinatra (2.0.7)
+      mustermann (~> 1.0)
+      rack (~> 2.0)
+      rack-protection (= 2.0.7)
+      tilt (~> 2.0)
+    sinatra-contrib (2.0.7)
+      backports (>= 2.8.2)
+      multi_json
+      mustermann (~> 1.0)
+      rack-protection (= 2.0.7)
+      sinatra (= 2.0.7)
+      tilt (~> 2.0)
     sprockets (3.7.2)
       concurrent-ruby (~> 1.0)
       rack (> 1, < 3)
@@ -609,6 +626,11 @@ GEM
     stackprof (0.2.15)
     statsd-ruby (1.4.0)
     stoplight (2.2.0)
+    stoplight-admin (0.3.5)
+      haml (~> 5.0.4)
+      redis (>= 3.2)
+      sinatra-contrib (~> 2.0.5)
+      stoplight (>= 1.4)
     streamio-ffmpeg (3.0.2)
       multi_json (~> 1.8)
     strong_migrations (0.5.1)
@@ -784,6 +806,7 @@ DEPENDENCIES
   sprockets-rails (~> 3.2)
   stackprof
   stoplight (~> 2.2.0)
+  stoplight-admin (~> 0.3.5)
   streamio-ffmpeg (~> 3.0)
   strong_migrations (~> 0.5)
   thor (~> 0.20)
diff --git a/config/initializers/content_security_policy.rb b/config/initializers/content_security_policy.rb
index 2e8a2296d2ae238d015373dbac914313c2e636e4..6666ab5553b6d3468d81c3fb853fe1c4c9294717 100644
--- a/config/initializers/content_security_policy.rb
+++ b/config/initializers/content_security_policy.rb
@@ -18,14 +18,15 @@ media_host ||= assets_host
 
 instance_ticker_host     = 'https://wee.jp'
 instance_ticker_img_host = 'https://res.cloudinary.com'
+bootstrap_cdn_host       = 'https://maxcdn.bootstrapcdn.com'
 
 Rails.application.config.content_security_policy do |p|
   p.base_uri        :none
   p.default_src     :none
   p.frame_ancestors :none
-  p.font_src        :self, assets_host
+  p.font_src        :self, assets_host, bootstrap_cdn_host
   p.img_src         :self, :https, :data, :blob, assets_host, instance_ticker_img_host
-  p.style_src       :self, :unsafe_inline, assets_host, instance_ticker_host
+  p.style_src       :self, :unsafe_inline, assets_host, instance_ticker_host, bootstrap_cdn_host
   p.media_src       :self, :https, :data, assets_host
   p.frame_src       :self, :https
   p.manifest_src    :self, assets_host
@@ -34,11 +35,11 @@ Rails.application.config.content_security_policy do |p|
     webpacker_urls = %w(ws http).map { |protocol| "#{protocol}#{Webpacker.dev_server.https? ? 's' : ''}://#{Webpacker.dev_server.host_with_port}" }
 
     p.connect_src :self, :data, :blob, assets_host, media_host, Rails.configuration.x.streaming_api_base_url, *webpacker_urls
-    p.script_src  :self, :unsafe_inline, :unsafe_eval, assets_host
+    p.script_src  :self, :unsafe_inline, :unsafe_eval, assets_host, bootstrap_cdn_host
     p.worker_src  :self, :blob, assets_host
   else
     p.connect_src :self, :data, :blob, assets_host, media_host, Rails.configuration.x.streaming_api_base_url
-    p.script_src  :self, assets_host
+    p.script_src  :self, assets_host, bootstrap_cdn_host
     p.worker_src  :self, :blob, assets_host
   end
 end
diff --git a/config/routes.rb b/config/routes.rb
index 96562d5fc2a41fa00ebdffadf2361c1369c7bc9c..7b75652c195ae3a6be933ebacc4800a558a447c8 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -2,6 +2,13 @@
 
 require 'sidekiq/web'
 require 'sidekiq-scheduler/web'
+require 'sinatra/stoplight_admin'
+
+class StoplightAdmin < Sinatra::Base
+  register Sinatra::StoplightAdmin
+  set :data_store, Stoplight::Light.default_data_store
+  set :haml, :escape_html => false
+end
 
 Sidekiq::Web.set :session_secret, Rails.application.secrets[:secret_key_base]
 
@@ -15,6 +22,7 @@ Rails.application.routes.draw do
   authenticate :user, lambda { |u| u.admin? } do
     mount Sidekiq::Web, at: 'sidekiq', as: :sidekiq
     mount PgHero::Engine, at: 'pghero', as: :pghero
+    mount StoplightAdmin, at: 'stoplights', as: :stoplights
   end
 
   use_doorkeeper do