@bygghammar/cms-platform 0.20.0 → 0.22.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 +76 -0
- package/README.md +18 -0
- package/docs/NEW-SITE.md +103 -0
- package/package.json +10 -3
- package/scripts/sync-migrations.mjs +49 -0
- package/src/platform/contract.ts +0 -5
- package/src/server/forms-core.ts +820 -0
- package/migrations/20260811112455_217c4028-f587-4c98-9e4f-9e6c452ab761.sql +0 -20
- package/migrations/20260811114438_6687d67d-bad3-4803-9638-8b7670d2e5d4.sql +0 -86
- package/migrations/20260811220548_80d99ec2-bd4b-475d-a627-9408bb60ce56.sql +0 -1
- package/migrations/20260811222519_6b040f56-4de3-49e0-92e4-d9deec5ead6a.sql +0 -3
- package/migrations/20260812000000_seed_voyara_content.sql +0 -390
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to `@bygghammar/cms-platform`.
|
|
4
|
+
|
|
5
|
+
The package follows semver with the pre-1.0 convention that a **minor** bump may
|
|
6
|
+
contain breaking changes to shared views, adapters or cores; patch releases are
|
|
7
|
+
always compatible. In addition, `PLATFORM_CONTRACT_VERSION` in
|
|
8
|
+
`platform/contract` is bumped whenever a shared screen starts requiring schema
|
|
9
|
+
or adapter capabilities an older site does not have. Sites assert that constant
|
|
10
|
+
in a test and upgrade deliberately.
|
|
11
|
+
|
|
12
|
+
## 0.22.0
|
|
13
|
+
|
|
14
|
+
- Added `docs/NEW-SITE.md`: the supported starter path for a new site (install,
|
|
15
|
+
contract assertion, migrations, theme, host registration, server cores,
|
|
16
|
+
backoffice routes, verification).
|
|
17
|
+
- Added this changelog and a written compatibility policy.
|
|
18
|
+
- Added the `cms-platform-migrations` bin, which copies missing canonical
|
|
19
|
+
migrations into a site's migration directory without overwriting or deleting
|
|
20
|
+
anything.
|
|
21
|
+
- Removed five Voyara-specific content/data migrations from the canonical set
|
|
22
|
+
(SEO copy, a homepage block seed, a locale-domain update, a booking-link
|
|
23
|
+
rewrite and the content seed). Canonical migrations are schema only; site
|
|
24
|
+
content stays in the site's own migration directory. Existing sites keep
|
|
25
|
+
those files locally and remain compatible.
|
|
26
|
+
- No runtime source changes; safe upgrade from 0.21.x.
|
|
27
|
+
|
|
28
|
+
## 0.21.0
|
|
29
|
+
|
|
30
|
+
- Added `server/forms-core`: host-agnostic forms server rules — effective
|
|
31
|
+
settings, recipient routing, notification templates, submitter detection,
|
|
32
|
+
field-removal safety, version snapshots, audit trail and the list/save/delete/
|
|
33
|
+
restore/purge/duplicate cores plus site defaults, usage and delivery logging.
|
|
34
|
+
|
|
35
|
+
## 0.20.0
|
|
36
|
+
|
|
37
|
+
- Added `server/media-usage-core` (usage scan, remote media import, reference
|
|
38
|
+
rewriting) and completed `server/media-cleanup-core`.
|
|
39
|
+
|
|
40
|
+
## 0.19.0
|
|
41
|
+
|
|
42
|
+
- Added `server/guards`, `server/redirects-core` and `server/page-seo-core`.
|
|
43
|
+
|
|
44
|
+
## 0.18.0
|
|
45
|
+
|
|
46
|
+
- Extracted `FormEditorView`, `FormsIndexView` and `RedirectsView`.
|
|
47
|
+
|
|
48
|
+
## 0.17.0
|
|
49
|
+
|
|
50
|
+
- Extracted the media library UI, including client-side optimisation and usage
|
|
51
|
+
inspection.
|
|
52
|
+
|
|
53
|
+
## 0.15.0 – 0.16.0
|
|
54
|
+
|
|
55
|
+
- Extracted `SectionFormView` and `PageEditorView`.
|
|
56
|
+
|
|
57
|
+
## 0.14.0
|
|
58
|
+
|
|
59
|
+
- Expanded the `PlatformData` host contract to every backoffice module and added
|
|
60
|
+
`assertPlatformData` / `REQUIRED_PLATFORM_DATA`.
|
|
61
|
+
|
|
62
|
+
## 0.12.0 – 0.13.0
|
|
63
|
+
|
|
64
|
+
- Extracted `ReviewImageUpload` and `PageSeoPanel`.
|
|
65
|
+
|
|
66
|
+
## 0.5.0 – 0.11.0
|
|
67
|
+
|
|
68
|
+
- Phase 1 and 2: pure forms/media/http/i18n helpers, backup core, trips and
|
|
69
|
+
navigation contracts, and the first host contract.
|
|
70
|
+
- Phase 5 groundwork: canonical migrations shipped under `migrations/` with
|
|
71
|
+
`SCHEMA_MIGRATIONS` and `PLATFORM_CONTRACT_VERSION`.
|
|
72
|
+
|
|
73
|
+
## 0.1.0
|
|
74
|
+
|
|
75
|
+
- First release: blocks, block types, icons, i18n core, UI primitives and the
|
|
76
|
+
`theme.css` design-token contract.
|
package/README.md
CHANGED
|
@@ -18,6 +18,24 @@ future sites). **Code only** — no content, no data, no secrets, no theme.
|
|
|
18
18
|
active-state helpers. Menu content and visual headers remain per-site.
|
|
19
19
|
- `src/theme.css` — the design-token contract + neutral starter theme
|
|
20
20
|
|
|
21
|
+
## Starting a new site
|
|
22
|
+
|
|
23
|
+
`docs/NEW-SITE.md` is the supported starter path: install, assert the contract,
|
|
24
|
+
apply the canonical schema with `bunx cms-platform-migrations`, import
|
|
25
|
+
`theme.css`, register host components / platform data / translations, wrap the
|
|
26
|
+
server cores and mount the shared backoffice views.
|
|
27
|
+
|
|
28
|
+
## Compatibility policy
|
|
29
|
+
|
|
30
|
+
- `CHANGELOG.md` records every release; read it before upgrading.
|
|
31
|
+
- Pre-1.0, a **minor** release may break shared views, adapters or cores; patch
|
|
32
|
+
releases are always compatible.
|
|
33
|
+
- `PLATFORM_CONTRACT_VERSION` (`platform/contract`) is bumped when a shared
|
|
34
|
+
screen starts requiring schema or adapter capabilities an older site lacks.
|
|
35
|
+
Sites pin it in a test.
|
|
36
|
+
- `migrations/` is schema only. Site content, SEO copy and seeds never belong
|
|
37
|
+
there.
|
|
38
|
+
|
|
21
39
|
## What must never live here
|
|
22
40
|
|
|
23
41
|
- colours, fonts or spacing values used by a specific site (see `theme.css`)
|
package/docs/NEW-SITE.md
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# Starting a new site on @bygghammar/cms-platform
|
|
2
|
+
|
|
3
|
+
This is the supported path from an empty TanStack Start project to a working
|
|
4
|
+
CMS site. Every step is code or configuration in the new site; nothing here
|
|
5
|
+
copies content, media or secrets between sites.
|
|
6
|
+
|
|
7
|
+
## 0. Prerequisites
|
|
8
|
+
|
|
9
|
+
- TanStack Start v1 (React 19, Vite 7), Tailwind v4, shadcn/ui.
|
|
10
|
+
- A Supabase-compatible backend for the site (its own project/stack — never
|
|
11
|
+
shared with another site, never a production database during authoring).
|
|
12
|
+
|
|
13
|
+
## 1. Install
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
bun add @bygghammar/cms-platform@<exact version>
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Pin an exact version and commit the lockfile. Read `CHANGELOG.md` before every
|
|
20
|
+
upgrade.
|
|
21
|
+
|
|
22
|
+
## 2. Assert the contract
|
|
23
|
+
|
|
24
|
+
```ts
|
|
25
|
+
import {
|
|
26
|
+
PLATFORM_CONTRACT_VERSION,
|
|
27
|
+
SCHEMA_MIGRATIONS,
|
|
28
|
+
assertPlatformContract,
|
|
29
|
+
missingMigrations,
|
|
30
|
+
} from "@bygghammar/cms-platform/platform/contract";
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Add one test that pins the contract version the site was built against and one
|
|
34
|
+
that asserts `missingMigrations(appliedFilenames)` is empty. See
|
|
35
|
+
`tests/platform-contract.test.ts` in any existing site for the exact shape.
|
|
36
|
+
|
|
37
|
+
## 3. Apply the canonical schema
|
|
38
|
+
|
|
39
|
+
The package ships the canonical migrations under `migrations/`, oldest first.
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
bunx cms-platform-migrations ./supabase/migrations
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
The command copies any migration the target directory is missing and never
|
|
46
|
+
overwrites or deletes a file, so it is safe to re-run after an upgrade. Apply
|
|
47
|
+
the copied files with the site's normal migration tooling. Site-specific
|
|
48
|
+
migrations live alongside them with later timestamps and must stay additive.
|
|
49
|
+
|
|
50
|
+
## 4. Theme
|
|
51
|
+
|
|
52
|
+
```css
|
|
53
|
+
/* src/styles.css */
|
|
54
|
+
@import "@bygghammar/cms-platform/theme.css";
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Then override the design tokens for the new brand in the site's own layer.
|
|
58
|
+
Never edit colours, fonts or spacing inside the package.
|
|
59
|
+
|
|
60
|
+
## 5. Register the host
|
|
61
|
+
|
|
62
|
+
Three registrations, all at startup:
|
|
63
|
+
|
|
64
|
+
- **Host components** — `registerHostComponents()` from
|
|
65
|
+
`@bygghammar/cms-platform/host` for the site's link, image, video and rich
|
|
66
|
+
text primitives.
|
|
67
|
+
- **Platform data adapter** — `registerHostPlatform({ data, site })` from
|
|
68
|
+
`@bygghammar/cms-platform/platform`. `data` implements every member in
|
|
69
|
+
`REQUIRED_PLATFORM_DATA` (pages, versions, global sections, media, SEO,
|
|
70
|
+
redirects, forms); `site` describes name, `backofficeBasePath` and locales.
|
|
71
|
+
Guard it with a test that calls `assertPlatformData`.
|
|
72
|
+
- **Translations** — the site's own `sv`/`en` maps via the i18n register
|
|
73
|
+
module. Translation data is content and stays in the site.
|
|
74
|
+
|
|
75
|
+
## 6. Server functions
|
|
76
|
+
|
|
77
|
+
Wrap the shared server cores in the site's own `createServerFn` files:
|
|
78
|
+
|
|
79
|
+
| Package core | Purpose |
|
|
80
|
+
| --- | --- |
|
|
81
|
+
| `server/guards` | `assertStaff`, `assertSuperadmin` |
|
|
82
|
+
| `server/forms-core` | form definitions, versions, settings, delivery log |
|
|
83
|
+
| `server/redirects-core` | path normalisation and redirect writes |
|
|
84
|
+
| `server/page-seo-core` | slug conflicts and slug-change 301s |
|
|
85
|
+
| `server/media-usage-core` | usage scan and remote import |
|
|
86
|
+
| `server/media-cleanup-core` | duplicate/rename planning and apply |
|
|
87
|
+
|
|
88
|
+
The site supplies clients, storage and page-key → path maps; the package owns
|
|
89
|
+
the rules. Keep privileged clients inside handlers.
|
|
90
|
+
|
|
91
|
+
## 7. Backoffice routes
|
|
92
|
+
|
|
93
|
+
Each backoffice route is a thin adapter around the package view
|
|
94
|
+
(`PageEditorView`, `MediaLibraryView`, `FormEditorView`, `FormsIndexView`,
|
|
95
|
+
`RedirectsView`, `SectionFormView`, `PageSeoPanel`). Routes own the path and
|
|
96
|
+
auth gate only.
|
|
97
|
+
|
|
98
|
+
## 8. Verify
|
|
99
|
+
|
|
100
|
+
1. Types pass.
|
|
101
|
+
2. Full test suite passes, including the contract tests from step 2.
|
|
102
|
+
3. `/` renders.
|
|
103
|
+
4. The backoffice signs in, and one page, one form and one media asset save.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bygghammar/cms-platform",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.22.0",
|
|
4
4
|
"description": "Shared CMS platform: blocks, block types, i18n core, UI primitives and design-token contract used by every Bygghammar/Voyara site.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -10,7 +10,10 @@
|
|
|
10
10
|
},
|
|
11
11
|
"files": [
|
|
12
12
|
"README.md",
|
|
13
|
+
"CHANGELOG.md",
|
|
14
|
+
"docs",
|
|
13
15
|
"migrations",
|
|
16
|
+
"scripts",
|
|
14
17
|
"src"
|
|
15
18
|
],
|
|
16
19
|
"repository": {
|
|
@@ -108,7 +111,8 @@
|
|
|
108
111
|
"./server/redirects-core": "./src/server/redirects-core.ts",
|
|
109
112
|
"./server/page-seo-core": "./src/server/page-seo-core.ts",
|
|
110
113
|
"./server/media-cleanup-core": "./src/server/media-cleanup-core.ts",
|
|
111
|
-
"./server/media-usage-core": "./src/server/media-usage-core.ts"
|
|
114
|
+
"./server/media-usage-core": "./src/server/media-usage-core.ts",
|
|
115
|
+
"./server/forms-core": "./src/server/forms-core.ts"
|
|
112
116
|
},
|
|
113
117
|
"dependencies": {
|
|
114
118
|
"fflate": "^0.8.3"
|
|
@@ -180,5 +184,8 @@
|
|
|
180
184
|
"@tiptap/extension-table": {
|
|
181
185
|
"optional": true
|
|
182
186
|
}
|
|
187
|
+
},
|
|
188
|
+
"bin": {
|
|
189
|
+
"cms-platform-migrations": "scripts/sync-migrations.mjs"
|
|
183
190
|
}
|
|
184
|
-
}
|
|
191
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Copy canonical platform migrations into a site's migration directory.
|
|
4
|
+
*
|
|
5
|
+
* Additive only: a file that already exists in the target is left untouched and
|
|
6
|
+
* nothing is ever deleted or overwritten, so this is safe to re-run after an
|
|
7
|
+
* upgrade.
|
|
8
|
+
*
|
|
9
|
+
* Usage: cms-platform-migrations [targetDir] [--check]
|
|
10
|
+
* targetDir defaults to ./supabase/migrations
|
|
11
|
+
* --check exits non-zero when files are missing instead of copying them
|
|
12
|
+
*/
|
|
13
|
+
import { copyFileSync, existsSync, mkdirSync, readdirSync } from "node:fs";
|
|
14
|
+
import { dirname, join, resolve } from "node:path";
|
|
15
|
+
import { fileURLToPath } from "node:url";
|
|
16
|
+
|
|
17
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
18
|
+
const source = resolve(here, "..", "migrations");
|
|
19
|
+
|
|
20
|
+
const args = process.argv.slice(2);
|
|
21
|
+
const checkOnly = args.includes("--check");
|
|
22
|
+
const target = resolve(args.find((a) => !a.startsWith("--")) ?? "supabase/migrations");
|
|
23
|
+
|
|
24
|
+
if (!existsSync(source)) {
|
|
25
|
+
console.error(`No migrations directory in the package at ${source}`);
|
|
26
|
+
process.exit(1);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const canonical = readdirSync(source)
|
|
30
|
+
.filter((f) => f.endsWith(".sql"))
|
|
31
|
+
.sort();
|
|
32
|
+
|
|
33
|
+
const present = new Set(existsSync(target) ? readdirSync(target) : []);
|
|
34
|
+
const missing = canonical.filter((f) => !present.has(f));
|
|
35
|
+
|
|
36
|
+
if (missing.length === 0) {
|
|
37
|
+
console.log(`Up to date: ${canonical.length} canonical migrations already present.`);
|
|
38
|
+
process.exit(0);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (checkOnly) {
|
|
42
|
+
console.error(`Missing ${missing.length} canonical migrations:`);
|
|
43
|
+
for (const f of missing) console.error(` ${f}`);
|
|
44
|
+
process.exit(1);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
mkdirSync(target, { recursive: true });
|
|
48
|
+
for (const f of missing) copyFileSync(join(source, f), join(target, f));
|
|
49
|
+
console.log(`Copied ${missing.length} migration(s) into ${target}. Apply them with your migration tooling.`);
|
package/src/platform/contract.ts
CHANGED
|
@@ -67,12 +67,7 @@ export const SCHEMA_MIGRATIONS: readonly string[] = [
|
|
|
67
67
|
"20260803201518_6e8a6028-b70f-4a7d-8bc9-95c86304e7ae.sql",
|
|
68
68
|
"20260803201535_32a9a213-cb92-4035-b8cd-8211ca34af68.sql",
|
|
69
69
|
"20260811103505_29df753d-14fa-4a05-8fea-f4207785fba3.sql",
|
|
70
|
-
"20260811112455_217c4028-f587-4c98-9e4f-9e6c452ab761.sql",
|
|
71
|
-
"20260811114438_6687d67d-bad3-4803-9638-8b7670d2e5d4.sql",
|
|
72
70
|
"20260811130318_7cb95e95-9baa-40af-8f3f-de1d4e09cec4.sql",
|
|
73
|
-
"20260811220548_80d99ec2-bd4b-475d-a627-9408bb60ce56.sql",
|
|
74
|
-
"20260811222519_6b040f56-4de3-49e0-92e4-d9deec5ead6a.sql",
|
|
75
|
-
"20260812000000_seed_voyara_content.sql",
|
|
76
71
|
"20260818040722_1bdf1b8f-7fb0-4ae8-8ecf-73f1fadff3c2.sql",
|
|
77
72
|
"20260818040808_69a5e832-57e8-4aa7-aff8-7fd7777faa7c.sql",
|
|
78
73
|
"20260818040839_e6523163-bbf5-4a39-9233-91759059569a.sql",
|