diff --git a/packages/client/src/pages/admin-file.vue b/packages/client/src/pages/admin-file.vue
index 2cbe8890a1..7273ddce6a 100644
--- a/packages/client/src/pages/admin-file.vue
+++ b/packages/client/src/pages/admin-file.vue
@@ -1,30 +1,46 @@
 <template>
 <MkStickyContainer>
 	<template #header><MkPageHeader :actions="headerActions" :tabs="headerTabs"/></template>
-	<MkSpacer :content-max="500" :margin-min="16" :margin-max="32">
-		<div v-if="file" class="cxqhhsmd _formRoot">
-			<div class="_formBlock">
+	<MkSpacer v-if="file" :content-max="500" :margin-min="16" :margin-max="32">
+		<div v-if="tab === 'overview'" class="cxqhhsmd _formRoot">
+			<a class="_formBlock thumbnail" :href="file.url" target="_blank">
 				<MkDriveFileThumbnail class="thumbnail" :file="file" fit="contain"/>
-				<div class="info">
-					<span style="margin-right: 1em;">{{ file.type }}</span>
-					<span>{{ bytes(file.size) }}</span>
-					<MkTime :time="file.createdAt" mode="detail" style="display: block;"/>
-				</div>
+			</a>
+			<div class="_formBlock">
+				<MkKeyValue :copy="file.type" oneline style="margin: 1em 0;">
+					<template #key>MIME Type</template>
+					<template #value><span class="_monospace">{{ file.type }}</span></template>
+				</MkKeyValue>
+				<MkKeyValue oneline style="margin: 1em 0;">
+					<template #key>Size</template>
+					<template #value><span class="_monospace">{{ bytes(file.size) }}</span></template>
+				</MkKeyValue>
+				<MkKeyValue :copy="file.id" oneline style="margin: 1em 0;">
+					<template #key>ID</template>
+					<template #value><span class="_monospace">{{ file.id }}</span></template>
+				</MkKeyValue>
+				<MkKeyValue :copy="file.md5" oneline style="margin: 1em 0;">
+					<template #key>MD5</template>
+					<template #value><span class="_monospace">{{ file.md5 }}</span></template>
+				</MkKeyValue>
+				<MkKeyValue oneline style="margin: 1em 0;">
+					<template #key>{{ i18n.ts.createdAt }}</template>
+					<template #value><span class="_monospace"><MkTime :time="file.createdAt" mode="detail" style="display: block;"/></span></template>
+				</MkKeyValue>
 			</div>
 			<div class="_formBlock">
 				<MkSwitch v-model="isSensitive" @update:modelValue="toggleIsSensitive">NSFW</MkSwitch>
 			</div>
 			<FormLink class="_formBlock" :to="file.url" :external="true">Open</FormLink>
-			<FormLink class="_formBlock" :to="`/user-info/${file.userId}`">{{ $ts.user }}</FormLink>
+			<FormLink class="_formBlock" :to="`/user-info/${file.userId}`">{{ $ts.user }} ({{ acct(file.user) }})</FormLink>
 
 			<div class="_formBlock">
 				<MkButton full danger @click="del"><i class="fas fa-trash-alt"></i> {{ $ts.delete }}</MkButton>
 			</div>
-			<div v-if="info" class="_formBlock">
-				<details class="_content rawdata">
-					<pre><code>{{ JSON.stringify(info, null, 2) }}</code></pre>
-				</details>
-			</div>
+		</div>
+		<div v-else-if="tab === 'raw'" class="_formRoot">
+			<MkObjectView v-if="info" tall :value="info">
+			</MkObjectView>
 		</div>
 	</MkSpacer>
 </MkStickyContainer>
@@ -34,13 +50,17 @@
 import { computed } from 'vue';
 import MkButton from '@/components/ui/button.vue';
 import MkSwitch from '@/components/form/switch.vue';
+import MkObjectView from '@/components/object-view.vue';
 import MkDriveFileThumbnail from '@/components/drive-file-thumbnail.vue';
+import MkKeyValue from '@/components/key-value.vue';
 import FormLink from '@/components/form/link.vue';
 import bytes from '@/filters/bytes';
 import * as os from '@/os';
 import { i18n } from '@/i18n';
 import { definePageMetadata } from '@/scripts/page-metadata';
+import { acct } from '@/filters/user';
 
+let tab = $ref('overview');
 let file: any = $ref(null);
 let info: any = $ref(null);
 let isSensitive: boolean = $ref(false);
@@ -74,9 +94,25 @@ async function toggleIsSensitive(v) {
 	isSensitive = v;
 }
 
-const headerActions = $computed(() => []);
+const headerActions = $computed(() => [{
+	text: i18n.ts.openInNewTab,
+	icon: 'fas fa-external-link-alt',
+	handler: () => {
+		window.open(file.url, '_blank');
+	},
+}]);
 
-const headerTabs = $computed(() => []);
+const headerTabs = $computed(() => [{
+	active: tab === 'overview',
+	title: i18n.ts.overview,
+	icon: 'fas fa-info-circle',
+	onClick: () => { tab = 'overview'; },
+}, {
+	active: tab === 'raw',
+	title: 'Raw data',
+	icon: 'fas fa-code',
+	onClick: () => { tab = 'raw'; },
+}]);
 
 definePageMetadata(computed(() => ({
 	title: file ? i18n.ts.file + ': ' + file.name : i18n.ts.file,
@@ -87,19 +123,12 @@ definePageMetadata(computed(() => ({
 
 <style lang="scss" scoped>
 .cxqhhsmd {
-	> ._section {
-		> .thumbnail {
-			height: 150px;
-			max-width: 100%;
-		}
+	> .thumbnail {
+		display: block;
 
-		> .info {
-			text-align: center;
-			margin-top: 8px;
-		}
-		
-		> .rawdata {
-			overflow: auto;
+		> .thumbnail {
+			height: 300px;
+			max-width: 100%;
 		}
 	}
 }
diff --git a/packages/client/src/pages/instance-info.vue b/packages/client/src/pages/instance-info.vue
index afee31b44a..cca04aca93 100644
--- a/packages/client/src/pages/instance-info.vue
+++ b/packages/client/src/pages/instance-info.vue
@@ -73,7 +73,7 @@
 				<FormLink :to="`https://${host}/manifest.json`" external style="margin-bottom: 8px;">manifest.json</FormLink>
 			</FormSection>
 		</div>
-		<div v-if="tab === 'chart'" class="_formRoot">
+		<div v-else-if="tab === 'chart'" class="_formRoot">
 			<div class="cmhjzshl">
 				<div class="selects">
 					<MkSelect v-model="chartSrc" style="margin: 0 10px 0 0; flex: 1;">
@@ -98,7 +98,7 @@
 				</div>
 			</div>
 		</div>
-		<div v-if="tab === 'raw'" class="_formRoot">
+		<div v-else-if="tab === 'raw'" class="_formRoot">
 			<MkObjectView tall :value="instance">
 			</MkObjectView>
 		</div>
@@ -130,11 +130,11 @@ const props = defineProps<{
 }>();
 
 let tab = $ref('overview');
+let chartSrc = $ref('instance-requests');
 let meta = $ref<misskey.entities.DetailedInstanceMetadata | null>(null);
 let instance = $ref<misskey.entities.Instance | null>(null);
 let suspended = $ref(false);
 let isBlocked = $ref(false);
-let chartSrc = $ref('instance-requests');
 
 async function fetch() {
 	if (iAmModerator) {
diff --git a/packages/client/src/pages/user-info.vue b/packages/client/src/pages/user-info.vue
index 996c018dd9..233a8857fc 100644
--- a/packages/client/src/pages/user-info.vue
+++ b/packages/client/src/pages/user-info.vue
@@ -3,14 +3,18 @@
 	<template #header><MkPageHeader :actions="headerActions" :tabs="headerTabs"/></template>
 	<MkSpacer :content-max="500" :margin-min="16" :margin-max="32">
 		<FormSuspense :p="init">
-			<div class="_formRoot">
+			<div v-if="tab === 'overview'" class="_formRoot">
 				<div class="_formBlock aeakzknw">
 					<MkAvatar class="avatar" :user="user" :show-indicator="true"/>
 				</div>
 
-				<FormLink class="_formBlock" :to="userPage(user)">Profile</FormLink>
+				<div v-if="user.url" class="_formLinksGrid _formBlock">
+					<FormLink :to="userPage(user)">Profile</FormLink>
+					<FormLink :to="user.url" :external="true">Profile (remote)</FormLink>
+				</div>
+				<FormLink v-else class="_formBlock" :to="userPage(user)">Profile</FormLink>
 
-				<FormLink v-if="user.url" class="_formBlock" :to="user.url" :external="true">Profile (remote)</FormLink>
+				<FormLink v-if="user.host" class="_formBlock" :to="`/instance-info/${user.host}`">{{ i18n.ts.instanceInfo }}</FormLink>
 
 				<div class="_formBlock">
 					<MkKeyValue :copy="acct(user)" oneline style="margin: 1em 0;">
@@ -57,7 +61,23 @@
 
 					<FormButton v-if="user.host != null" class="_formBlock" @click="updateRemoteUser"><i class="fas fa-sync"></i> {{ $ts.updateRemoteUser }}</FormButton>
 				</FormSection>
-
+			</div>
+			<div v-else-if="tab === 'chart'" class="_formRoot">
+				<div class="cmhjzshm">
+					<div class="selects">
+						<MkSelect v-model="chartSrc" style="margin: 0 10px 0 0; flex: 1;">
+							<option value="per-user-notes">{{ $ts.notes }}</option>
+						</MkSelect>
+					</div>
+					<div class="charts">
+						<div class="label">{{ i18n.t('recentNHours', { n: 90 }) }}</div>
+						<MkChart class="chart" :src="chartSrc" span="hour" :limit="90" :args="{ user, withoutAll: true }" :detailed="true"></MkChart>
+						<div class="label">{{ i18n.t('recentNDays', { n: 90 }) }}</div>
+						<MkChart class="chart" :src="chartSrc" span="day" :limit="90" :args="{ user, withoutAll: true }" :detailed="true"></MkChart>
+					</div>
+				</div>
+			</div>
+			<div v-else-if="tab === 'raw'" class="_formRoot">
 				<MkObjectView v-if="info && $i.isAdmin" tall :value="info">
 				</MkObjectView>
 
@@ -72,6 +92,7 @@
 <script lang="ts" setup>
 import { computed, defineAsyncComponent, defineComponent, watch } from 'vue';
 import * as misskey from 'misskey-js';
+import MkChart from '@/components/chart.vue';
 import MkObjectView from '@/components/object-view.vue';
 import FormTextarea from '@/components/form/textarea.vue';
 import FormSwitch from '@/components/form/switch.vue';
@@ -79,6 +100,7 @@ import FormLink from '@/components/form/link.vue';
 import FormSection from '@/components/form/section.vue';
 import FormButton from '@/components/ui/button.vue';
 import MkKeyValue from '@/components/key-value.vue';
+import MkSelect from '@/components/form/select.vue';
 import FormSuspense from '@/components/form/suspense.vue';
 import * as os from '@/os';
 import number from '@/filters/number';
@@ -93,6 +115,8 @@ const props = defineProps<{
 	userId: string;
 }>();
 
+let tab = $ref('overview');
+let chartSrc = $ref('per-user-notes');
 let user = $ref<null | misskey.entities.UserDetailed>();
 let init = $ref();
 let info = $ref();
@@ -209,7 +233,22 @@ watch(() => user, () => {
 
 const headerActions = $computed(() => []);
 
-const headerTabs = $computed(() => []);
+const headerTabs = $computed(() => [{
+	active: tab === 'overview',
+	title: i18n.ts.overview,
+	icon: 'fas fa-info-circle',
+	onClick: () => { tab = 'overview'; },
+}, {
+	active: tab === 'chart',
+	title: i18n.ts.charts,
+	icon: 'fas fa-chart-simple',
+	onClick: () => { tab = 'chart'; },
+}, {
+	active: tab === 'raw',
+	title: 'Raw data',
+	icon: 'fas fa-code',
+	onClick: () => { tab = 'raw'; },
+}]);
 
 definePageMetadata(computed(() => ({
 	title: user ? acct(user) : i18n.ts.userInfo,
@@ -226,4 +265,18 @@ definePageMetadata(computed(() => ({
 		height: 64px;
 	}
 }
+
+.cmhjzshm {
+	> .selects {
+		display: flex;
+		margin: 0 0 16px 0;
+	}
+
+	> .charts {
+		> .label {
+			margin-bottom: 12px;
+			font-weight: bold;
+		}
+	}
+}
 </style>