diff --git a/packages/frontend/lib/rollup-plugin-unwind-css-module-class-name.test.ts b/packages/frontend/lib/rollup-plugin-unwind-css-module-class-name.test.ts
index fab80eae2f2ac50e136ac065120617fd08b27867..d78f05439583799ed0d1139ec4318500cd51fc7c 100644
--- a/packages/frontend/lib/rollup-plugin-unwind-css-module-class-name.test.ts
+++ b/packages/frontend/lib/rollup-plugin-unwind-css-module-class-name.test.ts
@@ -6,7 +6,7 @@
 import { parse } from 'acorn';
 import { generate } from 'astring';
 import { describe, expect, it } from 'vitest';
-import { normalizeClass, unwindCssModuleClassName } from './rollup-plugin-unwind-css-module-class-name';
+import { normalizeClass, unwindCssModuleClassName } from './rollup-plugin-unwind-css-module-class-name.js';
 import type * as estree from 'estree';
 
 function parseExpression(code: string): estree.Expression {
diff --git a/packages/frontend/src/components/MkAbuseReport.stories.impl.ts b/packages/frontend/src/components/MkAbuseReport.stories.impl.ts
index 3b6452962031cdd8edf598d6f9673af9aab4d744..77e7c84d5c9cf65fc7516bb25b281f990778bb65 100644
--- a/packages/frontend/src/components/MkAbuseReport.stories.impl.ts
+++ b/packages/frontend/src/components/MkAbuseReport.stories.impl.ts
@@ -7,8 +7,8 @@
 import { action } from '@storybook/addon-actions';
 import { StoryObj } from '@storybook/vue3';
 import { rest } from 'msw';
-import { abuseUserReport } from '../../.storybook/fakes';
-import { commonHandlers } from '../../.storybook/mocks';
+import { abuseUserReport } from '../../.storybook/fakes.js';
+import { commonHandlers } from '../../.storybook/mocks.js';
 import MkAbuseReport from './MkAbuseReport.vue';
 export const Default = {
 	render(args) {
diff --git a/packages/frontend/src/components/MkAbuseReportWindow.stories.impl.ts b/packages/frontend/src/components/MkAbuseReportWindow.stories.impl.ts
index b45d54679be0a00d5ac920363c5cafe31a5ff0f0..dc842b3d1bd2b81460c7272ceb754f6c193fcb82 100644
--- a/packages/frontend/src/components/MkAbuseReportWindow.stories.impl.ts
+++ b/packages/frontend/src/components/MkAbuseReportWindow.stories.impl.ts
@@ -7,8 +7,8 @@
 import { action } from '@storybook/addon-actions';
 import { StoryObj } from '@storybook/vue3';
 import { rest } from 'msw';
-import { userDetailed } from '../../.storybook/fakes';
-import { commonHandlers } from '../../.storybook/mocks';
+import { userDetailed } from '../../.storybook/fakes.js';
+import { commonHandlers } from '../../.storybook/mocks.js';
 import MkAbuseReportWindow from './MkAbuseReportWindow.vue';
 export const Default = {
 	render(args) {
diff --git a/packages/frontend/src/components/MkAccountMoved.stories.impl.ts b/packages/frontend/src/components/MkAccountMoved.stories.impl.ts
index a6d4d18c1b6eacd63e51aa1b0cecf35457659860..33c6c24631c88c41e1e61cedc83d6bea659c1370 100644
--- a/packages/frontend/src/components/MkAccountMoved.stories.impl.ts
+++ b/packages/frontend/src/components/MkAccountMoved.stories.impl.ts
@@ -5,7 +5,7 @@
 
 /* eslint-disable @typescript-eslint/explicit-function-return-type */
 import { StoryObj } from '@storybook/vue3';
-import { userDetailed } from '../../.storybook/fakes';
+import { userDetailed } from '../../.storybook/fakes.js';
 import MkAccountMoved from './MkAccountMoved.vue';
 export const Default = {
 	render(args) {
diff --git a/packages/frontend/src/components/MkAchievements.stories.impl.ts b/packages/frontend/src/components/MkAchievements.stories.impl.ts
index a67e1def13f3e4522c8e5d5a73ce0562fde7cc64..6d972467b153d178f7262a7b97437a9874a86f7c 100644
--- a/packages/frontend/src/components/MkAchievements.stories.impl.ts
+++ b/packages/frontend/src/components/MkAchievements.stories.impl.ts
@@ -6,8 +6,8 @@
 /* eslint-disable @typescript-eslint/explicit-function-return-type */
 import { StoryObj } from '@storybook/vue3';
 import { rest } from 'msw';
-import { userDetailed } from '../../.storybook/fakes';
-import { commonHandlers } from '../../.storybook/mocks';
+import { userDetailed } from '../../.storybook/fakes.js';
+import { commonHandlers } from '../../.storybook/mocks.js';
 import MkAchievements from './MkAchievements.vue';
 import { ACHIEVEMENT_TYPES } from '@/scripts/achievements.js';
 export const Empty = {
diff --git a/packages/frontend/src/components/MkAutocomplete.stories.impl.ts b/packages/frontend/src/components/MkAutocomplete.stories.impl.ts
index 8232759ba045f95a59710b3174300055f91233b3..969519386fc9733da1fd23a485330aaa728b820a 100644
--- a/packages/frontend/src/components/MkAutocomplete.stories.impl.ts
+++ b/packages/frontend/src/components/MkAutocomplete.stories.impl.ts
@@ -9,8 +9,8 @@ import { expect } from '@storybook/jest';
 import { userEvent, waitFor, within } from '@storybook/testing-library';
 import { StoryObj } from '@storybook/vue3';
 import { rest } from 'msw';
-import { userDetailed } from '../../.storybook/fakes';
-import { commonHandlers } from '../../.storybook/mocks';
+import { userDetailed } from '../../.storybook/fakes.js';
+import { commonHandlers } from '../../.storybook/mocks.js';
 import MkAutocomplete from './MkAutocomplete.vue';
 import MkInput from './MkInput.vue';
 import { tick } from '@/scripts/test-utils.js';
diff --git a/packages/frontend/src/components/MkAvatars.stories.impl.ts b/packages/frontend/src/components/MkAvatars.stories.impl.ts
index 659c0eebdf407ca3adabaeca750f001ce36cd86a..d41b64695fdcfb1fc14e0c364b26a7420096d310 100644
--- a/packages/frontend/src/components/MkAvatars.stories.impl.ts
+++ b/packages/frontend/src/components/MkAvatars.stories.impl.ts
@@ -6,8 +6,8 @@
 /* eslint-disable @typescript-eslint/explicit-function-return-type */
 import { StoryObj } from '@storybook/vue3';
 import { rest } from 'msw';
-import { userDetailed } from '../../.storybook/fakes';
-import { commonHandlers } from '../../.storybook/mocks';
+import { userDetailed } from '../../.storybook/fakes.js';
+import { commonHandlers } from '../../.storybook/mocks.js';
 import MkAvatars from './MkAvatars.vue';
 export const Default = {
 	render(args) {
diff --git a/packages/frontend/src/components/MkContextMenu.vue b/packages/frontend/src/components/MkContextMenu.vue
index b78252be895c9c938623b8de8ddc3923ec518e76..e29cf472f7dfed4fd5ca2031a4a695ca2c42dfc4 100644
--- a/packages/frontend/src/components/MkContextMenu.vue
+++ b/packages/frontend/src/components/MkContextMenu.vue
@@ -20,7 +20,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 <script lang="ts" setup>
 import { onMounted, onBeforeUnmount, shallowRef, ref } from 'vue';
 import MkMenu from './MkMenu.vue';
-import { MenuItem } from './types/menu.vue';
+import { MenuItem } from '@/types/menu.js';
 import contains from '@/scripts/contains.js';
 import { defaultStore } from '@/store.js';
 import * as os from '@/os.js';
diff --git a/packages/frontend/src/components/MkDateSeparatedList.vue b/packages/frontend/src/components/MkDateSeparatedList.vue
index b5508af62e4afa1c782451fdca5373bfde47cb59..b45aef45ffe898407c89055605ec35de34dd615f 100644
--- a/packages/frontend/src/components/MkDateSeparatedList.vue
+++ b/packages/frontend/src/components/MkDateSeparatedList.vue
@@ -6,11 +6,11 @@ SPDX-License-Identifier: AGPL-3.0-only
 <script lang="ts">
 import { defineComponent, h, PropType, TransitionGroup, useCssModule } from 'vue';
 import MkAd from '@/components/global/MkAd.vue';
-import { isDebuggerEnabled, stackTraceInstances } from '@/debug';
+import { isDebuggerEnabled, stackTraceInstances } from '@/debug.js';
 import { i18n } from '@/i18n.js';
 import * as os from '@/os.js';
 import { defaultStore } from '@/store.js';
-import { MisskeyEntity } from '@/types/date-separated-list';
+import { MisskeyEntity } from '@/types/date-separated-list.js';
 
 export default defineComponent({
 	props: {
diff --git a/packages/frontend/src/components/MkGalleryPostPreview.stories.impl.ts b/packages/frontend/src/components/MkGalleryPostPreview.stories.impl.ts
index 29e27e1373d823fad4fffc5e23f0b5dd933dbc5e..035b727a35c2e2a491d013db97f799137007c19b 100644
--- a/packages/frontend/src/components/MkGalleryPostPreview.stories.impl.ts
+++ b/packages/frontend/src/components/MkGalleryPostPreview.stories.impl.ts
@@ -7,7 +7,7 @@
 import { expect } from '@storybook/jest';
 import { userEvent, waitFor, within } from '@storybook/testing-library';
 import { StoryObj } from '@storybook/vue3';
-import { galleryPost } from '../../.storybook/fakes';
+import { galleryPost } from '../../.storybook/fakes.js';
 import MkGalleryPostPreview from './MkGalleryPostPreview.vue';
 export const Default = {
 	render(args) {
diff --git a/packages/frontend/src/components/MkInviteCode.stories.impl.ts b/packages/frontend/src/components/MkInviteCode.stories.impl.ts
index 0127ce061bb6bab867111635c10f5fdcedddd1e3..2ea32dd3b67a5afb31e6ec374bc1dc95d25275c8 100644
--- a/packages/frontend/src/components/MkInviteCode.stories.impl.ts
+++ b/packages/frontend/src/components/MkInviteCode.stories.impl.ts
@@ -6,8 +6,8 @@
 /* eslint-disable @typescript-eslint/explicit-function-return-type */
 import { StoryObj } from '@storybook/vue3';
 import { rest } from 'msw';
-import { userDetailed, inviteCode } from '../../.storybook/fakes';
-import { commonHandlers } from '../../.storybook/mocks';
+import { userDetailed, inviteCode } from '../../.storybook/fakes.js';
+import { commonHandlers } from '../../.storybook/mocks.js';
 import MkInviteCode from './MkInviteCode.vue';
 
 export const Default = {
diff --git a/packages/frontend/src/components/MkMenu.vue b/packages/frontend/src/components/MkMenu.vue
index b0f997a1b9a76562eddc407d46afdafc57c62b86..5f48f43bfbb77af386ff5a520fe4d9afbe4b43ef 100644
--- a/packages/frontend/src/components/MkMenu.vue
+++ b/packages/frontend/src/components/MkMenu.vue
@@ -77,7 +77,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 import { computed, defineAsyncComponent, nextTick, onBeforeUnmount, onMounted, ref, shallowRef, watch } from 'vue';
 import { focusPrev, focusNext } from '@/scripts/focus.js';
 import MkSwitchButton from '@/components/MkSwitch.button.vue';
-import { MenuItem, InnerMenuItem, MenuPending, MenuAction, MenuSwitch, MenuParent } from '@/types/menu';
+import { MenuItem, InnerMenuItem, MenuPending, MenuAction, MenuSwitch, MenuParent } from '@/types/menu.js';
 import * as os from '@/os.js';
 import { i18n } from '@/i18n.js';
 import { isTouchUsing } from '@/scripts/touch.js';
diff --git a/packages/frontend/src/components/MkPageWindow.vue b/packages/frontend/src/components/MkPageWindow.vue
index d1d4c2106cccec704d9a7e087a0782e69c9d86b4..13a703e9f639795dcd7573ad6e01aa863de96e30 100644
--- a/packages/frontend/src/components/MkPageWindow.vue
+++ b/packages/frontend/src/components/MkPageWindow.vue
@@ -37,7 +37,7 @@ import copyToClipboard from '@/scripts/copy-to-clipboard.js';
 import { url } from '@/config.js';
 import { mainRouter, routes, page } from '@/router.js';
 import { $i } from '@/account.js';
-import { Router, useScrollPositionManager } from '@/nirax';
+import { Router, useScrollPositionManager } from '@/nirax.js';
 import { i18n } from '@/i18n.js';
 import { PageMetadata, provideMetadataReceiver } from '@/scripts/page-metadata.js';
 import { openingWindowsCount } from '@/os.js';
diff --git a/packages/frontend/src/components/MkPagination.vue b/packages/frontend/src/components/MkPagination.vue
index 07347eda29588fd390c90be6fd265180c08bd54a..bdd96238d3f0a60b9ea6665adbbbb2ef16fc2645 100644
--- a/packages/frontend/src/components/MkPagination.vue
+++ b/packages/frontend/src/components/MkPagination.vue
@@ -49,7 +49,7 @@ import * as os from '@/os.js';
 import { onScrollTop, isTopVisible, getBodyScrollHeight, getScrollContainer, onScrollBottom, scrollToBottom, scroll, isBottomVisible } from '@/scripts/scroll.js';
 import { useDocumentVisibility } from '@/scripts/use-document-visibility.js';
 import { defaultStore } from '@/store.js';
-import { MisskeyEntity } from '@/types/date-separated-list';
+import { MisskeyEntity } from '@/types/date-separated-list.js';
 import { i18n } from '@/i18n.js';
 
 const SECOND_FETCH_LIMIT = 30;
diff --git a/packages/frontend/src/components/MkUserSetupDialog.Follow.stories.impl.ts b/packages/frontend/src/components/MkUserSetupDialog.Follow.stories.impl.ts
index 9122bb898383258baa8e39102595e44c8f72e0d0..45c7da40ce2e51171e07aa0cd00ae0a571a7dcdf 100644
--- a/packages/frontend/src/components/MkUserSetupDialog.Follow.stories.impl.ts
+++ b/packages/frontend/src/components/MkUserSetupDialog.Follow.stories.impl.ts
@@ -6,8 +6,8 @@
 /* eslint-disable @typescript-eslint/explicit-function-return-type */
 import { StoryObj } from '@storybook/vue3';
 import { rest } from 'msw';
-import { commonHandlers } from '../../.storybook/mocks';
-import { userDetailed } from '../../.storybook/fakes';
+import { commonHandlers } from '../../.storybook/mocks.js';
+import { userDetailed } from '../../.storybook/fakes.js';
 import MkUserSetupDialog_Follow from './MkUserSetupDialog.Follow.vue';
 export const Default = {
 	render(args) {
diff --git a/packages/frontend/src/components/MkUserSetupDialog.User.stories.impl.ts b/packages/frontend/src/components/MkUserSetupDialog.User.stories.impl.ts
index 3324c0186cff7e722f8c01cdd411fc3b8c58ac47..31176c0832a2cad220331d00b9246dc4d1a93c1f 100644
--- a/packages/frontend/src/components/MkUserSetupDialog.User.stories.impl.ts
+++ b/packages/frontend/src/components/MkUserSetupDialog.User.stories.impl.ts
@@ -5,7 +5,7 @@
 
 /* eslint-disable @typescript-eslint/explicit-function-return-type */
 import { StoryObj } from '@storybook/vue3';
-import { userDetailed } from '../../.storybook/fakes';
+import { userDetailed } from '../../.storybook/fakes.js';
 import MkUserSetupDialog_User from './MkUserSetupDialog.User.vue';
 export const Default = {
 	render(args) {
diff --git a/packages/frontend/src/components/MkUserSetupDialog.stories.impl.ts b/packages/frontend/src/components/MkUserSetupDialog.stories.impl.ts
index 2795bcb2fafc7eee5803c59a16fdf0e6a606d47a..5182db12b2e9f20996434ca41d9ca0bc15c9fae0 100644
--- a/packages/frontend/src/components/MkUserSetupDialog.stories.impl.ts
+++ b/packages/frontend/src/components/MkUserSetupDialog.stories.impl.ts
@@ -6,8 +6,8 @@
 /* eslint-disable @typescript-eslint/explicit-function-return-type */
 import { StoryObj } from '@storybook/vue3';
 import { rest } from 'msw';
-import { commonHandlers } from '../../.storybook/mocks';
-import { userDetailed } from '../../.storybook/fakes';
+import { commonHandlers } from '../../.storybook/mocks.js';
+import { userDetailed } from '../../.storybook/fakes.js';
 import MkUserSetupDialog from './MkUserSetupDialog.vue';
 export const Default = {
 	render(args) {
diff --git a/packages/frontend/src/components/MkWidgets.vue b/packages/frontend/src/components/MkWidgets.vue
index 35300a3bf30cb1910b8661b5e5cbec79abe1920e..a5d5ff733fef70c97100d6c1f863d62f3094c858 100644
--- a/packages/frontend/src/components/MkWidgets.vue
+++ b/packages/frontend/src/components/MkWidgets.vue
@@ -54,7 +54,7 @@ import { defineAsyncComponent, ref } from 'vue';
 import { v4 as uuid } from 'uuid';
 import MkSelect from '@/components/MkSelect.vue';
 import MkButton from '@/components/MkButton.vue';
-import { widgets as widgetDefs } from '@/widgets';
+import { widgets as widgetDefs } from '@/widgets/index.js';
 import * as os from '@/os.js';
 import { i18n } from '@/i18n.js';
 
diff --git a/packages/frontend/src/components/global/MkAcct.stories.impl.ts b/packages/frontend/src/components/global/MkAcct.stories.impl.ts
index 00c1d9433039415c97a63ceb26ca86f736d7a96e..49ec61211cdf559dc3f609e813279dfbaf5d71d0 100644
--- a/packages/frontend/src/components/global/MkAcct.stories.impl.ts
+++ b/packages/frontend/src/components/global/MkAcct.stories.impl.ts
@@ -5,7 +5,7 @@
 
 /* eslint-disable @typescript-eslint/explicit-function-return-type */
 import { StoryObj } from '@storybook/vue3';
-import { userDetailed } from '../../../.storybook/fakes';
+import { userDetailed } from '../../../.storybook/fakes.js';
 import MkAcct from './MkAcct.vue';
 export const Default = {
 	render(args) {
diff --git a/packages/frontend/src/components/global/MkAvatar.stories.impl.ts b/packages/frontend/src/components/global/MkAvatar.stories.impl.ts
index 877511f8fc8cfe8dd5a9af1284f2b02aa6418aed..515d7eab1876e69225f724e073bcccd5d2396321 100644
--- a/packages/frontend/src/components/global/MkAvatar.stories.impl.ts
+++ b/packages/frontend/src/components/global/MkAvatar.stories.impl.ts
@@ -5,7 +5,7 @@
 
 /* eslint-disable @typescript-eslint/explicit-function-return-type */
 import { StoryObj } from '@storybook/vue3';
-import { userDetailed } from '../../../.storybook/fakes';
+import { userDetailed } from '../../../.storybook/fakes.js';
 import MkAvatar from './MkAvatar.vue';
 const common = {
 	render(args) {
diff --git a/packages/frontend/src/components/global/MkMisskeyFlavoredMarkdown.stories.impl.ts b/packages/frontend/src/components/global/MkMisskeyFlavoredMarkdown.stories.impl.ts
index 9d9febf693c56e30b853d23e390868f74053bf85..9cdb490e4b31cb55ad871fd0c979664521101228 100644
--- a/packages/frontend/src/components/global/MkMisskeyFlavoredMarkdown.stories.impl.ts
+++ b/packages/frontend/src/components/global/MkMisskeyFlavoredMarkdown.stories.impl.ts
@@ -7,7 +7,7 @@
 import { StoryObj } from '@storybook/vue3';
 import { within } from '@storybook/testing-library';
 import { expect } from '@storybook/jest';
-import MkMisskeyFlavoredMarkdown from './MkMisskeyFlavoredMarkdown.ts';
+import MkMisskeyFlavoredMarkdown from './MkMisskeyFlavoredMarkdown.js';
 export const Default = {
 	render(args) {
 		return {
diff --git a/packages/frontend/src/components/global/MkStickyContainer.vue b/packages/frontend/src/components/global/MkStickyContainer.vue
index 1d707af2d165ca4b318b965eaba642c5291208f9..70cc68b14ca063b4fe7d38eee71b2ca18821319a 100644
--- a/packages/frontend/src/components/global/MkStickyContainer.vue
+++ b/packages/frontend/src/components/global/MkStickyContainer.vue
@@ -20,7 +20,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 <script lang="ts" setup>
 import { onMounted, onUnmounted, provide, inject, Ref, ref, watch, shallowRef } from 'vue';
 
-import { CURRENT_STICKY_BOTTOM, CURRENT_STICKY_TOP } from '@/const';
+import { CURRENT_STICKY_BOTTOM, CURRENT_STICKY_TOP } from '@/const.js';
 
 const rootEl = shallowRef<HTMLElement>();
 const headerEl = shallowRef<HTMLElement>();
diff --git a/packages/frontend/src/components/global/MkUrl.stories.impl.ts b/packages/frontend/src/components/global/MkUrl.stories.impl.ts
index 84ac13f95a41b35ba79e5cefe408346bde8649bf..b35b6114fdd4e3e4af4050a687720a562ae04495 100644
--- a/packages/frontend/src/components/global/MkUrl.stories.impl.ts
+++ b/packages/frontend/src/components/global/MkUrl.stories.impl.ts
@@ -8,7 +8,7 @@ import { expect } from '@storybook/jest';
 import { userEvent, waitFor, within } from '@storybook/testing-library';
 import { StoryObj } from '@storybook/vue3';
 import { rest } from 'msw';
-import { commonHandlers } from '../../../.storybook/mocks';
+import { commonHandlers } from '../../../.storybook/mocks.js';
 import MkUrl from './MkUrl.vue';
 export const Default = {
 	render(args) {
diff --git a/packages/frontend/src/components/global/MkUserName.stories.impl.ts b/packages/frontend/src/components/global/MkUserName.stories.impl.ts
index 01455e492d8cdf1abd1fdb44d61f7d08484b6375..8f47a6c1ab174c0b64d4821277fc9420d2f9ccfe 100644
--- a/packages/frontend/src/components/global/MkUserName.stories.impl.ts
+++ b/packages/frontend/src/components/global/MkUserName.stories.impl.ts
@@ -6,7 +6,7 @@
 /* eslint-disable @typescript-eslint/explicit-function-return-type */
 import { expect } from '@storybook/jest';
 import { StoryObj } from '@storybook/vue3';
-import { userDetailed } from '../../../.storybook/fakes';
+import { userDetailed } from '../../../.storybook/fakes.js';
 import MkUserName from './MkUserName.vue';
 export const Default = {
 	render(args) {
diff --git a/packages/frontend/src/components/global/RouterView.vue b/packages/frontend/src/components/global/RouterView.vue
index 9da8f8c3799407b12a4bf3a272a0b803827807a7..99ed8adbefd5bc7be2595146ed29e9a528269c87 100644
--- a/packages/frontend/src/components/global/RouterView.vue
+++ b/packages/frontend/src/components/global/RouterView.vue
@@ -17,7 +17,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 
 <script lang="ts" setup>
 import { inject, onBeforeUnmount, provide, shallowRef, ref } from 'vue';
-import { Resolved, Router } from '@/nirax';
+import { Resolved, Router } from '@/nirax.js';
 import { defaultStore } from '@/store.js';
 
 const props = defineProps<{
diff --git a/packages/frontend/src/components/page/page.block.vue b/packages/frontend/src/components/page/page.block.vue
index c039a1c7b7819067a4dcabbef0cb20978b3d8304..7dbbaa03b4828167f067fa4acac37e229304f4cc 100644
--- a/packages/frontend/src/components/page/page.block.vue
+++ b/packages/frontend/src/components/page/page.block.vue
@@ -14,7 +14,7 @@ import XText from './page.text.vue';
 import XSection from './page.section.vue';
 import XImage from './page.image.vue';
 import XNote from './page.note.vue';
-import { Block } from './block.type';
+import { Block } from './block.type.js';
 
 function getComponent(type: string) {
 	switch (type) {
diff --git a/packages/frontend/src/components/page/page.image.vue b/packages/frontend/src/components/page/page.image.vue
index 80a75f02a58928681d3e35162918aa0ab65be70e..29aebf63e548810760e571a793acc833769790d3 100644
--- a/packages/frontend/src/components/page/page.image.vue
+++ b/packages/frontend/src/components/page/page.image.vue
@@ -16,7 +16,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 <script lang="ts" setup>
 import { ref } from 'vue';
 import * as Misskey from 'misskey-js';
-import { ImageBlock } from './block.type';
+import { ImageBlock } from './block.type.js';
 import MediaImage from '@/components/MkMediaImage.vue';
 
 const props = defineProps<{
diff --git a/packages/frontend/src/components/page/page.note.vue b/packages/frontend/src/components/page/page.note.vue
index d052ce2c1f862c829ac87947f0bf4282c2014be7..5ca707dbc22fbb603a2ecb70f6edcfbbf925cf75 100644
--- a/packages/frontend/src/components/page/page.note.vue
+++ b/packages/frontend/src/components/page/page.note.vue
@@ -13,7 +13,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 <script lang="ts" setup>
 import { onMounted, Ref, ref } from 'vue';
 import * as Misskey from 'misskey-js';
-import { NoteBlock } from './block.type';
+import { NoteBlock } from './block.type.js';
 import MkNote from '@/components/MkNote.vue';
 import MkNoteDetailed from '@/components/MkNoteDetailed.vue';
 import * as os from '@/os.js';
diff --git a/packages/frontend/src/components/page/page.section.vue b/packages/frontend/src/components/page/page.section.vue
index 84d0399cf825e91cc92a716ccb7fcffef4966b1d..e4e5a43b594bca67c44e4de093a61860b51206e3 100644
--- a/packages/frontend/src/components/page/page.section.vue
+++ b/packages/frontend/src/components/page/page.section.vue
@@ -25,7 +25,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 <script lang="ts" setup>
 import { defineAsyncComponent } from 'vue';
 import * as Misskey from 'misskey-js';
-import { SectionBlock } from './block.type';
+import { SectionBlock } from './block.type.js';
 
 const XBlock = defineAsyncComponent(() => import('./page.block.vue'));
 
diff --git a/packages/frontend/src/components/page/page.text.vue b/packages/frontend/src/components/page/page.text.vue
index 892522d4b54b86ad2cc1bc041f82fbb10e8a1db2..c0849a6d427212b31de0fcd796bf0bad0a84d4d8 100644
--- a/packages/frontend/src/components/page/page.text.vue
+++ b/packages/frontend/src/components/page/page.text.vue
@@ -14,7 +14,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 import { defineAsyncComponent } from 'vue';
 import * as mfm from '@sharkey/sfm-js';
 import * as Misskey from 'misskey-js';
-import { TextBlock } from './block.type';
+import { TextBlock } from './block.type.js';
 import { extractUrlFromMfm } from '@/scripts/extract-url-from-mfm.js';
 
 const MkUrlPreview = defineAsyncComponent(() => import('@/components/MkUrlPreview.vue'));
diff --git a/packages/frontend/src/directives/hotkey.ts b/packages/frontend/src/directives/hotkey.ts
index 85f06c098dd8dd5a0603cd40288631f18f47fd7c..13e548299fcf35ea99f2beb1b8de16ebfe3fbe5e 100644
--- a/packages/frontend/src/directives/hotkey.ts
+++ b/packages/frontend/src/directives/hotkey.ts
@@ -4,7 +4,7 @@
  */
 
 import { Directive } from 'vue';
-import { makeHotkey } from '../scripts/hotkey';
+import { makeHotkey } from '../scripts/hotkey.js';
 
 export default {
 	mounted(el, binding) {
diff --git a/packages/frontend/src/directives/index.ts b/packages/frontend/src/directives/index.ts
index fad6960948699c1f7ba6f8a56fa30251a2ac1f7a..fcd7c3091e2ed333b2e5d64873326bea63a95232 100644
--- a/packages/frontend/src/directives/index.ts
+++ b/packages/frontend/src/directives/index.ts
@@ -5,17 +5,17 @@
 
 import { App } from 'vue';
 
-import userPreview from './user-preview';
-import getSize from './get-size';
-import ripple from './ripple';
-import tooltip from './tooltip';
-import hotkey from './hotkey';
-import appear from './appear';
-import anim from './anim';
-import clickAnime from './click-anime';
-import panel from './panel';
-import adaptiveBorder from './adaptive-border';
-import adaptiveBg from './adaptive-bg';
+import userPreview from './user-preview.js';
+import getSize from './get-size.js';
+import ripple from './ripple.js';
+import tooltip from './tooltip.js';
+import hotkey from './hotkey.js';
+import appear from './appear.js';
+import anim from './anim.js';
+import clickAnime from './click-anime.js';
+import panel from './panel.js';
+import adaptiveBorder from './adaptive-border.js';
+import adaptiveBg from './adaptive-bg.js';
 
 export default function(app: App) {
 	for (const [key, value] of Object.entries(directives)) {
diff --git a/packages/frontend/src/pages/admin/_header_.vue b/packages/frontend/src/pages/admin/_header_.vue
index 353030b1b97b0e133bb0ccfa06a6a1fee9d83e54..bac3aa154a07addd2398804e43d284ead7079d6a 100644
--- a/packages/frontend/src/pages/admin/_header_.vue
+++ b/packages/frontend/src/pages/admin/_header_.vue
@@ -38,7 +38,7 @@ import tinycolor from 'tinycolor2';
 import { popupMenu } from '@/os.js';
 import { scrollToTop } from '@/scripts/scroll.js';
 import MkButton from '@/components/MkButton.vue';
-import { globalEvents } from '@/events';
+import { globalEvents } from '@/events.js';
 import { injectPageMetadata } from '@/scripts/page-metadata.js';
 
 type Tab = {
diff --git a/packages/frontend/src/pages/admin/roles.edit.vue b/packages/frontend/src/pages/admin/roles.edit.vue
index b3c06454ae7517c8e203134478e33718b91ce556..548e56d37ed9725bd0da1aa791afdf846091fbbc 100644
--- a/packages/frontend/src/pages/admin/roles.edit.vue
+++ b/packages/frontend/src/pages/admin/roles.edit.vue
@@ -31,7 +31,7 @@ import { i18n } from '@/i18n.js';
 import { definePageMetadata } from '@/scripts/page-metadata.js';
 import { useRouter } from '@/router.js';
 import MkButton from '@/components/MkButton.vue';
-import { rolesCache } from '@/cache';
+import { rolesCache } from '@/cache.js';
 
 const router = useRouter();
 
diff --git a/packages/frontend/src/pages/admin/roles.vue b/packages/frontend/src/pages/admin/roles.vue
index 07cce6d9a57472666faf5f1e83d815e63fd81a0e..9cb48130d8cd518b348b8c407eb0114628980b00 100644
--- a/packages/frontend/src/pages/admin/roles.vue
+++ b/packages/frontend/src/pages/admin/roles.vue
@@ -258,7 +258,7 @@ import { definePageMetadata } from '@/scripts/page-metadata.js';
 import { instance } from '@/instance.js';
 import { useRouter } from '@/router.js';
 import MkFoldableSection from '@/components/MkFoldableSection.vue';
-import { ROLE_POLICIES } from '@/const';
+import { ROLE_POLICIES } from '@/const.js';
 
 const router = useRouter();
 const baseRoleQ = ref('');
diff --git a/packages/frontend/src/pages/clip.vue b/packages/frontend/src/pages/clip.vue
index 041cc0a204cb75f14c9555191b94e74f84d082e3..9b5f0224ccbdd421e2d879acc951f3c713b22ff2 100644
--- a/packages/frontend/src/pages/clip.vue
+++ b/packages/frontend/src/pages/clip.vue
@@ -35,7 +35,7 @@ import * as os from '@/os.js';
 import { definePageMetadata } from '@/scripts/page-metadata.js';
 import { url } from '@/config.js';
 import MkButton from '@/components/MkButton.vue';
-import { clipsCache } from '@/cache';
+import { clipsCache } from '@/cache.js';
 import { isSupportShare } from '@/scripts/navigator.js';
 import copyToClipboard from '@/scripts/copy-to-clipboard.js';
 
diff --git a/packages/frontend/src/pages/my-antennas/edit.vue b/packages/frontend/src/pages/my-antennas/edit.vue
index a325eb9b0f626eeb566b8b749c45e989665d49cf..6cb368ca9d9b14b4c9d5c4ef9aff1a03f7db4c85 100644
--- a/packages/frontend/src/pages/my-antennas/edit.vue
+++ b/packages/frontend/src/pages/my-antennas/edit.vue
@@ -16,7 +16,7 @@ import * as os from '@/os.js';
 import { i18n } from '@/i18n.js';
 import { useRouter } from '@/router.js';
 import { definePageMetadata } from '@/scripts/page-metadata.js';
-import { antennasCache } from '@/cache';
+import { antennasCache } from '@/cache.js';
 
 const router = useRouter();
 
diff --git a/packages/frontend/src/pages/my-antennas/index.vue b/packages/frontend/src/pages/my-antennas/index.vue
index 2a5fe0795714b41c340ac5d0050c35e96e6a1a5b..b46fb7a5d79d404b2bfbf19d6773d49d4a2fffff 100644
--- a/packages/frontend/src/pages/my-antennas/index.vue
+++ b/packages/frontend/src/pages/my-antennas/index.vue
@@ -32,7 +32,7 @@ import { onActivated, computed } from 'vue';
 import MkButton from '@/components/MkButton.vue';
 import { i18n } from '@/i18n.js';
 import { definePageMetadata } from '@/scripts/page-metadata.js';
-import { antennasCache } from '@/cache';
+import { antennasCache } from '@/cache.js';
 import { infoImageUrl } from '@/instance.js';
 
 const antennas = computed(() => antennasCache.value.value ?? []);
diff --git a/packages/frontend/src/pages/my-clips/index.vue b/packages/frontend/src/pages/my-clips/index.vue
index 31ccf9ce2d7a589a743f581e828412192e0fab52..05a3ec4d2e9cb35e2a6c8457911aa25c8635b10d 100644
--- a/packages/frontend/src/pages/my-clips/index.vue
+++ b/packages/frontend/src/pages/my-clips/index.vue
@@ -33,7 +33,7 @@ import MkClipPreview from '@/components/MkClipPreview.vue';
 import * as os from '@/os.js';
 import { i18n } from '@/i18n.js';
 import { definePageMetadata } from '@/scripts/page-metadata.js';
-import { clipsCache } from '@/cache';
+import { clipsCache } from '@/cache.js';
 
 const pagination = {
 	endpoint: 'clips/list' as const,
diff --git a/packages/frontend/src/pages/my-lists/index.vue b/packages/frontend/src/pages/my-lists/index.vue
index b0d750b218326aa2a5451278a4347bea525baf10..3379cf43d40a3590db1cd04c3c08d17502c0ac40 100644
--- a/packages/frontend/src/pages/my-lists/index.vue
+++ b/packages/frontend/src/pages/my-lists/index.vue
@@ -35,7 +35,7 @@ import MkAvatars from '@/components/MkAvatars.vue';
 import * as os from '@/os.js';
 import { i18n } from '@/i18n.js';
 import { definePageMetadata } from '@/scripts/page-metadata.js';
-import { userListsCache } from '@/cache';
+import { userListsCache } from '@/cache.js';
 import { infoImageUrl } from '@/instance.js';
 import { $i } from '@/account.js';
 
diff --git a/packages/frontend/src/pages/settings/navbar.vue b/packages/frontend/src/pages/settings/navbar.vue
index 0112543781f58aa77779e56992de30a230ccf1b7..f3c9ec8926de5cbf2255e3b18fb334a88329fced 100644
--- a/packages/frontend/src/pages/settings/navbar.vue
+++ b/packages/frontend/src/pages/settings/navbar.vue
@@ -52,7 +52,7 @@ import MkButton from '@/components/MkButton.vue';
 import FormSlot from '@/components/form/slot.vue';
 import MkContainer from '@/components/MkContainer.vue';
 import * as os from '@/os.js';
-import { navbarItemDef } from '@/navbar';
+import { navbarItemDef } from '@/navbar.js';
 import { defaultStore } from '@/store.js';
 import { unisonReload } from '@/scripts/unison-reload.js';
 import { i18n } from '@/i18n.js';
diff --git a/packages/frontend/src/pages/settings/theme.manage.vue b/packages/frontend/src/pages/settings/theme.manage.vue
index a2ecd0574fe1014e99ccd30486886d3e2863dd78..366c39c010eeff49f30e0551a095a12f791b546d 100644
--- a/packages/frontend/src/pages/settings/theme.manage.vue
+++ b/packages/frontend/src/pages/settings/theme.manage.vue
@@ -40,7 +40,7 @@ import MkButton from '@/components/MkButton.vue';
 import { Theme, getBuiltinThemesRef } from '@/scripts/theme.js';
 import copyToClipboard from '@/scripts/copy-to-clipboard.js';
 import * as os from '@/os.js';
-import { getThemes, removeTheme } from '@/theme-store';
+import { getThemes, removeTheme } from '@/theme-store.js';
 import { i18n } from '@/i18n.js';
 import { definePageMetadata } from '@/scripts/page-metadata.js';
 
diff --git a/packages/frontend/src/pages/settings/theme.vue b/packages/frontend/src/pages/settings/theme.vue
index 58c0b8fc82d88b689ff89f45679db70030500526..cb9c714441a55d21b56ecb98ffe913adb04b4da9 100644
--- a/packages/frontend/src/pages/settings/theme.vue
+++ b/packages/frontend/src/pages/settings/theme.vue
@@ -85,7 +85,7 @@ import { ColdDeviceStorage, defaultStore } from '@/store.js';
 import { i18n } from '@/i18n.js';
 import { instance } from '@/instance.js';
 import { uniqueBy } from '@/scripts/array.js';
-import { fetchThemes, getThemes } from '@/theme-store';
+import { fetchThemes, getThemes } from '@/theme-store.js';
 import { definePageMetadata } from '@/scripts/page-metadata.js';
 import { miLocalStorage } from '@/local-storage.js';
 
diff --git a/packages/frontend/src/pages/theme-editor.vue b/packages/frontend/src/pages/theme-editor.vue
index 6c4a54eb5c068f178776bcca8ff632e0b4cf4f3c..4b4196d0a97260246727ba2b02bd219703415b53 100644
--- a/packages/frontend/src/pages/theme-editor.vue
+++ b/packages/frontend/src/pages/theme-editor.vue
@@ -91,7 +91,7 @@ import darkTheme from '@/themes/_dark.json5';
 import { host } from '@/config.js';
 import * as os from '@/os.js';
 import { ColdDeviceStorage, defaultStore } from '@/store.js';
-import { addTheme } from '@/theme-store';
+import { addTheme } from '@/theme-store.js';
 import { i18n } from '@/i18n.js';
 import { useLeaveGuard } from '@/scripts/use-leave-guard.js';
 import { definePageMetadata } from '@/scripts/page-metadata.js';
diff --git a/packages/frontend/src/pages/user/home.stories.impl.ts b/packages/frontend/src/pages/user/home.stories.impl.ts
index 80b4f1a9e975c53b23e498a28f10cfe040a0d51c..a2ef5d50d1ef8dd2e7c3c1150f612176e22c8db0 100644
--- a/packages/frontend/src/pages/user/home.stories.impl.ts
+++ b/packages/frontend/src/pages/user/home.stories.impl.ts
@@ -6,8 +6,8 @@
 /* eslint-disable @typescript-eslint/explicit-function-return-type */
 import { StoryObj } from '@storybook/vue3';
 import { rest } from 'msw';
-import { userDetailed } from '../../../.storybook/fakes';
-import { commonHandlers } from '../../../.storybook/mocks';
+import { userDetailed } from '../../../.storybook/fakes.js';
+import { commonHandlers } from '../../../.storybook/mocks.js';
 import home_ from './home.vue';
 export const Default = {
 	render(args) {
diff --git a/packages/frontend/src/scripts/upload/compress-config.ts b/packages/frontend/src/scripts/upload/compress-config.ts
index 8fe64c8b76b97af35c8be339a0b838e166b421f9..2deb9cbb816db72fba7b352c3e9caad02544d1fe 100644
--- a/packages/frontend/src/scripts/upload/compress-config.ts
+++ b/packages/frontend/src/scripts/upload/compress-config.ts
@@ -4,7 +4,7 @@
  */
 
 import isAnimated from 'is-file-animated';
-import { isWebpSupported } from './isWebpSupported';
+import { isWebpSupported } from './isWebpSupported.js';
 import type { BrowserImageResizerConfig } from 'browser-image-resizer';
 
 const compressTypeMap = {
diff --git a/packages/frontend/src/ui/_common_/common.vue b/packages/frontend/src/ui/_common_/common.vue
index 6b69e1accf30a6312a223e321ee6d77026aaa057..6ece7d86d75187f73af0a4a1d1abf4a3a8344c15 100644
--- a/packages/frontend/src/ui/_common_/common.vue
+++ b/packages/frontend/src/ui/_common_/common.vue
@@ -47,7 +47,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 <script lang="ts" setup>
 import { defineAsyncComponent, ref } from 'vue';
 import * as Misskey from 'misskey-js';
-import { swInject } from './sw-inject';
+import { swInject } from './sw-inject.js';
 import XNotification from './notification.vue';
 import { popups, pendingApiRequestsCount } from '@/os.js';
 import { uploads } from '@/scripts/upload.js';
@@ -56,7 +56,7 @@ import { $i } from '@/account.js';
 import { useStream } from '@/stream.js';
 import { i18n } from '@/i18n.js';
 import { defaultStore } from '@/store.js';
-import { globalEvents } from '@/events';
+import { globalEvents } from '@/events.js';
 
 const XStreamIndicator = defineAsyncComponent(() => import('./stream-indicator.vue'));
 const XUpload = defineAsyncComponent(() => import('./upload.vue'));
diff --git a/packages/frontend/src/ui/_common_/navbar-for-mobile.vue b/packages/frontend/src/ui/_common_/navbar-for-mobile.vue
index 346e5976ba839634924275012d291f77d398a055..618be2db88000b30e53d0ff872f4719017df1f42 100644
--- a/packages/frontend/src/ui/_common_/navbar-for-mobile.vue
+++ b/packages/frontend/src/ui/_common_/navbar-for-mobile.vue
@@ -50,9 +50,9 @@ SPDX-License-Identifier: AGPL-3.0-only
 
 <script lang="ts" setup>
 import { computed, defineAsyncComponent, toRef } from 'vue';
-import { openInstanceMenu } from './common';
+import { openInstanceMenu } from './common.js';
 import * as os from '@/os.js';
-import { navbarItemDef } from '@/navbar';
+import { navbarItemDef } from '@/navbar.js';
 import { $i, openAccountMenu as openAccountMenu_ } from '@/account.js';
 import { defaultStore } from '@/store.js';
 import { i18n } from '@/i18n.js';
diff --git a/packages/frontend/src/ui/classic.header.vue b/packages/frontend/src/ui/classic.header.vue
index 62531a4f4d94a5a0a39898bc795a8923ccdb253e..f0e0271128ccd1b32c85f92d47f2570005e89867 100644
--- a/packages/frontend/src/ui/classic.header.vue
+++ b/packages/frontend/src/ui/classic.header.vue
@@ -48,9 +48,9 @@ SPDX-License-Identifier: AGPL-3.0-only
 
 <script lang="ts" setup>
 import { computed, defineAsyncComponent, onMounted, ref } from 'vue';
-import { openInstanceMenu } from './_common_/common';
+import { openInstanceMenu } from './_common_/common.js';
 import * as os from '@/os.js';
-import { navbarItemDef } from '@/navbar';
+import { navbarItemDef } from '@/navbar.js';
 import { openAccountMenu as openAccountMenu_, $i } from '@/account.js';
 import MkButton from '@/components/MkButton.vue';
 import { defaultStore } from '@/store.js';
diff --git a/packages/frontend/src/ui/deck/column.vue b/packages/frontend/src/ui/deck/column.vue
index 77e074f2ffd691248f41104daef7992701912c09..9ed7e452e3cda0f3317688f1f2b5fb8fe255b337 100644
--- a/packages/frontend/src/ui/deck/column.vue
+++ b/packages/frontend/src/ui/deck/column.vue
@@ -43,7 +43,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 
 <script lang="ts" setup>
 import { onBeforeUnmount, onMounted, provide, watch, shallowRef, ref, computed } from 'vue';
-import { updateColumn, swapLeftColumn, swapRightColumn, swapUpColumn, swapDownColumn, stackLeftColumn, popRightColumn, removeColumn, swapColumn, Column } from './deck-store';
+import { updateColumn, swapLeftColumn, swapRightColumn, swapUpColumn, swapDownColumn, stackLeftColumn, popRightColumn, removeColumn, swapColumn, Column } from './deck-store.js';
 import * as os from '@/os.js';
 import { i18n } from '@/i18n.js';
 import { MenuItem } from '@/types/menu.js';
diff --git a/packages/frontend/src/ui/deck/list-column.vue b/packages/frontend/src/ui/deck/list-column.vue
index 3e0ec6aac0d93d4dad1d45f00762a3ac0a631988..45ecc476e7ae788f515a04be2d792d8d93e6544a 100644
--- a/packages/frontend/src/ui/deck/list-column.vue
+++ b/packages/frontend/src/ui/deck/list-column.vue
@@ -16,7 +16,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 <script lang="ts" setup>
 import { watch, shallowRef, ref } from 'vue';
 import XColumn from './column.vue';
-import { updateColumn, Column } from './deck-store';
+import { updateColumn, Column } from './deck-store.js';
 import MkTimeline from '@/components/MkTimeline.vue';
 import * as os from '@/os.js';
 import { i18n } from '@/i18n.js';
diff --git a/packages/frontend/src/ui/deck/main-column.vue b/packages/frontend/src/ui/deck/main-column.vue
index 4e17cb80fdde1e076f86b174354602edcd1d32b9..cd567040f4cd79f3518df3ba5bf5c17d650a4f56 100644
--- a/packages/frontend/src/ui/deck/main-column.vue
+++ b/packages/frontend/src/ui/deck/main-column.vue
@@ -26,7 +26,7 @@ import * as os from '@/os.js';
 import { i18n } from '@/i18n.js';
 import { mainRouter } from '@/router.js';
 import { PageMetadata, provideMetadataReceiver } from '@/scripts/page-metadata.js';
-import { useScrollPositionManager } from '@/nirax';
+import { useScrollPositionManager } from '@/nirax.js';
 import { getScrollContainer } from '@/scripts/scroll.js';
 
 defineProps<{
diff --git a/packages/frontend/src/widgets/server-metric/index.vue b/packages/frontend/src/widgets/server-metric/index.vue
index 57fbb6811b3e6cf4aec1aa97690d76d0f376e823..ddfc6e68fafbf76408072ac5d066fb48cacc54e5 100644
--- a/packages/frontend/src/widgets/server-metric/index.vue
+++ b/packages/frontend/src/widgets/server-metric/index.vue
@@ -21,7 +21,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 
 <script lang="ts" setup>
 import { onUnmounted, ref } from 'vue';
-import { useWidgetPropsManager, Widget, WidgetComponentExpose } from '../widget';
+import { useWidgetPropsManager, Widget, WidgetComponentExpose } from '../widget.js';
 import XCpuMemory from './cpu-mem.vue';
 import XNet from './net.vue';
 import XCpu from './cpu.vue';
diff --git a/packages/frontend/test/init.ts b/packages/frontend/test/init.ts
index dfc02378d5a4d7a5c0acbfad32501a14f103b6ae..6d93ff8cb0012fc36da5d38da7e5bfee53f0ff99 100644
--- a/packages/frontend/test/init.ts
+++ b/packages/frontend/test/init.ts
@@ -10,7 +10,7 @@ const fetchMocker = createFetchMock(vi);
 fetchMocker.enableMocks();
 
 // Set i18n
-import locales from '../../../locales';
+import locales from '../../../locales/index.js';
 import { updateI18n } from '@/i18n.js';
 updateI18n(locales['en-US']);
 
@@ -28,7 +28,7 @@ vi.mock('@/store.js', () => {
 					media: false,
 					avatar: false,
 					urlPreview: false,
-					code: false,		
+					code: false,
 				},
 
 			},
diff --git a/packages/frontend/vite.config.local-dev.ts b/packages/frontend/vite.config.local-dev.ts
index aea46f423123c46f5cfccb318c8a9a529306d2e2..5a6f511c66080a24b33a9435862e14e0f1e3fe31 100644
--- a/packages/frontend/vite.config.local-dev.ts
+++ b/packages/frontend/vite.config.local-dev.ts
@@ -1,6 +1,6 @@
 import dns from 'dns';
 import { defineConfig } from 'vite';
-import locales from '../../locales';
+import locales from '../../locales/index.js';
 import { getConfig } from './vite.config.js';
 
 dns.setDefaultResultOrder('ipv4first');
diff --git a/packages/frontend/vite.config.ts b/packages/frontend/vite.config.ts
index 8a1c56e6b12f792869a7681518ffb03b78274386..ea8c4ced6082c198e60063c8576d0f0c9f5a8125 100644
--- a/packages/frontend/vite.config.ts
+++ b/packages/frontend/vite.config.ts
@@ -3,10 +3,10 @@ import pluginReplace from '@rollup/plugin-replace';
 import pluginVue from '@vitejs/plugin-vue';
 import { type UserConfig, defineConfig } from 'vite';
 
-import locales from '../../locales';
+import locales from '../../locales/index.js';
 import meta from '../../package.json';
-import pluginUnwindCssModuleClassName from './lib/rollup-plugin-unwind-css-module-class-name';
-import pluginJson5 from './vite.json5';
+import pluginUnwindCssModuleClassName from './lib/rollup-plugin-unwind-css-module-class-name.js';
+import pluginJson5 from './vite.json5.js';
 
 const extensions = ['.ts', '.tsx', '.js', '.jsx', '.mjs', '.json', '.json5', '.svg', '.sass', '.scss', '.css', '.vue'];
 
@@ -26,6 +26,7 @@ const hash = (str: string, seed = 0): number => {
 };
 
 const BASE62_DIGITS = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
+
 function toBase62(n: number): string {
 	if (n === 0) {
 		return '0';