Archilyzer · Source

archilyzer

Archilyzer
git clone https://archilyzer.pages.dev/source/archilyzer.git
Log | Files | Refs | README | LICENSE

commit 603fefc1d99d97123ac64972332031431a906a52
parent dc5cfc080f44b3e1738024fa0842ef01af19ce33
Author: I Mean I'm Just Saying <imeanimjustsaying@kiwifarms.st>
Date:   Thu,  2 Jul 2026 00:56:18 -0400

Add "Skip data rebuild" option to Build static export

Let the editor trigger a build that composes from existing .export-index
staging without regenerating the pool-wide data (index/stats/charts).

A new build:nodata export script has the same body as build (compose:site
&& next build) but a distinct name, so npm's prebuild lifecycle hook (which
runs build:data) doesn't fire. runBuildPhase gains a skipData option that
routes to it, threaded from a new checkbox on BuildExportButton through
buildExportAction. Build & deploy is unchanged (always a full build).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Diffstat:
Meditor/CHANGELOG.md | 1+
Meditor/app/build/buildAction.ts | 5++++-
Meditor/app/deploy/buildDeployCore.ts | 15++++++++++++++-
Meditor/app/deploy/components/BuildExportButton.tsx | 15++++++++++++++-
Meditor/e2e/build.spec.ts | 6++++++
Mexport/package.json | 1+
6 files changed, 40 insertions(+), 3 deletions(-)

diff --git a/editor/CHANGELOG.md b/editor/CHANGELOG.md @@ -1,6 +1,7 @@ # Changelog ## [Unreleased] +- **"Build static export" can now skip the data rebuild and compose from existing staging.** The `export/` build normally regenerates the pool-wide data first (its npm `prebuild` hook runs `build:data` = `build:index && build:stats && build:templates`), and the index step (heavy transcript → page-tree + LMDB processing) dominates build time. A new **Skip data rebuild (index, stats, charts)** checkbox on the Build static export control lets you rebuild a site *without* that work — it runs only `compose:site && next build` against the current `.export-index/` staging, which is exactly what you want when re-composing after a code/theme/template change or building a different site from already-staged data. It routes to a new `build:nodata` export script (same body as `build`, but a distinct name so npm's `prebuild` hook doesn't fire); the checkbox reuses the streamed-log/queue/cancel machinery of the existing managed build. Assumes a prior full build produced the staging (do a full build first if the data is stale). Only the build-only control is affected — the one-click **Build & deploy** button always does a full build. See `export/package.json` (`build:nodata`), `editor/app/deploy/buildDeployCore.ts` (`runBuildPhase` `skipData`), `editor/app/build/buildAction.ts` (`buildExportAction`), and `editor/app/deploy/components/BuildExportButton.tsx`. - **The neutral Base theme is now all-sans.** The default Base family previously inherited the shared Source **Serif** display face for the wordmark and page headings; it now uses the sans face instead, matching the pre-theme all-sans look. This is a shared token change (`html:not([data-theme])` in `common/styles/tokens.css`), so any surface on the Base family — including the editor's default — reads sans; the Archive/Selenized/Swiss families keep their own type voices. - **A dedicated Cleanup page with a live "reclaimable" sidebar badge and per-channel include/exclude.** Space-reclaim cleaning now has its own home (`/cleanup`, in the Pool nav) instead of being scattered across each channel's detail page. It opens with a serif **reclamation console** readout — the total reclaimable audio across channels, a token-colored breakdown bar (transcribed audio / extra formats / wrong-format), and a per-channel ledger that runs the same `cleanAudioAction` / `cleanExtraAudioFormatsAction` / `removeWrongFormatAudioAction` sweeps (plus failed-list housekeeping) the channel page does — the per-channel `CleanupStage` stays put. The sidebar **Cleanup** item carries an amber badge with the running reclaimable total (e.g. `12.4 GB`), recomputed on each auto-refresh tick. A per-channel **Counted / Excluded** toggle (new `ChannelConfig.excludeFromCleanup`, persisted in `config.json` like `excludeFromBuild`/`excludeFromSync`) holds a channel's space back from the total without disabling its sweeps — e.g. keep a finicky-to-redownload channel's audio around for now. The headline total uses the primary "clean audio" reclaim only (the three sweeps overlap, so they aren't summed). See `editor/app/cleanup/{page.tsx,lib/loadCleanup.ts,components/{ChannelCleanupCard,ChannelCleanupToggle}.tsx}`, `editor/app/channels/actions.ts` (`toggleChannelCleanupInclusionAction`), `editor/app/{lib/nav.ts,layout.tsx}`, and `common/lib/channelConfig.ts`. - **Badges and alerts are now colorful and theme-aware in every theme.** The design system only tokenized red (`--destructive`); every green/amber/blue status was hardcoded Tailwind palette that ignored the four theme families. New semantic tokens — **`--success` / `--warning` / `--info`** (each with `-foreground` + a soft fill partner) plus `--destructive-soft` — are defined across all eight family blocks (base/archive/terminal/swiss × light/dark) and registered in `@theme inline`. The shared kit `Badge` gains `success` / `warning` / `info` / `brand` soft-filled variants, and a **new `Alert` component** (`common/components/ui/alert.tsx`) replaces ad-hoc notice divs. High-traffic status UI is migrated onto the tokens: channel stage badges (`StageBadge`), worker state badges + dots (`WorkersView`, `MonitorWidget`), the scheduler status column (`SchedulerView`), and the widget disk strip — so each recolors correctly in Archive, Terminal, and Swiss, light and dark. See `common/styles/tokens.css`, `common/components/ui/{badge,alert}.tsx`. diff --git a/editor/app/build/buildAction.ts b/editor/app/build/buildAction.ts @@ -63,6 +63,7 @@ export async function buildStatsAction( export async function buildExportAction( siteId: string, queueKey?: string, + skipData?: boolean, ): Promise<StreamActionResult> { const paths = getPaths(); const id = siteId.trim(); @@ -73,12 +74,14 @@ export async function buildExportAction( // persisted build mode (basic vs docker) via runBuildPhase, and so the same // child-streaming path is shared with build-then-deploy. Cancel still works: // the abort signal is forwarded to the child by runChildIntoLog. + // `skipData` composes from the existing .export-index staging without + // regenerating the pool-wide index/stats/charts. return runManagedFunction({ kind: "build-export", queueKey: queueKey === undefined ? DEFAULT_BUILD_QUEUE : queueKey.trim(), paths, fn: async (onLog, signal) => { - const code = await runBuildPhase(onLog, signal, id, paths); + const code = await runBuildPhase(onLog, signal, id, paths, { skipData }); if (signal.aborted) return; if (code !== 0) throw new Error(`Build failed (exit ${code})`); }, diff --git a/editor/app/deploy/buildDeployCore.ts b/editor/app/deploy/buildDeployCore.ts @@ -30,6 +30,7 @@ export async function runBuildPhase( signal: AbortSignal, siteId: string, paths: Paths, + opts?: { skipData?: boolean }, ): Promise<number> { const { mode } = getSettings().buildPipeline; if (mode === "docker") { @@ -38,9 +39,21 @@ export async function runBuildPhase( "for now. Parallel container builds arrive in a follow-up.\n", ); } + // When skipping the data rebuild, run the `build:nodata` script instead of + // `build`. `build:nodata` has the same body (compose:site + next build) but a + // different name, so npm's `prebuild` lifecycle hook (which runs build:data = + // index/stats/templates) does NOT fire — we compose from the existing + // .export-index staging. Assumes a prior full build produced that staging. + const skipData = opts?.skipData === true; + if (skipData) { + onLog( + "[notice] Skipping data rebuild (index/stats/charts) — composing from " + + "existing .export-index staging.\n", + ); + } return runChildIntoLog(onLog, signal, { command: "pnpm", - args: ["run", "build"], + args: ["run", skipData ? "build:nodata" : "build"], cwd: paths.exportDir, env: { ...process.env, diff --git a/editor/app/deploy/components/BuildExportButton.tsx b/editor/app/deploy/components/BuildExportButton.tsx @@ -17,10 +17,11 @@ const DEFAULT_BUILD_QUEUE = "build"; export function BuildExportButton({ existingQueues, siteId, siteTitle }: Props) { const [exportQueue, setExportQueue] = useState(DEFAULT_BUILD_QUEUE); + const [skipData, setSkipData] = useState(false); return ( <StreamActionLog - trigger={() => buildExportAction(siteId as string, exportQueue)} + trigger={() => buildExportAction(siteId as string, exportQueue, skipData)} cancelAction={cancelJobAction} buttonLabel="Build static export" runningLabel="Building static export…" @@ -37,6 +38,18 @@ export function BuildExportButton({ existingQueues, siteId, siteTitle }: Props) Select a specific site from the sidebar to build. </p> )} + <label className="flex items-center gap-2 text-sm"> + <input + type="checkbox" + checked={skipData} + onChange={(e) => setSkipData(e.target.checked)} + /> + Skip data rebuild (index, stats, charts) + </label> + <p className="text-xs text-muted-foreground"> + Reuses the existing index/stats — only composes the site and runs + next build. Do a full build first if data is stale. + </p> <QueueControl value={exportQueue} onChange={setExportQueue} diff --git a/editor/e2e/build.spec.ts b/editor/e2e/build.spec.ts @@ -94,4 +94,10 @@ test("build static export lives on the deploy page, not the build page", async ( name: "Build static export", }); await expect(exportButton).toBeEnabled(); + + // The build-only control offers a "skip data rebuild" option (compose from + // existing staging without regenerating index/stats/charts). Default off. + const skipData = page.getByLabel("Skip data rebuild (index, stats, charts)"); + await expect(skipData).toBeVisible(); + await expect(skipData).not.toBeChecked(); }); diff --git a/export/package.json b/export/package.json @@ -13,6 +13,7 @@ "compose:site": "tsx ../common/bin/compose-site.ts", "prebuild": "pnpm run build:data", "build": "pnpm run compose:site && next build", + "build:nodata": "pnpm run compose:site && next build", "start": "serve out", "lint": "eslint", "e2e": "playwright test",