create-bearminion 1.4.0 → 1.5.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 +6 -0
- package/package.json +2 -2
- package/template/README.md +1 -1
- package/template/package.json +4 -4
- package/template/src/components/seo/Seo.astro +11 -9
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# create-bearminion
|
|
2
2
|
|
|
3
|
+
## 1.5.0
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 8a428e7: Sitewide JSON-LD. `site.seo.jsonLd` is optional (up to 10 blocks, 50 KB, so no migration) and the default template emits its blocks on every page. A page's own `seo.jsonLd` still replaces only the generated `WebPage` block, and a block with the same `@id` is emitted once, the page's first. With the conventional ids `<url>/#organization` and `<url>/#website` in the site's blocks, the generated `WebPage` gets `isPartOf` and `publisher` as `@id` references. The Site tab has a Structured data group with an Edit JSON-LD dialog and a Generate button that fills an `Organization` and a `WebSite` from the site name, address and language, replacing blocks with the same `@id`. The logo is added only for a full https address. A warning shows while the site address is still `example.com`. `siteJsonLdIds`, `mergeJsonLd`, `hasJsonLdId`, `generateSiteJsonLd`, `upsertJsonLd` and `isPlaceholderSiteUrl` are exported; themes that emit JSON-LD should use `mergeJsonLd` (see the theme docs).
|
|
8
|
+
|
|
3
9
|
## 1.4.0
|
|
4
10
|
|
|
5
11
|
### Minor Changes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-bearminion",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"description": "Create a BearMinion site: an Astro website you edit by clicking on it.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Jakub Lange",
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"@types/node": "^22.19.0",
|
|
47
47
|
"tsdown": "0.23.1",
|
|
48
48
|
"typescript": "~5.9.3",
|
|
49
|
-
"vitest": "^5.0.
|
|
49
|
+
"vitest": "^5.0.5"
|
|
50
50
|
},
|
|
51
51
|
"scripts": {
|
|
52
52
|
"build": "tsdown",
|
package/template/README.md
CHANGED
|
@@ -184,7 +184,7 @@ The site's own images (`logo.png`, `favicon.png`, `og.png`, `hero.png`) live in
|
|
|
184
184
|
|
|
185
185
|
## SEO and sitemap
|
|
186
186
|
|
|
187
|
-
`Seo.astro` reads the page `seo` object and the site defaults in `site.json`. The document title is `seo.titleTemplate` with `%s` replaced by the page SEO title. Description falls back to the site description. The canonical URL is `seo.canonical` when set, otherwise the page path joined to `site.url`. Robots is `noindex` or `index`, plus `nofollow` or `follow`. Open Graph, Twitter, and WebPage JSON-LD use the same title, description, and image. A page that sets `seo.jsonLd` gets those blocks instead of the generated WebPage block,
|
|
187
|
+
`Seo.astro` reads the page `seo` object and the site defaults in `site.json`. The document title is `seo.titleTemplate` with `%s` replaced by the page SEO title. Description falls back to the site description. The canonical URL is `seo.canonical` when set, otherwise the page path joined to `site.url`. Robots is `noindex` or `index`, plus `nofollow` or `follow`. Open Graph, Twitter, and WebPage JSON-LD use the same title, description, and image. Every block in `site.seo.jsonLd` (usually an `Organization` and a `WebSite`) is emitted on every page, and the generated WebPage then points at them by `@id`. A page that sets `seo.jsonLd` gets those blocks instead of the generated WebPage block only, never instead of the site's. A block with the same `@id` is emitted once, the page's copy winning. One script tag per block. `site.analytics.head` and `site.analytics.bodyEnd` are emitted by `Base.astro` in production builds only, behind the [cookie banner](#cookie-banner) unless it is switched off.
|
|
188
188
|
|
|
189
189
|
`astro.config.ts` sets `site` from `site.json` and adds `@astrojs/sitemap`. The filter keeps content pages whose `seo.noindex` is false. `content/pages/preview.json` is the sample noindex page: it is built, it emits `noindex`, and it is absent from the sitemap. `src/pages/robots.txt.ts` points crawlers at `sitemap-index.xml`.
|
|
190
190
|
|
package/template/package.json
CHANGED
|
@@ -18,8 +18,8 @@
|
|
|
18
18
|
"@fontsource/instrument-serif": "^5.3.0",
|
|
19
19
|
"@fontsource/jetbrains-mono": "^5.3.0",
|
|
20
20
|
"@tailwindcss/vite": "^4.1.12",
|
|
21
|
-
"astro": "^7.
|
|
22
|
-
"bearminion": "^1.
|
|
21
|
+
"astro": "^7.4.1",
|
|
22
|
+
"bearminion": "^1.5.0",
|
|
23
23
|
"class-variance-authority": "^0.7.1",
|
|
24
24
|
"sharp": "^0.35.5",
|
|
25
25
|
"tailwind-merge": "^3.7.0",
|
|
@@ -27,8 +27,8 @@
|
|
|
27
27
|
"zod": "^4.6.7"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
|
-
"@astrojs/check": "^0.9.
|
|
31
|
-
"@storybook-astro/framework": "^1.
|
|
30
|
+
"@astrojs/check": "^0.9.11",
|
|
31
|
+
"@storybook-astro/framework": "^1.13.0",
|
|
32
32
|
"@storybook/builder-vite": "^10.6.2",
|
|
33
33
|
"@types/node": "^22.19.0",
|
|
34
34
|
"storybook": "^10.6.2",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
import type
|
|
2
|
+
import { hasJsonLdId, mergeJsonLd, siteJsonLdIds, type Page } from 'bearminion'
|
|
3
3
|
import type { Site } from '../organisms/site-definition'
|
|
4
4
|
import { isRemote, resolveLocalAsset } from '../../lib/assets'
|
|
5
5
|
|
|
@@ -31,19 +31,21 @@ const robots = [page.seo.noindex ? 'noindex' : 'index', page.seo.nofollow ? 'nof
|
|
|
31
31
|
const ogImageSrc = page.seo.ogImage ?? site.seo.ogImage
|
|
32
32
|
const ogImage = ogImageSrc ? absoluteImage(ogImageSrc) : undefined
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
// Blocks from site.seo.jsonLd go on every page. When the site describes itself, the generated WebPage points at those blocks.
|
|
35
|
+
const siteBlocks = site.seo.jsonLd ?? []
|
|
36
|
+
const ids = siteJsonLdIds(site.url)
|
|
37
|
+
const webPage = {
|
|
35
38
|
'@context': 'https://schema.org',
|
|
36
39
|
'@type': 'WebPage',
|
|
37
40
|
name: title,
|
|
38
41
|
description,
|
|
39
42
|
url: canonical,
|
|
40
43
|
...(ogImage ? { image: ogImage } : {}),
|
|
41
|
-
isPartOf: {
|
|
42
|
-
|
|
43
|
-
name: site.name,
|
|
44
|
-
url: site.url,
|
|
45
|
-
},
|
|
44
|
+
isPartOf: hasJsonLdId(siteBlocks, ids.website) ? { '@id': ids.website } : { '@type': 'WebSite', name: site.name, url: site.url },
|
|
45
|
+
...(hasJsonLdId(siteBlocks, ids.organization) ? { publisher: { '@id': ids.organization } } : {}),
|
|
46
46
|
}
|
|
47
|
+
// A page's own JSON-LD replaces only the generated WebPage. Blocks with the same @id are emitted once, the page's first.
|
|
48
|
+
const blocks = mergeJsonLd(siteBlocks, page.seo.jsonLd ?? [webPage])
|
|
47
49
|
---
|
|
48
50
|
|
|
49
51
|
<title>{title}</title>
|
|
@@ -60,9 +62,9 @@ const jsonLd = {
|
|
|
60
62
|
<meta name="twitter:title" content={title} />
|
|
61
63
|
<meta name="twitter:description" content={description} />
|
|
62
64
|
{ogImage && <meta name="twitter:image" content={ogImage} />}
|
|
63
|
-
{/*
|
|
65
|
+
{/* `<` is escaped so a value cannot close the script tag. */}
|
|
64
66
|
{
|
|
65
|
-
|
|
67
|
+
blocks.map((block) => (
|
|
66
68
|
<script type="application/ld+json" set:html={JSON.stringify(block).replace(/</g, '\\u003c')} />
|
|
67
69
|
))
|
|
68
70
|
}
|