From b77c3310cb920d5fd4c4a18d070a5a8da4ada7fd Mon Sep 17 00:00:00 2001 From: KKKK Date: Fri, 23 Oct 2026 19:42:24 +0800 Subject: [PATCH 1/3] Let pnpm install and use Node.js 24 for the local edition devEngines.runtime downloads the pinned Node.js 24 into the project, so a machine with another Node.js version can run every pnpm command; the doctor and setup errors now point at running through pnpm. --- CONTRIBUTING.md | 2 +- docs/beat-geo/getting-started.md | 2 +- docs/self-hosting.md | 4 +- package.json | 7 ++ pnpm-lock.yaml | 137 +++++++++++++++++++++++++++++++ scripts/local-doctor.mjs | 4 +- scripts/setup-local.mjs | 2 +- 7 files changed, 151 insertions(+), 7 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e64806ac..681b0c5a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,5 +1,5 @@ # Contributing to BeatGEO -Use a branch and pull request against main. Follow AGENTS.md, retain third-party notices, and keep credentials or raw customer/browser evidence out of Git. Use Node.js 24 and pnpm 12.4.1. Run lint and affected tests; distinguish mocked checks from real provider validation. +Use a branch and pull request against main. Follow AGENTS.md, retain third-party notices, and keep credentials or raw customer/browser evidence out of Git. Use pnpm 12.4.1; it installs and runs the project's Node.js 24. Run lint and affected tests; distinguish mocked checks from real provider validation. No upstream CLA or commercial service enrollment is required. Contributions are provided under this repository's MIT license. diff --git a/docs/beat-geo/getting-started.md b/docs/beat-geo/getting-started.md index 8b38bd08..fdb3a7ab 100644 --- a/docs/beat-geo/getting-started.md +++ b/docs/beat-geo/getting-started.md @@ -4,7 +4,7 @@ ```mermaid flowchart TD - A[准备 Git、Node 24、pnpm、Chrome] --> B[环境检查 local:doctor] + A[准备 Git、pnpm、Chrome(Node 24 由 pnpm 自动安装)] --> B[环境检查 local:doctor] B --> C[local:setup 自动建独立数据库并准备扩展] C --> D[local:start 启动网页、采集器和调度进程] D --> E[直接进入本地工作台并填写网站] diff --git a/docs/self-hosting.md b/docs/self-hosting.md index c4efd08a..b387bf56 100644 --- a/docs/self-hosting.md +++ b/docs/self-hosting.md @@ -1,8 +1,8 @@ # Self-hosting -For the complete first-use journey, see [Getting started](beat-geo/getting-started.md). Run `node scripts/local-doctor.mjs` to check prerequisites without changing data. +For the complete first-use journey, see [Getting started](beat-geo/getting-started.md). Run `pnpm local:doctor` to check prerequisites without changing data. -For a new local installation, use `pnpm local:setup` and `pnpm local:start`, then open http://localhost:3140/. This source installer requires Git, Node.js 24, pnpm 12.4.1 and Chrome; it bundles and manages its own PostgreSQL (no Docker required) and the pinned BeatBrowser extension. The advanced manual path below is for an existing dedicated PostgreSQL installation. SQLite is not supported. Build from source; no BeatGEO npm CLI, SDK or container images are published in this MVP. +For a new local installation, use `pnpm local:setup` and `pnpm local:start`, then open http://localhost:3140/. This source installer requires Git, pnpm 12.4.1 and Chrome (pnpm installs and uses Node.js 24 for this project); it bundles and manages its own PostgreSQL (no Docker required) and the pinned BeatBrowser extension. The advanced manual path below is for an existing dedicated PostgreSQL installation. SQLite is not supported. Build from source; no BeatGEO npm CLI, SDK or container images are published in this MVP. Default local storage lives in `.beat-geo/postgres`. Stop BeatGEO before backing up this directory together with `.beat-geo/database.json` and both private `.env` files. Older Docker/manual installations keep their original data and configuration; the local installer does not convert them. Back up and explicitly migrate existing data before switching to bundled storage. The local installer and launcher support bundled storage only. The native path has been exercised on macOS arm64; other upstream-supported platforms still require release validation. diff --git a/package.json b/package.json index 47f7d5f8..7281e10f 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,13 @@ "engines": { "node": "24.x" }, + "devEngines": { + "runtime": { + "name": "node", + "version": "24.x", + "onFail": "download" + } + }, "scripts": { "dev": "turbo dev --filter=!@workspace/www", "build": "turbo build", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1470a093..0267e9bb 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -205,6 +205,9 @@ importers: knip: specifier: ^6.39.0 version: 6.39.0 + node: + specifier: runtime:24.x + version: runtime:24.22.1 tsx: specifier: ^4.23.15 version: 4.23.15 @@ -8128,6 +8131,138 @@ packages: node-rsa@1.1.1: resolution: {integrity: sha512-Jd4cvbJMryN21r5HgxQOpMEqv+ooke/korixNNK3mGqfGJmy0M77WDDzo/05969+OkMy3XW1UuZsSmW9KQm7Fw==} + node@runtime:24.22.1: + resolution: + type: variations + variants: + - resolution: + archive: tarball + bin: + node: bin/node + integrity: sha256-9ie20HmCnmSKS4AP+oidN9viORNQcDADDbhaqGFZGiY= + type: binary + url: https://nodejs.org/download/release/v24.22.1/node-v24.22.1-aix-ppc64.tar.gz + targets: + - cpu: ppc64 + os: aix + - resolution: + archive: tarball + bin: + node: bin/node + integrity: sha256-icaCWT12zUQjP6U7FWMmTn3py7GJytFpE1xbT637wKc= + type: binary + url: https://nodejs.org/download/release/v24.22.1/node-v24.22.1-darwin-arm64.tar.gz + targets: + - cpu: arm64 + os: darwin + - resolution: + archive: tarball + bin: + node: bin/node + integrity: sha256-0TJVfn7iuFrwiwyMNDOOZcZDDyI40B9ydyjvQtyDsDU= + type: binary + url: https://nodejs.org/download/release/v24.22.1/node-v24.22.1-darwin-x64.tar.gz + targets: + - cpu: x64 + os: darwin + - resolution: + archive: tarball + bin: + node: bin/node + integrity: sha256-M8N74jS6i+4EGWEEexkWD019DxZOjiRveL3RD+/xSLM= + type: binary + url: https://nodejs.org/download/release/v24.22.1/node-v24.22.1-linux-arm64.tar.gz + targets: + - cpu: arm64 + os: linux + - resolution: + archive: tarball + bin: + node: bin/node + integrity: sha256-nOVyhEUBaynkmtCY96M2Bhql93DRd9knJ4vCb9Ym5kM= + type: binary + url: https://nodejs.org/download/release/v24.22.1/node-v24.22.1-linux-ppc64le.tar.gz + targets: + - cpu: ppc64le + os: linux + - resolution: + archive: tarball + bin: + node: bin/node + integrity: sha256-cZea6xw4W8jugxANODo7HsClIC4D35+ZanBAMwnK/7U= + type: binary + url: https://nodejs.org/download/release/v24.22.1/node-v24.22.1-linux-s390x.tar.gz + targets: + - cpu: s390x + os: linux + - resolution: + archive: tarball + bin: + node: bin/node + integrity: sha256-myUNKdariuON0jAZ4sBKbWspFqsdrXIcX24dorKQHGo= + type: binary + url: https://nodejs.org/download/release/v24.22.1/node-v24.22.1-linux-x64-musl.tar.gz + targets: + - cpu: x64 + os: linux + libc: musl + - resolution: + archive: tarball + bin: + node: bin/node + integrity: sha256-62co53xXajUWLBIsRcyt8iTYn/AKvI2uRswol8YALXw= + type: binary + url: https://nodejs.org/download/release/v24.22.1/node-v24.22.1-linux-x64.tar.gz + targets: + - cpu: x64 + os: linux + - resolution: + archive: zip + bin: + node: node.exe + integrity: sha256-oMgHMZ/t4kxKDY+EVkyCphm9MTsWsQwAfDg8JgnpkXE= + prefix: node-v24.22.1-win-arm64 + type: binary + url: https://nodejs.org/download/release/v24.22.1/node-v24.22.1-win-arm64.zip + targets: + - cpu: arm64 + os: win32 + - resolution: + archive: zip + bin: + node: node.exe + integrity: sha256-0gRtKMLD3NIRrFFFwL8w4gR++d+zBmk8jG4uzNi5X6U= + prefix: node-v24.22.1-win-x64 + type: binary + url: https://nodejs.org/download/release/v24.22.1/node-v24.22.1-win-x64.zip + targets: + - cpu: x64 + os: win32 + - resolution: + archive: tarball + bin: + node: bin/node + integrity: sha256-glQSWCWj5eg0vYomDatMgwP3IEZKdBUG7CeYm5uhdps= + type: binary + url: https://unofficial-builds.nodejs.org/download/release/v24.22.1/node-v24.22.1-linux-arm64-musl.tar.gz + targets: + - cpu: arm64 + os: linux + libc: musl + - resolution: + archive: tarball + bin: + node: bin/node + integrity: sha256-Cp7dzi0ujzrdvpT6RtdRMlstdPf9HOYylhZNNrbfxuU= + type: binary + url: https://unofficial-builds.nodejs.org/download/release/v24.22.1/node-v24.22.1-linux-x64-musl.tar.gz + targets: + - cpu: x64 + os: linux + libc: musl + version: 24.22.1 + hasBin: true + non-error@0.1.0: resolution: {integrity: sha512-TMB1uHiGsHRGv1uYclfhivcnf0/PdFp2pNqRxXjncaAsjYMoisaQJI+SSZCqRq+VliwRTC8tsMQfmrWjDMhkPQ==} engines: {node: '>=20'} @@ -18429,6 +18564,8 @@ snapshots: dependencies: asn1: 0.2.6 + node@runtime:24.22.1: {} + non-error@0.1.0: {} normalize-path@3.0.0: {} diff --git a/scripts/local-doctor.mjs b/scripts/local-doctor.mjs index 8552541f..130e401b 100644 --- a/scripts/local-doctor.mjs +++ b/scripts/local-doctor.mjs @@ -8,7 +8,7 @@ const REQUIREMENTS = [ ]; export function inspectLocalRequirements({ nodeVersion = process.versions.node, run = spawnSync } = {}) { - const checks = [{ name: "Node.js 24", ok: nodeVersion.split(".")[0] === "24", fix: "Install and select Node.js 24." }]; + const checks = [{ name: "Node.js 24", ok: nodeVersion.split(".")[0] === "24", fix: "Run it as pnpm local:doctor; pnpm installs and uses the project's Node.js 24." }]; for (const [command, args, name, fix, accepts] of REQUIREMENTS) { const result = run(command, args, { encoding: "utf8", timeout: 5000, stdio: "pipe" }); checks.push({ name, ok: !result.error && result.status === 0 && (!accepts || accepts(result.stdout)), fix }); @@ -30,7 +30,7 @@ if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) for (const check of checks) console.log(`${check.ok ? "OK" : "NEEDS ACTION"} · ${check.name}${check.ok ? "" : ` — ${check.fix}`}`); console.log("Local storage is bundled and managed by BeatGEO. No separate database installation is needed."); - console.log("Chrome: install it on this computer, then load the bundled BeatBrowser extension in Setup."); + console.log("Chrome: install it, then after pnpm local:setup load .beat-geo/extension at chrome://extensions (Developer mode → Load unpacked)."); console.log("This check does not create a database, install extensions or call paid APIs."); process.exitCode = checks.every((check) => check.ok) ? 0 : 1; } diff --git a/scripts/setup-local.mjs b/scripts/setup-local.mjs index 4f08ca3b..902bb96f 100644 --- a/scripts/setup-local.mjs +++ b/scripts/setup-local.mjs @@ -17,7 +17,7 @@ let database; try { if (process.argv.slice(2).some((arg) => arg !== "--resume")) throw new Error("Use pnpm local:setup or pnpm local:setup --resume. Local storage is bundled; no database option is needed."); - if (Number(process.versions.node.split(".")[0]) !== 24) throw new Error("Use Node.js 24 and pnpm 12.4.1."); + if (Number(process.versions.node.split(".")[0]) !== 24) throw new Error("Run it as pnpm local:setup; pnpm installs and uses the project's Node.js 24."); const local = path.join(root, ".beat-geo"); const resume = process.argv.includes("--resume"); const configured = existsSync(path.join(root, ".env")) || existsSync(path.join(root, "apps/web/.env")); From 411ce3a35e15c69838d2a874cb04c0f824fb6037 Mon Sep 17 00:00:00 2001 From: KKKK Date: Fri, 23 Oct 2026 19:42:24 +0800 Subject: [PATCH 2/3] Stop local services in order on Ctrl+C A terminal's Ctrl+C reached the bundled PostgreSQL, and embedded-postgres also stops it on any SIGINT, so the worker lost its connections mid-shutdown and pnpm reported exit 130. The launcher now runs in its own process group and is asked to stop over IPC; the web app and worker run as single direct processes so the database waits for them. Closing the terminal stops them the same way. --- scripts/start-local.mjs | 37 ++++++++++++++++++++++++++++++++----- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/scripts/start-local.mjs b/scripts/start-local.mjs index 56788a75..c807432f 100644 --- a/scripts/start-local.mjs +++ b/scripts/start-local.mjs @@ -8,6 +8,27 @@ import { startEmbeddedDatabase } from "./local-database.mjs"; import { prepareExtension, requireBundledStorage } from "./local-runtime.mjs"; import { assertCompatibleBridge } from "../apps/browser-lab/core.mjs"; +// Ctrl+C must stop the services in order: web and worker first, the database last. A terminal +// signals its whole foreground process group, and the embedded-postgres library also stops the +// database on any SIGINT/SIGTERM it sees, so the worker lost its connections mid-shutdown. The +// launcher and its database therefore run in their own process group, and this outer process +// asks them to stop over IPC, which those signal hooks ignore. +if (process.platform !== "win32" && !process.env.BEATGEO_LAUNCHER) { + const launcher = spawn(process.execPath, [fileURLToPath(import.meta.url), ...process.argv.slice(2)], { + stdio: ["inherit", "inherit", "inherit", "ipc"], + detached: true, + env: { ...process.env, BEATGEO_LAUNCHER: "1" }, + }); + const forward = () => { + if (launcher.connected) launcher.send("stop"); + }; + process.on("SIGINT", forward); + process.on("SIGTERM", forward); + launcher.on("error", () => process.exit(1)); + launcher.on("exit", (code, signalName) => process.exit(code ?? (signalName ? 1 : 0))); + await new Promise(() => {}); +} + const root = fileURLToPath(new URL("../", import.meta.url)); const envPath = process.argv[2] || path.join(root, ".env"); if (!existsSync(envPath)) throw new Error("Run pnpm local:setup first, or supply your BeatGEO environment file."); @@ -41,13 +62,16 @@ async function stop(code = 0) { try { await database?.stop(); } catch { console.error("Local storage did not stop cleanly. Restart BeatGEO before backing up."); code = 1; } process.exit(code); } -function start(command, args) { - const child = spawn(command, args, { cwd: root, stdio: "inherit", env: process.env, detached: process.platform !== "win32" }); +function start(command, args, cwd = root) { + const child = spawn(command, args, { cwd, stdio: "inherit", env: process.env, detached: process.platform !== "win32" }); children.push(child); child.on("error", () => { console.error("A local service could not start."); void stop(1); }); child.on("exit", (code) => { if (!stopping) void stop(code || 1); }); } process.on("SIGINT", () => { void stop(); }); +process.on("message", (message) => { if (message === "stop") void stop(); }); +// The outer process is gone (its terminal closed): stop in order rather than keep running unseen. +process.on("disconnect", () => { void stop(); }); process.on("SIGTERM", () => { void stop(); }); try { await prepareExtension(root); @@ -67,10 +91,13 @@ try { cwd: root, timeout: 15000, stdio: "pipe", }); } catch (error) { - console.log(error.message?.startsWith("[BROWSER_VERSION_MISMATCH]") ? error.message : "Chrome is not connected yet. Complete the extension step in Setup."); + console.log(error.message?.startsWith("[BROWSER_VERSION_MISMATCH]") ? error.message : "Chrome is not connected yet. Load .beat-geo/extension at chrome://extensions, then sign in to ChatGPT in that Chrome profile."); } - start("pnpm", ["--filter", "@workspace/web", "exec", "vite", "--host", "127.0.0.1", "--port", app.port || "3140", "--strictPort"]); - start("pnpm", ["--filter", "@workspace/worker", "start"]); + // Started directly rather than through `pnpm --filter … exec`, which reports a stopped child as a failure. + start(process.execPath, ["node_modules/vite/bin/vite.js", "--host", "127.0.0.1", "--port", app.port || "3140", "--strictPort"], path.join(root, "apps/web")); + // One process (tsx loaded in place, not its CLI wrapper), so stop() waits for the worker's + // own graceful shutdown before stopping the database. + start(process.execPath, ["--import", "tsx", "src/index.ts"], path.join(root, "apps/worker")); console.log(`BeatGEO workspace: ${app.origin}/\nKeep this terminal running for scheduled monitoring. Ctrl+C stops these services and saves local data.`); } catch (error) { console.error(error instanceof Error ? error.message : "BeatGEO could not start."); From 52d99168f728b1843dfc09a72a97c24b57c71097 Mon Sep 17 00:00:00 2001 From: KKKK Date: Fri, 23 Oct 2026 19:42:24 +0800 Subject: [PATCH 3/3] Guide first-run users through Chrome before adding a website The quick start connects Chrome first, explains the extension's debugger and all-sites permissions, and says what to do when another BeatBrowser version is already running. A non-browser request to the workspace now says the app is running instead of reading like an error. --- .changeset/first-run-polish.md | 5 +++++ README.de.md | 10 +++++----- README.ja.md | 10 +++++----- README.ko.md | 10 +++++----- README.md | 10 +++++----- README.zh-CN.md | 10 +++++----- apps/web/src/lib/auth/local-request.ts | 2 +- 7 files changed, 31 insertions(+), 26 deletions(-) create mode 100644 .changeset/first-run-polish.md diff --git a/.changeset/first-run-polish.md b/.changeset/first-run-polish.md new file mode 100644 index 00000000..53f78858 --- /dev/null +++ b/.changeset/first-run-polish.md @@ -0,0 +1,5 @@ +--- +"@workspace/web": patch +--- + +pnpm now installs and uses Node.js 24 for the local edition, stopping it no longer prints a failure, and the first-run guidance connects Chrome before adding a website. diff --git a/README.de.md b/README.de.md index ecf1d75b..8ff62e4d 100644 --- a/README.de.md +++ b/README.de.md @@ -27,23 +27,23 @@ Gib deine Website und dein Geschäftsfeld an, bestätige die vorgeschlagenen Fra ## Schnellstart -Benötigt werden **Git, Node.js 24, pnpm 12.4.1 und Chrome**. BeatGEO bringt PostgreSQL mit und verwaltet es automatisch. Docker und eine separate Datenbankinstallation sind nicht erforderlich. +Benötigt werden **Git, pnpm 12.4.1 und Chrome**. pnpm installiert und nutzt für dieses Projekt Node.js 24, unabhängig von der Node.js-Version des Systems. BeatGEO bringt PostgreSQL mit und verwaltet es automatisch. Docker und eine separate Datenbankinstallation sind nicht erforderlich. ```sh git clone https://github.com/BeatAPI/BeatGEO.git cd BeatGEO -node scripts/local-doctor.mjs +pnpm local:doctor pnpm local:setup pnpm local:start ``` Öffne **http://localhost:3140/** direkt im lokalen Arbeitsbereich. Für BeatGEO sind weder Registrierung noch Anmeldung oder Passwort nötig. BeatAPI und Chrome lassen sich unter `/setup` verbinden: -1. **Marke anlegen.** Website eingeben → Fragen erzeugen und bestätigen → erste Erfassung → Antworten und Quellen prüfen → Verbesserung speichern → dieselben Fragen erneut testen. -2. **Chrome verbinden.** Unter `chrome://extensions` den Entwicklermodus aktivieren und `.beat-geo/extension` entpackt laden. Verbundenes Profil auswählen und dort bei ChatGPT anmelden. Eine verbundene Erweiterung bestätigt keine Website-Anmeldung. +1. **Chrome verbinden.** Unter `chrome://extensions` den Entwicklermodus aktivieren und `.beat-geo/extension` entpackt laden. Verbundenes Profil auswählen und dort bei ChatGPT anmelden. Eine verbundene Erweiterung bestätigt keine Website-Anmeldung. Die Erweiterung verlangt Debugger-Zugriff und Zugriff auf alle Websites, weil sie Seiten in deinem angemeldeten Chrome für dich bedient. Prüfe diese Berechtigungen vor dem Laden. +2. **Marke anlegen.** Website eingeben → Fragen erzeugen und bestätigen → erste Erfassung → Antworten und Quellen prüfen → Verbesserung speichern → dieselben Fragen erneut testen. 3. **Recherche verbinden.** BeatAPI-Key unter Connections prüfen, Recherchemodell auswählen und speichern. Alternativ diesen Schritt überspringen und Branchenvorlagen nutzen. -Das Setup richtet eine eigene lokale PostgreSQL-Datenbank und die Erweiterung ein. Kein zweiter Repository-Klon, kein zusätzliches BeatBrowser-Konto und keine globale CLI-Installation nötig. Eine vorhandene BeatBrowser-Verbindung kann verwendet werden; pro Chrome-Profil nur eine Erweiterungskopie aktivieren. +Das Setup richtet eine eigene lokale PostgreSQL-Datenbank und die Erweiterung ein. Kein zweiter Repository-Klon, kein zusätzliches BeatBrowser-Konto und keine globale CLI-Installation nötig. Eine vorhandene BeatBrowser-Verbindung kann verwendet werden; pro Chrome-Profil nur eine Erweiterungskopie aktivieren. Meldet `pnpm local:start` eine bereits laufende andere BeatBrowser-Version, verweise in `.env` mit `BEAT_BROWSER_COMMAND` und `BEAT_BROWSER_ARGS_JSON` auf diese Installation oder aktualisiere sie zusammen mit ihrer Erweiterung. **Für laufendes Monitoring muss die Umgebung laufen:** Computer wach und online halten; Chrome und `pnpm local:start` müssen aktiv bleiben. Der Dashboard-Tab darf geschlossen werden. Zum Neustart reicht `pnpm local:start`; die Datenbank nicht neu anlegen. Bei ausgeschaltetem oder offline befindlichem Computer findet keine Erfassung statt. diff --git a/README.ja.md b/README.ja.md index da8bf016..b12ecd9d 100644 --- a/README.ja.md +++ b/README.ja.md @@ -27,23 +27,23 @@ ## クイックスタート -**Git、Node.js 24、pnpm 12.4.1、Chrome** を用意してください。PostgreSQL は BeatGEO に同梱され、自動管理されます。Docker やデータベースの別途インストールは不要です。 +**Git、pnpm 12.4.1、Chrome** を用意してください。このプロジェクトでは pnpm が Node.js 24 を自動でインストールして使うため、システムの Node.js バージョンは問いません。PostgreSQL は BeatGEO に同梱され、自動管理されます。Docker やデータベースの別途インストールは不要です。 ```sh git clone https://github.com/BeatAPI/BeatGEO.git cd BeatGEO -node scripts/local-doctor.mjs +pnpm local:doctor pnpm local:setup pnpm local:start ``` **http://localhost:3140/** を開くと、ローカルワークスペースに直接入れます。BeatGEO の登録・ログイン・パスワード設定は不要です。BeatAPI と Chrome の接続は `/setup` で行えます。 -1. **ブランドを作成。** サイトを入力 → 質問を生成して確認 → 初回収集 → 回答と引用を確認 → 改善を記録 → 同じ質問で再測定します。 -2. **Chrome を接続。** `chrome://extensions` でデベロッパーモードを有効にし、`.beat-geo/extension` を読み込みます。接続したプロファイルを選び、同じプロファイルで ChatGPT にログインしてください。拡張機能の接続とサイトへのログインは別です。 +1. **Chrome を接続。** `chrome://extensions` でデベロッパーモードを有効にし、`.beat-geo/extension` を読み込みます。接続したプロファイルを選び、同じプロファイルで ChatGPT にログインしてください。拡張機能の接続とサイトへのログインは別です。拡張機能は、ログイン済みの Chrome でページを代わりに操作するため、デバッガーとすべてのサイトへのアクセス権限を要求します。読み込む前に権限を確認してください。 +2. **ブランドを作成。** サイトを入力 → 質問を生成して確認 → 初回収集 → 回答と引用を確認 → 改善を記録 → 同じ質問で再測定します。 3. **リサーチを設定。** Connections で BeatAPI キーを検証し、リサーチモデルを選択して保存します。スキップして業種別の初期質問を使うこともできます。 -セットアップが専用のローカル PostgreSQL と拡張機能を準備します。BeatBrowser を別にクローンしたり、別アカウントやグローバル CLI を用意したりする必要はありません。既存の接続も利用できますが、同じ Chrome プロファイルで拡張機能を二重に有効化しないでください。 +セットアップが専用のローカル PostgreSQL と拡張機能を準備します。BeatBrowser を別にクローンしたり、別アカウントやグローバル CLI を用意したりする必要はありません。既存の接続も利用できますが、同じ Chrome プロファイルで拡張機能を二重に有効化しないでください。 `pnpm local:start` が別バージョンの BeatBrowser の稼働を知らせた場合は、`.env` の `BEAT_BROWSER_COMMAND` と `BEAT_BROWSER_ARGS_JSON` でそのインストールを指定するか、拡張機能と一緒に更新してください。 **継続監視には稼働中の環境が必要です。** パソコンをスリープさせず、ネット接続、Chrome、`pnpm local:start` を維持します。ダッシュボードのタブは閉じても構いません。再開時は `pnpm local:start` を実行し、データベースは作り直さないでください。オフライン中の収集はできません。 diff --git a/README.ko.md b/README.ko.md index 42284201..53231e2d 100644 --- a/README.ko.md +++ b/README.ko.md @@ -27,23 +27,23 @@ ## 빠른 시작 -**Git, Node.js 24, pnpm 12.4.1, Chrome**을 준비하세요. PostgreSQL은 BeatGEO에 포함되어 자동으로 관리됩니다. Docker나 별도의 데이터베이스를 설치할 필요가 없습니다. +**Git, pnpm 12.4.1, Chrome**을 준비하세요. 이 프로젝트에서는 pnpm이 Node.js 24를 자동으로 설치해 사용하므로 시스템의 Node.js 버전은 상관없습니다. PostgreSQL은 BeatGEO에 포함되어 자동으로 관리됩니다. Docker나 별도의 데이터베이스를 설치할 필요가 없습니다. ```sh git clone https://github.com/BeatAPI/BeatGEO.git cd BeatGEO -node scripts/local-doctor.mjs +pnpm local:doctor pnpm local:setup pnpm local:start ``` **http://localhost:3140/**을 열면 로컬 작업 공간으로 바로 들어갑니다. BeatGEO 회원가입, 로그인, 비밀번호 설정은 필요하지 않습니다. `/setup`에서 BeatAPI와 Chrome을 연결할 수 있습니다. -1. **브랜드 생성.** 웹사이트 입력 → 질문 생성 및 확인 → 첫 수집 → 답변과 인용 확인 → 개선 항목 저장 → 같은 질문으로 재측정합니다. -2. **Chrome 연결.** `chrome://extensions`에서 개발자 모드를 켜고 `.beat-geo/extension`을 압축 해제된 확장 프로그램으로 로드합니다. 연결된 프로필을 선택하고 같은 프로필에서 ChatGPT에 로그인하세요. 확장 프로그램 연결과 웹사이트 로그인은 별개입니다. +1. **Chrome 연결.** `chrome://extensions`에서 개발자 모드를 켜고 `.beat-geo/extension`을 압축 해제된 확장 프로그램으로 로드합니다. 연결된 프로필을 선택하고 같은 프로필에서 ChatGPT에 로그인하세요. 확장 프로그램 연결과 웹사이트 로그인은 별개입니다. 확장 프로그램은 로그인된 Chrome에서 페이지를 대신 조작하기 때문에 디버거 권한과 모든 사이트 접근 권한을 요청합니다. 로드하기 전에 권한을 확인하세요. +2. **브랜드 생성.** 웹사이트 입력 → 질문 생성 및 확인 → 첫 수집 → 답변과 인용 확인 → 개선 항목 저장 → 같은 질문으로 재측정합니다. 3. **리서치 연결.** Connections에서 BeatAPI 키를 검증하고 리서치 모델을 선택해 저장합니다. 건너뛰고 업종별 기본 질문을 사용해도 됩니다. -설치 과정에서 전용 로컬 PostgreSQL과 확장 프로그램을 준비합니다. 별도의 저장소 복제, BeatBrowser 계정, 전역 CLI 설치는 필요하지 않습니다. 기존 BeatBrowser 연결을 재사용할 수 있지만, Chrome 프로필 하나에는 확장 프로그램 한 개만 활성화하세요. +설치 과정에서 전용 로컬 PostgreSQL과 확장 프로그램을 준비합니다. 별도의 저장소 복제, BeatBrowser 계정, 전역 CLI 설치는 필요하지 않습니다. 기존 BeatBrowser 연결을 재사용할 수 있지만, Chrome 프로필 하나에는 확장 프로그램 한 개만 활성화하세요. `pnpm local:start`가 다른 버전의 BeatBrowser가 이미 실행 중이라고 알리면, `.env`의 `BEAT_BROWSER_COMMAND`와 `BEAT_BROWSER_ARGS_JSON`으로 그 설치를 지정하거나 확장 프로그램과 함께 업데이트하세요. **지속적인 모니터링에는 실행 중인 환경이 필요합니다.** 컴퓨터가 절전 모드에 들어가지 않도록 하고 인터넷 연결, Chrome, `pnpm local:start`를 유지하세요. 대시보드 탭은 닫아도 됩니다. 다음에는 `pnpm local:start`로 다시 시작하며, 데이터베이스를 새로 만들지 않습니다. 컴퓨터가 오프라인이면 수집도 중단됩니다. diff --git a/README.md b/README.md index 22d6480b..e1dcebee 100644 --- a/README.md +++ b/README.md @@ -27,23 +27,23 @@ Start with your website and business. Review suggested monitoring questions, col ## Quick start -Prepare **Git, Node.js 24, pnpm 12.4.1, and Chrome**. PostgreSQL is bundled and managed by BeatGEO; no Docker or separate database installation is required. +Prepare **Git, pnpm 12.4.1 and Chrome**. pnpm installs and uses Node.js 24 for this project, whatever Node.js version your system has. PostgreSQL is bundled and managed by BeatGEO; no Docker or separate database installation is required. ```sh git clone https://github.com/BeatAPI/BeatGEO.git cd BeatGEO -node scripts/local-doctor.mjs +pnpm local:doctor pnpm local:setup pnpm local:start ``` Open **http://localhost:3140/** to enter your local workspace directly. There is no BeatGEO registration, login or password. Connections at `/setup` lets you add an optional BeatAPI key and connect Chrome: -1. **Create a brand.** Enter the website, generate and confirm questions, then start the first collection. Read the answers and citations, save an improvement, and compare a retest. -2. **Connect Chrome.** Load `.beat-geo/extension` via `chrome://extensions` → Developer mode → Load unpacked. Select the connected profile and sign in to ChatGPT in that profile. An extension connection does not establish website login. +1. **Connect Chrome.** Load `.beat-geo/extension` via `chrome://extensions` → Developer mode → Load unpacked. Select the connected profile and sign in to ChatGPT in that profile. An extension connection does not establish website login. The extension requests debugger access and access to all sites because it operates pages in your signed-in Chrome on your behalf; review these permissions before loading it. +2. **Create a brand.** Enter the website, generate and confirm questions, then start the first collection. Read the answers and citations, save an improvement, and compare a retest. 3. **Connect research.** In Connections, enter a BeatAPI key, validate it, select a research model and save. You can skip research and use industry starter questions. -The installer prepares a dedicated local PostgreSQL database and the included extension. No second repository clone, BeatBrowser account or global CLI installation is needed. Existing BeatBrowser connections can be reused; enable only one extension copy per profile. +The installer prepares a dedicated local PostgreSQL database and the included extension. No second repository clone, BeatBrowser account or global CLI installation is needed. Existing BeatBrowser connections can be reused; enable only one extension copy per profile. If `pnpm local:start` reports a different BeatBrowser version already running, point BeatGEO at that installation with `BEAT_BROWSER_COMMAND` and `BEAT_BROWSER_ARGS_JSON` in `.env`, or update it and its extension together. **To keep monitoring:** leave the computer awake and online, with Chrome and `pnpm local:start` running. You can close the dashboard tab. Restart with `pnpm local:start`; do not recreate the database. This local edition does not provide monitoring while your computer is offline. diff --git a/README.zh-CN.md b/README.zh-CN.md index 2ca6cabd..83620186 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -27,23 +27,23 @@ ## 快速开始 -准备 **Git、Node.js 24、pnpm 12.4.1 和 Chrome**。BeatGEO 自带并管理独立 PostgreSQL,无需安装 Docker 或数据库。 +准备 **Git、pnpm 12.4.1 和 Chrome**。pnpm 会为本项目自动安装并使用 Node.js 24,与电脑上的 Node.js 版本无关。BeatGEO 自带并管理独立 PostgreSQL,无需安装 Docker 或数据库。 ```sh git clone https://github.com/BeatAPI/BeatGEO.git cd BeatGEO -node scripts/local-doctor.mjs +pnpm local:doctor pnpm local:setup pnpm local:start ``` 打开 **http://localhost:3140/**,直接进入本地工作台,无需注册、登录或设置密码。可在 `/setup` 连接 BeatAPI 和 Chrome: -1. **创建品牌。** 填网站 → 生成并确认问题 → 首次采集 → 查看回答和引用 → 保存优化行动 → 同组复测。 -2. **连接 Chrome。** 在 `chrome://extensions` 开启开发者模式,加载 `.beat-geo/extension`。选择连接的配置,并在同一配置登录 ChatGPT。扩展连接成功不代表网站已经登录。 +1. **连接 Chrome。** 在 `chrome://extensions` 开启开发者模式,加载 `.beat-geo/extension`。选择连接的配置,并在同一配置登录 ChatGPT。扩展连接成功不代表网站已经登录。扩展会申请调试(debugger)和访问所有网站的权限,因为它要在你已登录的 Chrome 中代你操作页面;加载前请先确认这些权限。 +2. **创建品牌。** 填网站 → 生成并确认问题 → 首次采集 → 查看回答和引用 → 保存优化行动 → 同组复测。 3. **连接研究能力。** 在 Connections 填入 BeatAPI Key → 验证 → 选择研究模型 → 保存。也可跳过,使用行业模板题库。 -安装脚本会准备独立 PostgreSQL 和内置扩展,不必再克隆 BeatBrowser、注册另一套账号或安装全局 CLI。已有 BeatBrowser 可以复用,同一 Chrome 配置只启用一份扩展。 +安装脚本会准备独立 PostgreSQL 和内置扩展,不必再克隆 BeatBrowser、注册另一套账号或安装全局 CLI。已有 BeatBrowser 可以复用,同一 Chrome 配置只启用一份扩展。如果 `pnpm local:start` 提示本机已在运行其他版本的 BeatBrowser,可在 `.env` 用 `BEAT_BROWSER_COMMAND` 和 `BEAT_BROWSER_ARGS_JSON` 指向那份安装,或把它和扩展一起升级。 **持续监测需要持续运行:** 电脑保持唤醒和联网,Chrome、`pnpm local:start` 保持运行。可以关闭工作台网页;下次执行 `pnpm local:start` 即可,不要重建数据库。本地版不会在电脑离线时继续采集。 diff --git a/apps/web/src/lib/auth/local-request.ts b/apps/web/src/lib/auth/local-request.ts index 28c5908e..72d8111f 100644 --- a/apps/web/src/lib/auth/local-request.ts +++ b/apps/web/src/lib/auth/local-request.ts @@ -90,7 +90,7 @@ export async function handleLocalWorkspaceRequest(request: Request, options: Loc if (isUntrustedWrite(request)) return refusal("Local writes require a same-origin browser request."); if (request.headers.has("cookie") && (await options.getSession(request.headers))) return options.next(request); if (!isBrowserNavigation(request) || pathname.startsWith("/api/") || pathname.startsWith("/_server")) - return refusal("Open the local workspace in your browser to continue.", 401); + return refusal("BeatGEO is running. Open this address in your browser to use the workspace.", 401); const bootstrap = await options.bootstrap(request.headers); if (!bootstrap.ok) return refusal("The local workspace could not be opened. Check its database and configuration.", 503);