diff --git a/packages/frontend/src/components/MkAbuseReport.vue b/packages/frontend/src/components/MkAbuseReport.vue
index d46e5da0640d56fcbeac0a709af76a0e24d74841..cb97875bcd8261a571e42f26cc079eb0502e72df 100644
--- a/packages/frontend/src/components/MkAbuseReport.vue
+++ b/packages/frontend/src/components/MkAbuseReport.vue
@@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 <template>
 <div class="bcekxzvu _margin _panel">
 	<div class="target">
-		<MkA v-user-preview="report.targetUserId" class="info" :to="`/user-info/${report.targetUserId}`">
+		<MkA v-user-preview="report.targetUserId" class="info" :to="`/admin/user/${report.targetUserId}`">
 			<MkAvatar class="avatar" :user="report.targetUser" indicator/>
 			<div class="names">
 				<MkUserName class="name" :user="report.targetUser"/>
diff --git a/packages/frontend/src/pages/admin-file.vue b/packages/frontend/src/pages/admin-file.vue
index 2614b20c285930a5593072553d0d4970ce840f72..4083c02049c0b278a1975a3f0954cc299d43464a 100644
--- a/packages/frontend/src/pages/admin-file.vue
+++ b/packages/frontend/src/pages/admin-file.vue
@@ -33,7 +33,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 					<template #value><span class="_monospace"><MkTime :time="file.createdAt" mode="detail" style="display: block;"/></span></template>
 				</MkKeyValue>
 			</div>
-			<MkA v-if="file.user" class="user" :to="`/user-info/${file.user.id}`">
+			<MkA v-if="file.user" class="user" :to="`/admin/user/${file.user.id}`">
 				<MkUserCardMini :user="file.user"/>
 			</MkA>
 			<div>
diff --git a/packages/frontend/src/pages/user-info.vue b/packages/frontend/src/pages/admin-user.vue
similarity index 70%
rename from packages/frontend/src/pages/user-info.vue
rename to packages/frontend/src/pages/admin-user.vue
index 35cd116fad1992aa94c4424b218ba54b8dbff6a2..1b79a14f55b905f7aeb1fe3905bb500b1cea45c2 100644
--- a/packages/frontend/src/pages/user-info.vue
+++ b/packages/frontend/src/pages/admin-user.vue
@@ -24,12 +24,6 @@ SPDX-License-Identifier: AGPL-3.0-only
 
 				<MkInfo v-if="user.username.includes('.')">{{ i18n.ts.isSystemAccount }}</MkInfo>
 
-				<div v-if="user.url" class="_formLinksGrid">
-					<FormLink :to="userPage(user)">Profile</FormLink>
-					<FormLink :to="user.url" :external="true">Profile (remote)</FormLink>
-				</div>
-				<FormLink v-else :to="userPage(user)">Profile</FormLink>
-
 				<FormLink v-if="user.host" :to="`/instance-info/${user.host}`">{{ i18n.ts.instanceInfo }}</FormLink>
 
 				<div style="display: flex; flex-direction: column; gap: 1em;">
@@ -57,6 +51,11 @@ SPDX-License-Identifier: AGPL-3.0-only
 					</MkKeyValue>
 				</div>
 
+				<MkTextarea v-model="moderationNote" manualSave>
+					<template #label>Moderation note</template>
+				</MkTextarea>
+
+				<!--
 				<FormSection>
 					<template #label>ActivityPub</template>
 
@@ -90,95 +89,85 @@ SPDX-License-Identifier: AGPL-3.0-only
 						</MkFolder>
 					</div>
 				</FormSection>
-			</div>
+			-->
 
-			<div v-else-if="tab === 'moderation'" class="_gaps_m">
-				<MkSwitch v-model="suspended" @update:modelValue="toggleSuspend">{{ i18n.ts.suspend }}</MkSwitch>
-
-				<div>
-					<MkButton v-if="user.host == null && iAmModerator" inline style="margin-right: 8px;" @click="resetPassword"><i class="ti ti-key"></i> {{ i18n.ts.resetPassword }}</MkButton>
-					<MkButton v-if="$i.isAdmin" inline danger @click="deleteAccount">{{ i18n.ts.deleteAccount }}</MkButton>
-				</div>
-
-				<MkFolder>
-					<template #icon><i class="ti ti-license"></i></template>
-					<template #label>{{ i18n.ts._role.policies }}</template>
+				<FormSection>
 					<div class="_gaps">
-						<div v-for="policy in Object.keys(info.policies)" :key="policy">
-							{{ policy }} ... {{ info.policies[policy] }}
+						<MkSwitch v-model="suspended" @update:modelValue="toggleSuspend">{{ i18n.ts.suspend }}</MkSwitch>
+
+						<div>
+							<MkButton v-if="user.host == null" inline style="margin-right: 8px;" @click="resetPassword"><i class="ti ti-key"></i> {{ i18n.ts.resetPassword }}</MkButton>
 						</div>
-					</div>
-				</MkFolder>
 
-				<MkFolder>
-					<template #icon><i class="ti ti-badges"></i></template>
-					<template #label>{{ i18n.ts.roles }}</template>
-					<div class="_gaps">
-						<MkButton v-if="user.host == null && iAmModerator" primary rounded @click="assignRole"><i class="ti ti-plus"></i> {{ i18n.ts.assign }}</MkButton>
-
-						<div v-for="role in info.roles" :key="role.id" :class="$style.roleItem">
-							<div :class="$style.roleItemMain">
-								<MkRolePreview :class="$style.role" :role="role" :forModeration="true"/>
-								<button class="_button" :class="$style.roleToggle" @click="toggleRoleItem(role)"><i class="ti ti-chevron-down"></i></button>
-								<button v-if="role.target === 'manual'" class="_button" :class="$style.roleUnassign" @click="unassignRole(role, $event)"><i class="ti ti-x"></i></button>
-								<button v-else class="_button" :class="$style.roleUnassign" disabled><i class="ti ti-ban"></i></button>
-							</div>
-							<div v-if="expandedRoles.includes(role.id)" :class="$style.roleItemSub">
-								<div>Assigned: <MkTime :time="info.roleAssigns.find(a => a.roleId === role.id).createdAt" mode="detail"/></div>
-								<div v-if="info.roleAssigns.find(a => a.roleId === role.id).expiresAt">Period: {{ new Date(info.roleAssigns.find(a => a.roleId === role.id).expiresAt).toLocaleString() }}</div>
-								<div v-else>Period: {{ i18n.ts.indefinitely }}</div>
+						<MkFolder>
+							<template #icon><i class="ti ti-license"></i></template>
+							<template #label>{{ i18n.ts._role.policies }}</template>
+							<div class="_gaps">
+								<div v-for="policy in Object.keys(info.policies)" :key="policy">
+									{{ policy }} ... {{ info.policies[policy] }}
+								</div>
 							</div>
-						</div>
-					</div>
-				</MkFolder>
+						</MkFolder>
 
-				<MkFolder v-if="user.host == null && iAmModerator">
-					<template #icon><i class="ti ti-speakerphone"></i></template>
-					<template #label>{{ i18n.ts.announcements }}</template>
-					<div class="_gaps">
-						<MkButton primary rounded @click="createAnnouncement"><i class="ti ti-plus"></i> {{ i18n.ts.new }}</MkButton>
-
-						<MkPagination :pagination="announcementsPagination">
-							<template #default="{ items }">
-								<div class="_gaps_s">
-									<div v-for="announcement in items" :key="announcement.id" v-panel :class="$style.announcementItem" @click="editAnnouncement(announcement)">
-										<span style="margin-right: 0.5em;">
-											<i v-if="announcement.icon === 'info'" class="ti ti-info-circle"></i>
-											<i v-else-if="announcement.icon === 'warning'" class="ti ti-alert-triangle" style="color: var(--warn);"></i>
-											<i v-else-if="announcement.icon === 'error'" class="ti ti-circle-x" style="color: var(--error);"></i>
-											<i v-else-if="announcement.icon === 'success'" class="ti ti-check" style="color: var(--success);"></i>
-										</span>
-										<span>{{ announcement.title }}</span>
-										<span v-if="announcement.reads > 0" style="margin-left: auto; opacity: 0.7;">{{ i18n.ts.messageRead }}</span>
-									</div>
+						<MkFolder>
+							<template #icon><i class="ti ti-password"></i></template>
+							<template #label>IP</template>
+							<MkInfo v-if="!iAmAdmin" warn>{{ i18n.ts.requireAdminForView }}</MkInfo>
+							<MkInfo v-else>The date is the IP address was first acknowledged.</MkInfo>
+							<template v-if="iAmAdmin && ips">
+								<div v-for="record in ips" :key="record.ip" class="_monospace" :class="$style.ip" style="margin: 1em 0;">
+									<span class="date">{{ record.createdAt }}</span>
+									<span class="ip">{{ record.ip }}</span>
 								</div>
 							</template>
-						</MkPagination>
+						</MkFolder>
+
+						<MkButton v-if="$i.isAdmin" inline danger @click="deleteAccount">{{ i18n.ts.deleteAccount }}</MkButton>
 					</div>
-				</MkFolder>
-
-				<MkFolder>
-					<template #icon><i class="ti ti-password"></i></template>
-					<template #label>IP</template>
-					<MkInfo v-if="!iAmAdmin" warn>{{ i18n.ts.requireAdminForView }}</MkInfo>
-					<MkInfo v-else>The date is the IP address was first acknowledged.</MkInfo>
-					<template v-if="iAmAdmin && ips">
-						<div v-for="record in ips" :key="record.ip" class="_monospace" :class="$style.ip" style="margin: 1em 0;">
-							<span class="date">{{ record.createdAt }}</span>
-							<span class="ip">{{ record.ip }}</span>
+				</FormSection>
+			</div>
+
+			<div v-else-if="tab === 'roles'" class="_gaps">
+				<MkButton v-if="user.host == null" primary rounded @click="assignRole"><i class="ti ti-plus"></i> {{ i18n.ts.assign }}</MkButton>
+
+				<div v-for="role in info.roles" :key="role.id" :class="$style.roleItem">
+					<div :class="$style.roleItemMain">
+						<MkRolePreview :class="$style.role" :role="role" :forModeration="true"/>
+						<button class="_button" :class="$style.roleToggle" @click="toggleRoleItem(role)"><i class="ti ti-chevron-down"></i></button>
+						<button v-if="role.target === 'manual'" class="_button" :class="$style.roleUnassign" @click="unassignRole(role, $event)"><i class="ti ti-x"></i></button>
+						<button v-else class="_button" :class="$style.roleUnassign" disabled><i class="ti ti-ban"></i></button>
+					</div>
+					<div v-if="expandedRoles.includes(role.id)" :class="$style.roleItemSub">
+						<div>Assigned: <MkTime :time="info.roleAssigns.find(a => a.roleId === role.id).createdAt" mode="detail"/></div>
+						<div v-if="info.roleAssigns.find(a => a.roleId === role.id).expiresAt">Period: {{ new Date(info.roleAssigns.find(a => a.roleId === role.id).expiresAt).toLocaleString() }}</div>
+						<div v-else>Period: {{ i18n.ts.indefinitely }}</div>
+					</div>
+				</div>
+			</div>
+
+			<div v-else-if="tab === 'announcements'" class="_gaps">
+				<MkButton primary rounded @click="createAnnouncement"><i class="ti ti-plus"></i> {{ i18n.ts.new }}</MkButton>
+
+				<MkPagination :pagination="announcementsPagination">
+					<template #default="{ items }">
+						<div class="_gaps_s">
+							<div v-for="announcement in items" :key="announcement.id" v-panel :class="$style.announcementItem" @click="editAnnouncement(announcement)">
+								<span style="margin-right: 0.5em;">
+									<i v-if="announcement.icon === 'info'" class="ti ti-info-circle"></i>
+									<i v-else-if="announcement.icon === 'warning'" class="ti ti-alert-triangle" style="color: var(--warn);"></i>
+									<i v-else-if="announcement.icon === 'error'" class="ti ti-circle-x" style="color: var(--error);"></i>
+									<i v-else-if="announcement.icon === 'success'" class="ti ti-check" style="color: var(--success);"></i>
+								</span>
+								<span>{{ announcement.title }}</span>
+								<span v-if="announcement.reads > 0" style="margin-left: auto; opacity: 0.7;">{{ i18n.ts.messageRead }}</span>
+							</div>
 						</div>
 					</template>
-				</MkFolder>
-
-				<MkFolder>
-					<template #icon><i class="ti ti-cloud"></i></template>
-					<template #label>{{ i18n.ts.files }}</template>
-					<MkFileListForAdmin :pagination="filesPagination" viewMode="grid"/>
-				</MkFolder>
+				</MkPagination>
+			</div>
 
-				<MkTextarea v-model="moderationNote" manualSave>
-					<template #label>Moderation note</template>
-				</MkTextarea>
+			<div v-else-if="tab === 'drive'" class="_gaps">
+				<MkFileListForAdmin :pagination="filesPagination" viewMode="grid"/>
 			</div>
 
 			<div v-else-if="tab === 'chart'" class="_gaps_m">
@@ -230,7 +219,7 @@ import { url } from '@/config';
 import { userPage, acct } from '@/filters/user';
 import { definePageMetadata } from '@/scripts/page-metadata';
 import { i18n } from '@/i18n';
-import { iAmAdmin, iAmModerator, $i } from '@/account';
+import { iAmAdmin, $i } from '@/account';
 import MkRolePreview from '@/components/MkRolePreview.vue';
 import MkPagination, { Paging } from '@/components/MkPagination.vue';
 
@@ -269,34 +258,26 @@ const announcementsPagination = {
 let expandedRoles = $ref([]);
 
 function createFetcher() {
-	if (iAmModerator) {
-		return () => Promise.all([os.api('users/show', {
-			userId: props.userId,
-		}), os.api('admin/show-user', {
-			userId: props.userId,
-		}), iAmAdmin ? os.api('admin/get-user-ips', {
-			userId: props.userId,
-		}) : Promise.resolve(null)]).then(([_user, _info, _ips]) => {
-			user = _user;
-			info = _info;
-			ips = _ips;
-			moderator = info.isModerator;
-			silenced = info.isSilenced;
-			suspended = info.isSuspended;
-			moderationNote = info.moderationNote;
-
-			watch($$(moderationNote), async () => {
-				await os.api('admin/update-user-note', { userId: user.id, text: moderationNote });
-				await refreshUser();
-			});
-		});
-	} else {
-		return () => os.api('users/show', {
-			userId: props.userId,
-		}).then((res) => {
-			user = res;
+	return () => Promise.all([os.api('users/show', {
+		userId: props.userId,
+	}), os.api('admin/show-user', {
+		userId: props.userId,
+	}), iAmAdmin ? os.api('admin/get-user-ips', {
+		userId: props.userId,
+	}) : Promise.resolve(null)]).then(([_user, _info, _ips]) => {
+		user = _user;
+		info = _info;
+		ips = _ips;
+		moderator = info.isModerator;
+		silenced = info.isSilenced;
+		suspended = info.isSuspended;
+		moderationNote = info.moderationNote;
+
+		watch($$(moderationNote), async () => {
+			await os.api('admin/update-user-note', { userId: user.id, text: moderationNote });
+			await refreshUser();
 		});
-	}
+	});
 }
 
 function refreshUser() {
@@ -472,11 +453,19 @@ const headerTabs = $computed(() => [{
 	key: 'overview',
 	title: i18n.ts.overview,
 	icon: 'ti ti-info-circle',
-}, iAmModerator ? {
-	key: 'moderation',
-	title: i18n.ts.moderation,
-	icon: 'ti ti-user-exclamation',
-} : null, {
+}, {
+	key: 'roles',
+	title: i18n.ts.roles,
+	icon: 'ti ti-badges',
+}, {
+	key: 'announcements',
+	title: i18n.ts.announcements,
+	icon: 'ti ti-speakerphone',
+}, {
+	key: 'drive',
+	title: i18n.ts.drive,
+	icon: 'ti ti-cloud',
+}, {
 	key: 'chart',
 	title: i18n.ts.charts,
 	icon: 'ti ti-chart-line',
@@ -484,11 +473,11 @@ const headerTabs = $computed(() => [{
 	key: 'raw',
 	title: 'Raw',
 	icon: 'ti ti-code',
-}].filter(x => x != null));
+}]);
 
 definePageMetadata(computed(() => ({
 	title: user ? acct(user) : i18n.ts.userInfo,
-	icon: 'ti ti-info-circle',
+	icon: 'ti ti-user-exclamation',
 })));
 </script>
 
diff --git a/packages/frontend/src/pages/admin/overview.moderators.vue b/packages/frontend/src/pages/admin/overview.moderators.vue
index 6ed2e6d2376953acd9f6788b743e23d2dfaa4fdd..c448ec037de0aceadb25a17dc6c7054fbc9b5a63 100644
--- a/packages/frontend/src/pages/admin/overview.moderators.vue
+++ b/packages/frontend/src/pages/admin/overview.moderators.vue
@@ -8,7 +8,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 	<Transition :name="defaultStore.state.animation ? '_transition_zoom' : ''" mode="out-in">
 		<MkLoading v-if="fetching"/>
 		<div v-else :class="$style.root" class="_panel">
-			<MkA v-for="user in moderators" :key="user.id" class="user" :to="`/user-info/${user.id}`">
+			<MkA v-for="user in moderators" :key="user.id" class="user" :to="`/admin/user/${user.id}`">
 				<MkAvatar :user="user" class="avatar" indicator/>
 			</MkA>
 		</div>
diff --git a/packages/frontend/src/pages/admin/overview.users.vue b/packages/frontend/src/pages/admin/overview.users.vue
index 6535fac720d864c8e2d2d4aa87b0b2767053034f..a366293bf8208be460d7648eb740be2b92b323b1 100644
--- a/packages/frontend/src/pages/admin/overview.users.vue
+++ b/packages/frontend/src/pages/admin/overview.users.vue
@@ -8,7 +8,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 	<Transition :name="defaultStore.state.animation ? '_transition_zoom' : ''" mode="out-in">
 		<MkLoading v-if="fetching"/>
 		<div v-else class="users">
-			<MkA v-for="(user, i) in newUsers" :key="user.id" :to="`/user-info/${user.id}`" class="user">
+			<MkA v-for="(user, i) in newUsers" :key="user.id" :to="`/admin/user/${user.id}`" class="user">
 				<MkUserCardMini :user="user"/>
 			</MkA>
 		</div>
diff --git a/packages/frontend/src/pages/admin/roles.role.vue b/packages/frontend/src/pages/admin/roles.role.vue
index 78513beee0beb86da602dd2617739070943b4084..779fb6d51b50a26df3d1d61eeb1e16fa8d91c024 100644
--- a/packages/frontend/src/pages/admin/roles.role.vue
+++ b/packages/frontend/src/pages/admin/roles.role.vue
@@ -37,7 +37,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 								<div class="_gaps_s">
 									<div v-for="item in items" :key="item.user.id" :class="[$style.userItem, { [$style.userItemOpend]: expandedItems.includes(item.id) }]">
 										<div :class="$style.userItemMain">
-											<MkA :class="$style.userItemMainBody" :to="`/user-info/${item.user.id}`">
+											<MkA :class="$style.userItemMainBody" :to="`/admin/user/${item.user.id}`">
 												<MkUserCardMini :user="item.user"/>
 											</MkA>
 											<button class="_button" :class="$style.userToggle" @click="toggleItem(item)"><i :class="$style.chevron" class="ti ti-chevron-down"></i></button>
diff --git a/packages/frontend/src/pages/admin/users.vue b/packages/frontend/src/pages/admin/users.vue
index f62ab47033e264014f800705e4948c1a53b37534..084d5c0ed0655f63f52b850d7aed772b936b36fc 100644
--- a/packages/frontend/src/pages/admin/users.vue
+++ b/packages/frontend/src/pages/admin/users.vue
@@ -45,7 +45,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 
 				<MkPagination v-slot="{items}" ref="paginationComponent" :pagination="pagination">
 					<div :class="$style.users">
-						<MkA v-for="user in items" :key="user.id" v-tooltip.mfm="`Last posted: ${dateString(user.updatedAt)}`" :class="$style.user" :to="`/user-info/${user.id}`">
+						<MkA v-for="user in items" :key="user.id" v-tooltip.mfm="`Last posted: ${dateString(user.updatedAt)}`" :class="$style.user" :to="`/admin/user/${user.id}`">
 							<MkUserCardMini :user="user"/>
 						</MkA>
 					</div>
@@ -116,7 +116,7 @@ async function addUser() {
 }
 
 function show(user) {
-	os.pageWindow(`/user-info/${user.id}`);
+	os.pageWindow(`/admin/user/${user.id}`);
 }
 
 const headerActions = $computed(() => [{
diff --git a/packages/frontend/src/pages/instance-info.vue b/packages/frontend/src/pages/instance-info.vue
index 24355c05562b0c463b2689ee2c31c56ec5986256..143589bd8c900f04677a9868ba47b45a3965a723 100644
--- a/packages/frontend/src/pages/instance-info.vue
+++ b/packages/frontend/src/pages/instance-info.vue
@@ -102,7 +102,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 		</div>
 		<div v-else-if="tab === 'users'" class="_gaps_m">
 			<MkPagination v-slot="{items}" :pagination="usersPagination" style="display: grid; grid-template-columns: repeat(auto-fill,minmax(270px,1fr)); grid-gap: 12px;">
-				<MkA v-for="user in items" :key="user.id" v-tooltip.mfm="`Last posted: ${dateString(user.updatedAt)}`" class="user" :to="`/user-info/${user.id}`">
+				<MkA v-for="user in items" :key="user.id" v-tooltip.mfm="`Last posted: ${dateString(user.updatedAt)}`" class="user" :to="`/admin/user/${user.id}`">
 					<MkUserCardMini :user="user"/>
 				</MkA>
 			</MkPagination>
diff --git a/packages/frontend/src/pages/settings/mute-block.vue b/packages/frontend/src/pages/settings/mute-block.vue
index dcfd8b1e2ed81fd251bea5c9fb61820dd664eca7..c35fc0e0e3d11d213a305d4c0be962b52fa0ca2f 100644
--- a/packages/frontend/src/pages/settings/mute-block.vue
+++ b/packages/frontend/src/pages/settings/mute-block.vue
@@ -24,7 +24,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 				<div class="_gaps_s">
 					<div v-for="item in items" :key="item.mutee.id" :class="[$style.userItem, { [$style.userItemOpend]: expandedRenoteMuteItems.includes(item.id) }]">
 						<div :class="$style.userItemMain">
-							<MkA :class="$style.userItemMainBody" :to="`/user-info/${item.mutee.id}`">
+							<MkA :class="$style.userItemMainBody" :to="userPage(item.mutee)">
 								<MkUserCardMini :user="item.mutee"/>
 							</MkA>
 							<button class="_button" :class="$style.userToggle" @click="toggleRenoteMuteItem(item)"><i :class="$style.chevron" class="ti ti-chevron-down"></i></button>
@@ -52,7 +52,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 				<div class="_gaps_s">
 					<div v-for="item in items" :key="item.mutee.id" :class="[$style.userItem, { [$style.userItemOpend]: expandedMuteItems.includes(item.id) }]">
 						<div :class="$style.userItemMain">
-							<MkA :class="$style.userItemMainBody" :to="`/user-info/${item.mutee.id}`">
+							<MkA :class="$style.userItemMainBody" :to="userPage(item.mutee)">
 								<MkUserCardMini :user="item.mutee"/>
 							</MkA>
 							<button class="_button" :class="$style.userToggle" @click="toggleMuteItem(item)"><i :class="$style.chevron" class="ti ti-chevron-down"></i></button>
@@ -82,7 +82,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 				<div class="_gaps_s">
 					<div v-for="item in items" :key="item.blockee.id" :class="[$style.userItem, { [$style.userItemOpend]: expandedBlockItems.includes(item.id) }]">
 						<div :class="$style.userItemMain">
-							<MkA :class="$style.userItemMainBody" :to="`/user-info/${item.blockee.id}`">
+							<MkA :class="$style.userItemMainBody" :to="userPage(item.blockee)">
 								<MkUserCardMini :user="item.blockee"/>
 							</MkA>
 							<button class="_button" :class="$style.userToggle" @click="toggleBlockItem(item)"><i :class="$style.chevron" class="ti ti-chevron-down"></i></button>
diff --git a/packages/frontend/src/router.ts b/packages/frontend/src/router.ts
index 0876e533d05b2d99f55225223f4bb99576d03eed..2e4494814a686ef28ea8d0217118f51d123f33d2 100644
--- a/packages/frontend/src/router.ts
+++ b/packages/frontend/src/router.ts
@@ -42,10 +42,6 @@ export const routes = [{
 }, {
 	path: '/clips/:clipId',
 	component: page(() => import('./pages/clip.vue')),
-}, {
-	path: '/user-info/:userId',
-	component: page(() => import('./pages/user-info.vue')),
-	hash: 'initialTab',
 }, {
 	path: '/instance-info/:host',
 	component: page(() => import('./pages/instance-info.vue')),
@@ -334,6 +330,9 @@ export const routes = [{
 }, {
 	path: '/registry',
 	component: page(() => import('./pages/registry.vue')),
+}, {
+	path: '/admin/user/:userId',
+	component: iAmModerator ? page(() => import('./pages/admin-user.vue')) : page(() => import('./pages/not-found.vue')),
 }, {
 	path: '/admin/file/:fileId',
 	component: iAmModerator ? page(() => import('./pages/admin-file.vue')) : page(() => import('./pages/not-found.vue')),
diff --git a/packages/frontend/src/scripts/get-user-menu.ts b/packages/frontend/src/scripts/get-user-menu.ts
index 69a6f75c12e33d1137a18eaaa3ecf47190a16ce5..b9c726e134eb82a2a01283017186b3a464a6ec71 100644
--- a/packages/frontend/src/scripts/get-user-menu.ts
+++ b/packages/frontend/src/scripts/get-user-menu.ts
@@ -133,13 +133,13 @@ export function getUserMenu(user: misskey.entities.UserDetailed, router: Router
 		action: () => {
 			copyToClipboard(`@${user.username}@${user.host ?? host}`);
 		},
-	}, {
-		icon: 'ti ti-info-circle',
-		text: i18n.ts.info,
+	}, ...(iAmModerator ? [{
+		icon: 'ti ti-user-exclamation',
+		text: i18n.ts.moderation,
 		action: () => {
-			router.push(`/user-info/${user.id}`);
+			router.push(`/admin/user/${user.id}`);
 		},
-	}, {
+	}] : []), {
 		icon: 'ti ti-rss',
 		text: i18n.ts.copyRSS,
 		action: () => {
diff --git a/packages/frontend/src/scripts/lookup-user.ts b/packages/frontend/src/scripts/lookup-user.ts
index 83d7914fb19c488a25f27739a6b0e557debb1639..75899adbaa75efc5f12a05a9beddfe87aec23396 100644
--- a/packages/frontend/src/scripts/lookup-user.ts
+++ b/packages/frontend/src/scripts/lookup-user.ts
@@ -14,7 +14,7 @@ export async function lookupUser() {
 	if (canceled) return;
 
 	const show = (user) => {
-		os.pageWindow(`/user-info/${user.id}`);
+		os.pageWindow(`/admin/user/${user.id}`);
 	};
 
 	const usernamePromise = os.api('users/show', Acct.parse(result));