@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 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`)
@@ -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.20.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.`);
@@ -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",