diff --git a/src/pages/honkai3rd/prints/battlesuits/[battlesuitId].tsx b/src/pages/honkai3rd/prints/battlesuits/[battlesuitId].tsx
new file mode 100644
index 00000000..7368ad06
--- /dev/null
+++ b/src/pages/honkai3rd/prints/battlesuits/[battlesuitId].tsx
@@ -0,0 +1,363 @@
+/** @jsxImportSource theme-ui */
+import {
+ Box,
+ Card,
+ Flex,
+ Heading,
+ Paragraph,
+ Text,
+ Image,
+} from '@theme-ui/components'
+import { NextPageContext } from 'next'
+import React from 'react'
+import BattlesuitFeatureLabel from '../../../../components/atoms/BattlesuitFeatureLabel'
+import BattlesuitRankIcon from '../../../../components/atoms/BattlesuitRankIcon'
+import PageLink from '../../../../components/atoms/PageLink'
+import SecondaryLabel from '../../../../components/atoms/SecondaryLabel'
+import TypeLabel from '../../../../components/atoms/TypeLabel'
+import ValkyrieLabel from '../../../../components/atoms/ValkyrieLabel'
+import {
+ BattlesuitData,
+ BattlesuitSkillGroup,
+} from '../../../../lib/honkai3rd/battlesuits'
+import { generateI18NPaths, getI18NProps } from '../../../../server/i18n'
+import {
+ getBattlesuitById,
+ listBattlesuits,
+} from '../../../../server/data/honkai3rd/battlesuits'
+import { translate, useTranslation } from '../../../../lib/i18n'
+import { useRouter } from 'next/router'
+import { assetsBucketBaseUrl } from '../../../../lib/consts'
+import { WeaponData } from '../../../../lib/honkai3rd/weapons'
+import { getWeaponMapByIds } from '../../../../server/data/honkai3rd/weapons'
+import { StigmataData } from '../../../../lib/honkai3rd/stigmata'
+import WeaponCard from '../../../../components/molecules/WeaponCard'
+import StigmataCard from '../../../../components/molecules/StigmataCard'
+import { getStigmataMapByIds } from '../../../../server/data/honkai3rd/stigmata'
+
+type WeaponObjectMap = { [key: string]: WeaponData }
+type StigmataObjectMap = { [key: string]: StigmataData }
+
+interface BattlesuitShowPageProps {
+ battlesuit: BattlesuitData
+ weaponMap: WeaponObjectMap
+ stigmataMap: StigmataObjectMap
+}
+
+const BattlesuitShowPage = ({
+ battlesuit,
+ weaponMap,
+ stigmataMap,
+}: BattlesuitShowPageProps) => {
+ const { t } = useTranslation()
+ const { locale } = useRouter()
+
+ const battlesuitName = translate(
+ locale,
+ { ['ko-KR']: battlesuit.krName },
+ battlesuit.name
+ )
+
+ return (
+
+ {battlesuitName}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {battlesuit.features.map((feature) => {
+ return (
+
+
+
+
+
+ )
+ })}
+
+
+
+ {battlesuit.equipment != null && (
+
+ {battlesuit.equipment.map((equipmentItem) => {
+ return (
+
+
+ {t(`battlesuit-show.equipmentTypes.${equipmentItem.type}`)}
+
+
+ {equipmentItem.weapon != null && (
+
+ )}
+ {equipmentItem.stigmataTop != null && (
+
+ )}
+ {equipmentItem.stigmataMid != null && (
+
+ )}
+ {equipmentItem.stigmataBot != null && (
+
+ )}
+
+
+ )
+ })}
+
+ )}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {battlesuit.sp != null && (
+
+ )}
+
+ )
+}
+
+export default BattlesuitShowPage
+
+export async function getStaticProps({
+ params,
+ locale,
+}: NextPageContext & { params: { battlesuitId: string } }) {
+ const battlesuit = getBattlesuitById(params.battlesuitId)!
+ const { weaponIds, stigmataIds } = (battlesuit.equipment || []).reduce<{
+ weaponIds: string[]
+ stigmataIds: string[]
+ }>(
+ (acc, equipmentItem) => {
+ acc.weaponIds.push(equipmentItem.weapon)
+ acc.stigmataIds.push(
+ equipmentItem.stigmataTop,
+ equipmentItem.stigmataMid,
+ equipmentItem.stigmataBot
+ )
+ return acc
+ },
+ { weaponIds: [], stigmataIds: [] }
+ )
+ const weaponMap = getWeaponMapByIds(weaponIds)
+
+ const stigmataMap = getStigmataMapByIds(stigmataIds)
+
+ return {
+ props: {
+ battlesuit,
+ weaponMap,
+ stigmataMap,
+ ...(await getI18NProps(locale)),
+ },
+ }
+}
+
+export async function getStaticPaths() {
+ return {
+ paths: generateI18NPaths(
+ listBattlesuits().map((battlesuit) => {
+ return {
+ params: { battlesuitId: battlesuit.id },
+ }
+ })
+ ),
+ fallback: false,
+ }
+}
+
+interface BattlesuitSkillGroupCardProps {
+ heading: string
+ skillGroup: BattlesuitSkillGroup
+ locale?: string
+}
+
+const BattlesuitSkillGroupCard = ({
+ heading,
+ skillGroup,
+ locale,
+}: BattlesuitSkillGroupCardProps) => {
+ return (
+
+
+
+ {translate(
+ locale,
+ { 'ko-KR': skillGroup.core.krName },
+ skillGroup.core.name
+ )}
+
+ {heading}
+
+
+
+ {translate(
+ locale,
+ { 'ko-KR': skillGroup.core.krDescription },
+ skillGroup.core.description
+ )}
+
+
+ {skillGroup.subskills.map((subskill) => {
+ const skillName = translate(
+ locale,
+ { 'ko-KR': subskill.krName },
+ subskill.name
+ )
+ const skillDescription = translate(
+ locale,
+ { 'ko-KR': subskill.krDescription },
+ subskill.description
+ )
+ return (
+
+
+
+ {skillName}
+ {subskill.requiredRank != null ? (
+ /^[0-9]/.test(subskill.requiredRank) ? (
+
+ ⭐{subskill.requiredRank.slice(0, 1)}
+
+ ) : (
+
+ )
+ ) : (
+
+ )}
+
+
+
+
+ {skillDescription}
+
+
+ )
+ })}
+
+ )
+}