From 406ce416f70ad1a1c0da97ef1a402c1b47678c0e Mon Sep 17 00:00:00 2001 From: posimai Date: Sat, 18 Apr 2026 22:17:52 +0900 Subject: [PATCH] =?UTF-8?q?init:=20Boki=20=E2=80=94=20=E7=B0=BF=E8=A8=982?= =?UTF-8?q?=E7=B4=9A=20=E6=A6=82=E5=BF=B5=E5=AD=A6=E7=BF=92=E3=83=BB?= =?UTF-8?q?=E7=90=86=E8=A7=A3=E5=BA=A6=E3=83=81=E3=82=A7=E3=83=83=E3=82=AF?= =?UTF-8?q?=E3=82=A2=E3=83=97=E3=83=AA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 64 ++++ index.html | 800 ++++++++++++++++++++++++++++++++++++++++++++++++++ manifest.json | 17 ++ package.json | 9 + sw.js | 37 +++ 5 files changed, 927 insertions(+) create mode 100644 README.md create mode 100644 index.html create mode 100644 manifest.json create mode 100644 package.json create mode 100644 sw.js diff --git a/README.md b/README.md new file mode 100644 index 0000000..d380f3e --- /dev/null +++ b/README.md @@ -0,0 +1,64 @@ +# Posimai Minimal App Template + +シンプルなツール系 PWA アプリ用のボイラープレート。 +サイドバーなし・i18n なし・Magic Link なし。ヘッダー + メインコンテンツのみ。 + +## _template vs _template-minimal の使い分け + +| テンプレート | 向いているアプリ | +|------------|----------------| +| `_template/` | 複数ビュー・i18n・Magic Link・設定パネルが必要なアプリ(brain, daily, together 等) | +| `_template-minimal/` | 単機能ツール(diff, clean, timer, lens, ambient 等) | + +## 使い方 + +```bash +# 1. テンプレートをコピー +cp -r _template-minimal posimai-[new-app-name] +cd posimai-[new-app-name] + +# 2. APP_NAME / APP_ID / APP_DESCRIPTION を置換 +# APP_NAME → 表示名 (例: "Posimai Memo") +# APP_ID → 識別子 (例: "posimai-memo") +# APP_DESCRIPTION → 説明文 + +# 3. 以降は _template/README.md の Step 3〜8 と同じ手順 +``` + +または `create-app.sh` を使う(`--minimal` フラグはまだない。手動コピーで対応): + +```bash +# create-app.sh は _template/ を使う。 +# minimal を使いたい場合は先に手動コピーしてから Git セットアップだけ行う: +cd posimai-[new-app-name] +git init -b main && git add . && git commit -m "init: APP_NAME" +gh repo create posimai/APP_ID --private +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 +echo "https://github.com/posimai/APP_ID.git" | vercel git connect +git commit --allow-empty -m "ci: trigger initial Vercel deployment" +npm run deploy +``` + +## 実装ガイド + +`index.html` の中の以下のコメント箇所を編集するだけ: + +1. ` +
+
+

簿記2級学習アプリ

+

商業簿記・工業簿記を単元ごとに学習し、理解度チェックで定着させましょう。3級の基礎から丁寧に復習できます。

+
+
+
+
修了単元
+
+
+
+
全単元
+
+
+
+
クイズ正解
+
+
+
+
+ +
+
+ + +
+
+ +
+
+
+
+
+ + +
+
+ + 概念解説 +
+
+
+ + +
+
+ + 重要ポイント +
+
    + +
+
+ + +
+
+
+ + 理解度チェック +
+
+
+ + + + +
+
+
正解 / 全問
+
+
+ + +
+
+
+ + +
+ + + +
+
+ + + + + + + diff --git a/manifest.json b/manifest.json new file mode 100644 index 0000000..4a34d89 --- /dev/null +++ b/manifest.json @@ -0,0 +1,17 @@ +{ + "id": "/posimai-boki/", + "name": "Boki — 簿記2級", + "short_name": "Boki", + "description": "簿記2級 概念学習・理解度チェックアプリ", + "start_url": "/", + "display": "standalone", + "display_override": ["window-controls-overlay", "standalone"], + "background_color": "#0C1221", + "theme_color": "#0C1221", + "orientation": "portrait-primary", + "categories": ["education"], + "icons": [ + { "src": "/logo.png", "sizes": "192x192", "type": "image/png", "purpose": "any" }, + { "src": "/logo.png", "sizes": "512x512", "type": "image/png", "purpose": "any maskable" } + ] +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..598135f --- /dev/null +++ b/package.json @@ -0,0 +1,9 @@ +{ + "name": "posimai-boki", + "version": "1.0.0", + "description": "簿記2級 概念学習・理解度チェックアプリ", + "private": true, + "scripts": { + "deploy": "git push gitea main && git push github main" + } +} diff --git a/sw.js b/sw.js new file mode 100644 index 0000000..eb248fa --- /dev/null +++ b/sw.js @@ -0,0 +1,37 @@ +// posimai-boki SW — stale-while-revalidate + skipWaiting +const CACHE = 'posimai-boki-v1'; +const STATIC = ['/', '/index.html', '/manifest.json', '/logo.png']; + +self.addEventListener('install', e => { + e.waitUntil( + caches.open(CACHE).then(c => c.addAll(STATIC.filter(u => { + try { new URL(u, self.location.origin); return true; } catch { return false; } + }))) + ); + self.skipWaiting(); +}); + +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); + return cached || network; + }) + ) + ); +});