{"id":35104222,"url":"https://github.com/jaichangpark/open-codelabs","last_synced_at":"2026-02-08T07:30:25.421Z","repository":{"id":330692041,"uuid":"1123113633","full_name":"JAICHANGPARK/open-codelabs","owner":"JAICHANGPARK","description":"open-codelabs","archived":false,"fork":false,"pushed_at":"2026-01-28T12:56:58.000Z","size":4296,"stargazers_count":4,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-01-29T01:57:51.749Z","etag":null,"topics":["codelabs","rust","self-hosted","sveltekit"],"latest_commit_sha":null,"homepage":"https://open-codelabs.web.app","language":"Svelte","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/JAICHANGPARK.png","metadata":{"files":{"readme":"README.ja.md","changelog":null,"contributing":"docs/contributing/code-style.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2025-12-26T07:56:10.000Z","updated_at":"2026-01-28T12:56:40.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/JAICHANGPARK/open-codelabs","commit_stats":null,"previous_names":["jaichangpark/open-codelabs"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/JAICHANGPARK/open-codelabs","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JAICHANGPARK%2Fopen-codelabs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JAICHANGPARK%2Fopen-codelabs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JAICHANGPARK%2Fopen-codelabs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JAICHANGPARK%2Fopen-codelabs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/JAICHANGPARK","download_url":"https://codeload.github.com/JAICHANGPARK/open-codelabs/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JAICHANGPARK%2Fopen-codelabs/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28915942,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-30T16:37:38.804Z","status":"ssl_error","status_checked_at":"2026-01-30T16:37:37.878Z","response_time":66,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["codelabs","rust","self-hosted","sveltekit"],"created_at":"2025-12-27T17:44:55.463Z","updated_at":"2026-01-30T17:01:28.070Z","avatar_url":"https://github.com/JAICHANGPARK.png","language":"Svelte","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Open Codelabs (ハンズオンシステム)\n\n[![Rust](https://img.shields.io/badge/rust-v1.75+-orange.svg)](https://www.rust-lang.org/)\n[![Svelte](https://img.shields.io/badge/svelte-v5-ff3e00.svg)](https://svelte.dev/)\n[![Bun](https://img.shields.io/badge/bun-v1.0+-black.svg)](https://bun.sh/)\n[![Docker](https://img.shields.io/badge/docker-blue.svg)](https://www.docker.com/)\n[![Firebase](https://img.shields.io/badge/firebase-yellow.svg)](https://firebase.google.com/)\n[![Supabase](https://img.shields.io/badge/supabase-3FCF8E.svg)](https://supabase.com/)\n\n**Open Codelabs** は、Google Codelab スタイルのハンズオンセッションを簡単に運営・管理できるように設計されたオープンソースプラットフォームです。最新の技術スタックで構築されており、ファシリテーター（管理者）と参加者の両方のロールをサポートしています。コンテンツは Markdown で直接管理するか、AI を使用して自動生成することができます。\n\n[English](README.md) | [한국어](README.ko.md) | [日本語](README.ja.md) | [中文](README.zh.md)\n\n---\n\n## 🚀 主な特徴\n\n- **ファシリテーターと参加者の分離**: 管理者はコードラボを作成・管理し、参加者は洗練された UI を通じてステップに従うことができます。\n- **AI コードラボ生成器**: Google Gemini AI を使用して、ソースコードや参照ドキュメントからプロフェッショナルなコードラボを自動生成します。\n- **Code Server ワークスペース（任意）**: コードラボごとの code-server ワークスペースを作成し、ステップごとのスナップショット（ブランチ/フォルダモード）とダウンロードを提供します。\n- **クイズ・フィードバック・修了証**: クイズやフィードバック提出を修了条件に設定し、検証 URL 付きの修了証を自動発行します。\n- **準備ガイド \u0026 資料管理**: 事前準備ガイドを手書きまたは AI 生成し、リンク/ファイルを一括配布できます。\n- **ライブワークショップツール**: ライブチャット/DM、ヘルプリクエストキュー、提出物パネル、修了証保持者だけを対象にするルーレット抽選を提供します。\n- **マルチランタイムサポート**: ローカル/プライベートセッション用の **Rust (Axum) + SQLite** バックエンド、またはサーバーレス環境用の **Firebase (Firestore/Hosting)** または **Supabase** デプロイをサポートしています。\n- **Google Codelab Look \u0026 Feel**: 慣れ親しんだ、読み取りやすい Google スタイルのデザインを採用しています。\n- **簡単な外部公開**: `ngrok`、`bore`、`cloudflared`(Cloudflare Tunnel) 統合スクリプトにより、ローカルサーバーを即座に外部に公開し、参加者が QR コードでアクセスできるようにサポートします。\n- **多言語対応**: グローバルなワークショップ運営のための i18n サポートが組み込まれています。\n\n---\n\n## ⚡ クイックスタート (Quickstart)\n\n数秒でシステムを起動できます：\n\n```bash\n# リポジトリをクローン\ngit clone https://github.com/JAICHANGPARK/open-codelabs.git\ncd open-codelabs\n\n# Docker Compose で起動\ndocker compose up --build\n```\n\n### 🦭 Podman ユーザーガイド\nPodman を使用している場合は、`podman-compose` を使用できます：\n```bash\npodman-compose up --build\n```\nまたは Podman の Docker 互換レイヤーを使用してください。\n\n### 🧱 事前ビルドイメージを使用 (GHCR)\nローカルビルドを省略したい場合は、公開済みイメージを利用できます：\n\n```bash\ncp .env.sample .env\ndocker compose -f docker-compose.images.yml up\n```\n\n---\n\n## 🛠 技術スタック\n\n### フロントエンド\n- **フレームワーク**: [SvelteKit 5](https://svelte.dev/) (Vite + TypeScript)\n- **ランタイム**: [Bun](https://bun.sh/)\n- **スタイリング**: Tailwind CSS 4.0\n- **状態管理**: Svelte Runes\n- **i18n**: `svelte-i18n`\n\n### バックエンド (セルフホスト)\n- **言語**: [Rust](https://www.rust-lang.org/)\n- **フレームワーク**: Axum (Tokio stack)\n- **データベース**: SQLite (via [SQLx](https://github.com/launchbadge/sqlx))\n\n### クラウド (サーバーレスオプション)\n- **プラットフォーム**: [Firebase](https://firebase.google.com/) (Hosting, Firestore, Storage) または [Supabase](https://supabase.com/) (Postgres, Auth, Storage, Realtime)\n\n---\n\n## 📂 プロジェクト構造\n\n```text\nopen-codelabs/\n├── backend/          # Rust Axum API サーバー\n│   ├── src/          # API ロジック\n│   └── migrations/   # データベースマイグレーション\n├── frontend/         # SvelteKit クライアント\n│   ├── src/          # コンポーネント、ルート、ライブラリ\n│   └── static/       # 静的アセット\n├── docs/             # ドキュメント (MkDocs)\n├── docker-compose.images.yml # 事前ビルドイメージ用 compose\n├── docker-compose.yml # システムオーケストレーション\n└── run-public.sh     # 公開デプロイスクリプト (ngrok/bore/cloudflare)\n```\n\n---\n\n## 🚦 はじめに\n\n### 事前準備\n- [Docker](https://www.docker.com/) \u0026 Docker Compose\n- [Bun](https://bun.sh/) (ローカル開発用)\n- [Rust](https://www.rust-lang.org/) (ローカルバックエンド開発用)\n\n### 1. Docker で実行 (推奨)\nシステム全体を起動する最も簡単な方法です。\n\n\u003e **注意**: デフォルトでは、データはホストマシンの `~/open-codelabs` フォルダに保存されます。保存場所をカスタマイズするには、ルートディレクトリの .env ファイルで DATA_VOLUME_PATH を編集してください。\n\u003e - **macOS/Linux**: `~/open-codelabs` \n\u003e - **Windows**: `C:/open-codelabs` (スラッシュ `/` を使用)\n\n```bash\ndocker-compose up --build\n```\n- **フロントエンド**: [http://localhost:5173](http://localhost:5173)\n- **バックエンド API**: [http://localhost:8080](http://localhost:8080)\n\n### 2. ローカル開発環境\n\n#### バックエンド\n```bash\ncd backend\n# .env ファイルを作成 (DATABASE_URL=sqlite:data/sqlite.db?mode=rwc)\ncargo run\n```\n\n#### フロントエンド\n```bash\ncd frontend\nbun install\n# .env ファイルを作成 (VITE_API_URL=http://localhost:8080)\nbun run dev\n```\n\n### 3. 環境変数 (.env)\n\nDocker Compose はリポジトリルートの `.env` を読み込みます。`.env.sample` をコピーして `.env` を作成し、必要な値を変更してください。\n(ローカル開発は `backend/.env.sample` と `frontend/.env.sample` を最小の開始点として使えます。)\n\n**イメージ (docker-compose.images.yml)**\n- `IMAGE_REGISTRY`: 事前ビルドイメージのレジストリ（既定 `ghcr.io`）。\n- `IMAGE_NAMESPACE`: イメージのネームスペース/組織名（既定 `open-codelabs`）。\n- `IMAGE_TAG`: 取得するイメージタグ（既定 `latest`）。\n\n**Backend**\n- `DATABASE_URL`: SQLx 接続文字列 (sqlite/postgres/mysql)。例: `sqlite:/app/data/sqlite.db?mode=rwc`。\n- `ADMIN_ID`: 管理者ログイン ID。\n- `ADMIN_PW`: 管理者ログインパスワード。フロントで暗号化した Gemini API キーの復号にも使用。\n- `AUTH_SECRETS`: JWT 署名用シークレット(カンマ区切り)。先頭が有効キーで、他はローテーション用。未設定時は `ADMIN_PW` を使用。\n- `AUTH_ISSUER`: JWT issuer クレーム。\n- `AUTH_AUDIENCE`: JWT audience クレーム。\n- `ADMIN_SESSION_TTL_SECONDS`: 管理者セッション TTL(秒)。\n- `ATTENDEE_SESSION_TTL_SECONDS`: 参加者セッション TTL(秒)。\n- `COOKIE_SECURE`: HTTPS 時は `true` (Secure クッキー + `__Host-` プレフィックス)。`COOKIE_SAMESITE=none` には必須。\n- `COOKIE_SAMESITE`: `lax`(既定)、`strict`、`none`。\n- `TRUST_PROXY`: リバースプロキシ配下で `X-Forwarded-*` ヘッダーを信頼する場合 `true`。\n- `CORS_ALLOWED_ORIGINS`: 許可するオリジン一覧(カンマ区切り)。空ならローカルの既定値。\n- `RATE_LIMIT_GENERAL_PER_MINUTE`: 一般 API の分/IP 制限。\n- `RATE_LIMIT_LOGIN_PER_5_MIN`: ログインの 5 分/IP 制限。\n- `RATE_LIMIT_AI_PER_MINUTE`: AI プロキシの分/IP 制限。\n- `RATE_LIMIT_UPLOAD_PER_MINUTE`: アップロード/提出 POST の分/IP 制限。\n- `CSP_HEADER`: UI 応答の Content-Security-Policy ヘッダー上書き。空なら既定値。\n- `HSTS_HEADER`: Strict-Transport-Security ヘッダー上書き(HTTPS のみ)。\n- `ALLOWED_GEMINI_MODELS`: 許可する Gemini モデル ID の一覧(カンマ区切り)。\n\n**AI**\n- `GEMINI_API_KEY`: 管理者のキーがない場合に使う既定の Gemini API キー。\n\n**Frontend**\n- `VITE_API_URL`: バックエンド API の基底 URL (例: `http://localhost:8080`、Docker では `http://backend:8080`)。\n- `VITE_ADMIN_ENCRYPTION_PASSWORD`: ブラウザで Gemini API キーを暗号化するパスワード。バックエンド `ADMIN_PW` と一致する必要あり。\n- `VITE_USE_SUPABASE`: `true` に設定すると Supabase モード（サーバーレス、Rust バックエンドなし）を有効化します。\n- `VITE_SUPABASE_URL`: Supabase プロジェクト URL。\n- `VITE_SUPABASE_ANON_KEY`: Supabase の anon キー。\n- `VITE_SUPABASE_STORAGE_BUCKET`: Supabase Storage のバケット名（既定 `open-codelabs`）。\n- `VITE_ADMIN_ID`: Firebase/Supabase モードの管理者ログイン ID。\n- `VITE_ADMIN_PW`: Firebase/Supabase モードの管理者ログインパスワード。\n- `FRONTEND_PORT`: フロントサーバーのポート。\n- `FRONTEND_HOST`: フロントサーバーのバインドホスト(例: `0.0.0.0`)。\n\n### 4. クラウドデプロイ (AWS / GCP / Firebase)\nサーバーレス環境やクラウドで運用する場合は、以下を参照してください。\n\n- **AWS**: コンテナ or VM 配置。 [AWS デプロイガイド](docs/self-hosting/aws.md) を参照。\n- **GCP (Cloud Run)**: コンテナ配置。 [GCP デプロイガイド](docs/self-hosting/gcp.md) を参照。\n- **Firebase**: 迅速なサーバーレス設定。 [Firebase デプロイガイド](docs/self-hosting/firebase.md) を参照。\n- **Supabase**: サーバーレス Postgres + Storage 構成。 [Supabase ガイド](docs/self-hosting/supabase.md) を参照。\n\n---\n\n## 🤖 AI コードラボ生成器\nOpen Codelabs には、コードを構造化されたチュートリアルに変換する AI 生成器が内蔵されています。\n1. 設定で Gemini API キーを入力します。\n2. ソースコードまたは技術的な説明を入力します。\n3. AI が各ステップ、説明、検証手順を自動生成します。\n\n---\n\n## 🧭 ファシリテーターツールキット（新機能）\n- **ライブタブ**: 参加者一覧、リアルタイムチャット/DM、ヘルプリクエスト処理。\n- **クイズ \u0026 フィードバック**: 修了条件を設定し、結果を集計。\n- **準備ガイド \u0026 資料**: 事前準備ガイドを作成/AI 生成し、リンク・ファイルを配布。\n- **提出物管理**: 参加者のアップロードファイルを収集・レビュー。\n- **修了証ルーレット抽選**: 修了証が発行された参加者のみを対象に公平に抽選。\n\n---\n\n## 🌐 外部への公開 (ngrok / bore / cloudflare)\nローカルマシンでワークショップを開催する場合、`run-public.sh` スクリプトを使用して外部アクセスを提供できます。\n\n```bash\nchmod +x run-public.sh\n./run-public.sh --ngrok  # ngrok を使用\n# または\n./run-public.sh --bore   # bore を使用 (Rust ベース)\n# または\n./run-public.sh --cloudflare  # Cloudflare Tunnel を使用\n```\n\n---\n\n## 📚 ドキュメント\n完全なドキュメントは GitHub Pages で確認できます：\n**[📖 Open Codelabs ドキュメントを見る](https://JAICHANGPARK.github.io/open-codelabs/)**\n\n追加ガイド:\n- [Code Server ワークスペース設定](docs/CODE_SERVER_SETUP.md)\n\n---\n\n## 📄 ライセンス\nこのプロジェクトは [Apache License 2.0](LICENSE) に基づいてライセンスされています。\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjaichangpark%2Fopen-codelabs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjaichangpark%2Fopen-codelabs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjaichangpark%2Fopen-codelabs/lists"}