@bygghammar/cms-platform 0.51.0 → 0.52.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 CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.52.0
4
+
5
+ - `IndexingStatusCard`: read-only search-engine indexing status (from
6
+ `site/indexing`), shown on the SEO list and SEO detail views via a new
7
+ optional `indexing` dep — the same box as Admin → Site settings.
8
+
3
9
  ## 0.51.0
4
10
 
5
11
  - `site/indexing`: environment-derived search-engine policy (`SITE_INDEXING`,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bygghammar/cms-platform",
3
- "version": "0.51.0",
3
+ "version": "0.52.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": [
@@ -197,7 +197,8 @@
197
197
  "./runtime/error-reporting": "./src/runtime/error-reporting.ts",
198
198
  "./server/media-usage-host": "./src/server/media-usage-host.ts",
199
199
  "./runtime/server-entry": "./src/runtime/server-entry.ts",
200
- "./site/indexing": "./src/site/indexing.ts"
200
+ "./site/indexing": "./src/site/indexing.ts",
201
+ "./backoffice/IndexingStatusCard": "./src/backoffice/IndexingStatusCard.tsx"
201
202
  },
202
203
  "dependencies": {
203
204
  "fflate": "^0.8.3"
@@ -0,0 +1,43 @@
1
+ import type { ReactNode } from "react";
2
+
3
+ import type { IndexingPolicy } from "../site/indexing";
4
+
5
+ /**
6
+ * Read-only search-engine indexing status, resolved server-side from the
7
+ * environment (`SITE_INDEXING` / `SITE_ENV` — see `site/indexing`). Shown on
8
+ * Site settings and the SEO screens so a blocked staging deployment is
9
+ * visible wherever metadata is edited. Never a database toggle: indexing is
10
+ * an environment fact so a content restore cannot flip it.
11
+ */
12
+ export function IndexingStatusCard({
13
+ indexing,
14
+ }: {
15
+ indexing?: IndexingPolicy;
16
+ }): ReactNode {
17
+ const status = indexing
18
+ ? indexing.mode === "block"
19
+ ? "Blocked — not indexed"
20
+ : "Indexed"
21
+ : "Unknown";
22
+ const source = indexing
23
+ ? indexing.source === "SITE_INDEXING"
24
+ ? `From SITE_INDEXING=${indexing.value}`
25
+ : indexing.source === "SITE_ENV"
26
+ ? `From SITE_ENV=${indexing.value}`
27
+ : "Safe default — SITE_INDEXING unset"
28
+ : "Set SITE_INDEXING per environment";
29
+
30
+ return (
31
+ <div className="max-w-sm border border-ink/10 bg-white p-4">
32
+ <div className="text-xs uppercase tracking-wider text-ink/50">Search engines</div>
33
+ <div className="mt-1 text-sm text-ink">{status}</div>
34
+ <div className="mt-2 text-[11px] uppercase tracking-wider text-ink/40">{source}</div>
35
+ <p className="mt-3 text-xs text-ink/50">
36
+ Indexing is an environment fact, not a setting here: set <code>SITE_INDEXING=off</code> on
37
+ staging and <code>SITE_INDEXING=on</code> in production. A blocked deployment serves{" "}
38
+ <code>Disallow: /</code> in robots.txt and a <code>noindex, nofollow</code> header on every
39
+ response.
40
+ </p>
41
+ </div>
42
+ );
43
+ }
@@ -7,6 +7,9 @@
7
7
  import type { ReactNode } from "react";
8
8
  import { Check, ChevronLeft, ChevronRight } from "lucide-react";
9
9
 
10
+ import type { IndexingPolicy } from "../../site/indexing";
11
+ import { IndexingStatusCard } from "../IndexingStatusCard";
12
+
10
13
  export type SeoListRow = {
11
14
  /** Page key, e.g. `index` or a CMS-only page key. */
12
15
  key: string;
@@ -21,10 +24,15 @@ export type SeoListDeps = {
21
24
  rows: readonly SeoListRow[];
22
25
  /** Navigate to the SEO editor for one page key. */
23
26
  openEditor: (key: string) => void;
27
+ /**
28
+ * Indexing policy for the running deployment, resolved from the environment
29
+ * server-side (see `site/indexing`). Shown read-only, same as Site settings.
30
+ */
31
+ indexing?: IndexingPolicy;
24
32
  };
25
33
 
26
34
  export function SeoListView({ deps }: { deps: SeoListDeps }): ReactNode {
27
- const { rows, openEditor } = deps;
35
+ const { rows, openEditor, indexing } = deps;
28
36
 
29
37
  return (
30
38
  <div className="p-8 md:p-12 w-full">
@@ -36,6 +44,10 @@ export function SeoListView({ deps }: { deps: SeoListDeps }): ReactNode {
36
44
  defaults from the codebase and are used directly by canonical, hreflang and sitemap.
37
45
  </p>
38
46
 
47
+ <div className="mt-6">
48
+ <IndexingStatusCard indexing={indexing} />
49
+ </div>
50
+
39
51
  <ul className="mt-10 divide-y divide-ink/10 border-y border-ink/10">
40
52
  {rows.map((row) => (
41
53
  <li key={row.key}>
@@ -73,10 +85,15 @@ export type SeoDetailDeps = {
73
85
  onBack: () => void;
74
86
  /** The host's page SEO panel for this page key. */
75
87
  children: ReactNode;
88
+ /**
89
+ * Indexing policy for the running deployment, resolved from the environment
90
+ * server-side (see `site/indexing`). Shown read-only, same as Site settings.
91
+ */
92
+ indexing?: IndexingPolicy;
76
93
  };
77
94
 
78
95
  export function SeoDetailView({ deps }: { deps: SeoDetailDeps }): ReactNode {
79
- const { pageKey, onBack, children } = deps;
96
+ const { pageKey, onBack, children, indexing } = deps;
80
97
 
81
98
  return (
82
99
  <div className="p-8 md:p-12 w-full">
@@ -98,6 +115,10 @@ export function SeoDetailView({ deps }: { deps: SeoDetailDeps }): ReactNode {
98
115
  hreflang, Open Graph and Twitter cards.
99
116
  </p>
100
117
 
118
+ <div className="mt-6">
119
+ <IndexingStatusCard indexing={indexing} />
120
+ </div>
121
+
101
122
  <div className="mt-8">{children}</div>
102
123
  </div>
103
124
  );