mirror of
https://github.com/hanzo-apps/hanzo.ai.git
synced 2026-10-28 07:32:52 +00:00
Prose that carried no decision or fact is gone: the hero, the questions, the gate and every step are a heading and at most a line. What scores is said once (the leaderboard step), and every claim the cloud does not keep is out. Step 1 is one share card (the member's link, Copy, the device's share sheet on phones, seven channels as icons, Customize behind a text button) and a quiet invite-by-email card. Step 3 is one searched, grouped list with one control a row: On when `opens` says so, Get access when it does not, Requested at once after the press. Stars and follows moved under the leaderboard as Earn more. The 1,800-line dashboard is a shell over share, rank, betas and alpha; what they read is one hook (standing.ts); the questions are data (program.ts). Dead access, card, hint and referral components are deleted. Every press is 44px, every input too, and a gate walks each screen at 390px. scripts/brands and scripts/prebuild are TypeScript now; the three marks the share row draws ship in a JSON only /beta loads. /beta's title and card say what the page says. Claude-Session: https://claude.ai/code/session_017vrVus6PPBgP5YRzKV1iqW
54 lines
1.7 KiB
JavaScript
54 lines
1.7 KiB
JavaScript
#!/usr/bin/env node
|
|
// What `next build` reads, regenerated before it runs.
|
|
//
|
|
// The first group each write files of their own and read none the others
|
|
// write, so they run at once: one after another they were 23 s of every
|
|
// deploy, most of it waiting on the network. The last three read what the
|
|
// first group wrote (the route tree's policy joins the catalog, and
|
|
// keep-stamps compares every snapshot), so they run after it, in order.
|
|
//
|
|
// Every script runs to its end before the build is refused, so one failure
|
|
// does not hide another.
|
|
import { spawn } from 'node:child_process'
|
|
import { existsSync } from 'node:fs'
|
|
|
|
const AT_ONCE = [
|
|
'gen-gui-css',
|
|
'rooms-assets',
|
|
'sync-mark',
|
|
'brands',
|
|
'zen',
|
|
'kai',
|
|
'coding',
|
|
'tools',
|
|
'sync-catalog',
|
|
'sync-models',
|
|
'sync-papers',
|
|
'sync-blog',
|
|
'sync-oss',
|
|
'sync-releases',
|
|
'sync-menu',
|
|
]
|
|
const AFTER = ['sync-rooms', 'sync-pages', 'keep-stamps']
|
|
|
|
// A script is TypeScript (`.ts`, run by Node's own type stripping) or a `.mjs` not yet converted.
|
|
const run = (name: string) =>
|
|
new Promise<string | null>((done) => {
|
|
spawn(process.execPath, [existsSync(`scripts/${name}.ts`) ? `scripts/${name}.ts` : `scripts/${name}.mjs`], { stdio: 'inherit' })
|
|
.on('error', (err) => done(`${name}: ${err.message}`))
|
|
.on('exit', (code, signal) => done(code === 0 ? null : `${name} exited ${signal ?? code}`))
|
|
})
|
|
|
|
const failed = (await Promise.all(AT_ONCE.map(run))).filter(Boolean)
|
|
if (failed.length) {
|
|
for (const f of failed) console.error(`prebuild: ${f}`)
|
|
process.exit(1)
|
|
}
|
|
for (const name of AFTER) {
|
|
const f = await run(name)
|
|
if (f) {
|
|
console.error(`prebuild: ${f}`)
|
|
process.exit(1)
|
|
}
|
|
}
|