chore: initial backup of root config, templates, and server source
Backs up CLAUDE.md, _template/, deploy-server.sh, scripts/, server.js to posimai-root repository for disaster recovery. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
commit
9e1a817ed6
|
|
@ -0,0 +1,69 @@
|
||||||
|
.vercel
|
||||||
|
|
||||||
|
# 一時ファイル・バックアップ(ルート)
|
||||||
|
_tmp_*
|
||||||
|
*.backup*
|
||||||
|
*.bak
|
||||||
|
*_temp.*
|
||||||
|
*_old.*
|
||||||
|
dummy*.txt
|
||||||
|
skip.txt
|
||||||
|
server-*.js
|
||||||
|
server_bk.js
|
||||||
|
|
||||||
|
# 依存関係・ビルド成果物
|
||||||
|
node_modules/
|
||||||
|
.next/
|
||||||
|
out/
|
||||||
|
dist/
|
||||||
|
build/
|
||||||
|
|
||||||
|
# 環境変数
|
||||||
|
.env
|
||||||
|
.env.local
|
||||||
|
.env.*.local
|
||||||
|
|
||||||
|
# OS
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
|
|
||||||
|
# 旧プロジェクト・レガシー(アクティブエコシステム外)
|
||||||
|
m-ai-dashboard/
|
||||||
|
m-ai-dashboard-bk/
|
||||||
|
mai_quick_scan/
|
||||||
|
mai_quick_scan_安定版最新/
|
||||||
|
_conoha/
|
||||||
|
article-keeper/
|
||||||
|
package_ar_info/
|
||||||
|
docs/
|
||||||
|
_template-preview/
|
||||||
|
mai-ponshu-room/
|
||||||
|
ponshu-room.bak/
|
||||||
|
|
||||||
|
# 各アプリディレクトリ(個別リポジトリ管理)
|
||||||
|
posimai-ambient/
|
||||||
|
posimai-analytics/
|
||||||
|
posimai-brain/
|
||||||
|
posimai-clean/
|
||||||
|
posimai-daily/
|
||||||
|
posimai-dashboard/
|
||||||
|
posimai-diff/
|
||||||
|
posimai-digest/
|
||||||
|
posimai-events/
|
||||||
|
posimai-feed/
|
||||||
|
posimai-habit/
|
||||||
|
posimai-hotels/
|
||||||
|
posimai-journal/
|
||||||
|
posimai-lens/
|
||||||
|
posimai-maps/
|
||||||
|
posimai-pulse/
|
||||||
|
posimai-reader/
|
||||||
|
posimai-site/
|
||||||
|
posimai-tech-events/
|
||||||
|
posimai-think/
|
||||||
|
posimai-timer/
|
||||||
|
posimai-together/
|
||||||
|
posimai-widget-dl/
|
||||||
|
posimai_widget/
|
||||||
|
ponshu-room/
|
||||||
|
ponshu_room_lite/
|
||||||
|
|
@ -0,0 +1,161 @@
|
||||||
|
# Posimai Project — AI Instructions
|
||||||
|
|
||||||
|
## 新しい AI への引き継ぎチェックリスト(必読)
|
||||||
|
|
||||||
|
別の AI エージェント(Antigravity 等)やセッションを新たに始めるときは、**必ず最初にこのセクションを読ませること。**
|
||||||
|
|
||||||
|
### 作業前に AI が確認すべき事項
|
||||||
|
|
||||||
|
1. **CLAUDE.md を全文読む**(このファイル)— デザインルール・デプロイ方法・禁止事項がすべてここにある
|
||||||
|
2. **memory/ ディレクトリを確認する** — `C:\Users\maita\.claude\projects\c--Users-maita-posimai-project\memory\MEMORY.md` にプロジェクト固有の記憶がある
|
||||||
|
3. **`posimai-dashboard/src/data/projects.json` を確認する** — 全アプリの一覧・ステータス・技術スタックがここにある
|
||||||
|
|
||||||
|
### AI が絶対に守るべきルール(違反時は即修正)
|
||||||
|
|
||||||
|
| 禁止事項 | 理由 |
|
||||||
|
|---------|------|
|
||||||
|
| 絵文字の使用(コード・コメント・HTML 問わず) | デザインルール違反 |
|
||||||
|
| `lucide@latest` の使用 | バージョン固定済み(`@0.344.0`) |
|
||||||
|
| CDN ライブラリのバージョン未固定(`@latest` 等) | SW キャッシュ破壊・予期せぬ破壊的変更のリスク |
|
||||||
|
| `vercel --prod` の直接実行 | GitHub push で自動デプロイされるため二重になる |
|
||||||
|
| `git push origin` の使用 | `gitea` と `github` の2リモートを使う |
|
||||||
|
| デザインシステム外の色の使用 | アクセントは `--accent` 1色のみ |
|
||||||
|
| manifest.json / sw.js のないアプリを作る | 全アプリ PWA 必須 |
|
||||||
|
| `theme-color` メタタグをメディアクエリなしで書く | ライトモード時に黒い問題が発生する |
|
||||||
|
|
||||||
|
### 作業完了時の必須チェック
|
||||||
|
|
||||||
|
- [ ] emoji が増えていないか (`grep -r "emoji\|✅\|📱\|⚙️\|🎉" --include="*.html"`)
|
||||||
|
- [ ] `@latest` が増えていないか (`grep -r "@latest" --include="*.html"`)
|
||||||
|
- [ ] `npm run deploy` でデプロイしたか(`git push gitea main && git push github main`)
|
||||||
|
- [ ] 大きな変更なら Dashboard Timeline に追記したか
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Deploy ルール(必須)
|
||||||
|
|
||||||
|
コードを変更してデプロイするときは **必ずこの手順** を使うこと:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git add .
|
||||||
|
git commit -m "feat/fix/chore: 変更内容"
|
||||||
|
npm run deploy
|
||||||
|
```
|
||||||
|
|
||||||
|
`npm run deploy` = `git push gitea main && git push github main`
|
||||||
|
|
||||||
|
- **Gitea**(`http://100.76.7.3:3000/mai/`): ローカルバックアップ
|
||||||
|
- **GitHub**(`https://github.com/posimai/`): Vercel 自動デプロイのトリガー
|
||||||
|
|
||||||
|
### やってはいけないこと
|
||||||
|
- `vercel --prod` を直接実行しない(GitHub push で自動デプロイされるため不要)
|
||||||
|
- **例外**: 新アプリの初回本番デプロイのみ、空コミット push で代替する(`_template/README.md` 参照)
|
||||||
|
- `git push origin` を使わない(`gitea` と `github` の2つのリモートを使う)
|
||||||
|
- `git push github main` だけ実行して Gitea を忘れない
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## プロジェクト構成
|
||||||
|
|
||||||
|
| アプリ | ディレクトリ | 説明 |
|
||||||
|
|--------|-------------|------|
|
||||||
|
| posimai-dashboard | `posimai-dashboard/` | Next.js メインダッシュボード |
|
||||||
|
| posimai-analytics | `posimai-analytics/` | Next.js アナリティクス |
|
||||||
|
| posimai-brain | `posimai-brain/` | 記事管理(静的) |
|
||||||
|
| posimai-feed | `posimai-feed/` | RSS フィード(静的) |
|
||||||
|
| posimai-events | `posimai-events/` | イベント情報(静的) |
|
||||||
|
| posimai-hotels | `posimai-hotels/` | ホテル価格ウォッチ(静的) |
|
||||||
|
| posimai-daily | `posimai-daily/` | オーディオファースト・ブリーフィング(静的/API融合) |
|
||||||
|
| posimai-maps | `posimai-maps/` | マップ(静的) |
|
||||||
|
| posimai-reader | `posimai-reader/` | 記事リーダー(静的) |
|
||||||
|
| posimai-together | `posimai-together/` | 共有スペース(静的) |
|
||||||
|
| posimai-journal | `posimai-journal/` | CMS エディタ(Synology API バック) |
|
||||||
|
| posimai-site | `posimai-site/` | 公開ホームページ(journal/site_config と連携) |
|
||||||
|
| posimai-digest | `posimai-digest/` | テキスト要約(静的) |
|
||||||
|
| posimai-ambient | `posimai-ambient/` | 常時表示アンビエント PWA(静的) |
|
||||||
|
| posimai-widget | `posimai_widget/` | Android ホーム画面ウィジェット(Flutter) |
|
||||||
|
|
||||||
|
## Synology バックエンド(server.js)
|
||||||
|
- ファイル: `server.js`(ルートに配置、git 管理外)
|
||||||
|
- デプロイ: File Station でアップロード → `docker cp` → `docker restart posimai_api`
|
||||||
|
- API base: `https://posimai-lab.tail72e846.ts.net/brain/api`
|
||||||
|
- 主なテーブル: `users`, `articles`, `journal_posts`, `site_config`, `reading_history`
|
||||||
|
|
||||||
|
## デザインシステム(projects.json designRules が正)
|
||||||
|
```
|
||||||
|
--bg: #0D0D0D 背景
|
||||||
|
--surface: #1A1A1A カード面
|
||||||
|
--surface2: #252525 ネスト面
|
||||||
|
--border: #2D2D2D ボーダー
|
||||||
|
--text: #F3F4F6 主テキスト
|
||||||
|
--text2: #9CA3AF 副テキスト
|
||||||
|
--text3: #6B7280 弱テキスト
|
||||||
|
--accent: #6EE7B7 アクセント(Posimai Teal)← デフォルト
|
||||||
|
--radius: 12px 角丸
|
||||||
|
```
|
||||||
|
- フォント: Inter(300/400/500/600)
|
||||||
|
- アイコン: Lucide(stroke 1.5〜2.0)
|
||||||
|
- ヘッダー: 高さ 52px、glassmorphism、アクセントドット + アプリ名
|
||||||
|
- 絵文字: **禁止**
|
||||||
|
- 全アプリ: manifest.json + sw.js + PWA メタタグ必須
|
||||||
|
|
||||||
|
### アプリ別アクセントカラー(デフォルトから意図的に変える場合のみ記載)
|
||||||
|
|
||||||
|
| アプリ | ダーク accent | ライト accent | 理由 |
|
||||||
|
|--------|-------------|-------------|------|
|
||||||
|
| 全般(デフォルト) | `#6EE7B7` Teal | `#059669` | Posimai ブランドカラー |
|
||||||
|
| posimai-journal | `#80CAEE` Sky-Blue | `#0284C7` | CMS 系・静かで知的な印象 |
|
||||||
|
| posimai-site | `#80CAEE` Sky-Blue | `#0284C7` | journal と同系統の公開サイト |
|
||||||
|
|
||||||
|
**新アプリ作成時のルール:**
|
||||||
|
1. デフォルト Teal を使うなら何も記載不要
|
||||||
|
2. 意図的に変える場合はこの表に追記してから実装する
|
||||||
|
3. 同じ用途・系統のアプリは同じアクセントカラーに揃える
|
||||||
|
|
||||||
|
## 新アプリ作成
|
||||||
|
|
||||||
|
`_template/` をコピーして使う。`APP_NAME` / `APP_ID` / `APP_DESCRIPTION` を置換するだけで動く。
|
||||||
|
|
||||||
|
**完全な手順(Git / Vercel セットアップ含む)は必ず `_template/README.md` を参照すること。**
|
||||||
|
特に以下の2点は詰まりやすいので注意:
|
||||||
|
- Gitea リポジトリは **Web UI で先に作成**してから `git remote add gitea` する
|
||||||
|
- `vercel git connect` 後、**空コミット push** で初回本番デプロイをトリガーする
|
||||||
|
|
||||||
|
### 新アプリ作成後の必須チェックリスト(抜け漏れ禁止)
|
||||||
|
|
||||||
|
新しいアプリを作ったら、**コード実装の完了直後に必ずこの順番で実行する**こと:
|
||||||
|
|
||||||
|
1. **Dashboard カード追加**
|
||||||
|
- `posimai-dashboard/src/data/projects.json` の `projects` 配列にエントリを追加
|
||||||
|
- 適切な `category` を設定(`posimai-pwa` / `active` / `flagship` / `micro` / `infra` など)
|
||||||
|
|
||||||
|
2. **Ecosystem Map 追加**
|
||||||
|
- `posimai-dashboard/src/app/ecosystem/page.tsx` の `NODES` 配列にノードを追加
|
||||||
|
- 関連する `EDGES`(依存関係)も追加
|
||||||
|
|
||||||
|
3. **Development Timeline に追記**
|
||||||
|
- `posimai-dashboard/src/app/timeline/page.tsx` の `EVENTS` 配列に今日の日付でエントリを追加
|
||||||
|
- type: `launch`(新規公開)/ `feature`(機能追加)/ `fix`(修正)/ `infra`(インフラ)
|
||||||
|
|
||||||
|
4. **Dashboard をデプロイ**
|
||||||
|
```bash
|
||||||
|
cd posimai-dashboard
|
||||||
|
git add src/data/projects.json src/app/ecosystem/page.tsx src/app/timeline/page.tsx
|
||||||
|
git commit -m "feat: add [app-name] to dashboard"
|
||||||
|
npm run deploy
|
||||||
|
```
|
||||||
|
|
||||||
|
5. **プロジェクト構成テーブルを CLAUDE.md に追記**(このファイル)
|
||||||
|
|
||||||
|
> ⚠️ ダッシュボード更新(カード・Ecosystem・Timeline)を忘れると、アプリが孤立してエコシステムから見えなくなる。
|
||||||
|
|
||||||
|
## 既存アプリに大きな変更をした場合の必須チェックリスト
|
||||||
|
|
||||||
|
機能追加・バグ修正・リリースなど **ユーザーが気づくレベルの変更** をしたら:
|
||||||
|
|
||||||
|
1. `posimai-dashboard/src/app/timeline/page.tsx` の `EVENTS` 配列に今日の日付でエントリを追加
|
||||||
|
2. Dashboard をデプロイ
|
||||||
|
|
||||||
|
## Git リモート(全アプリ共通)
|
||||||
|
- `gitea` → `http://100.76.7.3:3000/mai/[app-name].git`
|
||||||
|
- `github` → `https://github.com/posimai/[app-name].git`
|
||||||
|
|
@ -0,0 +1,202 @@
|
||||||
|
# Posimai Project — AI Instructions
|
||||||
|
|
||||||
|
## 新しい AI への引き継ぎチェックリスト(必読)
|
||||||
|
|
||||||
|
別の AI エージェント(Antigravity 等)やセッションを新たに始めるときは、**必ず最初にこのセクションを読ませること。**
|
||||||
|
|
||||||
|
### 作業前に AI が確認すべき事項
|
||||||
|
|
||||||
|
1. **CLAUDE.md を全文読む**(このファイル)— デザインルール・デプロイ方法・禁止事項がすべてここにある
|
||||||
|
2. **memory/ ディレクトリを確認する** — `C:\Users\maita\.claude\projects\c--Users-maita-posimai-project\memory\MEMORY.md` にプロジェクト固有の記憶がある
|
||||||
|
3. **`posimai-dashboard/src/data/projects.json` を確認する** — 全アプリの一覧・ステータス・技術スタックがここにある
|
||||||
|
|
||||||
|
### AI が絶対に守るべきルール(違反時は即修正)
|
||||||
|
|
||||||
|
| 禁止事項 | 理由 |
|
||||||
|
|---------|------|
|
||||||
|
| 絵文字の使用(コード・コメント・HTML 問わず) | デザインルール違反 |
|
||||||
|
| `lucide@latest` の使用 | バージョン固定済み(`@0.344.0`) |
|
||||||
|
| CDN ライブラリのバージョン未固定(`@latest` 等) | SW キャッシュ破壊・予期せぬ破壊的変更のリスク |
|
||||||
|
| `vercel --prod` の直接実行 | GitHub push で自動デプロイされるため二重になる |
|
||||||
|
| `git push origin` の使用 | `gitea` と `github` の2リモートを使う |
|
||||||
|
| デザインシステム外の色の使用 | アクセントは `--accent` 1色のみ |
|
||||||
|
| manifest.json / sw.js のないアプリを作る | 全アプリ PWA 必須 |
|
||||||
|
| `theme-color` メタタグをメディアクエリなしで書く | ライトモード時に黒い問題が発生する |
|
||||||
|
| **新アプリ作成後に Dashboard 更新を省略する** | アプリがエコシステムから孤立する。ユーザーに言われなくても必ずやる |
|
||||||
|
| SW でクロスオリジン GET リクエストをキャッシュする | Brain API 等の外部 API が古いデータを返す・データ消失に見える(Habit バグ事例あり) |
|
||||||
|
| `lucide.createIcons()` を早期 return の後にしか呼ばない | 早期 return のコードパスでアイコンが空になる(Habit バグ事例あり) |
|
||||||
|
| CSS でアクセントカラーをハードコード(`#6EE7B7` 直書き等) | ダーク/ライトテーマ切り替えが壊れる。必ず `var(--accent)` を使う |
|
||||||
|
| 底面固定要素に `env(safe-area-inset-bottom)` を付けない | iPhone のホームインジケーター領域にコンテンツが被る |
|
||||||
|
| 外部リンクに `rel="noopener"` を付けない | Tabnabbing 攻撃の温床。`target="_blank"` には必ずセットで付ける |
|
||||||
|
| **新アプリ作成前にアクセントカラーを宣言しない** | 実装後に変更コストが大きい。カテゴリ確認→CLAUDE.md テーブル追記→実装の順を守る |
|
||||||
|
|
||||||
|
### 作業完了時の必須チェック
|
||||||
|
|
||||||
|
- [ ] emoji が増えていないか (`grep -r "emoji\|✅\|📱\|⚙️\|🎉" --include="*.html"`)
|
||||||
|
- [ ] `@latest` が増えていないか (`grep -r "@latest" --include="*.html"`)
|
||||||
|
- [ ] `npm run deploy` でデプロイしたか(`git push gitea main && git push github main`)
|
||||||
|
- [ ] 大きな変更なら Dashboard Timeline に追記したか
|
||||||
|
- [ ] **新アプリなら Dashboard カード・Ecosystem・Timeline・Access Guide を更新してデプロイしたか**(ユーザーに言われる前に完了させる)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Deploy ルール(必須)
|
||||||
|
|
||||||
|
コードを変更してデプロイするときは **必ずこの手順** を使うこと:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git add .
|
||||||
|
git commit -m "feat/fix/chore: 変更内容"
|
||||||
|
npm run deploy
|
||||||
|
```
|
||||||
|
|
||||||
|
`npm run deploy` = `git push gitea main && git push github main`
|
||||||
|
|
||||||
|
- **Gitea**(`http://100.76.7.3:3000/mai/`): ローカルバックアップ
|
||||||
|
- **GitHub**(`https://github.com/posimai/`): Vercel 自動デプロイのトリガー
|
||||||
|
|
||||||
|
### やってはいけないこと
|
||||||
|
- `vercel --prod` を直接実行しない(GitHub push で自動デプロイされるため不要)
|
||||||
|
- **例外**: 新アプリの初回本番デプロイのみ、空コミット push で代替する(`_template/README.md` 参照)
|
||||||
|
- `git push origin` を使わない(`gitea` と `github` の2つのリモートを使う)
|
||||||
|
- `git push github main` だけ実行して Gitea を忘れない
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## プロジェクト構成
|
||||||
|
|
||||||
|
| アプリ | ディレクトリ | 説明 |
|
||||||
|
|--------|-------------|------|
|
||||||
|
| posimai-dashboard | `posimai-dashboard/` | Next.js メインダッシュボード |
|
||||||
|
| posimai-analytics | `posimai-analytics/` | Next.js アナリティクス |
|
||||||
|
| posimai-brain | `posimai-brain/` | 記事管理(静的) |
|
||||||
|
| posimai-feed | `posimai-feed/` | RSS フィード(静的) |
|
||||||
|
| posimai-events | `posimai-events/` | イベント情報(静的) |
|
||||||
|
| posimai-hotels | `posimai-hotels/` | ホテル価格ウォッチ(静的) |
|
||||||
|
| posimai-daily | `posimai-daily/` | オーディオファースト・ブリーフィング(静的/API融合) |
|
||||||
|
| posimai-maps | `posimai-maps/` | マップ(静的) |
|
||||||
|
| posimai-reader | `posimai-reader/` | 記事リーダー(静的) |
|
||||||
|
| posimai-together | `posimai-together/` | 共有スペース(静的) |
|
||||||
|
| posimai-journal | `posimai-journal/` | CMS エディタ(Synology API バック) |
|
||||||
|
| posimai-site | `posimai-site/` | 公開ホームページ(journal/site_config と連携) |
|
||||||
|
| posimai-digest | `posimai-digest/` | テキスト要約(静的) |
|
||||||
|
| posimai-ambient | `posimai-ambient/` | 常時表示アンビエント PWA(静的) |
|
||||||
|
| posimai-widget | `posimai_widget/` | Android ホーム画面ウィジェット(Flutter) |
|
||||||
|
| posimai-timer | `posimai-timer/` | ストップウォッチ+カウントダウン(静的) |
|
||||||
|
| posimai-habit | `posimai-habit/` | 習慣チェックリスト・ヒートマップ(静的) |
|
||||||
|
| posimai-pulse | `posimai-pulse/` | 気分・エネルギー記録(静的) |
|
||||||
|
| posimai-lens | `posimai-lens/` | 写真 EXIF メタデータ表示(静的) |
|
||||||
|
| posimai-diff | `posimai-diff/` | テキスト差分ビューア(静的) |
|
||||||
|
| posimai-clean | `posimai-clean/` | テキストクリーナー(静的) |
|
||||||
|
| posimai-tech-events | `posimai-tech-events/` | IT イベント情報(Doorkeeper/connpass RSS) |
|
||||||
|
| posimai-think | `posimai-think/` | AI 思考整理アシスタント(Gemini 直接呼び出し) |
|
||||||
|
|
||||||
|
## Synology バックエンド(server.js)
|
||||||
|
- ファイル: `server.js`(ルートに配置、git 管理外)
|
||||||
|
- **デプロイ方法(必須)**: `bash deploy-server.sh` を実行する(SSH → docker cp → docker restart まで自動)
|
||||||
|
- SSHパスワード → sudoパスワードの順に2回入力を求められる
|
||||||
|
- スクリプト内の処理: `ssh` でファイル転送 → `docker cp` → `docker restart posimai_api` → ログ確認
|
||||||
|
- ⚠️ `vercel --prod` や File Station での手動アップロードは使わない
|
||||||
|
- API base: `https://posimai-lab.tail72e846.ts.net/brain/api`
|
||||||
|
- 主なテーブル: `users`, `articles`, `journal_posts`, `site_config`, `reading_history`
|
||||||
|
- 主なエンドポイント: `/health`, `/auth-test`, `/articles`, `/article`, `/feeds`, `/events/rss`, `/tts/*`, `/journal/*`
|
||||||
|
|
||||||
|
## デザインシステム(projects.json designRules が正)
|
||||||
|
```
|
||||||
|
--bg: #0D0D0D 背景
|
||||||
|
--surface: #1A1A1A カード面
|
||||||
|
--surface2: #252525 ネスト面
|
||||||
|
--border: #2D2D2D ボーダー
|
||||||
|
--text: #F3F4F6 主テキスト
|
||||||
|
--text2: #9CA3AF 副テキスト
|
||||||
|
--text3: #6B7280 弱テキスト
|
||||||
|
--accent: #6EE7B7 アクセント(Posimai Teal)← デフォルト
|
||||||
|
--radius: 12px 角丸
|
||||||
|
```
|
||||||
|
- フォント: Inter(300/400/500/600)
|
||||||
|
- アイコン: Lucide(stroke 1.5〜2.0)
|
||||||
|
- ヘッダー: 高さ 52px、glassmorphism、アクセントドット + アプリ名
|
||||||
|
- 絵文字: **禁止**
|
||||||
|
- 全アプリ: manifest.json + sw.js + PWA メタタグ必須
|
||||||
|
- トランジション: `0.12s〜0.3s` の範囲、標準イージング `cubic-bezier(0.2, 0.9, 0.2, 1)`
|
||||||
|
- 空状態 (Empty State): 必ずアイコン + 説明テキストを実装する(空コンテナ禁止)
|
||||||
|
- 外部リンク: `target="_blank" rel="noopener"` を必ずセットで付ける
|
||||||
|
- 底面固定要素: `padding-bottom: max(Xpx, env(safe-area-inset-bottom))` で safe area 対応
|
||||||
|
- SW キャッシュ: クロスオリジン GET は必ずネットワーク経由(キャッシュ禁止)
|
||||||
|
```js
|
||||||
|
const ORIGIN = self.location.origin;
|
||||||
|
self.addEventListener('fetch', e => {
|
||||||
|
if (!e.request.url.startsWith(ORIGIN)) return; // APIはスルー
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### アプリ別アクセントカラー(デフォルトから意図的に変える場合のみ記載)
|
||||||
|
|
||||||
|
| アプリ | ダーク accent | ライト accent | 理由 |
|
||||||
|
|--------|-------------|-------------|------|
|
||||||
|
| 全般(デフォルト) | `#6EE7B7` Teal | `#059669` | Posimai ブランドカラー |
|
||||||
|
| posimai-journal | `#80CAEE` Sky-Blue | `#0284C7` | CMS 系・静かで知的な印象 |
|
||||||
|
| posimai-site | `#80CAEE` Sky-Blue | `#0284C7` | journal と同系統の公開サイト |
|
||||||
|
| ponshu-room | `#D4A574` 琥珀(Amber) | `#D4A574` | **Posimai デザインシステム適用外**。独立プロダクト。Washi テーマ(和紙×墨×琥珀)を使用。詳細は `ponshu-room/ROADMAP.md` を参照。 |
|
||||||
|
|
||||||
|
**新アプリ作成時のルール:**
|
||||||
|
1. デフォルト Teal を使うなら何も記載不要
|
||||||
|
2. 意図的に変える場合はこの表に追記してから実装する
|
||||||
|
3. 同じ用途・系統のアプリは同じアクセントカラーに揃える
|
||||||
|
|
||||||
|
## 新アプリ作成
|
||||||
|
|
||||||
|
`_template/` をコピーして使う。`APP_NAME` / `APP_ID` / `APP_DESCRIPTION` を置換するだけで動く。
|
||||||
|
|
||||||
|
**完全な手順(Git / Vercel セットアップ含む)は必ず `_template/README.md` を参照すること。**
|
||||||
|
特に以下の2点は詰まりやすいので注意:
|
||||||
|
- Gitea リポジトリは **Web UI で先に作成**してから `git remote add gitea` する
|
||||||
|
- `vercel git connect` 後、**空コミット push** で初回本番デプロイをトリガーする
|
||||||
|
|
||||||
|
### 新アプリ作成後の必須チェックリスト(抜け漏れ禁止)
|
||||||
|
|
||||||
|
新しいアプリを作ったら、**コード実装の完了直後に必ずこの順番で実行する**こと:
|
||||||
|
|
||||||
|
0. **【実装前】アクセントカラーを宣言する**
|
||||||
|
- このアプリのカテゴリを確認(インプット/作成・編集/ツール/共有/インフラ)
|
||||||
|
- デフォルト Teal で問題なければ何もしない
|
||||||
|
- Sky Blue 等に変える場合は CLAUDE.md の「アプリ別アクセントカラー」テーブルに**先に追記**してから実装を開始する
|
||||||
|
|
||||||
|
1. **Dashboard カード追加**
|
||||||
|
- `posimai-dashboard/src/data/projects.json` の `projects` 配列にエントリを追加
|
||||||
|
- 適切な `category` を設定(`posimai-pwa` / `active` / `flagship` / `micro` / `infra` など)
|
||||||
|
|
||||||
|
2. **Ecosystem Map 追加**
|
||||||
|
- `posimai-dashboard/src/app/ecosystem/page.tsx` の `NODES` 配列にノードを追加
|
||||||
|
- 関連する `EDGES`(依存関係)も追加
|
||||||
|
|
||||||
|
3. **Development Timeline に追記**
|
||||||
|
- `posimai-dashboard/src/app/timeline/page.tsx` の `EVENTS` 配列に今日の日付でエントリを追加
|
||||||
|
- type: `launch`(新規公開)/ `feature`(機能追加)/ `fix`(修正)/ `infra`(インフラ)
|
||||||
|
|
||||||
|
4. **Access Guide に追記**
|
||||||
|
- `posimai-dashboard/src/app/access/page.tsx` の `APPS` 配列にエントリを追加
|
||||||
|
- `accessLevel` / `codevAccess` / `authDetail` / `codevNote` を正確に記入する
|
||||||
|
|
||||||
|
5. **Dashboard をデプロイ**
|
||||||
|
```bash
|
||||||
|
cd posimai-dashboard
|
||||||
|
git add src/data/projects.json src/app/ecosystem/page.tsx src/app/timeline/page.tsx src/app/access/page.tsx
|
||||||
|
git commit -m "feat: add [app-name] to dashboard"
|
||||||
|
npm run deploy
|
||||||
|
```
|
||||||
|
|
||||||
|
6. **プロジェクト構成テーブルを CLAUDE.md に追記**(このファイル)
|
||||||
|
|
||||||
|
> ⚠️ ダッシュボード更新(カード・Ecosystem・Timeline)を忘れると、アプリが孤立してエコシステムから見えなくなる。
|
||||||
|
|
||||||
|
## 既存アプリに大きな変更をした場合の必須チェックリスト
|
||||||
|
|
||||||
|
機能追加・バグ修正・リリースなど **ユーザーが気づくレベルの変更** をしたら:
|
||||||
|
|
||||||
|
1. `posimai-dashboard/src/app/timeline/page.tsx` の `EVENTS` 配列に今日の日付でエントリを追加
|
||||||
|
2. Dashboard をデプロイ
|
||||||
|
|
||||||
|
## Git リモート(全アプリ共通)
|
||||||
|
- `gitea` → `http://100.76.7.3:3000/mai/[app-name].git`
|
||||||
|
- `github` → `https://github.com/posimai/[app-name].git`
|
||||||
|
|
@ -0,0 +1,86 @@
|
||||||
|
# Posimai Static App Template
|
||||||
|
|
||||||
|
新しい静的 PWA アプリを作るときのボイラープレート。
|
||||||
|
|
||||||
|
## 使い方
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. テンプレートをコピー
|
||||||
|
cp -r _template posimai-[new-app-name]
|
||||||
|
cd posimai-[new-app-name]
|
||||||
|
|
||||||
|
# 2. APP_NAME / APP_ID / APP_DESCRIPTION を置換
|
||||||
|
# APP_NAME → 表示名 (例: "Posimai Timer")
|
||||||
|
# APP_ID → 識別子 (例: "posimai-timer")
|
||||||
|
# APP_DESCRIPTION → 説明文
|
||||||
|
|
||||||
|
# 3. Git 初期化
|
||||||
|
git init && git add . && git commit -m "init: APP_NAME"
|
||||||
|
|
||||||
|
# 4. Gitea にリポジトリを作成(★ Web UI で先に行う)
|
||||||
|
# http://100.76.7.3:3000 にアクセス
|
||||||
|
# → 「+」→「新しいリポジトリ」→ 名前: APP_ID → 作成
|
||||||
|
# ※ この手順を飛ばすと git push gitea が 404 で失敗する
|
||||||
|
|
||||||
|
# 5. GitHub にリポジトリ作成(gh CLI)
|
||||||
|
gh repo create posimai/APP_ID --private
|
||||||
|
|
||||||
|
# 6. リモートを追加して初回 push
|
||||||
|
git remote add gitea http://100.76.7.3:3000/mai/APP_ID.git
|
||||||
|
git remote add github https://github.com/posimai/APP_ID.git
|
||||||
|
npm run deploy # = git push gitea main && git push github main
|
||||||
|
|
||||||
|
# 7. Vercel と GitHub を連携(1アプリにつき1回だけ)
|
||||||
|
# --yes では対話が消えないため echo パイプで GitHub を選択させる
|
||||||
|
echo "https://github.com/posimai/APP_ID.git" | vercel git connect
|
||||||
|
|
||||||
|
# 8. 初回本番デプロイをトリガー(1回だけ必要)
|
||||||
|
# vercel git connect だけでは本番反映されないため、空コミットで push する
|
||||||
|
git commit --allow-empty -m "ci: trigger initial Vercel deployment"
|
||||||
|
npm run deploy
|
||||||
|
# Vercel ダッシュボードで "Production" デプロイが完了したら以降は不要
|
||||||
|
# ※ 通常運用では vercel --prod は実行しない(GitHub push で自動)
|
||||||
|
```
|
||||||
|
|
||||||
|
以降の更新はすべて:
|
||||||
|
```bash
|
||||||
|
git add .
|
||||||
|
git commit -m "feat/fix/chore: 変更内容"
|
||||||
|
npm run deploy
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## デプロイフロー(全体像)
|
||||||
|
|
||||||
|
```
|
||||||
|
npm run deploy
|
||||||
|
│
|
||||||
|
├─► git push gitea main → Synology NAS (ローカルバックアップのみ)
|
||||||
|
│
|
||||||
|
└─► git push github main → GitHub
|
||||||
|
│
|
||||||
|
│ Webhook (push 検知)
|
||||||
|
▼
|
||||||
|
Vercel
|
||||||
|
└─ ビルド → 本番反映
|
||||||
|
```
|
||||||
|
|
||||||
|
- **Gitea** はバックアップ専用。Vercel とは無関係。
|
||||||
|
- **GitHub push** が Vercel の唯一のトリガー。
|
||||||
|
- `vercel --prod` の直接実行は禁止(初回トリガー用の空コミット push で代替)。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## デザイントークン(変更禁止)
|
||||||
|
|
||||||
|
| トークン | 値 | 用途 |
|
||||||
|
|---------|-----|------|
|
||||||
|
| `--bg` | `#0D0D0D` | ページ背景 |
|
||||||
|
| `--surface` | `#1A1A1A` | カード背景 |
|
||||||
|
| `--surface2` | `#252525` | ネスト要素 |
|
||||||
|
| `--border` | `#2D2D2D` | ボーダー |
|
||||||
|
| `--text` | `#F3F4F6` | 主テキスト |
|
||||||
|
| `--text2` | `#9CA3AF` | 副テキスト |
|
||||||
|
| `--accent` | `#6EE7B7` | アクセント |
|
||||||
|
| `--radius` | `12px` | 角丸 |
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"id": "/APP_ID/",
|
||||||
|
"name": "APP_NAME",
|
||||||
|
"short_name": "APP_NAME",
|
||||||
|
"description": "APP_DESCRIPTION",
|
||||||
|
"start_url": "/",
|
||||||
|
"display": "standalone",
|
||||||
|
"display_override": ["window-controls-overlay", "standalone"],
|
||||||
|
"background_color": "#0D0D0D",
|
||||||
|
"theme_color": "#0D0D0D",
|
||||||
|
"orientation": "portrait-primary",
|
||||||
|
"categories": ["productivity"],
|
||||||
|
"icons": [
|
||||||
|
{ "src": "/logo.png", "sizes": "192x192", "type": "image/png", "purpose": "any" },
|
||||||
|
{ "src": "/logo.png", "sizes": "512x512", "type": "image/png", "purpose": "any maskable" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"name": "APP_ID",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "APP_DESCRIPTION",
|
||||||
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"deploy": "git push gitea main && git push github main"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
// Posimai SW — stale-while-revalidate + update notification
|
||||||
|
// バージョンは index.html に inline で管理(この文字列変更で旧キャッシュ削除)
|
||||||
|
const CACHE = 'APP_ID-v2';
|
||||||
|
const STATIC = ['/', '/index.html', '/manifest.json', '/logo.png'];
|
||||||
|
|
||||||
|
self.addEventListener('install', e => {
|
||||||
|
e.waitUntil(
|
||||||
|
caches.open(CACHE).then(c => c.addAll(STATIC))
|
||||||
|
// skipWaiting() は意図的に呼ばない
|
||||||
|
// → updatefound イベントで UI 側からユーザーに通知する方式を採用
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
self.addEventListener('activate', e => {
|
||||||
|
e.waitUntil(
|
||||||
|
caches.keys().then(keys =>
|
||||||
|
Promise.all(keys.filter(k => k !== CACHE).map(k => caches.delete(k)))
|
||||||
|
).then(() => self.clients.claim())
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
self.addEventListener('fetch', e => {
|
||||||
|
if (e.request.method !== 'GET') return;
|
||||||
|
if (!e.request.url.startsWith(self.location.origin)) return;
|
||||||
|
|
||||||
|
e.respondWith(
|
||||||
|
caches.open(CACHE).then(cache =>
|
||||||
|
cache.match(e.request).then(cached => {
|
||||||
|
const network = fetch(e.request).then(res => {
|
||||||
|
if (res.ok && res.type === 'basic') cache.put(e.request, res.clone());
|
||||||
|
return res;
|
||||||
|
}).catch(() => cached);
|
||||||
|
// stale-while-revalidate: キャッシュがあればすぐ返し、裏でネットワーク更新
|
||||||
|
return cached || network;
|
||||||
|
})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# ============================================
|
||||||
|
# Posimai API — Synology server.js デプロイスクリプト
|
||||||
|
# 使い方: bash deploy-server.sh
|
||||||
|
# ============================================
|
||||||
|
set -e
|
||||||
|
|
||||||
|
HOST="mai@100.76.7.3"
|
||||||
|
CONTAINER="posimai_api"
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||||
|
SERVER_FILE="$SCRIPT_DIR/server.js"
|
||||||
|
REMOTE_TMP="/tmp/server-deploy.js"
|
||||||
|
DOCKER="/usr/local/bin/docker"
|
||||||
|
|
||||||
|
echo "========================================"
|
||||||
|
echo " Posimai API Deploy"
|
||||||
|
echo "========================================"
|
||||||
|
|
||||||
|
if [ ! -f "$SERVER_FILE" ]; then
|
||||||
|
echo "[ERROR] server.js が見つかりません: $SERVER_FILE"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "→ Step 1: server.js を Synology /tmp に転送..."
|
||||||
|
echo " (SSH パスワードを求められたら入力してください)"
|
||||||
|
ssh "$HOST" "cat > $REMOTE_TMP" < "$SERVER_FILE"
|
||||||
|
echo " ✓ 転送完了"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "→ Step 2: コンテナに適用 + 再起動..."
|
||||||
|
echo " (sudo パスワードを求められたら入力してください)"
|
||||||
|
ssh -t "$HOST" "
|
||||||
|
sudo $DOCKER cp $REMOTE_TMP $CONTAINER:/app/server.js && \
|
||||||
|
echo ' ✓ コピー完了' && \
|
||||||
|
sudo $DOCKER restart $CONTAINER && \
|
||||||
|
echo ' ✓ 再起動完了。ログを確認中...' && \
|
||||||
|
sleep 5 && \
|
||||||
|
sudo $DOCKER logs $CONTAINER --tail 20
|
||||||
|
"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "========================================"
|
||||||
|
echo " Deploy 完了"
|
||||||
|
echo "========================================"
|
||||||
|
|
@ -0,0 +1,156 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# =============================================================================
|
||||||
|
# Posimai — Design Rules Checker
|
||||||
|
# デプロイ前に実行して禁止パターンの混入を検出する
|
||||||
|
# 使い方: bash scripts/check-design.sh [対象ディレクトリ]
|
||||||
|
# 例: bash scripts/check-design.sh posimai-habit
|
||||||
|
# bash scripts/check-design.sh ← 全 HTML アプリを対象
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
TARGET="${1:-.}"
|
||||||
|
ERRORS=0
|
||||||
|
WARNINGS=0
|
||||||
|
|
||||||
|
RED='\033[0;31m'
|
||||||
|
YLW='\033[0;33m'
|
||||||
|
GRN='\033[0;32m'
|
||||||
|
DIM='\033[2m'
|
||||||
|
NC='\033[0m'
|
||||||
|
|
||||||
|
err() { echo -e "${RED}[ERR]${NC} $1"; ((ERRORS++)); }
|
||||||
|
warn() { echo -e "${YLW}[WARN]${NC} $1"; ((WARNINGS++)); }
|
||||||
|
ok() { echo -e "${GRN}[OK]${NC} $1"; }
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo " Posimai Design Rules Checker"
|
||||||
|
echo " Target: ${TARGET}"
|
||||||
|
echo " ────────────────────────────────────────"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ── 1. 絵文字の混入 ──────────────────────────────────────────────────────────
|
||||||
|
echo "1. 絵文字チェック"
|
||||||
|
EMOJI_HITS=$(grep -rn --include="*.html" --include="*.tsx" --include="*.ts" --include="*.js" \
|
||||||
|
-P '[\x{1F300}-\x{1F9FF}]|[\x{2600}-\x{27BF}]|✅|📱|⚙️|🎉|🚀|❌|⚠️|💡|🔧|📦|🎨' \
|
||||||
|
"${TARGET}" 2>/dev/null | grep -v ".git/" | grep -v "node_modules/")
|
||||||
|
if [ -n "$EMOJI_HITS" ]; then
|
||||||
|
err "絵文字が検出されました"
|
||||||
|
echo "$EMOJI_HITS" | while read -r line; do echo -e " ${DIM}${line}${NC}"; done
|
||||||
|
else
|
||||||
|
ok "絵文字なし"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ── 2. @latest バージョン未固定 ─────────────────────────────────────────────
|
||||||
|
echo "2. CDN バージョン固定チェック (@latest)"
|
||||||
|
LATEST_HITS=$(grep -rn --include="*.html" --include="*.tsx" --include="*.ts" \
|
||||||
|
"@latest" "${TARGET}" 2>/dev/null | grep -v ".git/" | grep -v "node_modules/")
|
||||||
|
if [ -n "$LATEST_HITS" ]; then
|
||||||
|
err "@latest が検出されました — バージョンを固定してください"
|
||||||
|
echo "$LATEST_HITS" | while read -r line; do echo -e " ${DIM}${line}${NC}"; done
|
||||||
|
else
|
||||||
|
ok "@latest なし"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ── 3. manifest.json 参照の確認 ──────────────────────────────────────────────
|
||||||
|
echo "3. manifest.json 参照チェック"
|
||||||
|
HTML_FILES=$(find "${TARGET}" -name "index.html" -not -path "*/.git/*" -not -path "*/node_modules/*" 2>/dev/null)
|
||||||
|
MISSING_MANIFEST=""
|
||||||
|
for f in $HTML_FILES; do
|
||||||
|
if ! grep -q "manifest.json" "$f"; then
|
||||||
|
MISSING_MANIFEST="${MISSING_MANIFEST}\n ${f}"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if [ -n "$MISSING_MANIFEST" ]; then
|
||||||
|
err "manifest.json 参照がない index.html:${MISSING_MANIFEST}"
|
||||||
|
else
|
||||||
|
[ -n "$HTML_FILES" ] && ok "全 index.html に manifest.json あり"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ── 4. sw.js 参照の確認 ──────────────────────────────────────────────────────
|
||||||
|
echo "4. sw.js 参照チェック"
|
||||||
|
MISSING_SW=""
|
||||||
|
for f in $HTML_FILES; do
|
||||||
|
if ! grep -q "sw.js" "$f"; then
|
||||||
|
MISSING_SW="${MISSING_SW}\n ${f}"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if [ -n "$MISSING_SW" ]; then
|
||||||
|
err "sw.js 参照がない index.html:${MISSING_SW}"
|
||||||
|
else
|
||||||
|
[ -n "$HTML_FILES" ] && ok "全 index.html に sw.js あり"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ── 5. theme-color メディアクエリ欠落チェック ────────────────────────────────
|
||||||
|
echo "5. theme-color メディアクエリチェック"
|
||||||
|
MISSING_MQ=""
|
||||||
|
for f in $HTML_FILES; do
|
||||||
|
# theme-color はあるがメディアクエリがない行を検出
|
||||||
|
if grep -q 'name="theme-color"' "$f"; then
|
||||||
|
if grep -P 'name="theme-color"' "$f" | grep -qv 'media='; then
|
||||||
|
MISSING_MQ="${MISSING_MQ}\n ${f}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if [ -n "$MISSING_MQ" ]; then
|
||||||
|
err "theme-color にメディアクエリがありません:${MISSING_MQ}"
|
||||||
|
else
|
||||||
|
[ -n "$HTML_FILES" ] && ok "theme-color メディアクエリ OK"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ── 6. アクセントカラー直書きチェック ───────────────────────────────────────
|
||||||
|
echo "6. アクセントカラー直書きチェック"
|
||||||
|
HARDCODED_HITS=$(grep -rn --include="*.html" --include="*.css" \
|
||||||
|
-E '(color|background|border|box-shadow|fill|stroke)\s*:\s*(#6EE7B7|#059669|#80CAEE|#0284C7)' \
|
||||||
|
"${TARGET}" 2>/dev/null | grep -v ".git/" | grep -v "node_modules/" | \
|
||||||
|
# CLAUDE.md や定義部分 (:root, CSS変数定義) は除外
|
||||||
|
grep -v "var(--" | grep -v ":root")
|
||||||
|
if [ -n "$HARDCODED_HITS" ]; then
|
||||||
|
warn "アクセントカラーが CSS 変数ではなく直書きされています (var(--accent) 推奨)"
|
||||||
|
echo "$HARDCODED_HITS" | while read -r line; do echo -e " ${DIM}${line}${NC}"; done
|
||||||
|
else
|
||||||
|
ok "アクセントカラー直書きなし"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ── 7. rel="noopener" チェック ────────────────────────────────────────────────
|
||||||
|
echo "7. rel=noopener チェック (target=_blank)"
|
||||||
|
NOOP_HITS=$(grep -rn --include="*.html" --include="*.tsx" --include="*.ts" \
|
||||||
|
'target="_blank"' "${TARGET}" 2>/dev/null | \
|
||||||
|
grep -v 'rel=.*noopener' | grep -v ".git/" | grep -v "node_modules/")
|
||||||
|
if [ -n "$NOOP_HITS" ]; then
|
||||||
|
warn 'target="_blank" に rel="noopener" がありません'
|
||||||
|
echo "$NOOP_HITS" | while read -r line; do echo -e " ${DIM}${line}${NC}"; done
|
||||||
|
else
|
||||||
|
ok 'rel="noopener" OK'
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ── 8. lucide@0.344.0 以外のバージョン ──────────────────────────────────────
|
||||||
|
echo "8. Lucide バージョンチェック"
|
||||||
|
LUCIDE_WRONG=$(grep -rn --include="*.html" \
|
||||||
|
"lucide@" "${TARGET}" 2>/dev/null | \
|
||||||
|
grep -v "lucide@0.344.0" | grep -v ".git/" | grep -v "node_modules/")
|
||||||
|
if [ -n "$LUCIDE_WRONG" ]; then
|
||||||
|
err "lucide@0.344.0 以外のバージョンが検出されました"
|
||||||
|
echo "$LUCIDE_WRONG" | while read -r line; do echo -e " ${DIM}${line}${NC}"; done
|
||||||
|
else
|
||||||
|
ok "Lucide バージョン OK"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ── 結果サマリ ────────────────────────────────────────────────────────────────
|
||||||
|
echo " ────────────────────────────────────────"
|
||||||
|
if [ $ERRORS -eq 0 ] && [ $WARNINGS -eq 0 ]; then
|
||||||
|
echo -e " ${GRN}すべてのチェックをパスしました。${NC}"
|
||||||
|
elif [ $ERRORS -eq 0 ]; then
|
||||||
|
echo -e " ${YLW}警告 ${WARNINGS} 件(エラーなし)。確認してからデプロイしてください。${NC}"
|
||||||
|
else
|
||||||
|
echo -e " ${RED}エラー ${ERRORS} 件 / 警告 ${WARNINGS} 件。デプロイ前に修正してください。${NC}"
|
||||||
|
echo ""
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
@ -0,0 +1,72 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# deploy-server.sh
|
||||||
|
# server-updated.js を Synology の posimai_api コンテナに自動デプロイする
|
||||||
|
#
|
||||||
|
# 使い方:
|
||||||
|
# bash scripts/deploy-server.sh
|
||||||
|
#
|
||||||
|
# === 初回セットアップ(一度だけ)=== 完全自動化のための NOPASSWD 設定
|
||||||
|
# ssh mai@100.76.7.3
|
||||||
|
# echo 'mai ALL=(ALL) NOPASSWD: /usr/local/bin/docker' | sudo tee /etc/sudoers.d/mai-docker
|
||||||
|
# chmod 440 /etc/sudoers.d/mai-docker
|
||||||
|
# exit
|
||||||
|
# # 以後 sudo docker コマンドがパスワードなしで実行可能になる
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
SERVER_FILE="$SCRIPT_DIR/../server.js"
|
||||||
|
SSH_HOST="mai@100.76.7.3"
|
||||||
|
DOCKER="/usr/local/bin/docker"
|
||||||
|
CONTAINER="posimai_api"
|
||||||
|
REMOTE_TMP="/tmp/posimai-server-deploy.js"
|
||||||
|
|
||||||
|
if [ ! -f "$SERVER_FILE" ]; then
|
||||||
|
echo "ERROR: $SERVER_FILE が見つかりません"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "==> [1/3] Synology にファイル転送中 (stdin 経由、SFTP不要)..."
|
||||||
|
cat "$SERVER_FILE" | ssh "$SSH_HOST" "cat > $REMOTE_TMP"
|
||||||
|
echo " 転送完了"
|
||||||
|
|
||||||
|
echo "==> [2/3] コンテナへコピー & 再起動..."
|
||||||
|
# NOPASSWD 設定済みの場合: -t なしで動作
|
||||||
|
# 未設定の場合: ターミナルから手動実行が必要
|
||||||
|
if ssh "$SSH_HOST" "sudo -n $DOCKER inspect $CONTAINER > /dev/null 2>&1"; then
|
||||||
|
# NOPASSWD 有効 — 完全自動
|
||||||
|
ssh "$SSH_HOST" "
|
||||||
|
sudo $DOCKER cp $REMOTE_TMP $CONTAINER:/app/server.js && \
|
||||||
|
sudo $DOCKER restart $CONTAINER && \
|
||||||
|
rm -f $REMOTE_TMP
|
||||||
|
"
|
||||||
|
echo " コンテナ再起動完了"
|
||||||
|
else
|
||||||
|
# NOPASSWD 未設定 — ファイルは転送済み、docker コマンドは手動実行
|
||||||
|
echo ""
|
||||||
|
echo "ファイル転送完了。以下を Synology SSH で実行してください:"
|
||||||
|
echo ""
|
||||||
|
echo " ssh -t $SSH_HOST \\"
|
||||||
|
echo " \"sudo $DOCKER cp $REMOTE_TMP $CONTAINER:/app/server.js && \\"
|
||||||
|
echo " sudo $DOCKER restart $CONTAINER && \\"
|
||||||
|
echo " rm -f $REMOTE_TMP\""
|
||||||
|
echo ""
|
||||||
|
echo "完全自動化するには初回セットアップ(スクリプト冒頭のコメント参照)を行ってください。"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "==> [3/3] ヘルスチェック..."
|
||||||
|
sleep 3
|
||||||
|
STATUS=$(ssh "$SSH_HOST" "sudo $DOCKER inspect --format='{{.State.Status}}' $CONTAINER 2>/dev/null || echo unknown")
|
||||||
|
echo " コンテナ状態: $STATUS"
|
||||||
|
|
||||||
|
if [ "$STATUS" = "running" ]; then
|
||||||
|
echo ""
|
||||||
|
echo "デプロイ成功!"
|
||||||
|
echo "API: https://posimai-lab.tail72e846.ts.net/brain/api"
|
||||||
|
else
|
||||||
|
echo ""
|
||||||
|
echo "WARNING: コンテナの状態を確認してください (status: $STATUS)"
|
||||||
|
echo " ssh mai@100.76.7.3"
|
||||||
|
echo " sudo /usr/local/bin/docker logs $CONTAINER --tail 50"
|
||||||
|
fi
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
# Brain記事エクスポートスクリプト
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory=$true)]
|
||||||
|
[int]$ArticleId
|
||||||
|
)
|
||||||
|
|
||||||
|
$outputFile = "article-$ArticleId-clean.md"
|
||||||
|
|
||||||
|
Write-Host "記事ID $ArticleId をエクスポート中..." -ForegroundColor Cyan
|
||||||
|
|
||||||
|
# SSHでPostgreSQLから取得
|
||||||
|
$content = ssh mai@100.76.7.3 "/usr/local/bin/docker exec gitea_db psql -U gitea -d posimai_brain -t -A -c 'SELECT full_text FROM articles WHERE id=$ArticleId'"
|
||||||
|
|
||||||
|
if ($LASTEXITCODE -ne 0) {
|
||||||
|
Write-Host "エラー: 記事の取得に失敗しました" -ForegroundColor Red
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# \nを実際の改行に変換
|
||||||
|
$content = $content -replace '\\n', "`r`n"
|
||||||
|
|
||||||
|
# UTF-8で保存
|
||||||
|
[System.IO.File]::WriteAllText("$PSScriptRoot\$outputFile", $content, [System.Text.Encoding]::UTF8)
|
||||||
|
|
||||||
|
Write-Host "✓ 保存完了: $outputFile" -ForegroundColor Green
|
||||||
|
Write-Host " ファイルサイズ: $([Math]::Round((Get-Item $outputFile).Length / 1KB, 2)) KB"
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# Brain記事エクスポートスクリプト (Git Bash用)
|
||||||
|
|
||||||
|
if [ -z "$1" ]; then
|
||||||
|
echo "使用方法: ./export-article.sh <記事ID>"
|
||||||
|
echo "例: ./export-article.sh 78"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
ARTICLE_ID=$1
|
||||||
|
OUTPUT_FILE="article-${ARTICLE_ID}.md"
|
||||||
|
|
||||||
|
echo "📥 記事ID ${ARTICLE_ID} をエクスポート中..."
|
||||||
|
|
||||||
|
# SSHでPostgreSQLから取得して、\nを実際の改行に変換
|
||||||
|
ssh mai@100.76.7.3 "/usr/local/bin/docker exec gitea_db psql -U gitea -d posimai_brain -t -A -c 'SELECT full_text FROM articles WHERE id=${ARTICLE_ID}'" | sed 's/\\n/\n/g' > "${OUTPUT_FILE}"
|
||||||
|
|
||||||
|
if [ $? -eq 0 ] && [ -s "${OUTPUT_FILE}" ]; then
|
||||||
|
FILE_SIZE=$(du -h "${OUTPUT_FILE}" | cut -f1)
|
||||||
|
echo "✅ 保存完了: ${OUTPUT_FILE}"
|
||||||
|
echo " ファイルサイズ: ${FILE_SIZE}"
|
||||||
|
else
|
||||||
|
echo "❌ エラー: 記事の取得に失敗しました"
|
||||||
|
rm -f "${OUTPUT_FILE}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
@ -0,0 +1,126 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
# Posimai New App Generator
|
||||||
|
# 使い方: bash scripts/new-app.sh <app-id> "<表示名>" "<説明>"
|
||||||
|
# 例: bash scripts/new-app.sh posimai-timer "Posimai Timer" "シンプルなタイマーアプリ"
|
||||||
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
set -e # エラーで即停止
|
||||||
|
|
||||||
|
# ── 引数チェック ──────────────────────────────────────────────
|
||||||
|
APP_ID="${1}"
|
||||||
|
APP_NAME="${2}"
|
||||||
|
APP_DESC="${3:-Posimai App}"
|
||||||
|
|
||||||
|
if [[ -z "$APP_ID" || -z "$APP_NAME" ]]; then
|
||||||
|
echo "使い方: bash scripts/new-app.sh <app-id> \"<表示名>\" \"<説明>\""
|
||||||
|
echo "例: bash scripts/new-app.sh posimai-timer \"Posimai Timer\" \"シンプルなタイマーアプリ\""
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ── 設定 ──────────────────────────────────────────────────────
|
||||||
|
BASE_DIR="$(cd "$(dirname "$0")/.." && pwd)"
|
||||||
|
TEMPLATE_DIR="$BASE_DIR/_template"
|
||||||
|
APP_DIR="$BASE_DIR/$APP_ID"
|
||||||
|
GITEA_URL="http://100.76.7.3:3000"
|
||||||
|
GITEA_USER="mai"
|
||||||
|
GITEA_PASS=$(printf "protocol=http\nhost=100.76.7.3\n" | git credential fill 2>/dev/null | grep ^password | cut -d= -f2)
|
||||||
|
GITHUB_ORG="posimai"
|
||||||
|
|
||||||
|
# ── 既存チェック ──────────────────────────────────────────────
|
||||||
|
if [[ -d "$APP_DIR" ]]; then
|
||||||
|
echo "エラー: $APP_DIR はすでに存在します"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "═══════════════════════════════════════"
|
||||||
|
echo " 新アプリ作成: $APP_NAME"
|
||||||
|
echo " ID: $APP_ID"
|
||||||
|
echo "═══════════════════════════════════════"
|
||||||
|
|
||||||
|
# ── Step 1: テンプレートをコピー ──────────────────────────────
|
||||||
|
echo ""
|
||||||
|
echo "[ 1/6 ] テンプレートをコピー中..."
|
||||||
|
cp -r "$TEMPLATE_DIR" "$APP_DIR"
|
||||||
|
|
||||||
|
# プレースホルダーを置換(全ファイル対象)
|
||||||
|
find "$APP_DIR" -type f \( -name "*.html" -o -name "*.json" -o -name "*.js" -o -name "*.md" \) | while read f; do
|
||||||
|
sed -i "s/APP_NAME/$APP_NAME/g; s/APP_ID/$APP_ID/g; s/APP_DESCRIPTION/$APP_DESC/g" "$f"
|
||||||
|
done
|
||||||
|
echo " 完了: $APP_DIR"
|
||||||
|
|
||||||
|
# ── Step 2: Git 初期化 ─────────────────────────────────────────
|
||||||
|
echo ""
|
||||||
|
echo "[ 2/6 ] Git 初期化..."
|
||||||
|
cd "$APP_DIR"
|
||||||
|
git init -b main
|
||||||
|
git add .
|
||||||
|
git commit -m "init: $APP_NAME"
|
||||||
|
echo " 完了"
|
||||||
|
|
||||||
|
# ── Step 3: Gitea リポジトリ作成 ─────────────────────────────
|
||||||
|
echo ""
|
||||||
|
echo "[ 3/6 ] Gitea にリポジトリ作成中..."
|
||||||
|
HTTP_STATUS=$(curl -s -o /dev/null -w "%{http_code}" \
|
||||||
|
-X POST "$GITEA_URL/api/v1/user/repos" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-u "$GITEA_USER:$GITEA_PASS" \
|
||||||
|
-d "{\"name\":\"$APP_ID\",\"private\":true,\"auto_init\":false}")
|
||||||
|
|
||||||
|
if [[ "$HTTP_STATUS" == "201" ]]; then
|
||||||
|
echo " 完了: $GITEA_URL/$GITEA_USER/$APP_ID"
|
||||||
|
else
|
||||||
|
echo " 警告: Gitea API status=$HTTP_STATUS (既存または接続不可)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
git remote add gitea "$GITEA_URL/$GITEA_USER/$APP_ID.git"
|
||||||
|
git push gitea main
|
||||||
|
echo " Push 完了"
|
||||||
|
|
||||||
|
# ── Step 4: GitHub リポジトリ作成 ────────────────────────────
|
||||||
|
echo ""
|
||||||
|
echo "[ 4/6 ] GitHub にリポジトリ作成中..."
|
||||||
|
gh repo create "$GITHUB_ORG/$APP_ID" --private --description "$APP_DESC" 2>&1
|
||||||
|
git remote add github "https://github.com/$GITHUB_ORG/$APP_ID.git"
|
||||||
|
git push github main
|
||||||
|
echo " 完了: https://github.com/$GITHUB_ORG/$APP_ID"
|
||||||
|
|
||||||
|
# ── Step 5: Vercel 接続 ───────────────────────────────────────
|
||||||
|
echo ""
|
||||||
|
echo "[ 5/6 ] Vercel に接続中..."
|
||||||
|
# github リモートを選択するため "2" を入力(gitea=1, github=2)
|
||||||
|
printf "2\n" | vercel git connect "https://github.com/$GITHUB_ORG/$APP_ID.git" --yes 2>&1 || true
|
||||||
|
echo " 完了"
|
||||||
|
|
||||||
|
# ── Step 6: git hooks インストール ───────────────────────────
|
||||||
|
echo ""
|
||||||
|
echo "[ 6/6 ] Git フック設定..."
|
||||||
|
cat > "$APP_DIR/.git/hooks/post-commit" << 'HOOK'
|
||||||
|
#!/bin/sh
|
||||||
|
echo ""
|
||||||
|
echo "📦 コミット完了。デプロイするには:"
|
||||||
|
echo " npm run deploy"
|
||||||
|
echo " (Gitea + GitHub → Vercel 自動デプロイ)"
|
||||||
|
echo ""
|
||||||
|
HOOK
|
||||||
|
chmod +x "$APP_DIR/.git/hooks/post-commit"
|
||||||
|
echo " 完了"
|
||||||
|
|
||||||
|
# ── 完了メッセージ ────────────────────────────────────────────
|
||||||
|
echo ""
|
||||||
|
echo "═══════════════════════════════════════"
|
||||||
|
echo " $APP_NAME — セットアップ完了!"
|
||||||
|
echo "═══════════════════════════════════════"
|
||||||
|
echo ""
|
||||||
|
echo " ディレクトリ : $APP_DIR"
|
||||||
|
echo " Gitea : $GITEA_URL/$GITEA_USER/$APP_ID"
|
||||||
|
echo " GitHub : https://github.com/$GITHUB_ORG/$APP_ID"
|
||||||
|
echo " Vercel : https://$APP_ID.vercel.app (初回デプロイ後)"
|
||||||
|
echo ""
|
||||||
|
echo " 次のコマンドで開発開始:"
|
||||||
|
echo " cd $APP_ID"
|
||||||
|
echo " # コードを編集して..."
|
||||||
|
echo " git add . && git commit -m \"feat: ...\""
|
||||||
|
echo " npm run deploy"
|
||||||
|
echo ""
|
||||||
Loading…
Reference in New Issue