前から記事で紹介していたサービスが公開できるレベルまで開発が完了。
コードがGitHubで公開しているので、諸々紹介
GitHub
URL
使用技術
web & サーバー
その他
サービス概要
- 年間のスケジュールをおおまかに登録できるwebサービス
- 1ヶ月に5つまでタスクが登録できて、1画面で1年間を確認できる
- ログインしないでも使用可能
- ログインすると閲覧にパスワード機能が使用できる(ログインしない場合はURLを知っている場合は誰でも閲覧可能)
機能紹介 & こだわりポイント紹介
印刷ボタンを押した時にきっちり一枚になるように実装
印刷ボタンを押した時にきっちり一枚になるように実装
印刷時の表示はcssは@media print
を使用すれば、styleの変更が可能
js側は以下で印刷時のハンドリングが可能
// 印刷プレビューを開く直前のハンドリング window.addEventListener('beforeprint', handleBeforePrint); // 印刷プレビューが閉じた直前のハンドリング window.addEventListener("afterprint", handleAfterPrint);
ログイン
ログインはNextAuth.jsで実装
以下のページを参考に、Discord、Google、Appleのログインが利用可能
アイコン系は全てemojiで表現
アイコン系は全てemojiで表現。サイト全体でほぼ画像を使用していないのでパフォーマンスも結構良い感じになっている。 Lighthouseの結果は以下の通り
Faviconも干支で切り替わるように設定
Next.jsだと簡単に画面毎に動的にFaviconを変わるように実装可能
表示自体画面のpathにicon.tsxを配置するのみでOK。コード以下のような感じになる
■ src/app/schedule/[id]/icon.tsx
import { ImageResponse } from "next/og"; import dayjs from "dayjs"; import { JpZodiac } from "~/utils/emoji"; export const size = { width: 32, height: 32, }; export const runtime = "edge"; export const contentType = "image/png"; export default function Icon() { return new ImageResponse( ( <div style={{ fontSize: 24, borderRadius: "50%", width: "100%", height: "100%", display: "flex", alignItems: "center", justifyContent: "center", color: "#333", }} > <span>{JpZodiac[(dayjs().year() + 8) % 12]} </span> </div> ), { ...size, }, ); }
ちなみにOGP画像も以下みたいな感じ実装できる
import { ImageResponse } from "@vercel/og"; export const runtime = "edge"; export async function GET() { const fontData = await fetch( new URL("../../../../public/NotoSansJP-Bold2.ttf", import.meta.url), ).then((res) => res.arrayBuffer()); return new ImageResponse( ( <div style={{ background: "white", display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", width: "100%", height: "100%", fontFamily: '"NotoSansJP"', }} > <div style={{ height: 40, backgroundColor: "#000000", width: "100%" }} /> <div style={{ flex: 1, maxWidth: "80%", display: "flex", justifyContent: "center", flexDirection: "column", paddingTop: 30, paddingBottom: 30, }} > <div style={{ fontSize: 28, }} > 年間スケジュール、まとめるなら </div> <div style={{ fontSize: 72, fontWeight: 800, letterSpacing: "0.5rem", paddingLeft: "2rem", }} > OOMAKA </div> </div> <div style={{ height: 40, backgroundColor: "#000000", width: "100%" }} /> </div> ), { width: 1200, height: 630, fonts: [ { name: "NotoSansJP", data: fontData, style: "normal", }, ], }, ); }
サービスを作成した感想
- 個人開発でwebサービスを作ったのが久々だったので学びが多かった
- Next.jsのサポートしている機能が多く、痒いところにも手が届く感が凄い
- ただやりすぎている箇所もあるのでRemix派の気持ちも分かった
- tRPCは最初はTypescriptでしか使えないなら微妙かなと思っていたが、Prismaとの相性が良すぎて生産性の向上に、かなり貢献した
- NextAuthはサーバーサイドとクライアントサイドのどちらでも認証情報が取得できてNext.jsでの認証では必須
- 最近アプリの開発ばかりしていたが、久々に別の最新技術に触れると刺激的で楽しかった