たより

stin's Blog icon

stin's Blog

すてぃんの個人ブログです。技術的なこと、日常のこと、雑記など色々書きます。

Claude Code で Shiki のテーマを見比べられるサイトを作った (Jotai もあるよ)

Shiki というコードシンタックスハイライターライブラリがあります。 https://shiki.style/ Shiki は多くのテーマバリエーションを提供しています。それらを並べて見比べたいと思い、Claude Code に作ってもらいました。 https://y-hiraoka.github.io/shiki-...

2026年の目標

あけましておめでとうございました。 2025年の振り返りと2026年の目標を立てていきましょう。 2025年の振り返り 2025年の目標は以下です。 https://blog.stin.ink/articles/new-years-resolutions-for-2025 技術ブログを 12 記事以上書く(媒体は問わな...

ts-rest や他色々を試すために Todo アプリを作る

ts-rest という RPC ライブラリを見かけて気になったので、実際に Todo アプリを作って試してみました。 ts-rest とは https://ts-rest.com/ ts-rest は、REST API を型安全に実装するためのライブラリです。サーバーサイドだけでなく、REST API にアクセスするク...

Hono Conf 2025 に参加してきたので感想を書く

2025年10月18日に開催された Hono Conf に現地参加したので、自分が見たセッションについて覚えている限りで感想を書きます。 https://honoconf.dev/2025 以下、「発表タイトル by 発表者名」で区切って書いていきます。発表資料が見つかったものについてはリンクも貼っておきます。 令和最...

Next.js on Cloudflare Workers (OpenNext) で Drizzle + D1 を使ったユニットテストを書く

OpenNext は Next.js アプリケーションを Vercel 以外に簡単にデプロイするためのツールです。Cloudflare Workers をサポートしています。 Cloudflare 自体も OpenNext によるデプロイを推奨しており、次のコマンドによって OpenNext による Next.js ア...

Drizzle ORM を使った書き捨てスクリプトから Cloudflare D1 にアクセスしたい

Cloudflare D1 (以下 D1) は Cloudflare のリレーショナルデータベースサービスです。実態はリモートにある SQLite です。 Drizzle ORM は TypeScript で各種データベースに接続するデータベースクライアントで ORM です。テーブルスキーマ管理と型安全性に優れています...

resend-local というツールを作った

Resend というメール送信サービスがあります。 そのAPIエミュレーターをローカルで起動する npm パッケージを作りました。次のコマンドでサーバー http://localhost:8005 で起動します。 Resend SDK は Base URL を環境変数経由で変更できます。.envなどで次のように指定すれ...

2025年の目標

あけましておめでとうございました。すでに 6 日が経過してしまいましたが、2024年の振り返りと2025年の目標を立てます。 2024年の振り返り 2024年の目標は以下の通りでした。 https://blog.stin.ink/articles/new-years-resolutions-for-2024 技術ブログ...

ハロー!プロジェクトファンクラブのデジタル会員証があまりに杜撰なので、正しい実装を考える

ハロー!プロジェクトのファンクラブ(以下FC)サイトが2024年11月にリニューアルされました。 https://www.upfc.jp/helloproject/news\_detail.php?@uid=s32dbjT7VpPSK55H リニューアル内容のひとつにデジタル会員証があります。 今までプラスチックカード...

指定したWebページを動く状態でクローンする方法

ふと、指定したURLのWebページをクローンして別の環境で再現する方法がないかと考えました。 HTMLとそれが参照するCSS, JavaScript, 画像ファイルなどをダウンロードして保存しておき、静的ファイルとして配信すれば同じWebページを再現できるはずです。 wget を使う wgetコマンドを使えば、HTML...

Honoの捉え方、またはNext.jsとの組み合わせ方

この記事は「Hono Advent Calendar 2024 シリーズ 2」17日目の記事です。 https://qiita.com/advent-calendar/2024/hono HonoというWebフレームワークがあります。Express.jsのような書き方でWebアプリケーションを作れるものです。 Hono...

記事をPicture-in-Pictureで読めるようにしてみた

Document Picture-in-Picture APIというWeb APIがあります。まだブラウザの実装が限定的ですが、Chromeなら116から使えるようです。 https://developer.mozilla.org/en-US/docs/Web/API/Document\_Picture-in-Pict...

Next.js 15にアップデートした

このサイトで使っているNext.jsをv15にアップデートしました。 所詮ブログサイトなのでほとんど大きな変更はないですが、変更した内容を残しておきます。 内容 パッケージのアップデート 使っているNext.js関連のパッケージを一気にアップデートします。 注意点は、Next.js自体はv15が正式リリースされています...

Rust始めてみた。JSONフォーマッターを作ってみた

唐突にRustを使ってみたいと思ったので勉強を始めてみました。 始めた理由 始めてみたかった理由は色々あります。 まずはやはりフロントエンド開発ツールが色々とRustで実装されることです。VercelはTurborepoとTurbopackをRustで実装していますね。JavaScriptコンパイラのSWCもRustで...

React useで非同期処理を簡単に扱う

先日 続・URLシェアを支える技術 CompressionStream という記事をZennに投稿しました。 この記事のためにlz-stringとCompressionStreamの圧縮率を比較できるサイト(以下比較サイト)をVite+Reactで作りました。 https://stinbox.github.io/lz-...

React.FCを使うよ、理に適っているからね

唐突に、React.FCの是非についてポジションを示そうと思ったので書きます。積極的に使う派閥です。 React.FC vs Normal Function Reactで関数コンポーネントを宣言するとき、TypeScriptの型の付け方として大きく次のような2つの書き方があります。 React.FCを使うパターン コン...

viteがプラグインなしでできることを探る

pluginを使わずにviteだけで始めてみることで理解が深まったらいいと思い、やってみる。 セットアップ 適当なディレクトリ内で、git初期化してnpm初期化してviteとTypeScriptをインストールする。 package.jsonのtypeはmoduleにして、scriptsにnpm run buildを追加...

真にチラつかないダークモードをついに実現したぞ。実現方法と気付きを書く

このサイトはダークモードに対応しています。なぜならダークモードは基本的人権だからです(要出典)。 しばらく、サイトに訪問した直後ライトモードとダークモードが切り替わってチラつく現象が発生していました。これを改善したので、実装方法と気付いたことを残しておきます。 ダークモードの実装方法 一般に、ダークモードの実装方法は3...

Remix を Cloudflare Pages にデプロイするまでやってみる

Remix に興味を持ったのでドキュメントを読み漁ってだいたい読み切ったので、練習がてら Node.js 向け Remix テンプレートを修正して Cloudflare Pages にデプロイする。 create-remix という npx コマンドでさっとテンプレートを作る。プロジェクト名は remix-on-clo...

2024年の目標

あけましておめでとうございました。すでに 5 日が経過してしまいましたが、2024 年の目標を立てます。 技術ブログを 20 記事以上書く(媒体は問わない) 個人開発アプリを 1 つリリースする 引っ越す 加えて、達成する目標とはちょっと違いますが、行動指針として「思い立ったらすぐに行動する」を掲げます。 2023 年...

react-markdown をやめて remark から自力でレンダリングするようにした話

Intro このブログサイトの記事ページではこれまで react-markdown というライブラリでマークダウンを HTML に変換して表示していました。この度、react-markdown を剥がして remark を直接使って記事をレンダリングするように変更しました。 前回の記事で Playwright で VR...

ブログに Playwright で VRT を導入した

Intro 記事ページのスタイルを維持したまま内部実装に大きめの変更を加えたかったので、Visual Regression Test(VRT)を導入しました。 といってもあまりに簡易的な内容です。CI で自動化とか Chromatic とか大規模なことはしていません。ただローカルPCで Playwright を動かして...

ポケモンBGMループ再生サイトの音声ファイルをキャッシュするために色々調べた

Intro 以前の記事でポケモンBGMループ再生サイトを Cloudflare Pages に載せ替えた話をつらつらと書きました。 https://blog.stin.ink/articles/pokemon-soundlibrary-on-cloudflare この記事が多くの方にご覧頂けて非常に嬉しい限りです。 そ...

ポケモンBGMループ再生サイトを Cloudflare Pages に載せ替えた

Intro https://pokemon-soundlibrary.stin.ink/ このポケモンのBGMを無限ループで再生できる Next.js 製サイトは、これまで Vercel にデプロイしていました。しかし Vercel にデプロイすることはいくつか問題点を抱えていました。 大量の音声ファイルを publi...

Next.js App Router の Static Exports の可能性を探るためにブログでやってみた話

Next.js Advent Calendar 2023 の12月4日の記事です。 https://qiita.com/advent-calendar/2023/next Static Exports とは Next.js の Static Exports は Next.js のビルド結果として完全に静的な HTML,...

stin.ink を Google Domains から Cloudflare Registrar に移管した

Cloudflare Registrar に移管した このブログもサブドメインとして使用されている stin.ink は、僕が持つ唯一のドメインです。Google Domains で取得して、色々サブドメインを生やして使っています。 半年ほど前ですが、Google Domains がサービスを終了して事業譲渡されること...

個人ブログ開発でとても便利な Contentlayer を導入してみた

またまた自分のブログサイトを改修した報告です。自分のブログサイトを改修してはそれをネタに記事を書くのを繰り返していて、なんか面白いですね。 このブログはソースコードと同じリポジトリに Markdown 記事を保存しています。サイト自体は Next.js で、Markdown はただの .md ファイルです。 これまで気...

Chakra UI は "use client" なしで使えるようになった「だけ」

Chakra UI が自分で "use client" を付けている 最近 Chakra UI が "use client" を付けずとも Next.js の App Router で使えるようになったと話題になりました。しかし調べてみると、どうやら JS 非依存なコードに書き換えられた訳ではなく、Chakra UI ...

ブログの記事ページに Table of Contents を設置したので実装方法などを書く

画面幅 991px 以上で閲覧すると、記事ページの右側に目次リンクが表示されるように実装しました。 目次生成ライブラリ tocbot tocbot というライブラリを使用しました。 https://tscanlin.github.io/tocbot 今までこちらのライブラリの存在を知らずに、どうやって実装しようか迷子に...

ポケモンBGMループ再生サイトをアップデートした

https://pokemon-soundlibrary.stin.ink ポケモン公式が公開している「ポケットモンスター ダイヤモンド・パール」の BGM をループ再生できるようにしたサイトを以前作りました。その後公式から「ポケットモンスター 赤・緑」の BGM も配布されたので、追加分も再生できるようにアップデート...

ブログのデザインを刷新した

このサイトのデザインを刷新しました(1 年半ぶり 2 回目)。 変更した理由 最近 Vercel のエンジニアが開発している Nextra という静的サイトジェネレーターをよく見かけるようになりました(出来たばかりのツールではなく、自分が意識的に見るようになったという意味)。このツールで実装できるサイトのダークモードデ...

localStorage に同期する React State を作るカスタムフック

React の useState と似た使い方で localStorage に保存されるカスタムフック useLocalStorage の実装を紹介します。このブログサイトのソースコードで使用しています。 react-use に同じ目的同じ名前のカスタムフックが入っていることは知っていますが、インターフェイスも内部実装...

ブログサイトを Next.js App Router に移行したので学びを書く

このサイトを Next.js App Router で実装し直しました。Server Components が扱えてなんか便利なやつです。 移行にあたって学んだことや App Router の嬉しいポイントなどを書いておきます。 スタイリングメソッドの移行 このブログサイトのスタイリングは vanilla-extrac...

個人ブログから Chakra UI を剥がして vanilla-extract を入れた(剥がした理由編)

すてぃんのブログから Chakra UI を剥がして vanilla-extract を導入しました。見た目はほとんど変わっていませんが、Chakra UI でスタイリングされていたものをすべて vanilla-extract で 1 から作り直しました。 ライブラリの変更理由は以下の通り。 最近 vanilla-ex...

2022 年振り返りを書き散らし

Hello! Project Year-End Party 2022 〜GOOD BYE & HELLO ! 〜参戦帰りの電車内で暇だったので書き散らす。 生活スタイル 2022 年の前半はアパートの隣の部屋の物音が気になりすぎてメンタルを壊しかけた。自分が過敏なだけかもしれないとメンタルクリニック的なところにも行くか...

@vercel/og を使ってブログに動的 og:image 生成を実装した

Vercel で og:image の動的生成するなら一択 先日 Vercel から HTML\&CSS で画像を生成できるライブラリ @vercel/og が発表されました。 https://vercel.com/blog/introducing-vercel-og-image-generation-fast-dyn...

Firebase Auth, Firestore, Functions for Firebase でサクッと管理者権限を割り振る

Firebase のユーザーに個別に権限を割り振りたい要件は多そう。すでに似たような記事はたくさんありますが、自分も実装方法を調べたので文章にしておきます。 実装イメージ Firebase Auth のカスタムクレームを使用します。Firebase ユーザーオブジェクトに独自のプロパティを生やすことができる機能です。 ...

React + TypeScript 用の eslint セットアップメモ書き

Vite で立ち上げた React + TypeScript プロジェクトには eslint のセットアップはされていない。プライベートでちょっとライブラリを試すみたいなケースでしか Vite を使っていなかったので eslint なしで作業していたが、やっぱり useEffect の依存配列の渡し漏れをして混乱するこ...

React でキーボードショートカットを設定するためのカスタムフックを実装する

以前、『ポケットモンスターダイヤモンド・パール』の BGM をループ再生できる Web サイトを作成しました。 https://dp-soundlibrary.stin.ink/ この Web サイトの実装については過去に Zenn に投稿しているのでそちらも御覧ください。 https://zenn.dev/stin/...

WebSocket を使ってみたくて簡単なチャットアプリを作って Google Cloud Run にデプロイしてみる

WebSocket でリアルタイム通信したいんじゃ WebSocket 通信を使ってみたいので調べた学習ノート。Node.js 用ライブラリの ws を使わずに WebSocket サーバー実装とかできたらかっこいいけどとりあえずライブラリに甘えます。 ws による最小構成 サーバーを起動する最小構成。 このコードをコ...

Google AdSense を Next.js 製ブログに入れるのに一手間かかる話

ブログに広告を入れてみたので許してください ブログにちょっとでも広告収入あると嬉しいなと思っていたものの、Adsense は審査が厳しいと聞いていたので手を出していませんでした。でもふとダメ元で申請してみたらなんと承認されて広告を貼り付けられるようになったので導入しました。煩わしく感じない程度の広告数にしておくのでどう...

見た目が同じなだけのコンポーネントを共通化すべきでない

WET is better than DRY https://twitter.com/stin\_factory/status/1522521205080989696 こんなツイートをしたらちょっと反響がありました。 大した事ないツイートがプチバズりしているの不思議 ではありますが、みんな似た経験をしているのでしょう。...

『プロを目指す人のためのTypeScript入門』読書感想文

https://twitter.com/stin\_factory/status/1520251902877118464?s=20\&t=ObJNlQRqSKg5E02UCk5xOw 尊敬する TypeScript の師匠(勝手に思ってるだけ)である uhyo さんが書いた『プロを目指す人のための TypeScript...

HTML 解体新書 読書感想文

https://twitter.com/stin\_factory/status/1516718102813511680 https://www.borndigital.co.jp/book/25999.html Amazon で予約開始してすぐに予約していたものが先日届いて 1 周読み切ったので読書感想文的なものを書...

Next.js ~RSS フィードの実装方法探訪記、或いは、 getServerSideProps での res.end() の考察について~

この個人ブログに RSS フィード機能を実装しました。 RSS フィードとはブログの記事のタイトルや公開日などの情報を XML 形式で配信するものです。 実装方法自体はググって出てきた記事を参考に行いましたが、その中で一つ疑問があったので調べてみました。 参考記事 https://zenn.dev/catnose99/...

ブログに next-seo を導入した

適当にやってた meta タグ設定をちゃんとしました Next.js のプロジェクトの meta タグ類を設定してくれるライブラリ next-seo をインストールしました。 今まで適当に meta タグをセットしていて、特に OGP 系は必須プロパティとかも入れずにやっていましたが、今回 next-seo を導入する...

Twitter シェアボタン React 作り方

Twitter のシェアボタンをブログに設置しました 記事ページの下部に Twitter のシェアボタンと Buy me a coffee のリンクを設置しました! Twitter のシェアボタンを作るに当たって考えたことを書いていきます。 コード https://github.com/y-hiraoka/stin-b...

Twitter ツイート埋め込み機能完全に理解した

Tweet URL を Tweet 埋め込みに変換して表示するように実装しました Tweet の URL だけを Markdown に記述すると ↓ Tweet 埋め込みの iframe が展開されるようにブログを実装しました!↓ https://twitter.com/jack/status/20 この記事では Tw...

ブログをフルリニューアルした!

すてぃんブログレボリューション 21 (updated) このブログサイトをフルリニューアルしました!(5 記事しか書いていなかったのにもうリニューアルとかwwというのはそれはそう) 今回はこのリニューアルについて、こだわりポイントと技術的な内容の 2 つを書こうと思います。 こだわりポイント Web デザイン リニュ...

react-router の型定義が知らない間にきれいになっていたので使い方を再考する

@types/react-router v5.1.9 から型定義がきれいになっていた react-router の型定義は受け取るパスが全て文字列のため、以前は TS コンパイラでパスの間違いを検出できませんでした。 そのため僕は typed-path-builder というライブラリを作って次の記事を書きました。 h...

Immutable.js で React ステートのモデルクラスを作る

Immutable.js で React ステート用モデルクラスを作る 昨今の React は関数コンポーネント一辺倒になり、 React エンジニアがクラス定義する場面はかなり減ってきているんじゃないかと思います。 関数コンポーネント内部で取り回されるステートもクラスインスタンスではなくプレーンなオブジェクトで、それ...

React Context を export するのはアンチパターンではないかと考える

Context を export するな みなさんは React Context を使っていますか?非常に便利ですよね。 え、使ってない?みんな React Context 使っとる。使ってへんのお前だけ。 冗談はさておき、この記事では Context を export するなという内容をお話しします。 React C...

Fragment をコンポーネントのトップに置くのはアンチパターンではないかと考える

Fragment をコンポーネントのトップに置くな 「Fragment をコンポーネントにトップに置く」というのは下のようなコンポーネントを作成することを指します。 これは、この MyComponent が生成する HTML 要素が h1 と p のふたつあるということを意味します。 この書き方がアンチパターンではない...

個人ブログを作ったので初記事を書く

個人ブログを開発しました 「開発」という単語がふさわしいのか不明です。 開発 作成 制作 開発というと大げさな気がします。作成というと軽い気がする。 制作は工作とか美術っぽい。 CMS 使わずにフルスクラッチなので開発でいいでしょう。 stin's blog を支える技術 「〇〇を支える技術」っていう言い回しを使ってみ...