@sandboxsonny/ace-kit 0.3.0 → 0.4.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.
@@ -0,0 +1,104 @@
1
+ # Sections
2
+
3
+ A **section** is a part of a page that an editor adds, fills in and reorders in the CMS: a hero, an FAQ, a gallery. You define what each kind can hold in a small file next to the component that draws it. Ace Kit sends those definitions to the CMS while your dev server runs, and types the component's props from them.
4
+
5
+ ```
6
+ src/components/sections/
7
+ Faq.astro
8
+ Faq.schema.ts <- what an FAQ can hold
9
+ Hero.astro
10
+ Hero.schema.ts
11
+ ```
12
+
13
+ ## Describing a section
14
+
15
+ ```ts
16
+ // Faq.schema.ts
17
+ import { defineSection } from "@sandboxsonny/ace-kit";
18
+
19
+ export default defineSection({
20
+ handle: "faq",
21
+ name: "FAQ",
22
+ fields: [{ handle: "heading", label: "Heading", type: "text" }],
23
+ blocks: {
24
+ question: {
25
+ name: "Question",
26
+ fields: [
27
+ { handle: "question", label: "Question", type: "text", required: true },
28
+ { handle: "answer", label: "Answer", type: "richtext" },
29
+ ],
30
+ },
31
+ },
32
+ });
33
+ ```
34
+
35
+ - **`handle`** is the section's kind in your code (`section.type`) and in the CMS: lowercase letters, numbers and hyphens. **`name`** is what the editor sees.
36
+ - **`fields`** are the section's own values. Each has a `handle`, a `label` and a `type`: `text`, `textarea`, `number`, `checkbox`, `select` (also give `options: [...]`), `image`, `richtext`, `date` or `link`. Add `required: true` to make the editor fill it in.
37
+ - **`blocks`** are the repeatable items inside a section, by handle, each with a `name` and its own `fields`. An FAQ's questions are blocks: the editor adds as many as they like and reorders them. A section without `blocks` is just fields.
38
+ - The file's **default export** must be the result of `defineSection`. Everything else in the file is ignored.
39
+
40
+ A section can't hold other sections; use blocks for a list inside one.
41
+
42
+ ## Drawing sections
43
+
44
+ The component's props follow its schema, with nothing written twice:
45
+
46
+ ```astro
47
+ ---
48
+ // Faq.astro
49
+ import type { SectionOf } from "@sandboxsonny/ace-kit";
50
+ import type faq from "./Faq.schema";
51
+
52
+ type Props = { section: SectionOf<typeof faq> };
53
+ const { section } = Astro.props;
54
+ ---
55
+
56
+ <h2>{section.values.heading}</h2>
57
+ {section.blocks.map((block) => (
58
+ <details>
59
+ <summary>{block.values.question}</summary>
60
+ </details>
61
+ ))}
62
+ ```
63
+
64
+ `section.values.heading` is a `string | undefined` (it isn't required); `block.values.question` is a `string` (it is). An `image` is `AceImageData`, a `link` is `AceLinkData`, a `select` is the union of its options, and a block's `values` depend on its `type` when a section has more than one kind of block.
65
+
66
+ Then draw a whole sections field with the component for each kind:
67
+
68
+ ```astro
69
+ ---
70
+ import AceSections from "@sandboxsonny/ace-kit/astro/AceSections.astro";
71
+ import Faq from "~/components/sections/Faq.astro";
72
+ import Hero from "~/components/sections/Hero.astro";
73
+ ---
74
+
75
+ <AceSections sections={entry.values.content} components={{ hero: Hero, faq: Faq }} />
76
+ ```
77
+
78
+ On React and React Router the same component comes from `@sandboxsonny/ace-kit/react` and `@sandboxsonny/ace-kit/react-router`. A section whose kind has no component is left out (and noted in the dev server's log), or drawn by a `fallback` component if you give one (React). Sections are drawn in the order the editor put them.
79
+
80
+ With `ace-kit generate`, a sections field is typed `AceSection[]`: a list of sections of any kind, which is what `AceSections` takes.
81
+
82
+ ## Syncing to the CMS
83
+
84
+ While the dev server runs, Ace Kit watches for `*.schema.ts` files (in `src`) and syncs them to the CMS whenever one is added, changed or removed, and once at start. It prints one line each time:
85
+
86
+ ```
87
+ 10:41:07 [ace-kit] Synced 3 section types (faq, gallery, hero) to localhost (http://localhost:8080).
88
+ ```
89
+
90
+ You don't run anything. You do need to be signed in once: `npx ace-kit login` (see [the command line](./command-line.md)). The sync goes to the site named by `ACE_SITE_DOMAIN` at `ACE_API_URL`, the same settings the site reads its content with, and only an owner of that site (or a super admin) can sync to it.
91
+
92
+ **Your dev site, not the live one.** Against a _hosted_ CMS the dev server works on a [dev site](./dev-sites.md): your own private copy of the site, made for you the first time, so a half-written field never reaches editors or visitors of the live site. The sync goes there. Against a CMS on your own machine there is no need for one, and the sync goes to the site itself.
93
+
94
+ **If there is no dev site to sync to** (you aren't signed in, or your account can't have one), automatic sync stays off against a hosted CMS, and the dev server says why. To allow it against the live site anyway, set `ACE_SYNC_SECTIONS=remote`; to turn it off, `ACE_SYNC_SECTIONS=false`. Running `npx ace-kit sync` yourself always syncs to the site `ACE_SITE_DOMAIN` names, which is how a change reaches the live site: deploy first, then run it.
95
+
96
+ **Nothing is deleted, and a partial picture is never sent.** The CMS treats what is sent as the whole list. A section, block or field you take out of your code is kept there, hidden, so the content already written in it isn't lost (put it back and it returns). A field changing kind (say `text` to `number`) is refused, because its saved values are of the old kind: use a new handle. If any schema file can't be loaded, or none are found, **nothing is synced**; the error says which file and why.
97
+
98
+ ### On a build server
99
+
100
+ `npx ace-kit sync` does the same once, in a command. With `ACE_TOKEN` set (see [the command line](./command-line.md)) it needs no browser. Schema files are TypeScript, which Node runs as it is from **Node 22.18** (use `.js` files on older versions).
101
+
102
+ ## What the CMS needs
103
+
104
+ An API with sections (its migration 00019), command-line sign-in (00020) and, for dev sites, 00022.
@@ -45,6 +45,7 @@ cms.getEntry("pagez", "about"); // type error: no such content type
45
45
  | Rich text | `AceRichTextDocument` |
46
46
  | Date | `string`, a day written `YYYY-MM-DD` (see `formatAceDate`) |
47
47
  | Link | `AceLinkData`: `{ href, label? }` |
48
+ | Sections | `AceSection[]` (see [Sections](./sections.md)) |
48
49
  | a kind this version doesn't know | `unknown` |
49
50
 
50
51
  A field is optional unless it is marked required in the CMS. Before you generate, handles are plain `string` and values are `Record<string, unknown>`, so nothing breaks.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sandboxsonny/ace-kit",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "Everything a website needs to use CMS Ace: a typed client, addressing, images, menus, rich text, live preview, and Astro and React adapters.",
5
5
  "keywords": [
6
6
  "cms",