プロフィール

arismmn timeline blog

← ブログ一覧に戻る

リンク集ページ「artifacts」を実装した

機能実装AstroUI/UX

概要

気になったウェブページや参考にしたリソースをまとめて表示できるリンク集ページ「artifacts」を実装した。

URLを入力するだけでOGP情報(タイトル・概要・アイキャッチ画像・ドメイン名)を自動取得し、ブログカード形式で表示する。管理画面からリンクの追加・削除・並び替えが可能。


実装内容

データベース

リンクカードのデータを保存する専用テーブルを新設した。各レコードは以下のカラムを持つ。

  • 記事URL
  • サイトタイトル
  • 概要文
  • アイキャッチ画像URL
  • ファビコンURL(Googleファビコンプロキシ経由)
  • ドメイン名
  • 表示順(sort_order)

表示順カラムにインデックスを付けてソートを高速化した。

OGP取得

URLを入力して「取得」ボタンを押すと、既存のOGP取得エンドポイントを呼び出してメタタグを解析する。取得した情報はプレビューとして管理画面に表示され、確認してから「追加」を押すとDBに保存される。

並び替え

カード一覧ではHTML5の Drag and Drop APIを使い、ドラッグ操作で表示順を変更できる。並び替え後は自動で並び替えAPIに送信され、DBの sort_order カラムが更新される。

公開ページのデザイン

2カラムのグリッドレイアウト(スマホは1カラム)でブログカードを並べる。各カードには以下を表示する。

  • アイキャッチ画像(取得できない場合はSVGプレースホルダー)
  • ドメイン名+ファビコン
  • サイトタイトル
  • 概要文(最大3行)

カードはホバーで浮き上がるアニメーションを付け、クリックすると外部ページが新しいタブで開く。


セキュリティ対応

外部URLを扱うページのため、以下のセキュリティ対策を実装した。

URLサニタイズ

  • リンクURLは https:// で始まるもののみ許可する
  • アイキャッチ画像URLも同様に https:// のみ許可する
  • ファビコンURLはGoogleのファビコンプロキシドメインのみ許可する

XSS対策

  • 管理画面のクライアントサイドJavaScriptでは escapeHtml() / escapeAttr() を使い、外部から取得したテキストを直接DOMに挿入しない
  • 公開ページ側ではAstroのテンプレート変数展開(自動エスケープ)を使用する
  • 外部リンクには rel="noopener noreferrer" を付与する

SSRF対策

  • OGP取得処理はバックエンドで行うが、既存のSSRF対策(プライベートIPブロック・タイムアウト)をそのまま継承している

参考

Claude Code
Powered by
Claude Code
(使用モデル Sonnet 4.6)
← ブログ一覧に戻る