友達リンク
1161字程度約4分
2025-08-17
友達リンクページの設定
友達リンクページは、他のブログやウェブサイトとの相互リンクを表示するためのページです。
友達リンクページの作成
1. ページファイルの作成
src/pages/friends.astro
ファイルを作成します:
---
import BaseLayout from '../layouts/BaseLayout.astro'
import { siteConfig } from '../config'
const title = '友達リンク'
const description = '素晴らしいブログやウェブサイトの友達リンク集'
// 友達リンクのデータ
const friends = [
{
name: 'サイト名1',
url: 'https://example1.com',
avatar: '/images/friends/friend1.jpg',
description: 'サイトの説明文'
},
{
name: 'サイト名2',
url: 'https://example2.com',
avatar: '/images/friends/friend2.jpg',
description: 'サイトの説明文'
}
]
---
<BaseLayout title={title} description={description}>
<main class="container mx-auto px-4 py-8">
<h1 class="text-4xl font-bold mb-8 text-center">友達リンク</h1>
<div class="prose prose-lg max-w-none mb-12">
<p class="text-center text-gray-600">
素晴らしいブログやウェブサイトをご紹介します。
</p>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{friends.map(friend => (
<a
href={friend.url}
target="_blank"
rel="noopener noreferrer"
class="block bg-white rounded-lg shadow-md hover:shadow-lg transition-shadow duration-300 p-6"
>
<div class="flex items-center mb-4">
<img
src={friend.avatar}
alt={friend.name}
class="w-12 h-12 rounded-full mr-4"
/>
<h3 class="text-xl font-semibold">{friend.name}</h3>
</div>
<p class="text-gray-600">{friend.description}</p>
</a>
))}
</div>
<!-- 友達リンク申請セクション -->
<div class="mt-16 bg-gray-50 rounded-lg p-8">
<h2 class="text-2xl font-bold mb-4">友達リンク申請</h2>
<p class="mb-4">相互リンクをご希望の方は、以下の条件をご確認ください:</p>
<ul class="list-disc list-inside mb-6 space-y-2">
<li>定期的に更新されているブログまたはウェブサイト</li>
<li>健全で有益なコンテンツを提供している</li>
<li>相互リンクが可能である</li>
</ul>
<p>
申請をご希望の方は、
<a href="/contact" class="text-blue-600 hover:underline">お問い合わせページ</a>
からご連絡ください。
</p>
</div>
</main>
</BaseLayout>
2. 設定ファイルでの管理
友達リンクのデータを設定ファイルで管理する場合:
// src/config/friends.ts
export interface Friend {
name: string;
url: string;
avatar: string;
description: string;
category?: string;
}
export const friendsData: Friend[] = [
{
name: 'テックブログ',
url: 'https://techblog.example.com',
avatar: '/images/friends/techblog.jpg',
description: 'プログラミングと技術に関する情報を発信',
category: '技術'
},
{
name: 'ライフスタイルブログ',
url: 'https://lifestyle.example.com',
avatar: '/images/friends/lifestyle.jpg',
description: '日常生活のヒントとアイデアを共有',
category: 'ライフスタイル'
},
{
name: 'デザインポートフォリオ',
url: 'https://design.example.com',
avatar: '/images/friends/design.jpg',
description: 'クリエイティブなデザイン作品を展示',
category: 'デザイン'
}
]
3. カテゴリ別表示
---
import { friendsData } from '../config/friends'
// カテゴリ別にグループ化
const friendsByCategory = friendsData.reduce((acc, friend) => {
const category = friend.category || 'その他';
if (!acc[category]) {
acc[category] = [];
}
acc[category].push(friend);
return acc;
}, {} as Record<string, typeof friendsData>);
---
<div class="space-y-12">
{Object.entries(friendsByCategory).map(([category, friends]) => (
<section>
<h2 class="text-2xl font-bold mb-6">{category}</h2>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{friends.map(friend => (
<div class="bg-white rounded-lg shadow-md hover:shadow-lg transition-shadow duration-300 p-6">
<!-- 友達リンクカード -->
</div>
))}
</div>
</section>
))}
</div>
高度なカスタマイズ
1. アニメーション効果
<style>
.friend-card {
transition: all 0.3s ease;
}
.friend-card:hover {
transform: translateY(-5px);
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1);
}
.friend-avatar {
transition: transform 0.3s ease;
}
.friend-card:hover .friend-avatar {
transform: scale(1.1);
}
</style>
2. ランダム表示
---
// 友達リンクをランダムに並び替え
const shuffledFriends = [...friends].sort(() => Math.random() - 0.5);
---
3. 検索機能
<div class="mb-8">
<input
type="text"
id="friendSearch"
placeholder="友達リンクを検索..."
class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
/>
</div>
<script>
document.getElementById('friendSearch').addEventListener('input', function(e) {
const searchTerm = e.target.value.toLowerCase();
const friendCards = document.querySelectorAll('.friend-card');
friendCards.forEach(card => {
const name = card.querySelector('h3').textContent.toLowerCase();
const description = card.querySelector('p').textContent.toLowerCase();
if (name.includes(searchTerm) || description.includes(searchTerm)) {
card.style.display = 'block';
} else {
card.style.display = 'none';
}
});
});
</script>
4. 統計情報
<div class="bg-blue-50 rounded-lg p-6 mb-8">
<div class="grid grid-cols-2 md:grid-cols-4 gap-4 text-center">
<div>
<div class="text-2xl font-bold text-blue-600">{friends.length}</div>
<div class="text-sm text-gray-600">総友達リンク数</div>
</div>
<div>
<div class="text-2xl font-bold text-green-600">
{Object.keys(friendsByCategory).length}
</div>
<div class="text-sm text-gray-600">カテゴリ数</div>
</div>
<div>
<div class="text-2xl font-bold text-purple-600">
{friends.filter(f => f.category === '技術').length}
</div>
<div class="text-sm text-gray-600">技術系サイト</div>
</div>
<div>
<div class="text-2xl font-bold text-orange-600">
{new Date().getFullYear()}
</div>
<div class="text-sm text-gray-600">更新年</div>
</div>
</div>
</div>
SEO最適化
1. 構造化データ
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "CollectionPage",
"name": "友達リンク",
"description": "素晴らしいブログやウェブサイトの友達リンク集",
"url": "https://yoursite.com/friends",
"mainEntity": {
"@type": "ItemList",
"itemListElement": [
{friends.map((friend, index) => ({
"@type": "ListItem",
"position": index + 1,
"item": {
"@type": "WebSite",
"name": friend.name,
"url": friend.url,
"description": friend.description
}
}))}
]
}
}
</script>
2. メタタグの最適化
---
const title = '友達リンク - あなたのサイト名'
const description = '素晴らしいブログやウェブサイトの友達リンク集。技術、ライフスタイル、デザインなど様々なカテゴリのサイトをご紹介。'
const image = '/images/friends-og.jpg'
---
<BaseLayout
title={title}
description={description}
image={image}
>
管理とメンテナンス
1. 定期的なリンクチェック
// scripts/check-friends-links.js
const https = require('https');
const { friendsData } = require('../src/config/friends');
async function checkLink(url) {
return new Promise((resolve) => {
const request = https.get(url, (response) => {
resolve({
url,
status: response.statusCode,
ok: response.statusCode >= 200 && response.statusCode < 400
});
});
request.on('error', () => {
resolve({ url, status: 'error', ok: false });
});
request.setTimeout(5000, () => {
request.destroy();
resolve({ url, status: 'timeout', ok: false });
});
});
}
async function checkAllLinks() {
console.log('友達リンクをチェック中...');
for (const friend of friendsData) {
const result = await checkLink(friend.url);
console.log(`${friend.name}: ${result.ok ? '✅' : '❌'} (${result.status})`);
}
}
checkAllLinks();
2. 申請フォームの作成
<!-- src/components/FriendApplicationForm.astro -->
<form action="/api/friend-application" method="POST" class="space-y-4">
<div>
<label for="siteName" class="block text-sm font-medium text-gray-700">
サイト名
</label>
<input
type="text"
id="siteName"
name="siteName"
required
class="mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md"
/>
</div>
<div>
<label for="siteUrl" class="block text-sm font-medium text-gray-700">
サイトURL
</label>
<input
type="url"
id="siteUrl"
name="siteUrl"
required
class="mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md"
/>
</div>
<div>
<label for="description" class="block text-sm font-medium text-gray-700">
サイト説明
</label>
<textarea
id="description"
name="description"
rows="3"
required
class="mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md"
></textarea>
</div>
<button
type="submit"
class="w-full bg-blue-600 text-white py-2 px-4 rounded-md hover:bg-blue-700"
>
申請を送信
</button>
</form>
注意事項
- プライバシー - 相手の許可を得てからリンクを追加してください
- 品質管理 - 定期的にリンク先の内容を確認してください
- 相互性 - 相互リンクの約束は守りましょう
- 更新頻度 - 定期的にリストを更新してください
友達リンクページは、コミュニティとのつながりを深める重要なページです。適切に管理して、訪問者にとって価値のあるリソースにしましょう。