diff --git a/CHANGELOG.md b/CHANGELOG.md
index c0eaf721c7..b26a4a02e3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -28,6 +28,11 @@
 - フォルダーやファイルに対しても開発者モード使用時、IDをコピーできるように
 - 引用対象を「もっと見る」で展開した場合、「閉じる」で畳めるように
 - プロフィールURLをコピーできるボタンを追加 #11190
+- `CURRENT_URL`で現在表示中のURLを取得できるように(AiScript)
+- ユーザーのContextMenuに「アンテナに追加」ボタンを追加
+- フォローやお気に入り登録をしていないチャンネルを開く時は概要ページを開くように
+- 画面ビューワをタップした場合、マウスクリックと同様に画像ビューワを閉じるように
+- オフライン時の画面にリロードボタンを追加
 - Fix: サーバーメトリクスが90度傾いている
 - Fix: 非ログイン時にクレデンシャルが必要なページに行くとエラーが出る問題を修正
 - Fix: sparkle内にリンクを入れるとクリック不能になる問題の修正
diff --git a/locales/index.d.ts b/locales/index.d.ts
index 42dddebbff..7555984b24 100644
--- a/locales/index.d.ts
+++ b/locales/index.d.ts
@@ -52,6 +52,7 @@ export interface Locale {
     "deleteAndEdit": string;
     "deleteAndEditConfirm": string;
     "addToList": string;
+    "addToAntenna": string;
     "sendMessage": string;
     "copyRSS": string;
     "copyUsername": string;
@@ -2157,4 +2158,4 @@ export interface Locale {
 declare const locales: {
     [lang: string]: Locale;
 };
-export = locales;
+export default locales;
diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml
index 16014da511..82efc8a469 100644
--- a/locales/ja-JP.yml
+++ b/locales/ja-JP.yml
@@ -49,6 +49,7 @@ delete: "削除"
 deleteAndEdit: "削除して編集"
 deleteAndEditConfirm: "このノートを削除してもう一度編集しますか?このノートへのリアクション、Renote、返信も全て削除されます。"
 addToList: "リストに追加"
+addToAntenna: "アンテナに追加"
 sendMessage: "メッセージを送信"
 copyRSS: "RSSをコピー"
 copyUsername: "ユーザー名をコピー"
diff --git a/packages/backend/src/boot/master.ts b/packages/backend/src/boot/master.ts
index 2a23757253..b04234fd1f 100644
--- a/packages/backend/src/boot/master.ts
+++ b/packages/backend/src/boot/master.ts
@@ -31,7 +31,7 @@ function greet() {
 		console.log(themeColor(' |     |_|___ ___| |_ ___ _ _ '));
 		console.log(themeColor(' | | | | |_ -|_ -| \'_| -_| | |'));
 		console.log(themeColor(' |_|_|_|_|___|___|_,_|___|_  |'));
-		console.log(' ' + chalk.gray(v) + themeColor('                        |___|\n'.substr(v.length)));
+		console.log(' ' + chalk.gray(v) + themeColor('                        |___|\n'.substring(v.length)));
 		//#endregion
 
 		console.log(' Misskey is an open-source decentralized microblogging platform.');
diff --git a/packages/backend/src/core/FetchInstanceMetadataService.ts b/packages/backend/src/core/FetchInstanceMetadataService.ts
index a0afaaf888..9e8d17442f 100644
--- a/packages/backend/src/core/FetchInstanceMetadataService.ts
+++ b/packages/backend/src/core/FetchInstanceMetadataService.ts
@@ -103,7 +103,7 @@ export class FetchInstanceMetadataService {
 
 			if (name) updates.name = name;
 			if (description) updates.description = description;
-			if (icon || favicon) updates.iconUrl = icon ?? favicon;
+			if (icon || favicon) updates.iconUrl = (icon && !icon.includes('data:image/png;base64')) ? icon : favicon;
 			if (favicon) updates.faviconUrl = favicon;
 			if (themeColor) updates.themeColor = themeColor;
 
diff --git a/packages/backend/src/core/NoteCreateService.ts b/packages/backend/src/core/NoteCreateService.ts
index fb36ca3b6a..4f3d66dd58 100644
--- a/packages/backend/src/core/NoteCreateService.ts
+++ b/packages/backend/src/core/NoteCreateService.ts
@@ -570,12 +570,14 @@ export class NoteCreateService implements OnApplicationShutdown {
 			if (data.reply) {
 				// 通知
 				if (data.reply.userHost === null) {
-					const threadMuted = await this.noteThreadMutingsRepository.findOneBy({
-						userId: data.reply.userId,
-						threadId: data.reply.threadId ?? data.reply.id,
+					const isThreadMuted = await this.noteThreadMutingsRepository.exist({
+						where: {
+							userId: data.reply.userId,
+							threadId: data.reply.threadId ?? data.reply.id,
+						}
 					});
 
-					if (!threadMuted) {
+					if (!isThreadMuted) {
 						nm.push(data.reply.userId, 'reply');
 						this.globalEventService.publishMainStream(data.reply.userId, 'reply', noteObj);
 
@@ -712,12 +714,14 @@ export class NoteCreateService implements OnApplicationShutdown {
 	@bindThis
 	private async createMentionedEvents(mentionedUsers: MinimumUser[], note: Note, nm: NotificationManager) {
 		for (const u of mentionedUsers.filter(u => this.userEntityService.isLocalUser(u))) {
-			const threadMuted = await this.noteThreadMutingsRepository.findOneBy({
-				userId: u.id,
-				threadId: note.threadId ?? note.id,
+			const isThreadMuted = await this.noteThreadMutingsRepository.exist({
+				where: {
+					userId: u.id,
+					threadId: note.threadId ?? note.id,
+				},
 			});
 
-			if (threadMuted) {
+			if (isThreadMuted) {
 				continue;
 			}
 
diff --git a/packages/backend/src/core/NoteReadService.ts b/packages/backend/src/core/NoteReadService.ts
index b84591e26d..52e9bd369a 100644
--- a/packages/backend/src/core/NoteReadService.ts
+++ b/packages/backend/src/core/NoteReadService.ts
@@ -43,11 +43,13 @@ export class NoteReadService implements OnApplicationShutdown {
 		//#endregion
 
 		// スレッドミュート
-		const threadMute = await this.noteThreadMutingsRepository.findOneBy({
-			userId: userId,
-			threadId: note.threadId ?? note.id,
+		const isThreadMuted = await this.noteThreadMutingsRepository.exist({
+			where: {
+				userId: userId,
+				threadId: note.threadId ?? note.id,
+			},
 		});
-		if (threadMute) return;
+		if (isThreadMuted) return;
 
 		const unread = {
 			id: this.idService.genId(),
@@ -62,9 +64,9 @@ export class NoteReadService implements OnApplicationShutdown {
 
 		// 2秒経っても既読にならなかったら「未読の投稿がありますよ」イベントを発行する
 		setTimeout(2000, 'unread note', { signal: this.#shutdownController.signal }).then(async () => {
-			const exist = await this.noteUnreadsRepository.findOneBy({ id: unread.id });
+			const exist = await this.noteUnreadsRepository.exist({ where: { id: unread.id } });
 
-			if (exist == null) return;
+			if (!exist) return;
 
 			if (params.isMentioned) {
 				this.globalEventService.publishMainStream(userId, 'unreadMention', note.id);
diff --git a/packages/backend/src/core/SignupService.ts b/packages/backend/src/core/SignupService.ts
index e6b17a8741..1e44406c16 100644
--- a/packages/backend/src/core/SignupService.ts
+++ b/packages/backend/src/core/SignupService.ts
@@ -71,12 +71,12 @@ export class SignupService {
 		const secret = generateUserToken();
 
 		// Check username duplication
-		if (await this.usersRepository.findOneBy({ usernameLower: username.toLowerCase(), host: IsNull() })) {
+		if (await this.usersRepository.exist({ where: { usernameLower: username.toLowerCase(), host: IsNull() } })) {
 			throw new Error('DUPLICATED_USERNAME');
 		}
 
 		// Check deleted username duplication
-		if (await this.usedUsernamesRepository.findOneBy({ username: username.toLowerCase() })) {
+		if (await this.usedUsernamesRepository.exist({ where: { username: username.toLowerCase() } })) {
 			throw new Error('USED_USERNAME');
 		}
 
diff --git a/packages/backend/src/core/UserFollowingService.ts b/packages/backend/src/core/UserFollowingService.ts
index 7d90bc2c08..4d7bfeaf23 100644
--- a/packages/backend/src/core/UserFollowingService.ts
+++ b/packages/backend/src/core/UserFollowingService.ts
@@ -122,22 +122,26 @@ export class UserFollowingService implements OnModuleInit {
 			let autoAccept = false;
 
 			// 鍵アカウントであっても、既にフォローされていた場合はスルー
-			const following = await this.followingsRepository.findOneBy({
-				followerId: follower.id,
-				followeeId: followee.id,
+			const isFollowing = await this.followingsRepository.exist({
+				where: {
+					followerId: follower.id,
+					followeeId: followee.id,
+				},
 			});
-			if (following) {
+			if (isFollowing) {
 				autoAccept = true;
 			}
 
 			// フォローしているユーザーは自動承認オプション
 			if (!autoAccept && (this.userEntityService.isLocalUser(followee) && followeeProfile.autoAcceptFollowed)) {
-				const followed = await this.followingsRepository.findOneBy({
-					followerId: followee.id,
-					followeeId: follower.id,
+				const isFollowed = await this.followingsRepository.exist({
+					where: {
+						followerId: followee.id,
+						followeeId: follower.id,
+					},
 				});
 
-				if (followed) autoAccept = true;
+				if (isFollowed) autoAccept = true;
 			}
 
 			// Automatically accept if the follower is an account who has moved and the locked followee had accepted the old account.
@@ -206,12 +210,14 @@ export class UserFollowingService implements OnModuleInit {
 
 		this.cacheService.userFollowingsCache.refresh(follower.id);
 
-		const req = await this.followRequestsRepository.findOneBy({
-			followeeId: followee.id,
-			followerId: follower.id,
+		const requestExist = await this.followRequestsRepository.exist({
+			where: {
+				followeeId: followee.id,
+				followerId: follower.id,
+			},
 		});
 
-		if (req) {
+		if (requestExist) {
 			await this.followRequestsRepository.delete({
 				followeeId: followee.id,
 				followerId: follower.id,
@@ -505,12 +511,14 @@ export class UserFollowingService implements OnModuleInit {
 			}
 		}
 
-		const request = await this.followRequestsRepository.findOneBy({
-			followeeId: followee.id,
-			followerId: follower.id,
+		const requestExist = await this.followRequestsRepository.exist({
+			where: {
+				followeeId: followee.id,
+				followerId: follower.id,
+			},
 		});
 
-		if (request == null) {
+		if (!requestExist) {
 			throw new IdentifiableError('17447091-ce07-46dd-b331-c1fd4f15b1e7', 'request not found');
 		}
 
diff --git a/packages/backend/src/core/activitypub/ApAudienceService.ts b/packages/backend/src/core/activitypub/ApAudienceService.ts
index 0eab7fa335..a4ab5eae20 100644
--- a/packages/backend/src/core/activitypub/ApAudienceService.ts
+++ b/packages/backend/src/core/activitypub/ApAudienceService.ts
@@ -16,6 +16,8 @@ type AudienceInfo = {
 	visibleUsers: User[],
 };
 
+type GroupedAudience = Record<'public' | 'followers' | 'other', string[]>;
+
 @Injectable()
 export class ApAudienceService {
 	constructor(
@@ -67,11 +69,11 @@ export class ApAudienceService {
 	}
 
 	@bindThis
-	private groupingAudience(ids: string[], actor: RemoteUser) {
-		const groups = {
-			public: [] as string[],
-			followers: [] as string[],
-			other: [] as string[],
+	private groupingAudience(ids: string[], actor: RemoteUser): GroupedAudience {
+		const groups: GroupedAudience = {
+			public: [],
+			followers: [],
+			other: [],
 		};
 
 		for (const id of ids) {
@@ -90,7 +92,7 @@ export class ApAudienceService {
 	}
 
 	@bindThis
-	private isPublic(id: string) {
+	private isPublic(id: string): boolean {
 		return [
 			'https://www.w3.org/ns/activitystreams#Public',
 			'as#Public',
@@ -99,9 +101,7 @@ export class ApAudienceService {
 	}
 
 	@bindThis
-	private isFollowers(id: string, actor: RemoteUser) {
-		return (
-			id === (actor.followersUri ?? `${actor.uri}/followers`)
-		);
+	private isFollowers(id: string, actor: RemoteUser): boolean {
+		return id === (actor.followersUri ?? `${actor.uri}/followers`);
 	}
 }
diff --git a/packages/backend/src/core/activitypub/ApDbResolverService.ts b/packages/backend/src/core/activitypub/ApDbResolverService.ts
index 20283a163c..d5a530c903 100644
--- a/packages/backend/src/core/activitypub/ApDbResolverService.ts
+++ b/packages/backend/src/core/activitypub/ApDbResolverService.ts
@@ -99,13 +99,15 @@ export class ApDbResolverService implements OnApplicationShutdown {
 		if (parsed.local) {
 			if (parsed.type !== 'users') return null;
 
-			return await this.cacheService.userByIdCache.fetchMaybe(parsed.id, () => this.usersRepository.findOneBy({
-				id: parsed.id,
-			}).then(x => x ?? undefined)) as LocalUser | undefined ?? null;
+			return await this.cacheService.userByIdCache.fetchMaybe(
+				parsed.id,
+				() => this.usersRepository.findOneBy({ id: parsed.id }).then(x => x ?? undefined),
+			) as LocalUser | undefined ?? null;
 		} else {
-			return await this.cacheService.uriPersonCache.fetch(parsed.uri, () => this.usersRepository.findOneBy({
-				uri: parsed.uri,
-			})) as RemoteUser | null;
+			return await this.cacheService.uriPersonCache.fetch(
+				parsed.uri,
+				() => this.usersRepository.findOneBy({ uri: parsed.uri }),
+			) as RemoteUser | null;
 		}
 	}
 
@@ -145,9 +147,11 @@ export class ApDbResolverService implements OnApplicationShutdown {
 	} | null> {
 		const user = await this.apPersonService.resolvePerson(uri) as RemoteUser;
 
-		if (user == null) return null;
-
-		const key = await this.publicKeyByUserIdCache.fetch(user.id, () => this.userPublickeysRepository.findOneBy({ userId: user.id }), v => v != null);
+		const key = await this.publicKeyByUserIdCache.fetch(
+			user.id,
+			() => this.userPublickeysRepository.findOneBy({ userId: user.id }),
+			v => v != null,
+		);
 
 		return {
 			user,
diff --git a/packages/backend/src/core/activitypub/ApDeliverManagerService.ts b/packages/backend/src/core/activitypub/ApDeliverManagerService.ts
index 82c2c9f71f..09461973d9 100644
--- a/packages/backend/src/core/activitypub/ApDeliverManagerService.ts
+++ b/packages/backend/src/core/activitypub/ApDeliverManagerService.ts
@@ -29,6 +29,121 @@ const isFollowers = (recipe: IRecipe): recipe is IFollowersRecipe =>
 const isDirect = (recipe: IRecipe): recipe is IDirectRecipe =>
 	recipe.type === 'Direct';
 
+class DeliverManager {
+	private actor: ThinUser;
+	private activity: IActivity | null;
+	private recipes: IRecipe[] = [];
+
+	/**
+	 * Constructor
+	 * @param userEntityService
+	 * @param followingsRepository
+	 * @param queueService
+	 * @param actor Actor
+	 * @param activity Activity to deliver
+	 */
+	constructor(
+		private userEntityService: UserEntityService,
+		private followingsRepository: FollowingsRepository,
+		private queueService: QueueService,
+
+		actor: { id: User['id']; host: null; },
+		activity: IActivity | null,
+	) {
+		// 型で弾いてはいるが一応ローカルユーザーかチェック
+		// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
+		if (actor.host != null) throw new Error('actor.host must be null');
+
+		// パフォーマンス向上のためキューに突っ込むのはidのみに絞る
+		this.actor = {
+			id: actor.id,
+		};
+		this.activity = activity;
+	}
+
+	/**
+	 * Add recipe for followers deliver
+	 */
+	@bindThis
+	public addFollowersRecipe(): void {
+		const deliver: IFollowersRecipe = {
+			type: 'Followers',
+		};
+
+		this.addRecipe(deliver);
+	}
+
+	/**
+	 * Add recipe for direct deliver
+	 * @param to To
+	 */
+	@bindThis
+	public addDirectRecipe(to: RemoteUser): void {
+		const recipe: IDirectRecipe = {
+			type: 'Direct',
+			to,
+		};
+
+		this.addRecipe(recipe);
+	}
+
+	/**
+	 * Add recipe
+	 * @param recipe Recipe
+	 */
+	@bindThis
+	public addRecipe(recipe: IRecipe): void {
+		this.recipes.push(recipe);
+	}
+
+	/**
+	 * Execute delivers
+	 */
+	@bindThis
+	public async execute(): Promise<void> {
+		// The value flags whether it is shared or not.
+		// key: inbox URL, value: whether it is sharedInbox
+		const inboxes = new Map<string, boolean>();
+
+		// build inbox list
+		// Process follower recipes first to avoid duplication when processing direct recipes later.
+		if (this.recipes.some(r => isFollowers(r))) {
+			// followers deliver
+			// TODO: SELECT DISTINCT ON ("followerSharedInbox") "followerSharedInbox" みたいな問い合わせにすればよりパフォーマンス向上できそう
+			// ただ、sharedInboxがnullなリモートユーザーも稀におり、その対応ができなさそう?
+			const followers = await this.followingsRepository.find({
+				where: {
+					followeeId: this.actor.id,
+					followerHost: Not(IsNull()),
+				},
+				select: {
+					followerSharedInbox: true,
+					followerInbox: true,
+				},
+			});
+
+			for (const following of followers) {
+				const inbox = following.followerSharedInbox ?? following.followerInbox;
+				if (inbox === null) throw new Error('inbox is null');
+				inboxes.set(inbox, following.followerSharedInbox != null);
+			}
+		}
+
+		for (const recipe of this.recipes.filter(isDirect)) {
+			// check that shared inbox has not been added yet
+			if (recipe.to.sharedInbox !== null && inboxes.has(recipe.to.sharedInbox)) continue;
+
+			// check that they actually have an inbox
+			if (recipe.to.inbox === null) continue;
+
+			inboxes.set(recipe.to.inbox, false);
+		}
+
+		// deliver
+		this.queueService.deliverMany(this.actor, this.activity, inboxes);
+	}
+}
+
 @Injectable()
 export class ApDeliverManagerService {
 	constructor(
@@ -52,7 +167,7 @@ export class ApDeliverManagerService {
 	 * @param activity Activity
 	 */
 	@bindThis
-	public async deliverToFollowers(actor: { id: LocalUser['id']; host: null; }, activity: IActivity) {
+	public async deliverToFollowers(actor: { id: LocalUser['id']; host: null; }, activity: IActivity): Promise<void> {
 		const manager = new DeliverManager(
 			this.userEntityService,
 			this.followingsRepository,
@@ -71,7 +186,7 @@ export class ApDeliverManagerService {
 	 * @param to Target user
 	 */
 	@bindThis
-	public async deliverToUser(actor: { id: LocalUser['id']; host: null; }, activity: IActivity, to: RemoteUser) {
+	public async deliverToUser(actor: { id: LocalUser['id']; host: null; }, activity: IActivity, to: RemoteUser): Promise<void> {
 		const manager = new DeliverManager(
 			this.userEntityService,
 			this.followingsRepository,
@@ -84,7 +199,7 @@ export class ApDeliverManagerService {
 	}
 
 	@bindThis
-	public createDeliverManager(actor: { id: User['id']; host: null; }, activity: IActivity | null) {
+	public createDeliverManager(actor: { id: User['id']; host: null; }, activity: IActivity | null): DeliverManager {
 		return new DeliverManager(
 			this.userEntityService,
 			this.followingsRepository,
@@ -95,123 +210,3 @@ export class ApDeliverManagerService {
 		);
 	}
 }
-
-class DeliverManager {
-	private actor: ThinUser;
-	private activity: IActivity | null;
-	private recipes: IRecipe[] = [];
-
-	/**
-	 * Constructor
-	 * @param userEntityService
-	 * @param followingsRepository
-	 * @param queueService
-	 * @param actor Actor
-	 * @param activity Activity to deliver
-	 */
-	constructor(
-		private userEntityService: UserEntityService,
-		private followingsRepository: FollowingsRepository,
-		private queueService: QueueService,
-
-		actor: { id: User['id']; host: null; },
-		activity: IActivity | null,
-	) {
-		// 型で弾いてはいるが一応ローカルユーザーかチェック
-		if (actor.host != null) throw new Error('actor.host must be null');
-
-		// パフォーマンス向上のためキューに突っ込むのはidのみに絞る
-		this.actor = {
-			id: actor.id,
-		};
-		this.activity = activity;
-	}
-
-	/**
-	 * Add recipe for followers deliver
-	 */
-	@bindThis
-	public addFollowersRecipe() {
-		const deliver = {
-			type: 'Followers',
-		} as IFollowersRecipe;
-
-		this.addRecipe(deliver);
-	}
-
-	/**
-	 * Add recipe for direct deliver
-	 * @param to To
-	 */
-	@bindThis
-	public addDirectRecipe(to: RemoteUser) {
-		const recipe = {
-			type: 'Direct',
-			to,
-		} as IDirectRecipe;
-
-		this.addRecipe(recipe);
-	}
-
-	/**
-	 * Add recipe
-	 * @param recipe Recipe
-	 */
-	@bindThis
-	public addRecipe(recipe: IRecipe) {
-		this.recipes.push(recipe);
-	}
-
-	/**
-	 * Execute delivers
-	 */
-	@bindThis
-	public async execute() {
-		// The value flags whether it is shared or not.
-		// key: inbox URL, value: whether it is sharedInbox
-		const inboxes = new Map<string, boolean>();
-
-		/*
-		build inbox list
-
-		Process follower recipes first to avoid duplication when processing
-		direct recipes later.
-		*/
-		if (this.recipes.some(r => isFollowers(r))) {
-			// followers deliver
-			// TODO: SELECT DISTINCT ON ("followerSharedInbox") "followerSharedInbox" みたいな問い合わせにすればよりパフォーマンス向上できそう
-			// ただ、sharedInboxがnullなリモートユーザーも稀におり、その対応ができなさそう?
-			const followers = await this.followingsRepository.find({
-				where: {
-					followeeId: this.actor.id,
-					followerHost: Not(IsNull()),
-				},
-				select: {
-					followerSharedInbox: true,
-					followerInbox: true,
-				},
-			}) as {
-				followerSharedInbox: string | null;
-				followerInbox: string;
-			}[];
-
-			for (const following of followers) {
-				const inbox = following.followerSharedInbox ?? following.followerInbox;
-				inboxes.set(inbox, following.followerSharedInbox != null);
-			}
-		}
-
-		this.recipes.filter((recipe): recipe is IDirectRecipe =>
-			// followers recipes have already been processed
-			isDirect(recipe)
-			// check that shared inbox has not been added yet
-			&& !(recipe.to.sharedInbox && inboxes.has(recipe.to.sharedInbox))
-			// check that they actually have an inbox
-			&& recipe.to.inbox != null,
-		)
-			.forEach(recipe => inboxes.set(recipe.to.inbox!, false));
-
-		// deliver
-		this.queueService.deliverMany(this.actor, this.activity, inboxes);
-	}
-}
diff --git a/packages/backend/src/core/activitypub/ApInboxService.ts b/packages/backend/src/core/activitypub/ApInboxService.ts
index fdc6350bad..8a301d1434 100644
--- a/packages/backend/src/core/activitypub/ApInboxService.ts
+++ b/packages/backend/src/core/activitypub/ApInboxService.ts
@@ -21,7 +21,7 @@ import { CacheService } from '@/core/CacheService.js';
 import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
 import { UserEntityService } from '@/core/entities/UserEntityService.js';
 import { QueueService } from '@/core/QueueService.js';
-import type { UsersRepository, NotesRepository, FollowingsRepository, AbuseUserReportsRepository, FollowRequestsRepository, } from '@/models/index.js';
+import type { UsersRepository, NotesRepository, FollowingsRepository, AbuseUserReportsRepository, FollowRequestsRepository } from '@/models/index.js';
 import { bindThis } from '@/decorators.js';
 import type { RemoteUser } from '@/models/entities/User.js';
 import { getApHrefNullable, getApId, getApIds, getApType, getOneApHrefNullable, isAccept, isActor, isAdd, isAnnounce, isBlock, isCollection, isCollectionOrOrderedCollection, isCreate, isDelete, isFlag, isFollow, isLike, isMove, isOrderedCollectionPage, isPost, isReject, isRemove, isTombstone, isUndo, isUpdate, validActor, validPost } from './type.js';
@@ -115,7 +115,7 @@ export class ApInboxService {
 		if (actor.uri) {
 			if (actor.lastFetchedAt == null || Date.now() - actor.lastFetchedAt.getTime() > 1000 * 60 * 60 * 24) {
 				setImmediate(() => {
-					this.apPersonService.updatePerson(actor.uri!);
+					this.apPersonService.updatePerson(actor.uri);
 				});
 			}
 		}
@@ -237,7 +237,7 @@ export class ApInboxService {
 
 	@bindThis
 	private async add(actor: RemoteUser, activity: IAdd): Promise<void> {
-		if ('actor' in activity && actor.uri !== activity.actor) {
+		if (actor.uri !== activity.actor) {
 			throw new Error('invalid actor');
 		}
 
@@ -281,7 +281,7 @@ export class ApInboxService {
 		const unlock = await this.appLockService.getApLock(uri);
 
 		try {
-		// 既に同じURIを持つものが登録されていないかチェック
+			// 既に同じURIを持つものが登録されていないかチェック
 			const exist = await this.apNoteService.fetchNote(uri);
 			if (exist) {
 				return;
@@ -300,7 +300,7 @@ export class ApInboxService {
 						return;
 					}
 
-					this.logger.warn(`Error in announce target ${targetUri} - ${err.statusCode ?? err}`);
+					this.logger.warn(`Error in announce target ${targetUri} - ${err.statusCode}`);
 				}
 				throw err;
 			}
@@ -417,7 +417,7 @@ export class ApInboxService {
 
 	@bindThis
 	private async delete(actor: RemoteUser, activity: IDelete): Promise<string> {
-		if ('actor' in activity && actor.uri !== activity.actor) {
+		if (actor.uri !== activity.actor) {
 			throw new Error('invalid actor');
 		}
 
@@ -428,7 +428,7 @@ export class ApInboxService {
 			// typeが不明だけど、どうせ消えてるのでremote resolveしない
 			formerType = undefined;
 		} else {
-			const object = activity.object as IObject;
+			const object = activity.object;
 			if (isTombstone(object)) {
 				formerType = toSingle(object.formerType);
 			} else {
@@ -511,7 +511,10 @@ export class ApInboxService {
 		// 対象ユーザーは一番最初のユーザー として あとはコメントとして格納する
 		const uris = getApIds(activity.object);
 
-		const userIds = uris.filter(uri => uri.startsWith(this.config.url + '/users/')).map(uri => uri.split('/').pop()!);
+		const userIds = uris
+			.filter(uri => uri.startsWith(this.config.url + '/users/'))
+			.map(uri => uri.split('/').at(-1))
+			.filter((userId): userId is string => userId !== undefined);
 		const users = await this.usersRepository.findBy({
 			id: In(userIds),
 		});
@@ -574,7 +577,7 @@ export class ApInboxService {
 
 	@bindThis
 	private async remove(actor: RemoteUser, activity: IRemove): Promise<void> {
-		if ('actor' in activity && actor.uri !== activity.actor) {
+		if (actor.uri !== activity.actor) {
 			throw new Error('invalid actor');
 		}
 
@@ -594,7 +597,7 @@ export class ApInboxService {
 
 	@bindThis
 	private async undo(actor: RemoteUser, activity: IUndo): Promise<string> {
-		if ('actor' in activity && actor.uri !== activity.actor) {
+		if (actor.uri !== activity.actor) {
 			throw new Error('invalid actor');
 		}
 
@@ -626,12 +629,14 @@ export class ApInboxService {
 			return 'skip: follower not found';
 		}
 
-		const following = await this.followingsRepository.findOneBy({
-			followerId: follower.id,
-			followeeId: actor.id,
+		const isFollowing = await this.followingsRepository.exist({
+			where: {
+				followerId: follower.id,
+				followeeId: actor.id,
+			},
 		});
 
-		if (following) {
+		if (isFollowing) {
 			await this.userFollowingService.unfollow(follower, actor);
 			return 'ok: unfollowed';
 		}
@@ -681,22 +686,26 @@ export class ApInboxService {
 			return 'skip: フォロー解除しようとしているユーザーはローカルユーザーではありません';
 		}
 
-		const req = await this.followRequestsRepository.findOneBy({
-			followerId: actor.id,
-			followeeId: followee.id,
+		const requestExist = await this.followRequestsRepository.exist({
+			where: {
+				followerId: actor.id,
+				followeeId: followee.id,
+			},
 		});
 
-		const following = await this.followingsRepository.findOneBy({
-			followerId: actor.id,
-			followeeId: followee.id,
+		const isFollowing = await this.followingsRepository.exist({
+			where: {
+				followerId: actor.id,
+				followeeId: followee.id,
+			},
 		});
 
-		if (req) {
+		if (requestExist) {
 			await this.userFollowingService.cancelFollowRequest(followee, actor);
 			return 'ok: follow request canceled';
 		}
 
-		if (following) {
+		if (isFollowing) {
 			await this.userFollowingService.unfollow(actor, followee);
 			return 'ok: unfollowed';
 		}
@@ -721,7 +730,7 @@ export class ApInboxService {
 
 	@bindThis
 	private async update(actor: RemoteUser, activity: IUpdate): Promise<string> {
-		if ('actor' in activity && actor.uri !== activity.actor) {
+		if (actor.uri !== activity.actor) {
 			return 'skip: invalid actor';
 		}
 
@@ -735,7 +744,7 @@ export class ApInboxService {
 		});
 
 		if (isActor(object)) {
-			await this.apPersonService.updatePerson(actor.uri!, resolver, object);
+			await this.apPersonService.updatePerson(actor.uri, resolver, object);
 			return 'ok: Person updated';
 		} else if (getApType(object) === 'Question') {
 			await this.apQuestionService.updateQuestion(object, resolver).catch(err => console.error(err));
diff --git a/packages/backend/src/core/activitypub/ApMfmService.ts b/packages/backend/src/core/activitypub/ApMfmService.ts
index 411cf17d19..d7269eca92 100644
--- a/packages/backend/src/core/activitypub/ApMfmService.ts
+++ b/packages/backend/src/core/activitypub/ApMfmService.ts
@@ -4,9 +4,9 @@ import { DI } from '@/di-symbols.js';
 import type { Config } from '@/config.js';
 import { MfmService } from '@/core/MfmService.js';
 import type { Note } from '@/models/entities/Note.js';
+import { bindThis } from '@/decorators.js';
 import { extractApHashtagObjects } from './models/tag.js';
 import type { IObject } from './type.js';
-import { bindThis } from '@/decorators.js';
 
 @Injectable()
 export class ApMfmService {
@@ -19,14 +19,13 @@ export class ApMfmService {
 	}
 
 	@bindThis
-	public htmlToMfm(html: string, tag?: IObject | IObject[]) {
-		const hashtagNames = extractApHashtagObjects(tag).map(x => x.name).filter((x): x is string => x != null);
-
+	public htmlToMfm(html: string, tag?: IObject | IObject[]): string {
+		const hashtagNames = extractApHashtagObjects(tag).map(x => x.name);
 		return this.mfmService.fromHtml(html, hashtagNames);
 	}
 
 	@bindThis
-	public getNoteHtml(note: Note) {
+	public getNoteHtml(note: Note): string | null {
 		if (!note.text) return '';
 		return this.mfmService.toHtml(mfm.parse(note.text), JSON.parse(note.mentionedRemoteUsers));
 	}
diff --git a/packages/backend/src/core/activitypub/ApRendererService.ts b/packages/backend/src/core/activitypub/ApRendererService.ts
index d8b95ca4d1..95e3a936d2 100644
--- a/packages/backend/src/core/activitypub/ApRendererService.ts
+++ b/packages/backend/src/core/activitypub/ApRendererService.ts
@@ -1,6 +1,6 @@
 import { createPublicKey } from 'node:crypto';
 import { Inject, Injectable } from '@nestjs/common';
-import { In, IsNull } from 'typeorm';
+import { In } from 'typeorm';
 import { v4 as uuid } from 'uuid';
 import * as mfm from 'mfm-js';
 import { DI } from '@/di-symbols.js';
@@ -26,7 +26,6 @@ import { isNotNull } from '@/misc/is-not-null.js';
 import { LdSignatureService } from './LdSignatureService.js';
 import { ApMfmService } from './ApMfmService.js';
 import type { IAccept, IActivity, IAdd, IAnnounce, IApDocument, IApEmoji, IApHashtag, IApImage, IApMention, IBlock, ICreate, IDelete, IFlag, IFollow, IKey, ILike, IMove, IObject, IPost, IQuestion, IReject, IRemove, ITombstone, IUndo, IUpdate } from './type.js';
-import type { IIdentifier } from './models/identifier.js';
 
 @Injectable()
 export class ApRendererService {
@@ -63,7 +62,7 @@ export class ApRendererService {
 	}
 
 	@bindThis
-	public renderAccept(object: any, user: { id: User['id']; host: null }): IAccept {
+	public renderAccept(object: string | IObject, user: { id: User['id']; host: null }): IAccept {
 		return {
 			type: 'Accept',
 			actor: this.userEntityService.genLocalUserUri(user.id),
@@ -72,7 +71,7 @@ export class ApRendererService {
 	}
 
 	@bindThis
-	public renderAdd(user: LocalUser, target: any, object: any): IAdd {
+	public renderAdd(user: LocalUser, target: string | IObject | undefined, object: string | IObject): IAdd {
 		return {
 			type: 'Add',
 			actor: this.userEntityService.genLocalUserUri(user.id),
@@ -82,7 +81,7 @@ export class ApRendererService {
 	}
 
 	@bindThis
-	public renderAnnounce(object: any, note: Note): IAnnounce {
+	public renderAnnounce(object: string | IObject, note: Note): IAnnounce {
 		const attributedTo = this.userEntityService.genLocalUserUri(note.userId);
 
 		let to: string[] = [];
@@ -133,13 +132,13 @@ export class ApRendererService {
 
 	@bindThis
 	public renderCreate(object: IObject, note: Note): ICreate {
-		const activity = {
+		const activity: ICreate = {
 			id: `${this.config.url}/notes/${note.id}/activity`,
 			actor: this.userEntityService.genLocalUserUri(note.userId),
 			type: 'Create',
 			published: note.createdAt.toISOString(),
 			object,
-		} as ICreate;
+		};
 
 		if (object.to) activity.to = object.to;
 		if (object.cc) activity.cc = object.cc;
@@ -209,7 +208,7 @@ export class ApRendererService {
 	 * @param id Follower|Followee ID
 	 */
 	@bindThis
-	public async renderFollowUser(id: User['id']) {
+	public async renderFollowUser(id: User['id']): Promise<string> {
 		const user = await this.usersRepository.findOneByOrFail({ id: id }) as PartialLocalUser | PartialRemoteUser;
 		return this.userEntityService.getUserUri(user);
 	}
@@ -223,8 +222,8 @@ export class ApRendererService {
 		return {
 			id: requestId ?? `${this.config.url}/follows/${follower.id}/${followee.id}`,
 			type: 'Follow',
-			actor: this.userEntityService.getUserUri(follower)!,
-			object: this.userEntityService.getUserUri(followee)!,
+			actor: this.userEntityService.getUserUri(follower),
+			object: this.userEntityService.getUserUri(followee),
 		};
 	}
 
@@ -264,14 +263,14 @@ export class ApRendererService {
 	public async renderLike(noteReaction: NoteReaction, note: { uri: string | null }): Promise<ILike> {
 		const reaction = noteReaction.reaction;
 
-		const object = {
+		const object: ILike = {
 			type: 'Like',
 			id: `${this.config.url}/likes/${noteReaction.id}`,
 			actor: `${this.config.url}/users/${noteReaction.userId}`,
 			object: note.uri ? note.uri : `${this.config.url}/notes/${noteReaction.noteId}`,
 			content: reaction,
 			_misskey_reaction: reaction,
-		} as ILike;
+		};
 
 		if (reaction.startsWith(':')) {
 			const name = reaction.replaceAll(':', '');
@@ -287,7 +286,7 @@ export class ApRendererService {
 	public renderMention(mention: PartialLocalUser | PartialRemoteUser): IApMention {
 		return {
 			type: 'Mention',
-			href: this.userEntityService.getUserUri(mention)!,
+			href: this.userEntityService.getUserUri(mention),
 			name: this.userEntityService.isRemoteUser(mention) ? `@${mention.username}@${mention.host}` : `@${(mention as LocalUser).username}`,
 		};
 	}
@@ -297,8 +296,8 @@ export class ApRendererService {
 		src: PartialLocalUser | PartialRemoteUser,
 		dst: PartialLocalUser | PartialRemoteUser,
 	): IMove {
-		const actor = this.userEntityService.getUserUri(src)!;
-		const target = this.userEntityService.getUserUri(dst)!;
+		const actor = this.userEntityService.getUserUri(src);
+		const target = this.userEntityService.getUserUri(dst);
 		return {
 			id: `${this.config.url}/moves/${src.id}/${dst.id}`,
 			actor,
@@ -310,10 +309,10 @@ export class ApRendererService {
 
 	@bindThis
 	public async renderNote(note: Note, dive = true): Promise<IPost> {
-		const getPromisedFiles = async (ids: string[]) => {
-			if (!ids || ids.length === 0) return [];
+		const getPromisedFiles = async (ids: string[]): Promise<DriveFile[]> => {
+			if (ids.length === 0) return [];
 			const items = await this.driveFilesRepository.findBy({ id: In(ids) });
-			return ids.map(id => items.find(item => item.id === id)).filter(item => item != null) as DriveFile[];
+			return ids.map(id => items.find(item => item.id === id)).filter((item): item is DriveFile => item != null);
 		};
 
 		let inReplyTo;
@@ -323,9 +322,9 @@ export class ApRendererService {
 			inReplyToNote = await this.notesRepository.findOneBy({ id: note.replyId });
 
 			if (inReplyToNote != null) {
-				const inReplyToUser = await this.usersRepository.findOneBy({ id: inReplyToNote.userId });
+				const inReplyToUserExist = await this.usersRepository.exist({ where: { id: inReplyToNote.userId } });
 
-				if (inReplyToUser != null) {
+				if (inReplyToUserExist) {
 					if (inReplyToNote.uri) {
 						inReplyTo = inReplyToNote.uri;
 					} else {
@@ -375,7 +374,7 @@ export class ApRendererService {
 			id: In(note.mentions),
 		}) : [];
 
-		const hashtagTags = (note.tags ?? []).map(tag => this.renderHashtag(tag));
+		const hashtagTags = note.tags.map(tag => this.renderHashtag(tag));
 		const mentionTags = mentionedUsers.map(u => this.renderMention(u as LocalUser | RemoteUser));
 
 		const files = await getPromisedFiles(note.fileIds);
@@ -451,37 +450,26 @@ export class ApRendererService {
 	@bindThis
 	public async renderPerson(user: LocalUser) {
 		const id = this.userEntityService.genLocalUserUri(user.id);
-		const isSystem = !!user.username.match(/\./);
+		const isSystem = user.username.includes('.');
 
 		const [avatar, banner, profile] = await Promise.all([
-			user.avatarId ? this.driveFilesRepository.findOneBy({ id: user.avatarId }) : Promise.resolve(undefined),
-			user.bannerId ? this.driveFilesRepository.findOneBy({ id: user.bannerId }) : Promise.resolve(undefined),
+			user.avatarId ? this.driveFilesRepository.findOneBy({ id: user.avatarId }) : undefined,
+			user.bannerId ? this.driveFilesRepository.findOneBy({ id: user.bannerId }) : undefined,
 			this.userProfilesRepository.findOneByOrFail({ userId: user.id }),
 		]);
 
-		const attachment: {
+		const attachment = profile.fields.map(field => ({
 			type: 'PropertyValue',
-			name: string,
-			value: string,
-			identifier?: IIdentifier,
-		}[] = [];
-
-		if (profile.fields) {
-			for (const field of profile.fields) {
-				attachment.push({
-					type: 'PropertyValue',
-					name: field.name,
-					value: (field.value != null && field.value.match(/^https?:/))
-						? `<a href="${new URL(field.value).href}" rel="me nofollow noopener" target="_blank">${new URL(field.value).href}</a>`
-						: field.value,
-				});
-			}
-		}
+			name: field.name,
+			value: /^https?:/.test(field.value)
+				? `<a href="${new URL(field.value).href}" rel="me nofollow noopener" target="_blank">${new URL(field.value).href}</a>`
+				: field.value,
+		}));
 
 		const emojis = await this.getEmojis(user.emojis);
 		const apemojis = emojis.filter(emoji => !emoji.localOnly).map(emoji => this.renderEmoji(emoji));
 
-		const hashtagTags = (user.tags ?? []).map(tag => this.renderHashtag(tag));
+		const hashtagTags = user.tags.map(tag => this.renderHashtag(tag));
 
 		const tag = [
 			...apemojis,
@@ -490,7 +478,7 @@ export class ApRendererService {
 
 		const keypair = await this.userKeypairService.getUserKeypair(user.id);
 
-		const person = {
+		const person: any = {
 			type: isSystem ? 'Application' : user.isBot ? 'Service' : 'Person',
 			id,
 			inbox: `${id}/inbox`,
@@ -508,11 +496,11 @@ export class ApRendererService {
 			image: banner ? this.renderImage(banner) : null,
 			tag,
 			manuallyApprovesFollowers: user.isLocked,
-			discoverable: !!user.isExplorable,
+			discoverable: user.isExplorable,
 			publicKey: this.renderKey(user, keypair, '#main-key'),
 			isCat: user.isCat,
 			attachment: attachment.length ? attachment : undefined,
-		} as any;
+		};
 
 		if (user.movedToUri) {
 			person.movedTo = user.movedToUri;
@@ -552,7 +540,7 @@ export class ApRendererService {
 	}
 
 	@bindThis
-	public renderReject(object: any, user: { id: User['id'] }): IReject {
+	public renderReject(object: string | IObject, user: { id: User['id'] }): IReject {
 		return {
 			type: 'Reject',
 			actor: this.userEntityService.genLocalUserUri(user.id),
@@ -561,7 +549,7 @@ export class ApRendererService {
 	}
 
 	@bindThis
-	public renderRemove(user: { id: User['id'] }, target: any, object: any): IRemove {
+	public renderRemove(user: { id: User['id'] }, target: string | IObject | undefined, object: string | IObject): IRemove {
 		return {
 			type: 'Remove',
 			actor: this.userEntityService.genLocalUserUri(user.id),
@@ -579,8 +567,8 @@ export class ApRendererService {
 	}
 
 	@bindThis
-	public renderUndo(object: any, user: { id: User['id'] }): IUndo {
-		const id = typeof object.id === 'string' && object.id.startsWith(this.config.url) ? `${object.id}/undo` : undefined;
+	public renderUndo(object: string | IObject, user: { id: User['id'] }): IUndo {
+		const id = typeof object !== 'string' && typeof object.id === 'string' && object.id.startsWith(this.config.url) ? `${object.id}/undo` : undefined;
 
 		return {
 			type: 'Undo',
@@ -592,7 +580,7 @@ export class ApRendererService {
 	}
 
 	@bindThis
-	public renderUpdate(object: any, user: { id: User['id'] }): IUpdate {
+	public renderUpdate(object: string | IObject, user: { id: User['id'] }): IUpdate {
 		return {
 			id: `${this.config.url}/users/${user.id}#updates/${new Date().getTime()}`,
 			actor: this.userEntityService.genLocalUserUri(user.id),
@@ -658,7 +646,7 @@ export class ApRendererService {
 					vcard: 'http://www.w3.org/2006/vcard/ns#',
 				},
 			],
-		}, x as T & { id: string; });
+		}, x as T & { id: string });
 	}
 
 	@bindThis
@@ -683,13 +671,13 @@ export class ApRendererService {
 	 */
 	@bindThis
 	public renderOrderedCollectionPage(id: string, totalItems: any, orderedItems: any, partOf: string, prev?: string, next?: string) {
-		const page = {
+		const page: any = {
 			id,
 			partOf,
 			type: 'OrderedCollectionPage',
 			totalItems,
 			orderedItems,
-		} as any;
+		};
 
 		if (prev) page.prev = prev;
 		if (next) page.next = next;
@@ -706,7 +694,7 @@ export class ApRendererService {
 	 * @param orderedItems attached objects (optional)
 	 */
 	@bindThis
-	public renderOrderedCollection(id: string | null, totalItems: any, first?: string, last?: string, orderedItems?: IObject[]) {
+	public renderOrderedCollection(id: string, totalItems: number, first?: string, last?: string, orderedItems?: IObject[]) {
 		const page: any = {
 			id,
 			type: 'OrderedCollection',
@@ -722,7 +710,7 @@ export class ApRendererService {
 
 	@bindThis
 	private async getEmojis(names: string[]): Promise<Emoji[]> {
-		if (names == null || names.length === 0) return [];
+		if (names.length === 0) return [];
 
 		const allEmojis = await this.customEmojiService.localEmojisCache.fetch();
 		const emojis = names.map(name => allEmojis.get(name)).filter(isNotNull);
diff --git a/packages/backend/src/core/activitypub/ApRequestService.ts b/packages/backend/src/core/activitypub/ApRequestService.ts
index 5005612ab8..44676cac20 100644
--- a/packages/backend/src/core/activitypub/ApRequestService.ts
+++ b/packages/backend/src/core/activitypub/ApRequestService.ts
@@ -140,7 +140,7 @@ export class ApRequestService {
 	}
 
 	@bindThis
-	public async signedPost(user: { id: User['id'] }, url: string, object: any) {
+	public async signedPost(user: { id: User['id'] }, url: string, object: unknown): Promise<void> {
 		const body = JSON.stringify(object);
 
 		const keypair = await this.userKeypairService.getUserKeypair(user.id);
@@ -169,7 +169,7 @@ export class ApRequestService {
 	 * @param url URL to fetch
 	 */
 	@bindThis
-	public async signedGet(url: string, user: { id: User['id'] }) {
+	public async signedGet(url: string, user: { id: User['id'] }): Promise<unknown> {
 		const keypair = await this.userKeypairService.getUserKeypair(user.id);
 
 		const req = ApRequestCreator.createSignedGet({
diff --git a/packages/backend/src/core/activitypub/ApResolverService.ts b/packages/backend/src/core/activitypub/ApResolverService.ts
index 62dcad68df..3dfdee2426 100644
--- a/packages/backend/src/core/activitypub/ApResolverService.ts
+++ b/packages/backend/src/core/activitypub/ApResolverService.ts
@@ -73,10 +73,6 @@ export class Resolver {
 
 	@bindThis
 	public async resolve(value: string | IObject): Promise<IObject> {
-		if (value == null) {
-			throw new Error('resolvee is null (or undefined)');
-		}
-
 		if (typeof value !== 'string') {
 			return value;
 		}
@@ -116,11 +112,11 @@ export class Resolver {
 			? await this.apRequestService.signedGet(value, this.user) as IObject
 			: await this.httpRequestService.getJson(value, 'application/activity+json, application/ld+json')) as IObject;
 
-		if (object == null || (
+		if (
 			Array.isArray(object['@context']) ?
 				!(object['@context'] as unknown[]).includes('https://www.w3.org/ns/activitystreams') :
 				object['@context'] !== 'https://www.w3.org/ns/activitystreams'
-		)) {
+		) {
 			throw new Error('invalid response');
 		}
 
diff --git a/packages/backend/src/core/activitypub/LdSignatureService.ts b/packages/backend/src/core/activitypub/LdSignatureService.ts
index 20fe2a0a77..af7e243229 100644
--- a/packages/backend/src/core/activitypub/LdSignatureService.ts
+++ b/packages/backend/src/core/activitypub/LdSignatureService.ts
@@ -3,6 +3,8 @@ import { Injectable } from '@nestjs/common';
 import { HttpRequestService } from '@/core/HttpRequestService.js';
 import { bindThis } from '@/decorators.js';
 import { CONTEXTS } from './misc/contexts.js';
+import type { JsonLdDocument } from 'jsonld';
+import type { JsonLd, RemoteDocument } from 'jsonld/jsonld-spec.js';
 
 // RsaSignature2017 based from https://github.com/transmute-industries/RsaSignature2017
 
@@ -18,22 +20,21 @@ class LdSignature {
 
 	@bindThis
 	public async signRsaSignature2017(data: any, privateKey: string, creator: string, domain?: string, created?: Date): Promise<any> {
-		const options = {
-			type: 'RsaSignature2017',
-			creator,
-			domain,
-			nonce: crypto.randomBytes(16).toString('hex'),
-			created: (created ?? new Date()).toISOString(),
-		} as {
+		const options: {
 			type: string;
 			creator: string;
 			domain?: string;
 			nonce: string;
 			created: string;
+		} = {
+			type: 'RsaSignature2017',
+			creator,
+			nonce: crypto.randomBytes(16).toString('hex'),
+			created: (created ?? new Date()).toISOString(),
 		};
 
-		if (!domain) {
-			delete options.domain;
+		if (domain) {
+			options.domain = domain;
 		}
 
 		const toBeSigned = await this.createVerifyData(data, options);
@@ -62,7 +63,7 @@ class LdSignature {
 	}
 
 	@bindThis
-	public async createVerifyData(data: any, options: any) {
+	public async createVerifyData(data: any, options: any): Promise<string> {
 		const transformedOptions = {
 			...options,
 			'@context': 'https://w3id.org/identity/v1',
@@ -82,7 +83,7 @@ class LdSignature {
 	}
 
 	@bindThis
-	public async normalize(data: any) {
+	public async normalize(data: JsonLdDocument): Promise<string> {
 		const customLoader = this.getLoader();
 		// XXX: Importing jsonld dynamically since Jest frequently fails to import it statically
 		// https://github.com/misskey-dev/misskey/pull/9894#discussion_r1103753595
@@ -93,14 +94,14 @@ class LdSignature {
 
 	@bindThis
 	private getLoader() {
-		return async (url: string): Promise<any> => {
-			if (!url.match('^https?\:\/\/')) throw new Error(`Invalid URL ${url}`);
+		return async (url: string): Promise<RemoteDocument> => {
+			if (!/^https?:\/\//.test(url)) throw new Error(`Invalid URL ${url}`);
 
 			if (this.preLoad) {
 				if (url in CONTEXTS) {
 					if (this.debug) console.debug(`HIT: ${url}`);
 					return {
-						contextUrl: null,
+						contextUrl: undefined,
 						document: CONTEXTS[url],
 						documentUrl: url,
 					};
@@ -110,7 +111,7 @@ class LdSignature {
 			if (this.debug) console.debug(`MISS: ${url}`);
 			const document = await this.fetchDocument(url);
 			return {
-				contextUrl: null,
+				contextUrl: undefined,
 				document: document,
 				documentUrl: url,
 			};
@@ -118,13 +119,17 @@ class LdSignature {
 	}
 
 	@bindThis
-	private async fetchDocument(url: string) {
-		const json = await this.httpRequestService.send(url, {
-			headers: {
-				Accept: 'application/ld+json, application/json',
+	private async fetchDocument(url: string): Promise<JsonLd> {
+		const json = await this.httpRequestService.send(
+			url,
+			{
+				headers: {
+					Accept: 'application/ld+json, application/json',
+				},
+				timeout: this.loderTimeout,
 			},
-			timeout: this.loderTimeout,
-		}, { throwErrorWhenResponseNotOk: false }).then(res => {
+			{ throwErrorWhenResponseNotOk: false },
+		).then(res => {
 			if (!res.ok) {
 				throw new Error(`${res.status} ${res.statusText}`);
 			} else {
@@ -132,7 +137,7 @@ class LdSignature {
 			}
 		});
 
-		return json;
+		return json as JsonLd;
 	}
 
 	@bindThis
diff --git a/packages/backend/src/core/activitypub/misc/contexts.ts b/packages/backend/src/core/activitypub/misc/contexts.ts
index aee0d3629c..2bcd3811b2 100644
--- a/packages/backend/src/core/activitypub/misc/contexts.ts
+++ b/packages/backend/src/core/activitypub/misc/contexts.ts
@@ -1,3 +1,5 @@
+import type { JsonLd } from 'jsonld/jsonld-spec.js';
+
 /* eslint:disable:quotemark indent */
 const id_v1 = {
 	'@context': {
@@ -86,7 +88,7 @@ const id_v1 = {
 		'accessControl': { '@id': 'perm:accessControl', '@type': '@id' },
 		'writePermission': { '@id': 'perm:writePermission', '@type': '@id' },
 	},
-};
+} satisfies JsonLd;
 
 const security_v1 = {
 	'@context': {
@@ -137,7 +139,7 @@ const security_v1 = {
 		'signatureAlgorithm': 'sec:signingAlgorithm',
 		'signatureValue': 'sec:signatureValue',
 	},
-};
+} satisfies JsonLd;
 
 const activitystreams = {
 	'@context': {
@@ -517,9 +519,9 @@ const activitystreams = {
 			'@type': '@id',
 		},
 	},
-};
+} satisfies JsonLd;
 
-export const CONTEXTS: Record<string, unknown> = {
+export const CONTEXTS: Record<string, JsonLd> = {
 	'https://w3id.org/identity/v1': id_v1,
 	'https://w3id.org/security/v1': security_v1,
 	'https://www.w3.org/ns/activitystreams': activitystreams,
diff --git a/packages/backend/src/core/activitypub/models/ApNoteService.ts b/packages/backend/src/core/activitypub/models/ApNoteService.ts
index d3359ef900..46ed976a6b 100644
--- a/packages/backend/src/core/activitypub/models/ApNoteService.ts
+++ b/packages/backend/src/core/activitypub/models/ApNoteService.ts
@@ -200,7 +200,7 @@ export class ApNoteService {
 				| { status: 'ok'; res: Note }
 				| { status: 'permerror' | 'temperror' }
 			> => {
-				if (!uri.match(/^https?:/)) return { status: 'permerror' };
+				if (!/^https?:/.test(uri)) return { status: 'permerror' };
 				try {
 					const res = await this.resolveNote(uri);
 					if (res == null) return { status: 'permerror' };
diff --git a/packages/backend/src/core/activitypub/type.ts b/packages/backend/src/core/activitypub/type.ts
index 58371c8fe5..00890654eb 100644
--- a/packages/backend/src/core/activitypub/type.ts
+++ b/packages/backend/src/core/activitypub/type.ts
@@ -218,7 +218,6 @@ export interface IApPropertyValue extends IObject {
 }
 
 export const isPropertyValue = (object: IObject): object is IApPropertyValue =>
-	object &&
 	getApType(object) === 'PropertyValue' &&
 	typeof object.name === 'string' &&
 	'value' in object &&
diff --git a/packages/backend/src/core/chart/core.ts b/packages/backend/src/core/chart/core.ts
index d352adcc1f..7a89233eda 100644
--- a/packages/backend/src/core/chart/core.ts
+++ b/packages/backend/src/core/chart/core.ts
@@ -254,7 +254,7 @@ export default abstract class Chart<T extends Schema> {
 	private convertRawRecord(x: RawRecord<T>): KVs<T> {
 		const kvs = {} as Record<string, number>;
 		for (const k of Object.keys(x).filter((k) => k.startsWith(COLUMN_PREFIX)) as (keyof Columns<T>)[]) {
-			kvs[(k as string).substr(COLUMN_PREFIX.length).split(COLUMN_DELIMITER).join('.')] = x[k] as unknown as number;
+			kvs[(k as string).substring(COLUMN_PREFIX.length).split(COLUMN_DELIMITER).join('.')] = x[k] as unknown as number;
 		}
 		return kvs as KVs<T>;
 	}
@@ -627,7 +627,7 @@ export default abstract class Chart<T extends Schema> {
 			}
 
 		// 要求された範囲の最も古い箇所に位置するログが存在しなかったら
-		} else if (!isTimeSame(new Date(logs[logs.length - 1].date * 1000), gt)) {
+		} else if (!isTimeSame(new Date(logs.at(-1)!.date * 1000), gt)) {
 			// 要求された範囲の最も古い箇所時点での最も新しいログを持ってきて末尾に追加する
 			// (隙間埋めできないため)
 			const outdatedLog = await repository.findOne({
diff --git a/packages/backend/src/core/entities/ChannelEntityService.ts b/packages/backend/src/core/entities/ChannelEntityService.ts
index 15ffd44861..d24657260f 100644
--- a/packages/backend/src/core/entities/ChannelEntityService.ts
+++ b/packages/backend/src/core/entities/ChannelEntityService.ts
@@ -47,17 +47,26 @@ export class ChannelEntityService {
 
 		const banner = channel.bannerId ? await this.driveFilesRepository.findOneBy({ id: channel.bannerId }) : null;
 
-		const hasUnreadNote = meId ? (await this.noteUnreadsRepository.findOneBy({ noteChannelId: channel.id, userId: meId })) != null : undefined;
+		const hasUnreadNote = meId ? await this.noteUnreadsRepository.exist({
+			where: {
+				noteChannelId: channel.id,
+				userId: meId
+			},
+		}) : undefined;
 
-		const following = meId ? await this.channelFollowingsRepository.findOneBy({
-			followerId: meId,
-			followeeId: channel.id,
-		}) : null;
+		const isFollowing = meId ? await this.channelFollowingsRepository.exist({
+			where: {
+				followerId: meId,
+				followeeId: channel.id,
+			},
+		}) : false;
 
-		const favorite = meId ? await this.channelFavoritesRepository.findOneBy({
-			userId: meId,
-			channelId: channel.id,
-		}) : null;
+		const isFavorited = meId ? await this.channelFavoritesRepository.exist({
+			where: {
+				userId: meId,
+				channelId: channel.id,
+			},
+		}) : false;
 
 		const pinnedNotes = channel.pinnedNoteIds.length > 0 ? await this.notesRepository.find({
 			where: {
@@ -80,8 +89,8 @@ export class ChannelEntityService {
 			notesCount: channel.notesCount,
 
 			...(me ? {
-				isFollowing: following != null,
-				isFavorited: favorite != null,
+				isFollowing,
+				isFavorited,
 				hasUnreadNote,
 			} : {}),
 
diff --git a/packages/backend/src/core/entities/ClipEntityService.ts b/packages/backend/src/core/entities/ClipEntityService.ts
index 33d3c53806..f558cbc33d 100644
--- a/packages/backend/src/core/entities/ClipEntityService.ts
+++ b/packages/backend/src/core/entities/ClipEntityService.ts
@@ -39,7 +39,7 @@ export class ClipEntityService {
 			description: clip.description,
 			isPublic: clip.isPublic,
 			favoritedCount: await this.clipFavoritesRepository.countBy({ clipId: clip.id }),
-			isFavorited: meId ? await this.clipFavoritesRepository.findOneBy({ clipId: clip.id, userId: meId }).then(x => x != null) : undefined,
+			isFavorited: meId ? await this.clipFavoritesRepository.exist({ where: { clipId: clip.id, userId: meId } }) : undefined,
 		});
 	}
 
diff --git a/packages/backend/src/core/entities/FlashEntityService.ts b/packages/backend/src/core/entities/FlashEntityService.ts
index e52a591884..92345457c9 100644
--- a/packages/backend/src/core/entities/FlashEntityService.ts
+++ b/packages/backend/src/core/entities/FlashEntityService.ts
@@ -40,7 +40,7 @@ export class FlashEntityService {
 			summary: flash.summary,
 			script: flash.script,
 			likedCount: flash.likedCount,
-			isLiked: meId ? await this.flashLikesRepository.findOneBy({ flashId: flash.id, userId: meId }).then(x => x != null) : undefined,
+			isLiked: meId ? await this.flashLikesRepository.exist({ where: { flashId: flash.id, userId: meId } }) : undefined,
 		});
 	}
 
diff --git a/packages/backend/src/core/entities/GalleryPostEntityService.ts b/packages/backend/src/core/entities/GalleryPostEntityService.ts
index 632c75304f..c44a5df118 100644
--- a/packages/backend/src/core/entities/GalleryPostEntityService.ts
+++ b/packages/backend/src/core/entities/GalleryPostEntityService.ts
@@ -46,7 +46,7 @@ export class GalleryPostEntityService {
 			tags: post.tags.length > 0 ? post.tags : undefined,
 			isSensitive: post.isSensitive,
 			likedCount: post.likedCount,
-			isLiked: meId ? await this.galleryLikesRepository.findOneBy({ postId: post.id, userId: meId }).then(x => x != null) : undefined,
+			isLiked: meId ? await this.galleryLikesRepository.exist({ where: { postId: post.id, userId: meId } }) : undefined,
 		});
 	}
 
diff --git a/packages/backend/src/core/entities/NoteEntityService.ts b/packages/backend/src/core/entities/NoteEntityService.ts
index e730c0eb8f..546e5f56d2 100644
--- a/packages/backend/src/core/entities/NoteEntityService.ts
+++ b/packages/backend/src/core/entities/NoteEntityService.ts
@@ -106,16 +106,14 @@ export class NoteEntityService implements OnModuleInit {
 				hide = false;
 			} else {
 			// フォロワーかどうか
-				const following = await this.followingsRepository.findOneBy({
-					followeeId: packedNote.userId,
-					followerId: meId,
+				const isFollowing = await this.followingsRepository.exist({
+					where: {
+						followeeId: packedNote.userId,
+						followerId: meId,
+					},
 				});
 
-				if (following == null) {
-					hide = true;
-				} else {
-					hide = false;
-				}
+				hide = !isFollowing;
 			}
 		}
 
diff --git a/packages/backend/src/core/entities/PageEntityService.ts b/packages/backend/src/core/entities/PageEntityService.ts
index d6da856637..94b26a5017 100644
--- a/packages/backend/src/core/entities/PageEntityService.ts
+++ b/packages/backend/src/core/entities/PageEntityService.ts
@@ -97,7 +97,7 @@ export class PageEntityService {
 			eyeCatchingImage: page.eyeCatchingImageId ? await this.driveFileEntityService.pack(page.eyeCatchingImageId) : null,
 			attachedFiles: this.driveFileEntityService.packMany((await Promise.all(attachedFiles)).filter((x): x is DriveFile => x != null)),
 			likedCount: page.likedCount,
-			isLiked: meId ? await this.pageLikesRepository.findOneBy({ pageId: page.id, userId: meId }).then(x => x != null) : undefined,
+			isLiked: meId ? await this.pageLikesRepository.exist({ where: { pageId: page.id, userId: meId } }) : undefined,
 		});
 	}
 
diff --git a/packages/backend/src/core/entities/UserEntityService.ts b/packages/backend/src/core/entities/UserEntityService.ts
index 6dacaa1032..7d248f8524 100644
--- a/packages/backend/src/core/entities/UserEntityService.ts
+++ b/packages/backend/src/core/entities/UserEntityService.ts
@@ -230,12 +230,14 @@ export class UserEntityService implements OnModuleInit {
 		/*
 		const myAntennas = (await this.antennaService.getAntennas()).filter(a => a.userId === userId);
 
-		const unread = myAntennas.length > 0 ? await this.antennaNotesRepository.findOneBy({
-			antennaId: In(myAntennas.map(x => x.id)),
-			read: false,
-		}) : null;
+		const isUnread = (myAntennas.length > 0 ? await this.antennaNotesRepository.exist({
+			where: {
+				antennaId: In(myAntennas.map(x => x.id)),
+				read: false,
+			},
+		}) : false);
 
-		return unread != null;
+		return isUnread;
 		*/
 		return false; // TODO
 	}
diff --git a/packages/backend/src/misc/acct.ts b/packages/backend/src/misc/acct.ts
index d1a6852a95..fb3b657cf7 100644
--- a/packages/backend/src/misc/acct.ts
+++ b/packages/backend/src/misc/acct.ts
@@ -4,7 +4,7 @@ export type Acct = {
 };
 
 export function parse(acct: string): Acct {
-	if (acct.startsWith('@')) acct = acct.substr(1);
+	if (acct.startsWith('@')) acct = acct.substring(1);
 	const split = acct.split('@', 2);
 	return { username: split[0], host: split[1] ?? null };
 }
diff --git a/packages/backend/src/misc/prelude/array.ts b/packages/backend/src/misc/prelude/array.ts
index 0b2830cb7b..2524eacfb3 100644
--- a/packages/backend/src/misc/prelude/array.ts
+++ b/packages/backend/src/misc/prelude/array.ts
@@ -67,8 +67,9 @@ export function maximum(xs: number[]): number {
 export function groupBy<T>(f: EndoRelation<T>, xs: T[]): T[][] {
 	const groups = [] as T[][];
 	for (const x of xs) {
-		if (groups.length !== 0 && f(groups[groups.length - 1][0], x)) {
-			groups[groups.length - 1].push(x);
+		const lastGroup = groups.at(-1);
+		if (lastGroup !== undefined && f(lastGroup[0], x)) {
+			lastGroup.push(x);
 		} else {
 			groups.push([x]);
 		}
diff --git a/packages/backend/src/queue/processors/CleanRemoteFilesProcessorService.ts b/packages/backend/src/queue/processors/CleanRemoteFilesProcessorService.ts
index c54bf59ae4..6f887089eb 100644
--- a/packages/backend/src/queue/processors/CleanRemoteFilesProcessorService.ts
+++ b/packages/backend/src/queue/processors/CleanRemoteFilesProcessorService.ts
@@ -1,7 +1,7 @@
 import { Inject, Injectable } from '@nestjs/common';
 import { IsNull, MoreThan, Not } from 'typeorm';
 import { DI } from '@/di-symbols.js';
-import type { DriveFilesRepository } from '@/models/index.js';
+import type { DriveFile, DriveFilesRepository } from '@/models/index.js';
 import type { Config } from '@/config.js';
 import type Logger from '@/logger.js';
 import { DriveService } from '@/core/DriveService.js';
@@ -31,7 +31,7 @@ export class CleanRemoteFilesProcessorService {
 		this.logger.info('Deleting cached remote files...');
 
 		let deletedCount = 0;
-		let cursor: any = null;
+		let cursor: DriveFile['id'] | null = null;
 
 		while (true) {
 			const files = await this.driveFilesRepository.find({
@@ -51,7 +51,7 @@ export class CleanRemoteFilesProcessorService {
 				break;
 			}
 
-			cursor = files[files.length - 1].id;
+			cursor = files.at(-1)?.id ?? null;
 
 			await Promise.all(files.map(file => this.driveService.deleteFileSync(file, true)));
 
diff --git a/packages/backend/src/queue/processors/DeleteAccountProcessorService.ts b/packages/backend/src/queue/processors/DeleteAccountProcessorService.ts
index 65ded170b7..b2886563f4 100644
--- a/packages/backend/src/queue/processors/DeleteAccountProcessorService.ts
+++ b/packages/backend/src/queue/processors/DeleteAccountProcessorService.ts
@@ -70,7 +70,7 @@ export class DeleteAccountProcessorService {
 					break;
 				}
 
-				cursor = notes[notes.length - 1].id;
+				cursor = notes.at(-1)?.id ?? null;
 
 				await this.notesRepository.delete(notes.map(note => note.id));
 
@@ -101,7 +101,7 @@ export class DeleteAccountProcessorService {
 					break;
 				}
 
-				cursor = files[files.length - 1].id;
+				cursor = files.at(-1)?.id ?? null;
 
 				for (const file of files) {
 					await this.driveService.deleteFileSync(file);
diff --git a/packages/backend/src/queue/processors/DeleteDriveFilesProcessorService.ts b/packages/backend/src/queue/processors/DeleteDriveFilesProcessorService.ts
index 6772c5dc76..07e3762330 100644
--- a/packages/backend/src/queue/processors/DeleteDriveFilesProcessorService.ts
+++ b/packages/backend/src/queue/processors/DeleteDriveFilesProcessorService.ts
@@ -1,7 +1,7 @@
 import { Inject, Injectable } from '@nestjs/common';
 import { MoreThan } from 'typeorm';
 import { DI } from '@/di-symbols.js';
-import type { UsersRepository, DriveFilesRepository } from '@/models/index.js';
+import type { UsersRepository, DriveFilesRepository, DriveFile } from '@/models/index.js';
 import type { Config } from '@/config.js';
 import type Logger from '@/logger.js';
 import { DriveService } from '@/core/DriveService.js';
@@ -40,7 +40,7 @@ export class DeleteDriveFilesProcessorService {
 		}
 
 		let deletedCount = 0;
-		let cursor: any = null;
+		let cursor: DriveFile['id'] | null = null;
 
 		while (true) {
 			const files = await this.driveFilesRepository.find({
@@ -59,7 +59,7 @@ export class DeleteDriveFilesProcessorService {
 				break;
 			}
 
-			cursor = files[files.length - 1].id;
+			cursor = files.at(-1)?.id ?? null;
 
 			for (const file of files) {
 				await this.driveService.deleteFileSync(file);
diff --git a/packages/backend/src/queue/processors/ExportBlockingProcessorService.ts b/packages/backend/src/queue/processors/ExportBlockingProcessorService.ts
index eb758e162d..d100c6d09f 100644
--- a/packages/backend/src/queue/processors/ExportBlockingProcessorService.ts
+++ b/packages/backend/src/queue/processors/ExportBlockingProcessorService.ts
@@ -3,7 +3,7 @@ import { Inject, Injectable } from '@nestjs/common';
 import { MoreThan } from 'typeorm';
 import { format as dateFormat } from 'date-fns';
 import { DI } from '@/di-symbols.js';
-import type { UsersRepository, BlockingsRepository } from '@/models/index.js';
+import type { UsersRepository, BlockingsRepository, Blocking } from '@/models/index.js';
 import type { Config } from '@/config.js';
 import type Logger from '@/logger.js';
 import { DriveService } from '@/core/DriveService.js';
@@ -53,7 +53,7 @@ export class ExportBlockingProcessorService {
 			const stream = fs.createWriteStream(path, { flags: 'a' });
 
 			let exportedCount = 0;
-			let cursor: any = null;
+			let cursor: Blocking['id'] | null = null;
 
 			while (true) {
 				const blockings = await this.blockingsRepository.find({
@@ -72,7 +72,7 @@ export class ExportBlockingProcessorService {
 					break;
 				}
 
-				cursor = blockings[blockings.length - 1].id;
+				cursor = blockings.at(-1)?.id ?? null;
 
 				for (const block of blockings) {
 					const u = await this.usersRepository.findOneBy({ id: block.blockeeId });
diff --git a/packages/backend/src/queue/processors/ExportFavoritesProcessorService.ts b/packages/backend/src/queue/processors/ExportFavoritesProcessorService.ts
index 76c38a6b86..2be42b1a7a 100644
--- a/packages/backend/src/queue/processors/ExportFavoritesProcessorService.ts
+++ b/packages/backend/src/queue/processors/ExportFavoritesProcessorService.ts
@@ -94,7 +94,7 @@ export class ExportFavoritesProcessorService {
 					break;
 				}
 
-				cursor = favorites[favorites.length - 1].id;
+				cursor = favorites.at(-1)?.id ?? null;
 
 				for (const favorite of favorites) {
 					let poll: Poll | undefined;
diff --git a/packages/backend/src/queue/processors/ExportFollowingProcessorService.ts b/packages/backend/src/queue/processors/ExportFollowingProcessorService.ts
index 8726cb1402..d54e5e0b34 100644
--- a/packages/backend/src/queue/processors/ExportFollowingProcessorService.ts
+++ b/packages/backend/src/queue/processors/ExportFollowingProcessorService.ts
@@ -79,7 +79,7 @@ export class ExportFollowingProcessorService {
 					break;
 				}
 
-				cursor = followings[followings.length - 1].id;
+				cursor = followings.at(-1)?.id ?? null;
 
 				for (const following of followings) {
 					const u = await this.usersRepository.findOneBy({ id: following.followeeId });
diff --git a/packages/backend/src/queue/processors/ExportMutingProcessorService.ts b/packages/backend/src/queue/processors/ExportMutingProcessorService.ts
index 0f11a9e843..030e38931e 100644
--- a/packages/backend/src/queue/processors/ExportMutingProcessorService.ts
+++ b/packages/backend/src/queue/processors/ExportMutingProcessorService.ts
@@ -3,7 +3,7 @@ import { Inject, Injectable } from '@nestjs/common';
 import { IsNull, MoreThan } from 'typeorm';
 import { format as dateFormat } from 'date-fns';
 import { DI } from '@/di-symbols.js';
-import type { MutingsRepository, UsersRepository, BlockingsRepository } from '@/models/index.js';
+import type { MutingsRepository, UsersRepository, BlockingsRepository, Muting } from '@/models/index.js';
 import type { Config } from '@/config.js';
 import type Logger from '@/logger.js';
 import { DriveService } from '@/core/DriveService.js';
@@ -56,7 +56,7 @@ export class ExportMutingProcessorService {
 			const stream = fs.createWriteStream(path, { flags: 'a' });
 
 			let exportedCount = 0;
-			let cursor: any = null;
+			let cursor: Muting['id'] | null = null;
 
 			while (true) {
 				const mutes = await this.mutingsRepository.find({
@@ -76,7 +76,7 @@ export class ExportMutingProcessorService {
 					break;
 				}
 
-				cursor = mutes[mutes.length - 1].id;
+				cursor = mutes.at(-1)?.id ?? null;
 
 				for (const mute of mutes) {
 					const u = await this.usersRepository.findOneBy({ id: mute.muteeId });
diff --git a/packages/backend/src/queue/processors/ExportNotesProcessorService.ts b/packages/backend/src/queue/processors/ExportNotesProcessorService.ts
index 24fb331883..75f32ffee3 100644
--- a/packages/backend/src/queue/processors/ExportNotesProcessorService.ts
+++ b/packages/backend/src/queue/processors/ExportNotesProcessorService.ts
@@ -90,7 +90,7 @@ export class ExportNotesProcessorService {
 					break;
 				}
 
-				cursor = notes[notes.length - 1].id;
+				cursor = notes.at(-1)?.id ?? null;
 
 				for (const note of notes) {
 					let poll: Poll | undefined;
diff --git a/packages/backend/src/server/ActivityPubServerService.ts b/packages/backend/src/server/ActivityPubServerService.ts
index f53351d999..634f5f0a4e 100644
--- a/packages/backend/src/server/ActivityPubServerService.ts
+++ b/packages/backend/src/server/ActivityPubServerService.ts
@@ -181,7 +181,7 @@ export class ActivityPubServerService {
 				undefined,
 				inStock ? `${partOf}?${url.query({
 					page: 'true',
-					cursor: followings[followings.length - 1].id,
+					cursor: followings.at(-1)!.id,
 				})}` : undefined,
 			);
 
@@ -189,7 +189,11 @@ export class ActivityPubServerService {
 			return (this.apRendererService.addContext(rendered));
 		} else {
 			// index page
-			const rendered = this.apRendererService.renderOrderedCollection(partOf, user.followersCount, `${partOf}?page=true`);
+			const rendered = this.apRendererService.renderOrderedCollection(
+				partOf,
+				user.followersCount,
+				`${partOf}?page=true`,
+			);
 			reply.header('Cache-Control', 'public, max-age=180');
 			this.setResponseType(request, reply);
 			return (this.apRendererService.addContext(rendered));
@@ -269,7 +273,7 @@ export class ActivityPubServerService {
 				undefined,
 				inStock ? `${partOf}?${url.query({
 					page: 'true',
-					cursor: followings[followings.length - 1].id,
+					cursor: followings.at(-1)!.id,
 				})}` : undefined,
 			);
 
@@ -277,7 +281,11 @@ export class ActivityPubServerService {
 			return (this.apRendererService.addContext(rendered));
 		} else {
 			// index page
-			const rendered = this.apRendererService.renderOrderedCollection(partOf, user.followingCount, `${partOf}?page=true`);
+			const rendered = this.apRendererService.renderOrderedCollection(
+				partOf,
+				user.followingCount,
+				`${partOf}?page=true`,
+			);
 			reply.header('Cache-Control', 'public, max-age=180');
 			this.setResponseType(request, reply);
 			return (this.apRendererService.addContext(rendered));
@@ -310,7 +318,10 @@ export class ActivityPubServerService {
 
 		const rendered = this.apRendererService.renderOrderedCollection(
 			`${this.config.url}/users/${userId}/collections/featured`,
-			renderedNotes.length, undefined, undefined, renderedNotes,
+			renderedNotes.length,
+			undefined,
+			undefined,
+			renderedNotes,
 		);
 
 		reply.header('Cache-Control', 'public, max-age=180');
@@ -387,7 +398,7 @@ export class ActivityPubServerService {
 				})}` : undefined,
 				notes.length ? `${partOf}?${url.query({
 					page: 'true',
-					until_id: notes[notes.length - 1].id,
+					until_id: notes.at(-1)!.id,
 				})}` : undefined,
 			);
 
@@ -395,7 +406,9 @@ export class ActivityPubServerService {
 			return (this.apRendererService.addContext(rendered));
 		} else {
 			// index page
-			const rendered = this.apRendererService.renderOrderedCollection(partOf, user.notesCount,
+			const rendered = this.apRendererService.renderOrderedCollection(
+				partOf,
+				user.notesCount,
 				`${partOf}?page=true`,
 				`${partOf}?page=true&since_id=000000000000000000000000`,
 			);
diff --git a/packages/backend/src/server/api/SignupApiService.ts b/packages/backend/src/server/api/SignupApiService.ts
index fc5f3811eb..5e18dcbe08 100644
--- a/packages/backend/src/server/api/SignupApiService.ts
+++ b/packages/backend/src/server/api/SignupApiService.ts
@@ -128,12 +128,12 @@ export class SignupApiService {
 		}
 
 		if (instance.emailRequiredForSignup) {
-			if (await this.usersRepository.findOneBy({ usernameLower: username.toLowerCase(), host: IsNull() })) {
+			if (await this.usersRepository.exist({ where: { usernameLower: username.toLowerCase(), host: IsNull() } })) {
 				throw new FastifyReplyError(400, 'DUPLICATED_USERNAME');
 			}
 
 			// Check deleted username duplication
-			if (await this.usedUsernamesRepository.findOneBy({ username: username.toLowerCase() })) {
+			if (await this.usedUsernamesRepository.exist({ where: { username: username.toLowerCase() } })) {
 				throw new FastifyReplyError(400, 'USED_USERNAME');
 			}
 
diff --git a/packages/backend/src/server/api/endpoints/admin/promo/create.ts b/packages/backend/src/server/api/endpoints/admin/promo/create.ts
index bee1ffbaee..8401cf51d9 100644
--- a/packages/backend/src/server/api/endpoints/admin/promo/create.ts
+++ b/packages/backend/src/server/api/endpoints/admin/promo/create.ts
@@ -50,9 +50,9 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
 				throw e;
 			});
 
-			const exist = await this.promoNotesRepository.findOneBy({ noteId: note.id });
+			const exist = await this.promoNotesRepository.exist({ where: { noteId: note.id } });
 
-			if (exist != null) {
+			if (exist) {
 				throw new ApiError(meta.errors.alreadyPromoted);
 			}
 
diff --git a/packages/backend/src/server/api/endpoints/admin/roles/update.ts b/packages/backend/src/server/api/endpoints/admin/roles/update.ts
index 467f157a61..1fedab4540 100644
--- a/packages/backend/src/server/api/endpoints/admin/roles/update.ts
+++ b/packages/backend/src/server/api/endpoints/admin/roles/update.ts
@@ -69,8 +69,8 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
 		private globalEventService: GlobalEventService,
 	) {
 		super(meta, paramDef, async (ps) => {
-			const role = await this.rolesRepository.findOneBy({ id: ps.roleId });
-			if (role == null) {
+			const roleExist = await this.rolesRepository.exist({ where: { id: ps.roleId } });
+			if (!roleExist) {
 				throw new ApiError(meta.errors.noSuchRole);
 			}
 
diff --git a/packages/backend/src/server/api/endpoints/auth/accept.ts b/packages/backend/src/server/api/endpoints/auth/accept.ts
index e69f9c12e2..aa199ab730 100644
--- a/packages/backend/src/server/api/endpoints/auth/accept.ts
+++ b/packages/backend/src/server/api/endpoints/auth/accept.ts
@@ -58,12 +58,14 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
 			const accessToken = secureRndstr(32);
 
 			// Fetch exist access token
-			const exist = await this.accessTokensRepository.findOneBy({
-				appId: session.appId,
-				userId: me.id,
+			const exist = await this.accessTokensRepository.exist({
+				where: {
+					appId: session.appId,
+					userId: me.id,
+				},
 			});
 
-			if (exist == null) {
+			if (!exist) {
 				const app = await this.appsRepository.findOneByOrFail({ id: session.appId });
 
 				// Generate Hash
diff --git a/packages/backend/src/server/api/endpoints/blocking/create.ts b/packages/backend/src/server/api/endpoints/blocking/create.ts
index d9ba99f209..4ad40c8f1c 100644
--- a/packages/backend/src/server/api/endpoints/blocking/create.ts
+++ b/packages/backend/src/server/api/endpoints/blocking/create.ts
@@ -84,12 +84,14 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
 			});
 
 			// Check if already blocking
-			const exist = await this.blockingsRepository.findOneBy({
-				blockerId: blocker.id,
-				blockeeId: blockee.id,
+			const exist = await this.blockingsRepository.exist({
+				where: {
+					blockerId: blocker.id,
+					blockeeId: blockee.id,
+				},
 			});
 
-			if (exist != null) {
+			if (exist) {
 				throw new ApiError(meta.errors.alreadyBlocking);
 			}
 
diff --git a/packages/backend/src/server/api/endpoints/blocking/delete.ts b/packages/backend/src/server/api/endpoints/blocking/delete.ts
index 46dd26a45a..38913ae932 100644
--- a/packages/backend/src/server/api/endpoints/blocking/delete.ts
+++ b/packages/backend/src/server/api/endpoints/blocking/delete.ts
@@ -84,12 +84,14 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
 			});
 
 			// Check not blocking
-			const exist = await this.blockingsRepository.findOneBy({
-				blockerId: blocker.id,
-				blockeeId: blockee.id,
+			const exist = await this.blockingsRepository.exist({
+				where: {
+					blockerId: blocker.id,
+					blockeeId: blockee.id,
+				}
 			});
 
-			if (exist == null) {
+			if (!exist) {
 				throw new ApiError(meta.errors.notBlocking);
 			}
 
diff --git a/packages/backend/src/server/api/endpoints/clips/add-note.ts b/packages/backend/src/server/api/endpoints/clips/add-note.ts
index c3561e2a71..2837f2cf81 100644
--- a/packages/backend/src/server/api/endpoints/clips/add-note.ts
+++ b/packages/backend/src/server/api/endpoints/clips/add-note.ts
@@ -87,12 +87,14 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
 				throw e;
 			});
 
-			const exist = await this.clipNotesRepository.findOneBy({
-				noteId: note.id,
-				clipId: clip.id,
+			const exist = await this.clipNotesRepository.exist({
+				where: {
+					noteId: note.id,
+					clipId: clip.id,
+				},
 			});
 
-			if (exist != null) {
+			if (exist) {
 				throw new ApiError(meta.errors.alreadyClipped);
 			}
 
diff --git a/packages/backend/src/server/api/endpoints/clips/favorite.ts b/packages/backend/src/server/api/endpoints/clips/favorite.ts
index f08caaf8d7..ce09855531 100644
--- a/packages/backend/src/server/api/endpoints/clips/favorite.ts
+++ b/packages/backend/src/server/api/endpoints/clips/favorite.ts
@@ -58,12 +58,14 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
 				throw new ApiError(meta.errors.noSuchClip);
 			}
 
-			const exist = await this.clipFavoritesRepository.findOneBy({
-				clipId: clip.id,
-				userId: me.id,
+			const exist = await this.clipFavoritesRepository.exist({
+				where: {
+					clipId: clip.id,
+					userId: me.id,
+				},
 			});
 
-			if (exist != null) {
+			if (exist) {
 				throw new ApiError(meta.errors.alreadyFavorited);
 			}
 
diff --git a/packages/backend/src/server/api/endpoints/drive/files/check-existence.ts b/packages/backend/src/server/api/endpoints/drive/files/check-existence.ts
index 290cd4d2ce..cdcdde7e8a 100644
--- a/packages/backend/src/server/api/endpoints/drive/files/check-existence.ts
+++ b/packages/backend/src/server/api/endpoints/drive/files/check-existence.ts
@@ -34,12 +34,14 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
 		private driveFilesRepository: DriveFilesRepository,
 	) {
 		super(meta, paramDef, async (ps, me) => {
-			const file = await this.driveFilesRepository.findOneBy({
-				md5: ps.md5,
-				userId: me.id,
+			const exist = await this.driveFilesRepository.exist({
+				where: {
+					md5: ps.md5,
+					userId: me.id,
+				},
 			});
 
-			return file != null;
+			return exist;
 		});
 	}
 }
diff --git a/packages/backend/src/server/api/endpoints/flash/like.ts b/packages/backend/src/server/api/endpoints/flash/like.ts
index 23de2f3970..57245f9f41 100644
--- a/packages/backend/src/server/api/endpoints/flash/like.ts
+++ b/packages/backend/src/server/api/endpoints/flash/like.ts
@@ -66,12 +66,14 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
 			}
 
 			// if already liked
-			const exist = await this.flashLikesRepository.findOneBy({
-				flashId: flash.id,
-				userId: me.id,
+			const exist = await this.flashLikesRepository.exist({
+				where: {
+					flashId: flash.id,
+					userId: me.id,
+				},
 			});
 
-			if (exist != null) {
+			if (exist) {
 				throw new ApiError(meta.errors.alreadyLiked);
 			}
 
diff --git a/packages/backend/src/server/api/endpoints/following/create.ts b/packages/backend/src/server/api/endpoints/following/create.ts
index 4ad16de911..009fc96f64 100644
--- a/packages/backend/src/server/api/endpoints/following/create.ts
+++ b/packages/backend/src/server/api/endpoints/following/create.ts
@@ -99,12 +99,14 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
 			});
 
 			// Check if already following
-			const exist = await this.followingsRepository.findOneBy({
-				followerId: follower.id,
-				followeeId: followee.id,
+			const exist = await this.followingsRepository.exist({
+				where: {
+					followerId: follower.id,
+					followeeId: followee.id,
+				},
 			});
 
-			if (exist != null) {
+			if (exist) {
 				throw new ApiError(meta.errors.alreadyFollowing);
 			}
 
diff --git a/packages/backend/src/server/api/endpoints/following/delete.ts b/packages/backend/src/server/api/endpoints/following/delete.ts
index 4f12db1273..570c4eb81e 100644
--- a/packages/backend/src/server/api/endpoints/following/delete.ts
+++ b/packages/backend/src/server/api/endpoints/following/delete.ts
@@ -84,12 +84,14 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
 			});
 
 			// Check not following
-			const exist = await this.followingsRepository.findOneBy({
-				followerId: follower.id,
-				followeeId: followee.id,
+			const exist = await this.followingsRepository.exist({
+				where: {
+					followerId: follower.id,
+					followeeId: followee.id,
+				},
 			});
 
-			if (exist == null) {
+			if (!exist) {
 				throw new ApiError(meta.errors.notFollowing);
 			}
 
diff --git a/packages/backend/src/server/api/endpoints/gallery/posts/like.ts b/packages/backend/src/server/api/endpoints/gallery/posts/like.ts
index 6ac5fa8606..c0bb55f640 100644
--- a/packages/backend/src/server/api/endpoints/gallery/posts/like.ts
+++ b/packages/backend/src/server/api/endpoints/gallery/posts/like.ts
@@ -66,12 +66,14 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
 			}
 
 			// if already liked
-			const exist = await this.galleryLikesRepository.findOneBy({
-				postId: post.id,
-				userId: me.id,
+			const exist = await this.galleryLikesRepository.exist({
+				where: {
+					postId: post.id,
+					userId: me.id,
+				},
 			});
 
-			if (exist != null) {
+			if (exist) {
 				throw new ApiError(meta.errors.alreadyLiked);
 			}
 
diff --git a/packages/backend/src/server/api/endpoints/i/import-antennas.ts b/packages/backend/src/server/api/endpoints/i/import-antennas.ts
index 12ec5855d3..8582e98f76 100644
--- a/packages/backend/src/server/api/endpoints/i/import-antennas.ts
+++ b/packages/backend/src/server/api/endpoints/i/import-antennas.ts
@@ -66,8 +66,8 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
 		private downloadService: DownloadService,
 	) {
 		super(meta, paramDef, async (ps, me) => {
-			const users = await this.usersRepository.findOneBy({ id: me.id });
-			if (users === null) throw new ApiError(meta.errors.noSuchUser);
+			const userExist = await this.usersRepository.exist({ where: { id: me.id } });
+			if (!userExist) throw new ApiError(meta.errors.noSuchUser);
 			const file = await this.driveFilesRepository.findOneBy({ id: ps.fileId });
 			if (file === null) throw new ApiError(meta.errors.noSuchFile);
 			if (file.size === 0) throw new ApiError(meta.errors.emptyFile);
diff --git a/packages/backend/src/server/api/endpoints/i/read-announcement.ts b/packages/backend/src/server/api/endpoints/i/read-announcement.ts
index b8922b91e5..352fe54c5d 100644
--- a/packages/backend/src/server/api/endpoints/i/read-announcement.ts
+++ b/packages/backend/src/server/api/endpoints/i/read-announcement.ts
@@ -47,19 +47,21 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
 	) {
 		super(meta, paramDef, async (ps, me) => {
 			// Check if announcement exists
-			const announcement = await this.announcementsRepository.findOneBy({ id: ps.announcementId });
+			const announcementExist = await this.announcementsRepository.exist({ where: { id: ps.announcementId } });
 
-			if (announcement == null) {
+			if (!announcementExist) {
 				throw new ApiError(meta.errors.noSuchAnnouncement);
 			}
 
 			// Check if already read
-			const read = await this.announcementReadsRepository.findOneBy({
-				announcementId: ps.announcementId,
-				userId: me.id,
+			const alreadyRead = await this.announcementReadsRepository.exist({
+				where: {
+					announcementId: ps.announcementId,
+					userId: me.id,
+				},
 			});
 
-			if (read != null) {
+			if (alreadyRead) {
 				return;
 			}
 
diff --git a/packages/backend/src/server/api/endpoints/i/revoke-token.ts b/packages/backend/src/server/api/endpoints/i/revoke-token.ts
index 93daeb0cd7..415a60147b 100644
--- a/packages/backend/src/server/api/endpoints/i/revoke-token.ts
+++ b/packages/backend/src/server/api/endpoints/i/revoke-token.ts
@@ -28,9 +28,9 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
 		private globalEventService: GlobalEventService,
 	) {
 		super(meta, paramDef, async (ps, me) => {
-			const token = await this.accessTokensRepository.findOneBy({ id: ps.tokenId });
+			const tokenExist = await this.accessTokensRepository.exist({ where: { id: ps.tokenId } });
 
-			if (token) {
+			if (tokenExist) {
 				await this.accessTokensRepository.delete({
 					id: ps.tokenId,
 					userId: me.id,
diff --git a/packages/backend/src/server/api/endpoints/mute/create.ts b/packages/backend/src/server/api/endpoints/mute/create.ts
index ee358d5c6c..ef53f9ef41 100644
--- a/packages/backend/src/server/api/endpoints/mute/create.ts
+++ b/packages/backend/src/server/api/endpoints/mute/create.ts
@@ -79,12 +79,14 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
 			});
 
 			// Check if already muting
-			const exist = await this.mutingsRepository.findOneBy({
-				muterId: muter.id,
-				muteeId: mutee.id,
+			const exist = await this.mutingsRepository.exist({
+				where: {
+					muterId: muter.id,
+					muteeId: mutee.id,
+				},
 			});
 
-			if (exist != null) {
+			if (exist) {
 				throw new ApiError(meta.errors.alreadyMuting);
 			}
 
diff --git a/packages/backend/src/server/api/endpoints/notes/create.ts b/packages/backend/src/server/api/endpoints/notes/create.ts
index 96be5ed844..739316997a 100644
--- a/packages/backend/src/server/api/endpoints/notes/create.ts
+++ b/packages/backend/src/server/api/endpoints/notes/create.ts
@@ -217,11 +217,13 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
 
 				// Check blocking
 				if (renote.userId !== me.id) {
-					const block = await this.blockingsRepository.findOneBy({
-						blockerId: renote.userId,
-						blockeeId: me.id,
+					const blockExist = await this.blockingsRepository.exist({
+						where: {
+							blockerId: renote.userId,
+							blockeeId: me.id,
+						},
 					});
-					if (block) {
+					if (blockExist) {
 						throw new ApiError(meta.errors.youHaveBeenBlocked);
 					}
 				}
@@ -240,11 +242,13 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
 
 				// Check blocking
 				if (reply.userId !== me.id) {
-					const block = await this.blockingsRepository.findOneBy({
-						blockerId: reply.userId,
-						blockeeId: me.id,
+					const blockExist = await this.blockingsRepository.exist({
+						where: {
+							blockerId: reply.userId,
+							blockeeId: me.id,
+						},
 					});
-					if (block) {
+					if (blockExist) {
 						throw new ApiError(meta.errors.youHaveBeenBlocked);
 					}
 				}
diff --git a/packages/backend/src/server/api/endpoints/notes/favorites/create.ts b/packages/backend/src/server/api/endpoints/notes/favorites/create.ts
index 611ea19560..9299d66039 100644
--- a/packages/backend/src/server/api/endpoints/notes/favorites/create.ts
+++ b/packages/backend/src/server/api/endpoints/notes/favorites/create.ts
@@ -63,12 +63,14 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
 			});
 
 			// if already favorited
-			const exist = await this.noteFavoritesRepository.findOneBy({
-				noteId: note.id,
-				userId: me.id,
+			const exist = await this.noteFavoritesRepository.exist({
+				where: {
+					noteId: note.id,
+					userId: me.id,
+				},
 			});
 
-			if (exist != null) {
+			if (exist) {
 				throw new ApiError(meta.errors.alreadyFavorited);
 			}
 
diff --git a/packages/backend/src/server/api/endpoints/pages/like.ts b/packages/backend/src/server/api/endpoints/pages/like.ts
index 543c126d9c..bc66488103 100644
--- a/packages/backend/src/server/api/endpoints/pages/like.ts
+++ b/packages/backend/src/server/api/endpoints/pages/like.ts
@@ -66,12 +66,14 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
 			}
 
 			// if already liked
-			const exist = await this.pageLikesRepository.findOneBy({
-				pageId: page.id,
-				userId: me.id,
+			const exist = await this.pageLikesRepository.exist({
+				where: {
+					pageId: page.id,
+					userId: me.id,
+				},
 			});
 
-			if (exist != null) {
+			if (exist) {
 				throw new ApiError(meta.errors.alreadyLiked);
 			}
 
diff --git a/packages/backend/src/server/api/endpoints/promo/read.ts b/packages/backend/src/server/api/endpoints/promo/read.ts
index 90febdbce7..9baa930f5f 100644
--- a/packages/backend/src/server/api/endpoints/promo/read.ts
+++ b/packages/backend/src/server/api/endpoints/promo/read.ts
@@ -44,12 +44,14 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
 				throw err;
 			});
 
-			const exist = await this.promoReadsRepository.findOneBy({
-				noteId: note.id,
-				userId: me.id,
+			const exist = await this.promoReadsRepository.exist({
+				where: {
+					noteId: note.id,
+					userId: me.id,
+				},
 			});
 
-			if (exist != null) {
+			if (exist) {
 				return;
 			}
 
diff --git a/packages/backend/src/server/api/endpoints/users/followers.ts b/packages/backend/src/server/api/endpoints/users/followers.ts
index c6f71474bc..18d66500ab 100644
--- a/packages/backend/src/server/api/endpoints/users/followers.ts
+++ b/packages/backend/src/server/api/endpoints/users/followers.ts
@@ -97,11 +97,13 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
 				if (me == null) {
 					throw new ApiError(meta.errors.forbidden);
 				} else if (me.id !== user.id) {
-					const following = await this.followingsRepository.findOneBy({
-						followeeId: user.id,
-						followerId: me.id,
+					const isFollowing = await this.followingsRepository.exist({
+						where: {
+							followeeId: user.id,
+							followerId: me.id,
+						},
 					});
-					if (following == null) {
+					if (!isFollowing) {
 						throw new ApiError(meta.errors.forbidden);
 					}
 				}
diff --git a/packages/backend/src/server/api/endpoints/users/following.ts b/packages/backend/src/server/api/endpoints/users/following.ts
index b072c96626..6ea7b923d6 100644
--- a/packages/backend/src/server/api/endpoints/users/following.ts
+++ b/packages/backend/src/server/api/endpoints/users/following.ts
@@ -97,11 +97,13 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
 				if (me == null) {
 					throw new ApiError(meta.errors.forbidden);
 				} else if (me.id !== user.id) {
-					const following = await this.followingsRepository.findOneBy({
-						followeeId: user.id,
-						followerId: me.id,
+					const isFollowing = await this.followingsRepository.exist({
+						where: {
+							followeeId: user.id,
+							followerId: me.id,
+						},
 					});
-					if (following == null) {
+					if (!isFollowing) {
 						throw new ApiError(meta.errors.forbidden);
 					}
 				}
diff --git a/packages/backend/src/server/api/endpoints/users/lists/create-from-public.ts b/packages/backend/src/server/api/endpoints/users/lists/create-from-public.ts
index cccffcdad4..beb0ba85ff 100644
--- a/packages/backend/src/server/api/endpoints/users/lists/create-from-public.ts
+++ b/packages/backend/src/server/api/endpoints/users/lists/create-from-public.ts
@@ -84,11 +84,13 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
 		private roleService: RoleService,
 	) {
 		super(meta, paramDef, async (ps, me) => {
-			const list = await this.userListsRepository.findOneBy({
-				id: ps.listId,
-				isPublic: true,
+			const listExist = await this.userListsRepository.exist({
+				where: {
+					id: ps.listId,
+					isPublic: true,
+				},
 			});
-			if (list === null) throw new ApiError(meta.errors.noSuchList);
+			if (!listExist) throw new ApiError(meta.errors.noSuchList);
 			const currentCount = await this.userListsRepository.countBy({
 				userId: me.id,
 			});
@@ -114,18 +116,22 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
 				});
 
 				if (currentUser.id !== me.id) {
-					const block = await this.blockingsRepository.findOneBy({
-						blockerId: currentUser.id,
-						blockeeId: me.id,
+					const blockExist = await this.blockingsRepository.exist({
+						where: {
+							blockerId: currentUser.id,
+							blockeeId: me.id,
+						},
 					});
-					if (block) {
+					if (blockExist) {
 						throw new ApiError(meta.errors.youHaveBeenBlocked);
 					}
 				}
 
-				const exist = await this.userListJoiningsRepository.findOneBy({
-					userListId: userList.id,
-					userId: currentUser.id,
+				const exist = await this.userListJoiningsRepository.exist({
+					where: {
+						userListId: userList.id,
+						userId: currentUser.id,
+					},
 				});
 
 				if (exist) {
diff --git a/packages/backend/src/server/api/endpoints/users/lists/favorite.ts b/packages/backend/src/server/api/endpoints/users/lists/favorite.ts
index ea1a022bec..2c09a47fef 100644
--- a/packages/backend/src/server/api/endpoints/users/lists/favorite.ts
+++ b/packages/backend/src/server/api/endpoints/users/lists/favorite.ts
@@ -41,21 +41,25 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
 		private idService: IdService,
 	) {
 		super(meta, paramDef, async (ps, me) => {
-			const userList = await this.userListsRepository.findOneBy({
-				id: ps.listId,
-				isPublic: true,
+			const userListExist = await this.userListsRepository.exist({
+				where: {
+					id: ps.listId,
+					isPublic: true,
+				},
 			});
 
-			if (userList === null) {
+			if (!userListExist) {
 				throw new ApiError(meta.errors.noSuchList);
 			}
 
-			const exist = await this.userListFavoritesRepository.findOneBy({
-				userId: me.id,
-				userListId: ps.listId,
+			const exist = await this.userListFavoritesRepository.exist({
+				where: {
+					userId: me.id,
+					userListId: ps.listId,
+				},
 			});
 
-			if (exist !== null) {
+			if (exist) {
 				throw new ApiError(meta.errors.alreadyFavorited);
 			}
 
diff --git a/packages/backend/src/server/api/endpoints/users/lists/push.ts b/packages/backend/src/server/api/endpoints/users/lists/push.ts
index 925037e484..6e1f6b2c62 100644
--- a/packages/backend/src/server/api/endpoints/users/lists/push.ts
+++ b/packages/backend/src/server/api/endpoints/users/lists/push.ts
@@ -100,18 +100,22 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
 
 			// Check blocking
 			if (user.id !== me.id) {
-				const block = await this.blockingsRepository.findOneBy({
-					blockerId: user.id,
-					blockeeId: me.id,
+				const blockExist = await this.blockingsRepository.exist({
+					where: {
+						blockerId: user.id,
+						blockeeId: me.id,
+					},
 				});
-				if (block) {
+				if (blockExist) {
 					throw new ApiError(meta.errors.youHaveBeenBlocked);
 				}
 			}
 
-			const exist = await this.userListJoiningsRepository.findOneBy({
-				userListId: userList.id,
-				userId: user.id,
+			const exist = await this.userListJoiningsRepository.exist({
+				where: {
+					userListId: userList.id,
+					userId: user.id,
+				},
 			});
 
 			if (exist) {
diff --git a/packages/backend/src/server/api/endpoints/users/lists/show.ts b/packages/backend/src/server/api/endpoints/users/lists/show.ts
index 8077841c8c..3fd418d04e 100644
--- a/packages/backend/src/server/api/endpoints/users/lists/show.ts
+++ b/packages/backend/src/server/api/endpoints/users/lists/show.ts
@@ -69,10 +69,12 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
 					userListId: ps.listId,
 				});
 				if (me !== null) {
-					additionalProperties.isLiked = (await this.userListFavoritesRepository.findOneBy({
-						userId: me.id,
-						userListId: ps.listId,
-					}) !== null);
+					additionalProperties.isLiked = await this.userListFavoritesRepository.exist({
+						where: {
+							userId: me.id,
+							userListId: ps.listId,
+						},
+					});
 				} else {
 					additionalProperties.isLiked = false;
 				}
diff --git a/packages/backend/src/server/api/endpoints/users/lists/unfavorite.ts b/packages/backend/src/server/api/endpoints/users/lists/unfavorite.ts
index be8e317816..a7c3b58947 100644
--- a/packages/backend/src/server/api/endpoints/users/lists/unfavorite.ts
+++ b/packages/backend/src/server/api/endpoints/users/lists/unfavorite.ts
@@ -39,12 +39,14 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
 		private userListFavoritesRepository: UserListFavoritesRepository,
 	) {
 		super(meta, paramDef, async (ps, me) => {
-			const userList = await this.userListsRepository.findOneBy({
-				id: ps.listId,
-				isPublic: true,
+			const userListExist = await this.userListsRepository.exist({
+				where: {
+					id: ps.listId,
+					isPublic: true,
+				},
 			});
 
-			if (userList === null) {
+			if (!userListExist) {
 				throw new ApiError(meta.errors.noSuchList);
 			}
 
diff --git a/packages/backend/src/server/api/stream/channels/user-list.ts b/packages/backend/src/server/api/stream/channels/user-list.ts
index d97d2b8ba9..ea4cff0bc0 100644
--- a/packages/backend/src/server/api/stream/channels/user-list.ts
+++ b/packages/backend/src/server/api/stream/channels/user-list.ts
@@ -34,11 +34,13 @@ class UserListChannel extends Channel {
 		this.listId = params.listId as string;
 
 		// Check existence and owner
-		const list = await this.userListsRepository.findOneBy({
-			id: this.listId,
-			userId: this.user!.id,
+		const listExist = await this.userListsRepository.exist({
+			where: {
+				id: this.listId,
+				userId: this.user!.id,
+			},
 		});
-		if (!list) return;
+		if (!listExist) return;
 
 		// Subscribe stream
 		this.subscriber.on(`userListStream:${this.listId}`, this.send);
diff --git a/packages/backend/test/utils.ts b/packages/backend/test/utils.ts
index 48947072e3..31ea3e5ab8 100644
--- a/packages/backend/test/utils.ts
+++ b/packages/backend/test/utils.ts
@@ -447,12 +447,12 @@ export async function testPaginationConsistency<Entity extends { id: string, cre
 	for (const limit of [1, 5, 10, 100, undefined]) {
 		// 1. sinceId/DateとuntilId/Dateで両端を指定して取得した結果が期待通りになっていること
 		if (ordering === 'desc') {
-			const end = expected[expected.length - 1];
+			const end = expected.at(-1)!;
 			let last = await fetchEntities(rangeToParam({ limit, since: end }));
 			const actual: Entity[] = [];
 			while (last.length !== 0) {
 				actual.push(...last);
-				last = await fetchEntities(rangeToParam({ limit, until: last[last.length - 1], since: end }));
+				last = await fetchEntities(rangeToParam({ limit, until: last.at(-1), since: end }));
 			}
 			actual.push(end);
 			assert.deepStrictEqual(
@@ -467,7 +467,7 @@ export async function testPaginationConsistency<Entity extends { id: string, cre
 			const actual: Entity[] = [];
 			while (last.length !== 0) {
 				actual.push(...last);
-				last = await fetchEntities(rangeToParam({ limit, since: last[last.length - 1] }));
+				last = await fetchEntities(rangeToParam({ limit, since: last.at(-1) }));
 			}
 			assert.deepStrictEqual(
 				actual.map(({ id, createdAt }) => id + ':' + createdAt),
@@ -480,7 +480,7 @@ export async function testPaginationConsistency<Entity extends { id: string, cre
 			const actual: Entity[] = [];
 			while (last.length !== 0) {
 				actual.push(...last);
-				last = await fetchEntities(rangeToParam({ limit, until: last[last.length - 1] }));
+				last = await fetchEntities(rangeToParam({ limit, until: last.at(-1) }));
 			}
 			assert.deepStrictEqual(
 				actual.map(({ id, createdAt }) => id + ':' + createdAt),
diff --git a/packages/frontend/.storybook/preload-locale.ts b/packages/frontend/.storybook/preload-locale.ts
index 636931967f..2b7362b88d 100644
--- a/packages/frontend/.storybook/preload-locale.ts
+++ b/packages/frontend/.storybook/preload-locale.ts
@@ -1,5 +1,5 @@
 import { writeFile } from 'node:fs/promises';
-import * as locales from '../../../locales/index.js';
+import locales from '../../../locales/index.js';
 
 await writeFile(
 	new URL('locale.ts', import.meta.url),
diff --git a/packages/frontend/src/cache.ts b/packages/frontend/src/cache.ts
index c95da64bba..cb315c8ff7 100644
--- a/packages/frontend/src/cache.ts
+++ b/packages/frontend/src/cache.ts
@@ -4,3 +4,4 @@ import { Cache } from '@/scripts/cache';
 export const clipsCache = new Cache<misskey.entities.Clip[]>(Infinity);
 export const rolesCache = new Cache(Infinity);
 export const userListsCache = new Cache<misskey.entities.UserList[]>(Infinity);
+export const antennasCache = new Cache<misskey.entities.Antenna[]>(Infinity);
diff --git a/packages/frontend/src/components/MkAsUi.vue b/packages/frontend/src/components/MkAsUi.vue
index 8bfcfa6aa6..7aa8f94c3b 100644
--- a/packages/frontend/src/components/MkAsUi.vue
+++ b/packages/frontend/src/components/MkAsUi.vue
@@ -39,7 +39,7 @@
 			<MkAsUi v-if="!g(child).hidden" :component="g(child)" :components="props.components" :size="size"/>
 		</template>
 	</MkFolder>
-	<div v-else-if="c.type === 'container'" :class="[$style.container, { [$style.fontSerif]: c.font === 'serif', [$style.fontMonospace]: c.font === 'monospace', [$style.containerCenter]: c.align === 'center' }]" :style="{ backgroundColor: c.bgColor ?? null, color: c.fgColor ?? null, borderWidth: c.borderWidth ? `${c.borderWidth}px` : 0, borderColor: c.borderColor ?? 'var(--divider)', padding: c.padding ? `${c.padding}px` : 0, borderRadius: c.rounded ? '8px' : 0 }">
+	<div v-else-if="c.type === 'container'" :class="[$style.container, { [$style.fontSerif]: c.font === 'serif', [$style.fontMonospace]: c.font === 'monospace' }]" :style="{ textAlign: c.align ?? null, backgroundColor: c.bgColor ?? null, color: c.fgColor ?? null, borderWidth: c.borderWidth ? `${c.borderWidth}px` : 0, borderColor: c.borderColor ?? 'var(--divider)', padding: c.padding ? `${c.padding}px` : 0, borderRadius: c.rounded ? '8px' : 0 }">
 		<template v-for="child in c.children" :key="child">
 			<MkAsUi v-if="!g(child).hidden" :component="g(child)" :components="props.components" :size="size" :align="c.align"/>
 		</template>
@@ -102,10 +102,6 @@ function openPostForm() {
 	gap: 12px;
 }
 
-.containerCenter {
-	text-align: center;
-}
-
 .fontSerif {
 	font-family: serif;
 }
diff --git a/packages/frontend/src/components/MkAvatars.vue b/packages/frontend/src/components/MkAvatars.vue
index 630620fc08..437dce0a14 100644
--- a/packages/frontend/src/components/MkAvatars.vue
+++ b/packages/frontend/src/components/MkAvatars.vue
@@ -1,24 +1,29 @@
 <template>
 <div>
-	<div v-for="user in users" :key="user.id" style="display:inline-block;width:32px;height:32px;margin-right:8px;">
+	<div v-for="user in users.slice(0, limit)" :key="user.id" style="display:inline-block;width:32px;height:32px;margin-right:8px;">
 		<MkAvatar :user="user" style="width:32px; height:32px;" indicator link preview/>
 	</div>
+	<div v-if="users.length > limit" style="display: inline-block;">...</div>
 </div>
 </template>
 
 <script lang="ts" setup>
 import { onMounted, ref } from 'vue';
 import * as os from '@/os';
+import { UserLite } from 'misskey-js/built/entities';
 
-const props = defineProps<{
+const props = withDefaults(defineProps<{
 	userIds: string[];
-}>();
+	limit?: number;
+}>(), {
+	limit: Infinity,
+});
 
-const users = ref([]);
+const users = ref<UserLite[]>([]);
 
 onMounted(async () => {
 	users.value = await os.api('users/show', {
 		userIds: props.userIds,
-	});
+	}) as unknown as UserLite[];
 });
 </script>
diff --git a/packages/frontend/src/components/MkDrive.file.vue b/packages/frontend/src/components/MkDrive.file.vue
index bb4361ef60..599819b3fe 100644
--- a/packages/frontend/src/components/MkDrive.file.vue
+++ b/packages/frontend/src/components/MkDrive.file.vue
@@ -25,8 +25,8 @@
 		<MkDriveFileThumbnail :class="$style.thumbnail" :file="file" fit="contain"/>
 
 		<p :class="$style.name">
-			<span>{{ file.name.lastIndexOf('.') != -1 ? file.name.substr(0, file.name.lastIndexOf('.')) : file.name }}</span>
-			<span v-if="file.name.lastIndexOf('.') != -1" style="opacity: 0.5;">{{ file.name.substr(file.name.lastIndexOf('.')) }}</span>
+			<span>{{ file.name.lastIndexOf('.') != -1 ? file.name.substring(0, file.name.lastIndexOf('.')) : file.name }}</span>
+			<span v-if="file.name.lastIndexOf('.') != -1" style="opacity: 0.5;">{{ file.name.substring(file.name.lastIndexOf('.')) }}</span>
 		</p>
 	</div>
 </div>
diff --git a/packages/frontend/src/components/MkDrive.vue b/packages/frontend/src/components/MkDrive.vue
index 201a6ccdc8..aff227da40 100644
--- a/packages/frontend/src/components/MkDrive.vue
+++ b/packages/frontend/src/components/MkDrive.vue
@@ -568,7 +568,7 @@ function fetchMoreFolders() {
 	os.api('drive/folders', {
 		folderId: folder.value ? folder.value.id : null,
 		type: props.type,
-		untilId: folders.value[folders.value.length - 1].id,
+		untilId: folders.value.at(-1)?.id,
 		limit: max + 1,
 	}).then(folders => {
 		if (folders.length === max + 1) {
@@ -591,7 +591,7 @@ function fetchMoreFiles() {
 	os.api('drive/files', {
 		folderId: folder.value ? folder.value.id : null,
 		type: props.type,
-		untilId: files.value[files.value.length - 1].id,
+		untilId: files.value.at(-1)?.id,
 		limit: max + 1,
 	}).then(files => {
 		if (files.length === max + 1) {
diff --git a/packages/frontend/src/components/MkLink.vue b/packages/frontend/src/components/MkLink.vue
index 2e4f93e848..8e61c70484 100644
--- a/packages/frontend/src/components/MkLink.vue
+++ b/packages/frontend/src/components/MkLink.vue
@@ -1,6 +1,6 @@
 <template>
 <component
-	:is="self ? 'MkA' : 'a'" ref="el" style="word-break: break-all;" class="_link" :[attr]="self ? url.substr(local.length) : url" :rel="rel" :target="target"
+	:is="self ? 'MkA' : 'a'" ref="el" style="word-break: break-all;" class="_link" :[attr]="self ? url.substring(local.length) : url" :rel="rel" :target="target"
 	:title="url"
 >
 	<slot></slot>
diff --git a/packages/frontend/src/components/MkMediaList.vue b/packages/frontend/src/components/MkMediaList.vue
index 34f59c5573..be0aed6524 100644
--- a/packages/frontend/src/components/MkMediaList.vue
+++ b/packages/frontend/src/components/MkMediaList.vue
@@ -113,7 +113,7 @@ onMounted(() => {
 			right: 0,
 		},
 		imageClickAction: 'close',
-		tapAction: 'toggle-controls',
+		tapAction: 'close',
 		bgOpacity: 1,
 		showAnimationDuration: 100,
 		hideAnimationDuration: 100,
diff --git a/packages/frontend/src/components/MkMiniChart.vue b/packages/frontend/src/components/MkMiniChart.vue
index 89050e10f0..e884455709 100644
--- a/packages/frontend/src/components/MkMiniChart.vue
+++ b/packages/frontend/src/components/MkMiniChart.vue
@@ -59,8 +59,8 @@ function draw(): void {
 
 	polygonPoints = `0,${ viewBoxY } ${ polylinePoints } ${ viewBoxX },${ viewBoxY }`;
 
-	headX = _polylinePoints[_polylinePoints.length - 1][0];
-	headY = _polylinePoints[_polylinePoints.length - 1][1];
+	headX = _polylinePoints.at(-1)![0];
+	headY = _polylinePoints.at(-1)![1];
 }
 
 watch(() => props.src, draw, { immediate: true });
diff --git a/packages/frontend/src/components/MkPageWindow.vue b/packages/frontend/src/components/MkPageWindow.vue
index 6318a9fd70..6e35ad4241 100644
--- a/packages/frontend/src/components/MkPageWindow.vue
+++ b/packages/frontend/src/components/MkPageWindow.vue
@@ -120,7 +120,7 @@ const contextmenu = $computed(() => ([{
 
 function back() {
 	history.pop();
-	router.replace(history[history.length - 1].path, history[history.length - 1].key);
+	router.replace(history.at(-1)!.path, history.at(-1)!.key);
 }
 
 function reload() {
diff --git a/packages/frontend/src/components/MkPagination.vue b/packages/frontend/src/components/MkPagination.vue
index 661b04c365..b9a75f6002 100644
--- a/packages/frontend/src/components/MkPagination.vue
+++ b/packages/frontend/src/components/MkPagination.vue
@@ -233,7 +233,7 @@ const fetchMore = async (): Promise<void> => {
 		...(props.pagination.offsetMode ? {
 			offset: offset.value,
 		} : {
-			untilId: Array.from(items.value.keys())[items.value.size - 1],
+			untilId: Array.from(items.value.keys()).at(-1),
 		}),
 	}).then(res => {
 		for (let i = 0; i < res.length; i++) {
@@ -297,7 +297,7 @@ const fetchMoreAhead = async (): Promise<void> => {
 		...(props.pagination.offsetMode ? {
 			offset: offset.value,
 		} : {
-			sinceId: Array.from(items.value.keys())[items.value.size - 1],
+			sinceId: Array.from(items.value.keys()).at(-1),
 		}),
 	}).then(res => {
 		if (res.length === 0) {
diff --git a/packages/frontend/src/components/MkPostForm.vue b/packages/frontend/src/components/MkPostForm.vue
index b269feb07f..462c3be6a8 100644
--- a/packages/frontend/src/components/MkPostForm.vue
+++ b/packages/frontend/src/components/MkPostForm.vue
@@ -564,7 +564,7 @@ async function onPaste(ev: ClipboardEvent) {
 				return;
 			}
 
-			quoteId = paste.substr(url.length).match(/^\/notes\/(.+?)\/?$/)[1];
+			quoteId = paste.substring(url.length).match(/^\/notes\/(.+?)\/?$/)[1];
 		});
 	}
 }
diff --git a/packages/frontend/src/components/MkReactionsViewer.reaction.vue b/packages/frontend/src/components/MkReactionsViewer.reaction.vue
index aabebb3abf..69d495d86f 100644
--- a/packages/frontend/src/components/MkReactionsViewer.reaction.vue
+++ b/packages/frontend/src/components/MkReactionsViewer.reaction.vue
@@ -6,7 +6,7 @@
 	:class="[$style.root, { [$style.reacted]: note.myReaction == reaction, [$style.canToggle]: canToggle, [$style.large]: defaultStore.state.largeNoteReactions }]"
 	@click="toggleReaction()"
 >
-	<MkReactionIcon :class="$style.icon" :reaction="reaction" :emojiUrl="note.reactionEmojis[reaction.substr(1, reaction.length - 2)]"/>
+	<MkReactionIcon :class="$style.icon" :reaction="reaction" :emojiUrl="note.reactionEmojis[reaction.substring(1, reaction.length - 1)]"/>
 	<span :class="$style.count">{{ count }}</span>
 </button>
 </template>
diff --git a/packages/frontend/src/components/MkUrlPreview.vue b/packages/frontend/src/components/MkUrlPreview.vue
index fcad5b8064..5c37f70bd9 100644
--- a/packages/frontend/src/components/MkUrlPreview.vue
+++ b/packages/frontend/src/components/MkUrlPreview.vue
@@ -32,7 +32,7 @@
 	</div>
 </template>
 <div v-else>
-	<component :is="self ? 'MkA' : 'a'" :class="[$style.link, { [$style.compact]: compact }]" :[attr]="self ? url.substr(local.length) : url" rel="nofollow noopener" :target="target" :title="url">
+	<component :is="self ? 'MkA' : 'a'" :class="[$style.link, { [$style.compact]: compact }]" :[attr]="self ? url.substring(local.length) : url" rel="nofollow noopener" :target="target" :title="url">
 		<div v-if="thumbnail" :class="$style.thumbnail" :style="`background-image: url('${thumbnail}')`">
 		</div>
 		<article :class="$style.body">
diff --git a/packages/frontend/src/components/MkUserPopup.vue b/packages/frontend/src/components/MkUserPopup.vue
index 937e0f0798..3b6e348e0b 100644
--- a/packages/frontend/src/components/MkUserPopup.vue
+++ b/packages/frontend/src/components/MkUserPopup.vue
@@ -88,7 +88,7 @@ onMounted(() => {
 		user = props.q;
 	} else {
 		const query = props.q.startsWith('@') ?
-			Acct.parse(props.q.substr(1)) :
+			Acct.parse(props.q.substring(1)) :
 			{ userId: props.q };
 
 		os.api('users/show', query).then(res => {
diff --git a/packages/frontend/src/components/global/MkA.stories.impl.ts b/packages/frontend/src/components/global/MkA.stories.impl.ts
index 639ed19af2..6e3ff573cb 100644
--- a/packages/frontend/src/components/global/MkA.stories.impl.ts
+++ b/packages/frontend/src/components/global/MkA.stories.impl.ts
@@ -29,11 +29,11 @@ export const Default = {
 		const canvas = within(canvasElement);
 		const a = canvas.getByRole<HTMLAnchorElement>('link');
 		await expect(a.href).toMatch(/^https?:\/\/.*#test$/);
-		await userEvent.click(a, { button: 2 });
+		await userEvent.pointer({ keys: '[MouseRight]', target: a });
 		await tick();
 		const menu = canvas.getByRole('menu');
 		await expect(menu).toBeInTheDocument();
-		await userEvent.click(a, { button: 0 });
+		await userEvent.click(a);
 		a.blur();
 		await tick();
 		await expect(menu).not.toBeInTheDocument();
diff --git a/packages/frontend/src/components/global/MkAd.stories.impl.ts b/packages/frontend/src/components/global/MkAd.stories.impl.ts
index 7d8a42a03c..58b6cc14c4 100644
--- a/packages/frontend/src/components/global/MkAd.stories.impl.ts
+++ b/packages/frontend/src/components/global/MkAd.stories.impl.ts
@@ -1,9 +1,9 @@
 /* eslint-disable @typescript-eslint/explicit-function-return-type */
 import { expect } from '@storybook/jest';
-import { userEvent, within } from '@storybook/testing-library';
+import { userEvent, waitFor, within } from '@storybook/testing-library';
 import { StoryObj } from '@storybook/vue3';
-import { i18n } from '@/i18n';
 import MkAd from './MkAd.vue';
+import { i18n } from '@/i18n';
 const common = {
 	render(args) {
 		return {
@@ -36,6 +36,7 @@ const common = {
 		const i = buttons[0];
 		await expect(i).toBeInTheDocument();
 		await userEvent.click(i);
+		await waitFor(() => expect(canvasElement).toHaveTextContent(i18n.ts._ad.back));
 		await expect(a).not.toBeInTheDocument();
 		await expect(i).not.toBeInTheDocument();
 		buttons = canvas.getAllByRole<HTMLButtonElement>('button');
@@ -49,6 +50,7 @@ const common = {
 		await expect(back).toBeInTheDocument();
 		await expect(back).toHaveTextContent(i18n.ts._ad.back);
 		await userEvent.click(back);
+		await waitFor(() => expect(canvas.queryByRole('img')).toBeTruthy());
 		if (reduce) {
 			await expect(reduce).not.toBeInTheDocument();
 		}
diff --git a/packages/frontend/src/components/global/MkCustomEmoji.vue b/packages/frontend/src/components/global/MkCustomEmoji.vue
index e8a7f17cc6..e7af472682 100644
--- a/packages/frontend/src/components/global/MkCustomEmoji.vue
+++ b/packages/frontend/src/components/global/MkCustomEmoji.vue
@@ -18,7 +18,7 @@ const props = defineProps<{
 	useOriginalSize?: boolean;
 }>();
 
-const customEmojiName = computed(() => (props.name[0] === ':' ? props.name.substr(1, props.name.length - 2) : props.name).replace('@.', ''));
+const customEmojiName = computed(() => (props.name[0] === ':' ? props.name.substring(1, props.name.length - 1) : props.name).replace('@.', ''));
 const isLocal = computed(() => !props.host && (customEmojiName.value.endsWith('@.') || !customEmojiName.value.includes('@')));
 
 const rawUrl = computed(() => {
diff --git a/packages/frontend/src/components/global/i18n.ts b/packages/frontend/src/components/global/i18n.ts
index 2708b759aa..6706d08f2f 100644
--- a/packages/frontend/src/components/global/i18n.ts
+++ b/packages/frontend/src/components/global/i18n.ts
@@ -11,13 +11,13 @@ export default function(props: { src: string; tag?: string; textTag?: string; },
 			parsed.push(str);
 			break;
 		} else {
-			if (nextBracketOpen > 0) parsed.push(str.substr(0, nextBracketOpen));
+			if (nextBracketOpen > 0) parsed.push(str.substring(0, nextBracketOpen));
 			parsed.push({
 				arg: str.substring(nextBracketOpen + 1, nextBracketClose),
 			});
 		}
 
-		str = str.substr(nextBracketClose + 1);
+		str = str.substring(nextBracketClose + 1);
 	}
 
 	return h(props.tag ?? 'span', parsed.map(x => typeof x === 'string' ? (props.textTag ? h(props.textTag, x) : x) : slots[x.arg]()));
diff --git a/packages/frontend/src/pages/about-misskey.vue b/packages/frontend/src/pages/about-misskey.vue
index b67cf26473..196a1b76e7 100644
--- a/packages/frontend/src/pages/about-misskey.vue
+++ b/packages/frontend/src/pages/about-misskey.vue
@@ -88,10 +88,13 @@
 					<template #label>Special thanks</template>
 					<div class="_gaps" style="text-align: center;">
 						<div>
-							<a style="display: inline-block;" class="masknetwork" title="Mask Network" href="https://mask.io/" target="_blank"><img width="200" src="https://misskey-hub.net/sponsors/masknetwork.png" alt="Mask Network"></a>
+							<a style="display: inline-block;" class="masknetwork" title="Mask Network" href="https://mask.io/" target="_blank"><img width="180" src="https://misskey-hub.net/sponsors/masknetwork.png" alt="Mask Network"></a>
 						</div>
 						<div>
-							<a style="display: inline-block;" class="dcadvirth" title="DC Advirth" href="https://www.dotchain.ltd/advirth" target="_blank"><img width="200" src="https://misskey-hub.net/sponsors/dcadvirth.png" alt="DC Advirth"></a>
+							<a style="display: inline-block;" class="skeb" title="Skeb" href="https://skeb.jp/" target="_blank"><img width="180" src="https://misskey-hub.net/sponsors/skeb.svg" alt="Skeb"></a>
+						</div>
+						<div>
+							<a style="display: inline-block;" class="dcadvirth" title="DC Advirth" href="https://www.dotchain.ltd/advirth" target="_blank"><img width="100" src="https://misskey-hub.net/sponsors/dcadvirth.png" alt="DC Advirth"></a>
 						</div>
 					</div>
 				</FormSection>
@@ -161,6 +164,9 @@ const patronsWithIcon = [{
 }, {
 	name: '清遊あみ',
 	icon: 'https://misskey-hub.net/patrons/de25195b88e940a388388bea2e7637d8.jpg',
+}, {
+	name: 'Nagi8410',
+	icon: 'https://misskey-hub.net/patrons/31b102ab4fc540ed806b0461575d38be.jpg',
 }];
 
 const patrons = [
@@ -256,6 +262,7 @@ const patrons = [
 	'binvinyl',
 	'渡志郎',
 	'ぷーざ',
+	'越貝鯛丸',
 ];
 
 let thereIsTreasure = $ref($i && !claimedAchievements.includes('foundTreasure'));
diff --git a/packages/frontend/src/pages/admin/overview.queue.vue b/packages/frontend/src/pages/admin/overview.queue.vue
index b08757aeb8..7d8d468512 100644
--- a/packages/frontend/src/pages/admin/overview.queue.vue
+++ b/packages/frontend/src/pages/admin/overview.queue.vue
@@ -85,7 +85,7 @@ onMounted(() => {
 	connection.on('stats', onStats);
 	connection.on('statsLog', onStatsLog);
 	connection.send('requestLog', {
-		id: Math.random().toString().substr(2, 8),
+		id: Math.random().toString().substring(2, 10),
 		length: 100,
 	});
 });
diff --git a/packages/frontend/src/pages/admin/overview.vue b/packages/frontend/src/pages/admin/overview.vue
index 838c197f05..41a6d4f5b7 100644
--- a/packages/frontend/src/pages/admin/overview.vue
+++ b/packages/frontend/src/pages/admin/overview.vue
@@ -156,7 +156,7 @@ onMounted(async () => {
 
 	nextTick(() => {
 		queueStatsConnection.send('requestLog', {
-			id: Math.random().toString().substr(2, 8),
+			id: Math.random().toString().substring(2, 10),
 			length: 100,
 		});
 	});
diff --git a/packages/frontend/src/pages/admin/queue.chart.vue b/packages/frontend/src/pages/admin/queue.chart.vue
index 8e6856fddd..83ca9639e7 100644
--- a/packages/frontend/src/pages/admin/queue.chart.vue
+++ b/packages/frontend/src/pages/admin/queue.chart.vue
@@ -106,7 +106,7 @@ onMounted(() => {
 	connection.on('stats', onStats);
 	connection.on('statsLog', onStatsLog);
 	connection.send('requestLog', {
-		id: Math.random().toString().substr(2, 8),
+		id: Math.random().toString().substring(2, 10),
 		length: 200,
 	});
 });
diff --git a/packages/frontend/src/pages/channel.vue b/packages/frontend/src/pages/channel.vue
index bcc0fc6860..2a056f21d4 100644
--- a/packages/frontend/src/pages/channel.vue
+++ b/packages/frontend/src/pages/channel.vue
@@ -87,7 +87,7 @@ const props = defineProps<{
 	channelId: string;
 }>();
 
-let tab = $ref('timeline');
+let tab = $ref('overview');
 let channel = $ref(null);
 let favorited = $ref(false);
 let searchQuery = $ref('');
@@ -107,6 +107,9 @@ watch(() => props.channelId, async () => {
 		channelId: props.channelId,
 	});
 	favorited = channel.isFavorited;
+	if (favorited || channel.isFollowing) {
+		tab = 'timeline';
+	}
 }, { immediate: true });
 
 function edit() {
diff --git a/packages/frontend/src/pages/custom-emojis-manager.vue b/packages/frontend/src/pages/custom-emojis-manager.vue
index dde4d67f18..359bbeadc3 100644
--- a/packages/frontend/src/pages/custom-emojis-manager.vue
+++ b/packages/frontend/src/pages/custom-emojis-manager.vue
@@ -18,7 +18,7 @@
 						<MkButton inline @click="setTagBulk">Set tag</MkButton>
 						<MkButton inline @click="addTagBulk">Add tag</MkButton>
 						<MkButton inline @click="removeTagBulk">Remove tag</MkButton>
-						<MkButton inline @click="setLisenceBulk">Set Lisence</MkButton>
+						<MkButton inline @click="setLicenseBulk">Set License</MkButton>
 						<MkButton inline danger @click="delBulk">Delete</MkButton>
 					</div>
 					<MkPagination ref="emojisPaginationComponent" :pagination="pagination">
@@ -221,7 +221,7 @@ const setCategoryBulk = async () => {
 	emojisPaginationComponent.value.reload();
 };
 
-const setLisenceBulk = async () => {
+const setLicenseBulk = async () => {
 	const { canceled, result } = await os.inputText({
 		title: 'License',
 	});
diff --git a/packages/frontend/src/pages/my-antennas/create.vue b/packages/frontend/src/pages/my-antennas/create.vue
index 355d18fdb5..632c36bbf8 100644
--- a/packages/frontend/src/pages/my-antennas/create.vue
+++ b/packages/frontend/src/pages/my-antennas/create.vue
@@ -9,6 +9,7 @@ import XAntenna from './editor.vue';
 import { i18n } from '@/i18n';
 import { definePageMetadata } from '@/scripts/page-metadata';
 import { useRouter } from '@/router';
+import { antennasCache } from '@/cache';
 
 const router = useRouter();
 
@@ -26,13 +27,10 @@ let draft = $ref({
 });
 
 function onAntennaCreated() {
+	antennasCache.delete();
 	router.push('/my/antennas');
 }
 
-const headerActions = $computed(() => []);
-
-const headerTabs = $computed(() => []);
-
 definePageMetadata({
 	title: i18n.ts.manageAntennas,
 	icon: 'ti ti-antenna',
diff --git a/packages/frontend/src/pages/my-antennas/edit.vue b/packages/frontend/src/pages/my-antennas/edit.vue
index da9b2de48f..3fb9690ac1 100644
--- a/packages/frontend/src/pages/my-antennas/edit.vue
+++ b/packages/frontend/src/pages/my-antennas/edit.vue
@@ -10,6 +10,7 @@ import * as os from '@/os';
 import { i18n } from '@/i18n';
 import { useRouter } from '@/router';
 import { definePageMetadata } from '@/scripts/page-metadata';
+import { antennasCache } from '@/cache';
 
 const router = useRouter();
 
@@ -20,6 +21,7 @@ const props = defineProps<{
 }>();
 
 function onAntennaUpdated() {
+	antennasCache.delete();
 	router.push('/my/antennas');
 }
 
@@ -27,10 +29,6 @@ os.api('antennas/show', { antennaId: props.antennaId }).then((antennaResponse) =
 	antenna = antennaResponse;
 });
 
-const headerActions = $computed(() => []);
-
-const headerTabs = $computed(() => []);
-
 definePageMetadata({
 	title: i18n.ts.manageAntennas,
 	icon: 'ti ti-antenna',
diff --git a/packages/frontend/src/pages/my-antennas/index.vue b/packages/frontend/src/pages/my-antennas/index.vue
index 2ca026b9a1..1e9136f1fa 100644
--- a/packages/frontend/src/pages/my-antennas/index.vue
+++ b/packages/frontend/src/pages/my-antennas/index.vue
@@ -2,15 +2,20 @@
 <MkStickyContainer>
 	<template #header><MkPageHeader :actions="headerActions" :tabs="headerTabs"/></template>
 	<MkSpacer :contentMax="700">
-		<div class="ieepwinx">
-			<MkButton :link="true" to="/my/antennas/create" primary class="add"><i class="ti ti-plus"></i> {{ i18n.ts.add }}</MkButton>
+		<div>
+			<div v-if="antennas.length === 0" class="empty">
+				<div class="_fullinfo">
+					<img :src="infoImageUrl" class="_ghost"/>
+					<div>{{ i18n.ts.nothing }}</div>
+				</div>
+			</div>
 
-			<div class="">
-				<MkPagination v-slot="{items}" ref="list" :pagination="pagination">
-					<MkA v-for="antenna in items" :key="antenna.id" class="ljoevbzj" :to="`/my/antennas/${antenna.id}`">
-						<div class="name">{{ antenna.name }}</div>
-					</MkA>
-				</MkPagination>
+			<MkButton :link="true" to="/my/antennas/create" primary :class="$style.add"><i class="ti ti-plus"></i> {{ i18n.ts.add }}</MkButton>
+
+			<div v-if="antennas.length > 0" class="_gaps">
+				<MkA v-for="antenna in antennas" :key="antenna.id" :class="$style.antenna" :to="`/my/antennas/${antenna.id}`">
+					<div class="name">{{ antenna.name }}</div>
+				</MkA>
 			</div>
 		</div>
 	</MkSpacer>
@@ -18,19 +23,31 @@
 </template>
 
 <script lang="ts" setup>
-import { } from 'vue';
-import MkPagination from '@/components/MkPagination.vue';
 import MkButton from '@/components/MkButton.vue';
 import { i18n } from '@/i18n';
 import { definePageMetadata } from '@/scripts/page-metadata';
+import { antennasCache } from '@/cache';
+import { api } from '@/os';
+import { onActivated } from 'vue';
+import { infoImageUrl } from '@/instance';
 
-const pagination = {
-	endpoint: 'antennas/list' as const,
-	noPaging: true,
-	limit: 10,
-};
+const antennas = $computed(() => antennasCache.value.value ?? []);
 
-const headerActions = $computed(() => []);
+function fetch() {
+	antennasCache.fetch(() => api('antennas/list'));
+}
+
+fetch();
+
+const headerActions = $computed(() => [{
+	asFullButton: true,
+	icon: 'ti ti-refresh',
+	text: i18n.ts.reload,
+	handler: () => {
+		antennasCache.delete();
+		fetch();
+	},
+}]);
 
 const headerTabs = $computed(() => []);
 
@@ -38,30 +55,30 @@ definePageMetadata({
 	title: i18n.ts.manageAntennas,
 	icon: 'ti ti-antenna',
 });
+
+onActivated(() => {
+	antennasCache.fetch(() => api('antennas/list'));
+});
 </script>
 
-<style lang="scss" scoped>
-.ieepwinx {
+<style lang="scss" module>
+.add {
+	margin: 0 auto 16px auto;
+}
 
-	> .add {
-		margin: 0 auto 16px auto;
-	}
+.antenna {
+	display: block;
+	padding: 16px;
+	border: solid 1px var(--divider);
+	border-radius: 6px;
 
-	.ljoevbzj {
-		display: block;
-		padding: 16px;
-		margin-bottom: 8px;
-		border: solid 1px var(--divider);
-		border-radius: 6px;
-
-		&:hover {
-			border: solid 1px var(--accent);
-			text-decoration: none;
-		}
-
-		> .name {
-			font-weight: bold;
-		}
+	&:hover {
+		border: solid 1px var(--accent);
+		text-decoration: none;
 	}
 }
+
+.name {
+	font-weight: bold;
+}
 </style>
diff --git a/packages/frontend/src/pages/my-lists/index.vue b/packages/frontend/src/pages/my-lists/index.vue
index cee241c489..0f59ca0b36 100644
--- a/packages/frontend/src/pages/my-lists/index.vue
+++ b/packages/frontend/src/pages/my-lists/index.vue
@@ -3,38 +3,43 @@
 	<template #header><MkPageHeader :actions="headerActions" :tabs="headerTabs"/></template>
 	<MkSpacer :contentMax="700">
 		<div class="_gaps">
+			<div v-if="items.length === 0" class="empty">
+				<div class="_fullinfo">
+					<img :src="infoImageUrl" class="_ghost"/>
+					<div>{{ i18n.ts.nothing }}</div>
+				</div>
+			</div>
+
 			<MkButton primary rounded style="margin: 0 auto;" @click="create"><i class="ti ti-plus"></i> {{ i18n.ts.createList }}</MkButton>
 
-			<MkPagination v-slot="{items}" ref="pagingComponent" :pagination="pagination">
-				<div class="_gaps">
-					<MkA v-for="list in items" :key="list.id" class="_panel" :class="$style.list" :to="`/my/lists/${ list.id }`">
-						<div style="margin-bottom: 4px;">{{ list.name }}</div>
-						<MkAvatars :userIds="list.userIds"/>
-					</MkA>
-				</div>
-			</MkPagination>
+			<div v-if="items.length > 0" class="_gaps">
+				<MkA v-for="list in items" :key="list.id" class="_panel" :class="$style.list" :to="`/my/lists/${ list.id }`">
+					<div style="margin-bottom: 4px;">{{ list.name }}</div>
+					<MkAvatars :userIds="list.userIds" :limit="10"/>
+				</MkA>
+			</div>
 		</div>
 	</MkSpacer>
 </MkStickyContainer>
 </template>
 
 <script lang="ts" setup>
-import { } from 'vue';
-import MkPagination from '@/components/MkPagination.vue';
+import { onActivated } from 'vue';
 import MkButton from '@/components/MkButton.vue';
 import MkAvatars from '@/components/MkAvatars.vue';
 import * as os from '@/os';
 import { i18n } from '@/i18n';
 import { definePageMetadata } from '@/scripts/page-metadata';
 import { userListsCache } from '@/cache';
+import { infoImageUrl } from '@/instance';
 
-const pagingComponent = $shallowRef<InstanceType<typeof MkPagination>>();
+const items = $computed(() => userListsCache.value.value ?? []);
 
-const pagination = {
-	endpoint: 'users/lists/list' as const,
-	noPaging: true,
-	limit: 10,
-};
+function fetch() {
+	userListsCache.fetch(() => os.api('users/lists/list'));
+}
+
+fetch();
 
 async function create() {
 	const { canceled, result: name } = await os.inputText({
@@ -43,10 +48,18 @@ async function create() {
 	if (canceled) return;
 	await os.apiWithDialog('users/lists/create', { name: name });
 	userListsCache.delete();
-	pagingComponent.reload();
+	fetch();
 }
 
-const headerActions = $computed(() => []);
+const headerActions = $computed(() => [{
+	asFullButton: true,
+	icon: 'ti ti-refresh',
+	text: i18n.ts.reload,
+	handler: () => {
+		userListsCache.delete();
+		fetch();
+	},
+}]);
 
 const headerTabs = $computed(() => []);
 
@@ -58,6 +71,10 @@ definePageMetadata({
 		handler: create,
 	},
 });
+
+onActivated(() => {
+	fetch();
+});
 </script>
 
 <style lang="scss" module>
diff --git a/packages/frontend/src/pages/settings/index.vue b/packages/frontend/src/pages/settings/index.vue
index b4f056d8a6..d53519e0d5 100644
--- a/packages/frontend/src/pages/settings/index.vue
+++ b/packages/frontend/src/pages/settings/index.vue
@@ -166,7 +166,7 @@ const menuDef = computed(() => [{
 		active: currentPage?.route.name === 'import-export',
 	}, {
 		icon: 'ti ti-plane',
-		text: `${i18n.ts.accountMigration} (${i18n.ts.experimental})`,
+		text: `${i18n.ts.accountMigration}`,
 		to: '/settings/migration',
 		active: currentPage?.route.name === 'migration',
 	}, {
diff --git a/packages/frontend/src/pages/settings/migration.vue b/packages/frontend/src/pages/settings/migration.vue
index 102bc68523..38e0d0abb2 100644
--- a/packages/frontend/src/pages/settings/migration.vue
+++ b/packages/frontend/src/pages/settings/migration.vue
@@ -1,8 +1,5 @@
 <template>
 <div class="_gaps_m">
-	<FormInfo warn>
-		{{ i18n.ts.thisIsExperimentalFeature }}
-	</FormInfo>
 	<MkFolder :defaultOpen="true">
 		<template #icon><i class="ti ti-plane-arrival"></i></template>
 		<template #label>{{ i18n.ts._accountMigration.moveFrom }}</template>
diff --git a/packages/frontend/src/scripts/aiscript/api.ts b/packages/frontend/src/scripts/aiscript/api.ts
index b6b7445b67..5453fe827d 100644
--- a/packages/frontend/src/scripts/aiscript/api.ts
+++ b/packages/frontend/src/scripts/aiscript/api.ts
@@ -11,6 +11,7 @@ export function createAiScriptEnv(opts) {
 		USER_NAME: $i ? values.STR($i.name) : values.NULL,
 		USER_USERNAME: $i ? values.STR($i.username) : values.NULL,
 		CUSTOM_EMOJIS: utils.jsToVal(customEmojis.value),
+		CURRENT_URL: values.STR(window.location.href),
 		'Mk:dialog': values.FN_NATIVE(async ([title, text, type]) => {
 			await os.alert({
 				type: type ? type.value : 'info',
diff --git a/packages/frontend/src/scripts/array.ts b/packages/frontend/src/scripts/array.ts
index 4620c8b735..c9a146e707 100644
--- a/packages/frontend/src/scripts/array.ts
+++ b/packages/frontend/src/scripts/array.ts
@@ -78,8 +78,9 @@ export function maximum(xs: number[]): number {
 export function groupBy<T>(f: EndoRelation<T>, xs: T[]): T[][] {
 	const groups = [] as T[][];
 	for (const x of xs) {
-		if (groups.length !== 0 && f(groups[groups.length - 1][0], x)) {
-			groups[groups.length - 1].push(x);
+		const lastGroup = groups.at(-1);
+		if (lastGroup !== undefined && f(lastGroup[0], x)) {
+			lastGroup.push(x);
 		} else {
 			groups.push([x]);
 		}
diff --git a/packages/frontend/src/scripts/autocomplete.ts b/packages/frontend/src/scripts/autocomplete.ts
index 1bae3790f5..564573ae8a 100644
--- a/packages/frontend/src/scripts/autocomplete.ts
+++ b/packages/frontend/src/scripts/autocomplete.ts
@@ -65,7 +65,7 @@ export class Autocomplete {
 	 */
 	private onInput() {
 		const caretPos = this.textarea.selectionStart;
-		const text = this.text.substr(0, caretPos).split('\n').pop()!;
+		const text = this.text.substring(0, caretPos).split('\n').pop()!;
 
 		const mentionIndex = text.lastIndexOf('@');
 		const hashtagIndex = text.lastIndexOf('#');
@@ -91,7 +91,7 @@ export class Autocomplete {
 		let opened = false;
 
 		if (isMention) {
-			const username = text.substr(mentionIndex + 1);
+			const username = text.substring(mentionIndex + 1);
 			if (username !== '' && username.match(/^[a-zA-Z0-9_]+$/)) {
 				this.open('user', username);
 				opened = true;
@@ -102,7 +102,7 @@ export class Autocomplete {
 		}
 
 		if (isHashtag && !opened) {
-			const hashtag = text.substr(hashtagIndex + 1);
+			const hashtag = text.substring(hashtagIndex + 1);
 			if (!hashtag.includes(' ')) {
 				this.open('hashtag', hashtag);
 				opened = true;
@@ -110,7 +110,7 @@ export class Autocomplete {
 		}
 
 		if (isEmoji && !opened) {
-			const emoji = text.substr(emojiIndex + 1);
+			const emoji = text.substring(emojiIndex + 1);
 			if (!emoji.includes(' ')) {
 				this.open('emoji', emoji);
 				opened = true;
@@ -118,7 +118,7 @@ export class Autocomplete {
 		}
 
 		if (isMfmTag && !opened) {
-			const mfmTag = text.substr(mfmTagIndex + 1);
+			const mfmTag = text.substring(mfmTagIndex + 1);
 			if (!mfmTag.includes(' ')) {
 				this.open('mfmTag', mfmTag.replace('[', ''));
 				opened = true;
@@ -208,9 +208,9 @@ export class Autocomplete {
 		if (type === 'user') {
 			const source = this.text;
 
-			const before = source.substr(0, caret);
+			const before = source.substring(0, caret);
 			const trimmedBefore = before.substring(0, before.lastIndexOf('@'));
-			const after = source.substr(caret);
+			const after = source.substring(caret);
 
 			const acct = value.host === null ? value.username : `${value.username}@${toASCII(value.host)}`;
 
@@ -226,9 +226,9 @@ export class Autocomplete {
 		} else if (type === 'hashtag') {
 			const source = this.text;
 
-			const before = source.substr(0, caret);
+			const before = source.substring(0, caret);
 			const trimmedBefore = before.substring(0, before.lastIndexOf('#'));
-			const after = source.substr(caret);
+			const after = source.substring(caret);
 
 			// 挿入
 			this.text = `${trimmedBefore}#${value} ${after}`;
@@ -242,9 +242,9 @@ export class Autocomplete {
 		} else if (type === 'emoji') {
 			const source = this.text;
 
-			const before = source.substr(0, caret);
+			const before = source.substring(0, caret);
 			const trimmedBefore = before.substring(0, before.lastIndexOf(':'));
-			const after = source.substr(caret);
+			const after = source.substring(caret);
 
 			// 挿入
 			this.text = trimmedBefore + value + after;
@@ -258,9 +258,9 @@ export class Autocomplete {
 		} else if (type === 'mfmTag') {
 			const source = this.text;
 
-			const before = source.substr(0, caret);
+			const before = source.substring(0, caret);
 			const trimmedBefore = before.substring(0, before.lastIndexOf('$'));
-			const after = source.substr(caret);
+			const after = source.substring(caret);
 
 			// 挿入
 			this.text = `${trimmedBefore}$[${value} ]${after}`;
diff --git a/packages/frontend/src/scripts/cache.ts b/packages/frontend/src/scripts/cache.ts
index 858e5f03bf..a61d858353 100644
--- a/packages/frontend/src/scripts/cache.ts
+++ b/packages/frontend/src/scripts/cache.ts
@@ -1,7 +1,8 @@
+import { ref } from "vue";
 
 export class Cache<T> {
 	private cachedAt: number | null = null;
-	private value: T | undefined;
+	public value = ref<T | undefined>();
 	private lifetime: number;
 
 	constructor(lifetime: Cache<never>['lifetime']) {
@@ -10,21 +11,20 @@ export class Cache<T> {
 
 	public set(value: T): void {
 		this.cachedAt = Date.now();
-		this.value = value;
+		this.value.value = value;
 	}
 
-	public get(): T | undefined {
+	private get(): T | undefined {
 		if (this.cachedAt == null) return undefined;
 		if ((Date.now() - this.cachedAt) > this.lifetime) {
-			this.value = undefined;
+			this.value.value = undefined;
 			this.cachedAt = null;
 			return undefined;
 		}
-		return this.value;
+		return this.value.value;
 	}
 
 	public delete() {
-		this.value = undefined;
 		this.cachedAt = null;
 	}
 
diff --git a/packages/frontend/src/scripts/gen-search-query.ts b/packages/frontend/src/scripts/gen-search-query.ts
index da7d622632..956e0f35d0 100644
--- a/packages/frontend/src/scripts/gen-search-query.ts
+++ b/packages/frontend/src/scripts/gen-search-query.ts
@@ -5,7 +5,7 @@ export async function genSearchQuery(v: any, q: string) {
 	let host: string;
 	let userId: string;
 	if (q.split(' ').some(x => x.startsWith('@'))) {
-		for (const at of q.split(' ').filter(x => x.startsWith('@')).map(x => x.substr(1))) {
+		for (const at of q.split(' ').filter(x => x.startsWith('@')).map(x => x.substring(1))) {
 			if (at.includes('.')) {
 				if (at === localHost || at === '.') {
 					host = null;
diff --git a/packages/frontend/src/scripts/get-user-menu.ts b/packages/frontend/src/scripts/get-user-menu.ts
index bdcd1aabdc..1c93d58b44 100644
--- a/packages/frontend/src/scripts/get-user-menu.ts
+++ b/packages/frontend/src/scripts/get-user-menu.ts
@@ -1,3 +1,4 @@
+import { toUnicode } from 'punycode';
 import { defineAsyncComponent } from 'vue';
 import * as misskey from 'misskey-js';
 import { i18n } from '@/i18n';
@@ -8,8 +9,7 @@ import { defaultStore, userActions } from '@/store';
 import { $i, iAmModerator } from '@/account';
 import { mainRouter } from '@/router';
 import { Router } from '@/nirax';
-import { rolesCache, userListsCache } from '@/cache';
-import { toUnicode } from 'punycode';
+import { antennasCache, rolesCache, userListsCache } from '@/cache';
 
 export function getUserMenu(user: misskey.entities.UserDetailed, router: Router = mainRouter) {
 	const meId = $i ? $i.id : null;
@@ -166,11 +166,39 @@ export function getUserMenu(user: misskey.entities.UserDetailed, router: Router
 
 			return lists.map(list => ({
 				text: list.name,
-				action: () => {
-					os.apiWithDialog('users/lists/push', {
+				action: async () => {
+					await os.apiWithDialog('users/lists/push', {
 						listId: list.id,
 						userId: user.id,
 					});
+					userListsCache.delete();
+				},
+			}));
+		},
+	}, {
+		type: 'parent',
+		icon: 'ti ti-antenna',
+		text: i18n.ts.addToAntenna,
+		children: async () => {
+			const antennas = await antennasCache.fetch(() => os.api('antennas/list'));
+			const canonical = user.host === null ? `@${user.username}` : `@${user.username}@${toUnicode(user.host)}`;
+			return antennas.filter((a) => a.src === 'users').map(antenna => ({
+				text: antenna.name,
+				action: async () => {
+					await os.apiWithDialog('antennas/update', {
+						antennaId: antenna.id,
+						name: antenna.name,
+						keywords: antenna.keywords,
+						excludeKeywords: antenna.excludeKeywords,
+						src: antenna.src,
+						userListId: antenna.userListId,
+						users: [...antenna.users, canonical],
+						caseSensitive: antenna.caseSensitive,
+						withReplies: antenna.withReplies,
+						withFile: antenna.withFile,
+						notify: antenna.notify,
+					});
+					antennasCache.delete();
 				},
 			}));
 		},
diff --git a/packages/frontend/src/scripts/lookup.ts b/packages/frontend/src/scripts/lookup.ts
index a55868368e..3f357a3c92 100644
--- a/packages/frontend/src/scripts/lookup.ts
+++ b/packages/frontend/src/scripts/lookup.ts
@@ -18,7 +18,7 @@ export async function lookup(router?: Router) {
 	}
 
 	if (query.startsWith('#')) {
-		_router.push(`/tags/${encodeURIComponent(query.substr(1))}`);
+		_router.push(`/tags/${encodeURIComponent(query.substring(1))}`);
 		return;
 	}
 
diff --git a/packages/frontend/src/scripts/theme-editor.ts b/packages/frontend/src/scripts/theme-editor.ts
index 944875ff15..001d87381c 100644
--- a/packages/frontend/src/scripts/theme-editor.ts
+++ b/packages/frontend/src/scripts/theme-editor.ts
@@ -35,7 +35,7 @@ export const fromThemeString = (str?: string) : ThemeValue => {
 	} else if (str.startsWith('"')) {
 		return {
 			type: 'css',
-			value: str.substr(1).trim(),
+			value: str.substring(1).trim(),
 		};
 	} else {
 		return str;
diff --git a/packages/frontend/src/scripts/theme.ts b/packages/frontend/src/scripts/theme.ts
index f2e8253565..bc61256cac 100644
--- a/packages/frontend/src/scripts/theme.ts
+++ b/packages/frontend/src/scripts/theme.ts
@@ -98,7 +98,7 @@ function compile(theme: Theme): Record<string, string> {
 	function getColor(val: string): tinycolor.Instance {
 		// ref (prop)
 		if (val[0] === '@') {
-			return getColor(theme.props[val.substr(1)]);
+			return getColor(theme.props[val.substring(1)]);
 		}
 
 		// ref (const)
@@ -109,7 +109,7 @@ function compile(theme: Theme): Record<string, string> {
 		// func
 		else if (val[0] === ':') {
 			const parts = val.split('<');
-			const func = parts.shift().substr(1);
+			const func = parts.shift().substring(1);
 			const arg = parseFloat(parts.shift());
 			const color = getColor(parts.join('<'));
 
diff --git a/packages/frontend/src/widgets/WidgetJobQueue.vue b/packages/frontend/src/widgets/WidgetJobQueue.vue
index 3c8ffdb55a..36706c37e4 100644
--- a/packages/frontend/src/widgets/WidgetJobQueue.vue
+++ b/packages/frontend/src/widgets/WidgetJobQueue.vue
@@ -124,7 +124,7 @@ connection.on('stats', onStats);
 connection.on('statsLog', onStatsLog);
 
 connection.send('requestLog', {
-	id: Math.random().toString().substr(2, 8),
+	id: Math.random().toString().substring(2, 10),
 	length: 1,
 });
 
diff --git a/packages/frontend/src/widgets/server-metric/cpu-mem.vue b/packages/frontend/src/widgets/server-metric/cpu-mem.vue
index 80a8e427e1..b9ba400b4d 100644
--- a/packages/frontend/src/widgets/server-metric/cpu-mem.vue
+++ b/packages/frontend/src/widgets/server-metric/cpu-mem.vue
@@ -100,7 +100,7 @@ onMounted(() => {
 	props.connection.on('stats', onStats);
 	props.connection.on('statsLog', onStatsLog);
 	props.connection.send('requestLog', {
-		id: Math.random().toString().substr(2, 8),
+		id: Math.random().toString().substring(2, 10),
 	});
 });
 
@@ -121,10 +121,10 @@ function onStats(connStats) {
 	cpuPolygonPoints = `${viewBoxX - (stats.length - 1)},${viewBoxY} ${cpuPolylinePoints} ${viewBoxX},${viewBoxY}`;
 	memPolygonPoints = `${viewBoxX - (stats.length - 1)},${viewBoxY} ${memPolylinePoints} ${viewBoxX},${viewBoxY}`;
 
-	cpuHeadX = cpuPolylinePointsStats[cpuPolylinePointsStats.length - 1][0];
-	cpuHeadY = cpuPolylinePointsStats[cpuPolylinePointsStats.length - 1][1];
-	memHeadX = memPolylinePointsStats[memPolylinePointsStats.length - 1][0];
-	memHeadY = memPolylinePointsStats[memPolylinePointsStats.length - 1][1];
+	cpuHeadX = cpuPolylinePointsStats.at(-1)![0];
+	cpuHeadY = cpuPolylinePointsStats.at(-1)![1];
+	memHeadX = memPolylinePointsStats.at(-1)![0];
+	memHeadY = memPolylinePointsStats.at(-1)![1];
 
 	cpuP = (connStats.cpu * 100).toFixed(0);
 	memP = (connStats.mem.active / props.meta.mem.total * 100).toFixed(0);
diff --git a/packages/frontend/src/widgets/server-metric/net.vue b/packages/frontend/src/widgets/server-metric/net.vue
index ab8b0fe471..817a422e63 100644
--- a/packages/frontend/src/widgets/server-metric/net.vue
+++ b/packages/frontend/src/widgets/server-metric/net.vue
@@ -70,7 +70,7 @@ onMounted(() => {
 	props.connection.on('stats', onStats);
 	props.connection.on('statsLog', onStatsLog);
 	props.connection.send('requestLog', {
-		id: Math.random().toString().substr(2, 8),
+		id: Math.random().toString().substring(2, 10),
 	});
 });
 
@@ -94,10 +94,10 @@ function onStats(connStats) {
 	inPolygonPoints = `${viewBoxX - (stats.length - 1)},${viewBoxY} ${inPolylinePoints} ${viewBoxX},${viewBoxY}`;
 	outPolygonPoints = `${viewBoxX - (stats.length - 1)},${viewBoxY} ${outPolylinePoints} ${viewBoxX},${viewBoxY}`;
 
-	inHeadX = inPolylinePointsStats[inPolylinePointsStats.length - 1][0];
-	inHeadY = inPolylinePointsStats[inPolylinePointsStats.length - 1][1];
-	outHeadX = outPolylinePointsStats[outPolylinePointsStats.length - 1][0];
-	outHeadY = outPolylinePointsStats[outPolylinePointsStats.length - 1][1];
+	inHeadX = inPolylinePointsStats.at(-1)![0];
+	inHeadY = inPolylinePointsStats.at(-1)![1];
+	outHeadX = outPolylinePointsStats.at(-1)![0];
+	outHeadY = outPolylinePointsStats.at(-1)![1];
 
 	inRecent = connStats.net.rx;
 	outRecent = connStats.net.tx;
diff --git a/packages/misskey-js/src/acct.ts b/packages/misskey-js/src/acct.ts
index c32cee86c9..b25bc564ea 100644
--- a/packages/misskey-js/src/acct.ts
+++ b/packages/misskey-js/src/acct.ts
@@ -4,7 +4,7 @@ export type Acct = {
 };
 
 export function parse(acct: string): Acct {
-	if (acct.startsWith('@')) acct = acct.substr(1);
+	if (acct.startsWith('@')) acct = acct.substring(1);
 	const split = acct.split('@', 2);
 	return { username: split[0], host: split[1] || null };
 }
diff --git a/packages/sw/src/sw.ts b/packages/sw/src/sw.ts
index 2783f2bfb5..1f085c7392 100644
--- a/packages/sw/src/sw.ts
+++ b/packages/sw/src/sw.ts
@@ -21,6 +21,10 @@ globalThis.addEventListener('activate', ev => {
 	);
 });
 
+function offlineContentHTML(): string {
+	return `<!doctype html>Offline. Service Worker @${_VERSION_} <button onclick="location.reload()">reload</button>`
+}
+
 globalThis.addEventListener('fetch', ev => {
 	let isHTMLRequest = false;
 	if (ev.request.headers.get('sec-fetch-dest') === 'document') {
@@ -34,7 +38,14 @@ globalThis.addEventListener('fetch', ev => {
 	if (!isHTMLRequest) return;
 	ev.respondWith(
 		fetch(ev.request)
-			.catch(() => new Response(`Offline. Service Worker @${_VERSION_}`, { status: 200 })),
+			.catch(() => {
+				return new Response(offlineContentHTML(), {
+					status: 200,
+					headers: {
+						'content-type': 'text/html',
+					},
+				});
+			}),
 	);
 });