create-prenta 1.3.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/CHANGELOG.md +964 -0
- package/LICENSE +21 -0
- package/assets/prisma/migrations/0001_init/migration.sql +941 -0
- package/assets/prisma/migrations/0002_media_usage_field_path/migration.sql +11 -0
- package/assets/prisma/migrations/0003_ai_crawler_hits/migration.sql +21 -0
- package/assets/prisma/migrations/0004_drop_search_vector/migration.sql +4 -0
- package/assets/prisma/migrations/0005_script_tag_delivery_controls/migration.sql +8 -0
- package/assets/prisma/migrations/0006_totp_last_step/migration.sql +4 -0
- package/assets/prisma/migrations/0007_workflow_fk_drop_dead_enums/migration.sql +27 -0
- package/assets/prisma/migrations/0008_form_delivery_attempts/migration.sql +29 -0
- package/assets/prisma/migrations/0009_webhook_secret_rotation/migration.sql +6 -0
- package/assets/prisma/migrations/0010_media_is_decorative/migration.sql +3 -0
- package/assets/prisma/migrations/0011_media_content_hash/migration.sql +4 -0
- package/assets/prisma/migrations/0012_rename_to_prenta/migration.sql +89 -0
- package/assets/prisma/migrations/migration_lock.toml +3 -0
- package/assets/prisma/schema.prisma +989 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +182 -0
- package/dist/index.js.map +1 -0
- package/dist/options.d.ts +160 -0
- package/dist/options.d.ts.map +1 -0
- package/dist/options.js +206 -0
- package/dist/options.js.map +1 -0
- package/dist/scaffold.d.ts +45 -0
- package/dist/scaffold.d.ts.map +1 -0
- package/dist/scaffold.js +2163 -0
- package/dist/scaffold.js.map +1 -0
- package/dist/templates/admin-page.ts.template.d.ts +24 -0
- package/dist/templates/admin-page.ts.template.d.ts.map +1 -0
- package/dist/templates/admin-page.ts.template.js +145 -0
- package/dist/templates/admin-page.ts.template.js.map +1 -0
- package/dist/templates/astro-site.d.ts +36 -0
- package/dist/templates/astro-site.d.ts.map +1 -0
- package/dist/templates/astro-site.js +918 -0
- package/dist/templates/astro-site.js.map +1 -0
- package/dist/templates/login-page.ts.template.d.ts +14 -0
- package/dist/templates/login-page.ts.template.d.ts.map +1 -0
- package/dist/templates/login-page.ts.template.js +143 -0
- package/dist/templates/login-page.ts.template.js.map +1 -0
- package/dist/templates/marketing-custom.d.ts +56 -0
- package/dist/templates/marketing-custom.d.ts.map +1 -0
- package/dist/templates/marketing-custom.js +814 -0
- package/dist/templates/marketing-custom.js.map +1 -0
- package/dist/templates/prenta.config.ts.template.d.ts +3 -0
- package/dist/templates/prenta.config.ts.template.d.ts.map +1 -0
- package/dist/templates/prenta.config.ts.template.js +253 -0
- package/dist/templates/prenta.config.ts.template.js.map +1 -0
- package/package.json +58 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,964 @@
|
|
|
1
|
+
# create-actuate-cms
|
|
2
|
+
|
|
3
|
+
## 1.3.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 5eea995: Product rename: ActuateCMS is now **Prenta**. Every package moves from the
|
|
8
|
+
`@actuate-media/*` scope to `@prenta/*` with simplified names (`@prenta/core`,
|
|
9
|
+
`@prenta/admin`, `create-prenta`), and version numbers continue from where the
|
|
10
|
+
old scope left off.
|
|
11
|
+
|
|
12
|
+
This is a clean break — no backwards-compat aliases:
|
|
13
|
+
- **npm packages**: `@actuate-media/cms-core` → `@prenta/core`,
|
|
14
|
+
`@actuate-media/cms-admin` → `@prenta/admin`, all other packages keep their
|
|
15
|
+
suffix under `@prenta/*`. `create-actuate-cms` → `create-prenta`
|
|
16
|
+
(`npm create prenta`), `create-actuate-astro` → `create-prenta-astro`.
|
|
17
|
+
CLI bins: `actuate`/`actuate-cms` → `prenta`/`prenta-cms`; `actuate-mcp` →
|
|
18
|
+
`prenta-mcp`.
|
|
19
|
+
- **Database**: migration `0012_rename_to_prenta` renames all 36 `actuate_*`
|
|
20
|
+
tables to `prenta_*` in place (plus prefixed constraints, indexes, and
|
|
21
|
+
sequences). Run `prisma migrate deploy` when upgrading.
|
|
22
|
+
- **Runtime identifiers**: `getActuateConfig` → `getPrentaConfig`,
|
|
23
|
+
`handleActuateAPI` → `handlePrentaAPI`, `ActuateClient` → `PrentaClient`,
|
|
24
|
+
`ActuateDB` → `PrentaDB`, config file `actuate.config.ts` →
|
|
25
|
+
`prenta.config.ts`, CSS scopes `.actuate-admin`/`.actuate-canvas` →
|
|
26
|
+
`.prenta-admin`/`.prenta-canvas`, preview protocol `actuate-preview:*` →
|
|
27
|
+
`prenta-preview:*`, webhook headers `X-Actuate-*` → `X-Prenta-*`, session
|
|
28
|
+
cookie `actuate_session` → `prenta_session`, env vars `ACTUATE_*` →
|
|
29
|
+
`PRENTA_*`, purge route `/api/actuate/purge` → `/api/prenta/purge`.
|
|
30
|
+
- **Sessions and webhooks**: all sessions reset on upgrade (cookie + JWT issuer
|
|
31
|
+
changed); webhook consumers must re-verify signatures against the new
|
|
32
|
+
`X-Prenta-*` headers.
|
|
33
|
+
|
|
34
|
+
The old `@actuate-media/*` packages are deprecated on npm and will receive no
|
|
35
|
+
further releases.
|
|
36
|
+
|
|
37
|
+
## 1.2.4
|
|
38
|
+
|
|
39
|
+
### Patch Changes
|
|
40
|
+
|
|
41
|
+
- 6ff80a6: Add `@actuate-media/sections-react/testing` (`assertSectionRenderParity`, canvas render options) and wire an Astro-split starter `test:parity` gate so canvas and public orchestrators can't drift into a WYSIWYG lie.
|
|
42
|
+
|
|
43
|
+
## 1.2.3
|
|
44
|
+
|
|
45
|
+
### Patch Changes
|
|
46
|
+
|
|
47
|
+
- 73854fc: Add `siteIdentityJsonLd*` / `jsonLdHasOrganization` so any page can emit resolvable WebSite + Organization JSON-LD (fixes dangling `#organization` @ids). Add `assertServingOriginConfigured` ops guard (Launch Gate E) and wire it into the Astro starter middleware + CMS API route boot; BaseLayout falls back to site-identity JSON-LD when page meta lacks Organization.
|
|
48
|
+
|
|
49
|
+
## 1.2.2
|
|
50
|
+
|
|
51
|
+
### Patch Changes
|
|
52
|
+
|
|
53
|
+
- 576f076: Fix `blogPostCollection` archivePath footgun: deriving with a new slug/urlPrefix rebases `seo.archivePath` onto the urlPrefix unless set explicitly; `defineConfig` warns on duplicate archive paths. Astro starter/example: hybrid prerender defaults (`404.astro` prerendered; CMS catch-all / home / blog index explicit `prerender = false`).
|
|
54
|
+
|
|
55
|
+
## 1.2.1
|
|
56
|
+
|
|
57
|
+
### Patch Changes
|
|
58
|
+
|
|
59
|
+
- dfffe08: Add `publicPageCacheControl()` on `@actuate-media/cms-core/astro/cache` (ADR 0011 cache-static defaults: 1h s-maxage / 24h SWR; preview → `private, no-store`) and wire the Astro starter + example site to use it instead of hardcoded Cache-Control strings. Purge remains path/URL-based per ADR 0011.
|
|
60
|
+
|
|
61
|
+
## 1.2.0
|
|
62
|
+
|
|
63
|
+
### Minor Changes
|
|
64
|
+
|
|
65
|
+
- cf97a40: Launch-critical Astro SEO + freshness: `documentPublicPath` / `rewritePublicOrigin`, first-class `AstroPageMeta.robots`, admin/MCP path builders (#739), Yoast child sitemap + XSL proxies with origin rewrite, production purge 503 without CDN credentials, globals purge webhooks, and Launch Gate docs.
|
|
66
|
+
|
|
67
|
+
## 1.1.0
|
|
68
|
+
|
|
69
|
+
### Minor Changes
|
|
70
|
+
|
|
71
|
+
- 7230d21: Scaffolded Astro public sites (`astro-split` workspaces and `--framework astro-site`) now pin Astro 7 (`astro@^7.1`, `@astrojs/vercel@^11`, `@astrojs/react@^6`). This picks up the fixes for three Astro XSS advisories (GHSA-f48w-9m4c-m7f5, GHSA-7pw4-f3q4-r2p2, GHSA-4g3v-8h47-v7g6). No template API changes: `output: 'server'`, the Vercel adapter, middleware, live content collections, and the purge webhook route all work unchanged on Astro 7. Node.js requirement stays 22.12+.
|
|
72
|
+
|
|
73
|
+
## 1.0.0
|
|
74
|
+
|
|
75
|
+
### Major Changes
|
|
76
|
+
|
|
77
|
+
- 90f9801: Astro-first scaffolding: `astro-split` is now the default framework and emits a pnpm workspace instead of a nested `site/` folder.
|
|
78
|
+
|
|
79
|
+
**create-actuate-cms (breaking)**
|
|
80
|
+
- Default framework flipped from `next` to `astro-split`. `npm create actuate-cms` now scaffolds a pnpm workspace — Next CMS host in `apps/cms`, Astro public site in `apps/site` — instead of a Next monolith. Pass `--framework next` for the classic monolith (unchanged output).
|
|
81
|
+
- The `astro-split` layout changed from a root Next app with a nested `site/` Astro app to a proper workspace (`pnpm-workspace.yaml`, delegating root scripts, `packageManager: pnpm`). Re-running the scaffolder over an old layout is not supported.
|
|
82
|
+
- `astro-split` + `marketing-custom` (the default template) now compose: the section kit lands in `packages/sections` and all three layers are wired from it — `apps/cms/actuate.config.ts` imports the schema, the admin page imports `sectionRenderers` (via `transpilePackages`), and the Astro site registers the same renderer map. `verify:sections` runs from the root, both apps, and CI.
|
|
83
|
+
- Same-apex routing is now the default: `apps/site/vercel.json` ships rewrites for `/api/cms/*` and the admin/login paths to the CMS host (`CMS_HOST_ORIGIN` placeholder) instead of an opt-in `vercel.preview-proxy.example.json`.
|
|
84
|
+
- The Astro site template ships cache-static delivery: `Cache-Control: public, s-maxage=3600, stale-while-revalidate=86400` on published pages, a `/api/actuate/purge` webhook endpoint built on `createPublishPurgeReceiver` (Cloudflare / Vercel adapters selected by env), and an optional Upstash layer-2 cache that the purge endpoint drains.
|
|
85
|
+
- `ASTRO.md` documents the workspace flow, production routing, and the purge webhook setup (Settings → Webhooks).
|
|
86
|
+
|
|
87
|
+
**create-actuate-astro**
|
|
88
|
+
- `--split` now scaffolds the pnpm workspace (`apps/cms` + `apps/site` + `packages/sections` with the designed-sections standard template). Site-only mode (the default) is unchanged.
|
|
89
|
+
|
|
90
|
+
## 0.33.2
|
|
91
|
+
|
|
92
|
+
### Patch Changes
|
|
93
|
+
|
|
94
|
+
- 56c1309: Fix page tag saves silently no-oping when `tags` / `primaryTag` were undeclared (passthrough + scaffold `page-tags` collection), and replace the status-token tag palette with distinct `--tag-*` colors so pink is no longer warning orange.
|
|
95
|
+
|
|
96
|
+
## 0.33.1
|
|
97
|
+
|
|
98
|
+
### Patch Changes
|
|
99
|
+
|
|
100
|
+
- f4766d4: Bump `sharp` to `^0.35.0` so consumers inherit the patched libvips line (GHSA-f88m-g3jw-g9cj) instead of resolving `0.34.5` from the previous pin.
|
|
101
|
+
|
|
102
|
+
## 0.33.0
|
|
103
|
+
|
|
104
|
+
### Minor Changes
|
|
105
|
+
|
|
106
|
+
- c72bd83: Make **Standard (designed sections)** (`marketing-custom`) the default scaffold template so new projects ship schema + shared admin/public section renderers + seed/verify by default. Minimal built-ins-only kits remain available via `--template default`.
|
|
107
|
+
|
|
108
|
+
## 0.32.2
|
|
109
|
+
|
|
110
|
+
### Patch Changes
|
|
111
|
+
|
|
112
|
+
- f676bcc: Resolve View live / View Site from the effective public site URL (`GET /site/public-url`, DB SEO overrides first), warn when that URL matches the CMS admin host, unlock Settings → General site URL overrides for split deploys, and default Astro-split `NEXT_PUBLIC_SITE_URL` to the Astro apex.
|
|
113
|
+
|
|
114
|
+
## 0.32.1
|
|
115
|
+
|
|
116
|
+
### Patch Changes
|
|
117
|
+
|
|
118
|
+
- 3d1a79f: Timestamp-bound HMAC webhook signing with skew/replay verification (`verifyActuateWebhook`), delivery-id headers on form webhooks, publish secret reveal + 24h rotation grace, and consumer verification docs (#679).
|
|
119
|
+
|
|
120
|
+
## 0.32.0
|
|
121
|
+
|
|
122
|
+
### Minor Changes
|
|
123
|
+
|
|
124
|
+
- 58f3ca1: Split-deploy hardening: denormalize media IDs on document write, regenerate JSON-LD on published updates, include Organization parent for Corporation/OnlineBusiness subtypes, and ship Astro security-headers middleware matching Next baselines.
|
|
125
|
+
|
|
126
|
+
## 0.31.0
|
|
127
|
+
|
|
128
|
+
### Minor Changes
|
|
129
|
+
|
|
130
|
+
- cc6ad93: Split-deploy SEO redirects: ship `applyPublicRedirect` / `createAstroRedirectMiddleware`, wire Astro starters and Next scaffold to the shared engine, clarify Never hit vs Stale, and return 409 on duplicate source updates.
|
|
131
|
+
|
|
132
|
+
## 0.30.1
|
|
133
|
+
|
|
134
|
+
### Patch Changes
|
|
135
|
+
|
|
136
|
+
- b6945e3: Astro starter: the scaffolded `BaseLayout.astro` now renders the full composed head from `/resolve` — Open Graph tags, `twitter:card`, a robots meta tag (including the forced `noindex` in preview mode), and hreflang alternate links — via a single `meta` prop (`AstroPageMeta` from `toPageMeta()`), and injects JSON-LD with `<Fragment set:html>` instead of an invalid `<div>` inside `<head>`. Static pages can still pass plain `title` / `description` / `canonical` props. `examples/astro-site` re-synced from the template.
|
|
137
|
+
|
|
138
|
+
## 0.30.0
|
|
139
|
+
|
|
140
|
+
### Minor Changes
|
|
141
|
+
|
|
142
|
+
- c6b006c: Astro discoverability and best practices: `create-actuate-astro` + `--framework astro-site`, Live Content Collections loader (`@actuate-media/cms-core/astro/content`), islands/preview docs, and fleet first-cutover runbook.
|
|
143
|
+
|
|
144
|
+
## 0.29.1
|
|
145
|
+
|
|
146
|
+
### Patch Changes
|
|
147
|
+
|
|
148
|
+
- fe3e76c: Astro public-site starter and `--framework astro-split` `site/` template now pin Astro 6 (`astro@^6.4`, `@astrojs/vercel@^10`, `@astrojs/react@^5`) and require Node.js 22.12+.
|
|
149
|
+
|
|
150
|
+
## 0.29.0
|
|
151
|
+
|
|
152
|
+
### Minor Changes
|
|
153
|
+
|
|
154
|
+
- fb89234: Add `--framework next|astro-split` (default `next`). `astro-split` scaffolds a Next CMS host (admin + API, no public catch-all) plus an Astro public site under `site/` that uses `createAstroSiteHelpers`, sections-react, and SEO proxies. Also ships `examples/astro-site` as the reference starter.
|
|
155
|
+
|
|
156
|
+
## 0.28.14
|
|
157
|
+
|
|
158
|
+
### Patch Changes
|
|
159
|
+
|
|
160
|
+
- fdfae4c: Include `graphql` + `graphql-yoga` in generated projects.
|
|
161
|
+
|
|
162
|
+
cms-core made these optional peer dependencies (Tier 2), so scaffolded apps now
|
|
163
|
+
declare them directly to keep the `/api/cms/graphql` endpoint working out of the
|
|
164
|
+
box — the same pattern already used for `sharp` and `@vercel/blob`. Remove both
|
|
165
|
+
from `package.json` if you only use the REST API.
|
|
166
|
+
|
|
167
|
+
## 0.28.13
|
|
168
|
+
|
|
169
|
+
### Patch Changes
|
|
170
|
+
|
|
171
|
+
- da73f45: Drop the broken `lint` script from scaffolded projects.
|
|
172
|
+
|
|
173
|
+
The scaffolder emitted `"lint": "next lint"` while pinning Next ^16 — but Next 16
|
|
174
|
+
removed the `next lint` subcommand, and the generated project ships no ESLint
|
|
175
|
+
config or `eslint-config-next` dependency, so `npm run lint` errored on a fresh
|
|
176
|
+
install. Removed the script (consumers can add ESLint themselves).
|
|
177
|
+
|
|
178
|
+
(Companion docs fix in the same PR: the "Add to Existing Project" guide now
|
|
179
|
+
installs `@vercel/blob` and `sharp` for Vercel media uploads — `@vercel/blob` is
|
|
180
|
+
a dynamically-imported optional peer whose absence 500s the first upload.)
|
|
181
|
+
|
|
182
|
+
## 0.28.12
|
|
183
|
+
|
|
184
|
+
### Patch Changes
|
|
185
|
+
|
|
186
|
+
- 95ea95a: Ship an `actuate-add-section` agent skill in the `marketing-custom` scaffold.
|
|
187
|
+
|
|
188
|
+
New projects get `.cursor/skills/actuate-add-section/SKILL.md` — a prescriptive
|
|
189
|
+
contract that turns a designed section into an editable Actuate section (schema
|
|
190
|
+
in `types.ts` + renderer in `register.tsx`, plus optional block + seed), kept in
|
|
191
|
+
sync. When you ask an agent (Cursor, Claude, …) to "make this section editable"
|
|
192
|
+
in the kit, it follows the contract instead of re-deriving it — so a design
|
|
193
|
+
becomes an editable CMS section without hand-wiring. The skill documents the
|
|
194
|
+
exact field types, the `section.content` renderer pattern, a design→schema
|
|
195
|
+
mapping, and a verify checklist. SECTIONS.md and the Design-First Playbook doc
|
|
196
|
+
reference it.
|
|
197
|
+
|
|
198
|
+
## 0.28.11
|
|
199
|
+
|
|
200
|
+
### Patch Changes
|
|
201
|
+
|
|
202
|
+
- cb94bf0: Simplify custom-section authoring in the `marketing-custom` template.
|
|
203
|
+
|
|
204
|
+
A custom section used to be four hand-synced artifacts: a block component, a
|
|
205
|
+
schema entry, a public `register.tsx` renderer, and a separate
|
|
206
|
+
`admin-renderers.tsx` canvas renderer. The public renderer also had a latent bug
|
|
207
|
+
(it destructured a non-existent `content` prop instead of `section.content`).
|
|
208
|
+
|
|
209
|
+
Now a section is just its schema (`types.ts`) plus ONE renderer map
|
|
210
|
+
(`register.tsx`) — a single `sectionRenderers` object, typed as
|
|
211
|
+
`AdminSectionRendererMap`, that drives BOTH the public site and the admin editor
|
|
212
|
+
canvas (the two renderer signatures are structural mirrors, so one component
|
|
213
|
+
serves both; the admin map type is assignable to the public one for
|
|
214
|
+
registration). The separate `admin-renderers.tsx` file and its wiring are gone;
|
|
215
|
+
`verify:sections` and `SECTIONS.md` are updated to match.
|
|
216
|
+
|
|
217
|
+
Also adds a **Design-First Playbook** doc: a repeatable "design → editable CMS
|
|
218
|
+
pages" recipe (Design Inventory → schema + renderer → seed → verify).
|
|
219
|
+
|
|
220
|
+
## 0.28.10
|
|
221
|
+
|
|
222
|
+
### Patch Changes
|
|
223
|
+
|
|
224
|
+
- 4421c32: Fix media upload 500 ("Cannot find package 'sharp'") on Vercel.
|
|
225
|
+
|
|
226
|
+
cms-core optimizes uploaded images with `sharp` and marks it a Next
|
|
227
|
+
`serverExternalPackage` (a native module can't be bundled). Because it's also
|
|
228
|
+
dynamically imported (`import(/* webpackIgnore */ 'sharp')`), Next never traces
|
|
229
|
+
it — so unless the app depends on `sharp` directly, Vercel omits it from the
|
|
230
|
+
function bundle and every image upload 500s.
|
|
231
|
+
|
|
232
|
+
Two fixes:
|
|
233
|
+
- `create-actuate-cms` now adds `sharp` to the generated `package.json`
|
|
234
|
+
dependencies (like it already does for `@vercel/blob`), so scaffolded sites
|
|
235
|
+
bundle it.
|
|
236
|
+
- The `/media/upload` handler now degrades gracefully: if optimization throws
|
|
237
|
+
(e.g. sharp is missing), it stores the original image and logs a warning
|
|
238
|
+
instead of returning a 500. Uploads succeed; add `sharp` to re-enable
|
|
239
|
+
webp/resize/blur-placeholder.
|
|
240
|
+
|
|
241
|
+
Existing sites hit by this: `npm install sharp` and redeploy.
|
|
242
|
+
|
|
243
|
+
## 0.28.9
|
|
244
|
+
|
|
245
|
+
### Patch Changes
|
|
246
|
+
|
|
247
|
+
- f283357: Implement the AWS platform adapter (`aws()`) at parity with `vercel()`.
|
|
248
|
+
|
|
249
|
+
`@actuate-media/platform-aws` previously threw "not yet implemented" — which
|
|
250
|
+
also meant scaffolded `--platform aws` sites had **no working media storage**
|
|
251
|
+
(`storage: { provider: 's3' }` auto-wires to `aws().storage`). All six adapters
|
|
252
|
+
are now implemented:
|
|
253
|
+
- **Storage** — S3 (`@aws-sdk/client-s3`) with presigned URLs
|
|
254
|
+
(`@aws-sdk/s3-request-presigner`) and CloudFront-aware public URLs. Reads
|
|
255
|
+
`AWS_S3_BUCKET` / `AWS_REGION` (plus the scaffolder's `S3_*` fallback names);
|
|
256
|
+
credentials come from the task/instance IAM role by default.
|
|
257
|
+
- **Database** — RDS/Aurora Postgres via a real `pg` connection pool.
|
|
258
|
+
- **Cache** — ElastiCache (Redis/Valkey) via `ioredis`, with an in-memory
|
|
259
|
+
fallback; tag invalidation delegates to `next/cache`.
|
|
260
|
+
- **Email** — SES (`@aws-sdk/client-ses`), honoring reply-to/from.
|
|
261
|
+
- **Scheduler** — EventBridge Scheduler guidance + `generateEventBridgeConfig()`
|
|
262
|
+
/ `toEventBridgeCron()` helpers (standard 5-field → EventBridge 6-field).
|
|
263
|
+
- **Rate limit** — Redis sliding-window log (ZADD/ZREMRANGEBYSCORE/ZCARD) with
|
|
264
|
+
an in-memory fallback.
|
|
265
|
+
|
|
266
|
+
Every AWS SDK is an optional peer dependency, dynamically imported on first use,
|
|
267
|
+
so installing the package pulls in nothing until an adapter runs.
|
|
268
|
+
|
|
269
|
+
The `create-actuate-cms` scaffolder now emits AWS-standard env var names
|
|
270
|
+
(`AWS_S3_BUCKET`, `AWS_REGION`, optional `AWS_S3_PUBLIC_URL`) for `--platform aws`
|
|
271
|
+
and enriches the generated AWS deployment guide (S3 IAM, EventBridge cron).
|
|
272
|
+
|
|
273
|
+
## 0.28.8
|
|
274
|
+
|
|
275
|
+
### Patch Changes
|
|
276
|
+
|
|
277
|
+
- cc18833: SEO audit remediation — 47 verified fixes across the SEO system.
|
|
278
|
+
|
|
279
|
+
Highlights: redirect middleware no longer excludes legacy `.html/.php/.aspx`
|
|
280
|
+
URLs (migrations); robots.txt now `Allow`s the default OG image (`/api/cms/og.png`)
|
|
281
|
+
so social shares render; RSS always emits the mandatory channel `<description>`;
|
|
282
|
+
structured-data auto-detection no longer emits invalid `Review/Event/JobPosting`
|
|
283
|
+
(required fields enforced or the node is suppressed) and no longer mis-types
|
|
284
|
+
collections by substring (`newsletters`→NewsArticle etc.); the sitemap endpoint
|
|
285
|
+
no longer selects full document JSON for up to 45k rows; IndexNow submits on
|
|
286
|
+
every publish instead of being swallowed by the sitemap debounce; the exported
|
|
287
|
+
`renderJsonLdScript()` now escapes `<`; the editor no longer shows two
|
|
288
|
+
conflicting scores and the Content-tab analysis now understands section-built
|
|
289
|
+
pages; plus pagination `rel`/canonical, `og:locale` normalization + alternates,
|
|
290
|
+
canonical absolutization, VideoObject/Product/WebSite-SearchAction builders,
|
|
291
|
+
redirect loop/case handling, plugin-seo sitemap caps + real `lastmod`, and
|
|
292
|
+
plugin link-health routed through `safeFetch`. Adds several new exports on
|
|
293
|
+
`@actuate-media/cms-core` (e.g. `buildVideoObjectSchema`, `buildProductSchema`).
|
|
294
|
+
|
|
295
|
+
## 0.28.7
|
|
296
|
+
|
|
297
|
+
### Patch Changes
|
|
298
|
+
|
|
299
|
+
- d6665dd: Fix the consumer build produced by `npm create actuate-cms`. Scaffolded projects
|
|
300
|
+
now ship an `.npmrc` with `node-linker=hoisted` so Next.js/Turbopack can resolve
|
|
301
|
+
the published packages' transitive dependencies (Radix/TipTap internals) during
|
|
302
|
+
`next build` — previously a default `pnpm install` failed with "Module not found"
|
|
303
|
+
for packages like `@radix-ui/react-use-controllable-state`. Also fixes the
|
|
304
|
+
generated `actuate.config.ts` to use the media plugin's `allowedTypes` option
|
|
305
|
+
(was the non-existent `allowedMimeTypes`, which failed type-check on build).
|
|
306
|
+
- 041a228: Scaffolded projects no longer migrate the production database from preview
|
|
307
|
+
deploys. The build command now runs `prisma migrate deploy` through
|
|
308
|
+
`scripts/deploy-migrate.mjs`, which applies migrations only on Vercel
|
|
309
|
+
**production** builds (`VERCEL_ENV=production`) — or when `ALLOW_MIGRATE_DEPLOY=true`
|
|
310
|
+
is set explicitly against an isolated preview database. Previously every build
|
|
311
|
+
(including preview deploys from unmerged PRs) ran a bare `prisma migrate deploy`
|
|
312
|
+
against the configured database.
|
|
313
|
+
|
|
314
|
+
## 0.28.6
|
|
315
|
+
|
|
316
|
+
### Patch Changes
|
|
317
|
+
|
|
318
|
+
- 4afb589: Fix accent color not applying when AdminRoot is wrapped in an outer `.actuate-admin` by targeting the marked admin shell root for theme overrides, and remove the duplicate wrapper from the scaffold admin page template.
|
|
319
|
+
- 4afb589: Add legitimacy-gated 404 redirect recovery: wire public 404 logging, filter probe URLs before suggesting redirects, connect broken internal links to the SEO audit approve flow, and seed suggestions during audits.
|
|
320
|
+
|
|
321
|
+
## 0.28.5
|
|
322
|
+
|
|
323
|
+
### Patch Changes
|
|
324
|
+
|
|
325
|
+
- 163ae1d: Design parity phase 3 (wave 1): split-pane editors, Script Tag delivery controls, Media SEO Audit, Pages tree view, and Dashboard onboarding.
|
|
326
|
+
|
|
327
|
+
**cms-core**
|
|
328
|
+
- `ScriptTag` gains `loadAsync`, `disableInPreview` (default on), and `consentCategory` fields (migration `0005_script_tag_delivery_controls`), accepted and validated on the script-tag API routes.
|
|
329
|
+
- `resolveScriptTagsForPath` accepts `{ preview }` and skips preview-disabled tags; the public `GET /script-tags/resolve` endpoint supports `?preview=1`. `loadAsync` injects `async` into external scripts, and consent-gated tags are wrapped in a bootstrap that waits for the consent plugin's "accept all" before injecting. The resolved response shape is unchanged.
|
|
330
|
+
- `ScriptTagGroup` now preserves `async`/`defer` attributes on external scripts.
|
|
331
|
+
- `GET /media` items include server-derived `seoScore`, `seoGrade`, and `seoIssues` (from `calculateMediaSeoScore`), and `PUT /media/:id` accepts `caption`, `description`, and `focusKeyword`.
|
|
332
|
+
|
|
333
|
+
**cms-admin**
|
|
334
|
+
- New `SplitPaneLayout` / `InspectorPane` primitives implementing the design's inline editor-pane pattern; Script Tags is converted to a split-pane view with placement tiles, priority stepper, scope tiles, consent category grid, and Load async / Disable in preview toggles.
|
|
335
|
+
- Media gains a Library / SEO Audit tab bar with summary cards, filter pills, an audit table with score bars, and an Edit flow into the library detail panel (which now edits caption, description, and focus keyword).
|
|
336
|
+
- Pages gains a List / Tree view toggle: hierarchy from `parentPageId` with path-prefix fallback, expand/collapse rows, template pills, and an "Add sub-page" action that preselects the parent (also editable via a new Parent page picker in Page settings).
|
|
337
|
+
- The Dashboard shows a getting-started onboarding block (derived 6-step checklist + quick links) in place of the activity grid while the site has no content or media.
|
|
338
|
+
|
|
339
|
+
**create-actuate-cms**
|
|
340
|
+
- Scaffolded middleware flags `?preview=` requests and the site layout resolves script tags with `preview: true` (uncached) so tags marked "disable in preview" never fire during CMS preview; Prisma assets mirror the new migration.
|
|
341
|
+
|
|
342
|
+
## 0.28.4
|
|
343
|
+
|
|
344
|
+
### Patch Changes
|
|
345
|
+
|
|
346
|
+
- 685958f: Correct 0.x upgrade guidance: document that npm update only applies patches within the pinned minor; use `actuate upgrade` for minor bumps. Admin Updates panel and update server now show the full upgrade command chain.
|
|
347
|
+
|
|
348
|
+
Clarify scaffold README populate/script-tag and upgrade steps.
|
|
349
|
+
|
|
350
|
+
## 0.28.3
|
|
351
|
+
|
|
352
|
+
### Patch Changes
|
|
353
|
+
|
|
354
|
+
- 1a21341: Clarify scaffold README: `actuate populate` does not seed Script Tags; use admin or a custom insert-if-missing script.
|
|
355
|
+
|
|
356
|
+
## 0.28.2
|
|
357
|
+
|
|
358
|
+
### Patch Changes
|
|
359
|
+
|
|
360
|
+
- 6d254f3: Fix Script Tags delivery and admin toggles: green/red enabled switches with optimistic saves, in-process resolve + executable script rendering in scaffold layouts, pathname header for scoped tags, and cache invalidation on tag writes.
|
|
361
|
+
|
|
362
|
+
## 0.28.1
|
|
363
|
+
|
|
364
|
+
### Patch Changes
|
|
365
|
+
|
|
366
|
+
- 1a3cf91: Agent-ready public forms (WebMCP): declarative tool metadata on public form schemas, zero-JS `renderPublicFormHtml` / `ActuateFormHtml`, urlencoded submit parsing, HTML confirmation responses, scaffold form prefetch, `actuate doctor` check, and docs.
|
|
367
|
+
|
|
368
|
+
## 0.28.0
|
|
369
|
+
|
|
370
|
+
### Minor Changes
|
|
371
|
+
|
|
372
|
+
- a6360cc: Forms launch kit (Batch 7): Integrations tab with Zapier Catch Hook helper and webhook CRUD in the form schema drawer; marketing seed contact form + /contact page; ActuateForm success focus; actuate doctor forms/CRM checks; forms-and-integrations docs.
|
|
373
|
+
|
|
374
|
+
## 0.27.0
|
|
375
|
+
|
|
376
|
+
### Minor Changes
|
|
377
|
+
|
|
378
|
+
- a59a501: Batch 6 site performance and SEO: path-scoped ISR cache tags in createNextSiteHelpers, scaffold CMS API cache wiring with onInvalidate, JSON-LD in the catch-all, font preload template, and doctor checks for API cache and structured data HTML.
|
|
379
|
+
- e1ad198: Platform site-launch defaults: export `createNextSiteHelpers()` from `@actuate-media/cms-core/next/site` for ISR-friendly cached `/resolve`, scaffold new projects with production plugins and cached catch-all pages, and extend `actuate doctor` with site-launch checks (plugins, SEO routes, cached resolve, SSR sections).
|
|
380
|
+
|
|
381
|
+
## 0.26.10
|
|
382
|
+
|
|
383
|
+
### Patch Changes
|
|
384
|
+
|
|
385
|
+
- 0a170a7: Add `@actuate-media/plugin-consent` — cookie banner with `am_cookie_consent` / `am-consent` wiring and GA4, Google Ads, and Meta Pixel loaders gated on Accept all. Scaffold with `--plugins consent` to emit layout + config wiring.
|
|
386
|
+
|
|
387
|
+
## 0.26.9
|
|
388
|
+
|
|
389
|
+
### Patch Changes
|
|
390
|
+
|
|
391
|
+
- 330da89: Scaffold SEO defaults in `actuate.config.ts`, document the prototype-to-production launch checklist, extend the deployment guide with SEO verification steps, and add `path: '/'` plus site-settings globals to the marketing seed.
|
|
392
|
+
|
|
393
|
+
## 0.26.8
|
|
394
|
+
|
|
395
|
+
### Patch Changes
|
|
396
|
+
|
|
397
|
+
- 3983016: Yoast-style public sitemap URLs (`/post-sitemap.xml`, `/post-sitemap2.xml`, …), human-readable XSLT browser views, and middleware rewrites so collection sitemaps resolve at the site root.
|
|
398
|
+
|
|
399
|
+
## 0.26.7
|
|
400
|
+
|
|
401
|
+
### Patch Changes
|
|
402
|
+
|
|
403
|
+
- 4899af9: Fix consumer production builds on Next.js 16 by not injecting a no-op webpack hook in `withActuateCMS`. Add `CRON_SECRET` to scaffold `.env.example`. Remove obsolete `earlyAccess` from scaffolded `prisma.config.ts`. Load project `.env` files in `actuate doctor` and `actuate deploy:check`.
|
|
404
|
+
|
|
405
|
+
## 0.26.6
|
|
406
|
+
|
|
407
|
+
### Patch Changes
|
|
408
|
+
|
|
409
|
+
- 2b61b66: Core Web Vitals: give the `hero` section an optional image rendered as the page LCP, and serve AVIF in scaffolded sites.
|
|
410
|
+
- **Hero image (LCP):** the canonical `hero` section now has an optional `imageUrl`/`imageAlt` field. When set, the renderer draws it below the copy as the page's single priority (eager, `fetchpriority=high`) image with a full-width `sizes` hint and intrinsic dimensions — the explicit, dimensioned LCP element the best-practice spec calls for (rather than leaving the LCP to chance). Alt text is required when an image is set (existing accessibility rule). Dimensions are backfilled by the `/resolve` enrichment (hero is now enriched like `feature`).
|
|
411
|
+
- **AVIF delivery:** `create-actuate-cms` now sets `images.formats: ['image/avif', 'image/webp']` so scaffolded sites serve AVIF (≈50% smaller than JPEG) first, then WebP — a direct LCP win via `next/image` format negotiation.
|
|
412
|
+
|
|
413
|
+
## 0.26.5
|
|
414
|
+
|
|
415
|
+
### Patch Changes
|
|
416
|
+
|
|
417
|
+
- 7b7f0be: Core Web Vitals: get intrinsic image dimensions onto every image so `next/image` engages and CLS is eliminated.
|
|
418
|
+
|
|
419
|
+
Without `width`/`height`, consumers silently fall back to an unsized `<img>` (no srcset, layout shift). This closes that gap two ways:
|
|
420
|
+
- **Read-time (`/resolve`) enrichment** now covers the **post featured image** and **`hero` section images** (previously only `feature`/`gallery`). The resolver looks up dimensions + alt from `actuate_media` and returns the featured image as `post.featuredImage = { url, width, height, alt }` (new `ResolveFeaturedImage` type). Exposes a `featuredImageUrl()` helper. Purely additive — the stored document is never mutated.
|
|
421
|
+
- **Author-time persistence**: selecting an image in the section editor's media picker now writes the intrinsic `width`/`height` alongside the URL (`imageUrl` → `imageWidth`/`imageHeight`; gallery `url` → `width`/`height`), so dimensions travel with the document even without `/resolve`. Exposes `companionDimensionKeys()`.
|
|
422
|
+
|
|
423
|
+
`create-actuate-cms` + `apps/dev`: the generated post page now feeds the resolved featured-image dimensions into the post header for a CLS-free, dimensioned LCP image.
|
|
424
|
+
|
|
425
|
+
## 0.26.4
|
|
426
|
+
|
|
427
|
+
### Patch Changes
|
|
428
|
+
|
|
429
|
+
- 8a64a6e: Core Web Vitals: enforce the single-priority-image (LCP) policy and ship responsive `sizes` by default.
|
|
430
|
+
|
|
431
|
+
The section renderer now guarantees the key LCP/CLS image rules automatically, so an editor (or AI author) can't ship a slow page:
|
|
432
|
+
- **One priority image per page.** A new `LcpController` (exported `createLcpController`) grants the eager, `fetchpriority="high"` slot to the first image on the page; every other image lazy-loads. This replaces `PostHeader`'s hard-coded `priority` (which could collide with a section image). Pass one shared controller via `options.lcp` to both `PostHeader` and `Sections` to share the budget.
|
|
433
|
+
- **Responsive `sizes` everywhere.** Built-in renderers emit contextual `sizes` (full-width header, half-width feature, column-aware gallery via the exported `gallerySizes`) so mobile stops over-downloading the desktop image. `defaultRenderImage` now forwards `sizes` and sets `fetchPriority`.
|
|
434
|
+
- **No raw `<img>`.** The author-bio avatar now renders through `renderImage` (dimensioned, lazy) like every other image.
|
|
435
|
+
- `PostContext` gains `featuredImageWidth`/`featuredImageHeight` so the post header featured image can be dimensioned (CLS).
|
|
436
|
+
|
|
437
|
+
`create-actuate-cms`: the generated catch-all creates a per-request shared `LcpController` for the post header + body and forwards `sizes`/`fetchPriority` in its `next/image` fallback.
|
|
438
|
+
|
|
439
|
+
Note: `ResolvedRenderOptions` now includes a required `lcp` field — only affects code that constructs that internal type directly; consumers passing `RenderOptions` are unaffected (`lcp` is optional there).
|
|
440
|
+
|
|
441
|
+
## 0.26.3
|
|
442
|
+
|
|
443
|
+
### Patch Changes
|
|
444
|
+
|
|
445
|
+
- 108a043: Make the uploaded favicon actually drive the browser tab.
|
|
446
|
+
|
|
447
|
+
Previously the admin tab favicon only read the static `admin.branding.favicon` config value, and the `create-actuate-cms` layouts had no favicon wiring at all — so a favicon uploaded in Settings → Appearance never reached the browser tab.
|
|
448
|
+
- **cms-admin**: the admin now applies the Settings → Appearance favicon to its own browser tab at runtime — fetched on mount and re-applied live when the brand is saved (no reload). The authenticated `public/brand` read bypasses shared caches, so the live update is always fresh. The static `admin.branding.favicon` remains a fast default that the uploaded favicon overrides.
|
|
449
|
+
- **create-actuate-cms**: the generated `(site)` and `(admin)` layouts now resolve the favicon from Brand Settings via `generateMetadata` (mirroring the dev app), so uploads update the public site's `<head>` icons out of the box. Wrapped in try/catch so DB-less builds still emit valid metadata.
|
|
450
|
+
|
|
451
|
+
## 0.26.2
|
|
452
|
+
|
|
453
|
+
### Patch Changes
|
|
454
|
+
|
|
455
|
+
- 6f140bc: Auto-wire the `platform.storage` shorthand to a real adapter server-side, and keep `actuate.config.ts` client-safe.
|
|
456
|
+
|
|
457
|
+
`actuate.config.ts` is imported by the admin client bundle, so putting a platform adapter (e.g. `platform: vercel()`) in it pulls `node:*`/`@vercel/blob` into the client build and breaks it with `Module not found: node:fs`. The config must stay adapter-free.
|
|
458
|
+
- **cms-core**: When the API handler boots and sees a remote `platform.storage` shorthand (`vercel-blob` → `@actuate-media/platform-vercel`, `s3` → `@actuate-media/platform-aws`) with no adapter registered, it now dynamically imports the matching platform package and registers its storage adapter server-side. The import specifier is computed so bundlers never try to statically resolve an optional peer; a missing package degrades to a clear guidance warning instead of a silent upload failure. An explicitly registered adapter always wins. `setStorageAdapter` / `getStorageAdapter` are now also re-exported from `@actuate-media/cms-core/api` for server-side registration of custom adapters.
|
|
459
|
+
- **cms-core**: Clearer upload/diagnostics errors — when a Vercel Blob store is linked (`BLOB_STORE_ID`) but `BLOB_READ_WRITE_TOKEN` is missing, messages now explain that Vercel does not provide the token via OIDC and it must be added per-environment.
|
|
460
|
+
- **create-actuate-cms**: The generated `actuate.config.ts` uses the client-safe `storage: { provider: 'vercel-blob' | 's3' }` shorthand again (reverting the adapter-in-config change that broke the client build); uploads work out of the box via server-side auto-wiring.
|
|
461
|
+
|
|
462
|
+
## 0.26.1
|
|
463
|
+
|
|
464
|
+
### Patch Changes
|
|
465
|
+
|
|
466
|
+
- 1c81772: Make storage configuration honest. `platform.storage: { provider: 'vercel-blob' }` is a descriptive shorthand that never registered an adapter, so uploads silently failed with a misleading `BLOB_READ_WRITE_TOKEN` error. Now:
|
|
467
|
+
- cms-core logs a clear boot-time warning when a remote `provider` shorthand is set but no adapter is registered, and `/media/upload` (used by media + appearance uploads) returns an error that names the real gap — a missing adapter, not a missing token.
|
|
468
|
+
- `create-actuate-cms` generates `platform: vercel()` (a real adapter) instead of the inert shorthand, and the docs gain a dedicated Storage section.
|
|
469
|
+
|
|
470
|
+
## 0.26.0
|
|
471
|
+
|
|
472
|
+
### Minor Changes
|
|
473
|
+
|
|
474
|
+
- 9f5e5dc: Add the AI crawler activity panel (llms.txt measurement layer):
|
|
475
|
+
- **`cms-core`** — new `AiCrawlerHit` model (`actuate_ai_crawler_hits`) + migration, aggregated per `(bot, surface)` so storage stays bounded. `detectAiBot()` classifies known AI user-agents (training vs retrieval) from the existing taxonomy; `llms.txt`, `llms-full.txt`, and `.md` requests from a known crawler are recorded best-effort. New `GET /ai-crawlers` (admin) returns aggregated activity, and an opt-in honeypot (`seo.llms.honeypot`) appends a trap link to `llms.txt` served by `GET /ai-crawlers/trap`.
|
|
476
|
+
- **`cms-admin`** — new "AI crawler activity" panel under SEO → Technical showing per-bot hits, type, surface, and last-seen, plus totals. Frames the numbers honestly (visibility, not a traffic channel).
|
|
477
|
+
- **`create-actuate-cms`** — scaffolded Prisma assets include the new migration so fresh projects get crawler tracking out of the box.
|
|
478
|
+
|
|
479
|
+
Recording is always best-effort and gracefully no-ops on databases that predate the model.
|
|
480
|
+
|
|
481
|
+
## 0.25.0
|
|
482
|
+
|
|
483
|
+
### Minor Changes
|
|
484
|
+
|
|
485
|
+
- 0bcc567: Add per-page Markdown for the AI/agent layer:
|
|
486
|
+
- **`GET /md?path=…`** (`@actuate-media/cms-core`) — returns a clean Markdown rendering of a single published page via `documentToMarkdown()`. Served with `X-Robots-Tag: noindex`; noindexed and `llmsInclude: NEVER` documents return `404` (the selection filter is the privacy boundary).
|
|
487
|
+
- **Clean `/{path}.md` URLs** — `create-actuate-cms` middleware rewrites `/{path}.md` → `/api/cms/md`, so any page is fetchable as Markdown by appending `.md` (e.g. `/about.md`). The HTML page stays canonical and `.md` URLs are never in the sitemap.
|
|
488
|
+
- **Shared path resolver** — extracted `matchPathToCollection()` so `/md` and `/resolve` agree on which document a public URL maps to (no logic drift).
|
|
489
|
+
|
|
490
|
+
## 0.24.0
|
|
491
|
+
|
|
492
|
+
### Minor Changes
|
|
493
|
+
|
|
494
|
+
- a889054: Add the advanced `llms.txt` layer — clean Markdown content export for AI agents:
|
|
495
|
+
- **`documentToMarkdown()` serializer** (`@actuate-media/cms-core`) — renders a published document to clean Markdown. Rich-text/HTML slots are converted with Turndown; structured section content (and the page-builder block tree) is walked generically using an allow-list of prose/heading keys, so non-content data (URLs, ids, settings) never leaks and new section types render without per-type code.
|
|
496
|
+
- **`/llms-full.txt`** — opt-in route (`seo.llms.fullEnabled`) serving the same curated, noindex, sitemap-excluded selection as `/llms.txt` with each page's Markdown inlined and delimited by its canonical URL. Bounded by `seo.llms.maxFullBytes` (default 2 MB) with clean truncation.
|
|
497
|
+
- **Shared selection** — `/llms.txt` and `/llms-full.txt` now share one selector (`selectLlmsDocs` / `toLlmsPage`) so curation and the noindex privacy boundary can't drift.
|
|
498
|
+
- **Scaffold** — `create-actuate-cms` proxies `/llms-full.txt` at the domain root (always generated; enabling is config-only).
|
|
499
|
+
|
|
500
|
+
## 0.23.0
|
|
501
|
+
|
|
502
|
+
### Minor Changes
|
|
503
|
+
|
|
504
|
+
- 4bf16c4: Harden the `/llms.txt` AI discovery file:
|
|
505
|
+
- **Root proxy** — `create-actuate-cms` now scaffolds `app/llms.txt/route.ts`, exposing the file at the spec-required domain root (`/llms.txt`) in addition to `/api/cms/llms.txt`.
|
|
506
|
+
- **noindex** — the route now sends `X-Robots-Tag: noindex` (and the scaffolded proxy preserves it) so the machine-facing index isn't itself indexed.
|
|
507
|
+
- **Sanitization** — titles, descriptions, and the site summary are collapsed to a single line and stripped of markdown link-breaking and control/zero-width characters, then length-capped. Reduces corruption and instruction-smuggling risk from editor fields.
|
|
508
|
+
- **Curation controls** — new `seo.llms` config: `disabled`, `eligibleCollections` (restrict AUTO selection to high-value types), `maxPerSection` (default 25), and `maxEntries` (default 50) so large archives can't flood the file.
|
|
509
|
+
|
|
510
|
+
## 0.22.0
|
|
511
|
+
|
|
512
|
+
### Minor Changes
|
|
513
|
+
|
|
514
|
+
- 3f7fbf3: Add RSS 2.0 (`/feed.xml`) and JSON Feed 1.1 (`/feed.json`) content feeds.
|
|
515
|
+
|
|
516
|
+
Both serve the newest published items across post-type collections (falling back
|
|
517
|
+
to pages when there are no post collections), newest first, capped at 50, with
|
|
518
|
+
canonical URLs and per-document `noindex` exclusion. Item descriptions prefer the
|
|
519
|
+
GEO key takeaway, then the meta description, then the excerpt. Pure builders are
|
|
520
|
+
exported as `buildRssFeed` / `buildJsonFeed`. New `create-actuate-cms` projects
|
|
521
|
+
scaffold root `/feed.xml` + `/feed.json` proxy routes.
|
|
522
|
+
|
|
523
|
+
### Patch Changes
|
|
524
|
+
|
|
525
|
+
- df5d0de: SEO sitemap hardening: canonical URLs, noindex exclusion, accurate lastmod, hreflang, and IndexNow.
|
|
526
|
+
|
|
527
|
+
**cms-core**
|
|
528
|
+
- Sitemaps and the canonical `<link>` / `og:url` now resolve through a single shared `resolveDocumentUrl()` helper, so they can never disagree. It honours an explicit `data.path` (e.g. `/` for the homepage, `/about/story`), maps `home`/`index` to the site root, and otherwise uses `<urlPrefix>/<slug>`. Fixes homepages being listed as `/home` and any page whose `data.path` differed from `/{slug}`.
|
|
529
|
+
- Noindexed documents (`noIndex`/`noindex`/`robotsPolicy: noindex*`, collection/site defaults, non-production guard) are now excluded from the sitemap so it never conflicts with a page's own robots meta tag.
|
|
530
|
+
- The "Include posts in sitemap" crawl setting is now honoured by sitemap generation (both the index and the per-collection sitemap, which 404s when posts are excluded).
|
|
531
|
+
- The "Index entire site" master switch is now enforced: when off, `robots.txt` emits a blanket `Disallow: /` for all crawlers, the sitemap (index + per-collection) serves empty, and publish-time search-engine/IndexNow pings are suppressed. This governs the public site only — CMS admin/API protection (auth + the admin's own `noindex` meta tag + the always-present `/admin` and `/api/` disallows) is unaffected.
|
|
532
|
+
- Sitemap-index `<lastmod>` now reflects each collection's newest published change instead of "now", so crawlers can trust it.
|
|
533
|
+
- `robots.txt` and the SEO settings now advertise the canonical public `/sitemap.xml` instead of the internal `/api/cms/sitemap.xml`.
|
|
534
|
+
- hreflang `<xhtml:link rel="alternate">` annotations (incl. `x-default`) are emitted for translated documents when i18n is configured with more than one locale. No overhead for single-locale sites.
|
|
535
|
+
- IndexNow support: when `INDEXNOW_KEY` is set, changed URLs are submitted to IndexNow (Bing, Yandex, …) on publish/update/delete, and the key is served at `/api/cms/indexnow-key.txt`. New exports: `resolveDocumentUrl`, `buildIndexNowSubmission`, `INDEXNOW_ENDPOINT`.
|
|
536
|
+
|
|
537
|
+
**create-actuate-cms**
|
|
538
|
+
- Scaffolded projects ship root `app/sitemap.xml/route.ts` and `app/robots.txt/route.ts` proxy routes so the canonical `/sitemap.xml` and `/robots.txt` URLs resolve out of the box.
|
|
539
|
+
|
|
540
|
+
## 0.21.0
|
|
541
|
+
|
|
542
|
+
### Minor Changes
|
|
543
|
+
|
|
544
|
+
- a6a17e9: Split login: serve the auth screens on their own non-obvious path while the admin app stays at `/admin`.
|
|
545
|
+
- **cms-core**: new `admin.loginPath` config. `createCMSMiddleware` applies the same guards (IP allowlist, CMS_SECRET check, setup bypass) to the login mount and redirects expired sessions there. Emailed password-reset and invite links point at the login mount when configured.
|
|
546
|
+
- **cms-admin**: new `LoginRoot` component mounts login (+ MFA), the first-run setup wizard, and forgot/reset-password on a separate route (e.g. `/securelogin`, with setup at `/securelogin/setup`), then hands off to the admin app after sign-in. `<AdminRoot loginPath>` makes the admin mount render a 404 lookalike for signed-out visitors instead of a login form — no redirect, so the login location is never leaked.
|
|
547
|
+
- **create-actuate-cms**: new `--login-path` flag and prompt (default `/securelogin`). New projects scaffold the split-login layout by default: login/setup at the login path, admin app at the admin path, config + proxy wired accordingly. Pass `--login-path` equal to `--admin-path` for the classic inline login.
|
|
548
|
+
|
|
549
|
+
## 0.20.0
|
|
550
|
+
|
|
551
|
+
### Minor Changes
|
|
552
|
+
|
|
553
|
+
- 3e2daa4: Inline branded preview — see the draft through your real site without leaving the editor.
|
|
554
|
+
- cms-admin: the page and post editors gain a "Site preview" toggle in the top bar that swaps the structure canvas for an iframe of the public site rendering the draft (same signed `?preview=<token>` contract as "View on site"). Unsaved edits are persisted first, the frame reloads after every save, and the existing viewport controls size the frame.
|
|
555
|
+
- cms-core: `createSiteClient().resolveDocument(path, { previewToken })` forwards a preview token to `/resolve` so consumer routes can render drafts at their real URL.
|
|
556
|
+
- create-actuate-cms: the scaffolded catch-all route now forwards `?preview=` to the resolver and shows a draft banner, so new projects support "View on site" and inline preview out of the box.
|
|
557
|
+
|
|
558
|
+
## 0.19.0
|
|
559
|
+
|
|
560
|
+
### Minor Changes
|
|
561
|
+
|
|
562
|
+
- 0f9c510: Editor & scaffold improvements from Upchat feedback.
|
|
563
|
+
|
|
564
|
+
**cms-admin** — Repeater rows now derive a scannable header from their values
|
|
565
|
+
("Pro · $79/mo", "99.99% · Uptime") instead of only the positional label
|
|
566
|
+
("Plan 2"), so long repeaters read like a list instead of a spreadsheet. Blank
|
|
567
|
+
rows still fall back to "Plan N".
|
|
568
|
+
|
|
569
|
+
**create-actuate-cms** — The `marketing-custom` template now ships the full
|
|
570
|
+
custom-section experience out of the box:
|
|
571
|
+
- `src/sections/admin-renderers.tsx` is scaffolded and pre-wired into
|
|
572
|
+
`<AdminRoot sectionRenderers={...}>`, so the editor canvas renders real
|
|
573
|
+
components for custom section types instead of structural placeholders.
|
|
574
|
+
- A pre-filled `actuate.seed.json` ("Marketing homepage" with hero, stats,
|
|
575
|
+
pricing, and CTA sections) loads via `npm run populate`, so the first visit
|
|
576
|
+
to the Page editor shows a fully-authored page instead of an empty canvas.
|
|
577
|
+
- `SECTIONS.md` and the project README document both workflows.
|
|
578
|
+
|
|
579
|
+
## 0.18.0
|
|
580
|
+
|
|
581
|
+
### Minor Changes
|
|
582
|
+
|
|
583
|
+
- 0c3a6eb: Posts UX improvements from external-consumer feedback:
|
|
584
|
+
- New `admin.excludeFromPostsAggregate: true` collection flag keeps a post-shaped collection out of the admin's aggregate Posts area (cross-collection list, type tabs, New Post picker) while leaving its own admin list and API routes fully accessible. Enforced server-side in `GET /posts` and mirrored in the admin client.
|
|
585
|
+
- `blogPostCollection()` now satisfies the admin Post Editor's full field contract out of the box: it gains `sections` (json), `category`, and `publishDate` (replacing `publishedDate` — update seeds/queries that referenced the old key), and `body` is no longer hard-required so section-driven posts can publish.
|
|
586
|
+
- `create-actuate-cms` scaffolds now define `posts: blogPostCollection()` instead of an inline collection, so new projects always start with an editor-compatible posts schema.
|
|
587
|
+
|
|
588
|
+
## 0.17.1
|
|
589
|
+
|
|
590
|
+
### Patch Changes
|
|
591
|
+
|
|
592
|
+
- 854152d: Developer experience improvements from external-consumer feedback:
|
|
593
|
+
- Every published package now ships its `CHANGELOG.md` in the npm tarball, and packages that were missing a `README.md` (cli, cms-admin, cms-core, import, platform-vercel, all plugins, sections-react) now have one — so release notes and usage docs are visible on npmjs.com and in `node_modules`.
|
|
594
|
+
- New client-safe form validation entry point: `@actuate-media/cms-core/forms/client` exports `validateFormFieldClient()`, `validateFormValuesClient()`, visibility/conditional helpers, and the exact `FORM_EMAIL_RE` / `FORM_PHONE_RE` regexes the server enforces — zero Node dependencies, so public-site forms can mirror server rules without reimplementing them. The server validator now imports the same primitives, so client and server can never drift.
|
|
595
|
+
|
|
596
|
+
## 0.17.0
|
|
597
|
+
|
|
598
|
+
### Minor Changes
|
|
599
|
+
|
|
600
|
+
- 72a4fe9: Prisma Postgres is now the default (and recommended) database for scaffolded projects. `create-actuate-cms` adds a `prisma-postgres` database choice with matching `.env.example` connection strings and deployment-guide copy; Neon and Supabase remain available as explicit choices. Internal docs, deployment rules, and code comments no longer describe this repository's own deployment as Neon — it runs on Prisma Postgres. Benchmark policy messages now suggest a dedicated Prisma Postgres database for isolated runs.
|
|
601
|
+
|
|
602
|
+
## 0.16.0
|
|
603
|
+
|
|
604
|
+
### Minor Changes
|
|
605
|
+
|
|
606
|
+
- 8e73cf5: Add a `--template marketing-custom` starter (and interactive prompt) that scaffolds custom section types end to end: a `src/sections/types.ts` schema wired into `actuate.config.ts` (`sections.types`), public renderers in `src/sections/register.tsx`, a typed `src/blocks/` component source tree, a `verify:sections` static check, `blocks:extract`/`blocks:diff` scripts for the component-blocks manifest, and a `SECTIONS.md` guide.
|
|
607
|
+
|
|
608
|
+
The default `pages` collection now ships with an explicit `path` field via the `pagePathField()` preset.
|
|
609
|
+
|
|
610
|
+
## 0.15.0
|
|
611
|
+
|
|
612
|
+
### Minor Changes
|
|
613
|
+
|
|
614
|
+
- 74662c0: Next.js 16 scaffold fixes and polish.
|
|
615
|
+
- Generate `proxy.ts` (exporting a `proxy` function) instead of `middleware.ts`, matching the Next.js 16 convention.
|
|
616
|
+
- Fix an over-escaped template literal in the generated `app/(site)/layout.tsx` `fetch` call that produced invalid syntax, and add `metadataBase` to the site metadata.
|
|
617
|
+
- Guard the public catch-all route with `isAdminPath()` so requests under the admin base are never resolved as CMS content.
|
|
618
|
+
- Add `@actuate-media/component-blocks` to the default dependencies.
|
|
619
|
+
- New integration tests assert the generated `proxy.ts`, template literal, `metadataBase`, admin guard, and dependency, and TypeScript-parse the key generated files.
|
|
620
|
+
|
|
621
|
+
## 0.14.0
|
|
622
|
+
|
|
623
|
+
### Minor Changes
|
|
624
|
+
|
|
625
|
+
- 13906f6: Scaffold a Renovate preset for the code plane (ADR 0003 §2). New projects ship a `renovate.json` that groups every `@actuate-media/*` upgrade into a single scheduled PR, **auto-merges non-major bumps once CI passes** (leaning on the migration gate added in the previous release), and labels major bumps `breaking-change` for manual review. Uses current `matchPackageNames` glob syntax. `DEPLOYMENT.md` documents enabling Renovate and the branch-protection rule that makes CI-gated auto-merge effective. "Patch the fleet" becomes merging each repo's grouped, independently CI-gated PR — no bespoke orchestrator.
|
|
626
|
+
|
|
627
|
+
## 0.13.0
|
|
628
|
+
|
|
629
|
+
### Minor Changes
|
|
630
|
+
|
|
631
|
+
- e2d8d71: Scaffold a provider-agnostic CI migration gate (ADR 0003). New projects ship a `.github/workflows/ci.yml` that, on every pull request, stands up a throwaway Postgres service container and runs `prisma migrate deploy` against it — so a broken or out-of-order migration fails in review instead of breaking the production Vercel build. It needs no secrets and works regardless of where production runs (Prisma Postgres, Neon, Supabase, or self-hosted); `migrate deploy` reads `DIRECT_DATABASE_URL` per the generated `prisma.config.ts`. `DEPLOYMENT.md` documents the gate.
|
|
632
|
+
|
|
633
|
+
## 0.12.0
|
|
634
|
+
|
|
635
|
+
### Minor Changes
|
|
636
|
+
|
|
637
|
+
- 127f91a: Generate a VS Code MCP config (`.vscode/mcp.json`) alongside the existing
|
|
638
|
+
Cursor/Claude `.cursor/mcp.json`, using VS Code's `servers` + `type: "stdio"`
|
|
639
|
+
schema. Both files ship a placeholder API key and are git-ignored, so a freshly
|
|
640
|
+
scaffolded project wires up an AI agent in either editor after a single
|
|
641
|
+
key-paste. The post-scaffold instructions now cover both editors.
|
|
642
|
+
|
|
643
|
+
## 0.11.0
|
|
644
|
+
|
|
645
|
+
### Minor Changes
|
|
646
|
+
|
|
647
|
+
- 31224ae: WS-E (E4 follow-up): seed demo navigation menus and render a footer nav so
|
|
648
|
+
navigation works end-to-end on a fresh scaffold.
|
|
649
|
+
- **cli:** `actuate seed --demo` now seeds two `navigations` documents — a
|
|
650
|
+
`main` menu (location `header`, linking Home/About/Contact) and a `footer`
|
|
651
|
+
menu (location `footer`, linking Privacy/Terms) — so the shipped `<SiteNav>`
|
|
652
|
+
renders real links out of the box instead of an empty header. Items point at
|
|
653
|
+
the demo pages by public URL.
|
|
654
|
+
- **create-actuate-cms:** the generated site layout now also fetches the
|
|
655
|
+
`footer` menu and renders it in a semantic `<footer>` (with a copyright line),
|
|
656
|
+
alongside the existing header nav. The body is a flex column so the footer
|
|
657
|
+
sits at the bottom. Both navs still degrade gracefully when no menu exists.
|
|
658
|
+
|
|
659
|
+
## 0.10.0
|
|
660
|
+
|
|
661
|
+
### Minor Changes
|
|
662
|
+
|
|
663
|
+
- 204da7a: WS-E (E3): media resolution + responsive images in the public render path.
|
|
664
|
+
- **sections-react:** new pluggable `renderImage` `RenderOptions` hook (with
|
|
665
|
+
exported `RenderImage`/`RenderImageProps` types and a `defaultRenderImage`).
|
|
666
|
+
The default emits a lazy, `decoding="async"` `<img>` and forwards intrinsic
|
|
667
|
+
`width`/`height` when known; a Next.js consumer can pass a `next/image`-backed
|
|
668
|
+
renderer for responsive `srcset` + optimization. The `feature`, `gallery`, and
|
|
669
|
+
post-header images now route through it (`<PostHeader>` gains an optional
|
|
670
|
+
`options` prop). The package stays React-only — no `next` dependency.
|
|
671
|
+
- **cms-core:** the `/resolve` endpoint now enriches section images with
|
|
672
|
+
intrinsic `width`/`height` and library `altText`, matched from `actuate_media`
|
|
673
|
+
by stored URL (`storageKey`/`publicUrl`). Additive and best-effort — the
|
|
674
|
+
stored document is never mutated and a lookup failure never breaks resolve.
|
|
675
|
+
`feature` sections gain `imageWidth`/`imageHeight` (+ backfilled `imageAlt`);
|
|
676
|
+
`gallery` rows gain `width`/`height` (+ backfilled `alt`).
|
|
677
|
+
- **create-actuate-cms:** the generated catch-all page renders CMS images via a
|
|
678
|
+
`next/image`-backed `renderImage` (falling back to a fluid `<img>` when the
|
|
679
|
+
CMS doesn't know dimensions), and `next.config` now allow-lists the storage
|
|
680
|
+
host under `images.remotePatterns` so optimization works out of the box.
|
|
681
|
+
|
|
682
|
+
- e2e0bd7: WS-E (E4): public navigation endpoint + navigation rendering in the scaffold.
|
|
683
|
+
- **cms-core:** new unauthenticated `GET /api/cms/public/navigations/:slug` that
|
|
684
|
+
returns a clean `{ name, slug, location, items }` tree. Like globals it is site
|
|
685
|
+
chrome — not status-gated — and safe when the navigation plugin isn't installed
|
|
686
|
+
(no match → 404). A shared, pure `coercePublicNavItems` helper sanitizes the
|
|
687
|
+
open `data.items` JSON: drops unlabeled nodes, strips internal `id`s, caps
|
|
688
|
+
recursion depth, and only passes through `_blank`/`_self` targets. Both
|
|
689
|
+
`createSiteClient` and `createServerSiteClient` gain `getNavigation(slug)`
|
|
690
|
+
returning `PublicNavigation | null`, and `PublicNavigation` / `PublicNavItem`
|
|
691
|
+
are now exported types.
|
|
692
|
+
- **sections-react:** new presentational `<SiteNav>` — an accessible `<nav>`
|
|
693
|
+
landmark whose submenus use native `<details>`/`<summary>` disclosure
|
|
694
|
+
(keyboard-operable, no client JS). New-tab links get
|
|
695
|
+
`rel="noopener noreferrer"`; an empty menu renders nothing. Exports `SiteNav`
|
|
696
|
+
plus `SiteNavProps`/`SiteNavItem`.
|
|
697
|
+
- **create-actuate-cms:** `lib/cms.ts` re-exports `getNavigation`, and the
|
|
698
|
+
generated site layout fetches the `main` menu and renders a header with the
|
|
699
|
+
site name + `<SiteNav>`, degrading gracefully to just the name when no menu
|
|
700
|
+
exists yet.
|
|
701
|
+
|
|
702
|
+
- a413616: Scaffold a ready-to-use MCP config and connect-an-agent onboarding (WS-C C5).
|
|
703
|
+
|
|
704
|
+
New projects now ship a `.cursor/mcp.json` wiring the Actuate MCP server (`npx -y @actuate-media/mcp-server`) with a placeholder `ACTUATE_API_KEY`. The file is added to `.gitignore` so a real key pasted in is never committed, and the post-setup output explains the "create API key → paste into `.cursor/mcp.json` → restart Cursor/Claude" flow. The MCP guide is also published into the docs-site nav (`apps/docs/content/mcp.md`).
|
|
705
|
+
|
|
706
|
+
- 6927e4b: Non-interactive scaffolding + env wiring fixes (WS-D D1/D4).
|
|
707
|
+
- **Non-interactive mode (D1):** `create-actuate-cms` now accepts `--yes`,
|
|
708
|
+
`--admin-path`, `--plugins` (comma list, `all`, or `none`), `--platform`,
|
|
709
|
+
`--database`, and `--auth` flags. With `--yes` (or no TTY, e.g. CI/agents) it
|
|
710
|
+
scaffolds headlessly from flags + defaults instead of hanging on a prompt.
|
|
711
|
+
Provided flags also skip their prompt in interactive mode. Invalid values fail
|
|
712
|
+
fast with an actionable error listing the allowed choices.
|
|
713
|
+
- **OAuth env names (D4):** the generated `.env.example` now emits
|
|
714
|
+
`OAUTH_GOOGLE_CLIENT_ID` / `OAUTH_GOOGLE_CLIENT_SECRET` (and the GitHub/
|
|
715
|
+
Microsoft equivalents) to match what `cms-core` actually reads at runtime. The
|
|
716
|
+
bare `GOOGLE_CLIENT_ID` names (which the server ignored) and the unused
|
|
717
|
+
`MICROSOFT_TENANT_ID` are removed.
|
|
718
|
+
- **Vercel Blob dependency (D4):** Vercel projects now get `@vercel/blob` as a
|
|
719
|
+
direct dependency. The generated config wires `storage.provider: 'vercel-blob'`,
|
|
720
|
+
but `@vercel/blob` was only an optional peer of `platform-vercel` — so the
|
|
721
|
+
first media upload previously failed with a missing-module error.
|
|
722
|
+
- **Commerce webhook path (D4):** the scaffolded Stripe `webhookEndpoint` now
|
|
723
|
+
points at `/api/cms/stripe/webhook` (the mounted CMS API) instead of the
|
|
724
|
+
non-existent `/api/actuate/stripe/webhook`.
|
|
725
|
+
|
|
726
|
+
## 0.9.0
|
|
727
|
+
|
|
728
|
+
### Minor Changes
|
|
729
|
+
|
|
730
|
+
- 9ba332c: Converge the scaffolder onto the canonical page-content contract (ADR 0001, WS-A4).
|
|
731
|
+
- **create-actuate-cms**: New projects now use the canonical `sections` (JSON `PageSection[]`) field for both `pages` and `posts`, and the generated public catch-all renders `data.sections` with `<Sections>` from `@actuate-media/sections-react` — passing cms-core's allow-list `sanitizeHtml` so author HTML (e.g. the article-body section) is sanitized before the DOM, and rendering a `<PostHeader>` for post-type documents. The deprecated Model C path is retired: the `content[]`/`BLOCK_MAP` `BlockRenderer`, `HeroBlock`, `CTABlock`, `TextBlock`, `ImageTextBlock`, `SiteHeader`, and `SiteFooter` generators (and the `blocks`-gated `layout`/headers/footers config) are removed. Generated apps now depend on `@actuate-media/sections-react` and emit the matching Tailwind `@source` directive.
|
|
732
|
+
- **@actuate-media/cms-core**: `ResolveResult` (the typed `createSiteClient().resolveDocument()` return) now exposes the optional `meta`, `metadata`, `jsonLd`, `jsonLdHtml`, `template`, `post`, and `preview` fields the `/resolve` endpoint already returns, plus the new `ResolvePostAuthor`, `ResolveRelatedPost`, `ResolvePostContext`, and `ResolvePreview` types — so consumers can render the full post experience (header, author, related posts, SEO metadata) without re-declaring the shape.
|
|
733
|
+
|
|
734
|
+
## 0.8.2
|
|
735
|
+
|
|
736
|
+
### Patch Changes
|
|
737
|
+
|
|
738
|
+
- ae1af8f: Authoring correctness fixes for the AI site-building workflow (roadmap WS-B/E quick wins).
|
|
739
|
+
- **cms-core**: `createDocument` now honors a requested `status` (`DRAFT` or
|
|
740
|
+
`PUBLISHED`) instead of always forcing `DRAFT`. Publishing on create is gated
|
|
741
|
+
to EDITOR/ADMIN, stamps `publishedAt`, and emits the `document.published`
|
|
742
|
+
webhook + sitemap notify. This fixes `POST /page-builder/create?publish=true`
|
|
743
|
+
(and `status: 'PUBLISHED'`), which previously created a draft silently.
|
|
744
|
+
Statuses other than `DRAFT`/`PUBLISHED` on create are rejected with guidance
|
|
745
|
+
to schedule/archive via update.
|
|
746
|
+
- **client**: `listMedia()` now returns the canonical
|
|
747
|
+
`{ docs, total, page, pageSize, totalPages }` (`MediaList`) envelope. The
|
|
748
|
+
server returns the asset array under `items`/`data` (never `docs`), so the
|
|
749
|
+
previous typing made `listMedia().docs` always `undefined`. Adds exported
|
|
750
|
+
`MediaAsset` and `MediaList` types and an optional `init` (signal/cache) arg.
|
|
751
|
+
- **mcp-server**: the `list_media` tool now normalizes the same `items`→`docs`
|
|
752
|
+
shape so its output matches `list_documents`.
|
|
753
|
+
- **create-actuate-cms**: generated `TextBlock`/`ImageTextBlock` now sanitize
|
|
754
|
+
author-supplied HTML with `sanitizeHtml` before `dangerouslySetInnerHTML`
|
|
755
|
+
(was an XSS vector on hostile content).
|
|
756
|
+
|
|
757
|
+
## 0.8.1
|
|
758
|
+
|
|
759
|
+
### Patch Changes
|
|
760
|
+
|
|
761
|
+
- 951963a: Build the Settings > Users access-control system: real invites, roles, seats, and access review.
|
|
762
|
+
|
|
763
|
+
**@actuate-media/cms-core**
|
|
764
|
+
- Schema: add `OWNER` and `VIEWER` to the `UserRole` enum, a new `InviteStatus` enum, a new `Invite` model (`actuate_invites`), and additive user-lifecycle columns (`suspendedAt`, `lockedAt`, `forcePasswordReset`, `mfaRequired`, `failedLoginCount`, `lastActiveAt`, `invitedById`, `acceptedInviteAt`). Two hand-authored migrations (`0011_user_roles_owner_viewer`, `0012_invites_and_user_lifecycle`) — enum values are added in their own migration so Postgres can use them as defaults afterward. All user columns are nullable/defaulted so existing rows migrate cleanly.
|
|
765
|
+
- Add a `roles` module (also exported as the `@actuate-media/cms-core/roles` subpath): display mapping (`OWNER/ADMIN/EDITOR/VIEWER` plus legacy `AUTHOR→Editor`, `CLIENT→Viewer`), assignable roles, privilege ranking, and per-role permission derivation.
|
|
766
|
+
- Add an `Invite` lifecycle service (`createInvite`, `listInvites`, `resendInvite`, `cancelInvite`, `updateInviteRole`, `extendInvite`, `expireStaleInvites`, `markInviteAcceptedForEmail`). Invite tokens are hashed at rest, single-use, and expire (7/14/30 days). Completing the password-reset flow for an invited email now marks the invite `ACCEPTED` atomically.
|
|
767
|
+
- Add a `team` module (`listTeamMembers`, `getUserStats`, `computeAccessReview`) that derives seat usage and access-review recommendations (inactive 90d+, external domain, admin/owner without MFA, stale invite) from real user/security signals.
|
|
768
|
+
- New admin endpoints: enriched `GET /users` (search/role/status filters), `GET /users/stats`, `PATCH /users/:id/role`, hardened `DELETE /users/:id` (revoke = suspend, last-Owner protection), `GET /invites` + `POST /invites/:id/resend|cancel` + `PATCH /invites/:id`, and `GET /access-review` + `POST /access-review/:id/dismiss`. Role assignment/removal of Owner is Owner-only, self-escalation is blocked, role downgrades revoke sessions, and seat limits are enforced. All sensitive actions are audit-logged.
|
|
769
|
+
|
|
770
|
+
**@actuate-media/cms-admin**
|
|
771
|
+
- Rebuild the Settings > Users tab to match the design: dynamic summary cards (members, pending invites, admins, seats used), an actionable access-review banner, a combined team table (active members + pending invites) with role-filter pills and search, per-row role dropdowns and revoke/resend/cancel actions, and an invite modal with role radio cards and advanced options (custom message, expiry). Includes loading, empty, filtered-empty, and error states; destructive and Owner-assignment actions require confirmation.
|
|
772
|
+
|
|
773
|
+
**create-actuate-cms**
|
|
774
|
+
- Sync the scaffold's Prisma schema and migrations with the new Users-management schema so newly created projects start with the `Invite` model, new roles, and user-lifecycle columns.
|
|
775
|
+
|
|
776
|
+
## 0.8.0
|
|
777
|
+
|
|
778
|
+
### Minor Changes
|
|
779
|
+
|
|
780
|
+
- f043e18: Fix day-one auth dead-ends and wire up transactional email + user invites.
|
|
781
|
+
|
|
782
|
+
**@actuate-media/cms-core**
|
|
783
|
+
- Add a transactional email sender registry (`setEmailSender`, `getRegisteredEmailSender`, `resolveEmailSender`). Password-reset and form-notification email now resolve a sender via this registry, so apps that configure email purely through `emailPlugin()` actually send (previously only `config.platform.email` was consulted, so reset/notification mail silently never sent).
|
|
784
|
+
- Password reset links are now built from the configured admin path instead of a hardcoded `/admin`, so resets work on apps mounted elsewhere.
|
|
785
|
+
- Add an admin-only `POST /users/invite` endpoint plus `createUserInvite` / `normalizeInviteRole` / `VALID_INVITE_ROLES`. Invites provision the user with an unusable password and a single-use, 7-day token, then email a "set your password" link (reusing the existing `/reset-password` page). When no email sender is configured the response returns the link so an admin can share it manually. Rate-limited per admin.
|
|
786
|
+
|
|
787
|
+
**@actuate-media/cms-admin**
|
|
788
|
+
- `AdminRoot` gains an `onLogout` prop. The account-menu "Logout" item now revokes the server session (`POST /auth/logout`), clears local session state, and returns to the login screen — previously it navigated to a non-existent `/logout` route (404) and left the session valid.
|
|
789
|
+
- The "Invite User" dialog is now a real flow backed by `POST /users/invite` (loading state, error handling, valid roles, optional name) instead of a fake success toast.
|
|
790
|
+
|
|
791
|
+
**create-actuate-cms**
|
|
792
|
+
- The scaffolded admin page now wires `onVerifyTotp` (so MFA users can complete the second-factor step) and `onLogout`, matching the dev app.
|
|
793
|
+
|
|
794
|
+
**@actuate-media/plugin-email**
|
|
795
|
+
- `emailPlugin()` now registers its resolved provider with cms-core's email sender registry, so configuring email via the plugin is sufficient for password-reset, invite, and form-notification email.
|
|
796
|
+
|
|
797
|
+
- 456e5f2: Fix client onboarding so a freshly scaffolded project actually has a working database.
|
|
798
|
+
|
|
799
|
+
**create-actuate-cms**
|
|
800
|
+
- Scaffolded projects now ship the canonical Prisma schema (all `actuate_*` models with `@@map`) and the full migration history, synced from `@actuate-media/cms-core` via `scripts/sync-prisma-assets.ts` and guarded by a drift test. Previously the scaffolder hand-maintained a divergent schema (14 of 33 models, no `@@map`) and shipped no migrations, so `prisma migrate deploy` in the build created no tables and core features (full-text search, i18n, API metrics, API keys, webhooks, notifications, etc.) were broken.
|
|
801
|
+
- The generated `prisma.config.ts` now warns when migrations would run against the pooled `DATABASE_URL` because `DIRECT_DATABASE_URL` is unset.
|
|
802
|
+
- The generated admin page now shows an actionable "run migrations" / backend-unreachable message instead of silently dropping to the login screen when the database has no tables or `/setup/status` fails.
|
|
803
|
+
- Next-steps + deployment docs now use `prisma migrate deploy` (applies the bundled migrations).
|
|
804
|
+
|
|
805
|
+
**@actuate-media/cms-core**
|
|
806
|
+
- `checkSetupRequired` now reports `migrationsRequired: true` (new `SetupStatus` field) when the database is reachable but the tables don't exist yet, and `POST /setup/create-admin` returns an actionable 503 in that case. New exported helper `isSchemaMissingError`.
|
|
807
|
+
- The admin middleware now returns an actionable HTML page (with remediation steps) when `CMS_SECRET` is missing, instead of a bare `500`.
|
|
808
|
+
|
|
809
|
+
## 0.7.0
|
|
810
|
+
|
|
811
|
+
### Minor Changes
|
|
812
|
+
|
|
813
|
+
- 5fa84d3: SEO Operations Center — a full detect → prioritize → explain → route → fix → audit → generate workflow.
|
|
814
|
+
|
|
815
|
+
**cms-core**
|
|
816
|
+
- Additive `0009_seo` migration (mirrored to `apps/dev`): `SEOAuditRun`, `SEOIssue` (+ severity/status/category enums), `Redirect` extensions (`hits`, `lastHitAt`, `enabled`, `priority`, `preserveQuery`, `source`), `Redirect404Hit`, and `RedirectSuggestion`. All columns are nullable or defaulted, so it is safe to apply to an existing database.
|
|
817
|
+
- Pure, explainable scoring model (`seo/score.ts`): `calculatePageSeoScore` / `calculateSiteSeoScore` with documented weights and breakdowns.
|
|
818
|
+
- Persistent audit engine (`seo/audit-engine.ts`) with cross-run issue lifecycle (open / resolved / ignored / recurring) and a redirect engine (chain/loop detection, safe flatten, hit tracking, 404 logging, gated AI 404 recovery).
|
|
819
|
+
- New endpoints: `POST /seo/audit`, `GET /seo/audits[/:id]`, `GET /seo/issues[/:id]`, issue `resolve`/`ignore`/`reopen`/`fix`, `GET /seo/overview`, redirect CRUD + import/export + chains/loops/flatten/suggest, technical settings (`/seo/sitemap/*`, `/seo/crawl-settings`, `/seo/robots`), and approval-gated `/ai/seo/*` (generate-field, explain-issue, generate-schema, summarize) that degrade gracefully with 501 when `plugin-ai` is unconfigured.
|
|
820
|
+
- `/resolve` now returns Next.js-ready `metadata` plus validated JSON-LD; public `robots.txt` honors the admin-edited body.
|
|
821
|
+
|
|
822
|
+
**cms-admin**
|
|
823
|
+
- Rebuilt `SEO.tsx` into a five-tab Operations Center (Overview / Content / Technical / Redirects / Audit) with `?tab=` deep-link routing, dynamic badge counts, a typed `seo-service.ts` client, reusable token-only primitives and a focus-trapped drawer, editor/fix/copilot drawers, and full loading / empty / error / permission states.
|
|
824
|
+
|
|
825
|
+
**mcp-server**
|
|
826
|
+
- New SEO tools: `seo_overview`, `run_seo_audit`, `list_seo_audit_runs`, `list_seo_issues`, `get_seo_issue`, `set_seo_issue_status`, `list_redirect_rules`, `seo_redirect_overview`, `seo_redirect_chains`.
|
|
827
|
+
|
|
828
|
+
**create-actuate-cms**
|
|
829
|
+
- Scaffolded projects now ship a redirect-resolving `middleware.ts` backed by the database redirect table.
|
|
830
|
+
|
|
831
|
+
## 0.6.4
|
|
832
|
+
|
|
833
|
+
### Patch Changes
|
|
834
|
+
|
|
835
|
+
- c8f1022: Update scaffolded `.env.example` and deploy README to reflect the email + rate-limit changes:
|
|
836
|
+
- Email section now documents `EMAIL_PROVIDER` (resend/ses/smtpcom/smtp), `EMAIL_FROM`, and the generic SMTP vars (`SMTP_HOST`/`SMTP_PORT`/`SMTP_SECURE`/`SMTP_USER`/`SMTP_PASS`, requires `nodemailer`).
|
|
837
|
+
- Rate-limit guidance now notes that the Vercel Marketplace Upstash integration provisions `KV_REST_API_URL` / `KV_REST_API_TOKEN` (read automatically), correcting the previous claim that it provisions `UPSTASH_REDIS_REST_URL` / `UPSTASH_REDIS_REST_TOKEN`.
|
|
838
|
+
|
|
839
|
+
## 0.6.3
|
|
840
|
+
|
|
841
|
+
### Patch Changes
|
|
842
|
+
|
|
843
|
+
- 560d1de: Dashboard redesign + real-data backends.
|
|
844
|
+
|
|
845
|
+
`@actuate-media/cms-admin`:
|
|
846
|
+
- Sidebar now uses explicit Content and Settings group headers with nested
|
|
847
|
+
Pages children (Saved Sections, Templates). The collapse control moved
|
|
848
|
+
to the sidebar footer.
|
|
849
|
+
- Header hoists primary page actions (e.g. "+ New Post", "View Site")
|
|
850
|
+
into the top utility bar so the page hero is no longer the source of
|
|
851
|
+
truth for those affordances. The notification bell is wired to the
|
|
852
|
+
real `NotificationBell` component.
|
|
853
|
+
- Dashboard greeting picks the user's first name, and the "Delivery API"
|
|
854
|
+
- "Content Health" cards now read live data from new endpoints.
|
|
855
|
+
|
|
856
|
+
`@actuate-media/cms-core`:
|
|
857
|
+
- New `ApiRequestMetric` table (minute-bucketed counter + log-scale
|
|
858
|
+
latency histogram) and `recordApiRequest` instrumentation wired into
|
|
859
|
+
`handler-factory.ts`. Writes are fire-and-forget — request paths are
|
|
860
|
+
never blocked on the metric DB.
|
|
861
|
+
- New `ContentIssue` table + nightly `processContentHealthScan` cron
|
|
862
|
+
(`/api/cms/cron/content-health`) that runs a pure-logic scanner for
|
|
863
|
+
missing meta descriptions, missing alt text, outdated content
|
|
864
|
+
(>90 days), and broken internal links via HEAD probes.
|
|
865
|
+
- New endpoints `GET /api/cms/stats/api-delivery` and
|
|
866
|
+
`GET /api/cms/stats/content-health` return the dashboard's
|
|
867
|
+
aggregates with stable, never-undefined response shapes.
|
|
868
|
+
- Migration `0007_dashboard_metrics` adds both tables with the indexes
|
|
869
|
+
the new queries need. Safe to apply to populated DBs (no backfill).
|
|
870
|
+
|
|
871
|
+
`create-actuate-cms`:
|
|
872
|
+
- Scaffolded `vercel.json` now includes the nightly content-health
|
|
873
|
+
cron entry, and the deployment guide documents it.
|
|
874
|
+
|
|
875
|
+
## 0.6.2
|
|
876
|
+
|
|
877
|
+
### Patch Changes
|
|
878
|
+
|
|
879
|
+
- e2fabee: Add AI-friendly deployment diagnostics, align generated schemas with first-run admin features, and harden setup guidance for design-first deployments.
|
|
880
|
+
|
|
881
|
+
## 0.6.1
|
|
882
|
+
|
|
883
|
+
### Patch Changes
|
|
884
|
+
|
|
885
|
+
- b224105: Fix post-release developer experience regressions in public site globals, scaffolded Prisma wiring, and seed/populate database initialization.
|
|
886
|
+
|
|
887
|
+
## 0.6.0
|
|
888
|
+
|
|
889
|
+
### Minor Changes
|
|
890
|
+
|
|
891
|
+
- 266b657: Add first-class public site helpers, CLI init/populate workflows, and generated frontend boilerplate for globals, document resolution, and media normalization.
|
|
892
|
+
|
|
893
|
+
## 0.5.1
|
|
894
|
+
|
|
895
|
+
### Patch Changes
|
|
896
|
+
|
|
897
|
+
- b5de8dd: Fix ESM module resolution and dependency duplication issues reported during consumer integration.
|
|
898
|
+
- Add "default" export condition to all platform and plugin packages so they resolve correctly from require() contexts (fixes ERR_PACKAGE_PATH_NOT_EXPORTED in next.config.ts and serverless functions).
|
|
899
|
+
- Move @actuate-media/cms-core from direct dependencies to peerDependencies across all packages to prevent duplicate installations when consumer version ranges don't exactly match the pinned version.
|
|
900
|
+
- Add "prepack" lifecycle script to create-actuate-cms to guarantee dist/ is built before npm publishes the package (fixes empty dist/ in v0.4.0).
|
|
901
|
+
|
|
902
|
+
## 0.5.0
|
|
903
|
+
|
|
904
|
+
### Minor Changes
|
|
905
|
+
|
|
906
|
+
- 54c7a3b: Add Script Tags management system for injecting tracking codes, analytics, and custom scripts into public site pages. Admins create tags with HTML/JS code, choose placement (head, body open, body close), set scope (entire site, parent pages + descendants, or exact URLs), and assign priority order. Includes new ScriptTag database model, CRUD + public resolve API endpoints, admin list and editor views, and updated scaffolder site layout with automatic tag rendering.
|
|
907
|
+
|
|
908
|
+
## 0.4.0
|
|
909
|
+
|
|
910
|
+
### Minor Changes
|
|
911
|
+
|
|
912
|
+
- 140b05c: Resolve package versions from npm registry at scaffold time instead of hardcoding ^0.1.0, which under pre-1.0 semver rules prevented consumers from receiving updates beyond 0.1.x. Falls back gracefully if npm is unreachable. Also fixes CLI --version to read from package.json instead of a stale hardcoded string.
|
|
913
|
+
|
|
914
|
+
## 0.3.0
|
|
915
|
+
|
|
916
|
+
### Minor Changes
|
|
917
|
+
|
|
918
|
+
- 80aa939: Add scaffold site rendering layer with catch-all route, block components, layout components, and critical config wiring fixes.
|
|
919
|
+
- Fix API route template to pass config to handleActuateAPI (enables /resolve and layout regions)
|
|
920
|
+
- Fix admin page template to pass real config to AdminRoot (enables layout sidebar and blocks field)
|
|
921
|
+
- Fix /resolve endpoint to handle root path (/) by looking up "home" or "index" slug
|
|
922
|
+
- Add blocks-first page fields, header/footer collections, and layout config to scaffold (conditional on blocks plugin)
|
|
923
|
+
- Generate catch-all page route with dynamic SEO metadata and first-boot welcome page
|
|
924
|
+
- Generate BlockRenderer, HeroBlock, CTABlock, TextBlock, ImageTextBlock components
|
|
925
|
+
- Generate SiteHeader and SiteFooter layout components with graceful fallbacks
|
|
926
|
+
|
|
927
|
+
## 0.2.0
|
|
928
|
+
|
|
929
|
+
### Minor Changes
|
|
930
|
+
|
|
931
|
+
- 4e3a5eb: RC2-RC4 and hardening release.
|
|
932
|
+
|
|
933
|
+
**cms-core:**
|
|
934
|
+
- Replace isomorphic-dompurify with sanitize-html (eliminates Vercel ESM crash)
|
|
935
|
+
- Remove cms-core from serverExternalPackages, move to transpilePackages
|
|
936
|
+
- Add GET /api/cms/health endpoint with model probing and diagnostics
|
|
937
|
+
- Harden db() Proxy with try/catch on property access and rawDb()
|
|
938
|
+
- Harden safeCount/safeFindMany against Proxy throws
|
|
939
|
+
- Add startup validation for missing CMS_SECRET (503 instead of 500)
|
|
940
|
+
- Bypass auth on /stats when secret is missing (returns zero-data)
|
|
941
|
+
- Loosen NextConfigLike types (experimental/images/webpack as unknown)
|
|
942
|
+
- Implement login anomaly detection (new IP, brute force, unusual hours)
|
|
943
|
+
- Implement webhook DNS resolution with private range checking
|
|
944
|
+
- Implement TOTP reauth verification
|
|
945
|
+
- Add Zod validation for secret in defineConfig (min 32 chars)
|
|
946
|
+
- Read CMS_CORE_VERSION from package.json at runtime instead of hardcoding '0.1.0'
|
|
947
|
+
|
|
948
|
+
**cms-admin:**
|
|
949
|
+
- Ship pre-compiled CSS (dist/actuate-admin.css) with all 48 responsive classes
|
|
950
|
+
- New export: @actuate-media/cms-admin/styles/precompiled.css
|
|
951
|
+
- Add CSS containment (`contain: layout style`) on .actuate-admin
|
|
952
|
+
- Fix ShortcutHelp modal using React state instead of DOM manipulation
|
|
953
|
+
- Add fixed-position layout isolation wrapper to AdminRoot
|
|
954
|
+
- Add useApiData retry limits (maxRetries=3) with exponential backoff
|
|
955
|
+
- Dashboard shows health-aware "Database Setup Required" banner
|
|
956
|
+
|
|
957
|
+
**cli:**
|
|
958
|
+
- Add `actuate db:init` command (injects CMS models into Prisma schema)
|
|
959
|
+
- Add `actuate db:status` command (checks model presence and DB connectivity)
|
|
960
|
+
|
|
961
|
+
**create-actuate-cms:**
|
|
962
|
+
- Embed full CMS schema (9 models + enum) in generated schema.prisma
|
|
963
|
+
- Add @actuate-media/cli to scaffolded devDependencies
|
|
964
|
+
- Use pre-compiled CSS import in scaffolded admin layout
|