diff --git a/src/pages/honkai3rd/prints/stigmata/[stigmataId].tsx b/src/pages/honkai3rd/prints/stigmata/[stigmataId].tsx
new file mode 100644
index 00000000..359e13db
--- /dev/null
+++ b/src/pages/honkai3rd/prints/stigmata/[stigmataId].tsx
@@ -0,0 +1,195 @@
+/** @jsxImportSource theme-ui */
+import { NextPageContext } from 'next'
+import React from 'react'
+import PageLink from '../../../../components/atoms/PageLink'
+import { StigmataSetProps } from '../../../../components/pages/StigmataSetPage'
+import { generateI18NPaths, getI18NProps } from '../../../../server/i18n'
+import {
+ listStigmata,
+ getStigmataById,
+ getStigmataListBySetId,
+ getStigmataSetBySetId,
+ listStigmataSet,
+} from '../../../../server/data/honkai3rd/stigmata'
+import { Box, Card, Flex, Heading, Paragraph } from 'theme-ui'
+import SecondaryLabel from '../../../../components/atoms/SecondaryLabel'
+import StigmataCard from '../../../../components/molecules/StigmataCard'
+import { translate, useTranslation } from '../../../../lib/i18n'
+import { useRouter } from 'next/router'
+
+type StigmataShowPageProps = StigmataSetProps
+
+const StigmataListPage = ({
+ stigmataSet,
+ stigmataSetList,
+}: StigmataShowPageProps) => {
+ const { t } = useTranslation()
+ const { locale } = useRouter()
+
+ const stigmataSetName = translate(
+ locale,
+ { 'ko-KR': stigmataSet.krName },
+ stigmataSet.name
+ )
+ const stigmataSetAltName = translate(
+ locale,
+ { 'ko-KR': stigmataSet.krAltName },
+ stigmataSet.altName
+ )
+
+ return (
+
+
+
+ {stigmataSetName}
+
+ {stigmataSetAltName}
+
+
+
+
+ {stigmataSetList.map((stigmataSetItem) => {
+ return (
+
+ )
+ })}
+
+ {stigmataSetList.map((stigmataSetItem) => {
+ const stigmataName = translate(
+ locale,
+ { 'ko-KR': stigmataSetItem.krName },
+ stigmataSetItem.name
+ )
+ const stigmataSkillDescrpition = translate(
+ locale,
+ { 'ko-KR': stigmataSetItem.skill.krDescription },
+ stigmataSetItem.skill.description
+ )
+ return (
+
+
+
+
+ {stigmataName}
+
+
+
+ {t(`stigmata-show.${stigmataSetItem.type}`)}
+
+
+
+ HP : {stigmataSetItem.hp} / ATK : {stigmataSetItem.atk} / DEF :{' '}
+ {stigmataSetItem.def} / CRT : {stigmataSetItem.crt}
+
+
+ {stigmataSkillDescrpition}
+
+
+ )
+ })}
+
+
+
+
+ {translate(
+ locale,
+ { 'ko-KR': stigmataSet.twoSetSkill.krName },
+ stigmataSet.twoSetSkill.name
+ )}
+
+
+ {translate(
+ locale,
+ { 'ko-KR': stigmataSet.twoSetSkill.krDescription },
+ stigmataSet.twoSetSkill.description
+ )}
+
+
+ {translate(
+ locale,
+ {
+ 'ko-KR': stigmataSet.threeSetSkill.krName,
+ },
+ stigmataSet.threeSetSkill.name
+ )}
+
+
+ {translate(
+ locale,
+ { 'ko-KR': stigmataSet.threeSetSkill.krDescription },
+ stigmataSet.threeSetSkill.description
+ )}
+
+
+
+ )
+}
+
+export default StigmataListPage
+
+export async function getStaticProps({
+ params,
+ locale,
+}: NextPageContext & { params: { stigmataId: string } }) {
+ const stigmataData = getStigmataById(params.stigmataId)!
+ if (stigmataData != null) {
+ return {
+ props: {
+ type: 'single',
+ stigmataData: stigmataData,
+ stigmataSetList: (getStigmataListBySetId(stigmataData.set!) || []).sort(
+ (a, b) => -a.type.localeCompare(b.type)
+ ),
+ stigmataSet: getStigmataSetBySetId(stigmataData.set!) || null,
+ ...(await getI18NProps(locale)),
+ },
+ }
+ }
+ const [stigmataSetId] = params.stigmataId.split('-set')
+ const stigmataSet = getStigmataSetBySetId(stigmataSetId)!
+ return {
+ props: {
+ type: 'set',
+ stigmataSet,
+ stigmataSetList: (getStigmataListBySetId(stigmataSet.id) || []).sort(
+ (a, b) => -a.type.localeCompare(b.type)
+ ),
+ ...(await getI18NProps(locale)),
+ },
+ }
+}
+
+export async function getStaticPaths() {
+ return {
+ paths: generateI18NPaths([
+ ...listStigmata().map((stigmata) => {
+ return {
+ params: { stigmataId: stigmata.id },
+ }
+ }),
+ ...listStigmataSet().map((stigmataSet) => {
+ return {
+ params: { stigmataId: `${stigmataSet.id}-set` },
+ }
+ }),
+ ]),
+ fallback: false,
+ }
+}
diff --git a/src/pages/honkai3rd/prints/weapons/[weaponId].tsx b/src/pages/honkai3rd/prints/weapons/[weaponId].tsx
new file mode 100644
index 00000000..404ec948
--- /dev/null
+++ b/src/pages/honkai3rd/prints/weapons/[weaponId].tsx
@@ -0,0 +1,185 @@
+/** @jsxImportSource theme-ui */
+import { Box, Card, Heading, Paragraph } from '@theme-ui/components'
+import { NextPageContext } from 'next'
+import SquareImageBox from '../../../../components/atoms/SquareImageBox'
+import { WeaponData } from '../../../../lib/honkai3rd/weapons'
+import { generateI18NPaths, getI18NProps } from '../../../../server/i18n'
+import {
+ getWeaponById,
+ getWeaponMapByIds,
+ listWeapons,
+} from '../../../../server/data/honkai3rd/weapons'
+import { useRouter } from 'next/router'
+import { useTranslation, translate } from '../../../../lib/i18n'
+import PageLink from '../../../../components/atoms/PageLink'
+import { assetsBucketBaseUrl } from '../../../../lib/consts'
+import { getBattlesuitMapByIds } from '../../../../server/data/honkai3rd/battlesuits'
+import { BattlesuitData } from '../../../../lib/honkai3rd/battlesuits'
+import BattlesuitCard from '../../../../components/molecules/BattlesuitCard'
+import WeaponCard from '../../../../components/molecules/WeaponCard'
+
+interface WeaponShowPageProps {
+ weapon: WeaponData
+ battlesuitMap: { [key: string]: BattlesuitData }
+ weaponMap: { [key: string]: WeaponData }
+}
+
+const WeaponShowPage = ({
+ weapon,
+ battlesuitMap,
+ weaponMap,
+}: WeaponShowPageProps) => {
+ const { locale } = useRouter()
+ const { t } = useTranslation()
+
+ const weaponName = translate(locale, { 'ko-KR': weapon.krName }, weapon.name)
+ const weaponCategory = t(`weapons-show.${weapon.category}`)
+
+ return (
+
+ {weaponName}
+
+
+
+
+
+
+
+
+ {weaponCategory}
+
+
+
+ {'⭐'.repeat(weapon.rarity)}
+
+
+ ATK : {weapon.atk} / CRT : {weapon.crt}
+
+ {weapon.battlesuits != null && weapon.battlesuits.length > 0 && (
+
+ {t('weapons-show.best-on')}
+ {weapon.battlesuits.map(({ id: battlesuitId }) => {
+ return (
+
+ )
+ })}
+
+ )}
+ {weapon.priWeapon != null && (
+
+ {t('weapons-show.pri-weapon')}
+
+
+ )}
+ {weapon.originalWeapons != null && weapon.originalWeapons.length > 0 && (
+
+ {t('weapons-show.original-weapon')}
+ {weapon.originalWeapons.map((originalWeaponId) => {
+ return (
+
+ )
+ })}
+
+ )}
+ {/* {weapon.sources != null && (
+
+ {t('weapons-show.sources')}
+ {weapon.sources
+ .sort((a, b) => a.type.localeCompare(b.type))
+ .map((source) => {
+ return
+ })}
+
+ )} */}
+
+
+
+ {weapon.skills.map((skill) => {
+ return (
+
+
+ {translate(locale, { 'ko-KR': skill.krName }, skill.name)}
+
+
+ {translate(
+ locale,
+ { 'ko-KR': skill.krDescription },
+ skill.description
+ )}
+
+
+ )
+ })}
+
+
+ )
+}
+
+export default WeaponShowPage
+
+export async function getStaticProps({
+ params,
+ locale,
+}: NextPageContext & { params: { weaponId: string } }) {
+ const weapon = getWeaponById(params.weaponId)
+ const battlesuitMap = getBattlesuitMapByIds(
+ weapon != null && weapon.battlesuits != null
+ ? weapon.battlesuits.map(({ id }) => id)
+ : []
+ )
+
+ const weaponIds = []
+ if (weapon != null) {
+ if (weapon.priWeapon != null) {
+ weaponIds.push(weapon.priWeapon)
+ }
+ if (weapon.originalWeapons != null) {
+ weaponIds.push(...weapon.originalWeapons)
+ }
+ }
+ const weaponMap = getWeaponMapByIds(weaponIds)
+
+ return {
+ props: {
+ weapon,
+ battlesuitMap,
+ weaponMap,
+ ...(await getI18NProps(locale)),
+ },
+ }
+}
+
+export async function getStaticPaths() {
+ return {
+ paths: generateI18NPaths(
+ listWeapons().map((weapon) => {
+ return {
+ params: { weaponId: weapon.id },
+ }
+ })
+ ),
+ fallback: false,
+ }
+}