diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml
index 406828e3ca..e35514ded9 100644
--- a/locales/ja-JP.yml
+++ b/locales/ja-JP.yml
@@ -766,6 +766,12 @@ customCssWarn: "この設定は必ず知識のある方が行ってください
 global: "グローバル"
 squareAvatars: "アイコンを四角形で表示"
 
+_docs: 
+  continueReading: "続きを読む"
+  features: "機能"
+  generalTopics: "一般的なトピック"
+  advancedTopics: "高度なトピック"
+
 _ad:
   back: "戻る"
   reduceFrequencyOfThisAd: "この広告の表示頻度を下げる"
diff --git a/src/client/pages/doc.vue b/src/client/pages/doc.vue
index a4cf25033e..58b352d638 100644
--- a/src/client/pages/doc.vue
+++ b/src/client/pages/doc.vue
@@ -107,6 +107,7 @@ export default defineComponent({
 	padding: 32px;
 	max-width: 800px;
 	margin: 0 auto;
+	background: var(--panel);
 
 	&.max-width_500px {
 		padding: 16px;
diff --git a/src/client/pages/docs.vue b/src/client/pages/docs.vue
index e51528f83d..e677fe0cbe 100644
--- a/src/client/pages/docs.vue
+++ b/src/client/pages/docs.vue
@@ -1,14 +1,38 @@
 <template>
-<div>
-	<main class="_section">
-		<div class="_content">
-			<ul>
-				<li v-for="doc in docs" :key="doc.path">
-					<MkA :to="`/docs/${doc.path}`">{{ doc.title }}</MkA>
-				</li>
-			</ul>
+<div class="vtaihdtm">
+	<div class="search">
+		<MkInput v-model:value="query" :debounce="true" type="search"><template #icon><i class="fas fa-search"></i></template><span>{{ $ts.search }}</span></MkInput>
+	</div>
+	<MkFolder>
+		<template #header>{{ $ts._docs.generalTopics }}</template>
+		<div class="docs">
+			<MkA v-for="doc in docs.filter(doc => doc.path.startsWith('general/'))" :key="doc.path" :to="`/docs/${doc.path}`" class="doc">
+				<div class="title">{{ doc.title }}</div>
+				<div class="summary">{{ doc.summary }}</div>
+				<div class="read">{{ $ts._docs.continueReading }}</div>
+			</MkA>
 		</div>
-	</main>
+	</MkFolder>
+	<MkFolder>
+		<template #header>{{ $ts._docs.features }}</template>
+		<div class="docs">
+			<MkA v-for="doc in docs.filter(doc => doc.path.startsWith('features/'))" :key="doc.path" :to="`/docs/${doc.path}`" class="doc">
+				<div class="title">{{ doc.title }}</div>
+				<div class="summary">{{ doc.summary }}</div>
+				<div class="read">{{ $ts._docs.continueReading }}</div>
+			</MkA>
+		</div>
+	</MkFolder>
+	<MkFolder>
+		<template #header>{{ $ts._docs.advancedTopics }}</template>
+		<div class="docs">
+			<MkA v-for="doc in docs.filter(doc => doc.path.startsWith('advanced/'))" :key="doc.path" :to="`/docs/${doc.path}`" class="doc">
+				<div class="title">{{ doc.title }}</div>
+				<div class="summary">{{ doc.summary }}</div>
+				<div class="read">{{ $ts._docs.continueReading }}</div>
+			</MkA>
+		</div>
+	</MkFolder>
 </div>
 </template>
 
@@ -16,8 +40,15 @@
 import { defineComponent } from 'vue';
 import { url, lang } from '@client/config';
 import * as symbols from '@client/symbols';
+import MkFolder from '@client/components/ui/folder.vue';
+import MkInput from '@client/components/ui/input.vue';
 
 export default defineComponent({
+	components: {
+		MkFolder,
+		MkInput,
+	},
+
 	data() {
 		return {
 			[symbols.PAGE_INFO]: {
@@ -25,6 +56,15 @@ export default defineComponent({
 				icon: 'fas fa-question-circle'
 			},
 			docs: [],
+			query: null,
+		}
+	},
+
+	watch: {
+		query() {
+			fetch(`${url}/docs.json?lang=${lang}&q=${this.query}`).then(res => res.json()).then(docs => {
+				this.docs = docs;
+			});
 		}
 	},
 
@@ -35,3 +75,48 @@ export default defineComponent({
 	},
 });
 </script>
+
+<style lang="scss" scoped>
+.vtaihdtm {
+	background: var(--panel);
+
+	> .search {
+		padding: 8px;
+	}
+
+	.docs {
+		display: grid;
+		grid-template-columns: repeat(auto-fill, minmax(270px, 1fr));
+		grid-gap: 12px;
+		margin: var(--margin);
+
+		> .doc {
+			display: inline-block;
+			padding: 16px;
+			border: solid 1px var(--divider);
+			border-radius: 6px;
+
+			&:hover {
+				border: solid 1px var(--accent);
+				text-decoration: none;
+			}
+
+			> .title {
+				font-weight: bold;
+			}
+
+			> .summary {
+				white-space: nowrap;
+				overflow: hidden;
+				text-overflow: ellipsis;
+				font-size: 0.9em;
+			}
+
+			> .read {
+				color: var(--link);
+				font-size: 0.9em;
+			}
+		}
+	}
+}
+</style>
diff --git a/src/client/router.ts b/src/client/router.ts
index 4c3aa765e6..2081c1020c 100644
--- a/src/client/router.ts
+++ b/src/client/router.ts
@@ -31,7 +31,7 @@ export const router = createRouter({
 		{ path: '/docs', component: page('docs') },
 		{ path: '/theme-editor', component: page('theme-editor') },
 		{ path: '/advanced-theme-editor', component: page('advanced-theme-editor') },
-		{ path: '/docs/:doc', component: page('doc'), props: route => ({ doc: route.params.doc }) },
+		{ path: '/docs/:doc(.*)', component: page('doc'), props: route => ({ doc: route.params.doc }) },
 		{ path: '/explore', component: page('explore') },
 		{ path: '/explore/tags/:tag', props: true, component: page('explore') },
 		{ path: '/search', component: page('search') },
diff --git a/src/docs/ja-JP/aiscript.md b/src/docs/ja-JP/advanced/aiscript.md
similarity index 100%
rename from src/docs/ja-JP/aiscript.md
rename to src/docs/ja-JP/advanced/aiscript.md
diff --git a/src/docs/ja-JP/api.md b/src/docs/ja-JP/advanced/api.md
similarity index 100%
rename from src/docs/ja-JP/api.md
rename to src/docs/ja-JP/advanced/api.md
diff --git a/src/docs/ja-JP/create-plugin.md b/src/docs/ja-JP/advanced/create-plugin.md
similarity index 100%
rename from src/docs/ja-JP/create-plugin.md
rename to src/docs/ja-JP/advanced/create-plugin.md
diff --git a/src/docs/ja-JP/reversi-bot.md b/src/docs/ja-JP/advanced/reversi-bot.md
similarity index 100%
rename from src/docs/ja-JP/reversi-bot.md
rename to src/docs/ja-JP/advanced/reversi-bot.md
diff --git a/src/docs/ja-JP/stream.md b/src/docs/ja-JP/advanced/stream.md
similarity index 100%
rename from src/docs/ja-JP/stream.md
rename to src/docs/ja-JP/advanced/stream.md
diff --git a/src/docs/ja-JP/custom-emoji.md b/src/docs/ja-JP/features/custom-emoji.md
similarity index 100%
rename from src/docs/ja-JP/custom-emoji.md
rename to src/docs/ja-JP/features/custom-emoji.md
diff --git a/src/docs/ja-JP/deck.md b/src/docs/ja-JP/features/deck.md
similarity index 100%
rename from src/docs/ja-JP/deck.md
rename to src/docs/ja-JP/features/deck.md
diff --git a/src/docs/ja-JP/follow.md b/src/docs/ja-JP/features/follow.md
similarity index 100%
rename from src/docs/ja-JP/follow.md
rename to src/docs/ja-JP/features/follow.md
diff --git a/src/docs/ja-JP/keyboard-shortcut.md b/src/docs/ja-JP/features/keyboard-shortcut.md
similarity index 100%
rename from src/docs/ja-JP/keyboard-shortcut.md
rename to src/docs/ja-JP/features/keyboard-shortcut.md
diff --git a/src/docs/ja-JP/mfm.md b/src/docs/ja-JP/features/mfm.md
similarity index 100%
rename from src/docs/ja-JP/mfm.md
rename to src/docs/ja-JP/features/mfm.md
diff --git a/src/docs/ja-JP/mute.md b/src/docs/ja-JP/features/mute.md
similarity index 100%
rename from src/docs/ja-JP/mute.md
rename to src/docs/ja-JP/features/mute.md
diff --git a/src/docs/ja-JP/pages.md b/src/docs/ja-JP/features/pages.md
similarity index 100%
rename from src/docs/ja-JP/pages.md
rename to src/docs/ja-JP/features/pages.md
diff --git a/src/docs/ja-JP/reaction.md b/src/docs/ja-JP/features/reaction.md
similarity index 86%
rename from src/docs/ja-JP/reaction.md
rename to src/docs/ja-JP/features/reaction.md
index 476af64e8b..fadce7af4e 100644
--- a/src/docs/ja-JP/reaction.md
+++ b/src/docs/ja-JP/features/reaction.md
@@ -9,7 +9,6 @@
 
 ## リモート投稿へのリアクションについて
 リアクションはMisskeyオリジナルの機能であるため、リモートインスタンスがMisskeyでない限りは、ほとんどの場合「Like」としてアクティビティが送信されます。一般的にはLikeは「お気に入り」として実装されているようです。
-また、相手がMisskeyであったとしても、カスタム絵文字リアクションは伝わらず、自動的に「👍」等にフォールバックされます。
 
 ## リモートからのリアクションについて
 リモートから「Like」アクティビティを受信したとき、Misskeyでは「👍」のリアクションとして解釈されます。
diff --git a/src/docs/ja-JP/theme.md b/src/docs/ja-JP/features/theme.md
similarity index 100%
rename from src/docs/ja-JP/theme.md
rename to src/docs/ja-JP/features/theme.md
diff --git a/src/docs/ja-JP/timelines.md b/src/docs/ja-JP/features/timelines.md
similarity index 100%
rename from src/docs/ja-JP/timelines.md
rename to src/docs/ja-JP/features/timelines.md
diff --git a/src/docs/ja-JP/general/misskey.md b/src/docs/ja-JP/general/misskey.md
new file mode 100644
index 0000000000..13ef1609d8
--- /dev/null
+++ b/src/docs/ja-JP/general/misskey.md
@@ -0,0 +1,43 @@
+# Misskeyについて
+
+Misskeyはオープンソースの分散型マイクロブログプラットフォームプロジェクトです。
+開発はsyuiloによって2014年から開始されました。
+
+## 分散型とは何か?
+分散(distributed)型とは、非中央集権(decentralized)とも呼ばれ、コミュニティが多数のサーバーに分散して存在し、それらが相互に通信することでコンテンツ共有ネットワークを形成していることが特徴のサービスです。
+単一のサーバーしか存在しない、もしくは複数存在しても互いに独立している場合は中央集権なサービスと言われ、例えばTwitterやFacebookなどほとんどのサービスがそれに該当します。
+
+## 常にオープンソース
+Misskeyはこれまでもこれからも、オープンソースであり続けます。オープンソースとは、ソフトウェアのソースコード(プログラム)が公開されていることです。ソースコードの修正や再配布が可能であることを定義に含めることもあります。
+Misskeyのすべてのソースコードは公開されていて、誰でも自由に閲覧、使用、修正、改変、再配布をすることができます。
+オープンソースは、自分で好きなように変えたり、有害な処理が含まれていないことを確認することができたり、誰でも開発に参加できるなどの、様々なメリットがあります。
+上述の分散型を実現するためにも、オープンソースであるということは必要不可欠な要素です。
+再び引き合いに出しますが、TwitterやFacebookなどの利益を得ているほとんどのサービスはオープンソースではありません。
+
+Misskeyのソースコードは、[GitHub上で公開されています。](https://github.com/misskey-dev)
+
+## 開発に参加する、開発を支援する
+Misskeyの開発に貢献するにはいろいろな方法があります。
+
+### 機能を追加したり、バグを修正する
+ソフトウェアエンジニアのスキルをお持ちの方であれば、ソースコードを編集する形でプロジェクトに貢献することができます。
+
+### 議論に参加する
+新しい機能、または既存の機能について意見を述べたり、不具合を報告したりすることでも貢献できます。
+そのようなディスカッションは[GitHub](https://github.com/misskey-dev)上か、[フォーラム](https://forum.misskey.io/)等で行われます。
+
+### テキストを翻訳する
+Misskeyは様々な言語に対応しています(i18n -internationalizationの略- と呼ばれます)。元の言語は基本的に日本語ですが、有志によって他の言語へと翻訳されています。
+その翻訳作業に加わっていただくことでもMisskeyに貢献できます。
+Misskeyは[Crowdinというサービスを使用して翻訳の管理を行っています。](https://crowdin.com/project/misskey)
+
+### 感想を投稿する
+不具合報告等だけではなく、Misskeyの良い点、楽しい点といったポジティブな意見もぜひ共有してください。開発の励みになり、それは間接的ですがプロジェクトへの貢献です。
+
+### 寄付をする
+Misskeyはビジネスではなく、利用は無料であるため、収益は皆様からの寄付のみです。(インスタンスによっては広告収入を得ているような場合もありますが、それは運営者の収入であり開発者への収入にはなりません)
+寄付をしていただければ、今後も開発を続けることが可能になり、プロジェクトへの貢献になります。
+寄付は[Patreon](https://www.patreon.com/syuilo)で受け付けています。
+
+## クレジット
+Misskeyの開発者や、Misskeyに寄付をしてくださった方の一覧は[こちら](/about-misskey)で見ることができます。
diff --git a/src/server/web/index.ts b/src/server/web/index.ts
index 50fea757f2..a732e7f5b4 100644
--- a/src/server/web/index.ts
+++ b/src/server/web/index.ts
@@ -121,14 +121,22 @@ router.get('/api.json', async ctx => {
 
 router.get('/docs.json', async ctx => {
 	const lang = ctx.query.lang;
+	const query = ctx.query.q;
 	if (!Object.keys(locales).includes(lang)) {
 		ctx.body = [];
 		return;
 	}
-	const paths = glob.sync(__dirname + `/../../../src/docs/${lang}/*.md`);
-	const docs: { path: string; title: string; }[] = [];
+	const dirPath = `${__dirname}/../../../src/docs/${lang}`.replace(/\\/g, '/');
+	const paths = glob.sync(`${dirPath}/**/*.md`);
+	const docs: { path: string; title: string; summary: string; }[] = [];
 	for (const path of paths) {
 		const md = fs.readFileSync(path, { encoding: 'utf8' });
+
+		if (query && query.length > 0) {
+			// TODO: カタカナをひらがなにして比較するなどしたい
+			if (!md.includes(query)) continue;
+		}
+
 		const parsed = markdown.parse(md, {});
 		if (parsed.length === 0) return;
 
@@ -147,9 +155,22 @@ router.get('/docs.json', async ctx => {
 			}
 		}
 
+		const firstParagrapfTokens = [];
+		while (buf[0].type !== 'paragraph_open') {
+			buf.shift();
+		}
+		buf.shift();
+		while (buf[0].type as string !== 'paragraph_close') {
+			const token = buf.shift();
+			if (token) {
+				firstParagrapfTokens.push(token);
+			}
+		}
+
 		docs.push({
-			path: path.split('/').pop()!.split('.')[0],
-			title: markdown.renderer.render(headingTokens, {}, {})
+			path: path.replace(`${dirPath}/`, '').split('.')[0],
+			title: markdown.renderer.render(headingTokens, {}, {}),
+			summary: markdown.renderer.render(firstParagrapfTokens, {}, {}),
 		});
 	}