diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
index 9ba110f776..74f9a4e532 100644
--- a/.github/workflows/lint.yml
+++ b/.github/workflows/lint.yml
@@ -16,7 +16,7 @@ jobs:
         submodules: true
     - uses: actions/setup-node@v1
       with:
-        node-version: 12.x
+        node-version: 16.x
     - uses: actions/cache@v2
       with:
         path: '**/node_modules'
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a98c9b5f69..c874648efd 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,12 @@
 You should also include the user name that made the change.
 -->
 
+## 12.109.2 (2022/04/03)
+
+### Bugfixes
+- API: admin/update-meta was not working @syuilo
+- Client: テーマを切り替えたり読み込んだりするとmeta[name="theme-color"]のcontentがundefinedになる問題を修正 @tamaina
+
 ## 12.109.1 (2022/04/02)
 
 ### Bugfixes
diff --git a/package.json b/package.json
index 425d2b1e53..9ab8f1eccc 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
 	"name": "misskey",
-	"version": "12.109.1",
+	"version": "12.109.2",
 	"codename": "indigo",
 	"repository": {
 		"type": "git",
diff --git a/packages/backend/.eslintrc.js b/packages/backend/.eslintrc.cjs
similarity index 100%
rename from packages/backend/.eslintrc.js
rename to packages/backend/.eslintrc.cjs
diff --git a/packages/backend/package.json b/packages/backend/package.json
index d6490f1cb6..99f78afae9 100644
--- a/packages/backend/package.json
+++ b/packages/backend/package.json
@@ -5,7 +5,7 @@
 	"scripts": {
 		"build": "tsc -p tsconfig.json || echo done. && tsc-alias -p tsconfig.json",
 		"watch": "node watch.mjs",
-		"lint": "eslint --quiet src/**/*.ts",
+		"lint": "eslint --quiet 'src/**/*.ts'",
 		"mocha": "cross-env TS_NODE_FILES=true TS_NODE_TRANSPILE_ONLY=true TS_NODE_PROJECT=\"./test/tsconfig.json\" mocha",
 		"test": "npm run mocha"
 	},
diff --git a/packages/backend/src/models/schema/emoji.ts b/packages/backend/src/models/schema/emoji.ts
index 5f9af88db4..e97fdd5ef6 100644
--- a/packages/backend/src/models/schema/emoji.ts
+++ b/packages/backend/src/models/schema/emoji.ts
@@ -27,6 +27,7 @@ export const packedEmojiSchema = {
 		host: {
 			type: 'string',
 			optional: false, nullable: true,
+			description: 'The local host is represented with `null`.',
 		},
 		url: {
 			type: 'string',
diff --git a/packages/backend/src/models/schema/user.ts b/packages/backend/src/models/schema/user.ts
index 616bedc0dc..253681695d 100644
--- a/packages/backend/src/models/schema/user.ts
+++ b/packages/backend/src/models/schema/user.ts
@@ -21,6 +21,7 @@ export const packedUserLiteSchema = {
 			type: 'string',
 			nullable: true, optional: false,
 			example: 'misskey.example.com',
+			description: 'The local host is represented with `null`.',
 		},
 		avatarUrl: {
 			type: 'string',
diff --git a/packages/backend/src/server/api/endpoints/admin/drive/files.ts b/packages/backend/src/server/api/endpoints/admin/drive/files.ts
index 646d85a1e0..119c4db19b 100644
--- a/packages/backend/src/server/api/endpoints/admin/drive/files.ts
+++ b/packages/backend/src/server/api/endpoints/admin/drive/files.ts
@@ -27,7 +27,12 @@ export const paramDef = {
 		untilId: { type: 'string', format: 'misskey:id' },
 		type: { type: 'string', nullable: true, pattern: /^[a-zA-Z0-9\/\-*]+$/.toString().slice(1, -1) },
 		origin: { type: 'string', enum: ['combined', 'local', 'remote'], default: "local" },
-		hostname: { type: 'string', nullable: true, default: null },
+		hostname: {
+			type: 'string',
+			nullable: true,
+			default: null,
+			description: 'The local host is represented with `null`.',
+		},
 	},
 	required: [],
 } as const;
diff --git a/packages/backend/src/server/api/endpoints/admin/drive/show-file.ts b/packages/backend/src/server/api/endpoints/admin/drive/show-file.ts
index 4b27fc0188..039df74f1b 100644
--- a/packages/backend/src/server/api/endpoints/admin/drive/show-file.ts
+++ b/packages/backend/src/server/api/endpoints/admin/drive/show-file.ts
@@ -40,6 +40,7 @@ export const meta = {
 			userHost: {
 				type: 'string',
 				optional: false, nullable: true,
+				description: 'The local host is represented with `null`.',
 			},
 			md5: {
 				type: 'string',
@@ -151,11 +152,20 @@ export const meta = {
 
 export const paramDef = {
 	type: 'object',
-	properties: {
-		fileId: { type: 'string', format: 'misskey:id' },
-		url: { type: 'string' },
-	},
-	required: [],
+	anyOf: [
+		{
+			properties: {
+				fileId: { type: 'string', format: 'misskey:id' },
+			},
+			required: ['fileId'],
+		},
+		{
+			properties: {
+				url: { type: 'string' },
+			},
+			required: ['url'],
+		},
+	],
 } as const;
 
 // eslint-disable-next-line import/no-default-export
diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/list-remote.ts b/packages/backend/src/server/api/endpoints/admin/emoji/list-remote.ts
index f19c3ddbd8..d16689a280 100644
--- a/packages/backend/src/server/api/endpoints/admin/emoji/list-remote.ts
+++ b/packages/backend/src/server/api/endpoints/admin/emoji/list-remote.ts
@@ -40,6 +40,7 @@ export const meta = {
 				host: {
 					type: 'string',
 					optional: false, nullable: true,
+					description: 'The local host is represented with `null`.',
 				},
 				url: {
 					type: 'string',
@@ -54,7 +55,12 @@ export const paramDef = {
 	type: 'object',
 	properties: {
 		query: { type: 'string', nullable: true, default: null },
-		host: { type: 'string', nullable: true, default: null },
+		host: {
+			type: 'string',
+			nullable: true,
+			default: null,
+			description: 'Use `null` to represent the local host.',
+		},
 		limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 },
 		sinceId: { type: 'string', format: 'misskey:id' },
 		untilId: { type: 'string', format: 'misskey:id' },
diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/list.ts b/packages/backend/src/server/api/endpoints/admin/emoji/list.ts
index f488a71a00..6192978fad 100644
--- a/packages/backend/src/server/api/endpoints/admin/emoji/list.ts
+++ b/packages/backend/src/server/api/endpoints/admin/emoji/list.ts
@@ -38,8 +38,9 @@ export const meta = {
 					optional: false, nullable: true,
 				},
 				host: {
-					type: 'string',
-					optional: false, nullable: true,
+					type: 'null',
+					optional: false,
+					description: 'The local host is represented with `null`. The field exists for compatibility with other API endpoints that return files.',
 				},
 				url: {
 					type: 'string',
diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/set-category-bulk.ts b/packages/backend/src/server/api/endpoints/admin/emoji/set-category-bulk.ts
index 6063f3e3be..cff58d6170 100644
--- a/packages/backend/src/server/api/endpoints/admin/emoji/set-category-bulk.ts
+++ b/packages/backend/src/server/api/endpoints/admin/emoji/set-category-bulk.ts
@@ -17,7 +17,11 @@ export const paramDef = {
 		ids: { type: 'array', items: {
 			type: 'string', format: 'misskey:id',
 		} },
-		category: { type: 'string', nullable: true },
+		category: {
+			type: 'string',
+			nullable: true,
+			description: 'Use `null` to reset the category.',
+		},
 	},
 	required: ['ids'],
 } as const;
diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/update.ts b/packages/backend/src/server/api/endpoints/admin/emoji/update.ts
index e26514e0ca..5b547b3b79 100644
--- a/packages/backend/src/server/api/endpoints/admin/emoji/update.ts
+++ b/packages/backend/src/server/api/endpoints/admin/emoji/update.ts
@@ -23,7 +23,11 @@ export const paramDef = {
 	properties: {
 		id: { type: 'string', format: 'misskey:id' },
 		name: { type: 'string' },
-		category: { type: 'string', nullable: true },
+		category: {
+			type: 'string',
+			nullable: true,
+			description: 'Use `null` to reset the category.',
+		},
 		aliases: { type: 'array', items: {
 			type: 'string',
 		} },
diff --git a/packages/backend/src/server/api/endpoints/admin/show-users.ts b/packages/backend/src/server/api/endpoints/admin/show-users.ts
index 1ec86fef2e..2703b4b9db 100644
--- a/packages/backend/src/server/api/endpoints/admin/show-users.ts
+++ b/packages/backend/src/server/api/endpoints/admin/show-users.ts
@@ -26,8 +26,13 @@ export const paramDef = {
 		sort: { type: 'string', enum: ['+follower', '-follower', '+createdAt', '-createdAt', '+updatedAt', '-updatedAt'] },
 		state: { type: 'string', enum: ['all', 'available', 'admin', 'moderator', 'adminOrModerator', 'silenced', 'suspended'], default: "all" },
 		origin: { type: 'string', enum: ['combined', 'local', 'remote'], default: "local" },
-		username: { type: 'string', default: null },
-		hostname: { type: 'string', default: null },
+		username: { type: 'string', nullable: true, default: null },
+		hostname: {
+			type: 'string',
+			nullable: true,
+			default: null,
+			description: 'The local host is represented with `null`.',
+		},
 	},
 	required: [],
 } as const;
diff --git a/packages/backend/src/server/api/endpoints/admin/update-meta.ts b/packages/backend/src/server/api/endpoints/admin/update-meta.ts
index 3c39bf0f30..b23ee9e3df 100644
--- a/packages/backend/src/server/api/endpoints/admin/update-meta.ts
+++ b/packages/backend/src/server/api/endpoints/admin/update-meta.ts
@@ -397,12 +397,14 @@ export default define(meta, paramDef, async (ps, me) => {
 	}
 
 	await db.transaction(async transactionalEntityManager => {
-		const meta = await transactionalEntityManager.findOne(Meta, {
+		const metas = await transactionalEntityManager.find(Meta, {
 			order: {
 				id: 'DESC',
 			},
 		});
 
+		const meta = metas[0];
+
 		if (meta) {
 			await transactionalEntityManager.update(Meta, meta.id, set);
 		} else {
diff --git a/packages/backend/src/server/api/endpoints/channels/pin-note.ts b/packages/backend/src/server/api/endpoints/channels/pin-note.ts
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/packages/backend/src/server/api/endpoints/clips/create.ts b/packages/backend/src/server/api/endpoints/clips/create.ts
index a2dbef12e0..4afe4222a1 100644
--- a/packages/backend/src/server/api/endpoints/clips/create.ts
+++ b/packages/backend/src/server/api/endpoints/clips/create.ts
@@ -20,7 +20,7 @@ export const paramDef = {
 	type: 'object',
 	properties: {
 		name: { type: 'string', minLength: 1, maxLength: 100 },
-		isPublic: { type: 'boolean' },
+		isPublic: { type: 'boolean', default: false },
 		description: { type: 'string', nullable: true, minLength: 1, maxLength: 2048 },
 	},
 	required: ['name'],
diff --git a/packages/backend/src/server/api/endpoints/drive/files/show.ts b/packages/backend/src/server/api/endpoints/drive/files/show.ts
index c8e9d3dd93..a2bc0c7aa4 100644
--- a/packages/backend/src/server/api/endpoints/drive/files/show.ts
+++ b/packages/backend/src/server/api/endpoints/drive/files/show.ts
@@ -28,22 +28,25 @@ export const meta = {
 			code: 'ACCESS_DENIED',
 			id: '25b73c73-68b1-41d0-bad1-381cfdf6579f',
 		},
-
-		fileIdOrUrlRequired: {
-			message: 'fileId or url required.',
-			code: 'INVALID_PARAM',
-			id: '89674805-722c-440c-8d88-5641830dc3e4',
-		},
 	},
 } as const;
 
 export const paramDef = {
 	type: 'object',
-	properties: {
-		fileId: { type: 'string', format: 'misskey:id' },
-		url: { type: 'string' },
-	},
-	required: [],
+	anyOf: [
+		{
+			properties: {
+				fileId: { type: 'string', format: 'misskey:id' },
+			},
+			required: ['fileId'],
+		},
+		{
+			properties: {
+				url: { type: 'string' },
+			},
+			required: ['url'],
+		},
+	],
 } as const;
 
 // eslint-disable-next-line import/no-default-export
@@ -62,8 +65,6 @@ export default define(meta, paramDef, async (ps, user) => {
 				thumbnailUrl: ps.url,
 			}],
 		});
-	} else {
-		throw new ApiError(meta.errors.fileIdOrUrlRequired);
 	}
 
 	if (file == null) {
diff --git a/packages/backend/src/server/api/endpoints/federation/instances.ts b/packages/backend/src/server/api/endpoints/federation/instances.ts
index e272971763..07e5c07c6a 100644
--- a/packages/backend/src/server/api/endpoints/federation/instances.ts
+++ b/packages/backend/src/server/api/endpoints/federation/instances.ts
@@ -22,7 +22,7 @@ export const meta = {
 export const paramDef = {
 	type: 'object',
 	properties: {
-		host: { type: 'string', nullable: true },
+		host: { type: 'string', nullable: true, description: 'Omit or use `null` to not filter by host.' },
 		blocked: { type: 'boolean', nullable: true },
 		notResponding: { type: 'boolean', nullable: true },
 		suspended: { type: 'boolean', nullable: true },
diff --git a/packages/backend/src/server/api/endpoints/messaging/messages.ts b/packages/backend/src/server/api/endpoints/messaging/messages.ts
index 9760709c29..dbf1f6c868 100644
--- a/packages/backend/src/server/api/endpoints/messaging/messages.ts
+++ b/packages/backend/src/server/api/endpoints/messaging/messages.ts
@@ -47,14 +47,25 @@ export const meta = {
 export const paramDef = {
 	type: 'object',
 	properties: {
-		userId: { type: 'string', format: 'misskey:id' },
-		groupId: { type: 'string', format: 'misskey:id' },
 		limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 },
 		sinceId: { type: 'string', format: 'misskey:id' },
 		untilId: { type: 'string', format: 'misskey:id' },
 		markAsRead: { type: 'boolean', default: true },
 	},
-	required: [],
+	anyOf: [
+		{
+			properties: {
+				userId: { type: 'string', format: 'misskey:id' },
+			},
+			required: ['userId'],
+		},
+		{
+			properties: {
+				groupId: { type: 'string', format: 'misskey:id' },
+			},
+			required: ['groupId'],
+		},
+	],
 } as const;
 
 // eslint-disable-next-line import/no-default-export
@@ -126,7 +137,5 @@ export default define(meta, paramDef, async (ps, user) => {
 		return await Promise.all(messages.map(message => MessagingMessages.pack(message, user, {
 			populateGroup: false,
 		})));
-	} else {
-		throw new Error();
 	}
 });
diff --git a/packages/backend/src/server/api/endpoints/messaging/messages/create.ts b/packages/backend/src/server/api/endpoints/messaging/messages/create.ts
index 8c1226b0f4..405af5ec17 100644
--- a/packages/backend/src/server/api/endpoints/messaging/messages/create.ts
+++ b/packages/backend/src/server/api/endpoints/messaging/messages/create.ts
@@ -67,12 +67,23 @@ export const meta = {
 export const paramDef = {
 	type: 'object',
 	properties: {
-		userId: { type: 'string', format: 'misskey:id' },
-		groupId: { type: 'string', format: 'misskey:id' },
 		text: { type: 'string', nullable: true, maxLength: 3000 },
 		fileId: { type: 'string', format: 'misskey:id' },
 	},
-	required: [],
+	anyOf: [
+		{
+			properties: {
+				userId: { type: 'string', format: 'misskey:id' },
+			},
+			required: ['userId'],
+		},
+		{
+			properties: {
+				groupId: { type: 'string', format: 'misskey:id' },
+			},
+			required: ['groupId'],
+		},
+	],
 } as const;
 
 // eslint-disable-next-line import/no-default-export
diff --git a/packages/backend/src/server/api/endpoints/meta.ts b/packages/backend/src/server/api/endpoints/meta.ts
index 057d22f33b..e1ae282a97 100644
--- a/packages/backend/src/server/api/endpoints/meta.ts
+++ b/packages/backend/src/server/api/endpoints/meta.ts
@@ -169,6 +169,7 @@ export const meta = {
 						host: {
 							type: 'string',
 							optional: false, nullable: true,
+							description: 'The local host is represented with `null`.',
 						},
 						url: {
 							type: 'string',
diff --git a/packages/backend/src/server/api/endpoints/mute/create.ts b/packages/backend/src/server/api/endpoints/mute/create.ts
index 0c3a3453f1..7e857e6731 100644
--- a/packages/backend/src/server/api/endpoints/mute/create.ts
+++ b/packages/backend/src/server/api/endpoints/mute/create.ts
@@ -38,7 +38,11 @@ export const paramDef = {
 	type: 'object',
 	properties: {
 		userId: { type: 'string', format: 'misskey:id' },
-		expiresAt: { type: 'integer', nullable: true },
+		expiresAt: {
+			type: 'integer',
+			nullable: true,
+			description: 'A Unix Epoch timestamp that must lie in the future. `null` means an indefinite mute.',
+		},
 	},
 	required: ['userId'],
 } as const;
diff --git a/packages/backend/src/server/api/endpoints/notes.ts b/packages/backend/src/server/api/endpoints/notes.ts
index 96657f8d3f..99c8b973f6 100644
--- a/packages/backend/src/server/api/endpoints/notes.ts
+++ b/packages/backend/src/server/api/endpoints/notes.ts
@@ -19,7 +19,7 @@ export const meta = {
 export const paramDef = {
 	type: 'object',
 	properties: {
-		local: { type: 'boolean' },
+		local: { type: 'boolean', default: false },
 		reply: { type: 'boolean' },
 		renote: { type: 'boolean' },
 		withFiles: { type: 'boolean' },
diff --git a/packages/backend/src/server/api/endpoints/notes/create.ts b/packages/backend/src/server/api/endpoints/notes/create.ts
index 961983f5f4..24d0c8134f 100644
--- a/packages/backend/src/server/api/endpoints/notes/create.ts
+++ b/packages/backend/src/server/api/endpoints/notes/create.ts
@@ -59,12 +59,6 @@ export const meta = {
 			id: '3ac74a84-8fd5-4bb0-870f-01804f82ce15',
 		},
 
-		contentRequired: {
-			message: 'Content required. You need to set text, fileIds, renoteId or poll.',
-			code: 'CONTENT_REQUIRED',
-			id: '6f57e42b-c348-439b-bc45-993995cc515a',
-		},
-
 		cannotCreateAlreadyExpiredPoll: {
 			message: 'Poll is already expired.',
 			code: 'CANNOT_CREATE_ALREADY_EXPIRED_POLL',
@@ -92,29 +86,41 @@ export const paramDef = {
 		visibleUserIds: { type: 'array', uniqueItems: true, items: {
 			type: 'string', format: 'misskey:id',
 		} },
-		text: { type: 'string', nullable: true, maxLength: MAX_NOTE_TEXT_LENGTH, default: null },
+		text: { type: 'string', maxLength: MAX_NOTE_TEXT_LENGTH, nullable: true },
 		cw: { type: 'string', nullable: true, maxLength: 100 },
 		localOnly: { type: 'boolean', default: false },
 		noExtractMentions: { type: 'boolean', default: false },
 		noExtractHashtags: { type: 'boolean', default: false },
 		noExtractEmojis: { type: 'boolean', default: false },
-		fileIds: { type: 'array', uniqueItems: true, minItems: 1, maxItems: 16, items: {
-			type: 'string', format: 'misskey:id',
-		} },
-		mediaIds: { type: 'array', uniqueItems: true, minItems: 1, maxItems: 16, items: {
-			type: 'string', format: 'misskey:id',
-		} },
+		fileIds: {
+			type: 'array',
+			uniqueItems: true,
+			minItems: 1,
+			maxItems: 16,
+			items: { type: 'string', format: 'misskey:id' },
+		},
+		mediaIds: {
+			deprecated: true,
+			description: 'Use `fileIds` instead. If both are specified, this property is discarded.',
+			type: 'array',
+			uniqueItems: true,
+			minItems: 1,
+			maxItems: 16,
+			items: { type: 'string', format: 'misskey:id' },
+		},
 		replyId: { type: 'string', format: 'misskey:id', nullable: true },
 		renoteId: { type: 'string', format: 'misskey:id', nullable: true },
 		channelId: { type: 'string', format: 'misskey:id', nullable: true },
 		poll: {
-			type: 'object', nullable: true,
+			type: 'object',
+			nullable: true,
 			properties: {
 				choices: {
-					type: 'array', uniqueItems: true, minItems: 2, maxItems: 10, 
-					items: {
-						type: 'string', minLength: 1, maxLength: 50,
-					},
+					type: 'array',
+					uniqueItems: true,
+					minItems: 2,
+					maxItems: 10,
+					items: { type: 'string', minLength: 1, maxLength: 50 },
 				},
 				multiple: { type: 'boolean', default: false },
 				expiresAt: { type: 'integer', nullable: true },
@@ -123,7 +129,34 @@ export const paramDef = {
 			required: ['choices'],
 		},
 	},
-	required: [],
+	anyOf: [
+		{
+			// (re)note with text, files and poll are optional
+			properties: {
+				text: { type: 'string', maxLength: MAX_NOTE_TEXT_LENGTH, nullable: false },
+			},
+			required: ['text'],
+		},
+		{
+			// (re)note with files, text and poll are optional
+			required: ['fileIds'],
+		},
+		{
+			// (re)note with files, text and poll are optional
+			required: ['mediaIds'],
+		},
+		{
+			// (re)note with poll, text and files are optional
+			properties: {
+				poll: { type: 'object', nullable: false, },
+			},
+			required: ['poll'],
+		},
+		{
+			// pure renote
+			required: ['renoteId'],
+		},
+	],
 } as const;
 
 // eslint-disable-next-line import/no-default-export
@@ -152,7 +185,7 @@ export default define(meta, paramDef, async (ps, user) => {
 
 		if (renote == null) {
 			throw new ApiError(meta.errors.noSuchRenoteTarget);
-		} else if (renote.renoteId && !renote.text && !renote.fileIds) {
+		} else if (renote.renoteId && !renote.text && !renote.fileIds && !renote.poll) {
 			throw new ApiError(meta.errors.cannotReRenote);
 		}
 
@@ -175,10 +208,7 @@ export default define(meta, paramDef, async (ps, user) => {
 
 		if (reply == null) {
 			throw new ApiError(meta.errors.noSuchReplyTarget);
-		}
-
-		// 返信対象が引用でないRenoteだったらエラー
-		if (reply.renoteId && !reply.text && !reply.fileIds) {
+		} else if (reply.renoteId && !reply.text && !reply.fileIds && !renote.poll) {
 			throw new ApiError(meta.errors.cannotReplyToPureRenote);
 		}
 
@@ -204,11 +234,6 @@ export default define(meta, paramDef, async (ps, user) => {
 		}
 	}
 
-	// テキストが無いかつ添付ファイルが無いかつRenoteも無いかつ投票も無かったらエラー
-	if (!(ps.text || files.length || renote || ps.poll)) {
-		throw new ApiError(meta.errors.contentRequired);
-	}
-
 	let channel: Channel | undefined;
 	if (ps.channelId != null) {
 		channel = await Channels.findOneBy({ id: ps.channelId });
diff --git a/packages/backend/src/server/api/endpoints/notes/global-timeline.ts b/packages/backend/src/server/api/endpoints/notes/global-timeline.ts
index 09a8194665..cb402ecaa1 100644
--- a/packages/backend/src/server/api/endpoints/notes/global-timeline.ts
+++ b/packages/backend/src/server/api/endpoints/notes/global-timeline.ts
@@ -35,7 +35,11 @@ export const meta = {
 export const paramDef = {
 	type: 'object',
 	properties: {
-		withFiles: { type: 'boolean' },
+		withFiles: {
+			type: 'boolean',
+			default: false,
+			description: 'Only show notes that have attached files.',
+		},
 		limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 },
 		sinceId: { type: 'string', format: 'misskey:id' },
 		untilId: { type: 'string', format: 'misskey:id' },
diff --git a/packages/backend/src/server/api/endpoints/notes/hybrid-timeline.ts b/packages/backend/src/server/api/endpoints/notes/hybrid-timeline.ts
index 7c9c122963..f9893527e0 100644
--- a/packages/backend/src/server/api/endpoints/notes/hybrid-timeline.ts
+++ b/packages/backend/src/server/api/endpoints/notes/hybrid-timeline.ts
@@ -48,7 +48,11 @@ export const paramDef = {
 		includeMyRenotes: { type: 'boolean', default: true },
 		includeRenotedMyNotes: { type: 'boolean', default: true },
 		includeLocalRenotes: { type: 'boolean', default: true },
-		withFiles: { type: 'boolean' },
+		withFiles: {
+			type: 'boolean',
+			default: false,
+			description: 'Only show notes that have attached files.',
+		},
 	},
 	required: [],
 } as const;
diff --git a/packages/backend/src/server/api/endpoints/notes/local-timeline.ts b/packages/backend/src/server/api/endpoints/notes/local-timeline.ts
index bb0bbe2a20..03edf30b31 100644
--- a/packages/backend/src/server/api/endpoints/notes/local-timeline.ts
+++ b/packages/backend/src/server/api/endpoints/notes/local-timeline.ts
@@ -37,7 +37,11 @@ export const meta = {
 export const paramDef = {
 	type: 'object',
 	properties: {
-		withFiles: { type: 'boolean' },
+		withFiles: {
+			type: 'boolean',
+			default: false,
+			description: 'Only show notes that have attached files.',
+		},
 		fileType: { type: 'array', items: {
 			type: 'string',
 		} },
diff --git a/packages/backend/src/server/api/endpoints/notes/search-by-tag.ts b/packages/backend/src/server/api/endpoints/notes/search-by-tag.ts
index c6503eb057..bb85c92008 100644
--- a/packages/backend/src/server/api/endpoints/notes/search-by-tag.ts
+++ b/packages/backend/src/server/api/endpoints/notes/search-by-tag.ts
@@ -25,21 +25,44 @@ export const meta = {
 export const paramDef = {
 	type: 'object',
 	properties: {
-		tag: { type: 'string' },
-		query: { type: 'array', items: {
-			type: 'array', items: {
-				type: 'string',
-			},
-		} },
 		reply: { type: 'boolean', nullable: true, default: null },
 		renote: { type: 'boolean', nullable: true, default: null },
-		withFiles: { type: 'boolean' },
+		withFiles: {
+			type: 'boolean',
+			default: false,
+			description: 'Only show notes that have attached files.',
+		},
 		poll: { type: 'boolean', nullable: true, default: null },
 		sinceId: { type: 'string', format: 'misskey:id' },
 		untilId: { type: 'string', format: 'misskey:id' },
 		limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 },
 	},
-	required: [],
+	anyOf: [
+		{
+			properties: {
+				tag: { type: 'string', minLength: 1 },
+			},
+			required: ['tag'],
+		},
+		{
+			properties: {
+				query: {
+					type: 'array',
+					description: 'The outer arrays are chained with OR, the inner arrays are chained with AND.',
+					items: {
+						type: 'array',
+						items: {
+							type: 'string',
+							minLength: 1,
+						},
+						minItems: 1,
+					},
+					minItems: 1,
+				},
+			},
+			required: ['query'],
+		},
+	],
 } as const;
 
 // eslint-disable-next-line import/no-default-export
diff --git a/packages/backend/src/server/api/endpoints/notes/search.ts b/packages/backend/src/server/api/endpoints/notes/search.ts
index e77892b150..af9b5f0a10 100644
--- a/packages/backend/src/server/api/endpoints/notes/search.ts
+++ b/packages/backend/src/server/api/endpoints/notes/search.ts
@@ -35,7 +35,11 @@ export const paramDef = {
 		untilId: { type: 'string', format: 'misskey:id' },
 		limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 },
 		offset: { type: 'integer', default: 0 },
-		host: { type: 'string', nullable: true },
+		host: {
+			type: 'string',
+			nullable: true,
+			description: 'The local host is represented with `null`.',
+		},
 		userId: { type: 'string', format: 'misskey:id', nullable: true, default: null },
 		channelId: { type: 'string', format: 'misskey:id', nullable: true, default: null },
 	},
diff --git a/packages/backend/src/server/api/endpoints/notes/timeline.ts b/packages/backend/src/server/api/endpoints/notes/timeline.ts
index fde66b241b..0f976d18be 100644
--- a/packages/backend/src/server/api/endpoints/notes/timeline.ts
+++ b/packages/backend/src/server/api/endpoints/notes/timeline.ts
@@ -38,7 +38,11 @@ export const paramDef = {
 		includeMyRenotes: { type: 'boolean', default: true },
 		includeRenotedMyNotes: { type: 'boolean', default: true },
 		includeLocalRenotes: { type: 'boolean', default: true },
-		withFiles: { type: 'boolean' },
+		withFiles: {
+			type: 'boolean',
+			default: false,
+			description: 'Only show notes that have attached files.',
+		},
 	},
 	required: [],
 } as const;
diff --git a/packages/backend/src/server/api/endpoints/notes/user-list-timeline.ts b/packages/backend/src/server/api/endpoints/notes/user-list-timeline.ts
index 866e306d8d..6c6402603a 100644
--- a/packages/backend/src/server/api/endpoints/notes/user-list-timeline.ts
+++ b/packages/backend/src/server/api/endpoints/notes/user-list-timeline.ts
@@ -42,7 +42,11 @@ export const paramDef = {
 		includeMyRenotes: { type: 'boolean', default: true },
 		includeRenotedMyNotes: { type: 'boolean', default: true },
 		includeLocalRenotes: { type: 'boolean', default: true },
-		withFiles: { type: 'boolean' },
+		withFiles: {
+			type: 'boolean',
+			default: false,
+			description: 'Only show notes that have attached files.',
+		},
 	},
 	required: ['listId'],
 } as const;
diff --git a/packages/backend/src/server/api/endpoints/pages/show.ts b/packages/backend/src/server/api/endpoints/pages/show.ts
index 1c218acfd4..3dcce8550f 100644
--- a/packages/backend/src/server/api/endpoints/pages/show.ts
+++ b/packages/backend/src/server/api/endpoints/pages/show.ts
@@ -26,12 +26,21 @@ export const meta = {
 
 export const paramDef = {
 	type: 'object',
-	properties: {
-		pageId: { type: 'string', format: 'misskey:id' },
-		name: { type: 'string' },
-		username: { type: 'string' },
-	},
-	required: [],
+	anyOf: [
+		{
+			properties: {
+				pageId: { type: 'string', format: 'misskey:id' },
+			},
+			required: ['pageId'],
+		},
+		{
+			properties: {
+				name: { type: 'string' },
+				username: { type: 'string' },
+			},
+			required: ['name', 'username'],
+		},
+	],
 } as const;
 
 // eslint-disable-next-line import/no-default-export
diff --git a/packages/backend/src/server/api/endpoints/users/followers.ts b/packages/backend/src/server/api/endpoints/users/followers.ts
index 5de624312a..26b1f20df0 100644
--- a/packages/backend/src/server/api/endpoints/users/followers.ts
+++ b/packages/backend/src/server/api/endpoints/users/followers.ts
@@ -38,14 +38,29 @@ export const meta = {
 export const paramDef = {
 	type: 'object',
 	properties: {
-		userId: { type: 'string', format: 'misskey:id' },
-		username: { type: 'string' },
-		host: { type: 'string', nullable: true },
 		sinceId: { type: 'string', format: 'misskey:id' },
 		untilId: { type: 'string', format: 'misskey:id' },
 		limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 },
 	},
-	required: [],
+	anyOf: [
+		{
+			properties: {
+				userId: { type: 'string', format: 'misskey:id' },
+			},
+			required: ['userId'],
+		},
+		{
+			properties: {
+				username: { type: 'string' },
+				host: {
+					type: 'string',
+					nullable: true,
+					description: 'The local host is represented with `null`.',
+				},
+			},
+			required: ['username', 'host'],
+		},
+	],
 } as const;
 
 // eslint-disable-next-line import/no-default-export
diff --git a/packages/backend/src/server/api/endpoints/users/following.ts b/packages/backend/src/server/api/endpoints/users/following.ts
index 55460f7c67..42cf5216e8 100644
--- a/packages/backend/src/server/api/endpoints/users/following.ts
+++ b/packages/backend/src/server/api/endpoints/users/following.ts
@@ -38,14 +38,29 @@ export const meta = {
 export const paramDef = {
 	type: 'object',
 	properties: {
-		userId: { type: 'string', format: 'misskey:id' },
-		username: { type: 'string' },
-		host: { type: 'string', nullable: true },
 		sinceId: { type: 'string', format: 'misskey:id' },
 		untilId: { type: 'string', format: 'misskey:id' },
 		limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 },
 	},
-	required: [],
+	anyOf: [
+		{
+			properties: {
+				userId: { type: 'string', format: 'misskey:id' },
+			},
+			required: ['userId'],
+		},
+		{
+			properties: {
+				username: { type: 'string' },
+				host: {
+					type: 'string',
+					nullable: true,
+					description: 'The local host is represented with `null`.',
+				},
+			},
+			required: ['username', 'host'],
+		},
+	],
 } as const;
 
 // eslint-disable-next-line import/no-default-export
diff --git a/packages/backend/src/server/api/endpoints/users/search-by-username-and-host.ts b/packages/backend/src/server/api/endpoints/users/search-by-username-and-host.ts
index 897b5de3fe..f74d80e2ae 100644
--- a/packages/backend/src/server/api/endpoints/users/search-by-username-and-host.ts
+++ b/packages/backend/src/server/api/endpoints/users/search-by-username-and-host.ts
@@ -28,7 +28,10 @@ export const paramDef = {
 		limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 },
 		detail: { type: 'boolean', default: true },
 	},
-	required: [],
+	anyOf: [
+		{ required: ['username'] },
+		{ required: ['host'] },
+	],
 } as const;
 
 // TODO: avatar,bannerをJOINしたいけどエラーになる
diff --git a/packages/backend/src/server/api/endpoints/users/show.ts b/packages/backend/src/server/api/endpoints/users/show.ts
index 775a4b29ff..b1a568145a 100644
--- a/packages/backend/src/server/api/endpoints/users/show.ts
+++ b/packages/backend/src/server/api/endpoints/users/show.ts
@@ -46,15 +46,33 @@ export const meta = {
 
 export const paramDef = {
 	type: 'object',
-	properties: {
-		userId: { type: 'string', format: 'misskey:id' },
-		userIds: { type: 'array', uniqueItems: true, items: {
-			type: 'string', format: 'misskey:id',
-		} },
-		username: { type: 'string' },
-		host: { type: 'string', nullable: true },
-	},
-	required: [],
+	anyOf: [
+		{
+			properties: {
+				userId: { type: 'string', format: 'misskey:id' },
+			},
+			required: ['userId'],
+		},
+		{
+			properties: {
+				userIds: { type: 'array', uniqueItems: true, items: {
+					type: 'string', format: 'misskey:id',
+				} },
+			},
+			required: ['userIds'],
+		},
+		{
+			properties: {
+				username: { type: 'string' },
+				host: {
+					type: 'string',
+					nullable: true,
+					description: 'The local host is represented with `null`.',
+				},
+			},
+			required: ['username', 'host'],
+		},
+	],
 } as const;
 
 // eslint-disable-next-line import/no-default-export
diff --git a/packages/client/package.json b/packages/client/package.json
index c6b0363adb..d44df92d7b 100644
--- a/packages/client/package.json
+++ b/packages/client/package.json
@@ -3,7 +3,7 @@
 	"scripts": {
 		"watch": "webpack --watch",
 		"build": "webpack",
-		"lint": "eslint --quiet src/**/*.{ts,vue}"
+		"lint": "eslint --quiet 'src/**/*.{ts,vue}'"
 	},
 	"resolutions": {
 		"chokidar": "^3.3.1",
diff --git a/packages/client/src/scripts/theme.ts b/packages/client/src/scripts/theme.ts
index 45743d0ffa..2cb78fae5c 100644
--- a/packages/client/src/scripts/theme.ts
+++ b/packages/client/src/scripts/theme.ts
@@ -51,14 +51,14 @@ export function applyTheme(theme: Theme, persist = true) {
 
 	if (_theme.base) {
 		const base = [lightTheme, darkTheme].find(x => x.id === _theme.base);
-		_theme.props = Object.assign({}, base.props, _theme.props);
+		if (base) _theme.props = Object.assign({}, base.props, _theme.props);
 	}
 
 	const props = compile(_theme);
 
 	for (const tag of document.head.children) {
 		if (tag.tagName === 'META' && tag.getAttribute('name') === 'theme-color') {
-			tag.setAttribute('content', props['html']);
+			tag.setAttribute('content', props['htmlThemeColor']);
 			break;
 		}
 	}