diff --git a/packages/backend/src/core/CoreModule.ts b/packages/backend/src/core/CoreModule.ts
index c31cef36e839c70506cc60a44f6986728bb214bd..2c27d33c0649364e2db91ed19009c03f80311606 100644
--- a/packages/backend/src/core/CoreModule.ts
+++ b/packages/backend/src/core/CoreModule.ts
@@ -116,6 +116,7 @@ import { FlashEntityService } from './entities/FlashEntityService.js';
 import { FlashLikeEntityService } from './entities/FlashLikeEntityService.js';
 import { RoleEntityService } from './entities/RoleEntityService.js';
 import { ReversiGameEntityService } from './entities/ReversiGameEntityService.js';
+import { MetaEntityService } from './entities/MetaEntityService.js';
 
 import { ApAudienceService } from './activitypub/ApAudienceService.js';
 import { ApDbResolverService } from './activitypub/ApDbResolverService.js';
@@ -254,6 +255,7 @@ const $FlashEntityService: Provider = { provide: 'FlashEntityService', useExisti
 const $FlashLikeEntityService: Provider = { provide: 'FlashLikeEntityService', useExisting: FlashLikeEntityService };
 const $RoleEntityService: Provider = { provide: 'RoleEntityService', useExisting: RoleEntityService };
 const $ReversiGameEntityService: Provider = { provide: 'ReversiGameEntityService', useExisting: ReversiGameEntityService };
+const $MetaEntityService: Provider = { provide: 'MetaEntityService', useExisting: MetaEntityService };
 
 const $ApAudienceService: Provider = { provide: 'ApAudienceService', useExisting: ApAudienceService };
 const $ApDbResolverService: Provider = { provide: 'ApDbResolverService', useExisting: ApDbResolverService };
@@ -393,6 +395,7 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
 		FlashLikeEntityService,
 		RoleEntityService,
 		ReversiGameEntityService,
+		MetaEntityService,
 
 		ApAudienceService,
 		ApDbResolverService,
@@ -528,6 +531,7 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
 		$FlashLikeEntityService,
 		$RoleEntityService,
 		$ReversiGameEntityService,
+		$MetaEntityService,
 
 		$ApAudienceService,
 		$ApDbResolverService,
@@ -663,6 +667,7 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
 		FlashLikeEntityService,
 		RoleEntityService,
 		ReversiGameEntityService,
+		MetaEntityService,
 
 		ApAudienceService,
 		ApDbResolverService,
@@ -797,6 +802,7 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
 		$FlashLikeEntityService,
 		$RoleEntityService,
 		$ReversiGameEntityService,
+		$MetaEntityService,
 
 		$ApAudienceService,
 		$ApDbResolverService,
diff --git a/packages/backend/src/core/entities/MetaEntityService.ts b/packages/backend/src/core/entities/MetaEntityService.ts
new file mode 100644
index 0000000000000000000000000000000000000000..b50d76288f273955d53fc722a35801d64b1fcca9
--- /dev/null
+++ b/packages/backend/src/core/entities/MetaEntityService.ts
@@ -0,0 +1,154 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { Brackets } from 'typeorm';
+import { Inject, Injectable } from '@nestjs/common';
+import JSON5 from 'json5';
+import type { Packed } from '@/misc/json-schema.js';
+import type { MiMeta } from '@/models/Meta.js';
+import type { AdsRepository } from '@/models/_.js';
+import { MAX_NOTE_TEXT_LENGTH } from '@/const.js';
+import { MetaService } from '@/core/MetaService.js';
+import { bindThis } from '@/decorators.js';
+import { UserEntityService } from '@/core/entities/UserEntityService.js';
+import { InstanceActorService } from '@/core/InstanceActorService.js';
+import type { Config } from '@/config.js';
+import { DI } from '@/di-symbols.js';
+import { DEFAULT_POLICIES } from '@/core/RoleService.js';
+
+@Injectable()
+export class MetaEntityService {
+	constructor(
+		@Inject(DI.config)
+		private config: Config,
+
+		@Inject(DI.adsRepository)
+		private adsRepository: AdsRepository,
+
+		private userEntityService: UserEntityService,
+		private metaService: MetaService,
+		private instanceActorService: InstanceActorService,
+	) { }
+
+	@bindThis
+	public async pack(meta?: MiMeta): Promise<Packed<'MetaLite'>> {
+		let instance = meta;
+
+		if (!instance) {
+			instance = await this.metaService.fetch();
+		}
+
+		const ads = await this.adsRepository.createQueryBuilder('ads')
+			.where('ads.expiresAt > :now', { now: new Date() })
+			.andWhere('ads.startsAt <= :now', { now: new Date() })
+			.andWhere(new Brackets(qb => {
+				// 曜日のビットフラグを確認する
+				qb.where('ads.dayOfWeek & :dayOfWeek > 0', { dayOfWeek: 1 << new Date().getDay() })
+					.orWhere('ads.dayOfWeek = 0');
+			}))
+			.getMany();
+
+		const packed: Packed<'MetaLite'> = {
+			maintainerName: instance.maintainerName,
+			maintainerEmail: instance.maintainerEmail,
+
+			version: this.config.version,
+			providesTarball: this.config.publishTarballInsteadOfProvideRepositoryUrl,
+
+			name: instance.name,
+			shortName: instance.shortName,
+			uri: this.config.url,
+			description: instance.description,
+			langs: instance.langs,
+			tosUrl: instance.termsOfServiceUrl,
+			repositoryUrl: instance.repositoryUrl,
+			feedbackUrl: instance.feedbackUrl,
+			impressumUrl: instance.impressumUrl,
+			privacyPolicyUrl: instance.privacyPolicyUrl,
+			disableRegistration: instance.disableRegistration,
+			emailRequiredForSignup: instance.emailRequiredForSignup,
+			enableHcaptcha: instance.enableHcaptcha,
+			hcaptchaSiteKey: instance.hcaptchaSiteKey,
+			enableMcaptcha: instance.enableMcaptcha,
+			mcaptchaSiteKey: instance.mcaptchaSitekey,
+			mcaptchaInstanceUrl: instance.mcaptchaInstanceUrl,
+			enableRecaptcha: instance.enableRecaptcha,
+			recaptchaSiteKey: instance.recaptchaSiteKey,
+			enableTurnstile: instance.enableTurnstile,
+			turnstileSiteKey: instance.turnstileSiteKey,
+			swPublickey: instance.swPublicKey,
+			themeColor: instance.themeColor,
+			mascotImageUrl: instance.mascotImageUrl ?? '/assets/ai.png',
+			bannerUrl: instance.bannerUrl,
+			infoImageUrl: instance.infoImageUrl,
+			serverErrorImageUrl: instance.serverErrorImageUrl,
+			notFoundImageUrl: instance.notFoundImageUrl,
+			iconUrl: instance.iconUrl,
+			backgroundImageUrl: instance.backgroundImageUrl,
+			logoImageUrl: instance.logoImageUrl,
+			maxNoteTextLength: MAX_NOTE_TEXT_LENGTH,
+			// クライアントの手間を減らすためあらかじめJSONに変換しておく
+			defaultLightTheme: instance.defaultLightTheme ? JSON.stringify(JSON5.parse(instance.defaultLightTheme)) : null,
+			defaultDarkTheme: instance.defaultDarkTheme ? JSON.stringify(JSON5.parse(instance.defaultDarkTheme)) : null,
+			ads: ads.map(ad => ({
+				id: ad.id,
+				url: ad.url,
+				place: ad.place,
+				ratio: ad.ratio,
+				imageUrl: ad.imageUrl,
+				dayOfWeek: ad.dayOfWeek,
+			})),
+			notesPerOneAd: instance.notesPerOneAd,
+			enableEmail: instance.enableEmail,
+			enableServiceWorker: instance.enableServiceWorker,
+
+			translatorAvailable: instance.deeplAuthKey != null,
+
+			serverRules: instance.serverRules,
+
+			policies: { ...DEFAULT_POLICIES, ...instance.policies },
+
+			mediaProxy: this.config.mediaProxy,
+		};
+
+		return packed;
+	}
+
+	@bindThis
+	public async packDetailed(meta?: MiMeta): Promise<Packed<'MetaDetailed'>> {
+		let instance = meta;
+
+		if (!instance) {
+			instance = await this.metaService.fetch();
+		}
+
+		const packed = await this.pack(instance);
+
+		const proxyAccount = instance.proxyAccountId ? await this.userEntityService.pack(instance.proxyAccountId).catch(() => null) : null;
+
+		const packDetailed: Packed<'MetaDetailed'> = {
+			...packed,
+			cacheRemoteFiles: instance.cacheRemoteFiles,
+			cacheRemoteSensitiveFiles: instance.cacheRemoteSensitiveFiles,
+			requireSetup: !await this.instanceActorService.realLocalUsersPresent(),
+			proxyAccountName: proxyAccount ? proxyAccount.username : null,
+			features: {
+				localTimeline: instance.policies.ltlAvailable,
+				globalTimeline: instance.policies.gtlAvailable,
+				registration: !instance.disableRegistration,
+				emailRequiredForSignup: instance.emailRequiredForSignup,
+				hcaptcha: instance.enableHcaptcha,
+				recaptcha: instance.enableRecaptcha,
+				turnstile: instance.enableTurnstile,
+				objectStorage: instance.useObjectStorage,
+				serviceWorker: instance.enableServiceWorker,
+				miauth: true,
+			},
+		};
+
+		return packDetailed;
+	}
+}
+
diff --git a/packages/backend/src/misc/json-schema.ts b/packages/backend/src/misc/json-schema.ts
index de38f145b24ec976562336f16fd02a7fdeafbafb..8449e5ff073ab6f5c1407a310b935f9f71c37753 100644
--- a/packages/backend/src/misc/json-schema.ts
+++ b/packages/backend/src/misc/json-schema.ts
@@ -50,6 +50,11 @@ import {
 } from '@/models/json-schema/role.js';
 import { packedAdSchema } from '@/models/json-schema/ad.js';
 import { packedReversiGameLiteSchema, packedReversiGameDetailedSchema } from '@/models/json-schema/reversi-game.js';
+import {
+	packedMetaLiteSchema,
+	packedMetaDetailedOnlySchema,
+	packedMetaDetailedSchema,
+} from '@/models/json-schema/meta.js';
 
 export const refs = {
 	UserLite: packedUserLiteSchema,
@@ -99,6 +104,9 @@ export const refs = {
 	RolePolicies: packedRolePoliciesSchema,
 	ReversiGameLite: packedReversiGameLiteSchema,
 	ReversiGameDetailed: packedReversiGameDetailedSchema,
+	MetaLite: packedMetaLiteSchema,
+	MetaDetailedOnly: packedMetaDetailedOnlySchema,
+	MetaDetailed: packedMetaDetailedSchema,
 };
 
 export type Packed<x extends keyof typeof refs> = SchemaType<typeof refs[x]>;
diff --git a/packages/backend/src/models/json-schema/meta.ts b/packages/backend/src/models/json-schema/meta.ts
new file mode 100644
index 0000000000000000000000000000000000000000..17789f3b46ce8a3fff176c785e89b22bffb8681d
--- /dev/null
+++ b/packages/backend/src/models/json-schema/meta.ts
@@ -0,0 +1,328 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+export const packedMetaLiteSchema = {
+	type: 'object',
+	optional: false, nullable: false,
+	properties: {
+		maintainerName: {
+			type: 'string',
+			optional: false, nullable: true,
+		},
+		maintainerEmail: {
+			type: 'string',
+			optional: false, nullable: true,
+		},
+		version: {
+			type: 'string',
+			optional: false, nullable: false,
+		},
+		providesTarball: {
+			type: 'boolean',
+			optional: false, nullable: false,
+		},
+		name: {
+			type: 'string',
+			optional: false, nullable: true,
+		},
+		shortName: {
+			type: 'string',
+			optional: false, nullable: true,
+		},
+		uri: {
+			type: 'string',
+			optional: false, nullable: false,
+			format: 'url',
+			example: 'https://misskey.example.com',
+		},
+		description: {
+			type: 'string',
+			optional: false, nullable: true,
+		},
+		langs: {
+			type: 'array',
+			optional: false, nullable: false,
+			items: {
+				type: 'string',
+				optional: false, nullable: false,
+			},
+		},
+		tosUrl: {
+			type: 'string',
+			optional: false, nullable: true,
+		},
+		repositoryUrl: {
+			type: 'string',
+			optional: false, nullable: true,
+			default: 'https://github.com/misskey-dev/misskey',
+		},
+		feedbackUrl: {
+			type: 'string',
+			optional: false, nullable: true,
+			default: 'https://github.com/misskey-dev/misskey/issues/new',
+		},
+		defaultDarkTheme: {
+			type: 'string',
+			optional: false, nullable: true,
+		},
+		defaultLightTheme: {
+			type: 'string',
+			optional: false, nullable: true,
+		},
+		disableRegistration: {
+			type: 'boolean',
+			optional: false, nullable: false,
+		},
+		emailRequiredForSignup: {
+			type: 'boolean',
+			optional: false, nullable: false,
+		},
+		enableHcaptcha: {
+			type: 'boolean',
+			optional: false, nullable: false,
+		},
+		hcaptchaSiteKey: {
+			type: 'string',
+			optional: false, nullable: true,
+		},
+		enableMcaptcha: {
+			type: 'boolean',
+			optional: false, nullable: false,
+		},
+		mcaptchaSiteKey: {
+			type: 'string',
+			optional: false, nullable: true,
+		},
+		mcaptchaInstanceUrl: {
+			type: 'string',
+			optional: false, nullable: true,
+		},
+		enableRecaptcha: {
+			type: 'boolean',
+			optional: false, nullable: false,
+		},
+		recaptchaSiteKey: {
+			type: 'string',
+			optional: false, nullable: true,
+		},
+		enableTurnstile: {
+			type: 'boolean',
+			optional: false, nullable: false,
+		},
+		turnstileSiteKey: {
+			type: 'string',
+			optional: false, nullable: true,
+		},
+		swPublickey: {
+			type: 'string',
+			optional: false, nullable: true,
+		},
+		mascotImageUrl: {
+			type: 'string',
+			optional: false, nullable: false,
+			default: '/assets/ai.png',
+		},
+		bannerUrl: {
+			type: 'string',
+			optional: false, nullable: true,
+		},
+		serverErrorImageUrl: {
+			type: 'string',
+			optional: false, nullable: true,
+		},
+		infoImageUrl: {
+			type: 'string',
+			optional: false, nullable: true,
+		},
+		notFoundImageUrl: {
+			type: 'string',
+			optional: false, nullable: true,
+		},
+		iconUrl: {
+			type: 'string',
+			optional: false, nullable: true,
+		},
+		maxNoteTextLength: {
+			type: 'number',
+			optional: false, nullable: false,
+		},
+		ads: {
+			type: 'array',
+			optional: false, nullable: false,
+			items: {
+				type: 'object',
+				optional: false, nullable: false,
+				properties: {
+					id: {
+						type: 'string',
+						optional: false, nullable: false,
+						format: 'id',
+						example: 'xxxxxxxxxx',
+					},
+					url: {
+						type: 'string',
+						optional: false, nullable: false,
+						format: 'url',
+					},
+					place: {
+						type: 'string',
+						optional: false, nullable: false,
+					},
+					ratio: {
+						type: 'number',
+						optional: false, nullable: false,
+					},
+					imageUrl: {
+						type: 'string',
+						optional: false, nullable: false,
+						format: 'url',
+					},
+					dayOfWeek: {
+						type: 'integer',
+						optional: false, nullable: false,
+					},
+				},
+			},
+		},
+		notesPerOneAd: {
+			type: 'number',
+			optional: false, nullable: false,
+			default: 0,
+		},
+		enableEmail: {
+			type: 'boolean',
+			optional: false, nullable: false,
+		},
+		enableServiceWorker: {
+			type: 'boolean',
+			optional: false, nullable: false,
+		},
+		translatorAvailable: {
+			type: 'boolean',
+			optional: false, nullable: false,
+		},
+		mediaProxy: {
+			type: 'string',
+			optional: false, nullable: false,
+		},
+		backgroundImageUrl: {
+			type: 'string',
+			optional: false, nullable: true,
+		},
+		impressumUrl: {
+			type: 'string',
+			optional: false, nullable: true,
+		},
+		logoImageUrl: {
+			type: 'string',
+			optional: false, nullable: true,
+		},
+		privacyPolicyUrl: {
+			type: 'string',
+			optional: false, nullable: true,
+		},
+		serverRules: {
+			type: 'array',
+			optional: false, nullable: false,
+			items: {
+				type: 'string',
+			},
+		},
+		themeColor: {
+			type: 'string',
+			optional: false, nullable: true,
+		},
+		policies: {
+			type: 'object',
+			optional: false, nullable: false,
+			ref: 'RolePolicies',
+		},
+	},
+} as const;
+
+export const packedMetaDetailedOnlySchema = {
+	type: 'object',
+	optional: false, nullable: false,
+	properties: {
+		features: {
+			type: 'object',
+			optional: true, nullable: false,
+			properties: {
+				registration: {
+					type: 'boolean',
+					optional: false, nullable: false,
+				},
+				emailRequiredForSignup: {
+					type: 'boolean',
+					optional: false, nullable: false,
+				},
+				localTimeline: {
+					type: 'boolean',
+					optional: false, nullable: false,
+				},
+				globalTimeline: {
+					type: 'boolean',
+					optional: false, nullable: false,
+				},
+				hcaptcha: {
+					type: 'boolean',
+					optional: false, nullable: false,
+				},
+				turnstile: {
+					type: 'boolean',
+					optional: false, nullable: false,
+				},
+				recaptcha: {
+					type: 'boolean',
+					optional: false, nullable: false,
+				},
+				objectStorage: {
+					type: 'boolean',
+					optional: false, nullable: false,
+				},
+				serviceWorker: {
+					type: 'boolean',
+					optional: false, nullable: false,
+				},
+				miauth: {
+					type: 'boolean',
+					optional: true, nullable: false,
+					default: true,
+				},
+			},
+		},
+		proxyAccountName: {
+			type: 'string',
+			optional: false, nullable: true,
+		},
+		requireSetup: {
+			type: 'boolean',
+			optional: false, nullable: false,
+			example: false,
+		},
+		cacheRemoteFiles: {
+			type: 'boolean',
+			optional: false, nullable: false,
+		},
+		cacheRemoteSensitiveFiles: {
+			type: 'boolean',
+			optional: false, nullable: false,
+		},
+	},
+} as const;
+
+export const packedMetaDetailedSchema = {
+	type: 'object',
+	allOf: [
+		{
+			type: 'object',
+			ref: 'MetaLite',
+		},
+		{
+			type: 'object',
+			ref: 'MetaDetailedOnly',
+		},
+	],
+} as const;
diff --git a/packages/backend/src/server/api/endpoints/meta.ts b/packages/backend/src/server/api/endpoints/meta.ts
index 834158baf41a0f1dd61df322e8997756e888f471..5460635e1d406dc4a02bc06ecf5951fd6c757074 100644
--- a/packages/backend/src/server/api/endpoints/meta.ts
+++ b/packages/backend/src/server/api/endpoints/meta.ts
@@ -3,18 +3,9 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { IsNull, LessThanOrEqual, MoreThan, Brackets } from 'typeorm';
-import { Inject, Injectable } from '@nestjs/common';
-import JSON5 from 'json5';
-import type { AdsRepository } from '@/models/_.js';
-import { MAX_NOTE_TEXT_LENGTH } from '@/const.js';
+import { Injectable } from '@nestjs/common';
 import { Endpoint } from '@/server/api/endpoint-base.js';
-import { UserEntityService } from '@/core/entities/UserEntityService.js';
-import { MetaService } from '@/core/MetaService.js';
-import { InstanceActorService } from '@/core/InstanceActorService.js';
-import type { Config } from '@/config.js';
-import { DI } from '@/di-symbols.js';
-import { DEFAULT_POLICIES } from '@/core/RoleService.js';
+import { MetaEntityService } from '@/core/entities/MetaEntityService.js';
 
 export const meta = {
 	tags: ['meta'],
@@ -23,297 +14,10 @@ export const meta = {
 
 	res: {
 		type: 'object',
-		optional: false, nullable: false,
-		properties: {
-			maintainerName: {
-				type: 'string',
-				optional: false, nullable: true,
-			},
-			maintainerEmail: {
-				type: 'string',
-				optional: false, nullable: true,
-			},
-			version: {
-				type: 'string',
-				optional: false, nullable: false,
-			},
-			providesTarball: {
-				type: 'boolean',
-				optional: false, nullable: false,
-			},
-			name: {
-				type: 'string',
-				optional: false, nullable: false,
-			},
-			shortName: {
-				type: 'string',
-				optional: false, nullable: true,
-			},
-			uri: {
-				type: 'string',
-				optional: false, nullable: false,
-				format: 'url',
-				example: 'https://misskey.example.com',
-			},
-			description: {
-				type: 'string',
-				optional: false, nullable: true,
-			},
-			langs: {
-				type: 'array',
-				optional: false, nullable: false,
-				items: {
-					type: 'string',
-					optional: false, nullable: false,
-				},
-			},
-			tosUrl: {
-				type: 'string',
-				optional: false, nullable: true,
-			},
-			repositoryUrl: {
-				type: 'string',
-				optional: false, nullable: true,
-				default: 'https://github.com/misskey-dev/misskey',
-			},
-			feedbackUrl: {
-				type: 'string',
-				optional: false, nullable: true,
-				default: 'https://github.com/misskey-dev/misskey/issues/new',
-			},
-			defaultDarkTheme: {
-				type: 'string',
-				optional: false, nullable: true,
-			},
-			defaultLightTheme: {
-				type: 'string',
-				optional: false, nullable: true,
-			},
-			disableRegistration: {
-				type: 'boolean',
-				optional: false, nullable: false,
-			},
-			cacheRemoteFiles: {
-				type: 'boolean',
-				optional: false, nullable: false,
-			},
-			cacheRemoteSensitiveFiles: {
-				type: 'boolean',
-				optional: false, nullable: false,
-			},
-			emailRequiredForSignup: {
-				type: 'boolean',
-				optional: false, nullable: false,
-			},
-			enableHcaptcha: {
-				type: 'boolean',
-				optional: false, nullable: false,
-			},
-			hcaptchaSiteKey: {
-				type: 'string',
-				optional: false, nullable: true,
-			},
-			enableMcaptcha: {
-				type: 'boolean',
-				optional: false, nullable: false,
-			},
-			mcaptchaSiteKey: {
-				type: 'string',
-				optional: false, nullable: true,
-			},
-			mcaptchaInstanceUrl: {
-				type: 'string',
-				optional: false, nullable: true,
-			},
-			enableRecaptcha: {
-				type: 'boolean',
-				optional: false, nullable: false,
-			},
-			recaptchaSiteKey: {
-				type: 'string',
-				optional: false, nullable: true,
-			},
-			enableTurnstile: {
-				type: 'boolean',
-				optional: false, nullable: false,
-			},
-			turnstileSiteKey: {
-				type: 'string',
-				optional: false, nullable: true,
-			},
-			swPublickey: {
-				type: 'string',
-				optional: false, nullable: true,
-			},
-			mascotImageUrl: {
-				type: 'string',
-				optional: false, nullable: false,
-				default: '/assets/ai.png',
-			},
-			bannerUrl: {
-				type: 'string',
-				optional: false, nullable: false,
-			},
-			serverErrorImageUrl: {
-				type: 'string',
-				optional: false, nullable: true,
-			},
-			infoImageUrl: {
-				type: 'string',
-				optional: false, nullable: true,
-			},
-			notFoundImageUrl: {
-				type: 'string',
-				optional: false, nullable: true,
-			},
-			iconUrl: {
-				type: 'string',
-				optional: false, nullable: true,
-			},
-			maxNoteTextLength: {
-				type: 'number',
-				optional: false, nullable: false,
-			},
-			ads: {
-				type: 'array',
-				optional: false, nullable: false,
-				items: {
-					type: 'object',
-					optional: false, nullable: false,
-					properties: {
-						id: {
-							type: 'string',
-							optional: false, nullable: false,
-							format: 'id',
-							example: 'xxxxxxxxxx',
-						},
-						url: {
-							type: 'string',
-							optional: false, nullable: false,
-							format: 'url',
-						},
-						place: {
-							type: 'string',
-							optional: false, nullable: false,
-						},
-						ratio: {
-							type: 'number',
-							optional: false, nullable: false,
-						},
-						imageUrl: {
-							type: 'string',
-							optional: false, nullable: false,
-							format: 'url',
-						},
-						dayOfWeek: {
-							type: 'integer',
-							optional: false, nullable: false,
-						},
-					},
-				},
-			},
-			notesPerOneAd: {
-				type: 'number',
-				optional: false, nullable: false,
-				default: 0,
-			},
-			requireSetup: {
-				type: 'boolean',
-				optional: false, nullable: false,
-				example: false,
-			},
-			enableEmail: {
-				type: 'boolean',
-				optional: false, nullable: false,
-			},
-			enableServiceWorker: {
-				type: 'boolean',
-				optional: false, nullable: false,
-			},
-			translatorAvailable: {
-				type: 'boolean',
-				optional: false, nullable: false,
-			},
-			proxyAccountName: {
-				type: 'string',
-				optional: false, nullable: true,
-			},
-			mediaProxy: {
-				type: 'string',
-				optional: false, nullable: false,
-			},
-			features: {
-				type: 'object',
-				optional: true, nullable: false,
-				properties: {
-					registration: {
-						type: 'boolean',
-						optional: false, nullable: false,
-					},
-					localTimeline: {
-						type: 'boolean',
-						optional: false, nullable: false,
-					},
-					globalTimeline: {
-						type: 'boolean',
-						optional: false, nullable: false,
-					},
-					hcaptcha: {
-						type: 'boolean',
-						optional: false, nullable: false,
-					},
-					recaptcha: {
-						type: 'boolean',
-						optional: false, nullable: false,
-					},
-					objectStorage: {
-						type: 'boolean',
-						optional: false, nullable: false,
-					},
-					serviceWorker: {
-						type: 'boolean',
-						optional: false, nullable: false,
-					},
-					miauth: {
-						type: 'boolean',
-						optional: true, nullable: false,
-						default: true,
-					},
-				},
-			},
-			backgroundImageUrl: {
-				type: 'string',
-				optional: false, nullable: true,
-			},
-			impressumUrl: {
-				type: 'string',
-				optional: false, nullable: true,
-			},
-			logoImageUrl: {
-				type: 'string',
-				optional: false, nullable: true,
-			},
-			privacyPolicyUrl: {
-				type: 'string',
-				optional: false, nullable: true,
-			},
-			serverRules: {
-				type: 'array',
-				optional: false, nullable: false,
-				items: {
-					type: 'string',
-				},
-			},
-			themeColor: {
-				type: 'string',
-				optional: false, nullable: true,
-			},
-			policies: {
-				type: 'object',
-				optional: false, nullable: false,
-				ref: 'RolePolicies',
-			},
-		},
+		oneOf: [
+			{ type: 'object', ref: 'MetaLite' },
+			{ type: 'object', ref: 'MetaDetailed' },
+		],
 	},
 } as const;
 
@@ -328,115 +32,10 @@ export const paramDef = {
 @Injectable()
 export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-disable-line import/no-default-export
 	constructor(
-		@Inject(DI.config)
-		private config: Config,
-
-		@Inject(DI.adsRepository)
-		private adsRepository: AdsRepository,
-
-		private userEntityService: UserEntityService,
-		private metaService: MetaService,
-		private instanceActorService: InstanceActorService,
+		private metaEntityService: MetaEntityService,
 	) {
 		super(meta, paramDef, async (ps, me) => {
-			const instance = await this.metaService.fetch(true);
-
-			const ads = await this.adsRepository.createQueryBuilder('ads')
-				.where('ads.expiresAt > :now', { now: new Date() })
-				.andWhere('ads.startsAt <= :now', { now: new Date() })
-				.andWhere(new Brackets(qb => {
-					// 曜日のビットフラグを確認する
-					qb.where('ads.dayOfWeek & :dayOfWeek > 0', { dayOfWeek: 1 << new Date().getDay() })
-						.orWhere('ads.dayOfWeek = 0');
-				}))
-				.getMany();
-
-			const response: any = {
-				maintainerName: instance.maintainerName,
-				maintainerEmail: instance.maintainerEmail,
-
-				version: this.config.version,
-				providesTarball: this.config.publishTarballInsteadOfProvideRepositoryUrl,
-
-				name: instance.name,
-				shortName: instance.shortName,
-				uri: this.config.url,
-				description: instance.description,
-				langs: instance.langs,
-				tosUrl: instance.termsOfServiceUrl,
-				repositoryUrl: instance.repositoryUrl,
-				feedbackUrl: instance.feedbackUrl,
-				impressumUrl: instance.impressumUrl,
-				privacyPolicyUrl: instance.privacyPolicyUrl,
-				disableRegistration: instance.disableRegistration,
-				emailRequiredForSignup: instance.emailRequiredForSignup,
-				enableHcaptcha: instance.enableHcaptcha,
-				hcaptchaSiteKey: instance.hcaptchaSiteKey,
-				enableMcaptcha: instance.enableMcaptcha,
-				mcaptchaSiteKey: instance.mcaptchaSitekey,
-				mcaptchaInstanceUrl: instance.mcaptchaInstanceUrl,
-				enableRecaptcha: instance.enableRecaptcha,
-				recaptchaSiteKey: instance.recaptchaSiteKey,
-				enableTurnstile: instance.enableTurnstile,
-				turnstileSiteKey: instance.turnstileSiteKey,
-				swPublickey: instance.swPublicKey,
-				themeColor: instance.themeColor,
-				mascotImageUrl: instance.mascotImageUrl,
-				bannerUrl: instance.bannerUrl,
-				infoImageUrl: instance.infoImageUrl,
-				serverErrorImageUrl: instance.serverErrorImageUrl,
-				notFoundImageUrl: instance.notFoundImageUrl,
-				iconUrl: instance.iconUrl,
-				backgroundImageUrl: instance.backgroundImageUrl,
-				logoImageUrl: instance.logoImageUrl,
-				maxNoteTextLength: MAX_NOTE_TEXT_LENGTH,
-				// クライアントの手間を減らすためあらかじめJSONに変換しておく
-				defaultLightTheme: instance.defaultLightTheme ? JSON.stringify(JSON5.parse(instance.defaultLightTheme)) : null,
-				defaultDarkTheme: instance.defaultDarkTheme ? JSON.stringify(JSON5.parse(instance.defaultDarkTheme)) : null,
-				ads: ads.map(ad => ({
-					id: ad.id,
-					url: ad.url,
-					place: ad.place,
-					ratio: ad.ratio,
-					imageUrl: ad.imageUrl,
-					dayOfWeek: ad.dayOfWeek,
-				})),
-				notesPerOneAd: instance.notesPerOneAd,
-				enableEmail: instance.enableEmail,
-				enableServiceWorker: instance.enableServiceWorker,
-
-				translatorAvailable: instance.deeplAuthKey != null,
-
-				serverRules: instance.serverRules,
-
-				policies: { ...DEFAULT_POLICIES, ...instance.policies },
-
-				mediaProxy: this.config.mediaProxy,
-
-				...(ps.detail ? {
-					cacheRemoteFiles: instance.cacheRemoteFiles,
-					cacheRemoteSensitiveFiles: instance.cacheRemoteSensitiveFiles,
-					requireSetup: !await this.instanceActorService.realLocalUsersPresent(),
-				} : {}),
-			};
-
-			if (ps.detail) {
-				const proxyAccount = instance.proxyAccountId ? await this.userEntityService.pack(instance.proxyAccountId).catch(() => null) : null;
-
-				response.proxyAccountName = proxyAccount ? proxyAccount.username : null;
-				response.features = {
-					registration: !instance.disableRegistration,
-					emailRequiredForSignup: instance.emailRequiredForSignup,
-					hcaptcha: instance.enableHcaptcha,
-					recaptcha: instance.enableRecaptcha,
-					turnstile: instance.enableTurnstile,
-					objectStorage: instance.useObjectStorage,
-					serviceWorker: instance.enableServiceWorker,
-					miauth: true,
-				};
-			}
-
-			return response;
+			return ps.detail ? await this.metaEntityService.packDetailed() : await this.metaEntityService.pack();
 		});
 	}
 }
diff --git a/packages/backend/src/server/web/ClientServerService.ts b/packages/backend/src/server/web/ClientServerService.ts
index f255e28fc2b649ff861a37b3d403ceaee23bc57f..e8908f50ec49d172463afa3b161e6c141b608a2d 100644
--- a/packages/backend/src/server/web/ClientServerService.ts
+++ b/packages/backend/src/server/web/ClientServerService.ts
@@ -28,6 +28,7 @@ import type { DbQueue, DeliverQueue, EndedPollNotificationQueue, InboxQueue, Obj
 import { UserEntityService } from '@/core/entities/UserEntityService.js';
 import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
 import { PageEntityService } from '@/core/entities/PageEntityService.js';
+import { MetaEntityService } from '@/core/entities/MetaEntityService.js';
 import { GalleryPostEntityService } from '@/core/entities/GalleryPostEntityService.js';
 import { ClipEntityService } from '@/core/entities/ClipEntityService.js';
 import { ChannelEntityService } from '@/core/entities/ChannelEntityService.js';
@@ -93,6 +94,7 @@ export class ClientServerService {
 		private userEntityService: UserEntityService,
 		private noteEntityService: NoteEntityService,
 		private pageEntityService: PageEntityService,
+		private metaEntityService: MetaEntityService,
 		private galleryPostEntityService: GalleryPostEntityService,
 		private clipEntityService: ClipEntityService,
 		private channelEntityService: ChannelEntityService,
@@ -173,7 +175,7 @@ export class ClientServerService {
 	}
 
 	@bindThis
-	private generateCommonPugData(meta: MiMeta) {
+	private async generateCommonPugData(meta: MiMeta) {
 		return {
 			instanceName: meta.name ?? 'Misskey',
 			icon: meta.iconUrl,
@@ -183,6 +185,8 @@ export class ClientServerService {
 			infoImageUrl: meta.infoImageUrl ?? 'https://xn--931a.moe/assets/info.jpg',
 			notFoundImageUrl: meta.notFoundImageUrl ?? 'https://xn--931a.moe/assets/not-found.jpg',
 			instanceUrl: this.config.url,
+			metaJson: JSON.stringify(await this.metaEntityService.packDetailed(meta)),
+			now: Date.now(),
 		};
 	}
 
@@ -433,7 +437,7 @@ export class ClientServerService {
 				url: this.config.url,
 				title: meta.name ?? 'Misskey',
 				desc: meta.description,
-				...this.generateCommonPugData(meta),
+				...await this.generateCommonPugData(meta),
 			});
 		};
 
@@ -520,7 +524,7 @@ export class ClientServerService {
 					user, profile, me,
 					avatarUrl: user.avatarUrl ?? this.userEntityService.getIdenticonUrl(user),
 					sub: request.params.sub,
-					...this.generateCommonPugData(meta),
+					...await this.generateCommonPugData(meta),
 				});
 			} else {
 				// リモートユーザーなので
@@ -570,7 +574,7 @@ export class ClientServerService {
 					avatarUrl: _note.user.avatarUrl,
 					// TODO: Let locale changeable by instance setting
 					summary: getNoteSummary(_note),
-					...this.generateCommonPugData(meta),
+					...await this.generateCommonPugData(meta),
 				});
 			} else {
 				return await renderBase(reply);
@@ -609,7 +613,7 @@ export class ClientServerService {
 					page: _page,
 					profile,
 					avatarUrl: _page.user.avatarUrl,
-					...this.generateCommonPugData(meta),
+					...await this.generateCommonPugData(meta),
 				});
 			} else {
 				return await renderBase(reply);
@@ -635,7 +639,7 @@ export class ClientServerService {
 					flash: _flash,
 					profile,
 					avatarUrl: _flash.user.avatarUrl,
-					...this.generateCommonPugData(meta),
+					...await this.generateCommonPugData(meta),
 				});
 			} else {
 				return await renderBase(reply);
@@ -661,7 +665,7 @@ export class ClientServerService {
 					clip: _clip,
 					profile,
 					avatarUrl: _clip.user.avatarUrl,
-					...this.generateCommonPugData(meta),
+					...await this.generateCommonPugData(meta),
 				});
 			} else {
 				return await renderBase(reply);
@@ -685,7 +689,7 @@ export class ClientServerService {
 					post: _post,
 					profile,
 					avatarUrl: _post.user.avatarUrl,
-					...this.generateCommonPugData(meta),
+					...await this.generateCommonPugData(meta),
 				});
 			} else {
 				return await renderBase(reply);
@@ -704,7 +708,7 @@ export class ClientServerService {
 				reply.header('Cache-Control', 'public, max-age=15');
 				return await reply.view('channel', {
 					channel: _channel,
-					...this.generateCommonPugData(meta),
+					...await this.generateCommonPugData(meta),
 				});
 			} else {
 				return await renderBase(reply);
@@ -723,7 +727,7 @@ export class ClientServerService {
 				reply.header('Cache-Control', 'public, max-age=3600');
 				return await reply.view('reversi-game', {
 					game: _game,
-					...this.generateCommonPugData(meta),
+					...await this.generateCommonPugData(meta),
 				});
 			} else {
 				return await renderBase(reply);
diff --git a/packages/backend/src/server/web/views/base.pug b/packages/backend/src/server/web/views/base.pug
index d167afe1e8e923e47977ceba4ec914cb4e955b1d..123336809be0fa25aed84e17e96106430e246ec4 100644
--- a/packages/backend/src/server/web/views/base.pug
+++ b/packages/backend/src/server/web/views/base.pug
@@ -68,6 +68,9 @@ html
 			var VERSION = "#{version}";
 			var CLIENT_ENTRY = "#{clientEntry.file}";
 
+		script(type='application/json' id='misskey_meta' data-generated-at=now)
+			!= metaJson
+
 		script
 			include ../boot.js
 
diff --git a/packages/frontend/src/boot/main-boot.ts b/packages/frontend/src/boot/main-boot.ts
index b19d45a35e87e333e90fb531e8635153e1962183..61f04678bff0a28700eccd86671c5cf893adbffa 100644
--- a/packages/frontend/src/boot/main-boot.ts
+++ b/packages/frontend/src/boot/main-boot.ts
@@ -11,7 +11,7 @@ import { alert, confirm, popup, post, toast } from '@/os.js';
 import { useStream } from '@/stream.js';
 import * as sound from '@/scripts/sound.js';
 import { $i, signout, updateAccount } from '@/account.js';
-import { fetchInstance, instance } from '@/instance.js';
+import { instance } from '@/instance.js';
 import { ColdDeviceStorage, defaultStore } from '@/store.js';
 import { makeHotkey } from '@/scripts/hotkey.js';
 import { reactionPicker } from '@/scripts/reaction-picker.js';
@@ -235,12 +235,10 @@ export async function mainBoot() {
 			}
 		}
 
-		fetchInstance().then(() => {
-			const modifiedVersionMustProminentlyOfferInAgplV3Section13Read = miLocalStorage.getItem('modifiedVersionMustProminentlyOfferInAgplV3Section13Read');
-			if (modifiedVersionMustProminentlyOfferInAgplV3Section13Read !== 'true' && instance.repositoryUrl !== 'https://github.com/misskey-dev/misskey') {
-				popup(defineAsyncComponent(() => import('@/components/MkSourceCodeAvailablePopup.vue')), {}, {}, 'closed');
-			}
-		});
+		const modifiedVersionMustProminentlyOfferInAgplV3Section13Read = miLocalStorage.getItem('modifiedVersionMustProminentlyOfferInAgplV3Section13Read');
+		if (modifiedVersionMustProminentlyOfferInAgplV3Section13Read !== 'true' && instance.repositoryUrl !== 'https://github.com/misskey-dev/misskey') {
+			popup(defineAsyncComponent(() => import('@/components/MkSourceCodeAvailablePopup.vue')), {}, {}, 'closed');
+		}
 
 		if ('Notification' in window) {
 			// 許可を得ていなかったらリクエスト
diff --git a/packages/frontend/src/instance.ts b/packages/frontend/src/instance.ts
index 205602369298f31423edf3b23e1dda4dfffabe8f..4232cbcd78d54c70d061cbc6d1913bd805084342 100644
--- a/packages/frontend/src/instance.ts
+++ b/packages/frontend/src/instance.ts
@@ -11,13 +11,24 @@ import { DEFAULT_INFO_IMAGE_URL, DEFAULT_NOT_FOUND_IMAGE_URL, DEFAULT_SERVER_ERR
 
 // TODO: 他のタブと永続化されたstateを同期
 
-const cached = miLocalStorage.getItem('instance');
+//#region loader
+const providedMetaEl = document.getElementById('misskey_meta');
+
+let cachedMeta = miLocalStorage.getItem('instance') ? JSON.parse(miLocalStorage.getItem('instance')!) : null;
+let cachedAt = miLocalStorage.getItem('instanceCachedAt') ? parseInt(miLocalStorage.getItem('instanceCachedAt')!) : 0;
+const providedMeta = providedMetaEl && providedMetaEl.textContent ? JSON.parse(providedMetaEl.textContent) : null;
+const providedAt = providedMetaEl && providedMetaEl.dataset.generatedAt ? parseInt(providedMetaEl.dataset.generatedAt) : 0;
+if (providedAt > cachedAt) {
+	miLocalStorage.setItem('instance', JSON.stringify(providedMeta));
+	miLocalStorage.setItem('instanceCachedAt', providedAt.toString());
+	cachedMeta = providedMeta;
+	cachedAt = providedAt;
+}
+//#endregion
 
 // TODO: instanceをリアクティブにするかは再考の余地あり
 
-export const instance: Misskey.entities.MetaResponse = reactive(cached ? JSON.parse(cached) : {
-	// TODO: set default values
-});
+export const instance: Misskey.entities.MetaResponse = reactive(cachedMeta ?? {});
 
 export const serverErrorImageUrl = computed(() => instance.serverErrorImageUrl ?? DEFAULT_SERVER_ERROR_IMAGE_URL);
 
@@ -25,7 +36,15 @@ export const infoImageUrl = computed(() => instance.infoImageUrl ?? DEFAULT_INFO
 
 export const notFoundImageUrl = computed(() => instance.notFoundImageUrl ?? DEFAULT_NOT_FOUND_IMAGE_URL);
 
-export async function fetchInstance() {
+export async function fetchInstance(force = false): Promise<void> {
+	if (!force) {
+		const cachedAt = miLocalStorage.getItem('instanceCachedAt') ? parseInt(miLocalStorage.getItem('instanceCachedAt')!) : 0;
+
+		if (Date.now() - cachedAt < 1000 * 60 * 60) {
+			return;
+		}
+	}
+
 	const meta = await misskeyApi('meta', {
 		detail: false,
 	});
@@ -35,4 +54,5 @@ export async function fetchInstance() {
 	}
 
 	miLocalStorage.setItem('instance', JSON.stringify(instance));
+	miLocalStorage.setItem('instanceCachedAt', Date.now().toString());
 }
diff --git a/packages/frontend/src/local-storage.ts b/packages/frontend/src/local-storage.ts
index 3de81c9bb9dccf61020680ad46408ca40b533957..8029bca68d53030af27b2f190a59c9de43bcca9a 100644
--- a/packages/frontend/src/local-storage.ts
+++ b/packages/frontend/src/local-storage.ts
@@ -7,6 +7,7 @@ type Keys =
 	'v' |
 	'lastVersion' |
 	'instance' |
+	'instanceCachedAt' |
 	'account' |
 	'accounts' |
 	'latestDonationInfoShownAt' |
diff --git a/packages/frontend/src/pages/admin/bot-protection.vue b/packages/frontend/src/pages/admin/bot-protection.vue
index e5e04fdeb8a63cc97b72c7a8d94c189a34f5c9e6..73c5e1919f41af20678e745ad0e39743846688b9 100644
--- a/packages/frontend/src/pages/admin/bot-protection.vue
+++ b/packages/frontend/src/pages/admin/bot-protection.vue
@@ -142,7 +142,7 @@ function save() {
 		turnstileSiteKey: turnstileSiteKey.value,
 		turnstileSecretKey: turnstileSecretKey.value,
 	}).then(() => {
-		fetchInstance();
+		fetchInstance(true);
 	});
 }
 </script>
diff --git a/packages/frontend/src/pages/admin/branding.vue b/packages/frontend/src/pages/admin/branding.vue
index 2b559f92c9bd3337d615ca5677561d8aa13c7aff..fe1b7c561daf7b7e646bda2641a45e6205dba83a 100644
--- a/packages/frontend/src/pages/admin/branding.vue
+++ b/packages/frontend/src/pages/admin/branding.vue
@@ -169,7 +169,7 @@ function save() {
 		feedbackUrl: feedbackUrl.value === '' ? null : feedbackUrl.value,
 		manifestJsonOverride: manifestJsonOverride.value === '' ? '{}' : JSON.stringify(JSON5.parse(manifestJsonOverride.value)),
 	}).then(() => {
-		fetchInstance();
+		fetchInstance(true);
 	});
 }
 
diff --git a/packages/frontend/src/pages/admin/email-settings.vue b/packages/frontend/src/pages/admin/email-settings.vue
index 839b9bee160eb69f2e3928b7a193391b94dd099c..4a858887f353a0c0774e39ef25d36df4383fad3f 100644
--- a/packages/frontend/src/pages/admin/email-settings.vue
+++ b/packages/frontend/src/pages/admin/email-settings.vue
@@ -124,7 +124,7 @@ function save() {
 		smtpUser: smtpUser.value,
 		smtpPass: smtpPass.value,
 	}).then(() => {
-		fetchInstance();
+		fetchInstance(true);
 	});
 }
 
diff --git a/packages/frontend/src/pages/admin/external-services.vue b/packages/frontend/src/pages/admin/external-services.vue
index ba3eb05e72ce62005d16a9fd57a4dbcdf7996c66..e0b82eb02ea0719810928898c427788180a31658 100644
--- a/packages/frontend/src/pages/admin/external-services.vue
+++ b/packages/frontend/src/pages/admin/external-services.vue
@@ -61,7 +61,7 @@ function save() {
 		deeplAuthKey: deeplAuthKey.value,
 		deeplIsPro: deeplIsPro.value,
 	}).then(() => {
-		fetchInstance();
+		fetchInstance(true);
 	});
 }
 
diff --git a/packages/frontend/src/pages/admin/instance-block.vue b/packages/frontend/src/pages/admin/instance-block.vue
index 5167b2e6b219a29cd4ec318261596b214e9330d0..6b14bd42c2af328580488c7995abbe04749a57b0 100644
--- a/packages/frontend/src/pages/admin/instance-block.vue
+++ b/packages/frontend/src/pages/admin/instance-block.vue
@@ -50,7 +50,7 @@ function save() {
 		silencedHosts: silencedHosts.value.split('\n') || [],
 
 	}).then(() => {
-		fetchInstance();
+		fetchInstance(true);
 	});
 }
 
diff --git a/packages/frontend/src/pages/admin/moderation.vue b/packages/frontend/src/pages/admin/moderation.vue
index d6cb1e39a76ac12a92d777c6ba607c9944c3db8d..9efb34ac9a0103c0552effa868fa2ecce2adad36 100644
--- a/packages/frontend/src/pages/admin/moderation.vue
+++ b/packages/frontend/src/pages/admin/moderation.vue
@@ -110,7 +110,7 @@ function save() {
 		hiddenTags: hiddenTags.value.split('\n'),
 		preservedUsernames: preservedUsernames.value.split('\n'),
 	}).then(() => {
-		fetchInstance();
+		fetchInstance(true);
 	});
 }
 
diff --git a/packages/frontend/src/pages/admin/object-storage.vue b/packages/frontend/src/pages/admin/object-storage.vue
index 4ff5ab09ca485f6280e985d2760728e3a9d6884b..5fddb715cd5c6ef90e69eacd9b3e5c8ecfe500a7 100644
--- a/packages/frontend/src/pages/admin/object-storage.vue
+++ b/packages/frontend/src/pages/admin/object-storage.vue
@@ -143,7 +143,7 @@ function save() {
 		objectStorageSetPublicRead: objectStorageSetPublicRead.value,
 		objectStorageS3ForcePathStyle: objectStorageS3ForcePathStyle.value,
 	}).then(() => {
-		fetchInstance();
+		fetchInstance(true);
 	});
 }
 
diff --git a/packages/frontend/src/pages/admin/other-settings.vue b/packages/frontend/src/pages/admin/other-settings.vue
index 651f0ef93692bd2bb84bf9d73807a53dd267e7b9..345cf333b51fcc30d537b0d6e072a811add370fb 100644
--- a/packages/frontend/src/pages/admin/other-settings.vue
+++ b/packages/frontend/src/pages/admin/other-settings.vue
@@ -73,7 +73,7 @@ function save() {
 		enableChartsForRemoteUser: enableChartsForRemoteUser.value,
 		enableChartsForFederatedInstances: enableChartsForFederatedInstances.value,
 	}).then(() => {
-		fetchInstance();
+		fetchInstance(true);
 	});
 }
 
diff --git a/packages/frontend/src/pages/admin/proxy-account.vue b/packages/frontend/src/pages/admin/proxy-account.vue
index 02b506d13dae01987eab6820ff9abf04dc4ce8fe..81db9f1da9c213a4b75ec7fff909c163892c50a8 100644
--- a/packages/frontend/src/pages/admin/proxy-account.vue
+++ b/packages/frontend/src/pages/admin/proxy-account.vue
@@ -56,7 +56,7 @@ function save() {
 	os.apiWithDialog('admin/update-meta', {
 		proxyAccountId: proxyAccountId.value,
 	}).then(() => {
-		fetchInstance();
+		fetchInstance(true);
 	});
 }
 
diff --git a/packages/frontend/src/pages/admin/security.vue b/packages/frontend/src/pages/admin/security.vue
index cadcf5a8cc6d4fb7853b8c5584420ac222a48a75..c4745978dfb68a331e0bce8dbca765044298db91 100644
--- a/packages/frontend/src/pages/admin/security.vue
+++ b/packages/frontend/src/pages/admin/security.vue
@@ -196,7 +196,7 @@ async function init() {
 	enableTruemailApi.value = meta.enableTruemailApi;
 	truemailInstance.value = meta.truemailInstance;
 	truemailAuthKey.value = meta.truemailAuthKey;
-	bannedEmailDomains.value = meta.bannedEmailDomains?.join('\n') || "";
+	bannedEmailDomains.value = meta.bannedEmailDomains?.join('\n') || '';
 }
 
 function save() {
@@ -221,7 +221,7 @@ function save() {
 		truemailAuthKey: truemailAuthKey.value,
 		bannedEmailDomains: bannedEmailDomains.value.split('\n'),
 	}).then(() => {
-		fetchInstance();
+		fetchInstance(true);
 	});
 }
 
diff --git a/packages/frontend/src/pages/admin/server-rules.vue b/packages/frontend/src/pages/admin/server-rules.vue
index 87318bccce006819a52f9048c705853b2b7683b8..ff9b8d62993afe6720045ea6c1c68c045dc14d46 100644
--- a/packages/frontend/src/pages/admin/server-rules.vue
+++ b/packages/frontend/src/pages/admin/server-rules.vue
@@ -58,7 +58,7 @@ const save = async () => {
 	await os.apiWithDialog('admin/update-meta', {
 		serverRules: serverRules.value,
 	});
-	fetchInstance();
+	fetchInstance(true);
 };
 
 const remove = (index: number): void => {
diff --git a/packages/frontend/src/pages/admin/settings.vue b/packages/frontend/src/pages/admin/settings.vue
index c505d70aa980a83df3268a384ea2d0cea929f680..9a198ee8a3436b69172b30a12173a8024a8afa66 100644
--- a/packages/frontend/src/pages/admin/settings.vue
+++ b/packages/frontend/src/pages/admin/settings.vue
@@ -243,7 +243,7 @@ async function save(): void {
 		notesPerOneAd: notesPerOneAd.value,
 	});
 
-	fetchInstance();
+	fetchInstance(true);
 }
 
 const headerTabs = computed(() => []);
diff --git a/packages/frontend/src/scripts/clear-cache.ts b/packages/frontend/src/scripts/clear-cache.ts
index f2db87c4fb06bf572d8ec3f4404cbbb2252230b4..b20109ec72bf96fb5a1fee52101c99020ad5b8ef 100644
--- a/packages/frontend/src/scripts/clear-cache.ts
+++ b/packages/frontend/src/scripts/clear-cache.ts
@@ -2,14 +2,18 @@ import { unisonReload } from '@/scripts/unison-reload.js';
 import * as os from '@/os.js';
 import { miLocalStorage } from '@/local-storage.js';
 import { fetchCustomEmojis } from '@/custom-emojis.js';
+import { fetchInstance } from '@/instance.js';
 
 export async function clearCache() {
 	os.waiting();
+	miLocalStorage.removeItem('instance');
+	miLocalStorage.removeItem('instanceCachedAt');
 	miLocalStorage.removeItem('locale');
 	miLocalStorage.removeItem('localeVersion');
 	miLocalStorage.removeItem('theme');
 	miLocalStorage.removeItem('emojis');
 	miLocalStorage.removeItem('lastEmojisFetchedAt');
+	await fetchInstance(true);
 	await fetchCustomEmojis(true);
 	unisonReload();
 }
diff --git a/packages/misskey-js/etc/misskey-js.api.md b/packages/misskey-js/etc/misskey-js.api.md
index c2428910fa5d540c07e075ed7b3c79291ca951f8..a2d5a4f5144e440eea14dfeaeed72f04ef484b1c 100644
--- a/packages/misskey-js/etc/misskey-js.api.md
+++ b/packages/misskey-js/etc/misskey-js.api.md
@@ -1715,7 +1715,10 @@ declare namespace entities {
         Role,
         RolePolicies,
         ReversiGameLite,
-        ReversiGameDetailed
+        ReversiGameDetailed,
+        MetaLite,
+        MetaDetailedOnly,
+        MetaDetailed
     }
 }
 export { entities }
@@ -2223,6 +2226,15 @@ type MeDetailed = components['schemas']['MeDetailed'];
 // @public (undocumented)
 type MeDetailedOnly = components['schemas']['MeDetailedOnly'];
 
+// @public (undocumented)
+type MetaDetailed = components['schemas']['MetaDetailed'];
+
+// @public (undocumented)
+type MetaDetailedOnly = components['schemas']['MetaDetailedOnly'];
+
+// @public (undocumented)
+type MetaLite = components['schemas']['MetaLite'];
+
 // @public (undocumented)
 type MetaRequest = operations['meta']['requestBody']['content']['application/json'];
 
diff --git a/packages/misskey-js/src/autogen/models.ts b/packages/misskey-js/src/autogen/models.ts
index 6400567a2dab474d57e03ea2e2dfb27413db373c..ab49f9478a1e2fcc0620d45c04b7b481bda28425 100644
--- a/packages/misskey-js/src/autogen/models.ts
+++ b/packages/misskey-js/src/autogen/models.ts
@@ -46,3 +46,6 @@ export type Role = components['schemas']['Role'];
 export type RolePolicies = components['schemas']['RolePolicies'];
 export type ReversiGameLite = components['schemas']['ReversiGameLite'];
 export type ReversiGameDetailed = components['schemas']['ReversiGameDetailed'];
+export type MetaLite = components['schemas']['MetaLite'];
+export type MetaDetailedOnly = components['schemas']['MetaDetailedOnly'];
+export type MetaDetailed = components['schemas']['MetaDetailed'];
diff --git a/packages/misskey-js/src/autogen/types.ts b/packages/misskey-js/src/autogen/types.ts
index 0b2a88b5378758d75ad516fbfd92f9990da1d70c..18bc45b983dfa58f0d7df5da0a2b1332c60e02aa 100644
--- a/packages/misskey-js/src/autogen/types.ts
+++ b/packages/misskey-js/src/autogen/types.ts
@@ -4724,6 +4724,96 @@ export type components = {
       logs: number[][];
       map: string[];
     };
+    MetaLite: {
+      maintainerName: string | null;
+      maintainerEmail: string | null;
+      version: string;
+      providesTarball: boolean;
+      name: string | null;
+      shortName: string | null;
+      /**
+       * Format: url
+       * @example https://misskey.example.com
+       */
+      uri: string;
+      description: string | null;
+      langs: string[];
+      tosUrl: string | null;
+      /** @default https://github.com/misskey-dev/misskey */
+      repositoryUrl: string | null;
+      /** @default https://github.com/misskey-dev/misskey/issues/new */
+      feedbackUrl: string | null;
+      defaultDarkTheme: string | null;
+      defaultLightTheme: string | null;
+      disableRegistration: boolean;
+      emailRequiredForSignup: boolean;
+      enableHcaptcha: boolean;
+      hcaptchaSiteKey: string | null;
+      enableMcaptcha: boolean;
+      mcaptchaSiteKey: string | null;
+      mcaptchaInstanceUrl: string | null;
+      enableRecaptcha: boolean;
+      recaptchaSiteKey: string | null;
+      enableTurnstile: boolean;
+      turnstileSiteKey: string | null;
+      swPublickey: string | null;
+      /** @default /assets/ai.png */
+      mascotImageUrl: string;
+      bannerUrl: string | null;
+      serverErrorImageUrl: string | null;
+      infoImageUrl: string | null;
+      notFoundImageUrl: string | null;
+      iconUrl: string | null;
+      maxNoteTextLength: number;
+      ads: {
+          /**
+           * Format: id
+           * @example xxxxxxxxxx
+           */
+          id: string;
+          /** Format: url */
+          url: string;
+          place: string;
+          ratio: number;
+          /** Format: url */
+          imageUrl: string;
+          dayOfWeek: number;
+        }[];
+      /** @default 0 */
+      notesPerOneAd: number;
+      enableEmail: boolean;
+      enableServiceWorker: boolean;
+      translatorAvailable: boolean;
+      mediaProxy: string;
+      backgroundImageUrl: string | null;
+      impressumUrl: string | null;
+      logoImageUrl: string | null;
+      privacyPolicyUrl: string | null;
+      serverRules: string[];
+      themeColor: string | null;
+      policies: components['schemas']['RolePolicies'];
+    };
+    MetaDetailedOnly: {
+      features?: {
+        registration: boolean;
+        emailRequiredForSignup: boolean;
+        localTimeline: boolean;
+        globalTimeline: boolean;
+        hcaptcha: boolean;
+        turnstile: boolean;
+        recaptcha: boolean;
+        objectStorage: boolean;
+        serviceWorker: boolean;
+        /** @default true */
+        miauth?: boolean;
+      };
+      proxyAccountName: string | null;
+      /** @example false */
+      requireSetup: boolean;
+      cacheRemoteFiles: boolean;
+      cacheRemoteSensitiveFiles: boolean;
+    };
+    MetaDetailed: components['schemas']['MetaLite'] & components['schemas']['MetaDetailedOnly'];
   };
   responses: never;
   parameters: never;
@@ -19448,91 +19538,7 @@ export type operations = {
       /** @description OK (with results) */
       200: {
         content: {
-          'application/json': {
-            maintainerName: string | null;
-            maintainerEmail: string | null;
-            version: string;
-            providesTarball: boolean;
-            name: string;
-            shortName: string | null;
-            /**
-             * Format: url
-             * @example https://misskey.example.com
-             */
-            uri: string;
-            description: string | null;
-            langs: string[];
-            tosUrl: string | null;
-            /** @default https://github.com/misskey-dev/misskey */
-            repositoryUrl: string | null;
-            /** @default https://github.com/misskey-dev/misskey/issues/new */
-            feedbackUrl: string | null;
-            defaultDarkTheme: string | null;
-            defaultLightTheme: string | null;
-            disableRegistration: boolean;
-            cacheRemoteFiles: boolean;
-            cacheRemoteSensitiveFiles: boolean;
-            emailRequiredForSignup: boolean;
-            enableHcaptcha: boolean;
-            hcaptchaSiteKey: string | null;
-            enableMcaptcha: boolean;
-            mcaptchaSiteKey: string | null;
-            mcaptchaInstanceUrl: string | null;
-            enableRecaptcha: boolean;
-            recaptchaSiteKey: string | null;
-            enableTurnstile: boolean;
-            turnstileSiteKey: string | null;
-            swPublickey: string | null;
-            /** @default /assets/ai.png */
-            mascotImageUrl: string;
-            bannerUrl: string;
-            serverErrorImageUrl: string | null;
-            infoImageUrl: string | null;
-            notFoundImageUrl: string | null;
-            iconUrl: string | null;
-            maxNoteTextLength: number;
-            ads: {
-                /**
-                 * Format: id
-                 * @example xxxxxxxxxx
-                 */
-                id: string;
-                /** Format: url */
-                url: string;
-                place: string;
-                ratio: number;
-                /** Format: url */
-                imageUrl: string;
-                dayOfWeek: number;
-              }[];
-            /** @default 0 */
-            notesPerOneAd: number;
-            /** @example false */
-            requireSetup: boolean;
-            enableEmail: boolean;
-            enableServiceWorker: boolean;
-            translatorAvailable: boolean;
-            proxyAccountName: string | null;
-            mediaProxy: string;
-            features?: {
-              registration: boolean;
-              localTimeline: boolean;
-              globalTimeline: boolean;
-              hcaptcha: boolean;
-              recaptcha: boolean;
-              objectStorage: boolean;
-              serviceWorker: boolean;
-              /** @default true */
-              miauth?: boolean;
-            };
-            backgroundImageUrl: string | null;
-            impressumUrl: string | null;
-            logoImageUrl: string | null;
-            privacyPolicyUrl: string | null;
-            serverRules: string[];
-            themeColor: string | null;
-            policies: components['schemas']['RolePolicies'];
-          };
+          'application/json': components['schemas']['MetaLite'] | components['schemas']['MetaDetailed'];
         };
       };
       /** @description Client error */