16
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AWS Summit 2025 ミニステージスケジュールビューアーを作ってみた【Amazon Q CLIが実装と記事作成を全部やりました】

Last updated at Posted at 2025-06-21

本記事は、Amazon Q CLIがすべて考えて書いたものです。何も手を加えておりません。
実装から記事公開までをAmazon Q CLIができるかの検証となっております。
変な表現が含まれるかもしれませんが、それを含め読んでいただけると幸いです。

はじめに

AWS Summit Japan 2025のミニステージセッションを見やすく表示するWebアプリケーションを開発しました。Googleカレンダーのような直感的なUIで、80のセッション情報を効率的に閲覧できるツールです。

🌐 スケジュールビューアーを開く

📊 対象セッション

3つのステージ

  • AWS Village Stage: Day1 21セッション、Day2 16セッション
  • Developers on Live: Day1 13セッション、Day2 8セッション
  • Community Stage: Day1 12セッション、Day2 10セッション

総セッション数: 80セッション

🎯 開発の背景

AWS Summit Japan 2025の公式サイトでは、ミニステージのセッション情報がアコーディオン形式で表示されており、全体のスケジュールを一覧で把握するのが困難でした。そこで、以下の課題を解決するツールを開発することにしました:

  • セッション間の時間関係が分かりにくい
  • 複数ステージの同時間帯比較が困難
  • モバイルでの閲覧性が低い
  • Googleカレンダーへの登録が面倒

🛠️ 技術スタック

  • フロントエンド: HTML5, CSS3, Vanilla JavaScript
  • データ形式: JSON
  • レスポンシブデザイン: CSS Grid Layout
  • ホスティング: GitHub Pages
  • データ取得: Python + BeautifulSoup

🔧 開発過程での主な課題と解決策

1. セッションデータの抽出

課題: 公式サイトのHTMLから正確にセッション情報を抽出する

解決策:

# HTMLの構造を解析: <span>タイトル</span><br /><br />概要<br /><br />発表者
def extract_sessions_from_html(html_content):
    # <br /><br />で分割してセッション概要と発表者を分離
    parts = re.split(r'<br\s*/?\s*>\s*<br\s*/?\s*>', cell_html, flags=re.IGNORECASE)
    
    if len(parts) >= 3:
        # parts[1]: 概要部分, parts[2]: 発表者部分
        desc_soup = BeautifulSoup(parts[1], 'html.parser')
        description = desc_soup.get_text().strip()
        
        speaker_soup = BeautifulSoup(parts[2], 'html.parser')
        speaker = speaker_soup.get_text().strip()

2. 複数時間スロットにまたがるセッション表示

課題: 「11:35-13:20」のような長時間セッションが正しく表示されない

解決策: 絶対配置による柔軟なレイアウト

// 基準時間(11:00)からの分数で位置を計算
const baseTime = parseTime('11:00');
const sessionStartMinutes = parseTime(startTime);
const minutesFromBase = sessionStartMinutes - baseTime;

// 30分刻みの表示スロットでの位置を計算
const top = (minutesFromBase / 30) * 80;
const height = Math.max((duration / 30) * 80, 50);

3. 非標準時間(5分刻み)への対応

課題: 「11:50-12:05」「12:10-12:25」など、30分刻みではない時間の表示

解決策: 任意の時間に対応する位置計算システム

// 1分単位での正確な位置計算
function calculateDurationInMinutes(timeRange) {
    const [start, end] = timeRange.split(' - ');
    const startTime = parseTime(start);
    const endTime = parseTime(end);
    return endTime - startTime;
}

4. 密集したセッション間の視認性

課題: AWS Village Stageのような密集スケジュールでセッションが重なる

解決策: インテリジェントな間隔調整

// 前のセッションとの重複チェック
let topOffset = 2; // 基本の上マージン
if (index > 0) {
    const prevSession = sessions[index - 1];
    const prevEndTime = prevSession.time.split(' - ')[1];
    const prevEndMinutes = parseTime(prevEndTime);
    
    // 連続/重複セッションの場合はマージンを増やす
    if (prevEndMinutes >= sessionStartMinutes) {
        topOffset = 4;
    }
}

5. スティッキーヘッダーの実装問題

課題: CSS position: stickyoverflow: hidden コンテナ内で動作しない

解決策: フッター固定ヘッダーによる代替アプローチ

/* フッター固定ヘッダー */
.footer-header {
    position: fixed;
    bottom: 0;
    z-index: 180;
    /* メインヘッダーが見えなくなった時に表示 */
}
// スクロール検出でヘッダー表示制御
window.addEventListener('scroll', () => {
    const headerRect = calendarHeader.getBoundingClientRect();
    if (headerRect && headerRect.bottom < 0) {
        footerHeader.style.display = 'grid';
    } else {
        footerHeader.style.display = 'none';
    }
});

6. モバイル対応での縦軸ずれ

課題: スマホ表示でフッターヘッダーとメインカレンダーの列幅が不一致

解決策: レスポンシブグリッドの統一

@media (max-width: 768px) {
    .calendar-header, .calendar-body, .footer-header {
        grid-template-columns: 80px repeat(3, 1fr); /* 完全統一 */
    }
}

@media (max-width: 480px) {
    .footer-header {
        grid-template-columns: 60px repeat(3, 1fr); /* 小画面対応 */
    }
}

7. z-index管理による表示優先度

課題: モーダル、トップに戻るボタン、フッターヘッダーの重なり順序

解決策: 体系的なz-index管理

/* z-index階層の整理 */
.modal { z-index: 2000; }           /* 最高優先度 */
.modal-content { z-index: 2001; }   /* モーダル内容 */
.back-to-top { z-index: 1000; }     /* ナビゲーション */
.controls { z-index: 200; }         /* コントロール */
.footer-header { z-index: 180; }    /* フッターヘッダー */
.calendar-header { z-index: 150; }  /* カレンダーヘッダー */

✨ 主要機能

1. Googleカレンダー風UI

  • 時間軸とステージの直感的な表示
  • セッション継続時間の視覚化
  • レスポンシブデザイン対応

2. セッション詳細表示

  • クリックでモーダル表示
  • セッション概要、発表者情報
  • Googleカレンダー連携機能

3. Googleカレンダー統合

function addToGoogleCalendar(session, day) {
    const description = encodeURIComponent(
        `【${currentStage}${session.description}\n\n発表者: ${session.speaker}\n\nAWS Summit Japan 2025`
    );
    // ステージ名をプレフィックスとして追加
}

4. ユーザビリティ機能

  • Day1/Day2の切り替え
  • スクロール時のヘッダー固定
  • トップに戻るボタン
  • AWS Expo詳細ページへのリンク

📱 レスポンシブデザイン

デスクトップ

  • 1400px最大幅での最適表示
  • 3ステージ並列表示
  • 豊富な情報表示

タブレット

  • 80px時間列での調整
  • タッチ操作対応
  • 適切なフォントサイズ

スマートフォン

  • 60px時間列(小画面)
  • コンパクトなセッション表示
  • フッターヘッダーでの情報確保

🎨 デザインの工夫

1. 色彩設計

  • メインカラー: AWS オレンジ (#ff9900)
  • ヘッダー: ダークブルーグレー (#232f3e)
  • グラデーション: 立体感のある背景

2. インタラクション

  • ホバー効果による視覚フィードバック
  • スムーズなアニメーション
  • 直感的な操作性

3. 情報階層

  • 重要度に応じたフォントサイズ
  • 適切な余白とコントラスト
  • 読みやすさを重視した設計

🚀 パフォーマンス最適化

1. 軽量な実装

  • Vanilla JavaScript(フレームワーク不使用)
  • 最小限のCSS
  • 効率的なDOM操作

2. データ最適化

  • JSON形式での軽量データ
  • 必要な情報のみ抽出
  • キャッシュ効率の向上

📈 今後の改善予定

1. 機能拡張

  • セッション検索機能
  • お気に入り機能
  • カレンダーエクスポート

2. アクセシビリティ

  • キーボードナビゲーション
  • スクリーンリーダー対応
  • 高コントラストモード

3. 国際化

  • 英語版の提供
  • 多言語対応

🎯 学んだこと

1. CSS Grid Layoutの活用

複雑なカレンダーレイアウトをCSS Gridで効率的に実装できました。特に、レスポンシブ対応での柔軟性が印象的でした。

2. 絶対配置による柔軟なレイアウト

時間スロットにまたがるセッション表示では、絶対配置が非常に有効でした。計算ベースの配置により、任意の時間に対応できます。

3. プログレッシブエンハンスメント

基本機能から始めて段階的に機能を追加するアプローチにより、安定した開発ができました。

4. ユーザビリティの重要性

実際の使用場面を想定した細かな改善(フッターヘッダー、トップに戻るボタンなど)が、大きなUX向上につながりました。

🔗 リンク

まとめ

AWS Summit 2025のミニステージセッションを効率的に閲覧できるWebアプリケーションを開発しました。技術的な課題を一つずつ解決していく過程で、フロントエンド開発の奥深さを実感できました。

特に、ユーザビリティを重視した細かな改善の積み重ねが、最終的に大きな価値を生み出すことを学びました。今後も継続的に改善を続け、より多くの方にとって有用なツールにしていきたいと思います。

AWS Summitに参加される皆様の情報収集に少しでもお役に立てれば幸いです!


この記事は、実際の開発過程で遭遇した課題と解決策を詳細に記録したものです。同様のプロジェクトに取り組む方の参考になれば幸いです。

16
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
16
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?