caracms 0.7.0 → 0.8.0

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/README.md CHANGED
@@ -27,8 +27,10 @@ one diff to review. Then look at what `init` would do:
27
27
  npx caracms init
28
28
  ```
29
29
 
30
- It prints every file it would add and every edit it would make, as a diff, and changes
31
- nothing. When it looks right, apply it and install what it added:
30
+ It asks where the site will run, [CaraCMS Cloud](#caracms-cloud) or self-hosted, then
31
+ prints every file it would add and every edit it would make, as a diff, and changes
32
+ nothing. (It asks only in a terminal: an agent or a script passes `--cloud` or
33
+ `--self-hosted`.) When it looks right, apply it and install what it added:
32
34
 
33
35
  ```sh
34
36
  npx caracms init --write
@@ -45,9 +47,12 @@ job of the `caracms-adopt` skill, one page at a time.
45
47
 
46
48
  Run from the site's root:
47
49
 
48
- - `caracms init [--write] [--railway]`: add caracms to an Astro site, or bring a set-up
49
- site's skills, schemas and CLAUDE.md block up to date. `--railway` also writes a
50
- Railway setup; without it, `init` prints the variables any host needs (Hosting, below).
50
+ - `caracms init [--write] [--railway] [--cloud | --self-hosted]`: add caracms to an Astro
51
+ site, or bring a set-up site's skills, schemas and CLAUDE.md block up to date.
52
+ `--cloud` or `--self-hosted` says where the site runs, written into `caracms.config.ts`
53
+ as `services` ([Where the site runs](#where-the-site-runs-services)); `--cloud` on a
54
+ self-hosted site also prints the steps of the move. `--railway` also writes a Railway
55
+ setup; without it, `init` prints the variables any host needs (Hosting, below).
51
56
  - `caracms validate [--fix] [--json]`: check the content against `caracms.config.ts`.
52
57
  Exits 1 when there are errors. `--fix` runs `caracms schemas` first, then lays each
53
58
  content file out as the editor saves it (two-space JSON; only whitespace changes).
@@ -59,8 +64,8 @@ Run from the site's root:
59
64
  keeping every key ([Moving a site's images in](#moving-a-sites-images-in)).
60
65
  - `caracms start`: serve the built site (Hosting, below).
61
66
 
62
- The skills (`caracms-content`, `caracms-blocks` and `caracms-adopt`, in `skills/`) say how
63
- the rest works, matching the installed version.
67
+ The skills (`caracms-content`, `caracms-blocks`, `caracms-adopt`, `caracms-tina` and
68
+ `caracms-hosting`, in `skills/`) say how the rest works, matching the installed version.
64
69
 
65
70
  ## Collections and addresses
66
71
 
@@ -204,7 +209,8 @@ It prints where the IP comes from when it starts.
204
209
  - Commit: `RAILWAY_GIT_COMMIT_SHA`, which Railway sets.
205
210
  - `caracms init --railway` writes `.railway/railway.ts`, which describes the whole
206
211
  project (the site, Redis, the buckets, imgproxy). Railway's own variables cover the
207
- repo, so `GITHUB_REPO` isn't needed.
212
+ repo, so `GITHUB_REPO` isn't needed. With `--cloud` it writes only the site and Redis:
213
+ the cloud brings the rest.
208
214
  - Try again: `CARACMS_RAILWAY_TOKEN`, a project token. Railway has no deploy hook.
209
215
 
210
216
  ### Render
@@ -317,6 +323,64 @@ only, with the same permissions as the token.
317
323
 
318
324
  ### CaraCMS Cloud
319
325
 
326
+ #### Where the site runs: `services`
327
+
328
+ `caracms.config.ts` says where the site's services (GitHub access, images, forms and
329
+ email, video) come from, and nothing else decides it:
330
+
331
+ ```ts
332
+ export default defineSite({
333
+ services: 'cloud', // or 'self-hosted'
334
+ collections: { … },
335
+ …
336
+ });
337
+ ```
338
+
339
+ - **`'cloud'`**: everything comes through `CARACMS_CLOUD_KEY`. The self-hosted variables
340
+ (the GitHub token or App and `GITHUB_REPO`, the image, video, and form and email ones
341
+ below) are **ignored**, never read, and each is named once in the build log and once
342
+ when the server starts:
343
+
344
+ > S3_BUCKET is set, but this site runs on CaraCMS Cloud (caracms.config.ts): it's ignored. Remove it once the old bucket and imgproxy are retired.
345
+
346
+ So a site can move with its old variables still set, and remove them afterwards. A
347
+ production build or server with no key fails with "This site runs on CaraCMS Cloud
348
+ (caracms.config.ts), but CARACMS_CLOUD_KEY isn't set. Make a key for it in
349
+ app.caracms.com." (the build fails; a running server's `/admin` answers 503 with it, and
350
+ the public site keeps serving). It never falls back to the self-hosted variables.
351
+ `astro dev` without a key is local mode, as always.
352
+ - **`'self-hosted'`**: the site's own variables, as [the variables](#the-variables) list
353
+ them. A `CARACMS_CLOUD_KEY` beside them is ignored the same way.
354
+ - **Not set** (a site from before caracms 0.8.0): the key decides, and setting it beside
355
+ the site's own variables is refused, as each section below says. The next `caracms init`
356
+ adds the field.
357
+
358
+ `caracms init --cloud` or `--self-hosted` writes the field (as the first line inside
359
+ `defineSite({`). With neither, `init` asks in a terminal and, run by an agent or a script,
360
+ leaves a set-up site's mode unset (and says so) or stops on a new one. Once the field is
361
+ there, `init` reads it and never asks again.
362
+
363
+ **Moving a self-hosted site onto the cloud.** `caracms init --cloud` on a self-hosted site
364
+ writes the field and prints the steps of the move, in order, each with the check that it
365
+ worked: make the site, its key and the App's install in app.caracms.com; push the field
366
+ (the host's build fails until the key is set: the old deployment keeps serving); copy the
367
+ images in with [`caracms media push`](#moving-a-sites-images-in); set the key on the host;
368
+ upload the video clips again; remove every variable the cloud replaces (it names them all,
369
+ marking the ones it found in `.env` and `.railway/railway.ts`; it can't see the host's own
370
+ page, so check that too); retire what the cloud replaced; and, last, cut
371
+ `.railway/railway.ts` down to the site and Redis. `init` never edits an existing
372
+ `.railway/railway.ts`: `railway config apply` would remove the buckets with it. With a key
373
+ in the environment or `.env`, `init --cloud` also checks it, showing the site, its team,
374
+ the linked repo and whether the App is installed on it, or the cloud's reason for refusing
375
+ it (it never prints the key). The `caracms-hosting` skill walks through all of this.
376
+
377
+ **Leaving.** `caracms init --self-hosted` on a cloud site writes the field back and prints
378
+ the way back: set up the site's own services ([Hosting](#hosting)), copy the site's folder
379
+ from the cloud's media bucket to a bucket of your own (the keys in content stay the same),
380
+ set the variables, then remove the key.
381
+
382
+ #### GitHub access on CaraCMS Cloud
383
+
320
384
  A site run by CaraCMS can take its GitHub access from CaraCMS Cloud instead of a token or
321
385
  an App of its own. The cloud gives the site's server a short-lived token for the site's
322
386
  repo, and only that repo, about once an hour.
@@ -329,8 +393,9 @@ repo, and only that repo, about once an hour.
329
393
  site's server.
330
394
 
331
395
  The key replaces `CARACMS_GITHUB_TOKEN` (or `GITHUB_APP_ID` and `GITHUB_APP_PRIVATE_KEY`)
332
- and `GITHUB_REPO`: the repo comes from the cloud when the server starts, so setting
333
- `GITHUB_REPO` beside the key is refused, and so is setting a token or an App as well. It
396
+ and `GITHUB_REPO`: the repo comes from the cloud when the server starts. With `services: 'cloud'`
397
+ they're ignored; on a site whose config doesn't say, setting `GITHUB_REPO` beside the key is
398
+ refused, and so is setting a token or an App as well. It
334
399
  also replaces the image variables ([Images](#images-on-caracms-cloud), below), the
335
400
  video ones ([Video](#video-on-caracms-cloud)), and the form and email ones
336
401
  ([Forms and email](#forms-and-email-on-caracms-cloud)).
@@ -350,7 +415,8 @@ start.
350
415
  With the key, the site's images live in its own folder of CaraCMS Cloud's media bucket and
351
416
  are served, resized and signed, from `img.caracms.cloud`. Set none of `S3_ENDPOINT`,
352
417
  `S3_REGION`, `S3_BUCKET`, `S3_ACCESS_KEY_ID`, `S3_SECRET_ACCESS_KEY`, `IMGPROXY_KEY`,
353
- `IMGPROXY_SALT` or `CARACMS_MEDIA_URL`: setting any of them beside the key is refused with
418
+ `IMGPROXY_SALT` or `CARACMS_MEDIA_URL`. With `services: 'cloud'` they're ignored; on a site
419
+ whose config doesn't say, setting any of them beside the key is refused with
354
420
 
355
421
  > Set CARACMS_CLOUD_KEY or the site's own media variables, not both: remove S3_BUCKET.
356
422
 
@@ -374,8 +440,9 @@ site's `.env`), with the same rules and output, and its uploads count like any o
374
440
 
375
441
  With the key, the site needs no submissions bucket and no Resend account. Set none of
376
442
  `SUBMISSIONS_S3_BUCKET`, `SUBMISSIONS_S3_ACCESS_KEY_ID`, `SUBMISSIONS_S3_SECRET_ACCESS_KEY`,
377
- `RESEND_API_KEY` or `FORMS_FROM`: setting any of them beside the key is refused, at build
378
- and when the server starts, with
443
+ `RESEND_API_KEY` or `FORMS_FROM`. With `services: 'cloud'` they're ignored; on a site whose
444
+ config doesn't say, setting any of them beside the key is refused, at build and when the
445
+ server starts, with
379
446
 
380
447
  > Set CARACMS_CLOUD_KEY or the site's own forms and email variables, not both: remove RESEND_API_KEY and FORMS_FROM.
381
448
 
@@ -406,8 +473,9 @@ them.
406
473
 
407
474
  `caracms media push` copies everything under `uploads/` in the site's own bucket into its
408
475
  CaraCMS Cloud folder, under the same keys, so the content doesn't change. It's the one
409
- command that takes both credentials, so give the site's own `S3_*` on its command line
410
- rather than in `.env` (the running site refuses both):
476
+ command that takes both credentials. The old bucket's `S3_*` can stay in `.env` once the
477
+ config says `services: 'cloud'` (the running site ignores them); on a site whose config
478
+ doesn't say, give them on its command line instead (it refuses both):
411
479
 
412
480
  ```bash
413
481
  S3_ENDPOINT=https://t3.storageapi.dev S3_REGION=auto S3_BUCKET=… S3_ACCESS_KEY_ID=… S3_SECRET_ACCESS_KEY=… npx caracms media push
@@ -423,8 +491,8 @@ CaraCMS to raise it, then run it again.
423
491
 
424
492
  With the key, the site's clips are uploaded to CaraCMS Cloud's Mux and listed from the
425
493
  site's own clips there; the editor works exactly as it does with a Mux account of your
426
- own. Set neither `MUX_TOKEN_ID` nor `MUX_TOKEN_SECRET`: setting either beside the key is
427
- refused with
494
+ own. Set neither `MUX_TOKEN_ID` nor `MUX_TOKEN_SECRET`. With `services: 'cloud'` they're
495
+ ignored; on a site whose config doesn't say, setting either beside the key is refused with
428
496
 
429
497
  > Set CARACMS_CLOUD_KEY or the site's own Mux variables, not both: remove MUX_TOKEN_ID.
430
498
 
package/bin/caracms.mjs CHANGED
@@ -31,7 +31,9 @@ import { createGate, describeClientIpSource, markProcessGated, parsePrelaunch, p
31
31
 
32
32
  const USAGE = `Usage: caracms <command>, from the site's root
33
33
 
34
- init [--write] [--railway] Add caracms to an existing Astro site. Shows the change; --write applies it.
34
+ init [--write] [--railway] [--cloud | --self-hosted]
35
+ Add caracms to an existing Astro site, and say where it runs (CaraCMS
36
+ Cloud or self-hosted). Shows the change; --write applies it.
35
37
  schemas Write schemas/ from caracms.config.ts, and add $schema to content files.
36
38
  validate [--fix] [--json] Check content against caracms.config.ts. --fix runs \`schemas\` first,
37
39
  then lays content files out as the editor saves them;
@@ -180,10 +182,16 @@ async function main(argv) {
180
182
  if (rest.length) return usage(`start takes no arguments.`);
181
183
  return start();
182
184
  case 'init': {
183
- const f = flags('init', rest, ['--write', '--railway']);
185
+ const f = flags('init', rest, ['--write', '--railway', '--cloud', '--self-hosted']);
184
186
  if (f.error) return usage(f.error);
185
187
  const { run } = await import('./init.mjs');
186
- process.exitCode = await run({ root: process.cwd(), write: f.set.has('--write'), railway: f.set.has('--railway') });
188
+ process.exitCode = await run({
189
+ root: process.cwd(),
190
+ write: f.set.has('--write'),
191
+ railway: f.set.has('--railway'),
192
+ cloud: f.set.has('--cloud'),
193
+ selfHosted: f.set.has('--self-hosted'),
194
+ });
187
195
  return;
188
196
  }
189
197
  case 'schemas':