論文情報テキストを作成するツールをNext.jsで実装

概要
著者名や論文誌名などを入力して、決められたフォーマットの論文情報テキストを作成するツールを、Next.jsで実装する。
フォーマット
著者名, 著者名, 著者名 (年) 論文タイトル. 論文誌名, 巻(号), 開始ページ-終了ページ
サンプル
著者情報は、実在しなさそうな名前を生成AIに考えてもらった。論文情報は、厨二発想で適当に。
星詠月歌, 蒼空海斗, 紅叶霧華 (2025) 超次元転移装置に螺旋構造を用いた場合に起こりうる二極化現象について. 超次元転移研究集, 1(2), 3-4
英語の場合は、著者名を「名字 名前のイニシャル」とする。
Hoshiyomi T, Aozora K, Koyo K (2025) 超次元転移装置に螺旋構造を用いた場合に起こりうる二極化現象について. 超次元転移研究集, 1(2), 3-4
アクセプト状態(詳しくは知らない)の場合は、末尾にその旨を記載する。
星詠月歌, 蒼空海斗, 紅叶霧華 (2025) 超次元転移装置に螺旋構造を用いた場合に起こりうる二極化現象について. 超次元転移研究集, 1(2), 3-4 (accepted)
成果物
Vercelにデプロイした。
https://paper-info-text.vercel.app/
特に認証情報など含まないので、リポジトリはPublicで。
https://github.com/namakurajin/paper-info-text
プロジェクトの作成
プロジェクトディレクトリを用意し、中に展開。
npx create-next-app@latest .
Tailwindは使わない。それ以外はデフォルトで。
✔ Would you like to use TypeScript? … No / Yes✔ Would you like to use ESLint? … No / Yes✔ Would you like to use Tailwind CSS? … No / Yes✔ Would you like your code inside a `src/` directory? … No / Yes✔ Would you like to use App Router? (recommended) … No / Yes✔ Would you like to use Turbopack for `next dev`? … No / Yes✔ Would you like to customize the import alias (`@/*` by default)? … No / Yes
開発サーバが起動できれば完了。
npm run dev# http://localhost:3000/
開発環境の整備
モジュールの追加
npm i @ark-ui/react destyle.css lucide-react react-toastify
モジュール名 | 簡易説明 |
---|---|
@ark-ui/react | ヘッドレスUIライブラリ。 |
lucide-react | アイコンライブラリ。 |
react-toastify | トーストUIライブラリ。 |
npm i -D sass
モジュール名 | 簡易説明 |
---|---|
sass | Sassによるスタイリング。 |
雑記
Reactおさらい
useStateのエラー
You’re importing a component that needs
useState
. This React hook only works in a client component. To fix, mark the file (or its parent) with the"use client"
directive.
useState
を使うコンポーネントを使用する場合は、"use client";
が必要。
ループのエラー
Each child in a list should have a unique “key” prop.
map()
でループさせる要素には、key
属性が必要。
Next.jsおさらい
Hydrationのエラー
Hydration failed because the server rendered HTML didn’t match the client. As a result this tree will be regenerated on the client. This can happen if a SSR-ed Client Component used
Chromeの拡張機能「ColorZilla」が原因でエラーが出たので、無効にした。
faviconやOGP
決められた名前で配置すれば自動で設定してくれる。
https://nextjs.org/docs/app/api-reference/file-conventions/metadata/opengraph-image
https://nextjs.org/docs/app/api-reference/file-conventions/metadata/app-icons
UIライブラリ
ヘッドレスUI(=スタイルなしコンポーネント)のArk UIを使用してみた。以下はチェックボックスの実装例で、ほとんどArk UIのCheckboxに関するドキュメントそのまま。
import { useState } from 'react';import { Checkbox } from '@ark-ui/react/checkbox';import { CheckIcon } from 'lucide-react'import styles from './InputCheckbox.module.scss';
interface Props { label: string; name: string; onChangeStatus(name: string, isChecked: boolean): void;};
export default function InputCheckbox({label, name, onChangeStatus}: Props) { const [checked, setChecked] = useState<Checkbox.CheckedState>(false);
const handleChange = (checked: Checkbox.CheckedState) => { if (checked === 'indeterminate') return; // 今回は不確定要素を考慮しない setChecked(checked); onChangeStatus(name, checked); };
return ( <Checkbox.Root className={styles.wrapper} checked={checked} onCheckedChange={(e) => handleChange(e.checked)} > <Checkbox.Control className={styles.checkbox}> <Checkbox.Indicator> <CheckIcon /> </Checkbox.Indicator> </Checkbox.Control> <Checkbox.HiddenInput name={name} className={styles.input} /> <Checkbox.Label>{label}</Checkbox.Label> </Checkbox.Root> );}
トースト
以下の記事を参考にした。
https://zenn.dev/koyabluetech/articles/78f6a4caf096e2
続く...かもね