create-apollo-monorepo 0.8.0 → 0.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.mjs +294 -6
- package/package.json +1 -1
package/index.mjs
CHANGED
|
@@ -367,8 +367,31 @@ function writeRootPackageJson(targetDir, dirName) {
|
|
|
367
367
|
"pnpm predev:setup && pnpm --filter ./apps/backend exec next dev",
|
|
368
368
|
"dev:cron": "pnpm --filter ./apps/backend exec bun scripts/dev-cron.ts",
|
|
369
369
|
// Build pipeline: cms-plugins → apollo-cms's own plugins → backend → frontend.
|
|
370
|
+
// `prebuild` runs first (npm/pnpm convention) and fails fast if the
|
|
371
|
+
// backend's required env vars are missing.
|
|
372
|
+
prebuild: "node scripts/check-env.mjs",
|
|
370
373
|
build:
|
|
371
374
|
"pnpm cms-plugins:build && pnpm --filter ./apps/backend exec bun run plugins:build && pnpm --filter ./apps/backend build && pnpm --filter ./apps/frontend build",
|
|
375
|
+
"build:backend":
|
|
376
|
+
"pnpm cms-plugins:build && pnpm --filter ./apps/backend exec bun run plugins:build && pnpm --filter ./apps/backend build",
|
|
377
|
+
"build:frontend": "pnpm --filter ./apps/frontend build",
|
|
378
|
+
// Production start. Runs FE :3001 + BE :3000 in parallel via
|
|
379
|
+
// \`next start\`. Run \`pnpm backend:upgrade\` BEFORE this — start does
|
|
380
|
+
// NOT run migrations on boot (zero-downtime restart safety).
|
|
381
|
+
start:
|
|
382
|
+
"concurrently -k -n FE,BE -c blue,magenta \"pnpm --filter ./apps/frontend start\" \"pnpm --filter ./apps/backend exec next start\"",
|
|
383
|
+
// Single-origin production: FE + BE + Node reverse proxy on :3030.
|
|
384
|
+
"start:rp":
|
|
385
|
+
"concurrently -k -n FE,BE,PX -c blue,magenta,cyan \"pnpm --filter ./apps/frontend start\" \"pnpm --filter ./apps/backend exec next start\" \"pnpm start:proxy\"",
|
|
386
|
+
"start:proxy": "NODE_ENV=production node apps/proxy/server.mjs",
|
|
387
|
+
"start:frontend": "pnpm --filter ./apps/frontend start",
|
|
388
|
+
"start:backend": "pnpm --filter ./apps/backend exec next start",
|
|
389
|
+
// Self-hosted scheduler fallback. Vercel deploys use Vercel Cron via
|
|
390
|
+
// apps/backend/vercel.json — skip this on Vercel. For Docker / VPS
|
|
391
|
+
// you can either run \`pnpm start:cron\` alongside \`pnpm start\` (PM2
|
|
392
|
+
// handles this via ecosystem.config.cjs), or use system cron / k8s
|
|
393
|
+
// CronJob to hit /api/cron with CRON_SECRET.
|
|
394
|
+
"start:cron": "pnpm --filter ./apps/backend exec bun scripts/dev-cron.ts",
|
|
372
395
|
"cms-plugins:build":
|
|
373
396
|
"pnpm --filter './apps/cms-plugins/*' --parallel --if-present build",
|
|
374
397
|
"cms-plugins:dev":
|
|
@@ -376,7 +399,13 @@ function writeRootPackageJson(targetDir, dirName) {
|
|
|
376
399
|
"cms-plugin:new": "node scripts/new-cms-plugin.mjs",
|
|
377
400
|
lint: "pnpm -r lint",
|
|
378
401
|
typecheck: "pnpm -r typecheck",
|
|
379
|
-
|
|
402
|
+
// Stash any local changes inside the submodule so the fast-forward
|
|
403
|
+
// merge can't conflict, then update, then run `pnpm install` at the
|
|
404
|
+
// root so workspace deps pick up any package.json changes pulled in
|
|
405
|
+
// from the new apollo-cms commit. The stash is restored if it was
|
|
406
|
+
// created; otherwise this is a no-op.
|
|
407
|
+
"backend:update":
|
|
408
|
+
"node -e \"const {execSync:e}=require('child_process');const r=s=>e(s,{stdio:'inherit'});const has=e('git -C apps/backend status --porcelain',{encoding:'utf8'}).trim().length>0;if(has)r('git -C apps/backend stash push -u -m backend-update-auto');r('git submodule update --remote --merge apps/backend');r('pnpm install');if(has){try{r('git -C apps/backend stash pop');}catch(_){console.error('[backend:update] stash pop had conflicts — resolve manually with: git -C apps/backend stash list');}}\"",
|
|
380
409
|
// `pnpm setup` is pnpm's CLI bootstrap built-in — must use `run` to
|
|
381
410
|
// forward to the workspace's setup script (apollo-cms's db:push + db:seed).
|
|
382
411
|
"backend:setup": "pnpm --filter ./apps/backend run setup",
|
|
@@ -1244,6 +1273,216 @@ console.log(\`Run: pnpm install && pnpm cms-plugins:build && pnpm dev:backend\`)
|
|
|
1244
1273
|
writeFileSync(resolve(scriptsDir, "new-cms-plugin.mjs"), script);
|
|
1245
1274
|
}
|
|
1246
1275
|
|
|
1276
|
+
// Pre-build env check. Fails the build before \`next build\` runs if backend
|
|
1277
|
+
// required vars are missing, so users don't sit through a 30s build only to
|
|
1278
|
+
// hit a runtime error on first request.
|
|
1279
|
+
function writeCheckEnvScript(targetDir) {
|
|
1280
|
+
const scriptsDir = resolve(targetDir, "scripts");
|
|
1281
|
+
mkdirSync(scriptsDir, { recursive: true });
|
|
1282
|
+
const script = `#!/usr/bin/env node
|
|
1283
|
+
// Pre-build sanity check. Reads apps/backend/.env.local and verifies that
|
|
1284
|
+
// required vars are present and non-empty. Skipped when SKIP_ENV_CHECK=1.
|
|
1285
|
+
//
|
|
1286
|
+
// In CI/Vercel where envs come from the platform (not files), set
|
|
1287
|
+
// SKIP_ENV_CHECK=1 and rely on the platform's own validation.
|
|
1288
|
+
|
|
1289
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
1290
|
+
import { dirname, resolve } from "node:path";
|
|
1291
|
+
import { fileURLToPath } from "node:url";
|
|
1292
|
+
|
|
1293
|
+
if (process.env.SKIP_ENV_CHECK === "1") process.exit(0);
|
|
1294
|
+
|
|
1295
|
+
const REQUIRED = ["DATABASE_URL", "APOLLO_SECRET", "NEXT_PUBLIC_DEFAULT_LOCALE"];
|
|
1296
|
+
|
|
1297
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
1298
|
+
const envPath = resolve(__dirname, "../apps/backend/.env.local");
|
|
1299
|
+
|
|
1300
|
+
if (!existsSync(envPath)) {
|
|
1301
|
+
// Allow build to proceed if env vars are coming from process.env directly.
|
|
1302
|
+
const fromProcess = REQUIRED.every((k) => process.env[k]);
|
|
1303
|
+
if (fromProcess) process.exit(0);
|
|
1304
|
+
console.error(
|
|
1305
|
+
\`✗ Missing apps/backend/.env.local and required vars not in process.env.\\n Required: \${REQUIRED.join(", ")}\\n Hint: re-run the installer or copy apps/backend/.env.local.example\`,
|
|
1306
|
+
);
|
|
1307
|
+
process.exit(1);
|
|
1308
|
+
}
|
|
1309
|
+
|
|
1310
|
+
const env = Object.fromEntries(
|
|
1311
|
+
readFileSync(envPath, "utf-8")
|
|
1312
|
+
.split("\\n")
|
|
1313
|
+
.filter((line) => line && !line.startsWith("#"))
|
|
1314
|
+
.map((line) => {
|
|
1315
|
+
const i = line.indexOf("=");
|
|
1316
|
+
return i === -1 ? [line, ""] : [line.slice(0, i).trim(), line.slice(i + 1).trim()];
|
|
1317
|
+
}),
|
|
1318
|
+
);
|
|
1319
|
+
|
|
1320
|
+
const missing = REQUIRED.filter((k) => !env[k] && !process.env[k]);
|
|
1321
|
+
if (missing.length) {
|
|
1322
|
+
console.error(\`✗ Missing required env vars: \${missing.join(", ")}\\n Edit apps/backend/.env.local or set them in process.env.\`);
|
|
1323
|
+
process.exit(1);
|
|
1324
|
+
}
|
|
1325
|
+
console.log("✓ env check passed");
|
|
1326
|
+
`;
|
|
1327
|
+
writeFileSync(resolve(scriptsDir, "check-env.mjs"), script);
|
|
1328
|
+
}
|
|
1329
|
+
|
|
1330
|
+
// PM2 ecosystem config — production process supervision for self-hosted deploys.
|
|
1331
|
+
// Includes FE, BE, optional proxy, and optional cron in fork mode (no clustering
|
|
1332
|
+
// since Next.js handles that internally and the proxy is single-threaded by design).
|
|
1333
|
+
function writePm2Config(targetDir, dirName, adminPrefix) {
|
|
1334
|
+
const singleOrigin = !!adminPrefix;
|
|
1335
|
+
const config = `// PM2 ecosystem config for ${dirName}.
|
|
1336
|
+
// Usage:
|
|
1337
|
+
// pnpm install
|
|
1338
|
+
// pnpm backend:upgrade
|
|
1339
|
+
// pnpm build
|
|
1340
|
+
// pm2 start ecosystem.config.cjs # FE + BE
|
|
1341
|
+
// pm2 start ecosystem.config.cjs --only proxy # add reverse proxy
|
|
1342
|
+
// pm2 start ecosystem.config.cjs --only cron # self-hosted cron fallback
|
|
1343
|
+
// pm2 save && pm2 startup # persist across reboots
|
|
1344
|
+
|
|
1345
|
+
module.exports = {
|
|
1346
|
+
apps: [
|
|
1347
|
+
{
|
|
1348
|
+
name: "frontend",
|
|
1349
|
+
cwd: "./apps/frontend",
|
|
1350
|
+
script: "node_modules/next/dist/bin/next",
|
|
1351
|
+
args: "start",
|
|
1352
|
+
env: { NODE_ENV: "production", PORT: 3001 },
|
|
1353
|
+
max_memory_restart: "1G",
|
|
1354
|
+
autorestart: true,
|
|
1355
|
+
},
|
|
1356
|
+
{
|
|
1357
|
+
name: "backend",
|
|
1358
|
+
cwd: "./apps/backend",
|
|
1359
|
+
script: "node_modules/next/dist/bin/next",
|
|
1360
|
+
args: "start",
|
|
1361
|
+
env: { NODE_ENV: "production", PORT: 3000 },
|
|
1362
|
+
max_memory_restart: "1G",
|
|
1363
|
+
autorestart: true,
|
|
1364
|
+
},
|
|
1365
|
+
{
|
|
1366
|
+
name: "proxy",
|
|
1367
|
+
script: "./apps/proxy/server.mjs",
|
|
1368
|
+
env: {
|
|
1369
|
+
NODE_ENV: "production",
|
|
1370
|
+
PORT: 3030,
|
|
1371
|
+
BACKEND: "http://127.0.0.1:3000",
|
|
1372
|
+
FRONTEND: "http://127.0.0.1:3001",
|
|
1373
|
+
${singleOrigin ? `ADMIN_PREFIX: "${adminPrefix}",` : ""}
|
|
1374
|
+
},
|
|
1375
|
+
max_memory_restart: "256M",
|
|
1376
|
+
autorestart: true,
|
|
1377
|
+
},
|
|
1378
|
+
{
|
|
1379
|
+
name: "cron",
|
|
1380
|
+
cwd: "./apps/backend",
|
|
1381
|
+
script: "scripts/dev-cron.ts",
|
|
1382
|
+
interpreter: "bun",
|
|
1383
|
+
env: { NODE_ENV: "production" },
|
|
1384
|
+
autorestart: true,
|
|
1385
|
+
},
|
|
1386
|
+
],
|
|
1387
|
+
};
|
|
1388
|
+
`;
|
|
1389
|
+
writeFileSync(resolve(targetDir, "ecosystem.config.cjs"), config);
|
|
1390
|
+
}
|
|
1391
|
+
|
|
1392
|
+
function writeClaudeMd(targetDir, adminPrefix) {
|
|
1393
|
+
const singleOrigin = !!adminPrefix;
|
|
1394
|
+
const prefix = adminPrefix || "/admin";
|
|
1395
|
+
const singleOriginSection = singleOrigin
|
|
1396
|
+
? `## Single-origin routing
|
|
1397
|
+
|
|
1398
|
+
Frontend is the public entry point. It rewrites these paths to the backend (do **not** create matching routes in the frontend):
|
|
1399
|
+
|
|
1400
|
+
- \`/admin/*\`, \`/uploads/*\`
|
|
1401
|
+
- \`/api/auth/*\`, \`/api/v1/*\`, \`/api/email/*\`, \`/api/cron\`, \`/api/health\`, \`/api/mcp\`, \`/api/admin/*\`, \`/api/editing-presence/*\`
|
|
1402
|
+
- \`/_next/static\` under \`APOLLO_ASSET_PREFIX=${prefix}\` (backend chunks)
|
|
1403
|
+
|
|
1404
|
+
Custom frontend APIs must be namespaced (e.g. \`/api/internal/*\`).
|
|
1405
|
+
|
|
1406
|
+
To disable single-origin: remove \`APOLLO_ASSET_PREFIX\` from \`apps/backend/.env.local\` and delete the \`rewrites()\` block in \`apps/frontend/next.config.ts\`.
|
|
1407
|
+
|
|
1408
|
+
Known gotcha: backend's \`/_next/image\` is not rewritten — custom admin code using \`<Image>\` on \`/uploads/*\` will 404. Use plain \`<img>\` or \`unoptimized\`.
|
|
1409
|
+
`
|
|
1410
|
+
: `## Routing model — separate origins
|
|
1411
|
+
|
|
1412
|
+
Frontend and backend run on independent origins. No rewrites; talk to the backend over its public URL.
|
|
1413
|
+
`;
|
|
1414
|
+
|
|
1415
|
+
const content = `# CLAUDE.md
|
|
1416
|
+
|
|
1417
|
+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
1418
|
+
|
|
1419
|
+
## Repo shape
|
|
1420
|
+
|
|
1421
|
+
pnpm workspace monorepo. Three workspaces under \`apps/\`:
|
|
1422
|
+
|
|
1423
|
+
- \`apps/frontend\` — public Next.js site${singleOrigin ? " (the public origin in single-origin mode)" : ""}.
|
|
1424
|
+
- \`apps/backend\` — **git submodule** pointing at \`apollo-cms\`. Treat as read-only; do not edit files in here. Open PRs upstream.
|
|
1425
|
+
- \`apps/cms-plugins/<slug>\` — project-specific Apollo CMS plugins. Loaded by the backend via \`APOLLO_EXTRA_PLUGINS_DIR=../cms-plugins\`. Each plugin is built with esbuild to \`dist/server.mjs\` before the backend builds.
|
|
1426
|
+
- \`apps/proxy/server.mjs\` — zero-dep Node reverse proxy used for single-origin dev and self-hosted deploys.
|
|
1427
|
+
|
|
1428
|
+
Built-in plugins in \`apps/backend/plugins/\` always win on slug collisions with \`apps/cms-plugins/\`.
|
|
1429
|
+
|
|
1430
|
+
${singleOriginSection}
|
|
1431
|
+
## Common commands
|
|
1432
|
+
|
|
1433
|
+
\`\`\`bash
|
|
1434
|
+
pnpm install
|
|
1435
|
+
pnpm backend:setup # first-time: db:push + db:seed
|
|
1436
|
+
pnpm backend:upgrade # release-time: db:push + replay src/upgrades/0.1.*.ts + seed
|
|
1437
|
+
pnpm backend:update # fast-forward the apollo-cms submodule
|
|
1438
|
+
|
|
1439
|
+
pnpm dev # FE + BE + plugin watcher (parallel)
|
|
1440
|
+
pnpm dev:rp # same + reverse proxy on :3030 (single origin, shared cookies)
|
|
1441
|
+
pnpm dev:frontend # FE only
|
|
1442
|
+
pnpm dev:backend # BE only (runs predev:setup to build plugins first)
|
|
1443
|
+
|
|
1444
|
+
pnpm build # cms-plugins → backend plugins → backend → frontend
|
|
1445
|
+
pnpm build:backend
|
|
1446
|
+
pnpm build:frontend
|
|
1447
|
+
|
|
1448
|
+
pnpm start # FE + BE
|
|
1449
|
+
pnpm start:rp # FE + BE + proxy
|
|
1450
|
+
|
|
1451
|
+
pnpm lint # recursive
|
|
1452
|
+
pnpm typecheck # recursive
|
|
1453
|
+
|
|
1454
|
+
pnpm cms-plugin:new <slug> # scaffold a new plugin from example-plugin
|
|
1455
|
+
\`\`\`
|
|
1456
|
+
|
|
1457
|
+
\`pnpm dev\` and \`pnpm build\` both run \`cms-plugins:build\` first (via \`predev:setup\` / build script chain) — plugins must compile to \`dist/server.mjs\` before the backend resolves them in production. In dev under Bun the loader also accepts \`index.ts\` directly.
|
|
1458
|
+
|
|
1459
|
+
Release flow on a server: \`pnpm install && pnpm backend:upgrade && pnpm build && pm2 reload all\`. \`pnpm start\` does **not** run migrations.
|
|
1460
|
+
|
|
1461
|
+
## Ports
|
|
1462
|
+
|
|
1463
|
+
Configured in \`ecosystem.config.cjs\` (PM2) and consumed by \`apps/proxy/server.mjs\` via env:
|
|
1464
|
+
|
|
1465
|
+
| Service | Port |
|
|
1466
|
+
| -------- | ---- |
|
|
1467
|
+
| proxy | 3030 |
|
|
1468
|
+
| backend | 3000 |
|
|
1469
|
+
| frontend | 3001 |
|
|
1470
|
+
|
|
1471
|
+
Proxy reads \`PORT\`, \`BACKEND\`, \`FRONTEND\`, \`ADMIN_PREFIX\` from env. When using the proxy locally, set \`NEXT_PUBLIC_SITE_URL=http://localhost:3030\` so Better Auth / OAuth callbacks land on the unified origin.
|
|
1472
|
+
|
|
1473
|
+
## Deploy
|
|
1474
|
+
|
|
1475
|
+
- Self-hosted: build on a runner, rsync to the server, then \`pm2 startOrReload ecosystem.config.cjs --update-env\`. If the backend submodule is private, the deploy runner needs a token with read access.
|
|
1476
|
+
- Vercel: two projects per repo (\`apps/backend\` and \`apps/frontend\` root dirs). Backend's Build Command must copy \`apps/cms-plugins/*/dist\` into \`apps/backend/plugins/\` before \`next build\` because Turbopack rejects \`outputFileTracingIncludes\` globs above the project root. "Include all submodules" must be ON in both projects.
|
|
1477
|
+
|
|
1478
|
+
## Submodule discipline
|
|
1479
|
+
|
|
1480
|
+
- Do not edit files under \`apps/backend\` — they belong to the upstream \`apollo-cms\` repo.
|
|
1481
|
+
- After \`pnpm backend:update\`, run \`pnpm install\` (in case package.json changed) then \`pnpm backend:upgrade\` (replays data migrations that \`backend:setup\` skips).
|
|
1482
|
+
`;
|
|
1483
|
+
writeFileSync(resolve(targetDir, "CLAUDE.md"), content);
|
|
1484
|
+
}
|
|
1485
|
+
|
|
1247
1486
|
function writeReadme(targetDir, dirName, frontendName, adminPrefix) {
|
|
1248
1487
|
const singleOrigin = !!adminPrefix;
|
|
1249
1488
|
|
|
@@ -1372,14 +1611,13 @@ folder + \`plugin.json#name\`.
|
|
|
1372
1611
|
Apollo CMS is tracked as a git submodule. Full upgrade flow:
|
|
1373
1612
|
|
|
1374
1613
|
\`\`\`bash
|
|
1375
|
-
pnpm backend:update # fast-forward apps/backend
|
|
1376
|
-
pnpm install # in case the submodule changed package.json
|
|
1614
|
+
pnpm backend:update # auto-stash, fast-forward apps/backend, run pnpm install
|
|
1377
1615
|
pnpm backend:upgrade # drizzle push + replay version migrations + seed
|
|
1378
1616
|
\`\`\`
|
|
1379
1617
|
|
|
1380
1618
|
| Script | What it does |
|
|
1381
1619
|
| --- | --- |
|
|
1382
|
-
| \`pnpm backend:update\` |
|
|
1620
|
+
| \`pnpm backend:update\` | Auto-stashes local submodule changes, fast-forwards \`apps/backend\`, runs \`pnpm install\` so new backend deps are picked up, then restores the stash. |
|
|
1383
1621
|
| \`pnpm backend:setup\` | First-time bootstrap: \`db:push\` + \`db:seed\` only |
|
|
1384
1622
|
| \`pnpm backend:upgrade\` | Full pipeline: \`db:push\` + replay \`src/upgrades/0.1.*.ts\` data migrations + \`db:seed\`. **Use this** after \`backend:update\` — \`backend:setup\` skips the data-migration phase. |
|
|
1385
1623
|
|
|
@@ -1391,6 +1629,53 @@ Do **not** edit files inside \`apps/backend\`. Open issues / PRs in the
|
|
|
1391
1629
|
Shared dev env lives in the root \`.env.local\`. The backend reads its own
|
|
1392
1630
|
\`apps/backend/.env.local\` (already populated by the installer).
|
|
1393
1631
|
|
|
1632
|
+
## Deploy (self-hosted)
|
|
1633
|
+
|
|
1634
|
+
Standard sequence on a VPS / Docker host / bare metal:
|
|
1635
|
+
|
|
1636
|
+
\`\`\`bash
|
|
1637
|
+
pnpm install
|
|
1638
|
+
pnpm backend:upgrade # db push + replay data migrations + seed (run ONCE per release)
|
|
1639
|
+
pnpm build # builds plugins → backend → frontend
|
|
1640
|
+
pnpm start # FE :3001 + BE :3000 — or:
|
|
1641
|
+
pnpm start:rp # adds Node reverse proxy on :3030 (single origin)
|
|
1642
|
+
\`\`\`
|
|
1643
|
+
|
|
1644
|
+
\`pnpm start\` does **not** run migrations on boot — that lets you restart
|
|
1645
|
+
processes without re-running \`drizzle-kit push\` every time. Always run
|
|
1646
|
+
\`pnpm backend:upgrade\` once per release before \`pnpm start\`.
|
|
1647
|
+
|
|
1648
|
+
| Script | What it does |
|
|
1649
|
+
| ------------------- | ------------------------------------------------------------------- |
|
|
1650
|
+
| \`pnpm build\` | Full pipeline: cms-plugins → backend plugins → backend → frontend |
|
|
1651
|
+
| \`pnpm start\` | FE + BE (parallel \`next start\`) |
|
|
1652
|
+
| \`pnpm start:rp\` | FE + BE + reverse proxy on :3030 |
|
|
1653
|
+
| \`pnpm start:proxy\` | Reverse proxy alone (already running FE/BE separately) |
|
|
1654
|
+
| \`pnpm start:cron\` | Self-hosted cron fallback — only if not using Vercel Cron / k8s |
|
|
1655
|
+
|
|
1656
|
+
### PM2 (recommended for VPS)
|
|
1657
|
+
|
|
1658
|
+
The installer scaffolds \`ecosystem.config.cjs\`. To supervise everything:
|
|
1659
|
+
|
|
1660
|
+
\`\`\`bash
|
|
1661
|
+
pm2 start ecosystem.config.cjs # FE + BE + proxy + cron (all four)
|
|
1662
|
+
pm2 start ecosystem.config.cjs --only frontend,backend # just the two apps
|
|
1663
|
+
pm2 save && pm2 startup # persist across reboots
|
|
1664
|
+
pm2 logs # tail all processes
|
|
1665
|
+
pm2 reload all # zero-downtime restart
|
|
1666
|
+
\`\`\`
|
|
1667
|
+
|
|
1668
|
+
The proxy and cron processes can be omitted with \`--only\` if you front the
|
|
1669
|
+
apps with nginx/Caddy or use platform cron (system cron, k8s CronJob).
|
|
1670
|
+
|
|
1671
|
+
### Docker / k8s
|
|
1672
|
+
|
|
1673
|
+
For containerized deploys:
|
|
1674
|
+
- Bake the build into the image (\`pnpm install && pnpm build\`)
|
|
1675
|
+
- Set entrypoint to \`pnpm start\` or \`pnpm start:rp\`
|
|
1676
|
+
- Run \`pnpm backend:upgrade\` as a separate init container / Job before app pods start
|
|
1677
|
+
- Use platform-native cron (k8s CronJob hitting \`/api/cron\` with \`CRON_SECRET\`) instead of \`pnpm start:cron\`
|
|
1678
|
+
|
|
1394
1679
|
## Deploy on Vercel
|
|
1395
1680
|
|
|
1396
1681
|
Two Vercel projects, one repo. Each project picks up its own Root Directory.
|
|
@@ -1505,12 +1790,15 @@ async function main() {
|
|
|
1505
1790
|
writeRootGitignore(targetDir);
|
|
1506
1791
|
writeRootEnv(targetDir, { dbUrl, siteUrl, locale, authSecret, cronSecret, adminPrefix, backendInternalUrl });
|
|
1507
1792
|
writeReadme(targetDir, dirName, frontendName, adminPrefix);
|
|
1793
|
+
writeClaudeMd(targetDir, adminPrefix);
|
|
1508
1794
|
if (adminPrefix) writeNginxSample(targetDir, adminPrefix);
|
|
1509
1795
|
writeProxyApp(targetDir, dirName, adminPrefix);
|
|
1796
|
+
writeCheckEnvScript(targetDir);
|
|
1797
|
+
writePm2Config(targetDir, dirName, adminPrefix);
|
|
1510
1798
|
success(
|
|
1511
|
-
`package.json, pnpm-workspace.yaml, .gitignore, .env.local, README.md${
|
|
1799
|
+
`package.json, pnpm-workspace.yaml, .gitignore, .env.local, README.md, CLAUDE.md${
|
|
1512
1800
|
adminPrefix ? ", nginx.conf.sample" : ""
|
|
1513
|
-
}, apps/proxy`,
|
|
1801
|
+
}, apps/proxy, ecosystem.config.cjs, scripts/check-env.mjs`,
|
|
1514
1802
|
);
|
|
1515
1803
|
|
|
1516
1804
|
// ── Step 4: git init ──
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-apollo-monorepo",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.1",
|
|
4
4
|
"description": "Scaffold a monorepo with a frontend app and Apollo CMS as a git submodule backend (single-origin via Next.js rewrites + assetPrefix)",
|
|
5
5
|
"bin": {
|
|
6
6
|
"create-apollo-monorepo": "index.mjs"
|