riverbankcms 0.2.0 → 0.2.2

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.
@@ -1,6 +1,8 @@
1
1
  ## RiverbankCMS SDK Context
2
2
 
3
- This repository is a site using **RiverbankCMS** as a headless CMS via the `@riverbankcms/sdk` package.
3
+ This repository is a fully headless site using **RiverbankCMS** as a CMS via
4
+ the `@riverbankcms/sdk` package. The host owns markup, styles, and block
5
+ rendering through the override registry.
4
6
 
5
7
  ### What This Means
6
8
 
@@ -23,7 +25,7 @@ Detailed documentation is available in `.riverbank/docs/`:
23
25
  - `content-management.md` - Content model and sync workflows
24
26
  - `schema.md` - Site-specific schema (auto-generated from config)
25
27
  - `block-types.md` - Available block types (auto-generated)
26
- - `theme-schema.md` - Theme schema reference (auto-generated from Zod)
28
+ - `theme-schema.md` - Optional theme schema reference (auto-generated from Zod)
27
29
  - `workflows/` - Step-by-step guides for common tasks, including editor workflows
28
30
  - `workflows/agent-safe-sync.md` - Agent-safe dry-run, scoped push, and `--env` guidance
29
31
  - `site-workflows/` - Site-specific workflows and customizations
@@ -46,6 +48,11 @@ Use CLI `--env=remote` / `--env=local` for CMS commands rather than relying on `
46
48
  3. **Preview**: `riverbankcms push --dry-run` shows what would change
47
49
  4. **Push**: `riverbankcms push` applies changes to CMS
48
50
 
51
+ Built-in semantic kinds such as `block.hero` remain in content JSON. Register
52
+ the host-owned override for every kind the site uses in `src/lib/block-overrides.tsx`.
53
+ The generated default uses `SITE_RENDERING` with override-only rendering and no
54
+ CMS theme runtime.
55
+
49
56
  For narrow edits, push the narrowest scope possible, for example `riverbankcms push pages privacy-policy --env=remote --dry-run`. If broad local content is stale or contains unrelated differences, see `.riverbank/docs/workflows/agent-safe-sync.md`.
50
57
 
51
58
  ### Editing Page Content Directly
@@ -10,7 +10,7 @@ All commands support these options:
10
10
  | ---------------- | ---------------------------------------------------------- |
11
11
  | `--json` | Output a single JSON envelope for machine parsing |
12
12
  | `--quiet` | Minimal output (suppress non-essential messages) |
13
- | `--env <target>` | Target environment: `local` (default), `remote`, or `both` |
13
+ | `--env <target>` | Target project environment: `local` (default), `remote`, or `both` |
14
14
  | `--remote` | **[Deprecated]** Use `--env=remote` instead |
15
15
 
16
16
  **The `--json` envelope (single-document contract):** under `--json`, *every* invocation emits **exactly one** JSON document on stdout:
@@ -25,8 +25,8 @@ All commands support these options:
25
25
 
26
26
  **Environment targeting:**
27
27
 
28
- - `--env=local` (default): Target local Supabase/development environment
29
- - `--env=remote`: Target production CMS
28
+ - `--env=local` (default): Target the local development CMS
29
+ - `--env=remote`: Target the production CMS
30
30
  - `--env=both`: Run against both environments sequentially
31
31
 
32
32
  **Safety behavior:**
@@ -67,12 +67,55 @@ RIVERBANK_REMOTE_API_KEY=bld_live_sk_... # Required for deploy command
67
67
 
68
68
  - Management API keys start with `bld_mgmt_sk_` (for write operations)
69
69
  - Content API keys start with `bld_live_sk_` (for read-only operations)
70
- - `RIVERBANK_*_SUPABASE_URL` is deprecated and ignored by media sync
71
70
 
72
71
  ---
73
72
 
74
73
  ## Setup Commands
75
74
 
75
+ ### Account authentication and site setup
76
+
77
+ Account commands use a provider-neutral Riverbank account session. Select the
78
+ account environment independently from the project `--env` target:
79
+
80
+ Production account OAuth is deliberately rollout-disabled. The examples below
81
+ use staging; use local for development. Do not use
82
+ `--account-env=production` until the production account rollout is explicitly
83
+ enabled.
84
+
85
+ ```bash
86
+ riverbankcms login --account-env=staging
87
+ riverbankcms whoami --account-env=staging
88
+ riverbankcms sites list --account-env=staging
89
+ riverbankcms sites create --account-env=staging --name "Dovetail" --yes
90
+ riverbankcms logout --account-env=staging
91
+ riverbankcms auth revoke --account-env=staging --yes
92
+ ```
93
+
94
+ The CLI stores the refresh session in the OS credential store when available.
95
+ If a locked-file fallback is required, the CLI explains the risk and requires
96
+ `--allow-locked-file`. `logout` removes this machine’s stored session;
97
+ `auth revoke` revokes the account grant so access tokens on other machines can
98
+ no longer refresh. Neither operation removes sites, project credentials, or
99
+ content.
100
+
101
+ Use `link` for an existing project and `init` for a complete new project:
102
+
103
+ ```bash
104
+ riverbankcms link --project ./my-site --account-env=staging --site <site-id> --preview
105
+ riverbankcms init ./my-site --account-env=staging --name "Dovetail" --preview
106
+ ```
107
+
108
+ Preview is explicit state. `--preview` includes preview routes and a preview
109
+ credential; `--no-preview` omits both. Interactive `init` asks for the choice;
110
+ JSON and other non-interactive mutations require an explicit choice and
111
+ `--yes`. Published CLI projects install packages from npm. Local/tarball
112
+ sources are test-fixture seams and are not public flags.
113
+
114
+ Generated projects are provider-neutral and contain only Riverbank project
115
+ configuration. The account refresh session is never written to the project
116
+ env file, and no database-provider URL, provider auth token, or service-role
117
+ credential is scaffolded.
118
+
76
119
  ### setup plan
77
120
 
78
121
  Show the safe site, key, user access, and env setup lifecycle for the selected environment.
@@ -88,10 +131,31 @@ riverbankcms setup plan --env=remote
88
131
  riverbankcms setup plan --env=both --json
89
132
  ```
90
133
 
91
- The setup planner is read-only. It does not create sites, issue API keys, or grant dashboard access. Those operations require a dashboard/admin actor or an approved CMS repo script with service-role/admin credentials. SDK management keys are site-scoped and are only used for verifying access and syncing content/config for an existing site.
134
+ The setup planner is read-only. It reports which values are missing and shows
135
+ the supported lifecycle. Use `riverbankcms sites create`, `riverbankcms link`,
136
+ or `riverbankcms init` with an authenticated account session to create sites
137
+ and issue project credentials for the signed-in account. Use the dashboard to
138
+ grant access to additional users. SDK management keys are site-scoped and are
139
+ used for project sync; they cannot create sites or grant other users access.
92
140
 
93
141
  Use this command when a project has missing `RIVERBANK_*_SITE_ID`, `RIVERBANK_*_DASHBOARD_URL`, or `RIVERBANK_*_MGMT_API_KEY` values, or when onboarding an existing remote site into an SDK repo.
94
142
 
143
+ ### Post-deployment revalidation
144
+
145
+ `init` scaffolds `/api/revalidate` but does not register a webhook or write a
146
+ webhook secret. After the project has a public HTTPS origin, activate it
147
+ explicitly:
148
+
149
+ ```bash
150
+ riverbankcms webhooks setup \
151
+ --env=remote \
152
+ --url=https://www.example.com/api/revalidate \
153
+ --yes
154
+ ```
155
+
156
+ Until setup is complete, the generated site’s ISR interval is the freshness
157
+ fallback. Keep the one-time webhook secret in the deployment environment.
158
+
95
159
  ---
96
160
 
97
161
  ## Content Sync Commands
@@ -75,16 +75,19 @@ content/
75
75
  navigation.json # All navigation menus
76
76
  ```
77
77
 
78
- ### 5. Themes
78
+ ### 5. Themes (Optional Opt-in)
79
79
 
80
- Site theme objects used for rendering blocks.
80
+ CMS theme objects are optional. Fully headless sites use host-owned markup,
81
+ styles, and block overrides instead of loading a CMS theme or SDK runtime
82
+ styles. Use a theme only when the site intentionally opts into themed built-in
83
+ rendering or local theme iteration.
81
84
 
82
85
  **Local file structure:**
83
86
 
84
87
  ```
85
88
  content/
86
89
  themes/
87
- current.json # Default theme (pulled from CMS or edited locally)
90
+ current.json # Optional theme (pulled from CMS or edited locally)
88
91
  ```
89
92
 
90
93
  ### 6. Footer Content
@@ -130,6 +133,12 @@ content/
130
133
  yoga-class.json # Event with schedule, pricing, venue/category refs
131
134
  ```
132
135
 
136
+ Event registration keeps the semantic `block.event-registration` kind. In the
137
+ fully headless default, register a host-owned `event-registration` override and
138
+ own its markup, accessibility, and styles. Use the public
139
+ `useHeadlessEventRegistrationFlow` controller from `@riverbankcms/sdk/bookings`
140
+ where it fits; controller support varies by functional block.
141
+
133
142
  ---
134
143
 
135
144
  ## Working with Identifiers
@@ -1,6 +1,6 @@
1
1
  # Getting Started with RiverbankCMS SDK
2
2
 
3
- This site uses RiverbankCMS as a headless CMS. Content is managed through the Riverbank CLI.
3
+ This site uses RiverbankCMS as a fully headless CMS. Content is managed through the Riverbank CLI, while the host owns markup, styles, and block rendering.
4
4
 
5
5
  ## Quick Setup
6
6
 
@@ -36,12 +36,10 @@ content/
36
36
  │ └── [content-type].json
37
37
  ├── pages/
38
38
  │ └── [page-identifier].json
39
- ├── themes/
40
- │ └── current.json
41
39
  └── navigation.json
42
40
  ```
43
41
 
44
- You can also pull just the theme:
42
+ Themes are optional. Only add `content/themes/` when this site explicitly opts into CMS/local theme rendering; fully headless sites use the host-owned `SITE_RENDERING` override-only configuration and do not need a theme file. The CLI still supports pulling a theme when you choose that opt-in:
45
43
 
46
44
  ```bash
47
45
  riverbankcms pull theme
@@ -76,11 +74,11 @@ Apply changes to the CMS:
76
74
  riverbankcms push
77
75
  ```
78
76
 
79
- ## Local Theme Iteration (Edge-safe)
77
+ ## Optional Local Theme Iteration (Edge-safe)
80
78
 
81
- If your SDK site uses `createCatchAllPage()`, you can render with local theme objects (and switch themes at runtime) without pushing theme changes to the CMS. See `cli-reference.md` for theme pull/push commands and the SDK README for the `createCatchAllPage({ themes, themeSwitch })` API.
79
+ Fully headless sites do not load CMS themes or SDK runtime styles by default. If a site intentionally opts into themed built-in rendering, `createCatchAllPage()` can render local theme objects (and switch themes at runtime) without pushing theme changes to the CMS. See `cli-reference.md` for the legitimate theme pull/push commands and the SDK README for the `createCatchAllPage({ themes, themeSwitch })` API.
82
80
 
83
- Event registration blocks need both the SDK base stylesheet and a runtime theme scope. Generated SDK pages that render inside `Layout` get `ThemeScope` by default. Standalone `Page` or `Block` usage should wrap registration content in `ThemeBridgeProvider` or manual `generateThemeBridgeCss` with a `data-theme-scope="sdk"` wrapper; keep visual changes in scoped CSS variables instead of forking booking logic.
81
+ Event registration keeps the semantic `block.event-registration` kind, but its UI is host-owned in the fully headless default. Register an `event-registration` override in `src/lib/block-overrides.tsx` and use the public `useHeadlessEventRegistrationFlow` controller from `@riverbankcms/sdk/bookings` where it fits; own the markup, accessibility, and styles in the host. Other functional blocks may have different public controller support, so check their SDK surface rather than assuming a controller exists for every kind.
84
82
 
85
83
  ## Key Documentation
86
84
 
@@ -90,7 +88,7 @@ Event registration blocks need both the SDK base stylesheet and a runtime theme
90
88
  | `content-management.md` | How content is structured |
91
89
  | `schema.md` | This site's content types and blocks (auto-generated) |
92
90
  | `block-types.md` | Available block types (auto-generated) |
93
- | `theme-schema.md` | Theme schema reference (auto-generated from Zod) |
91
+ | `theme-schema.md` | Optional theme schema reference (auto-generated from Zod) |
94
92
  | `workflows/` | Step-by-step guides for common tasks, including editor workflows |
95
93
  | `workflows/agent-safe-sync.md` | Agent-safe dry-run, scoped push, and stale-content handling |
96
94
 
@@ -127,13 +125,13 @@ Additional content configuration for scaffolding.
127
125
 
128
126
  ## Working with Remote/Production
129
127
 
130
- If the remote site, management key, or dashboard user access is not set up yet, start with the safe setup planner:
128
+ If the remote site or project management key is not set up yet, start with the safe setup planner:
131
129
 
132
130
  ```bash
133
131
  riverbankcms setup plan --env=remote
134
132
  ```
135
133
 
136
- See `workflows/remote-setup.md` for the full site/key/user lifecycle. The Riverbank CLI uses site-scoped management keys for sync; remote site creation, key issuance, and user access changes stay in the dashboard/admin surface.
134
+ See `workflows/remote-setup.md` for the full site/key/user lifecycle. The authenticated Riverbank CLI can create a site and link project credentials for the signed-in account. Use the dashboard to grant access to additional users.
137
135
 
138
136
  Use `--env=remote` to target production instead of local:
139
137
 
@@ -2,6 +2,13 @@
2
2
 
3
3
  This workflow guides you through adding a block to an existing page.
4
4
 
5
+ Generated sites use fully headless, override-only rendering by default. Keep
6
+ the built-in semantic kind in CMS content (for example, `block.hero` or
7
+ `block.body-text`), then register the host-owned renderer for every kind the
8
+ site uses in `src/lib/block-overrides.tsx`. The registry uses short semantic
9
+ keys such as `hero`; an unregistered kind raises `MissingBlockOverrideError`
10
+ instead of falling back to a built-in renderer.
11
+
5
12
  ## Prerequisites
6
13
 
7
14
  - Page already exists in the CMS
@@ -25,7 +32,7 @@ View built-in blocks in `block-types.md`. Common block kinds:
25
32
 
26
33
  Check `schema.md` for custom blocks specific to this site.
27
34
 
28
- Prefer built-in blocks before creating a custom block. For a simple policy/terms/about page, use `block.body-text` and put the page title, intro, and section headings in the rich text body. Only create a custom block when the needed structure or behavior cannot be represented by built-in blocks plus styling.
35
+ Prefer built-in blocks before creating a custom block. For a simple policy/terms/about page, use `block.body-text` and put the page title, intro, and section headings in the rich text body. Only create a custom block when the needed structure or behavior cannot be represented by built-in blocks plus a host-owned override or styling.
29
36
 
30
37
  ### 2. List Existing Blocks
31
38
 
@@ -2,6 +2,12 @@
2
2
 
3
3
  Add layout variants and custom fields to built-in system blocks without creating entirely new custom blocks.
4
4
 
5
+ In a fully headless generated site, the CMS kind remains a built-in semantic
6
+ kind such as `block.hero`; the host owns how that kind is rendered. Register
7
+ the host component for the kind in `src/lib/block-overrides.tsx` after adding
8
+ the extension. An extension changes the content contract, not the rendering
9
+ authority.
10
+
5
11
  ## When to Use Block Extensions
6
12
 
7
13
  **Use block extensions when:**
@@ -24,7 +30,7 @@ See `.riverbank/docs/block-types.md` for which system blocks support variants an
24
30
  ## Prerequisites
25
31
 
26
32
  - `riverbank.config.ts` exists
27
- - Block overrides file set up (e.g., `src/lib/block-overrides.tsx`)
33
+ - Host override registry set up (e.g., `src/lib/block-overrides.tsx`)
28
34
  - Understanding of the system block you're extending
29
35
 
30
36
  ## Steps
@@ -103,18 +109,23 @@ export function CustomHero({ content, ...props }: BlockOverrideProps<ExtendedHer
103
109
  }
104
110
  ```
105
111
 
106
- ### Step 3: Register in blockOverrides
112
+ ### Step 3: Register in `blockOverrides`
107
113
 
108
- Add your override component to the block overrides:
114
+ Add your host-owned override component to the typed registration map. The CMS
115
+ content continues to use `block.hero`; `hero` is the corresponding short
116
+ registry key.
109
117
 
110
118
  ```typescript
111
119
  // src/lib/block-overrides.tsx
112
- import type { BlockOverrides } from '@riverbankcms/sdk/rendering';
120
+ import {
121
+ defineBlockOverrideRegistrations,
122
+ type BlockOverrideRegistrations,
123
+ } from '@riverbankcms/sdk/rendering';
113
124
  import { CustomHero } from '@/components/CustomHero';
114
125
 
115
- export const blockOverrides: BlockOverrides = {
126
+ export const blockOverrides = defineBlockOverrideRegistrations({
116
127
  hero: CustomHero,
117
- };
128
+ }) satisfies BlockOverrideRegistrations;
118
129
  ```
119
130
 
120
131
  ### Step 4: Push Config
@@ -323,6 +334,11 @@ blockFieldExtensions: {
323
334
  **Override component:**
324
335
 
325
336
  ```typescript
337
+ import {
338
+ defineBlockOverrideRegistrations,
339
+ type BlockOverrideRegistrations,
340
+ } from '@riverbankcms/sdk/rendering';
341
+
326
342
  type ExtendedHeroContent = HeroContent & {
327
343
  layout?: 'default' | 'topography';
328
344
  topographyColor?: 'teal' | 'green' | 'tan' | 'brown';
@@ -338,9 +354,9 @@ const HeroOverride = (props: BlockOverrideProps<ExtendedHeroContent>) => {
338
354
  return <CustomHeroWithCanvas {...props} />;
339
355
  };
340
356
 
341
- export const blockOverrides: BlockOverrides = {
357
+ export const blockOverrides = defineBlockOverrideRegistrations({
342
358
  hero: HeroOverride,
343
- };
359
+ }) satisfies BlockOverrideRegistrations;
344
360
  ```
345
361
 
346
362
  ## Troubleshooting
@@ -359,7 +375,7 @@ export const blockOverrides: BlockOverrides = {
359
375
 
360
376
  ### Override component not rendering
361
377
 
362
- - Verify the override is registered in `blockOverrides`
378
+ - Verify the host override is registered in `blockOverrides`
363
379
  - Check the key matches the block name (e.g., `hero` for `block.hero`)
364
380
  - Ensure the component is exported correctly
365
381
 
@@ -2,6 +2,11 @@
2
2
 
3
3
  Create a site-specific block with custom fields and rendering when system blocks don't meet your needs.
4
4
 
5
+ Generated sites are fully headless by default: custom block kinds are content
6
+ semantics, while the host owns their markup and styles. Register each custom
7
+ kind in the host override registry; missing registrations fail visibly instead
8
+ of falling back to a CMS renderer.
9
+
5
10
  ## When to Use Custom Blocks
6
11
 
7
12
  Before creating a custom block, check `block-types.md` and the site `schema.md`. Many content needs are already covered by system blocks:
@@ -26,7 +31,7 @@ Do not create a custom block just to get “a rich text area with different spac
26
31
  ## Prerequisites
27
32
 
28
33
  - `riverbank.config.ts` exists
29
- - Block overrides file set up (e.g., `src/lib/block-overrides.tsx`)
34
+ - Host override registry set up (e.g., `src/lib/block-overrides.tsx`)
30
35
  - Understanding of the content structure you need
31
36
 
32
37
  ## Steps
@@ -163,18 +168,40 @@ export function OurFlowBlock({ content }: BlockOverrideProps<OurFlowContent>) {
163
168
  }
164
169
  ```
165
170
 
166
- ### Step 4: Register in blockOverrides
171
+ ### Step 4: Register in `blockOverrides`
167
172
 
168
- Add your component to the block overrides:
173
+ Register the host component with the typed registrations helper. The CMS
174
+ content keeps the semantic `custom.our-flow` kind.
169
175
 
170
176
  ```typescript
171
177
  // src/lib/block-overrides.tsx
172
- import type { BlockOverrides } from '@riverbankcms/sdk/rendering';
178
+ import {
179
+ defineBlockOverrideRegistrations,
180
+ type BlockOverrideRegistrations,
181
+ } from '@riverbankcms/sdk/rendering';
173
182
  import { OurFlowBlock } from '@/components/OurFlowBlock';
174
183
 
175
- export const blockOverrides: BlockOverrides = {
184
+ export const blockOverrides = defineBlockOverrideRegistrations({
176
185
  'custom.our-flow': OurFlowBlock,
177
- };
186
+ }) satisfies BlockOverrideRegistrations;
187
+ ```
188
+
189
+ For client-heavy or rarely used blocks, wrap the dynamic import with
190
+ `defineLazyBlockOverride` so the component is loaded only when its kind is
191
+ rendered:
192
+
193
+ ```typescript
194
+ import {
195
+ defineBlockOverrideRegistrations,
196
+ defineLazyBlockOverride,
197
+ type BlockOverrideRegistrations,
198
+ } from '@riverbankcms/sdk/rendering';
199
+
200
+ export const blockOverrides = defineBlockOverrideRegistrations({
201
+ 'custom.our-flow': defineLazyBlockOverride(async () =>
202
+ import('@/components/OurFlowBlock').then((module) => module.OurFlowBlock),
203
+ ),
204
+ }) satisfies BlockOverrideRegistrations;
178
205
  ```
179
206
 
180
207
  ### Step 5: Push Config
@@ -453,8 +480,8 @@ Pricing cards with nested features and conditional button actions:
453
480
 
454
481
  ### Component not rendering
455
482
 
456
- - Verify override is registered with exact block ID
457
- - Check the key in `blockOverrides` matches (e.g., `'custom.our-flow'`)
483
+ - Verify the host override is registered with the exact block ID
484
+ - Check the key in `blockOverrides` matches the semantic kind (e.g., `'custom.our-flow'`)
458
485
  - Ensure component is exported correctly
459
486
 
460
487
  ### Repeater items not working
@@ -4,6 +4,11 @@
4
4
 
5
5
  Enable dashboard preview editing for an SDK-hosted Next.js site. Preview mode lets the dashboard open the external site with a short-lived editor session, render draft content, and show the Riverbank preview shell.
6
6
 
7
+ The generated fully headless site keeps `SITE_RENDERING` as the rendering
8
+ authority in both the live catch-all route and this preview path. Preserve its
9
+ `overrides-only`/`runtime: none` contract when adding preview behavior: preview
10
+ changes the content/session source, not who owns block markup and styles.
11
+
7
12
  ## Prerequisites
8
13
 
9
14
  - A Riverbank SDK site using the Next.js App Router.
@@ -111,13 +116,20 @@ import {
111
116
  } from '@riverbankcms/sdk/preview-next/client'
112
117
 
113
118
  import { blockOverrides } from '@/lib/block-overrides'
119
+ import { SITE_RENDERING } from '@/lib/rendering'
114
120
 
115
121
  export function SdkPreviewModeClient(
116
122
  props: SdkPreviewModePropsWithoutBlockOverrides
117
123
  ) {
124
+ const { themeRuntime: _themeRuntime, ...previewProps } = props
125
+
118
126
  return (
119
127
  <PreviewQueryProvider>
120
- <SdkPreviewMode {...props} blockOverrides={blockOverrides} />
128
+ <SdkPreviewMode
129
+ {...previewProps}
130
+ rendering={SITE_RENDERING}
131
+ blockOverrides={blockOverrides}
132
+ />
121
133
  </PreviewQueryProvider>
122
134
  )
123
135
  }
@@ -134,11 +146,13 @@ import { createPreviewModeBeforeRender } from '@riverbankcms/sdk/preview-next/be
134
146
  import config from '../../../riverbank.config'
135
147
  import { blockOverrides } from '@/lib/block-overrides'
136
148
  import { getRiverbankClient } from '@/lib/riverbank-client'
149
+ import { SITE_RENDERING } from '@/lib/rendering'
137
150
  import { SdkPreviewModeClient } from '@/components/preview/SdkPreviewModeClient'
138
151
 
139
152
  const { Page, generateMetadata } = createCatchAllPage({
140
153
  getClient: getRiverbankClient,
141
154
  config,
155
+ rendering: SITE_RENDERING,
142
156
  blockOverrides,
143
157
  beforeRender: createPreviewModeBeforeRender({
144
158
  getClient: getRiverbankClient,
@@ -151,9 +165,16 @@ export default Page
151
165
  export { generateMetadata }
152
166
  ```
153
167
 
154
- ## Custom Header/Footer Chrome
168
+ ## Optional Custom Preview Chrome
155
169
 
156
- If your site replaces the SDK header or footer, pass that chrome into `PreviewLayoutProvider` only when there is an editable preview session. `RIVERBANK_PREVIEW_MODE=true` makes the route preview-capable, but `getPreviewSession()` tells you whether the current request actually has preview cookies. Regular visitors without preview cookies should keep the normal SDK `Layout`.
170
+ Fully headless generated sites keep a plain host-owned root layout. If the host
171
+ replaces the preview header or footer, pass that chrome into
172
+ `PreviewLayoutProvider` only when there is an editable preview session.
173
+ `RIVERBANK_PREVIEW_MODE=true` makes the route preview-capable, but
174
+ `getPreviewSession()` tells you whether the current request actually has
175
+ preview cookies. Regular visitors without preview cookies should keep the
176
+ site's normal layout. The `Layout` example below is only for a site that
177
+ intentionally opts into themed SDK rendering.
157
178
 
158
179
  In `src/app/layout.tsx`:
159
180
 
@@ -212,9 +233,12 @@ export default async function RootLayout({
212
233
 
213
234
  If your custom chrome needs CMS navigation data, build the `headerNode` and `footerNode` from the same data used by your normal layout before branching. Calling `getPreviewSession()` in the root layout reads cookies, so the layout becomes dynamic.
214
235
 
215
- ## Import Preview CSS
236
+ ## Import Preview Editor Chrome CSS
216
237
 
217
- For Tailwind sites, add this to `src/app/globals.css`:
238
+ Preview-enabled sites need the SDK preview editor chrome styles even when they
239
+ are fully headless. These imports provide the preview shell and editor chrome;
240
+ they are not the CMS theme or built-in block styles. A Tailwind site can add
241
+ this to `src/app/globals.css`:
218
242
 
219
243
  ```css
220
244
  @import 'tailwindcss';
@@ -222,7 +246,7 @@ For Tailwind sites, add this to `src/app/globals.css`:
222
246
  @import '@riverbankcms/sdk/preview-next/chrome.css';
223
247
  ```
224
248
 
225
- For non-Tailwind sites, use the legacy single import:
249
+ For non-Tailwind sites, use the legacy single preview-chrome import:
226
250
 
227
251
  ```css
228
252
  @import '@riverbankcms/sdk/preview-next/styles.css';
@@ -1,6 +1,9 @@
1
1
  # Remote Site, Key, and User Access Setup
2
2
 
3
- This SDK project can sync content once it has a site ID, dashboard URL, and site-scoped management key. Creating the remote site, issuing keys, and granting dashboard user access are admin operations.
3
+ This SDK project can sync content once it has a site ID, dashboard URL, and
4
+ site-scoped management key. The authenticated Riverbank CLI can create a site
5
+ and link project credentials for the signed-in account. Additional user access
6
+ remains a dashboard operation.
4
7
 
5
8
  ## Check the Plan
6
9
 
@@ -18,18 +21,50 @@ riverbankcms setup plan --env=remote --json
18
21
 
19
22
  ## Authority Model
20
23
 
21
- - Dashboard/admin users can create sites, issue site-scoped management keys, and grant dashboard access.
22
- - Approved CMS repo scripts can do the same when run with service-role/admin credentials.
23
- - SDK management keys can verify access and sync content/config for one site. They cannot create sites, issue new keys, or grant user access.
24
+ - The authenticated Riverbank CLI can create sites and issue project
25
+ credentials for the signed-in account through `sites create`, `link`, and
26
+ `init`.
27
+ - Dashboard administrators can manage sites, issue credentials, and grant
28
+ access to additional users.
29
+ - SDK management keys can verify access and sync content/config for one site.
30
+ They cannot create sites or grant other users access.
24
31
 
25
- Do not put platform-admin, service-role, or user-session credentials in an SDK site repository.
32
+ The CLI stores its refresh session in the OS credential store when available.
33
+ It never puts account sessions, platform-admin credentials, or service-role
34
+ credentials in an SDK site repository.
35
+
36
+ Production account OAuth is deliberately rollout-disabled. Use the staging (or
37
+ local) account environment while that rollout is disabled; replace
38
+ `<account-environment>` with `production` only after production account access
39
+ has been explicitly enabled.
26
40
 
27
41
  ## Remote Setup Lifecycle
28
42
 
29
- 1. Create or choose the remote site from the dashboard/admin surface.
30
- 2. Generate a management key for that site.
31
- 3. Grant the site owner or editor dashboard access from the dashboard/admin surface.
32
- 4. Add the remote SDK variables to `.env.local`:
43
+ 1. Sign in to the account environment:
44
+
45
+ ```bash
46
+ riverbankcms login --account-env=<account-environment>
47
+ ```
48
+
49
+ 2. Create a site or choose one visible to the signed-in account:
50
+
51
+ ```bash
52
+ riverbankcms sites list --account-env=<account-environment>
53
+ riverbankcms sites create --account-env=<account-environment> --name "My Site" --yes
54
+ ```
55
+
56
+ 3. Link the project. `--preview` includes preview routes and a preview
57
+ credential; use `--no-preview` to omit them:
58
+
59
+ ```bash
60
+ riverbankcms link --project . --account-env=<account-environment> --site <site-id> --preview
61
+ ```
62
+
63
+ For a new directory, use `riverbankcms init` instead; it scaffolds, links,
64
+ initializes docs, and builds the complete project.
65
+
66
+ 4. Add the remote SDK variables to `.env.local` when linking an existing
67
+ project manually:
33
68
 
34
69
  ```bash
35
70
  RIVERBANK_REMOTE_SITE_ID=your-site-id
@@ -48,4 +83,25 @@ riverbankcms push --env=remote --dry-run
48
83
 
49
84
  ## Existing Sites and Users
50
85
 
51
- For an existing remote site, copy its site ID and create a fresh site-scoped management key if the old one is missing or should be rotated. Associate existing users with the site through the dashboard/admin surface. If the user does not exist yet, invite or create them through that approved flow rather than through the Riverbank CLI.
86
+ For an existing remote site, use `riverbankcms link` so the CLI issues the
87
+ needed site-scoped credentials and writes only ignored project env files.
88
+ Associate additional users with the site through the dashboard/admin surface.
89
+ If local work fails after the site is created, keep the site and resume with
90
+ the reported `riverbankcms init --resume <directory>` command after fixing the
91
+ local error.
92
+
93
+ ## Post-deployment revalidation
94
+
95
+ `init` scaffolds `/api/revalidate` but does not register a webhook or write a
96
+ webhook secret. Once the deployed site has a public HTTPS origin, activate
97
+ revalidation explicitly:
98
+
99
+ ```bash
100
+ riverbankcms webhooks setup \
101
+ --env=remote \
102
+ --url=https://www.example.com/api/revalidate \
103
+ --yes
104
+ ```
105
+
106
+ Until then, the generated site’s ISR interval is the freshness fallback. Keep
107
+ the one-time webhook secret in the deployment environment, not source control.
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { a as classifySdkEventPricing, i as classifySdkEventSchedule, o as classifySdkEventPaymentTerms, r as sdkEventUpsertOptionalFieldSchemas } from "./sdk-event-upsert-CTqsrhFT.mjs";
2
+ import { a as classifySdkEventPricing, i as classifySdkEventSchedule, o as classifySdkEventPaymentTerms, r as sdkEventUpsertOptionalFieldSchemas } from "./sdk-event-upsert-BCZUdIrL.mjs";
3
3
  import { z } from "zod";
4
4
 
5
5
  //#region ../blocks/src/lib/typeGuards.ts
@@ -2044,21 +2044,21 @@ const EVENT_CONTENT_TYPE_SCHEMA = {
2044
2044
  {
2045
2045
  id: "summary",
2046
2046
  type: "textarea",
2047
- label: "Summary",
2048
- description: "Short teaser shown in listings.",
2047
+ label: "Short introduction",
2048
+ description: "Write one or two sentences that help people quickly understand what this is. It appears wherever the event is listed and near the top of its page.",
2049
2049
  rows: 3
2050
2050
  },
2051
2051
  {
2052
2052
  id: "image",
2053
2053
  type: "media",
2054
- label: "Listing image",
2055
- description: "Optional image used for event cards and previews."
2054
+ label: "Event image",
2055
+ description: "Choose the main image people will see wherever the event is listed and on its page."
2056
2056
  },
2057
2057
  {
2058
2058
  id: "body",
2059
2059
  type: "richText",
2060
- label: "Details",
2061
- description: "Full event details and agenda."
2060
+ label: "About this event",
2061
+ description: "Add the main information people need before booking—what to expect, who it’s for, what’s included, and anything they should bring or know."
2062
2062
  }
2063
2063
  ],
2064
2064
  routing: {
@@ -4917,6 +4917,7 @@ const eventUpsertInputSchema = z.object({
4917
4917
  "event",
4918
4918
  "class",
4919
4919
  "course",
4920
+ "term",
4920
4921
  "workshop",
4921
4922
  "retreat",
4922
4923
  "performance"
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+ import "./sdk-peer-DiZYsNXj.mjs";
3
+ import { t as loadConfigFile } from "./load-config-Boa0tkmk.mjs";
4
+
5
+ export { loadConfigFile };