@mannisto/astro-metadata 2.0.0-alpha.5 → 2.0.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.
Files changed (37) hide show
  1. package/README.md +247 -108
  2. package/package.json +2 -2
  3. package/src/components/Canonical.astro +10 -0
  4. package/src/components/Description.astro +10 -0
  5. package/src/components/Favicon.astro +9 -0
  6. package/src/components/Feeds.astro +29 -0
  7. package/src/components/LanguageAlternates.astro +13 -0
  8. package/src/components/Manifest.astro +11 -0
  9. package/src/components/Metadata.astro +27 -199
  10. package/src/components/OpenGraph.astro +70 -0
  11. package/src/components/Robots.astro +10 -0
  12. package/src/components/Schema.astro +42 -0
  13. package/src/components/ThemeColor.astro +15 -0
  14. package/src/components/Title.astro +10 -0
  15. package/src/components/Twitter.astro +21 -0
  16. package/src/components/index.ts +13 -1
  17. package/src/integration.js +0 -6
  18. package/src/lib/checks.js +6 -1
  19. package/src/lib/manifest.ts +0 -1
  20. package/src/lib/open-graph.ts +54 -0
  21. package/src/lib/page.ts +164 -0
  22. package/src/lib/rules.js +0 -1
  23. package/src/lib/site.ts +65 -43
  24. package/src/lib/url.ts +4 -1
  25. package/src/runtime.ts +1 -3
  26. package/src/toolbar/app.ts +1 -15
  27. package/src/toolbar/data.ts +0 -2
  28. package/src/toolbar/highlight.ts +0 -3
  29. package/src/toolbar/ui/alert/alert.css +0 -2
  30. package/src/toolbar/ui/section/section.css +0 -7
  31. package/src/toolbar/ui/table/table.css +0 -2
  32. package/src/toolbar/views/metadata-panel.css +0 -7
  33. package/src/toolbar/views/metadata-panel.ts +1 -5
  34. package/src/toolbar/views/overview-view.css +0 -2
  35. package/src/toolbar/views/overview-view.ts +13 -0
  36. package/src/toolbar/views/previews/previews-view.css +0 -1
  37. package/src/toolbar/views/previews/previews-view.ts +0 -1
package/README.md CHANGED
@@ -1,25 +1,12 @@
1
1
  # Astro Metadata
2
2
 
3
- ![banner](./assets/banner.png)
3
+ ![banner](./docs/banner.png)
4
4
 
5
5
  ![Astro](https://img.shields.io/badge/astro-%232C2052.svg?style=for-the-badge&logo=astro&logoColor=white)
6
6
  ![npm version](https://img.shields.io/npm/v/@mannisto/astro-metadata?style=for-the-badge)
7
7
  ![license](https://img.shields.io/badge/license-MIT-green?style=for-the-badge)
8
8
 
9
- The page metadata for Astro: the title, the description, the canonical URL, social cards, favicons, the web app manifest and structured data. Set the site values one time, and give each page only its own values.
10
-
11
- - [Install](#install)
12
- - [Configuration](#configuration)
13
- - [Metadata component](#metadata-component)
14
- - [Favicons](#favicons)
15
- - [Web app manifest](#web-app-manifest)
16
- - [Structured data](#structured-data)
17
- - [Checks](#checks)
18
- - [API](#api)
19
- - [Good to know](#good-to-know)
20
- - [Migrate from v1](#migrate-from-v1)
21
- - [Contributing](#contributing)
22
- - [License](#license)
9
+ The page metadata for Astro: the title, the description, the canonical URL, social cards, favicons, the web app manifest and structured data. Set the site values one time, and give each page only its own values. In dev, an app in the Astro dev toolbar checks each page.
23
10
 
24
11
  ## Install
25
12
 
@@ -43,12 +30,28 @@ export default defineConfig({
43
30
  siteName: "Acme Studio",
44
31
  titleTemplate: "%s | Acme Studio",
45
32
  description: "Tools for small teams.",
46
- image: { url: "/og.jpg", alt: "Acme Studio", width: 1200, height: 630 },
47
- twitter: { site: "@acmestudio" },
33
+ image: {
34
+ url: "/og.jpg",
35
+ alt: "Acme Studio",
36
+ width: 1200,
37
+ height: 630,
38
+ },
39
+ twitter: {
40
+ site: "@acmestudio",
41
+ },
48
42
  themeColor: "#111111",
49
- feeds: [{ href: "/rss.xml", title: "News" }],
50
- favicon: { source: "./src/assets/logo.svg" },
51
- manifest: { name: "Acme Studio" },
43
+ feeds: [
44
+ {
45
+ href: "/rss.xml",
46
+ title: "News",
47
+ },
48
+ ],
49
+ favicon: {
50
+ source: "./src/assets/logo.svg",
51
+ },
52
+ manifest: {
53
+ name: "Acme Studio",
54
+ },
52
55
  }),
53
56
  ],
54
57
  })
@@ -69,32 +72,10 @@ Set `site` in the Astro config. The canonical URL and the social images must be
69
72
  | `favicon` | — | Generates the favicons from one image. See [Favicons](#favicons). |
70
73
  | `manifest` | — | Generates the web app manifest, or links your own. See [Web app manifest](#web-app-manifest). |
71
74
  | `schema` | — | The structured data of the site: `publisher` is the organization or the person behind the site. `false` turns it off. See [Structured data](#structured-data). |
72
- | `debug` | `true` | The Metadata app in the dev toolbar (`client`) and the checks in the build log (`build`). Set `false` to turn off both, or `{ client: false }` or `{ build: false }` to turn off one. See [Checks](#checks). |
75
+ | `debug` | `true` | The dev toolbar app (`client`) and the build log (`build`). See [Checks](#checks). |
73
76
  | `rules` | — | `ignore`: the ids of the check rules to turn off. `custom`: your own rules. See [Checks](#checks). |
74
77
  | `pages` | — | `ignore`: the pages without checks, as path patterns, for example `["/404", "/drafts/**"]`. See [Checks](#checks). |
75
78
 
76
- ### Translations
77
-
78
- Each text can be one string, or an object with one string for each locale:
79
-
80
- ```typescript
81
- metadata({
82
- siteName: { en: "Acme Studio", fi: "Acme Studio Suomi" },
83
- titleTemplate: { en: "%s | Acme Studio", fi: "%s | Acme Studio Suomi" },
84
- })
85
- ```
86
-
87
- `<Metadata>` uses the text of the locale of the page, or of its `locale` prop. A locale without a text uses the first text.
88
-
89
- ### Locales
90
-
91
- `<Metadata>` reads the locales from your i18n setup. You do not need extra code:
92
-
93
- - **[`@mannisto/astro-i18n`](https://github.com/eremannisto/astro-i18n):** the locale, the public URL of the page (`/about` and not `/en/about`) and the hreflang links.
94
- - **The `i18n` option of Astro:** the locale and the hreflang links.
95
-
96
- The hreflang links contain the page in each locale, and `x-default` for the default locale. To give your own links, use the `hreflang` prop. `hreflang={[]}` turns the links off, for example on a 404 page.
97
-
98
79
  ## Metadata component
99
80
 
100
81
  Put `<Metadata>` into the `<head>` of your layout, and give it the values of the page:
@@ -164,7 +145,98 @@ The page values override the site values. For example, `title="About"` gives:
164
145
  | `schema` | — | Structured data items of your own, for example a `Product`. See [Structured data](#structured-data). |
165
146
  | `locale` | The locale of the page | The locale of the translated site values. See [Locales](#locales). |
166
147
 
167
- A tag is rendered only when it has a value. For example, the robots tag is necessary only with `index` or `follow` set to `false`.
148
+ `<Metadata>` renders a tag only when the tag has a value. For example, the robots tag is necessary only with `index` or `follow` set to `false`.
149
+
150
+ ### Single components
151
+
152
+ `<Metadata>` renders all tags. To render only some of them, use the single components. They take the same props as `<Metadata>`, and they use the same site values:
153
+
154
+ ```astro
155
+ ---
156
+ import { Canonical, OpenGraph, Title } from "@mannisto/astro-metadata/components"
157
+ ---
158
+
159
+ <Title title="About" />
160
+ <Canonical />
161
+ <OpenGraph title="About" />
162
+ ```
163
+
164
+ | Component | Tags |
165
+ |---|---|
166
+ | `<Title>` | `title` |
167
+ | `<Description>` | `description` |
168
+ | `<Canonical>` | The canonical link |
169
+ | `<Robots>` | `robots` |
170
+ | `<ThemeColor>` | `theme-color` |
171
+ | `<OpenGraph>` | `og:*` and `article:*` |
172
+ | `<Twitter>` | `twitter:*` |
173
+ | `<Favicon>` | The favicon links |
174
+ | `<Manifest>` | The manifest link |
175
+ | `<Feeds>` | The feed links |
176
+ | `<LanguageAlternates>` | The hreflang links |
177
+ | `<Schema>` | The structured data |
178
+
179
+ ## Multiple languages
180
+
181
+ ### Translations
182
+
183
+ Each text can be one string, or an object with one string for each locale:
184
+
185
+ ```typescript
186
+ metadata({
187
+ siteName: "Acme Studio",
188
+ description: {
189
+ en: "Tools for small teams.",
190
+ fi: "Työkaluja pienille tiimeille.",
191
+ },
192
+ })
193
+ ```
194
+
195
+ `<Metadata>` uses the text of the locale of the page, or of its `locale` prop. A locale without a text uses the first text.
196
+
197
+ ### Locales
198
+
199
+ On a site with more than one language, `<Metadata>` finds the language of each page and its other language versions by itself. This works with [`@mannisto/astro-i18n`](https://github.com/eremannisto/astro-i18n) and with the [native i18n of Astro](https://docs.astro.build/en/guides/internationalization/). You do not need extra code.
200
+
201
+ Each page then tells search engines and social sites its language, and where the same page is in the other languages:
202
+
203
+ ```html
204
+ <meta property="og:locale" content="en_US">
205
+ <meta property="og:locale:alternate" content="fi_FI">
206
+ <link rel="alternate" hreflang="en" href="https://example.com/about/">
207
+ <link rel="alternate" hreflang="fi" href="https://example.com/fi/about/">
208
+ <link rel="alternate" hreflang="x-default" href="https://example.com/about/">
209
+ ```
210
+
211
+ With `@mannisto/astro-i18n`, the URLs also follow your `prefixDefaultLocale` option, for example `/about` and not `/en/about`.
212
+
213
+ With another i18n library, give the language of the page in `locale`, and the language versions in `hreflang`. `<Metadata>` makes the same tags from them:
214
+
215
+ ```astro
216
+ <Metadata
217
+ locale="fi"
218
+ hreflang={[
219
+ {
220
+ hreflang: "en",
221
+ href: "/about",
222
+ },
223
+ {
224
+ hreflang: "fi",
225
+ href: "/fi/about",
226
+ },
227
+ {
228
+ hreflang: "x-default",
229
+ href: "/about",
230
+ },
231
+ ]}
232
+ />
233
+ ```
234
+
235
+ A page that has no other language versions, for example a 404 page, can turn off the links:
236
+
237
+ ```astro
238
+ <Metadata hreflang={[]} />
239
+ ```
168
240
 
169
241
  ## Favicons
170
242
 
@@ -197,11 +269,25 @@ To generate other files, give a `files` list. It replaces the default files:
197
269
  favicon: {
198
270
  source: "./src/assets/logo.svg",
199
271
  files: [
200
- { path: "/favicon.ico", sizes: [16, 32, 48] },
201
- { path: "/favicon.svg" },
202
- { path: "/apple-touch-icon.png", size: 180 },
203
- { path: "/favicon-96.png", size: 96 },
204
- { path: "/favicon-512.png", size: 512 },
272
+ {
273
+ path: "/favicon.ico",
274
+ sizes: [16, 32, 48],
275
+ },
276
+ {
277
+ path: "/favicon.svg",
278
+ },
279
+ {
280
+ path: "/apple-touch-icon.png",
281
+ size: 180,
282
+ },
283
+ {
284
+ path: "/favicon-96.png",
285
+ size: 96,
286
+ },
287
+ {
288
+ path: "/favicon-512.png",
289
+ size: 512,
290
+ },
205
291
  ],
206
292
  }
207
293
  ```
@@ -249,7 +335,19 @@ metadata({
249
335
  })
250
336
  ```
251
337
 
252
- Your own manifest endpoint can use the generated icons with `Favicon.icons()`.
338
+ Your own manifest endpoint can use the generated icons with `Site.icons()`:
339
+
340
+ ```typescript
341
+ // src/pages/site.webmanifest.ts
342
+ import { Site } from "@mannisto/astro-metadata/runtime"
343
+
344
+ export const GET = () => {
345
+ return Response.json({
346
+ name: Site.name(),
347
+ icons: Site.icons(),
348
+ })
349
+ }
350
+ ```
253
351
 
254
352
  ## Structured data
255
353
 
@@ -278,7 +376,11 @@ For a personal site, use `publisher: { type: "Person" }`. Set `schema: false` to
278
376
  title="Hello"
279
377
  type="article"
280
378
  published={post.date}
281
- author={{ name: "Acme Writer", url: "/about", twitter: "@acmewriter" }}
379
+ author={{
380
+ name: "Acme Writer",
381
+ url: "/about",
382
+ twitter: "@acmewriter",
383
+ }}
282
384
  />
283
385
  ```
284
386
 
@@ -287,8 +389,14 @@ For a personal site, use `publisher: { type: "Person" }`. Set `schema: false` to
287
389
  ```astro
288
390
  <Metadata
289
391
  breadcrumbs={[
290
- { name: "Home", url: "/" },
291
- { name: "Blog", url: "/blog" },
392
+ {
393
+ name: "Home",
394
+ url: "/",
395
+ },
396
+ {
397
+ name: "Blog",
398
+ url: "/blog",
399
+ },
292
400
  ]}
293
401
  />
294
402
  ```
@@ -296,40 +404,75 @@ For a personal site, use `publisher: { type: "Person" }`. Set `schema: false` to
296
404
  **Your own items.** Give other types, for example a `Product` or an `Event`, in `schema`. The types come from [`schema-dts`](https://github.com/google/schema-dts), so your editor completes the schema.org fields:
297
405
 
298
406
  ```astro
299
- <Metadata schema={{ "@type": "Event", name: "Opening night", startDate: "2026-11-01" }} />
407
+ <Metadata
408
+ schema={{
409
+ "@type": "Event",
410
+ name: "Opening night",
411
+ startDate: "2026-11-01",
412
+ }}
413
+ />
300
414
  ```
301
415
 
302
416
  All items go into one graph. The items link to each other with `@id`, and all URLs are absolute.
303
417
 
418
+ ## Dev toolbar app
419
+
420
+ Run `astro dev`, and open the Metadata app in the dev toolbar. The app checks the current page, and shows its tags and its link previews. Click a problem to open the row of its tag.
421
+
422
+ <table>
423
+ <tr>
424
+ <td><img src="./docs/screenshots/01.png" alt="The Overview tab with no problems" width="260"></td>
425
+ <td><img src="./docs/screenshots/02.png" alt="The Overview tab with an error, two warnings and two notes" width="260"></td>
426
+ <td><img src="./docs/screenshots/03.png" alt="The Social section with the Open Graph tags" width="260"></td>
427
+ </tr>
428
+ <tr>
429
+ <td><img src="./docs/screenshots/04.png" alt="The Structured data section with the JSON-LD of the page" width="260"></td>
430
+ <td><img src="./docs/screenshots/05.png" alt="The Previews tab with the Google and Twitter (X) previews" width="260"></td>
431
+ <td><img src="./docs/screenshots/06.png" alt="The Raw tab with the tags of the head" width="260"></td>
432
+ </tr>
433
+ </table>
434
+
304
435
  ## Checks
305
436
 
306
- The integration checks the metadata of each page. Each problem has a level:
437
+ The dev toolbar app checks the current page. The build checks all prerendered pages, and compares them, for example for the same title on two pages. It logs the errors and the warnings:
307
438
 
308
- | Level | Meaning | Examples |
439
+ ```
440
+ [WARN] [@mannisto/astro-metadata] /about/index.html
441
+ - The page has no description.
442
+ ```
443
+
444
+ | Level | Description | Examples |
309
445
  | --- | --- | --- |
310
- | Error | The metadata is broken. | No title, placeholder text such as `undefined`, two canonical links, invalid JSON-LD, an `og:image` that does not load |
311
- | Warning | Fix it for better results. | A long title, the same title on two pages, no `twitter:card`, an `og:image` over 600 KB, an hreflang page that does not link back |
446
+ | Error | The metadata is broken. | No title, placeholder text such as `undefined`, invalid JSON-LD, an `og:image` that does not load |
447
+ | Warning | Fix it for better results. | A long title, the same title on two pages, an `og:image` over 600 KB |
312
448
  | Info | Good to know. | `noindex`, a short description, no `og:image:alt` |
313
449
 
314
- The checks look at three things:
315
-
316
- - **The head of each page:** the tags, the structured data and the hreflang links. A page with `noindex` gets no search and sharing checks.
317
- - **The files of each page:** the `og:image` and the favicons. The checks load them, and compare the real image size, format and file size with the tags. Files on other sites are not checked.
318
- - **All pages together:** the same title or description on two pages, and hreflang links that do not link back. Only the build can compare the pages.
450
+ To turn off the checks, use `debug`:
319
451
 
320
- The results show in two places:
452
+ ```typescript
453
+ // No dev toolbar app
454
+ metadata({
455
+ debug: {
456
+ client: false,
457
+ },
458
+ })
321
459
 
322
- - **In dev:** Open the Metadata app in the Astro dev toolbar. It shows the problems of the current page. Click a problem to open the row of its tag. The app also shows the link previews of Google, Twitter (X), Facebook, LinkedIn, WhatsApp, Discord and Slack, and all metadata tags.
323
- - **In the build:** The integration logs the errors and the warnings of the prerendered pages:
460
+ // No build log
461
+ metadata({
462
+ debug: {
463
+ build: false,
464
+ },
465
+ })
324
466
 
325
- ```
326
- [WARN] [@mannisto/astro-metadata] /about/index.html
327
- - The page has no description.
467
+ // Neither
468
+ metadata({
469
+ debug: false,
470
+ })
328
471
  ```
329
472
 
330
473
  ### Turn off rules
331
474
 
332
- All rules and their ids are in [`src/lib/rules.js`](./src/lib/rules.js). Give the ids of the rules to turn off in `rules.ignore`. This applies to the dev toolbar app and to the build:
475
+ Give the ids of the rules in `rules.ignore`. All rules and their ids are in [`src/lib/rules.js`](./src/lib/rules.js).
333
476
 
334
477
  ```typescript
335
478
  metadata({
@@ -341,7 +484,7 @@ metadata({
341
484
 
342
485
  ### Custom rules
343
486
 
344
- Add your own rules in `rules.custom`. A rule has an `id`, a `level` (`"error"`, `"warning"` or `"info"`), a `message`, and a `check` function that returns `true` when the page has the problem:
487
+ Add your own rules in `rules.custom`. A rule has an `id`, a `level` (`"error"`, `"warning"` or `"info"`), a `message` and a `check` function. The function returns `true` when the page has the problem:
345
488
 
346
489
  ```typescript
347
490
  metadata({
@@ -376,11 +519,11 @@ The rule can also have:
376
519
  - `field`, the tag of the problem, for example `"og:title"`. A click on the problem in the dev toolbar app opens its row.
377
520
  - `indexed: true`, to skip the rule on a noindex page.
378
521
 
379
- The custom rules run in the build and in the dev toolbar app. In dev, the dev server runs them, because they are functions in the Astro config. Text between backticks in a message shows as code in the dev toolbar app. The `MetadataRule` type gives your editor completion.
522
+ Text between backticks in a message shows as code in the dev toolbar app. The `MetadataRule` type gives your editor completion.
380
523
 
381
524
  ### Ignore pages
382
525
 
383
- Some pages do not need checks, for example a 404 page or the drafts. Give their paths in `pages.ignore`, without the base. In a pattern, `*` matches one part of the path, and `**` matches any number of parts:
526
+ Give the paths of the pages without checks in `pages.ignore`, without the base. `*` matches one part of the path, and `**` matches any number of parts:
384
527
 
385
528
  ```typescript
386
529
  metadata({
@@ -390,46 +533,36 @@ metadata({
390
533
  })
391
534
  ```
392
535
 
393
- The build does not check these pages, and does not compare them with the other pages. The dev toolbar app shows all values of these pages, but no problems.
394
-
395
- Set `debug: { build: false }` to hide the build warnings, `debug: { client: false }` to remove the dev toolbar app, and `debug: false` to turn off both.
536
+ The dev toolbar app still shows the values of these pages, but no problems.
396
537
 
397
538
  ## API
398
539
 
540
+ `Site` returns the values that you set in the integration, for example for a footer, a feed or your own manifest:
541
+
399
542
  ```typescript
400
- import { Favicon, Manifest, Schema, Site } from "@mannisto/astro-metadata/runtime"
543
+ import { Site } from "@mannisto/astro-metadata/runtime"
544
+
545
+ Site.description({ locale: "fi" })
401
546
  ```
402
547
 
403
- | Method | Returns | Description |
404
- |---|---|---|
405
- | `Site.config` | `MetadataConfig` | The site values of the integration |
406
- | `Site.name("fi")` | `string` | The site name of a locale |
407
- | `Site.title("About", "fi")` | `string` | The page title in the title template |
408
- | `Site.url("/og.jpg")` | `string` | The absolute URL of a path |
409
- | `Site.pageUrl("/about")` | `string` | The absolute URL of a page, with the trailing slash of Astro |
410
- | `Favicon.config` | `FaviconConfig` | The favicon config, or `undefined` without the `favicon` option |
411
- | `Favicon.files` | `ResolvedFaviconFile[]` | The generated files |
412
- | `Favicon.links()` | `FaviconLink[]` | The link tags of the generated files |
413
- | `Favicon.icons()` | `ManifestIcon[]` | The icons for a web app manifest |
414
- | `Favicon.url("/favicon.ico")` | `string` | The URL of a file, with the base and a hash |
415
- | `Favicon.generate("/favicon-32.png")` | `Promise<Response>` | Generates a file of the config |
416
- | `Manifest.config` | `ManifestConfig \| string` | The `manifest` option |
417
- | `Manifest.url("fi")` | `string` | The URL of the manifest of a locale |
418
- | `Manifest.build("fi")` | `object` | The manifest of a locale |
419
- | `Manifest.paths()` | `ManifestPath[]` | The generated manifest files |
420
- | `Schema.graph(page)` | `Graph` | The structured data that `<Metadata>` renders for a page |
421
- | `Schema.stringify(data)` | `string` | JSON that is safe inside a script tag |
422
-
423
- | Component | Props |
548
+ | Method | Returns |
424
549
  |---|---|
425
- | `<Metadata>` | See [Metadata component](#metadata-component) |
550
+ | `Site.name()` | `siteName` |
551
+ | `Site.template()` | `titleTemplate` |
552
+ | `Site.description()` | `description` |
553
+ | `Site.image()` | `image`, with an absolute URL |
554
+ | `Site.twitter()` | `twitter`, with the default card |
555
+ | `Site.themeColor()` | `themeColor` |
556
+ | `Site.icons()` | The generated favicons, for the `icons` of a web app manifest |
557
+
558
+ A translated text returns the text of `locale`, or the first text without `locale`. An option that is not set returns `undefined`.
426
559
 
427
560
  Import the types from `@mannisto/astro-metadata/runtime`, for example `import type { MetadataImage } from "@mannisto/astro-metadata/runtime"`.
428
561
 
429
562
  ## Good to know
430
563
 
431
- - **CMS data.** Give CMS values to `<Metadata>` as props. The site values of the integration are fixed at startup, and a change restarts the dev server.
432
- - **Trailing slash.** The canonical URL and the `hreflang` links follow the `trailingSlash` setting of Astro. With `"ignore"`, `build.format` decides.
564
+ - **CMS data.** Give CMS values to `<Metadata>` as props. The integration reads its site values one time at startup, and a change restarts the dev server.
565
+ - **Trailing slash.** The canonical URL and the `hreflang` links follow the `trailingSlash` option of Astro. With `"ignore"`, `build.format` decides.
433
566
  - **`sharp`.** The favicons use the `sharp` package that Astro installs. If you install Astro without its optional dependencies, install `sharp` yourself.
434
567
  - **Files in `public/`.** A file in `public/` with the same path as a generated favicon replaces the generated file. The integration shows a warning.
435
568
 
@@ -441,7 +574,10 @@ Version 2 is a new API. The main changes:
441
574
 
442
575
  ```diff
443
576
  - <Head title="About" titleTemplate="%s | My Site" description="..." />
444
- + metadata({ titleTemplate: "%s | My Site", description: "..." })
577
+ + metadata({
578
+ + titleTemplate: "%s | My Site",
579
+ + description: "...",
580
+ + })
445
581
  ```
446
582
 
447
583
  ### Use `<Metadata>` inside your own `<head>`
@@ -458,19 +594,18 @@ Version 2 is a new API. The main changes:
458
594
  + </head>
459
595
  ```
460
596
 
461
- ### Replace the removed components
597
+ ### Use the new props of the single components
462
598
 
463
- `Title`, `Description`, `Canonical`, `Robots`, `OpenGraph`, `Twitter`, `Favicon`, `LanguageAlternates`, `Keywords` and `Schema` are removed. `<Metadata>` renders their tags.
599
+ The single components take the props of `<Metadata>`, and `<Metadata>` renders all of them. There is no `Keywords` component, because search engines do not use the tag.
464
600
 
465
601
  ```diff
466
602
  - <LanguageAlternates alternates={links} />
467
- - <Schema schema={data} />
468
- + <Metadata hreflang={links} schema={data} />
603
+ + <LanguageAlternates hreflang={links} />
469
604
  ```
470
605
 
471
606
  ### Replace the `Metadata` store
472
607
 
473
- `Metadata.set()` and `Metadata.resolve()` are removed. Give the values as props to your layout.
608
+ v2 has no `Metadata.set()` and `Metadata.resolve()`. Give the values as props to your layout.
474
609
 
475
610
  ### Replace the robots object and the `false` props
476
611
 
@@ -483,7 +618,11 @@ Version 2 is a new API. The main changes:
483
618
 
484
619
  ```diff
485
620
  - <Head favicon={{ icons: [{ path: "/favicon.ico" }] }} />
486
- + metadata({ favicon: { source: "./src/assets/logo.svg" } })
621
+ + metadata({
622
+ + favicon: {
623
+ + source: "./src/assets/logo.svg",
624
+ + },
625
+ + })
487
626
  ```
488
627
 
489
628
  ## Contributing
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@mannisto/astro-metadata",
3
- "version": "2.0.0-alpha.5",
4
- "description": "Metadata for Astro: page tags, social cards, favicons, the web app manifest and structured data.",
3
+ "version": "2.0.0",
4
+ "description": "Metadata for Astro: page tags, social cards, favicons, the web app manifest, structured data and a dev toolbar app that checks your pages.",
5
5
  "license": "MIT",
6
6
  "type": "module",
7
7
  "homepage": "https://github.com/eremannisto/astro-metadata#readme",
@@ -0,0 +1,10 @@
1
+ ---
2
+ import { pageCanonical } from "../lib/page.ts"
3
+ import type { MetadataProps } from "../lib/page.ts"
4
+
5
+ export type Props = Pick<MetadataProps, "canonical">
6
+
7
+ const canonical = pageCanonical(Astro, Astro.props)
8
+ ---
9
+
10
+ <link rel="canonical" href={canonical} />
@@ -0,0 +1,10 @@
1
+ ---
2
+ import { pageDescription, pageLocale } from "../lib/page.ts"
3
+ import type { MetadataProps } from "../lib/page.ts"
4
+
5
+ export type Props = Pick<MetadataProps, "description" | "locale">
6
+
7
+ const description = pageDescription(Astro.props, pageLocale(Astro, Astro.props))
8
+ ---
9
+
10
+ {description && <meta name="description" content={description} />}
@@ -0,0 +1,9 @@
1
+ ---
2
+ import { Favicon } from "../lib/favicon.ts"
3
+ ---
4
+
5
+ {
6
+ Favicon.links().map((link) => {
7
+ return <link rel={link.rel} type={link.type} href={link.href} sizes={link.sizes} />
8
+ })
9
+ }
@@ -0,0 +1,29 @@
1
+ ---
2
+ import { getConfig, localize } from "../lib/config.ts"
3
+ import { pageLocale } from "../lib/page.ts"
4
+ import type { MetadataProps } from "../lib/page.ts"
5
+ import { withBase } from "../lib/url.ts"
6
+
7
+ export type Props = Pick<MetadataProps, "locale">
8
+
9
+ const locale = pageLocale(Astro, Astro.props)
10
+
11
+ const FEED_TYPES = {
12
+ rss: "application/rss+xml",
13
+ atom: "application/atom+xml",
14
+ json: "application/feed+json",
15
+ }
16
+ ---
17
+
18
+ {
19
+ getConfig().feeds?.map((feed) => {
20
+ return (
21
+ <link
22
+ rel="alternate"
23
+ type={FEED_TYPES[feed.type ?? "rss"]}
24
+ title={localize(feed.title, locale)}
25
+ href={withBase(feed.href)}
26
+ />
27
+ )
28
+ })
29
+ }
@@ -0,0 +1,13 @@
1
+ ---
2
+ import { pageHreflang } from "../lib/page.ts"
3
+ import type { MetadataProps } from "../lib/page.ts"
4
+ import { pageUrl } from "../lib/url.ts"
5
+
6
+ export type Props = Pick<MetadataProps, "hreflang">
7
+ ---
8
+
9
+ {
10
+ pageHreflang(Astro, Astro.props).map((link) => {
11
+ return <link rel="alternate" hreflang={link.hreflang} href={pageUrl(link.href)} />
12
+ })
13
+ }
@@ -0,0 +1,11 @@
1
+ ---
2
+ import { Manifest } from "../lib/manifest.ts"
3
+ import { pageLocale } from "../lib/page.ts"
4
+ import type { MetadataProps } from "../lib/page.ts"
5
+
6
+ export type Props = Pick<MetadataProps, "locale">
7
+
8
+ const manifest = Manifest.url(pageLocale(Astro, Astro.props))
9
+ ---
10
+
11
+ {manifest && <link rel="manifest" href={manifest} />}