ポートフォリオメディアサイト開発

事例ライブラリ

ポートフォリオメディアサイト開発

プロジェクト概要

「思想と技術を伝えるポートフォリオ型メディアサイト」をFlaskで構築した開発事例です。Markdownベースで記事を管理できるCMSとして設計し、見栄えと効率性を両立させることを目標としました。

背景・課題

なぜ作ったのか

従来の静的サイトジェネレーターやWordPressでは、以下の課題がありました:

  • 効率性の問題: 記事作成から公開までの手順が煩雑
  • 思想の表現: 技術だけでなく「なぜ作ったか」を伝える構造が不足
  • 継続性: 書き続けやすい環境の不備
  • カスタマイズ性: 独自の要件に柔軟に対応できない

解決アプローチ

「何を作ったか」より「なぜ作ったか」を伝える構造

この思想のもと、以下の要素を重視して設計:

  1. Markdownファースト: 効率的な記事作成
  2. モジュラー構造: 思想・実績・日常を明確に分離
  3. 検索・発見: タグとカテゴリによる情報整理
  4. 管理の簡単さ: Webベースの直感的な操作

技術スタック

レイヤー 技術 選定理由
Backend Flask 2.3.3 軽量で拡張性が高い
Database SQLite3 ファイルベースで管理が簡単
Frontend Bootstrap 5.3 レスポンシブ対応済み
Markdown Python-Markdown 豊富な拡張機能
検索 SQLite LIKE句 シンプルで十分な性能
UI/UX Font Awesome 6.0 直感的なアイコン

アーキテクチャ設計

システム構成

📁 portfolio_site/
├── 📄 portfolio_app.py          # Flask メインアプリ
├── 📄 init_db.py               # DB初期化
├── 📁 content/                 # Markdown記事
│   ├── 📁 profile/            # プロフィール・哲学
│   ├── 📁 portfolio/          # 事例ライブラリ
│   └── 📁 notes/              # 開発ノート・雑感
├── 📁 templates/              # Jinja2テンプレート
└── 📁 static/                 # CSS/JS/画像

データモデル

# 記事テーブル
CREATE TABLE articles (
    id INTEGER PRIMARY KEY,
    title TEXT NOT NULL,
    filename TEXT UNIQUE,
    category TEXT NOT NULL,
    tags TEXT,
    created_at TIMESTAMP,
    updated_at TIMESTAMP,
    published BOOLEAN DEFAULT 1
)

主要機能実装

1. Markdown→HTML変換システム

def convert_md_to_html(md_content):
    md = markdown.Markdown(extensions=[
        'extra',        # テーブル、脚注対応
        'codehilite',   # シンタックスハイライト
        'toc',          # 目次自動生成
        'nl2br',        # 改行処理
        'tables'        # テーブル拡張
    ])
    return md.convert(md_content)

特徴:
- Front Matter対応でメタデータ管理
- コードブロックのシンタックスハイライト
- テーブルや引用文の美しいレンダリング

2. カテゴリベース記事管理

3つの軸で情報を整理:

  • Profile (/category/profile): 開発哲学・思想
  • Portfolio (/category/portfolio): 技術事例・実績
  • Notes (/category/notes): 学習記録・雑感
@app.route('/category/<category>')
def category_view(category):
    articles = get_articles(category=category)
    category_names = {
        'profile': 'プロフィール・哲学',
        'portfolio': '事例ライブラリ',
        'notes': '開発ノート・雑感'
    }
    return render_template('category.html', ...)

3. 検索・タグシステム

def get_articles(category=None, tag=None, search=None):
    query = "SELECT * FROM articles WHERE published = 1"
    params = []

    if search:
        query += " AND (title LIKE ? OR filename LIKE ?)"
        params.extend([f'%{search}%', f'%{search}%'])

    if tag:
        query += " AND tags LIKE ?"
        params.append(f'%{tag}%')

実装ポイント:
- 全文検索でタイトル・ファイル名を対象
- タグクラウドで記事の傾向を視覚化
- カテゴリ横断での関連記事表示

4. 管理画面(CRUD操作)

記事作成・編集の工夫:
- リアルタイムMarkdownヘルプ表示
- カテゴリ別のクイック作成ボタン
- ファイル名の自動生成(日本語対応)

@app.route('/admin/article/new', methods=['GET', 'POST'])
def admin_new_article():
    if request.method == 'POST':
        title = request.form['title']
        filename = secure_filename(title) + '.md'

        if save_article(title, filename, category, tags, content):
            flash('記事を作成しました', 'success')

UI/UX設計

レスポンシブデザイン

Bootstrap 5を基盤として、以下を重視:

  • モバイルファースト: スマートフォンでの読みやすさ
  • カードレイアウト: 記事一覧の見やすさ
  • ナビゲーション: 直感的なカテゴリ移動

デザインシステム

/* カスタムスタイルの例 */
.hero-section {
    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}

.article-content {
    line-height: 1.7;
}

.article-content pre {
    background: #f8f9fa;
    border-radius: 0.375rem;
    padding: 1rem;
}

開発プロセス

1. 要件定義・設計 (1時間)

  • システム構想案の分析
  • 技術スタック選定
  • データベース設計

2. 基盤実装 (2時間)

  • Flask アプリケーション構築
  • データベーススキーマ作成
  • 基本的なCRUD機能

3. フロントエンド開発 (2時間)

  • Bootstrap 5 テンプレート作成
  • レスポンシブデザイン適用
  • Markdownスタイリング

4. 管理機能・検索機能 (1時間)

  • 管理画面インターフェース
  • 検索・タグ機能実装
  • サンプルデータ作成

技術的チャレンジと解決

1. 日本語ファイル名対応

課題: Markdownファイルの日本語ファイル名とURL安全性

解決: secure_filename() + データベースでのマッピング管理

filename = secure_filename(title) + '.md'
# "私の開発哲学" → "私の開発哲学.md"

2. Markdown拡張機能の活用

課題: 標準Markdownでは表現力が不足

解決: Python-Markdownの拡張機能を組み合わせ
- extra: テーブル・脚注・定義リスト
- codehilite: Pygmentsベースのハイライト
- toc: 見出しからの目次自動生成

3. 検索性能の最適化

課題: 記事数増加時の検索パフォーマンス

現在の対応: SQLite LIKE句での部分一致検索
将来の拡張: Whoosh や Elasticsearchへの移行を検討

学習・収穫

技術面

  • Flask の軽量性: 小規模アプリには最適な選択
  • SQLite の利便性: 開発・デプロイの簡単さを実感
  • Bootstrap 5: Grid システムの進化とユーティリティクラス

設計面

  • 情報アーキテクチャ: カテゴリ設計の重要性
  • ユーザビリティ: 書き手目線での管理画面設計
  • 拡張性: 将来機能追加を見越したコード構造

プロジェクト管理

  • 段階的実装: MVP → 機能追加のアプローチ
  • ドキュメント化: README・コメントの充実
  • バージョン管理: 適切なコミットメッセージの重要性

成果・効果

定量的成果

  • 開発時間: 約6時間で基本機能完成
  • コード行数: 1,777行(テンプレート含む)
  • ファイル数: 20ファイル(新規作成)

定性的成果

  • 使いやすさ: 直感的な記事作成・編集体験
  • 保守性: シンプルな構造で理解しやすいコード
  • 拡張性: 新機能追加が容易な設計

今後の展開

短期的改善

  • [ ] 画像アップロード機能
  • [ ] 記事のドラフト・公開状態管理
  • [ ] コメント・フィードバック機能

長期的発展

  • [ ] 全文検索エンジン強化(Whoosh/Elasticsearch)
  • [ ] 静的サイト生成対応
  • [ ] API化による外部連携
  • [ ] 多言語対応

パフォーマンス最適化

  • [ ] 記事キャッシュ機能
  • [ ] CDN対応
  • [ ] データベースインデックス最適化

まとめ

このプロジェクトを通じて、「効率性と見栄えの両立」という当初の目標を達成できました。

特に重要だったのは:

  1. 問題の本質理解: 単なるブログではなく「思想を伝える」メディア
  2. 技術選択の妥当性: Flask + SQLiteの軽量さが開発速度に貢献
  3. ユーザー体験重視: 書き手(自分)が使いやすい管理画面

「技術は手段、目的は価値の創造」

この開発を通じて改めて実感したのは、技術的な実装よりも「なぜ作るのか」「誰のために作るのか」という目的意識の重要性でした。

関連技術

Flask Python SQLite Bootstrap Markdown HTML/CSS JavaScript Git Web開発 ポートフォリオ

同様の開発をご希望ですか?

この事例と同様の開発やカスタマイズについて、
お気軽にご相談ください。

お問い合わせ