Astroでブログ作成してみた話 -技術編-
Next.jsばっかりやってたけどAstroでブログ作ってみたら爆速すぎた!1.5秒でビルド完了、設定不要でMarkdown対応、画像最適化も自動。個人ブログ作るならNext.jsよりAstroの方が圧倒的に楽だったので、実際の開発体験と選んだ理由を話します。
「ブログって、記事を書くだけじゃなくて、何か使えるものも置けたら面白くない?」
ふとそんなことを思って、個人ブログに ツールページ を作ってみました。
で、最初に何を作ろうかと考えた結果、「QRフォトメーカー」というやつに着手。
背景写真の上にQRコードを半透明で重ねて、写真が透けて見えるQRコードを生成できるWebツールです。
きっかけの一つは、技術イベントに参加したときの体験。
会場のWi-Fi情報がホワイトボードや紙に書いてあって、一文字ずつ打ち込むんだけど…これが地味に面倒。
「ならQRにしたら一発じゃん」って思ったのが始まりです。
この記事では、企画から実装、そして直した点を中心に振り返ります。
QRフォトメーカーは、ブラウザ上で完結するQRコード生成ツールです。
普通のQRコードって、白と黒の四角が並んだだけで味気ないなぁと思っていて。
このツールでは、背景に好きな写真や色を設定して、その上にQRコードを半透明で重ねることで、 写真が透けて見えるQRコード を作れるようにしました。
主な機能はこんな感じ。
技術スタックは以下の通り。
| 項目 | 選定 |
|---|---|
| フレームワーク | Astro(既存ブログサイトに組み込み) |
| 言語 | TypeScript |
| QR生成 | qr-code-styling |
| 画像合成 | Canvas API(ブラウザ標準) |
| 処理方式 | 全てクライアントサイド完結 |
Astro 5.x / qr-code-styling 1.9.2 で動作確認しています。
QR生成ライブラリは EasyQRCodeJS や QRCode.js などいくつか候補があったんだけど、最終的に qr-code-styling にしました。
決め手は、コミュニティが大きくて情報が見つかりやすかったのと、透明背景が公式でサポートされていたこと。
「これなら写真との合成もやりやすそうだな」と。
もう一つこだわったのは、 処理を全てブラウザ内で完結 させたこと。
そもそもAstroはコンテンツ駆動のフレームワークなので、現状はDBやバックエンドは持ちたくない。
それに、Wi-FiモードではSSIDやパスワードを扱うわけで、サーバーにデータが飛ばない方がプライバシー的にも安心できる。
開いてすぐサッと使える、そういうツールにしたかったし。
さて、このツールの核心は「半透明のQRドットを写真の上に重ねる」部分。
qr-code-stylingの dotsOptions.color にrgba文字列を渡せば半透明ドットになるのか、正直やってみるまで確信が持てなかった。
ドキュメントにも明確には書いてなくて、「まぁ試すか」の精神でやってみたら…あっさりいけた。
拍子抜けするくらいシンプルに収まりました。
const rgbaColor = `rgba(${r}, ${g}, ${b}, ${opacity})`;
const qrCode = new QRCodeStyling({
dotsOptions: {
color: rgbaColor, // rgbaで半透明ドットが実現できた
type: 'rounded',
},
backgroundOptions: {
color: 'transparent', // 背景は透明に
},
qrOptions: {
errorCorrectionLevel: 'H', // 背景と合成するので最高レベルに
},
});
合成の流れは、qr-code-stylingで透明背景のQRを生成 → Canvasに背景を描画 → その上にQRを重ねる、というもの。
ここはすんなりいって正直ホッとした。
背景との合成ではQRドットの一部が見えにくくなるため、誤り訂正レベルは最高の 'H' に設定しています。
これにより約30%のデータ欠損に耐えられます。透過度を下げすぎると読み取れなくなるので、最低値にも制限をかけています。
ここからが本番(というか苦労話)。
Wi-Fiモードでは、入力されたSSIDとパスワードから WIFI:T:WPA;S:MySSID;P:password;; という形式の文字列を生成してQRコードにします。
で、普通のパスワードなら問題ないんだけど、パスワードに ; や : 、" などの特殊文字が含まれていると…フォーマットが壊れる。
これ、テスト中に気づいてちょっと焦りました。
パスワードに特殊文字を使うのはよくある話だし、ここは対応必須。
対策として、Wi-Fi QRコードの仕様で定められた特殊文字をエスケープする関数を追加しました。
function escapeWifiValue(value: string): string {
return value.replace(/([\\;,:"'])/g, '\\$1');
}
function getQRData(): string {
if (currentMode === 'wifi') {
const ssid = escapeWifiValue(ssidInput.value);
const password = escapeWifiValue(passwordInput.value);
const encryption = encryptionSelect.value;
return `WIFI:T:${encryption};S:${ssid};P:${password};;`;
}
return urlInput.value;
}
地味だけど、こういう「普通に使ってたら踏む罠」を潰しておくのは大事。
技術的な問題を片付けた後、一番時間がかかったのが UXの改善 でした。
正直、ここが一番しんどかった。
QRコード周囲の余白(マージン)の調整、最初はスライダーにしてたんです。
でも冷静に考えると、細かい数値を触らせてもユーザーにとっては意味がない。「マージン37pxです」とか言われても困るでしょう。
で、最終的に 「なし / 小 / 大」の3択ボタン に落ち着きました。
Webツールとしてサッと使ってもらうには、選択肢を絞って迷わせないのが正解だなと。
Wi-Fiの暗号化方式は、最初「WPA/WPA2」「WEP」「なし」の3択で作ってました。
ただ、私自身WEPが何なのかよくわかってなくて(おい)、調べてみたら過去に脆弱性が見つかって以降、今はほぼ使われていないらしい。
なので削って「WPA/WPA2(推奨)」「なし(フリーWi-Fi)」の2択に。
ユーザーが迷う選択肢を一つ減らせたのは良かった。
これ、地味にハマったやつ。
背景画像を設定したのにURLをまだ入力していないと、プレビューが真っ白のまま。
ユーザーからすると「背景設定したのに何も表示されない…壊れてる?」ってなるわけです。
対策として、 QRデータ未入力でも背景だけはプレビューに表示 されるようにしました。
「ちゃんと背景は設定できてますよ」という安心感を与える、地味だけど大事な改善。
ちなみにこの状態ではQRコード自体は生成されていないので、ダウンロードボタンも無効のままにしています。
個人ブログに「使えるツール」を置くのは、なかなか面白い体験でした。
記事を書くのとは違う頭の使い方をするし、「自分のサイトにツールがある」というのが地味にテンション上がる。
今回やってみて一番感じたのは、技術的な実装よりもUXの調整に時間がかかるということ。
スライダーを3択ボタンにしたり、使われない規格を削ったり…こういう「ユーザーが迷わない形にする」作業が意外と奥深い。
今後も何かツールを作ってみたいなぁと思っています。
興味がある方は、ぜひ QRフォトメーカー を試してみてください。
読んでくれてありがとう。よかったらシェアやフォロー押してってください。Xで雑に絡んでくれるのも普通に嬉しい。